向JWT添加声明的Keycloak协议映射器获得Null指针异常

时间:2019-08-20 22:05:52

标签: keycloak keycloak-services

我很难在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;
    }


}

1 个答案:

答案 0 :(得分:1)

尝试在班级(package)的顶部添加一个KeycloakTokenEnhancer语句,然后将班级移到包中。

line 370 in DefaultKeycloakSessionFactory抛出NPE:

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

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

  

返回:
  类的程序包;如果归档或代码库中没有可用的程序包信息,则为null。