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.
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>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With