Shadowman
Shadowman

Reputation: 12039

NullPointerException on all KeyCloak Admin API Calls

I am trying to make calls to the KeyCloak Admin API using the Java client. Regardless of which operation I try -- create a realm, create user accounts, etc. -- I get the following Exception:

javax.ws.rs.ProcessingException: java.lang.NullPointerException at org.keycloak.admin.client.resource.BearerAuthFilter.filter(BearerAuthFilter.java:53) at org.jboss.resteasy.client.jaxrs.internal.ClientInvocation.filterRequest(ClientInvocation.java:573) at org.jboss.resteasy.client.jaxrs.internal.ClientInvocation.invoke(ClientInvocation.java:438) at org.jboss.resteasy.client.jaxrs.internal.proxy.ClientInvoker.invoke(ClientInvoker.java:102) at org.jboss.resteasy.client.jaxrs.internal.proxy.ClientProxy.invoke(ClientProxy.java:76) at com.sun.proxy.$Proxy214.create(Unknown Source)

My KeyCloak code looks like this...

Keycloak kc = KeycloakBuilder.builder().realm("master").clientId("admin-cli").username("admin") .password("password").serverUrl("http://localhost:8880/auth")
                .resteasyClient(new ResteasyClientBuilder().connectionPoolSize(10).build()).build();

RealmRepresentation realm = new RealmRepresentation();
        realm.setDisplayName(displayName);
        realm.setDisplayNameHtml(displayName);
        realm.setRealm(realmName);
        realm.setEnabled(enabled);

kc.realms().create(realm);

It is at this point I see the Exception. Any idea on what could be going wrong here? I see the Exception on ALL operations against the admin API. I know that the data is available, because I am able to make a curl call against the admin API and it works fine.

curl -vki -H "Authorization: Bearer XXXXX" http://localhost:8880/auth/admin/realms/master

When I make this call, I see the expected results. I only get failures when using the Java client. Any idea what's going on here??

UPDATE

I've increased the debugging logs on my KeyCloak instance. I see the following messages after attempting to create a security realm. (Note: I see similar errors regardless of what operation I perform)

14:36:16,553 DEBUG [org.keycloak.transaction.JtaTransactionWrapper] (default task-24) new JtaTransactionWrapper
14:36:16,553 DEBUG [org.keycloak.transaction.JtaTransactionWrapper] (default task-24) was existing? false
14:36:16,557 DEBUG [org.keycloak.authentication.AuthenticationProcessor] (default task-24) AUTHENTICATE CLIENT
14:36:16,557 DEBUG [org.keycloak.authentication.ClientAuthenticationFlow] (default task-24) client authenticator: client-secret
14:36:16,557 DEBUG [org.keycloak.authentication.ClientAuthenticationFlow] (default task-24) client authenticator SUCCESS: client-secret
14:36:16,557 DEBUG [org.keycloak.authentication.ClientAuthenticationFlow] (default task-24) Client admin-cli authenticated by client-secret
14:36:16,558 DEBUG [org.keycloak.authentication.AuthenticationProcessor] (default task-24) AUTHENTICATE ONLY
14:36:16,559 DEBUG [org.keycloak.authentication.DefaultAuthenticationFlow] (default task-24) processFlow
14:36:16,559 DEBUG [org.keycloak.authentication.DefaultAuthenticationFlow] (default task-24) check execution: direct-grant-validate-username requirement: REQUIRED
14:36:16,559 DEBUG [org.keycloak.authentication.DefaultAuthenticationFlow] (default task-24) authenticator: direct-grant-validate-username
14:36:16,560 DEBUG [org.keycloak.authentication.DefaultAuthenticationFlow] (default task-24) invoke authenticator.authenticate: direct-grant-validate-username
14:36:16,560 DEBUG [org.keycloak.authentication.DefaultAuthenticationFlow] (default task-24) authenticator SUCCESS: direct-grant-validate-username
14:36:16,561 DEBUG [org.keycloak.authentication.DefaultAuthenticationFlow] (default task-24) check execution: direct-grant-validate-password requirement: REQUIRED
14:36:16,561 DEBUG [org.keycloak.authentication.DefaultAuthenticationFlow] (default task-24) authenticator: direct-grant-validate-password
14:36:16,561 DEBUG [org.keycloak.authentication.DefaultAuthenticationFlow] (default task-24) invoke authenticator.authenticate: direct-grant-validate-password
14:36:16,658 DEBUG [org.keycloak.authentication.DefaultAuthenticationFlow] (default task-24) authenticator SUCCESS: direct-grant-validate-password
14:36:16,658 DEBUG [org.keycloak.authentication.DefaultAuthenticationFlow] (default task-24) check execution: direct-grant-validate-otp requirement: OPTIONAL
14:36:16,659 DEBUG [org.keycloak.authentication.DefaultAuthenticationFlow] (default task-24) authenticator: direct-grant-validate-otp
14:36:16,659 DEBUG [org.keycloak.authentication.DefaultAuthenticationFlow] (default task-24) invoke authenticator.authenticate: direct-grant-validate-otp
14:36:16,659 DEBUG [org.keycloak.authentication.DefaultAuthenticationFlow] (default task-24) authenticator ATTEMPTED: direct-grant-validate-otp
14:36:16,661 DEBUG [org.keycloak.services.managers.AuthenticationSessionManager] (default task-24) Removing authSession 'df66e278-8ffe-47ab-84d1-36ffe9152021'. Expire restart cookie: true
14:36:16,673 DEBUG [org.keycloak.events] (default task-24) type=LOGIN, realmId=master, clientId=admin-cli, userId=c830af10-3cfd-4ce0-b1aa-83a857a290d7, ipAddress=172.18.0.1, auth_method=openid-connect, token_id=8876c7ad-3ea4-4356-8fc2-f9b50112b952, grant_type=password, refresh_token_type=Refresh, scope='profile email', refresh_token_id=4c2325fc-0bb5-40d9-af55-4985546fd39a, client_auth_method=client-secret, username=kcadmin
14:36:16,673 DEBUG [org.keycloak.transaction.JtaTransactionWrapper] (default task-24) JtaTransactionWrapper  commit
14:36:16,676 DEBUG [org.keycloak.transaction.JtaTransactionWrapper] (default task-24) JtaTransactionWrapper end

