Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
470 views
in Technique[技术] by (71.8m points)

office365 - Microsoft.Owin.Security.OpenIdConnect with Azure Active Directory authentication ticket lifetime

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.Short lived authentication ticket

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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Actually, I needed to set UseTokenLifetime = false. Indeed, UseTokenLifetime = true changes the internal ticket in the Asp.NET cookie to the default lifetime of access_token which is one hour. The comments from @Tratcher were true but mislead me... Yes the access_token lifetime is controlled by Azure AD and there is nothing that I can do about it. But, we implemented the refresh_token management with ADAL.NET so there is a possibility to keep authentication/authorization with Microsoft Identity server for more than one hour. Setting UseTokenLifetTime = false and use cookie authentication with 15 days sliding expiry time between my client app and my server works like a charm now.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...