Azure B2C - user can still visit website after logging out
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.
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
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;
}
}