Attestation Conveyance Verification with YubiKey
See original GitHub issueDescribe the bug
Disclaimer
This might be a bug, or might be a fixed issue from a previous version, which now is causing the error. The questioning behind the classification is explained in the description of the possible bug.
Description
When trying to use Direct as Attestation Conveyance, keycloak reports an error (described in the actual behaviour). On previous version of keycloak (15.0), this error did not happen.
References
https://github.com/keycloak/keycloak-community/blob/main/design/web-authn-authenticator.md https://issues.redhat.com/browse/KEYCLOAK-11372 https://www.keycloak.org/docs/latest/server_installation/index.html#_truststore https://developers.yubico.com/yubico-piv-tool/Attestation.html https://www.w3.org/TR/webauthn/#attestation-statement
Considerations
We are using a physical YubiKey. Using Chrome
General Steps
This steps are required in both the expected behaviour and the actual behaviour. To avoid repetition, they are included in this section.
- Enable WebAuthn Verification following the steps defined in https://github.com/keycloak/keycloak-documentation/blob/main/server_admin/topics/authentication/webauthn.adoc
- Under Authentication > WebAuthn Policy > Attestation Conveyance Preference set it to Direct
- Acceptable AAGUID’s > the AAGUID’s of the accepted YubiKeys.
Version
17 (Quarkus)
Expected behavior
When the Attestation Conveyance Preference is set to direct, according to the WebAuthn Stadard, we expect Keycloak to verify the Attestation provided by the Authentication / Browser and register the key information.
Steps:
- User goes to login page
- User is presented with username and password (first login)
- User is required to register USB key to keycloak as specified in the General Steps
- User registers key successfully and keycloak saves the key information on the database
- User proceeds to initially intended web page
Actual behavior
On the actual behaviour, when Keycloak tries to register the key information, it shows the following error message:
2022-03-17 05:51:46,146 ERROR [org.keycloak.services.error.KeycloakErrorHandler] (executor-thread-20) Uncaught server error: java.lang.NoClassDefFoundError: org/apache/kerby/asn1/type/Asn1OctetString
at com.webauthn4j.validator.attestation.statement.packed.PackedAttestationStatementValidator.extractAAGUIDFromAttestationCertificate(PackedAttestationStatementValidator.java:106)
at com.webauthn4j.validator.attestation.statement.packed.PackedAttestationStatementValidator.validateX5c(PackedAttestationStatementValidator.java:90)
at com.webauthn4j.validator.attestation.statement.packed.PackedAttestationStatementValidator.validate(PackedAttestationStatementValidator.java:62)
at com.webauthn4j.validator.AttestationValidator.validateAttestationStatement(AttestationValidator.java:161)
at com.webauthn4j.validator.AttestationValidator.validate(AttestationValidator.java:97)
at com.webauthn4j.validator.RegistrationDataValidator.validate(RegistrationDataValidator.java:180)
at com.webauthn4j.WebAuthnRegistrationManager.validate(WebAuthnRegistrationManager.java:276)
at org.keycloak.authentication.requiredactions.WebAuthnRegister.processAction(WebAuthnRegister.java:231)
at org.keycloak.services.resources.LoginActionsService.processRequireAction(LoginActionsService.java:1040)
at org.keycloak.services.resources.LoginActionsService.requiredActionPOST(LoginActionsService.java:975)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.jboss.resteasy.core.MethodInjectorImpl.invoke(MethodInjectorImpl.java:170)
at org.jboss.resteasy.core.MethodInjectorImpl.invoke(MethodInjectorImpl.java:130)
at org.jboss.resteasy.core.ResourceMethodInvoker.internalInvokeOnTarget(ResourceMethodInvoker.java:660)
at org.jboss.resteasy.core.ResourceMethodInvoker.invokeOnTargetAfterFilter(ResourceMethodInvoker.java:524)
at org.jboss.resteasy.core.ResourceMethodInvoker.lambda$invokeOnTarget$2(ResourceMethodInvoker.java:474)
at org.jboss.resteasy.core.interception.jaxrs.PreMatchContainerRequestContext.filter(PreMatchContainerRequestContext.java:364)
at org.jboss.resteasy.core.ResourceMethodInvoker.invokeOnTarget(ResourceMethodInvoker.java:476)
at org.jboss.resteasy.core.ResourceMethodInvoker.invoke(ResourceMethodInvoker.java:434)
at org.jboss.resteasy.core.ResourceLocatorInvoker.invokeOnTargetObject(ResourceLocatorInvoker.java:192)
at org.jboss.resteasy.core.ResourceLocatorInvoker.invoke(ResourceLocatorInvoker.java:141)
at org.jboss.resteasy.core.ResourceLocatorInvoker.invoke(ResourceLocatorInvoker.java:32)
at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:492)
at org.jboss.resteasy.core.SynchronousDispatcher.lambda$invoke$4(SynchronousDispatcher.java:261)
at org.jboss.resteasy.core.SynchronousDispatcher.lambda$preprocess$0(SynchronousDispatcher.java:161)
at org.jboss.resteasy.core.interception.jaxrs.PreMatchContainerRequestContext.filter(PreMatchContainerRequestContext.java:364)
at org.jboss.resteasy.core.SynchronousDispatcher.preprocess(SynchronousDispatcher.java:164)
at org.jboss.resteasy.core.SynchronousDispatcher.invoke(SynchronousDispatcher.java:247)
at io.quarkus.resteasy.runtime.standalone.RequestDispatcher.service(RequestDispatcher.java:73)
at io.quarkus.resteasy.runtime.standalone.VertxRequestHandler.dispatch(VertxRequestHandler.java:151)
at io.quarkus.resteasy.runtime.standalone.VertxRequestHandler.handle(VertxRequestHandler.java:82)
at io.quarkus.resteasy.runtime.standalone.VertxRequestHandler.handle(VertxRequestHandler.java:42)
at io.vertx.ext.web.impl.RouteState.handleContext(RouteState.java:1212)
at io.vertx.ext.web.impl.RoutingContextImplBase.iterateNext(RoutingContextImplBase.java:163)
at io.vertx.ext.web.impl.RoutingContextImpl.next(RoutingContextImpl.java:141)
at io.quarkus.vertx.http.runtime.StaticResourcesRecorder$2.handle(StaticResourcesRecorder.java:67)
at io.quarkus.vertx.http.runtime.StaticResourcesRecorder$2.handle(StaticResourcesRecorder.java:55)
at io.vertx.ext.web.impl.RouteState.handleContext(RouteState.java:1212)
at io.vertx.ext.web.impl.RoutingContextImplBase.iterateNext(RoutingContextImplBase.java:163)
at io.vertx.ext.web.impl.RoutingContextImpl.next(RoutingContextImpl.java:141)
at io.quarkus.vertx.http.runtime.VertxHttpRecorder$5.handle(VertxHttpRecorder.java:362)
at io.quarkus.vertx.http.runtime.VertxHttpRecorder$5.handle(VertxHttpRecorder.java:340)
at io.vertx.ext.web.impl.RouteState.handleContext(RouteState.java:1212)
at io.vertx.ext.web.impl.RoutingContextImplBase.iterateNext(RoutingContextImplBase.java:163)
at io.vertx.ext.web.impl.RoutingContextImpl.next(RoutingContextImpl.java:141)
at org.keycloak.quarkus.runtime.integration.web.QuarkusRequestFilter.lambda$createBlockingHandler$1(QuarkusRequestFilter.java:66)
at io.vertx.core.impl.ContextImpl.lambda$null$0(ContextImpl.java:159)
at io.vertx.core.impl.AbstractContext.dispatch(AbstractContext.java:100)
How to Reproduce?
The key to reproduce is:
- Have Attestation Conveyance Preference set to Direct
- Have accepted AAGUID set up
Anything else?
In case of needing more information please let me know, I’ll try to provide as much as I can. We also tried other approaches:
- Adding truststore
- Adding keystore
One main area of concern is that, if keycloak is supposed to verify the attestation of the authenticator, it needs the root ca of the provider of the authenticator. Couldn’t find documentation as how that is supposed to be done.
Issue Analytics
- State:
- Created 2 years ago
- Reactions:2
- Comments:7 (6 by maintainers)
Top GitHub Comments
I haven’t experienced this issue in WebAuthn4j. It seems Keycloak Quarkus distribution lacks a dependency to kerby-asn1.
kerby-asn1-2.0.1.jar
should exist in<KEYCLOAK_HOME>/lib/lib/main
, but it’s missing. In Keycloak legacy distribution, it exists in<KEYCLOAK_HOME>/modules/system/layers/keycloak/org/apache/kerby/kerby-asn1/main
I just got the same error on docker hosted Keycloak 17.0.1 with yubikey 5.