UPDATE 2

It appears as though this issue is related to running this code within a Java EE container. If I run the exact same code in a standalone class, it works with no issue. However, if I copy and paste the code to a servlet and attempt to run it, I receive the NullPointerException. I am running the code on Wildfly 13 when I encounter the problem. I also see this issue when running integration tests via Arquillian. My assumption is that it must have something to do with dependencies, but I'm at a loss as to what needs to be changed.

Upvotes: 7

Views: 10197

Answers (4)

nonzaprej
nonzaprej

Reputation: 1600

Put simply (maybe even too much), there was a bug related to the Resteasy libraries, where the JsonBindingProvider was given precedence over the ResteasyJackson2Provider, which made some properties in json payloads not get mapped properly and their values get lost. Hence the NullPointerException.

The simplest solution if you're using JBoss or WildFly should be to exclude the resteasy-json-binding-provider module from your deployment in the jboss-deployment-structure.xml file:

<jboss-deployment-structure>
    <deployment>
        <exclusions>
            <module name="org.jboss.resteasy.resteasy-json-binding-provider"/>
        </exclusions>
    </deployment>
</jboss-deployment-structure>

Upvotes: 5

sider
sider

Reputation: 193

If you want to keep Java EE 8 support of WildFly 13, just create empty jackson provider:

public class CustomJacksonProvider extends ResteasyJackson2Provider {

}

and add it to your KeyCloak builder using register() method of ResteasyClientBuilder:

Keycloak kc = KeycloakBuilder.builder()
.realm("master")
.clientId("admin-cli")
.username("admin")
.password("password")
.serverUrl("http://localhost:8880/auth")
.resteasyClient(new ResteasyClientBuilder().connectionPoolSize(10).register(new CustomJacksonProvider()).build())
.build();

You also need to add some resteasy dependecies (as scope=provided) in order to be able to use ResteasyClientBuilder and ResteasyClientBuilder:

    <dependency>
        <groupId>org.jboss.resteasy</groupId>
        <artifactId>resteasy-client</artifactId>
        <version>3.6.2.Final</version>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>org.jboss.resteasy</groupId>
        <artifactId>resteasy-jackson2-provider</artifactId>
        <version>3.6.2.Final</version>
        <scope>provided</scope>
    </dependency>

Upvotes: 9

Shadowman
Shadowman

Reputation: 12039

Solved!! Apparently my Wildfly 13.0 instance was configured to enable Java EE 8 support. This seems to be the root cause of the issue, because removing that flag enabled all test cases to work as expected. Not sure why this was a problem, but it was definitely the underlying issue.

Upvotes: -3

user2743227
user2743227

Reputation:

You don't have an authorization header. Please try

Keycloak kc = KeycloakBuilder.builder().realm("master").clientId("admin-cli").username("admin") .password("password").authorization("authorization").serverUrl("http://localhost:8880/auth")
            .resteasyClient(new ResteasyClientBuilder().connectionPoolSize(10).build()).build();

Note the

.authorization("authorization")

Upvotes: 1

Related Questions