ASP.NET MVC中Windows身份验证与Azure AD OpenId共存及静默认证触发问题
解决Windows身份验证与Azure AD OIDC共存时的静默认证问题
当ASP.NET MVC应用同时启用Windows身份验证和Azure AD OpenID Connect认证时,Windows Auth的自动认证逻辑会抢先处理请求,导致OIDC的OnAuthorizationCodeReceived事件无法被自动触发,进而影响静默令牌刷新。以下是具体的解决步骤:
1. 调整认证中间件顺序
确保OIDC中间件在Windows身份验证中间件之前注册,让OIDC优先处理认证相关请求:
public void ConfigureAuth(IAppBuilder app) { // 先注册OIDC中间件 app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions { ClientId = ClientId, Authority = Authority, RedirectUri = RedirectUri, PostLogoutRedirectUri = PostLogoutRedirectUri, OnAuthorizationCodeReceived = context => HandleSilentAuthentication(context), // 启用令牌刷新相关配置 UseTokenLifetime = false, RefreshOnIssuerKeyNotFound = true, Scope = "openid profile offline_access" // 必须包含offline_access以获取刷新令牌 }); // 再注册Windows身份验证中间件 app.UseWindowsAuthentication(); }
2. 在OnAuthorizationCodeReceived中实现静默认证逻辑
在该事件中手动利用刷新令牌获取新访问令牌,无需用户交互:
private async Task HandleSilentAuthentication(AuthorizationCodeReceivedNotification context) { var credential = new ClientCredential(ClientId, ClientSecret); var authContext = new AuthenticationContext(Authority); // 从当前身份中获取已存储的刷新令牌 var refreshToken = context.OwinContext.Authentication.User.FindFirst("refresh_token")?.Value; if (!string.IsNullOrEmpty(refreshToken)) { try { // 使用刷新令牌获取新的访问令牌 var result = await authContext.AcquireTokenByRefreshTokenAsync(refreshToken, credential, ResourceId); // 更新当前身份的令牌信息 var identity = new ClaimsIdentity(context.AuthenticationTicket.Identity.AuthenticationType); identity.AddClaims(result.Claims); identity.AddClaim(new Claim("access_token", result.AccessToken)); identity.AddClaim(new Claim("refresh_token", result.RefreshToken)); context.AuthenticationTicket = new AuthenticationTicket(identity, context.AuthenticationTicket.Properties); } catch (AdalException) { // 刷新令牌失效时,重定向到登录页 context.Response.Redirect("/Account/Login"); context.HandleResponse(); } } }
3. 配置OIDC支持静默刷新
- 在Azure AD应用注册中启用
offline_access权限,并确保OIDC配置的Scope包含该权限。 - 设置
UseTokenLifetime = false,允许应用自定义令牌有效期,不依赖Azure AD返回的生命周期。 - 开启
RefreshOnIssuerKeyNotFound = true,当Azure AD密钥更新时自动触发令牌刷新。
4. 规避Windows Auth的自动抢占问题
如果Windows Auth仍抢先处理请求,可禁用其自动认证,改为在特定场景手动触发:
app.UseWindowsAuthentication(new WindowsAuthenticationOptions { AutomaticAuthentication = false });
之后在需要Windows身份验证的Action上添加特性:
[Authorize(AuthenticationSchemes = WindowsAuthenticationDefaults.AuthenticationScheme)] public ActionResult WindowsOnlyAction() { // 业务逻辑 return View(); }
内容的提问来源于stack exchange,提问作者thePolarExpress88
相关产品推荐
相关产品推荐

