【问题标题】:Identity Server 4: How to add Custom Claims only for UserInfoEndpoint and exclude them in AccessToken?Identity Server 4:如何仅为 UserInfoEndpoint 添加自定义声明并在 AccessToken 中排除它们?
【发布时间】:2020-06-05 08:31:13
【问题描述】:

我们希望在来自 UserInfoEndPoint 的用户声明中提供大量数据,但我们不想将这些声明嵌入到 AccessToken 中。

据我所知,当我们想要保持较小的 AccessToken 大小时,我们可以从 UserInfoEndPoint 返回附加数据。 Ref: Profile Service

所以,我按照以下方式实现了 IProfileService:

public class ProfileService : IProfileService
{
    public async Task GetProfileDataAsync(ProfileDataRequestContext context)
    {
        var sub = context.Subject.GetSubjectId();

        // Get data from Db
        var claims = new List<Claim>();

        claims.Add(new Claim("global_company_id", "88888888-D964-4A2B-8D56-B893A5BCD700"));
        //..... add series of additional claims

        context.IssuedClaims = claims;
    }

    public async Task IsActiveAsync(IsActiveContext context)
    {
        var sub = context.Subject.GetSubjectId();

        context.IsActive = true;
    }
}

它返回来自 UserInfoEndpoint 的扩展声明。但是,问题是这些声明集也包含在 Jwt 访问令牌中,这使令牌不必要地变大了。

{
  "nbf": 1582236568,
  "exp": 1582236868,
  "iss": "https://localhost:44378",
  "aud": [
    "https://localhost:44378/resources",
    "testapi"
  ],
  "client_id": "testClientId",
  "sub": "78452916-D260-4219-927C-954F4E987E70",
  "auth_time": 1582236558,
  "idp": "local",
  "name": "ttcg",
  "global_company_id": "88888888-D964-4A2B-8D56-B893A5BCD700",
  //........ series of claims here
  "scope": [
    "openid",
    "profile",
    "address",
    "roles",
    "country",
    "customClaims"
  ],
  "amr": [
    "pwd"
  ]
}

这是我在 Identity Server Provider 中的客户端配置:

var clientUrl = "http://localhost:64177";
            return new Client
            {
                ClientName = "Test Web Application",
                ClientId = "testClientId",
                AllowedGrantTypes = GrantTypes.Hybrid,
                AllowOfflineAccess = false,
                RequireConsent = false,
                RedirectUris = new List<string>
                    {
                        $"{clientUrl}/signin-oidc"
                    },
                PostLogoutRedirectUris = new List<string>
                    {
                        $"{clientUrl}/signout-callback-oidc"
                    },
                AllowedScopes = new List<string>
                    {
                        IdentityServerConstants.StandardScopes.OpenId,
                        IdentityServerConstants.StandardScopes.OfflineAccess,
                        "t1_global_ids"
                    },
                ClientSecrets =
                    {
                        new Secret("abc123".Sha256())
                    }
            };

这是我连接到 Identity Server 的 MVC .Net Core 客户端配置

services.AddAuthentication(options =>
            {
                options.DefaultScheme = "Cookies";
                options.DefaultChallengeScheme = "oidc";
            })
            .AddCookie("Cookies", options =>
            {
                options.AccessDeniedPath = "/AccessDenied";
            })
            .AddOpenIdConnect("oidc", options =>
            {
                options.SignInScheme = "Cookies";
                options.Authority = "http://identityserverUrl";
                options.ClientId = "testClientId";
                options.ResponseType = "code id_token";

                options.Scope.Add("openid");
                options.Scope.Add("profile");
                options.Scope.Add("CustomClaims"); // <-- here

                options.SaveTokens = true;
                options.ClientSecret = "abc123";
                options.GetClaimsFromUserInfoEndpoint = true;

            });

您能否帮我解决一下,让我知道是否可以将这些声明隐藏在令牌中?

【问题讨论】:

    标签: identityserver4 claims


    【解决方案1】:

    我玩过一次,找到了一个解决方案,但它可能被认为是“hacky”——它有效,但我从未在生产中使用它,因此使用风险自负。

    您的 ProfileService 的 GetProfileDataAsync() 方法在不同的时间被调用——当 JWT 创建时,当 UserEndpoint 被命中时等等。在这种情况下,您不希望在创建 JWT 时添加您的自定义声明,所以创建一个条件,当“调用者”是 JWT 创建过程(类型为“ClaimsProviderAccessToken”)时不添加它们。

    public async Task GetProfileDataAsync(ProfileDataRequestContext context)
    {
       if (context.Caller != IdentityServerConstants.ProfileDataCallers.ClaimsProviderAccessToken)
       {
          var sub = context.Subject.GetSubjectId();
    
          // Get data from Db
          var claims = new List<Claim>();
    
          claims.Add(new Claim("global_company_id", "88888888-D964-4A2B-8D56-B893A5BCD700"));
          //..... add series of additional claims
    
          context.IssuedClaims = claims;
       }
    }
    

    这样,JWT 不包含您的自定义声明,但如果您点击 UserEndpoint,它将作为 JSON 的一部分返回这些用户的声明。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-12-28
      • 2021-02-16
      • 1970-01-01
      • 2017-05-14
      • 2018-10-16
      • 1970-01-01
      • 2018-10-06
      • 1970-01-01
      相关资源
      最近更新 更多