0

Our company has custom-built Identity Server, which is used by a few of our web applications for authentication. I am trying to use our Identity Server with a newly created ASP.NET Core Web App, using the .NET 6 framework. I am trying to use the predefined OIDC URLs, without having to write the code myself.

The authentication is mostly working; for example, if I add [Authorize] to a certain Razor PageModel, it will automatically redirect to the Authority URL, and then return to that page upon authentication and be logged in.

What I am having trouble with is this: I cannot seem to get the automatic sign out to work. I am trying to use either of the predefined OIDC signout URLs (signout-oidc or signout-callback-oidc), but I seem to be missing something. I am also having trouble finding good sample code or clear documentation to help debug the issue.

I have also tried using OIDC events - for example "OnSignedOutCallbackRedirect":

services.AddAuthentication(options =>
{
    options.DefaultScheme = "Cookies";
    options.DefaultChallengeScheme = "oidc";
})
    .AddCookie("Cookies")
    .AddOpenIdConnect("oidc", async options =>
    {
        options.Authority = testIdentitySettings.Authority;
        options.SignedOutRedirectUri = testIdentitySettings.SignedOutRedirectUri;
        options.RequireHttpsMetadata = testIdentitySettings.RequireHttpsMetadata ?? true;
        options.ClientId = testIdentitySettings.ClientId;
        options.SignInScheme = "Cookies";
        options.Scope.Add("roles");
        options.SaveTokens = true;

        options.TokenValidationParameters = new TokenValidationParameters
        {
            NameClaimType = "name",
            RoleClaimType = "http://schemas.microsoft.com/ws/2008/06/identity/claims/role"
        };

        options.Events.OnSignedOutCallbackRedirect = async (context) =>
        {
            await context.HttpContext.SignOutAsync("Cookies");

            var redirUrl = context.Options.SignedOutRedirectUri;

            var prop = new AuthenticationProperties
            {
                RedirectUri = redirUrl
            };

            await context.HttpContext.SignOutAsync("oidc", prop);

            context.Response.Redirect(redirUrl);
            context.HandleResponse();
        };
    });

This almost seems to work. It does redirect to my SignedOutRedirectUri (/LoggedOut), and when I check the User on that page, the User.Identity shows IsAuthenticated = false, and has zero claims; however, if I then load the home page (/), the User.Identity is back as authenticated with all the claims.

Any help or insight would be appreciated.

2 Answers 2

1

For the Logout example, you could refer to the code below.

using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Auth0.AspNetCore.Authentication;

public class AccountController : Controller
{
    [Authorize]
    public async Task Logout()
    {
        var authenticationProperties = new LogoutAuthenticationPropertiesBuilder()
            // Indicate here where Auth0 should redirect the user after a logout.
            // Note that the resulting absolute Uri must be added to the
            // **Allowed Logout URLs** settings for the app.
            .WithRedirectUri(Url.Action("Index", "Home"))
            .Build();

        await HttpContext.SignOutAsync(Auth0Constants.AuthenticationScheme, authenticationProperties);
        await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
    }
}

Reference: Logout

If the issue persists, you could try to make tests with the code sample below to reduce the ExpireTimeSpan in the AddCookie configuration.

public void ConfigureServices(IServiceCollection services)
    {
        services.AddAuthentication(/* ... */)
            .AddCookie(options =>
            {
                options.ExpireTimeSpan = TimeSpan.FromMinutes(1);
            });
        // ...
    }

For more detailed information, please refer to this answer.

Sign up to request clarification or add additional context in comments.

2 Comments

This, and Tore's updated answer, sort of worked. It logged me out and I ended up on our Identity Server logout page (account/logout). Deepak, your "RedirectUri" didn't seem to work; I tried the above, and also a hard-coded URL to a logged out page on my site, but neither redirect worked. I was actually hoping to use the "signout-oidc-logout" URL, which I feel should automatically handle all of the above, but I'm at a loss on how to get that to work.
I figured out a solution that works for me. Basically, Tore and Deepak were both right about the need for the SignOutAsync calls, but I ended up manually building the logout URL (instead of using signout-oidc). The URL looks something like this: identityserver/connect/endsession?id_token_hint={idToken}&post_logout_redirect_uri={redirectUri}. I am going to give you both credit for the answer and close this, but I still wish I knew why the signout-oidc doesn't do all this automatically.
1

I would use this to do the signout:

[Authorize]
/// <summary>
/// Do the actual logout
/// </summary>
/// <returns></returns>
public async Task DoLogout()
{
    await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
    await HttpContext.SignOutAsync(OpenIdConnectDefaults.AuthenticationScheme);
}

I don't think you need to use the OnSignedOutCallbackRedirect handler.

In your case, as you have renamed the schemes, the logout method should be:

[Authorize]
/// <summary>
/// Do the actual logout
/// </summary>
/// <returns></returns>
public async Task DoLogout()
{
    await HttpContext.SignOutAsync("Cookies");
    await HttpContext.SignOutAsync("oidc");
}

2 Comments

I tried this, and received the following runtime error: InvalidOperationException: No sign-out authentication handler is registered for the scheme 'OpenIdConnect'. The registered sign-out schemes are: Cookies, oidc. Did you forget to call AddAuthentication().AddCookie("OpenIdConnect",...)? I was really hoping to use the built-in signout-callback-oidc (or even signout-oidc). Is there a way to do this?
I updated my answer. as I forgot you had renamed the schemes.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.