【问题标题】:Keycloak Protocol Mapper that adds claim to JWT gets Null Pointer Exception向 JWT 添加声明的 Keycloak 协议映射器获取空指针异常
【发布时间】:2019-12-26 04:04:12
【问题描述】:

我很难在 Keycloak 6.0.1 中获得一个非常简单的 Keycloak ProtocolMapper。
我正在尝试向访问令牌添加额外的声明。当我将构建的 jar 复制到部署目录时,我在部署目录中得到以下 NullPointerException,其中 .failed 文件中的内容如下。

{"WFLYCTL0080: Failed services" => {"jboss.deployment.unit.\"token-enhancer-1.0-SNAPSHOT.jar\".POST_MODULE" => "WFLYSRV0153: Failed to process phase POST_MODULE of deployment \"token-enhancer-1.0-SNAPSHOT.jar\"
    Caused by: java.lang.NullPointerException"}}

日志在下面显示相同的异常

21:18:46,697 INFO  [org.keycloak.subsystem.server.extension.KeycloakProviderDeploymentProcessor] (MSC service thread 1-1) Deploying Keycloak provider: token-enhancer-1.0-SNAPSHOT.jar
21:18:46,718 ERROR [org.jboss.msc.service.fail] (MSC service thread 1-1) MSC000001: Failed to start service jboss.deployment.unit."token-enhancer-1.0-SNAPSHOT.jar".POST_MODULE: org.jboss.msc.service.StartException in service jboss.deployment.unit."token-enhancer-1.0-SNAPSHOT.jar".POST_MODULE: WFLYSRV0153: Failed to process phase POST_MODULE of deployment "token-enhancer-1.0-SNAPSHOT.jar"
        at org.jboss.as.server.deployment.DeploymentUnitPhaseService.start(DeploymentUnitPhaseService.java:183)
        at org.jboss.msc.service.ServiceControllerImpl$StartTask.startService(ServiceControllerImpl.java:1738)
        at org.jboss.msc.service.ServiceControllerImpl$StartTask.execute(ServiceControllerImpl.java:1700)
        at org.jboss.msc.service.ServiceControllerImpl$ControllerTask.run(ServiceControllerImpl.java:1558)
        at org.jboss.threads.ContextClassLoaderSavingRunnable.run(ContextClassLoaderSavingRunnable.java:35)
        at org.jboss.threads.EnhancedQueueExecutor.safeRun(EnhancedQueueExecutor.java:1982)
        at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.doRunTask(EnhancedQueueExecutor.java:1486)
        at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1377)
        at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.NullPointerException
        at org.keycloak.services.DefaultKeycloakSessionFactory.isInternal(DefaultKeycloakSessionFactory.java:370)
        at org.keycloak.services.DefaultKeycloakSessionFactory.loadFactories(DefaultKeycloakSessionFactory.java:219)
        at org.keycloak.services.DefaultKeycloakSessionFactory.deploy(DefaultKeycloakSessionFactory.java:115)
        at org.keycloak.provider.ProviderManagerRegistry.deploy(ProviderManagerRegistry.java:42)
        at org.keycloak.subsystem.server.extension.KeycloakProviderDeploymentProcessor.deploy(KeycloakProviderDeploymentProcessor.java:55)
        at org.jboss.as.server.deployment.DeploymentUnitPhaseService.start(DeploymentUnitPhaseService.java:176)
        ... 8 more

21:18:46,719 ERROR [org.jboss.as.controller.management-operation] (DeploymentScanner-threads - 1) WFLYCTL0013: Operation ("full-replace-deployment") failed - address: ([]) - failure description: {"WFLYCTL0080: Failed services" => {"jboss.deployment.unit.\"token-enhancer-1.0-SNAPSHOT.jar\".POST_MODULE" => "WFLYSRV0153: Failed to process phase POST_MODULE of deployment \"token-enhancer-1.0-SNAPSHOT.jar\"
    Caused by: java.lang.NullPointerException"}}

我已将示例代码上传到github

我实现的 ProtocolMapper 类如下。

我遇到了困难,因为我不知道在哪里可以解决如此模糊的错误消息。调查此问题的好策略是什么?

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.OIDCLoginProtocol;
import org.keycloak.protocol.oidc.mappers.*;
import org.keycloak.provider.ProviderConfigProperty;
import org.keycloak.representations.AccessToken;
import org.keycloak.representations.IDToken;

import java.util.*;

public class KeycloakTokenEnhancer extends AbstractOIDCProtocolMapper implements OIDCAccessTokenMapper, OIDCIDTokenMapper, UserInfoTokenMapper {

    public static final String PROVIDER_ID = "oidc-token-enhancer-mapper";

    private static final List<ProviderConfigProperty> configProperties = new ArrayList<>();

    static {
        OIDCAttributeMapperHelper.addIncludeInTokensConfig(configProperties, KeycloakTokenEnhancer.class);
    }

    @Override
    public AccessToken transformAccessToken(AccessToken accessToken, ProtocolMapperModel protocolMapperModel, KeycloakSession keycloakSession, UserSessionModel userSessionModel, ClientSessionContext clientSessionContext) {
        return accessToken;
    }

    @Override
    public String getDisplayCategory() {
        return "Token Enhancer mapper";
    }

    @Override
    public String getDisplayType() {
        return "Token Enhancer Mapper";
    }

    @Override
    public String getHelpText() {
        return "Add to claims for the User Service";
    }

    @Override
    public List<ProviderConfigProperty> getConfigProperties() {
        return configProperties;
    }

    @Override
    public String getId() {
        return PROVIDER_ID;
    }


    protected void setClaim(IDToken token, ProtocolMapperModel mappingModel, UserSessionModel userSession) {
        token.getOtherClaims().put("fruit", "pear, apple, tangerine");
    }

    public static ProtocolMapperModel create(String name, boolean accessToken, boolean idToken, boolean userInfo) {
        ProtocolMapperModel mapper = new ProtocolMapperModel();
        mapper.setName(name);
        mapper.setProtocolMapper(PROVIDER_ID);
        mapper.setProtocol(OIDCLoginProtocol.LOGIN_PROTOCOL);
        Map<String, String> config = new HashMap<String, String>();
        if (accessToken) config.put(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN, "true");
        if (idToken) config.put(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN, "true");
        if (userInfo) config.put(OIDCAttributeMapperHelper.INCLUDE_IN_USERINFO, "true");
        mapper.setConfig(config);
        return mapper;
    }


}

【问题讨论】:

    标签: keycloak keycloak-services


    【解决方案1】:

    尝试在您的班级顶部添加package 语句 (KeycloakTokenEnhancer) 并将您的班级移动到包中。

    NPE 从line 370 in DefaultKeycloakSessionFactory 抛出:

    String packageName = factory.getClass().getPackage().getName();
    

    另请参阅: Javadoc of Class.html#getPackage

    回报:
    类的包,如果存档或代码库中没有包信息可用,则返回 null。

    【讨论】:

    • 您的回答让我找到了一种更好的解决问题的方法。我现在觉得很傻。谢谢。
    猜你喜欢
    • 2018-07-15
    • 2018-04-19
    • 2019-04-04
    • 1970-01-01
    • 1970-01-01
    • 2019-01-06
    • 2021-06-27
    • 1970-01-01
    • 2020-05-21
    相关资源
    最近更新 更多