Keycloak 可以将 JWT 访问令牌中的范围包含为数组吗?

Ada*_*rly 10 scopes oauth-2.0 keycloak

我想使用 Keycloak 来授权访问我的 API。

我已经定义了相关范围,并且这些范围按预期返回到访问令牌中:

{
  ... claims ...
  "scope": "openid profile user/Patient.write user/Patient.read",
  ... etc ...
}
Run Code Online (Sandbox Code Playgroud)

但托管 API 的服务器需要以数组表示的访问令牌中的范围,如下所示:

{
  ... claims ...
  "scope": [
    "openid",
    "profile",
    "user/Patient.read",
    "user/Patient.write"
  ],
  ...etc...
}
Run Code Online (Sandbox Code Playgroud)

我在 Keycloak 中看不到任何可以更改行为以将范围输出为数组的地方?

我已经考虑过使用自定义令牌映射器脚本来执行此操作,但范围似乎在映射器脚本中不可用,因此看起来我无法以这种方式重新映射它们。有什么方法可以将 Keycloak 中令牌的范围转换为这种形式吗?

And*_* M. 2

我发现解决这个问题的唯一方法是提供自定义映射器作为 Keycloak 扩展。

因此,您可以创建一个从默认值扩展的映射器AbstractOIDCProtocolMapper,并覆盖方法内现有的范围声明transformAccessToken

package com.example;

import org.keycloak.models.ClientSessionContext;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.ProtocolMapperModel;
import org.keycloak.models.UserSessionModel;
import org.keycloak.protocol.oidc.mappers.AbstractOIDCProtocolMapper;
import org.keycloak.protocol.oidc.mappers.OIDCAccessTokenMapper;
import org.keycloak.provider.ProviderConfigProperty;
import org.keycloak.representations.AccessToken;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;

public class CustomOIDCProtocolMapper extends AbstractOIDCProtocolMapper
    implements OIDCAccessTokenMapper {

    public static final String PROVIDER_ID = "oidc-custom-protocol-mapper";

    @Override
    public AccessToken transformAccessToken(AccessToken token, ProtocolMapperModel mappingModel, KeycloakSession session, UserSessionModel userSession, ClientSessionContext clientSessionCtx) {
        token.getOtherClaims().put("scope", Arrays.asList(token.getScope().split(" ")));
        setClaim(token, mappingModel, userSession, session, clientSessionCtx);
        return token;
    }

    @Override
    public String getDisplayCategory() {
        return TOKEN_MAPPER_CATEGORY;
    }

    @Override
    public String getDisplayType() {
        return "Custom Scope Claim Mapper";
    }

    @Override
    public String getHelpText() {
        return "Modifies `scope` claim in resulting access token";
    }

    @Override
    public List<ProviderConfigProperty> getConfigProperties() {
        return Collections.emptyList();
    }

    @Override
    public String getId() {
        return PROVIDER_ID;
    }
}
Run Code Online (Sandbox Code Playgroud)

然后通过创建文本文件来注册您的映射器resources/META-INF/services/org.keycloak.protocol.ProtocolMapper

com.example.CustomOIDCProtocolMapper
Run Code Online (Sandbox Code Playgroud)

然后将扩展打包为 Jar 文件并将其放入您的 Keycloakproviders/目录中。如果扩展已正确加载,您应该能够通过转到客户端设置来添加映射器。

将映射器添加到客户端

因此,您的客户端映射器选项卡内容应类似于以下内容:

客户端映射器的结果列表

将映射器正确添加到客户端后,scope声明将在生成的访问令牌中映射为 JSON 数组。

有关 Keycloak 扩展开发人员的文档可以在此处找到。