Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cannot redirect to the end session endpoint, the configuration may be missing or invalid OpenIdConnect SignOutAsync

I get an error

Cannot redirect to the end session endpoint, the configuration may be missing or invalid when signing out.

when I handle signing out

public async Task LogOut()
{
    await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);            
    await HttpContext.SignOutAsync("oidc");
}

Schemas

services.AddAuthentication(sharedOptions =>
    {
        sharedOptions.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
        sharedOptions.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
        sharedOptions.DefaultSignOutScheme = "oidc";
        sharedOptions.DefaultChallengeScheme = "oidc";
    })
    .AddCookie(options =>
    {
        options.AccessDeniedPath = new PathString("/Access/Unauthorised");
        options.Cookie.Name = "MyCookie";
    })
    .AddOpenIdConnect("oidc", options =>
    {
        options.ClientId = Configuration["oidc:ClientId"];
        options.ClientSecret = Configuration["oidc:ClientSecret"]; // for code flow
        options.SignedOutRedirectUri = Configuration["oidc:SignedOutRedirectUri"];
        options.Authority = Configuration["oidc:Authority"];
        options.ResponseType = OpenIdConnectResponseType.Code;
        options.GetClaimsFromUserInfoEndpoint = true;
        options.CallbackPath = new PathString("/oidc");
        options.Events = new OpenIdConnectEvents()
        {
            OnRedirectToIdentityProvider = context =>
            {
                context.ProtocolMessage.SetParameter("pfidpadapterid", Configuration["oidc:PingProtocolMessage"]);
                return Task.FromResult(0);
            }
        };
    });
like image 710
chridam Avatar asked Apr 13 '18 11:04

chridam


2 Answers

It seems like your authorization server does not support Session Management and Dynamic Registration. When it's supported, the discovery response contains end_session_endpoint. This is not the same as SignedOutRedirectUri, which is used as a final redirection target when the user is logged out on authorization server.

OnRedirectToIdentityProviderForSignOut event provides an option to set the issuer address, which in this case is the logout URI:

options.Events = new OpenIdConnectEvents()
{
    options.Events.OnRedirectToIdentityProviderForSignOut = context =>
    {
        context.ProtocolMessage.IssuerAddress =
            GetAbsoluteUri(Configuration["oidc:EndSessionEndpoint"], Configuration["oidc:Authority"]);
        return Task.CompletedTask;
    };
}

The helper method is used to support both relative and absolute path in the configuration:

private string GetAbsoluteUri(string signoutUri, string authority)
{
    var signOutUri = new Uri(signoutUri, UriKind.RelativeOrAbsolute);
    var authorityUri = new Uri(authority, UriKind.Absolute);

    var uri = signOutUri.IsAbsoluteUri ? signOutUri : new Uri(authorityUri, signOutUri);
    return uri.AbsoluteUri;
}   

This way the authorization server will get additional parameters in the query string, which it can use e.g. to redirect back to your application.

like image 60
user202472 Avatar answered Nov 17 '22 03:11

user202472


To fix this handle the OnRedirectToIdentityProviderForSignOut event and specify the Logout endpoint manually:

options.Events = new OpenIdConnectEvents()
{
    OnRedirectToIdentityProvider = context =>
    {
        context.ProtocolMessage.SetParameter("pfidpadapterid", Configuration["oidc:PingProtocolMessage"]);
        return Task.FromResult(0);
    },
    // handle the logout redirection 
    OnRedirectToIdentityProviderForSignOut = context =>
    {
        var logoutUri = Configuration["oidc:SignedOutRedirectUri"];
        context.Response.Redirect(logoutUri);
        context.HandleResponse();

        return Task.CompletedTask;
    }
};
like image 27
chridam Avatar answered Nov 17 '22 02:11

chridam