Identity Server 4: Как добавить пользовательские утверждения только для UserInfoEndpoint и исключить их в AccessToken? - PullRequest
1 голос
/ 21 февраля 2020

Мы хотим обслуживать большой объем данных в заявках пользователей из UserInfoEndPoint, но не хотим встраивать эти заявки в AccessToken.

Насколько я знаю, мы можем вернуть дополнительные данные из UserInfoEndPoint, когда мы хотим, чтобы размер AccessToken был небольшим. Ссылка: служба профиля

Итак, я реализовал 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())
                    }
            };

Вот моя MVC. Net Базовая конфигурация клиента, которая подключается к Identity Server

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;

            });

Не могли бы вы помочь мне с этим и дайте мне знать, возможно ли скрыть эти претензии в токене или нет?

1 Ответ

0 голосов
/ 21 февраля 2020

Я поэкспериментировал с этим один раз и нашел решение, но его можно было бы считать «хакерским» - оно работало, но я никогда не использовал его в работе, поэтому используйте на свой страх и риск.

GetProfileDataAsyn c () метод вашего ProfileService вызывается в разное время - при создании JWT, при достижении точки UserEndpoint и т. Д. c. В этом случае вы НЕ хотите, чтобы ваши пользовательские утверждения добавлялись при создании JWT, поэтому создайте условие, которое не добавляет их, когда «Caller» - это процесс создания 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.

...