【问题标题】:Added Custom Claim, showing in ID token missing in Access token添加了自定义声明,显示在访问令牌中缺少的 ID 令牌中
【发布时间】:2021-07-25 17:14:42
【问题描述】:

我有一个 .NET Core 身份提供程序(也使用 IdentityServer4),它使用 Azure AD 对 SPA 应用程序进行身份验证。我正在使用从 Azure 收到的对象标识符值添加“oid”声明。问题是,从 SPA 应用程序中,我可以在 ID 令牌中看到“oid”声明,但在访问令牌中看不到它。我也需要访问令牌中的 oid。以下是相关代码:

Startup.cs

services.AddAuthentication()
    .AddCookie("Cookies", options =>
    {
        options.ExpireTimeSpan = TimeSpan.FromMinutes(10);

    })
    .AddOpenIdConnect(ActiveDirectoryTenants.TenantA, ActiveDirectoryTenants.TenantA, options => Configuration.Bind("TenantAAzureAd", options))
    .AddOpenIdConnect(ActiveDirectoryTenants.TenantB, ActiveDirectoryTenants.TenantB, options => Configuration.Bind("TenantBAzureAd", options));
    
AddActiveDirectoryOpenIdConnectOptions(services, ActiveDirectoryTenants.TenantA);
AddActiveDirectoryOpenIdConnectOptions(services, ActiveDirectoryTenants.TenantB);

我有一个常用功能可以为这些配置添加其他选项。我尝试在 OnTokenValidated 中添加 oid 声明,但未在访问令牌中收到 oid 声明。

protected virtual void AddActiveDirectoryOpenIdConnectOptions(IServiceCollection services, string tenant)
{
    services.Configure<OpenIdConnectOptions>(tenant, options =>
    {
        options.Authority = options.Authority + "/v2.0/"; 
        options.TokenValidationParameters.ValidateIssuer = false; 

        options.Events = new OpenIdConnectEvents
        {
            OnRedirectToIdentityProvider = ctx =>
            {
                ctx.ProtocolMessage.LoginHint = ctx.Properties.GetString("username");
                return Task.CompletedTask;
            },
            OnTokenValidated = ctx =>
            {
                //Maybe need to add oid here??? 
            }
        };
    });
}

在成功登录 Azure AD 后正在添加 oid 声明。

AccountController.cs

public async Task<IActionResult> ExternalLoginCallback(string returnUrl, string remoteError = null, string openIdScheme = null)
{
    var authResult = await HttpContext.AuthenticateAsync(openIdScheme ?? ActiveDirectoryTenants.TenantA);
    var externalUser = authResult.Principal;
    var claims = externalUser.Claims.ToList();
    var applicationUser = //gets the user based on the email found in claims, omitted for brevity
    
    await userManager.AddClaimAsync(applicationUser, new Claim("oid", claims.First(x => x.Type == http://schemas.microsoft.com/identity/claims/objectidentifier).Value));
    
    await signInManager.SignInAsync(applicationUser, false, "AzureAD");

    return Redirect("~/");
}

在 SPA 应用程序中收到的 ID 令牌(注意 oid 声明):

{
  "nbf": xxx,
  "exp": xxx,
  "iss": "https://localhost:3000", 
  "aud": "xxx-spa-test",
  "iat": xxx,
  "at_hash": "",
  "s_hash": "",
  "sid": "",
  "sub": "guid",
  "auth_time": 1620026953,
  "idp": "AzureAD",
  "display_name": "Test User",
  "oid": "guid",
  "role": [
    "Staff",
  ],
  "name": "test@azureaddomain",
  "amr": [
    "external"
  ]
}

SPA 应用程序中收到的访问令牌(注意缺少的 oid 声明):

{
  "nbf": xxx,
  "exp": xxx,
  "iss": "https://localhost:3000",
  "aud": [
    "https://localhost:3000/resources",
    "xxx-api-test-scope"
  ],
  "client_id": "xxx-spa-test",
  "sub": "guid",
  "auth_time": 1620026953,
  "idp": "AzureAD",
  "role": [
    "Staff",
  ],
  "name": "test@azureaddomain",
  "scope": [
    "openid",
    "profile",
    "xxx-api-test-scope"
  ],
  "amr": [
    "external"
  ]
}

【问题讨论】:

    标签: identityserver4 access-token asp.net-core-identity


    【解决方案1】:

    要使声明最终出现在访问令牌中,您需要添加一个 ApiScope 并向其添加 Userclaim 名称。或者,添加一个 ApiScope 和一个包含 UserClaim 的 ApiResource。

    喜欢

    var apiresource1 = new ApiResource()
    {
        Name = "apiresource1",   //This is the name of the API
        ApiSecrets = new List<Secret>
        {
            new Secret("myapisecret".Sha256())
        },
        Description = "This is the order Api-resource description",
        Enabled = true,
        DisplayName = "Orders API Service",
        Scopes = new List<string> { "apiscope1"},
        UserClaims = new List<string>
        {
            //Custom user claims that should be provided when requesting access to this API.
            //These claims will be added to the access token, not the ID-token!
            "apiresource1-userclaim3",
        }
    };
    

    查看我的回答here了解更多详情

    【讨论】:

    • 感谢您的回答!这使我朝着正确的方向前进。在继承自 IResourceStore(来自 IdentityServer4)的实现类中将声明添加到 ApiResource 后,我现在可以看到自定义声明:)
    • 太棒了!很高兴你成功了!
    猜你喜欢
    • 2020-11-05
    • 1970-01-01
    • 2021-11-14
    • 1970-01-01
    • 2018-02-07
    • 2019-06-24
    • 2020-01-15
    • 2021-12-01
    • 2017-11-29
    相关资源
    最近更新 更多