Не удается получить доступ к ролям в токене JWT .NET Core - PullRequest
0 голосов
/ 10 декабря 2018

У меня есть приложение, созданное с использованием .NET Core API, Keycloak и JWT Token.

Более старая версия Keycloak, которую я использовал до сих пор, когда он создавал токен JWT, писал здесь роли на полезной нагрузке:

{
    "user_roles": [
        "offline_access",
        "uma_authorization",
        "admin",
        "create-realm"
  ]
}

Но теперь, после того как я обновил его,здесь записываются роли в полезной нагрузке:

{
  "realm_access": {
    "roles": [
      "create-realm",
      "teacher",
      "offline_access",
      "admin",
      "uma_authorization"
    ]
  },
}

И мне нужно знать, как заменить этот старый код на новый, чтобы сказать, что не смотрите user_roles, но посмотрите realm_access затем roles.

public void AddAuthorization(IServiceCollection services)
{
    services.AddAuthorization(options =>
    {
        options.AddPolicy("Administrator", policy => policy.RequireClaim("user_roles", "admin"));
        options.AddPolicy("Teacher", policy => policy.RequireClaim("user_roles", "teacher"));
        options.AddPolicy("Pupil", policy => policy.RequireClaim("user_roles", "pupil"));
        options.AddPolicy(
            "AdminOrTeacher",
            policyBuilder => policyBuilder.RequireAssertion(
                context => context.User.HasClaim(claim =>
                               claim.Type == "user_roles" && (claim.Value == "admin" || claim.Value == "teacher")
                          ))
        );
    });
}

1 Ответ

0 голосов
/ 17 декабря 2018

Следующий код преобразует требование realm_access.roles (токен JWT) из Keycloak (v4.7.0) в утверждения-роли Microsoft Identity Model:

public void ConfigureServices(IServiceCollection services)
{
    ...
    services.AddTransient<IClaimsTransformation, ClaimsTransformer>();
    ...
}

public class ClaimsTransformer : IClaimsTransformation
{
    public Task<ClaimsPrincipal> TransformAsync(ClaimsPrincipal principal)
    {
        ClaimsIdentity claimsIdentity = (ClaimsIdentity)principal.Identity;

        // flatten realm_access because Microsoft identity model doesn't support nested claims
        // by map it to Microsoft identity model, because automatic JWT bearer token mapping already processed here
        if (claimsIdentity.IsAuthenticated && claimsIdentity.HasClaim((claim) => claim.Type == "realm_access"))
        {
            var realmAccessClaim = claimsIdentity.FindFirst((claim) => claim.Type == "realm_access");
            var realmAccessAsDict = JsonConvert.DeserializeObject<Dictionary<string, string[]>>(realmAccessClaim.Value);
            if (realmAccessAsDict["roles"] != null)
            {
                foreach (var role in realmAccessAsDict["roles"])
                {
                    claimsIdentity.AddClaim(new Claim("http://schemas.microsoft.com/ws/2008/06/identity/claims/role", role));
                }
            }
        }

        return Task.FromResult(principal);
    }
}
...