ASP.NET MVC 5中如何持久化外部提供者的额外声明与令牌
在ASP.NET MVC 5中持久化OpenIdConnect的额外声明与令牌
1. 通过SecurityTokenValidated事件处理外部声明与令牌
你需要在OpenIdConnectAuthenticationOptions中配置Notifications,利用SecurityTokenValidated事件拦截认证流程,提取外部OpenId服务器返回的声明和令牌,将其整合到本地用户身份标识中,确保这些数据被持久化到认证Cookie。
修改后的配置代码如下:
app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions() { Authority = "openid-server-domain.com", RedeemCode = true, SaveTokens = true, ResponseType = "code", ClientId = "***", ClientSecret = "***", RedirectUri = "https://localhost:55555/connect/redirect", PostLogoutRedirectUri = "/disconnect/sign-out", Scope = "openid profile email", Notifications = new OpenIdConnectAuthenticationNotifications { SecurityTokenValidated = async n => { // 提取外部提供者返回的所有声明 var externalClaims = n.AuthenticationTicket.Identity.Claims.ToList(); // 可选:从UserInfo端点获取更多用户信息(如果需要额外字段) // var userInfoClient = new UserInfoClient(new Uri($"{n.Options.Authority}/connect/userinfo")); // var userInfoResp = await userInfoClient.GetAsync(n.ProtocolMessage.AccessToken); // externalClaims.AddRange(userInfoResp.Claims); // 创建本地身份标识,指定Name和Role的声明类型(适配MVC5的默认身份逻辑) var localIdentity = new ClaimsIdentity( externalClaims, n.AuthenticationTicket.Identity.AuthenticationType, ClaimTypes.Name, ClaimTypes.Role); // 可选:手动添加令牌为声明(注意:敏感令牌不建议存声明,优先用SaveTokens) // localIdentity.AddClaim(new Claim("access_token", n.ProtocolMessage.AccessToken)); // 更新认证票据,替换为包含额外声明的本地身份 n.AuthenticationTicket = new AuthenticationTicket(localIdentity, n.AuthenticationTicket.Properties); } } });
2. 配置Cookie认证确保持久化
MVC5默认通过CookieAuthenticationMiddleware存储用户身份,你可以调整Cookie的过期策略,确保声明和令牌长期有效:
app.UseCookieAuthentication(new CookieAuthenticationOptions { AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie, LoginPath = new PathString("/Account/Login"), // 设置Cookie有效期,支持持久化登录 ExpireTimeSpan = TimeSpan.FromDays(30), SlidingExpiration = true });
3. 在应用中访问持久化的声明与令牌
- 获取用户声明:在控制器或视图中通过
User.Identity提取:
var claimsIdentity = User.Identity as ClaimsIdentity; var email = claimsIdentity?.FindFirst(ClaimTypes.Email)?.Value; var username = claimsIdentity?.FindFirst(ClaimTypes.Name)?.Value;
- 获取令牌:因为你设置了
SaveTokens=true,令牌会加密存储在Cookie的AuthenticationProperties中,可通过Owin上下文获取:
var authManager = HttpContext.GetOwinContext().Authentication; var authResult = await authManager.AuthenticateAsync(DefaultAuthenticationTypes.ApplicationCookie); var accessToken = authResult?.Properties.GetTokenValue("access_token"); var idToken = authResult?.Properties.GetTokenValue("id_token");
注意事项
- 敏感令牌(如
access_token)不要添加为用户声明,避免Cookie泄露风险,依赖SaveTokens=true的方式存储更安全。 - 若OpenId服务器返回的声明类型与
.NET ClaimTypes不匹配,可自定义声明类型(如"custom_username")进行存储。
内容的提问来源于stack exchange,提问作者Jay
相关产品推荐
相关产品推荐

