I am building a multi tenant web app that connects Office 365 services using Microsoft.Owin.Security.OpenIdConnect, Version=3.0.0.0 and Azure Active Directory with Microsoft.IdentityModel.Clients.ActiveDirectory, Version=2.19.0.0 following this sample.
Our web app client (user agent) is authenticated to our server using an asp.NET cookie while the authentication between our server and authority server (Azure AD here) is made with OpenID Authorization Code Flow.
We set for the Asp.NET cookie a 30 days sliding expiration for its lifetime. However we still have a short lived AuthenticationTicket from the Authority Server even when setting UseTokenLifetime= true which is supposed to match the lifetime of the two authentication mechanisms.
The problem we have is: our end-users must relog frequently (less than hour). The question is then, how do we increase/change the lifetime of the authentication ticket in this owin openidconnect middleware?
REMARK: I also posted a question on the usage of refresh tokens with ADAL.
From what we have understood, this problem is only related to authentication. The lifetimes of the access_token and refresh_token which is an authorization concern managed by ActiveDirectory client are independent of this problem. Correct me if I am wrong.
Startup.Auth.cs
public partial class Startup
{
public const string CookieName = ".AspNet.MyName";
public const int DayExpireCookie = 30;
public void ConfigureAuth(IAppBuilder app)
{
app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
var cookieAuthenticationOptions = new CookieAuthenticationOptions()
{
CookieName = CookieName,
ExpireTimeSpan = TimeSpan.FromDays(DayExpireCookie),
AuthenticationType = CookieAuthenticationDefaults.AuthenticationType,
SlidingExpiration = true,
};
app.UseCookieAuthentication(cookieAuthenticationOptions);
app.UseOpenIdConnectAuthentication(
new OpenIdConnectAuthenticationOptions
{
ClientId = SettingsHelper.ClientId,
Authority = SettingsHelper.Authority,
ClientSecret = SettingsHelper.AppKey,
UseTokenLifetime = true,
TokenValidationParameters = new System.IdentityModel.Tokens.TokenValidationParameters
{
ValidateIssuer = false
},
Notifications = new OpenIdConnectAuthenticationNotifications()
{
// If there is a code in the OpenID Connect response, redeem it for an access token and refresh token, and store those away.
AuthorizationCodeReceived = (context) =>
{
var code = context.Code;
string tenantID = context.AuthenticationTicket.Identity.FindFirst("http://schemas.microsoft.com/identity/claims/tenantid").Value;
string signInUserId = context.AuthenticationTicket.Identity.FindFirst(ClaimTypes.NameIdentifier).Value;
AuthenticationContext authContext = new AuthenticationContext(string.Format("{0}/{1}", SettingsHelper.AuthorizationUri, tenantID), new ADALTokenCache(signInUserId));
ClientCredential credential = new ClientCredential(SettingsHelper.ClientId, SettingsHelper.AppKey);
// Get the access token for AAD Graph. Doing this will also initialize the token cache associated with the authentication context
// In theory, you could acquire token for any service your application has access to here so that you can initialize the token cache
Uri redirectUri = new Uri(HttpContext.Current.Request.Url.GetLeftPart(UriPartial.Path));
AuthenticationResult result = authContext.AcquireTokenByAuthorizationCode(code, redirectUri, credential, SettingsHelper.AADGraphResourceId);
return Task.FromResult(0);
},
RedirectToIdentityProvider = (RedirectToIdentityProviderNotification<OpenIdConnectMessage, OpenIdConnectAuthenticationOptions> context) =>
{
string appBaseUrl = context.Request.Scheme + "://" + context.Request.Host + context.Request.PathBase;
context.ProtocolMessage.RedirectUri = appBaseUrl + SettingsHelper.LoginRedirectRelativeUri;
context.ProtocolMessage.PostLogoutRedirectUri = appBaseUrl + SettingsHelper.LogoutRedirectRelativeUri;
return Task.FromResult(0);
},
AuthenticationFailed = (context) =>
{
context.HandleResponse();
return Task.FromResult(0);
}
}
});
}
}
Account Controller
public class AccountController : Controller
{
public void SignIn()
{
var dateTimeOffset = DateTimeOffset.UtcNow;
var authenticationProperties = new AuthenticationProperties
{
AllowRefresh = true,
IssuedUtc = dateTimeOffset,
ExpiresUtc = dateTimeOffset.AddDays(Startup.DayExpireCookie -1),
RedirectUri = SettingsHelper.LoginRedirectRelativeUri, IsPersistent = true
};
HttpContext.GetOwinContext()
.Authentication.Challenge(authenticationProperties,OpenIdConnectAuthenticationDefaults.AuthenticationType, CookieAuthenticationDefaults.AuthenticationType);
}
public void SignOut()
{
HttpContext.GetOwinContext().Authentication.SignOut(
new AuthenticationProperties { RedirectUri = SettingsHelper.LogoutRedirectRelativeUri, },
OpenIdConnectAuthenticationDefaults.AuthenticationType, CookieAuthenticationDefaults.AuthenticationType);
}
}
See Question&Answers more detail:
os