question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Attestation Conveyance Verification with YubiKey

See original GitHub issue

Describe 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.

  1. Enable WebAuthn Verification following the steps defined in https://github.com/keycloak/keycloak-documentation/blob/main/server_admin/topics/authentication/webauthn.adoc
  2. Under Authentication > WebAuthn Policy > Attestation Conveyance Preference set it to Direct
  3. 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:

  1. User goes to login page
  2. User is presented with username and password (first login)
  3. User is required to register USB key to keycloak as specified in the General Steps
  4. User registers key successfully and keycloak saves the key information on the database
  5. 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:

  1. Have Attestation Conveyance Preference set to Direct
  2. 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:

  1. Adding truststore
  2. 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:closed
  • Created 2 years ago
  • Reactions:2
  • Comments:7 (6 by maintainers)

github_iconTop GitHub Comments

3reactions
ynojimacommented, Mar 21, 2022

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

1reaction
Mistic92commented, Mar 31, 2022

I just got the same error on docker hosted Keycloak 17.0.1 with yubikey 5.

Default
2022-03-31 16:36:10.528 CEST2022-03-31 14:36:10,526 ERROR [org.keycloak.services.error.KeycloakErrorHandler] (executor-thread-65) Uncaught server error: java.lang.NoClassDefFoundError: org/apache/kerby/asn1/type/Asn1OctetString
Default
2022-03-31 16:36:10.528 CEST at com.webauthn4j.validator.attestation.statement.packed.PackedAttestationStatementValidator.extractAAGUIDFromAttestationCertificate(PackedAttestationStatementValidator.java:106)
Default
2022-03-31 16:36:10.528 CEST at com.webauthn4j.validator.attestation.statement.packed.PackedAttestationStatementValidator.validateX5c(PackedAttestationStatementValidator.java:90)
Read more comments on GitHub >

github_iconTop Results From Across the Web

Attestation - Yubico Developers
Attestation is built-in to the FIDO and WebAuthn protocols, which enables each relying party to use a cryptographically verified chain of trust from...
Read more >
Cannot enforce Webauthn attestation verification with truststore
Set config of "Attestation Conveyance Preference" to none. ... authenticator such as yubikey); Deny permission to read my security key info.
Read more >
FIDO2 Deep Dive: Attestations, Trust model and Security
The attestation statement also usually contains a certificate chain that the RP can use to verify the signature up to a common root...
Read more >
Web Authentication: An API for accessing Public Key ... - W3C
An attestation statement is conveyed in an attestation object during registration. See also § 6.5 Attestation and Figure 6.
Read more >
What's New in Passwordless Standards, 2021 edition!
Enterprise Attestation is a new feature coming as part of WebAuthn L2 and CTAP 2.1 that enables binding of an authenticator to an...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found