I created AspNetCore 3.1 Project and added IdentityServer4 for SSO (added 'Microsoft.AspNetCore.ApiAuthorization.IdentityServer' package). Sig-nin works fine, but logout doesn't.
In Startup.cs I have the following configuration for IdentityServer :
public void ConfigureServices(IServiceCollection services)
{
...
services.AddIdentityServer()
.AddApiAuthorization<ApplicationUser, ApplicationDbContext>(options =>
{ ...
var client = new Client
{
ClientName = "ssotestclient",
ClientId = "ssotestclient",
ClientSecrets = { new Secret("somesecret".Sha256()) },
AllowedGrantTypes = GrantTypes.Code.Union(GrantTypes.ResourceOwnerPasswordAndClientCredentials).ToArray(),
RequirePkce = false,
RequireClientSecret = false,
AllowOfflineAccess = false,
AlwaysSendClientClaims = true,
UpdateAccessTokenClaimsOnRefresh = true,
AlwaysIncludeUserClaimsInIdToken = true,
AllowedScopes = new List<string>
{
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Email,
IdentityServerConstants.StandardScopes.Profile,
IdentityServerConstants.StandardScopes.OfflineAccess
},
RequireConsent = false,
RedirectUris = {"https://mytestsite.local/signin-oidc" },
PostLogoutRedirectUris = {"https://mytestsite.local/signout-callback-oidc"}
}
options.Clients.Add(client);
});
The client Website is an AspNetCore MVC project with 'Microsoft.AspNetCore.Authentication.OpenIdConnect' package. Client initialization in Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication(options =>
{
options.DefaultScheme = "Cookies";
options.DefaultChallengeScheme = "oidc";
})
.AddCookie("Cookies")
.AddOpenIdConnect("oidc", options =>
{
options.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.Authority = "https://myssoserver.local";
options.RequireHttpsMetadata = false;
HttpClientHandler handler = new HttpClientHandler();
handler.ServerCertificateCustomValidationCallback = HttpClientHandler.DangerousAcceptAnyServerCertificateValidator;
options.BackchannelHttpHandler = handler;
options.ClientId = "ssotestclient";
options.ClientSecret = "secret";
options.ResponseType = "code";
options.UsePkce = true;
options.Scope.Add("email");
options.Scope.Add("profile");
options.SaveTokens = true;
});
services.AddAuthorization();
services.AddRazorPages();
services.AddControllers();
}
Logout button on the client website has the following code :
public async Task OnPostAsync(string returnUrl = null)
{
await HttpContext.SignOutAsync("Cookies");
await HttpContext.SignOutAsync("oidc");
}
After this the browser is redirected to SSO server with the following location:
https://myssoserver.local/connect/endsession?post_logout_redirect_uri=https%3A%2F%2Fmytestsite.local%2Fsignout-callback-oidc&id_token_hint=<token>&state=<state>&x-client-SKU=ID_NETSTANDARD2_0&x-client-ver=5.5.0.0
Actual values of token and state are trimmed from this post because they are too long.
As you can see the post_logout_redirect_uri, id_token_hint and state parameters are passed to the server endsession endpoint. And on the SSO server side I see the message that it has passed validation:
info: IdentityServer4.Validation.EndSessionRequestValidator[0]
End session request validation success
{
"ClientId": "sso_test_client",
"ClientName": "sso_test_client",
"SubjectId": "f3693d8c-6095-4f1a-9f8f-bdc7440e9395",
"PostLogOutUri": "https://mytestsite.local/signout-callback-oidc",
"State": "<state>",
"Raw": {
"post_logout_redirect_uri": "https://mytestsite.local/signout-callback-oidc",
"id_token_hint": "***REDACTED***",
"state": "<state>",
"x-client-SKU": "ID_NETSTANDARD2_0",
"x-client-ver": "5.5.0.0"
}
}
However after this request the browser receives 302 redirect to https://myssoserver.local/Identity/Account/Logout page instead of provided post_logout_redirect_uri. And actual logout doesn't happen, because only OnGet() handler is called that does nothing
Could not find similar issue on the web.
What could be wrong? Why do I get redirected to the Logout page instead of a callback uri? I searched through the project code and could not find any reference with the 'Logout' word apart from Logout page itself