Reputation: 349
I am working on a multi-tenant solution with Azure AD with web apps and a web api. The web app uses OpenIdConnect to retrieve a bearer token (which is cached in Azure Redis Cache), which is used in Angular to get JSON from the web api. User impersonation is used between the web app and web api (set up in Azure AD applications).
Problem:
This works fine for about an hour, then the Identity suddenly disappears on the web api side. If I refresh the web app, I see that the page is redirected to the Microsoft login page, but no action is required since the user is just redirected back to the web app and everything works again. As far as I can see, the web app uses the same bearer token when it fails and after the refresh (same expire time) when it works again. AuthenticationContext.AcquireTokenSilent works in both scenarios.
I have tried to increase a lot of different timeouts, but nothing has helped. I have also disabled all but bearer token authentication on the web api. I do not understand why the identity disapears and why it helps to refresh the client. Any ideas? :)
Additional info
This is how the RequestContext.Principal.Identity looks for about an hour after login or a refresh (on the web api):
And this is after about an hour, which causes authentication to fail:
Some of the code changes I have tried out:
In web api HttpConfiguration:
config.SuppressDefaultHostAuthentication();
config.Filters.Add(
new HostAuthenticationFilter(
new WindowsAzureActiveDirectoryBearerAuthenticationOptions().AuthenticationType));
This changed the unauthenticated principal from WindowsPrincipal to ClaimsPrincipal, but it still fails after an hour.
WindowsAzureActiveDirectoryBearerAuthenticationOptions BackChannelTimeout set to 5 days. Still fails
In the web app web.config:
sessionState timeout="525600" for RedisSessionStateProvider. Still fails
In the web app owin auth process, increased timespan and added sliding expiration. Still fails:
app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
CookieSecure = CookieSecureOption.Always,
ExpireTimeSpan = TimeSpan.FromDays(5),
SlidingExpiration = true,
CookieHttpOnly = true
});
app.UseOpenIdConnectAuthentication(
new OpenIdConnectAuthenticationOptions
{
ClientId = ClientId,
Authority = Constants.CommonAuthority,
UseTokenLifetime = false
Update:
To flesh out some details: We have a hybrid MVC Angular web application. Many MVC menu items which each lead to an Angular "single page application" for that menu item. MVC is used for routing, authentication and authorization. In addition, additional claims is retrieved and appended to the current principal server side. The menu items are MVC controllers that are protected with the Authorized and ClaimsPrincipalPermission attributes. Since the web page will run in Azure, we changed the default sessionProvider to Microsoft.Web.Redis.RedisSessionStateProvider. Only the MVC server side talks to this redis session cache. The bearer token (not refresh token) is shared with Angular through an Authorized protected MVC controller, which is then stored in the browser session storage (similar to adal.js use of localstorage?) Angular gets JSON content from a CORS enabled API that lives in a separate domain from the MVC app. The API and MVC app also belong to two different Azure AD applications.
Upvotes: 3
Views: 2055
Reputation: 7394
you seem to be crossing flows here. If you are making calls from JavaScript, you should obtain the token in the client - something like http://www.cloudidentity.com/blog/2014/10/28/adal-javascript-and-angularjs-deep-dive/. Redirect based authentication flows in which the outcome is a cookie are not well suited for scenarios in which you call API via JavaScript. Furthermore, if I understood correctly you are obtaining a token as a private client and then sharing it out of band (redis cache) with a public client running inside a user agent. That's a no-no from the security perspective.
That said: if you are really really set in keeping up with your current route, I suggest taking a look at http://www.cloudidentity.com/blog/2014/04/28/use-owin-azure-ad-to-secure-both-mvc-ux-and-web-api-in-the-same-project/ for achieving full separation between your web UX and web API routes.
Upvotes: 2