Azure B2C - user can still visit website after logging out

Brendan Finnegan 46 Reputation points
2024-06-12T19:27:00.6833333+00:00

Hello everyone,

I am having problems with my azure b2c logout methods. I am using a .NET 4.8 C# MVC app connected to azure b2c. Our app uses openidconnect and cookie authentication. The login works great, and I am using local Entra accounts for this test.

When a user clicks Log out, the method clears the OwinContext, expires the cookie from b2c, the ASP.net session cookie. It then makes a call to the B2C logout method and redirects to a different website.

My problem is that if a user click the "back" button on their browser, or opens a new tab and visits the website again, they are authenticated. The Request/Response objects show that the Session is cleared but somehow their identity is still present on the second call and the cookies look identical to the start.

Can anyone point me in the right direction? Thanks!

Here is a photo showing the cleared User Identity (right before the redirect) and in the LogOff method.

User's image

Here is a photo showing the User Identity and their claims (right after the redirect). This method is the Index method where the Claim is still there

User's image

Here is my Redirect URL and relevant code below

https://{tenant}.b2clogin.com/{tenant}.onmicrosoft.com/{flow}/oauth2/v2.0/logout?post_logout_redirect_uri={redirectURI}
public void ConfigureAuth(IAppBuilder app)
{
    app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);

    app.UseCookieAuthentication(new CookieAuthenticationOptions
    {
        // ASP.NET web host compatible cookie manager
        CookieManager = new SystemWebChunkingCookieManager(),
        CookieName = "MyPortal.AuthCookie",
        CookieSameSite = Microsoft.Owin.SameSiteMode.Lax,
        CookieSecure = CookieSecureOption.Always,
        CookieHttpOnly = true,
        CookiePath = Globals.ApplicationRelativePath
    });

    app.UseOpenIdConnectAuthentication(
        new OpenIdConnectAuthenticationOptions
        {
            // Generate the metadata address using the tenant and policy information
            MetadataAddress = String.Format(Globals.WellKnownMetadata, Globals.TenantId, Globals.DefaultPolicy),

            // These are standard OpenID Connect parameters, with values pulled from web.config
            ClientId = Globals.ClientId,
            RedirectUri = Globals.RedirectUri,
            PostLogoutRedirectUri = Globals.PostLogoutRedirectUri,
            UseTokenLifetime = true,

            // Add the ProtocolValidator property here
            // Specify the callbacks for each type of notifications
            Notifications = new OpenIdConnectAuthenticationNotifications
            {
                RedirectToIdentityProvider = OnRedirectToIdentityProvider,
                AuthenticationFailed = OnAuthenticationFailed,
                SecurityTokenValidated = OnSecurityTokenValidated
            },

            // Specify the claim type that specifies the Name property.
            TokenValidationParameters = new TokenValidationParameters
            {
                NameClaimType = "name",
                RoleClaimType = "extension_Role",
                ValidateIssuer = false
            },

            // Specify the scope by appending all of the scopes requested into one string (separated by a blank space)
            Scope = $"openid profile offline_access {Globals.ReadTasksScope} {Globals.WriteTasksScope}",

            // ASP.NET web host compatible cookie manager
            CookieManager = new SystemWebCookieManager(),
        }
    );
}

public ActionResult LogOff()
{
    //Log out through OWIN 
    IEnumerable<AuthenticationDescription> authTypes = HttpContext.GetOwinContext().Authentication.GetAuthenticationTypes();
    HttpContext.GetOwinContext().Authentication.SignOut(authTypes.Select(t => t.AuthenticationType).ToArray());
    Request.GetOwinContext().Authentication.GetAuthenticationTypes();
    HttpContext.User = new GenericPrincipal(new GenericIdentity(string.Empty), null);
	
    Session.Clear();
	Session.Abandon();
    //Expire cookie
    if (Request.Cookies["MyPortal.AuthCookie"] != null)
    {
		HttpCookie authCookie = new HttpCookie("HomeOwnerPortal.AuthCookie");
		authCookie.Expires = DateTime.Now.AddDays(-1d);
		Response.Cookies.Add(authCookie);
	}
    try
    {
        AccountManager accountManager = new AccountManager();
        accountManager.LogOff();
        var RequestUri = new System.Uri(Globals.AadLogoutUrl);
        return Redirect(RequestUri.ToString());
    }
    catch
    {
        throw;
    }
}
Microsoft Entra ID
Microsoft Entra ID
A Microsoft Entra identity service that provides identity management and access control capabilities. Replaces Azure Active Directory.
20,482 questions
{count} votes