keycloak-webauthn-conditional-mediation icon indicating copy to clipboard operation
keycloak-webauthn-conditional-mediation copied to clipboard

NullPointerException: Cannot invoke "String.replace(char, char)" because "base64Url" is null

Open ptr1120 opened this issue 1 year ago • 2 comments

Hello, thanks for providing this user friendly Keycloak authenticator. I set up my authentication flow using the WebAuthnConditionalAuthenticator and tested it using different scenarios. Thereby I noticed the user can click on "Sign in" without entering a username, which results in a NullPointerException

WARN  [org.keycloak.services] (executor-thread-7) KC-SERVICES0013: Failed authentication: java.lang.NullPointerException: Cannot invoke "String.replace(char, char)" because "base64Url" is null
     at org.keycloak.common.util.Base64Url.encodeBase64UrlToBase64(Base64Url.java:58)
     at org.keycloak.common.util.Base64Url.decode(Base64Url.java:32)
     at org.keycloak.authentication.authenticators.browser.WebAuthnAuthenticator.action(WebAuthnAuthenticator.java:151)
     at com.twogenidentity.keycloak.authenticator.WebAuthnConditionalMediationAuthenticator.action(WebAuthnConditionalMediationAuthenticator.java:47)
     at org.keycloak.authentication.DefaultAuthenticationFlow.processAction(DefaultAuthenticationFlow.java:154)
     at org.keycloak.authentication.AuthenticationProcessor.authenticationAction(AuthenticationProcessor.java:988)
     at org.keycloak.services.resources.LoginActionsService.processFlow(LoginActionsService.java:362)
     at org.keycloak.services.resources.LoginActionsService.processAuthentication(LoginActionsService.java:333)
     at org.keycloak.services.resources.LoginActionsService.authenticate(LoginActionsService.java:325)
     at org.keycloak.services.resources.LoginActionsService.authenticateForm(LoginActionsService.java:390)
     at org.keycloak.services.resources.LoginActionsService$quarkusrestinvoker$authenticateForm_32b8e198ac3110abd1d5774e83a4cf87858129f4.invoke(Unknown Source)
     at org.jboss.resteasy.reactive.server.handlers.InvocationHandler.handle(InvocationHandler.java:29)
     at io.quarkus.resteasy.reactive.server.runtime.QuarkusResteasyReactiveRequestContext.invokeHandler(QuarkusResteasyReactiveRequestContext.java:141)
     at org.jboss.resteasy.reactive.common.core.AbstractResteasyReactiveContext.run(AbstractResteasyReactiveContext.java:145)
     at io.quarkus.vertx.core.runtime.VertxCoreRecorder$14.runWith(VertxCoreRecorder.java:576)
     at org.jboss.threads.EnhancedQueueExecutor$Task.run(EnhancedQueueExecutor.java:2513)
     at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1538)
     at org.jboss.threads.DelegatingRunnable.run(DelegatingRunnable.java:29)
     at org.jboss.threads.ThreadLocalResettingRunnable.run(ThreadLocalResettingRunnable.java:29)
     at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
     at java.base/java.lang.Thread.run(Thread.java:840)

Is there a workaround or can the username somehow be validated?

ptr1120 avatar Jan 31 '24 17:01 ptr1120

Hi @ptr1120, The authenticator extends WebAuthnPasswordlessAuthenticator and If the username is empty, it calls super.action(context), meaning it follows the logic defined there. If you want to customize this behavior, you can change the if clause and check whether the user has selected a WebAuthn mechanism. For example, you can validate if you have some of these parameters in the request: https://github.com/keycloak/keycloak/blob/main/services/src/main/java/org/keycloak/authentication/authenticators/browser/WebAuthnAuthenticator.java#L151

embesozzi avatar Feb 02 '24 16:02 embesozzi

Hello @embesozzi , thank you, but the username is not empty, it is null. You can try with just clicking on "Sign in" without entering a username.

ptr1120 avatar Feb 02 '24 18:02 ptr1120