Asp.Net MVC manual token timeout when using Azure AD

This is a design / approach issue ...

I think something is missing here. We create an Asp.Net MVC 5 web application and provide it using Azure AD using the following script:

https://azure.microsoft.com/en-us/documentation/articles/active-directory-authentication-scenarios/#web-browser-to-web-application

https://github.com/Azure-Samples/active-directory-dotnet-webapp-openidconnect

The token / cookie is an absolute expiration and expires in one hour. So what does this do for the user? Every hour should they come back, no matter what? In our testing, when the user expires, the browser is redirected back to AD, and the user asks for credentials. This, of course, violates any AJAX calls that we load with partial views, and none of our DevExpress controls are stable as a result.

Based on the response to this post SO: MVC AD Azure Update Token via ADAL Ajax JavaScript and KnockoutJs

... expected to see? It seems to me that this is not a very viable solution for a centralized cloud-based business application in which users are logged in and work all day.

Am I missing something? Or is this just not the perfect scenario for business applications?

+8
c # asp.net-mvc azure
source share
2 answers

We faced a similar set of problems, as well as the same thoughts on how you can use Azure AD with ASP.NET MVC in web applications with such a low session latency (60 minutes).

The solution we came across seems to work (albeit with limited testing), should have an iFrame on the page, which we update every 5 minutes.

<iframe sandbox="allow-same-origin allow-scripts allow-popups allow-forms" id="refreshAuthenticationIframe" src="@Url.Action("CheckSessionTimeout", "Home", new { area = "" })" style="display:none;"></iframe> 

The "CheckSessionTimeout" page is mostly empty.

In the Javascript file referenced by the entire application, we have:

 var pageLoadTime = moment(); setInterval(refreshAuthenticationCookies, 1000); function refreshAuthenticationCookies() { if (moment().diff(pageLoadTime, "seconds") > 300) { document.getElementById("refreshAuthenticationIframe").contentDocument.location = "/Home/ForceSessionRefresh"; pageLoadTime = moment(); } } 

(NB: moment is the date / time of the JS library we use). On the Home controller, we have:

  public ActionResult CheckSessionTimeout() => View(); public ActionResult ForceSessionRefresh() { HttpContext.GetOwinContext() .Authentication.Challenge(new AuthenticationProperties { RedirectUri = "/Home/CheckSessiontimeout" }, OpenIdConnectAuthenticationDefaults.AuthenticationType); return null; } 

I am not sure if this is the best way / approach. This is the best we can do to fix what seems like a difficult limitation with Azure AD and ASP.NET MVC applications (which are not SPA applications that do not use the web APIs but use Ajax calls) as to where we come from which none of this matters with local applications running Kerberos auth (and our user expectations that the session timeout is what they want to see or worry about).

+6
source share

There are two ways to deal with this (at least this is how we do it in our application, it would be interesting to find out what the AD gurus say about it, so that we can also fix it if this is not the right way to do something- then):

General Approach - Use Update Token

When you get an access token from AD, today you get 3 points ago - an access token, access to a token and an update token. What you do is cache all three of them in your application. Until the access token expires, you can simply use this access token. After the token has expired, you can use the update token to get a new access token. The method in ADAL that you want to use for this purpose is AcquireTokenByRefreshToken .

Having said that , you should not accept a hard dependency in your application in the update token . Based on the best practices described here , the update token may expire or be canceled. In addition, based on the Vittorio post update token is not returned even in the ADAL 3 version. So you can think about it.

Another approach is silent use of a token

Another approach you could take is to get the new token quietly on behalf of the user after the token expires. I believe this requires that the user must manually log in at least once in your application and follow the OAuth2 stream. The method you want to use is AcquireTokenSilent .

Here's the pseudo code for our approach:

  var now = DateTime.UtcNow.Ticks; if (now <= tokenExpiry && !string.IsNullOrWhiteSpace(accessToken)) return accessToken; var clientCredential = new ClientCredential(ClientId, ClientSecret); var authContext = new AuthenticationContext(string.Format("{0}/{1}", AzureActiveDirectorySignInEndpoint, azureADTenantId)); AuthenticationResult authResult = null; if (!string.IsNullOrWhiteSpace(refreshToken)) { authResult = await authContext.AcquireTokenByRefreshTokenAsync(refreshToken, clientCredential, ADEndpoint); } else { authResult = await authContext.AcquireTokenSilentAsync(Endpoint, clientCredential, new UserIdentifier(userId, UserIdentifierType.UniqueId)); } return authResult.AccessToken;//Also you may want to cache the token again 
+2
source share

All Articles