【问题标题】:Identity Server 4 - Role claims missing in OpenIdConnect handler in MVC clientIdentity Server 4 - MVC 客户端的 OpenIdConnect 处理程序中缺少角色声明
【发布时间】:2021-03-18 18:32:12
【问题描述】:

我知道这个问题已经被报告了很多,并且有很多关于如何解决这个问题的文章。我已经经历了很多,但仍然无法解决这个问题。

我正在 Identity Server 中的 OnSecurityTokenValidated 回调中对 Principal.Identity 设置自定义声明,如下所示:

public async Task SecurityTokenValidated(SecurityTokenValidatedContext context) {
    var identity = context.Principal.Identity as ClaimsIdentity;
    foreach(var claim in context.Principal.Claims.Where(x = >x.Type == "adGroupClaimType").ToList()) {
        var groupName = Configuration.GetSection("ClaimMappings").GetValue < string > ($ "Prefix_{claim.Value}");
        if (!string.IsNullOrWhiteSpace(groupName)) {
            identity.AddClaim(new Claim(ClaimTypes.Role, groupName));
        }

        identity.RemoveClaim(claim);
    }
}

以下是我在 Identity Server 中使用的配置:

public static IEnumerable < IdentityResource > IdentityResources = >new List < IdentityResource > {
    new IdentityResources.OpenId(),
    new IdentityResources.Profile(),
    new IdentityResource("roles", new[] {
        ClaimTypes.Role
    })
};

public static IEnumerable < ApiScope > ApiScopes = >new List < ApiScope > {
    new ApiScope("api", "API")
};

public static IEnumerable < Client > Clients = >new List < Client > {
    new Client {
        ClientId = "mvc-openid",
        ClientSecrets = {
            new Secret("secret".Sha256())
        },
        AllowedGrantTypes = GrantTypes.HybridAndClientCredentials,
        RedirectUris = {
            "https://localhost:6001/signin-oidc"
        },
        AllowedScopes = new List < string > {
            IdentityServerConstants.StandardScopes.OpenId,
            IdentityServerConstants.StandardScopes.Profile,
            "api",
            "roles"
        },
        RequirePkce = false,
        AllowOfflineAccess = true,
        AllowAccessTokensViaBrowser = true
    }
};

有一个 MVC 客户端使用 OpenIdConnect 连接到 Identity Server。代码如下:

public void ConfigureServices(IServiceCollection services) {
    services.AddMvc();
    JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
    JwtSecurityTokenHandler.DefaultMapInboundClaims = false;

    services.AddAuthentication(options = >{
        options.DefaultScheme = "Cookies";
        options.DefaultChallengeScheme = "oidc";
    }).AddCookie(options = >{
        options.ExpireTimeSpan = 15;
        options.SlidingExpiration = true;
        options.Cookie.SameSite = Microsoft.AspNetCore.Http.SameSiteMode.None;
    }).AddOpenIdConnect("oidc", options = >{
        options.Authority = "https://localhost:5001";
        options.ClientId = "mvc-openid";
        options.ClientSecret = "secret";
        options.ResponseType = "code id_token token";
        options.GetClaimsFromUserInfoEndpoint = true;
        options.SaveTokens = true;
        options.Scope.Add("api");
        options.Scope.Add("roles");
        options.Scope.Add("offline_access");
        options.Events.OnTokenValidated = OnTokenValidated;
        options.TokenValidationParameters = new TokenValidationParameters {
            NameClaimType = ClaimTypes.Name,
            RoleClaimType = ClaimTypes.Role
        };

        options.ClaimActions.MapUniqueJsonKey(ClaimTypes.Role, ClaimTypes.Role);
    });
}

private Task OnTokenValidated(TokenValidatedContext context) {
    var t = context.Principal.Claims;
    return Task.CompletedTask;
}

当我检查 OnTokenValidated 中的声明时,我可以看到我从 Identity Server 设置的所有角色声明都丢失了。有人可以告诉我哪里出错了吗?我已经尝试了在 Stack Overflow 线程上找到的关于这个问题的几乎所有内容。现在不知道下一步该做什么。

【问题讨论】:

  • 将 AlwaysIncludeUserClaimsInIdToken = true 添加到您的客户端配置并检查这是否会将声明添加到您的 access_token
  • @mohammadmahdiTalachi 做到了。没有任何区别。

标签: c# asp.net-core identityserver4 openid-connect


【解决方案1】:

到目前为止,我也只找到了这个解决方案。

options.Events.OnUserInformationReceived = context =>
{
    var roleElement = context.User.RootElement.GetProperty("role");

    var claims = new List<Claim>();
    if (roleElement.ValueKind == System.Text.Json.JsonValueKind.Array)
    {
        foreach (var r in roleElement.EnumerateArray())
            claims.Add(new Claim(JwtClaimTypes.Role, r.GetString()));
    }
    else
    {
        claims.Add(new Claim(JwtClaimTypes.Role, roleElement.GetString()));
    }

    var id = context.Principal.Identity as ClaimsIdentity;
    id.AddClaims(claims);

    return Task.CompletedTask;
};

https://github.com/skoruba/IdentityServer4.Admin/issues/109

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-04-20
    • 2020-12-07
    • 2016-02-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多