Microsoft.Owin.Security.OpenIdConnect 具有 Azure Active Directory 身份验证票证生命周期
Microsoft.Owin.Security.OpenIdConnect with Azure Active Directory authentication ticket lifetime
我正在构建一个多租户 Web 应用程序,它使用 Microsoft.Owin.Security.OpenIdConnect、版本=3.0.0.0 和 Azure Active Directory 与 连接 Office 365 服务Microsoft.IdentityModel.Clients.ActiveDirectory,版本=2.19.0.0 关注 this sample。
我们的 Web 应用程序客户端(用户代理)使用 asp.NET cookie 向我们的服务器进行身份验证,而我们的服务器和授权服务器(此处为 Azure AD)之间的身份验证是使用 OpenID 授权代码流进行的。
我们为 Asp.NET cookie 设置了 30 天的滑动有效期。但是,即使设置了 UseTokenLifetime= true,我们仍然有来自授权服务器的短暂 AuthenticationTicket,这应该与两种身份验证机制的生命周期相匹配。
我们遇到的问题是:我们的最终用户必须经常重新登录(少于一小时)。那么问题是,我们如何increase/change这个owin openidconnect中间件中的身份验证票证的生命周期?
备注:我还发布了 刷新令牌与 ADAL 的用法。
据我们了解,此问题仅与身份验证有关。 access_token 和 refresh_token 的生命周期是 ActiveDirectory 客户端管理的授权问题,与此问题无关。如果我错了请纠正我。
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);
}
}
});
}
}
账户管理员
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);
}
}
其实,
我需要设置 UseTokenLifetime = false
。
实际上,UseTokenLifetime = true
将 Asp.NET cookie 中的内部票证更改为 access_token
的默认生命周期,即一小时。
@Tracher 的评论是真实的,但误导了我……是的,access_token
生命周期由 Azure AD 控制,我对此无能为力。但是,我们使用 ADAL.NET 实现了 refresh_token
管理,因此有可能将 authentication/authorization 与 Microsoft Identity 服务器保持一个多小时。设置 UseTokenLifetTime = false
并在我的客户端应用程序和我的服务器之间使用 15 天滑动到期时间的 cookie 身份验证现在就像一个魅力。
我正在构建一个多租户 Web 应用程序,它使用 Microsoft.Owin.Security.OpenIdConnect、版本=3.0.0.0 和 Azure Active Directory 与 连接 Office 365 服务Microsoft.IdentityModel.Clients.ActiveDirectory,版本=2.19.0.0 关注 this sample。
我们的 Web 应用程序客户端(用户代理)使用 asp.NET cookie 向我们的服务器进行身份验证,而我们的服务器和授权服务器(此处为 Azure AD)之间的身份验证是使用 OpenID 授权代码流进行的。
我们为 Asp.NET cookie 设置了 30 天的滑动有效期。但是,即使设置了 UseTokenLifetime= true,我们仍然有来自授权服务器的短暂 AuthenticationTicket,这应该与两种身份验证机制的生命周期相匹配。
我们遇到的问题是:我们的最终用户必须经常重新登录(少于一小时)。那么问题是,我们如何increase/change这个owin openidconnect中间件中的身份验证票证的生命周期?
备注:我还发布了
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);
}
}
});
}
}
账户管理员
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);
}
}
其实,
我需要设置 UseTokenLifetime = false
。
实际上,UseTokenLifetime = true
将 Asp.NET cookie 中的内部票证更改为 access_token
的默认生命周期,即一小时。
@Tracher 的评论是真实的,但误导了我……是的,access_token
生命周期由 Azure AD 控制,我对此无能为力。但是,我们使用 ADAL.NET 实现了 refresh_token
管理,因此有可能将 authentication/authorization 与 Microsoft Identity 服务器保持一个多小时。设置 UseTokenLifetTime = false
并在我的客户端应用程序和我的服务器之间使用 15 天滑动到期时间的 cookie 身份验证现在就像一个魅力。