You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 10:53:18