Successfully Signing Out of Azure AD Web Applications in MVC with OAuth2 and OWIN

Home » Azure AD Web Applications » Successfully Signing Out of Azure AD Web Applications in MVC with OAuth2 and OWIN

Successfully Signing Out of Azure AD Web Applications in MVC with OAuth2 and OWIN

Posted on

According to the Microsoft documentation and many posts on Stack Overflow, MSDN and elsewhere, the procedure to sign a user out of an Azure AD web application is very simple. Just call the SignOut method in the OWIN context, pass in a return URL if desired, specify the authentication types, and it’s all supposed to “automagically” work. Like this:

public void SignOut()
{
string callbackUrl = Url.Action(“SignOutCallback”, “Account”, routeValues: null, protocol: Request.Url.Scheme);
HttpContext.GetOwinContext().Authentication.SignOut(new AuthenticationProperties { RedirectUri = callbackUrl }, OpenIdConnectAuthenticationDefaults.AuthenticationType, CookieAuthenticationDefaults.AuthenticationType);

}

Except that it doesn’t. Work, that is.

The SignOut method dutifully calls the “oauth2/logout” endpoint at login.microsoftonline.com just like it’s supposed to, the user sees the logout dialog (including the “close your browser” message), and, if a callback URL is included, the browser is redirected to the specified controller (or page if the application is plain ol’ ASP.NET). But the user is never actually signed out. The login control still shows the user as logged in and a refresh of the page does not initiate a new authentication request. If no callback is specified, the user can manually navigate to any page in the application and still be authenticated. So even though the user went through the logout process the end result is that they are still logged into the application they tried to sign out of (unless, of course, they follow the instructions and close their browser, but since when do users actually follow instructions???).

There are a whole slew of posts and message threads that call for manually expiring cookies, clearing the response cache headers, even clearing the AuthenticationContext token cache, but none of those methods actually solve the core problem of forcing a full logout from the application IF the WSFederationAuthenticationModule is involved (and it most likely will be if you are building Azure AD web applications following the “version 2” documentation, current as of 2017 to present). While the OWIN interface brokers calls to Azure AD, and supposedly clears relevant cookies on a sign out request (I say “supposedly” because if you watch the response headers in Fiddler during a sign out request you’ll see that it actually creates a bunch of them and persists the FedAuth cookie, so it doesn’t really seem to be doing the job it was designed to do), it does not in any way force the WS Federation module to clear the current client credentials in the current session, which is what tells the app if the user is actually authenticated or not. So while Azure AD may believe the user is signed out the app certainly doesn’t think so.

The solution to all this is actually quite simple – just call the SignOut method for the SessionAuthenticationModule prior to calling SignOut for Azure AD, like so:

public void SignOut()
{
string callbackUrl = Url.Action(“SignOutCallback”, “Account”, routeValues: null, protocol: Request.Url.Scheme);
FederatedAuthentication.SessionAuthenticationModule.SignOut();
HttpContext.GetOwinContext().Authentication.SignOut(new AuthenticationProperties { RedirectUri = callbackUrl }, OpenIdConnectAuthenticationDefaults.AuthenticationType, CookieAuthenticationDefaults.AuthenticationType);

}

This forces the application to clear the user credentials in the current session, so when the callback URL is processed from the OWIN request the user will see the “SignIn” link if your callback controller has the AllowAnonymous attribute or get redirected back to the Microsoft login page if it doesn’t.  As simple but poorly documented and not-so-obvious solution to a common problem.