embesozzi / keycloak-webauthn-conditional-mediation

Keycloak Authentication Provider implementation for Webauthn with Conditional Mediation (Passkey autofill)
Apache License 2.0
16 stars 2 forks source link

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

Open ptr1120 opened 8 months ago

ptr1120 commented 8 months ago

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?

embesozzi commented 8 months ago

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

ptr1120 commented 8 months ago

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.