com.webauthn4j.data.RegistrationData Java Examples

The following examples show how to use com.webauthn4j.data.RegistrationData. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: WebAuthnRegister.java    From keycloak with Apache License 2.0 6 votes vote down vote up
private void checkAcceptedAuthenticator(RegistrationData response, WebAuthnPolicy policy) throws Exception {
    String aaguid = response.getAttestationObject().getAuthenticatorData().getAttestedCredentialData().getAaguid().toString();
    List<String> acceptableAaguids = policy.getAcceptableAaguids();
    boolean isAcceptedAuthenticator = false;
    if (acceptableAaguids != null && !acceptableAaguids.isEmpty()) {
        for(String acceptableAaguid : acceptableAaguids) {
            if (aaguid.equals(acceptableAaguid)) {
                isAcceptedAuthenticator = true;
                break;
            }
        }
    } else {
        // no accepted authenticators means accepting any kind of authenticator
        isAcceptedAuthenticator = true;
    }
    if (!isAcceptedAuthenticator) {
        throw new WebAuthnException("not acceptable aaguid = " + aaguid);
    }
}
 
Example #2
Source File: BeanAssertUtil.java    From webauthn4j with Apache License 2.0 6 votes vote down vote up
public static void validate(RegistrationData registrationData) {
    if (registrationData == null) {
        throw new ConstraintViolationException("registrationData must not be null");
    }

    validate(registrationData.getAttestationObject());

    if (registrationData.getAttestationObjectBytes() == null) {
        throw new ConstraintViolationException("attestationObjectBytes must not be null");
    }
    validateAuthenticationExtensionsClientOutputs(registrationData.getClientExtensions());

    validate(registrationData.getCollectedClientData());

    if (registrationData.getCollectedClientDataBytes() == null) {
        throw new ConstraintViolationException("collectedClientDataBytes must not be null");
    }
}
 
Example #3
Source File: WebAuthnRegistrationManager.java    From webauthn4j with Apache License 2.0 6 votes vote down vote up
@SuppressWarnings("squid:S1130")
public RegistrationData parse(RegistrationRequest registrationRequest) throws DataConversionException {

    byte[] clientDataBytes = registrationRequest.getClientDataJSON();
    byte[] attestationObjectBytes = registrationRequest.getAttestationObject();

    CollectedClientData collectedClientData = collectedClientDataConverter.convert(clientDataBytes);
    AttestationObject attestationObject = attestationObjectConverter.convert(attestationObjectBytes);
    Set<AuthenticatorTransport> transports = authenticatorTransportConverter.convertSet(registrationRequest.getTransports());
    AuthenticationExtensionsClientOutputs<RegistrationExtensionClientOutput<?>> clientExtensions =
            authenticationExtensionsClientOutputsConverter.convert(registrationRequest.getClientExtensionsJSON());

    return new RegistrationData(
            attestationObject,
            attestationObjectBytes,
            collectedClientData,
            clientDataBytes,
            clientExtensions,
            transports
    );

}
 
Example #4
Source File: WebAuthnRegistrationRequestValidatorTest.java    From webauthn4j-spring-security with Apache License 2.0 5 votes vote down vote up
@Test
public void validate_test() {
    WebAuthnRegistrationRequestValidator target = new WebAuthnRegistrationRequestValidator(
            webAuthnManager, serverPropertyProvider
    );

    ServerProperty serverProperty = mock(ServerProperty.class);
    when(serverPropertyProvider.provide(any())).thenReturn(serverProperty);

    CollectedClientData collectedClientData = mock(CollectedClientData.class);
    AttestationObject attestationObject = mock(AttestationObject.class);
    AuthenticationExtensionsClientOutputs<RegistrationExtensionClientOutput<?>> clientExtensionOutputs = new AuthenticationExtensionsClientOutputs<>();
    when(webAuthnManager.validate(any(RegistrationRequest.class), any(RegistrationParameters.class))).thenReturn(
            new RegistrationData(attestationObject, null, collectedClientData, null, clientExtensionOutputs, null));

    MockHttpServletRequest mockHttpServletRequest = new MockHttpServletRequest();
    mockHttpServletRequest.setScheme("https");
    mockHttpServletRequest.setServerName("example.com");
    mockHttpServletRequest.setServerPort(443);
    String clientDataBase64 = "clientDataBase64";
    String attestationObjectBase64 = "attestationObjectBase64";
    Set<String> transports = Collections.emptySet();
    String clientExtensionsJSON = "clientExtensionsJSON";

    target.validate(mockHttpServletRequest, clientDataBase64, attestationObjectBase64, transports, clientExtensionsJSON);

    ArgumentCaptor<RegistrationRequest> registrationRequestArgumentCaptor = ArgumentCaptor.forClass(RegistrationRequest.class);
    ArgumentCaptor<RegistrationParameters> registrationParametersArgumentCaptor = ArgumentCaptor.forClass(RegistrationParameters.class);
    verify(webAuthnManager).validate(registrationRequestArgumentCaptor.capture(), registrationParametersArgumentCaptor.capture());
    RegistrationRequest registrationRequest = registrationRequestArgumentCaptor.getValue();
    RegistrationParameters registrationParameters = registrationParametersArgumentCaptor.getValue();

    assertThat(registrationRequest.getClientDataJSON()).isEqualTo(Base64UrlUtil.decode(clientDataBase64));
    assertThat(registrationRequest.getAttestationObject()).isEqualTo(Base64UrlUtil.decode(attestationObjectBase64));
    assertThat(registrationRequest.getClientExtensionsJSON()).isEqualTo(clientExtensionsJSON);
    assertThat(registrationParameters.getServerProperty()).isEqualTo(serverProperty);
    assertThat(registrationParameters.getExpectedExtensionIds()).isEqualTo(target.getExpectedRegistrationExtensionIds());
}
 
Example #5
Source File: WebAuthnRegister.java    From keycloak with Apache License 2.0 5 votes vote down vote up
private void showInfoAfterWebAuthnApiCreate(RegistrationData response) {
    AttestedCredentialData attestedCredentialData = response.getAttestationObject().getAuthenticatorData().getAttestedCredentialData();
    AttestationStatement attestationStatement = response.getAttestationObject().getAttestationStatement();
    logger.debugv("createad key's algorithm = {0}", String.valueOf(attestedCredentialData.getCOSEKey().getAlgorithm().getValue()));
    logger.debugv("aaguid = {0}", attestedCredentialData.getAaguid().toString());
    logger.debugv("attestation format = {0}", attestationStatement.getFormat());
}
 
Example #6
Source File: BeanAssertUtilTest.java    From webauthn4j with Apache License 2.0 5 votes vote down vote up
@Test
void validate_RegistrationData_with_transports_null_test() {
    RegistrationData registrationData = new RegistrationData(
            TestDataUtil.createAttestationObjectWithFIDOU2FAttestationStatement(),
            new byte[32],
            TestDataUtil.createClientData(ClientDataType.CREATE),
            new byte[32],
            new AuthenticationExtensionsClientOutputs<>(),
            null
    );
    assertDoesNotThrow(
            () -> BeanAssertUtil.validate(registrationData)
    );
}
 
Example #7
Source File: BeanAssertUtilTest.java    From webauthn4j with Apache License 2.0 5 votes vote down vote up
@Test
void validate_RegistrationData_with_clientExtensions_null_test() {
    RegistrationData registrationData = new RegistrationData(
            TestDataUtil.createAttestationObjectWithFIDOU2FAttestationStatement(),
            new byte[32],
            TestDataUtil.createClientData(ClientDataType.CREATE),
            new byte[32],
            null,
            new HashSet<>()
    );
    assertDoesNotThrow(
            () -> BeanAssertUtil.validate(registrationData)
    );
}
 
Example #8
Source File: BeanAssertUtilTest.java    From webauthn4j with Apache License 2.0 5 votes vote down vote up
@Test
void validate_RegistrationData_with_clientDataBytes_null_test() {
    RegistrationData registrationData = new RegistrationData(
            TestDataUtil.createAttestationObjectWithFIDOU2FAttestationStatement(),
            new byte[32],
            TestDataUtil.createClientData(ClientDataType.CREATE),
            null,
            new AuthenticationExtensionsClientOutputs<>(),
            new HashSet<>()
    );
    assertThrows(ConstraintViolationException.class,
            () -> BeanAssertUtil.validate(registrationData)
    );
}
 
Example #9
Source File: BeanAssertUtilTest.java    From webauthn4j with Apache License 2.0 5 votes vote down vote up
@Test
void validate_RegistrationData_with_collectedClientData_null_test() {
    RegistrationData registrationData = new RegistrationData(
            TestDataUtil.createAttestationObjectWithFIDOU2FAttestationStatement(),
            new byte[32],
            null,
            new byte[32],
            new AuthenticationExtensionsClientOutputs<>(),
            new HashSet<>()
    );
    assertThrows(ConstraintViolationException.class,
            () -> BeanAssertUtil.validate(registrationData)
    );
}
 
Example #10
Source File: BeanAssertUtilTest.java    From webauthn4j with Apache License 2.0 5 votes vote down vote up
@Test
void validate_RegistrationData_with_attestationObjectBytes_null_test() {
    RegistrationData registrationData = new RegistrationData(
            TestDataUtil.createAttestationObjectWithFIDOU2FAttestationStatement(),
            null,
            TestDataUtil.createClientData(ClientDataType.CREATE),
            new byte[32],
            new AuthenticationExtensionsClientOutputs<>(),
            new HashSet<>()
    );
    assertThrows(ConstraintViolationException.class,
            () -> BeanAssertUtil.validate(registrationData)
    );
}
 
Example #11
Source File: BeanAssertUtilTest.java    From webauthn4j with Apache License 2.0 5 votes vote down vote up
@Test
void validate_RegistrationData_with_attestationObject_null_test() {
    RegistrationData registrationData = new RegistrationData(
            null,
            new byte[32],
            TestDataUtil.createClientData(ClientDataType.CREATE),
            new byte[32],
            new AuthenticationExtensionsClientOutputs<>(),
            new HashSet<>()
    );
    assertThrows(ConstraintViolationException.class,
            () -> BeanAssertUtil.validate(registrationData)
    );
}
 
Example #12
Source File: BeanAssertUtilTest.java    From webauthn4j with Apache License 2.0 5 votes vote down vote up
@Test
void validate_RegistrationData_test() {
    RegistrationData registrationData = new RegistrationData(
            TestDataUtil.createAttestationObjectWithFIDOU2FAttestationStatement(),
            new byte[32],
            TestDataUtil.createClientData(ClientDataType.CREATE),
            new byte[32],
            new AuthenticationExtensionsClientOutputs<>(),
            new HashSet<>()
    );
    BeanAssertUtil.validate(registrationData);
}
 
Example #13
Source File: AuthenticatorImpl.java    From webauthn4j with Apache License 2.0 5 votes vote down vote up
public static AuthenticatorImpl createFromRegistrationData(RegistrationData registrationData){
    return new AuthenticatorImpl(
            registrationData.getAttestationObject().getAuthenticatorData().getAttestedCredentialData(),
            registrationData.getAttestationObject().getAttestationStatement(),
            registrationData.getAttestationObject().getAuthenticatorData().getSignCount(),
            registrationData.getTransports());
}
 
Example #14
Source File: WebAuthnRegistrationRequestValidatorTest.java    From webauthn4j-spring-security with Apache License 2.0 5 votes vote down vote up
@Test
public void validate_with_transports_null_test() {
    WebAuthnRegistrationRequestValidator target = new WebAuthnRegistrationRequestValidator(
            webAuthnManager, serverPropertyProvider
    );

    ServerProperty serverProperty = mock(ServerProperty.class);
    when(serverPropertyProvider.provide(any())).thenReturn(serverProperty);

    CollectedClientData collectedClientData = mock(CollectedClientData.class);
    AttestationObject attestationObject = mock(AttestationObject.class);
    AuthenticationExtensionsClientOutputs<RegistrationExtensionClientOutput<?>> clientExtensionOutputs = new AuthenticationExtensionsClientOutputs<>();
    when(webAuthnManager.validate(any(RegistrationRequest.class), any(RegistrationParameters.class))).thenReturn(
            new RegistrationData(attestationObject, null, collectedClientData, null, clientExtensionOutputs, null));

    MockHttpServletRequest mockHttpServletRequest = new MockHttpServletRequest();
    mockHttpServletRequest.setScheme("https");
    mockHttpServletRequest.setServerName("example.com");
    mockHttpServletRequest.setServerPort(443);
    String clientDataBase64 = "clientDataBase64";
    String attestationObjectBase64 = "attestationObjectBase64";
    String clientExtensionsJSON = "clientExtensionsJSON";

    target.validate(mockHttpServletRequest, clientDataBase64, attestationObjectBase64, null, clientExtensionsJSON);

    ArgumentCaptor<RegistrationRequest> registrationRequestArgumentCaptor = ArgumentCaptor.forClass(RegistrationRequest.class);
    ArgumentCaptor<RegistrationParameters> registrationParametersArgumentCaptor = ArgumentCaptor.forClass(RegistrationParameters.class);
    verify(webAuthnManager).validate(registrationRequestArgumentCaptor.capture(), registrationParametersArgumentCaptor.capture());
    RegistrationRequest registrationRequest = registrationRequestArgumentCaptor.getValue();
    RegistrationParameters registrationParameters = registrationParametersArgumentCaptor.getValue();

    assertThat(registrationRequest.getClientDataJSON()).isEqualTo(Base64UrlUtil.decode(clientDataBase64));
    assertThat(registrationRequest.getAttestationObject()).isEqualTo(Base64UrlUtil.decode(attestationObjectBase64));
    assertThat(registrationRequest.getClientExtensionsJSON()).isEqualTo(clientExtensionsJSON);
    assertThat(registrationParameters.getServerProperty()).isEqualTo(serverProperty);
    assertThat(registrationParameters.getExpectedExtensionIds()).isEqualTo(target.getExpectedRegistrationExtensionIds());
}
 
Example #15
Source File: WebAuthnRegistrationRequestValidator.java    From webauthn4j-spring-security with Apache License 2.0 5 votes vote down vote up
public WebAuthnRegistrationRequestValidationResponse validate(HttpServletRequest httpServletRequest,
                                                              String clientDataBase64url,
                                                              String attestationObjectBase64url,
                                                              Set<String> transports,
                                                              String clientExtensionsJSON
) {
    Assert.notNull(httpServletRequest, "httpServletRequest must not be null");
    Assert.hasText(clientDataBase64url, "clientDataBase64url must have text");
    Assert.hasText(attestationObjectBase64url, "attestationObjectBase64url must have text");
    if (transports != null) {
        transports.forEach(transport -> Assert.hasText(transport, "each transport must have text"));
    }

    RegistrationRequest webAuthnRegistrationRequest =
            createRegistrationRequest(clientDataBase64url, attestationObjectBase64url, transports, clientExtensionsJSON);
    RegistrationParameters webAuthnRegistrationParameters =
            createRegistrationParameters(httpServletRequest);

    try {
        RegistrationData response = webAuthnManager.validate(webAuthnRegistrationRequest, webAuthnRegistrationParameters);
        return new WebAuthnRegistrationRequestValidationResponse(
                response.getCollectedClientData(),
                response.getAttestationObject(),
                response.getClientExtensions());
    } catch (WebAuthnException e) {
        throw ExceptionUtil.wrapWithAuthenticationException(e);
    }
}
 
Example #16
Source File: BeanAssertUtilTest.java    From webauthn4j with Apache License 2.0 4 votes vote down vote up
@Test
void validate_RegistrationData_with_null_test() {
    assertThrows(ConstraintViolationException.class,
            () -> BeanAssertUtil.validate((RegistrationData) null)
    );
}
 
Example #17
Source File: WebAuthnRegistrationManager.java    From webauthn4j with Apache License 2.0 4 votes vote down vote up
@SuppressWarnings("squid:S1130")
public RegistrationData validate(RegistrationData registrationData, RegistrationParameters registrationParameters) throws ValidationException {
    registrationDataValidator.validate(registrationData, registrationParameters);
    return registrationData;
}
 
Example #18
Source File: WebAuthnRegistrationManager.java    From webauthn4j with Apache License 2.0 4 votes vote down vote up
@SuppressWarnings("squid:S1130")
public RegistrationData validate(RegistrationRequest registrationRequest, RegistrationParameters registrationParameters) throws DataConversionException, ValidationException {
    RegistrationData registrationData = parse(registrationRequest);
    registrationDataValidator.validate(registrationData, registrationParameters);
    return registrationData;
}
 
Example #19
Source File: RegistrationDataValidator.java    From webauthn4j with Apache License 2.0 4 votes vote down vote up
public void validate(RegistrationData registrationData, RegistrationParameters registrationParameters) {

        BeanAssertUtil.validate(registrationData);
        BeanAssertUtil.validate(registrationParameters);

        byte[] clientDataBytes = registrationData.getCollectedClientDataBytes();
        byte[] attestationObjectBytes = registrationData.getAttestationObjectBytes();

        CollectedClientData collectedClientData = registrationData.getCollectedClientData();
        AttestationObject attestationObject = registrationData.getAttestationObject();
        Set<AuthenticatorTransport> transports = registrationData.getTransports();
        AuthenticationExtensionsClientOutputs<RegistrationExtensionClientOutput<?>> clientExtensions = registrationData.getClientExtensions();

        validateAuthenticatorDataField(attestationObject.getAuthenticatorData());

        ServerProperty serverProperty = registrationParameters.getServerProperty();

        RegistrationObject registrationObject = new RegistrationObject(
                attestationObject,
                attestationObjectBytes,
                collectedClientData,
                clientDataBytes,
                clientExtensions,
                transports,
                serverProperty
        );

        AuthenticatorData<RegistrationExtensionAuthenticatorOutput<?>> authenticatorData = attestationObject.getAuthenticatorData();

        //spec| Step3
        //spec| Verify that the value of C.type is webauthn.create.
        if (!Objects.equals(collectedClientData.getType(), ClientDataType.CREATE)) {
            throw new InconsistentClientDataTypeException("ClientData.type must be 'create' on registration, but it isn't.");
        }

        //spec| Step4
        //spec| Verify that the value of C.challenge matches the challenge that was sent to the authenticator in the create() call.
        challengeValidator.validate(collectedClientData, serverProperty);

        //spec| Step5
        //spec| Verify that the value of C.origin matches the Relying Party's origin.
        originValidator.validate(collectedClientData, serverProperty);

        //spec| Step6
        //spec| Verify that the value of C.tokenBinding.status matches the state of Token Binding for the TLS connection over
        //spec| which the assertion was obtained. If Token Binding was used on that TLS connection, also verify that
        //spec| C.tokenBinding.id matches the base64url encoding of the Token Binding ID for the connection.
        tokenBindingValidator.validate(collectedClientData.getTokenBinding(), serverProperty.getTokenBindingId());

        //spec| Step7
        //spec| Compute the hash of response.clientDataJSON using SHA-256.

        //spec| Step8
        //spec| Perform CBOR decoding on the attestationObject field of the AuthenticatorAttestationResponse structure to
        //spec| obtain the attestation statement format fmt, the authenticator data authData, and the attestation statement attStmt.

        //spec| Step9
        //spec| Verify that the RP ID hash in authData is indeed the SHA-256 hash of the RP ID expected by the RP.
        rpIdHashValidator.validate(authenticatorData.getRpIdHash(), serverProperty);


        //spec| Step10, 11
        validateUVUPFlags(authenticatorData, registrationParameters.isUserVerificationRequired(), registrationParameters.isUserPresenceRequired());

        //spec| Step12
        //spec| Verify that the values of the client extension outputs in clientExtensionResults and the authenticator
        //spec| extension outputs in the extensions in authData are as expected, considering the client extension input
        //spec| values that were given as the extensions option in the create() call. In particular, any extension identifier
        //spec| values in the clientExtensionResults and the extensions in authData MUST be also be present as extension
        //spec| identifier values in the extensions member of options, i.e., no extensions are present that were not requested.
        //spec| In the general case, the meaning of "are as expected" is specific to the Relying Party and which extensions are in use.
        AuthenticationExtensionsAuthenticatorOutputs<RegistrationExtensionAuthenticatorOutput<?>> authenticationExtensionsAuthenticatorOutputs = authenticatorData.getExtensions();
        List<String> expectedExtensionIdentifiers = registrationParameters.getExpectedExtensionIds();
        extensionValidator.validate(clientExtensions, authenticationExtensionsAuthenticatorOutputs, expectedExtensionIdentifiers);

        //spec| Step13-16,19
        attestationValidator.validate(registrationObject);

        //spec| Step17
        //spec| Check that the credentialId is not yet registered to any other user. If registration is requested for
        //spec| a credential that is already registered to a different user, the Relying Party SHOULD fail this registration
        //spec| ceremony, or it MAY decide to accept the registration, e.g. while deleting the older registration.

        //      (This step is out of WebAuthn4J scope. It's caller's responsibility.)

        //spec| Step18
        //spec| If the attestation statement attStmt verified successfully and is found to be trustworthy,
        //spec| then register the new credential with the account that was denoted in the options.user passed to create(),
        //spec| by associating it with the credential ID and credential public key contained in authData’s attestation data,
        //spec| as appropriate for the Relying Party's systems.

        //      (This step is out of WebAuthn4J scope. It's caller's responsibility.)

        // validate with custom logic
        for (CustomRegistrationValidator customRegistrationValidator : customRegistrationValidators) {
            customRegistrationValidator.validate(registrationObject);
        }
    }
 
Example #20
Source File: WebAuthnRegister.java    From keycloak with Apache License 2.0 4 votes vote down vote up
@Override
public void processAction(RequiredActionContext context) {

    MultivaluedMap<String, String> params = context.getHttpRequest().getDecodedFormParameters();

    String isSetRetry = params.getFirst(WebAuthnConstants.IS_SET_RETRY);
    if (isSetRetry != null && !isSetRetry.isEmpty()) {
        requiredActionChallenge(context);
        return;
    }

    context.getEvent().detail(Details.CREDENTIAL_TYPE, getCredentialType());

    // receive error from navigator.credentials.create()
    String errorMsgFromWebAuthnApi = params.getFirst(WebAuthnConstants.ERROR);
    if (errorMsgFromWebAuthnApi != null && !errorMsgFromWebAuthnApi.isEmpty()) {
        setErrorResponse(context, WEBAUTHN_ERROR_REGISTER_VERIFICATION, errorMsgFromWebAuthnApi);
        return;
    }

    WebAuthnPolicy policy = getWebAuthnPolicy(context);
    String rpId = policy.getRpId();
    if (rpId == null || rpId.isEmpty()) rpId =  context.getUriInfo().getBaseUri().getHost();
    String label = params.getFirst(WebAuthnConstants.AUTHENTICATOR_LABEL);
    byte[] clientDataJSON = Base64.getUrlDecoder().decode(params.getFirst(WebAuthnConstants.CLIENT_DATA_JSON));
    byte[] attestationObject = Base64.getUrlDecoder().decode(params.getFirst(WebAuthnConstants.ATTESTATION_OBJECT));

    String publicKeyCredentialId = params.getFirst(WebAuthnConstants.PUBLIC_KEY_CREDENTIAL_ID);

    Origin origin = new Origin(UriUtils.getOrigin(context.getUriInfo().getBaseUri()));
    Challenge challenge = new DefaultChallenge(context.getAuthenticationSession().getAuthNote(WebAuthnConstants.AUTH_CHALLENGE_NOTE));
    ServerProperty serverProperty = new ServerProperty(origin, rpId, challenge, null);
    // check User Verification by considering a malicious user might modify the result of calling WebAuthn API
    boolean isUserVerificationRequired = policy.getUserVerificationRequirement().equals(WebAuthnConstants.OPTION_REQUIRED);

    RegistrationRequest registrationRequest = new RegistrationRequest(attestationObject, clientDataJSON);
    RegistrationParameters registrationParameters = new RegistrationParameters(serverProperty, isUserVerificationRequired);

    WebAuthnRegistrationManager webAuthnRegistrationManager = createWebAuthnRegistrationManager();
    try {
        // parse
        RegistrationData registrationData = webAuthnRegistrationManager.parse(registrationRequest);
        // validate
        webAuthnRegistrationManager.validate(registrationData, registrationParameters);

        showInfoAfterWebAuthnApiCreate(registrationData);

        checkAcceptedAuthenticator(registrationData, policy);

        WebAuthnCredentialModelInput credential = new WebAuthnCredentialModelInput(getCredentialType());

        credential.setAttestedCredentialData(registrationData.getAttestationObject().getAuthenticatorData().getAttestedCredentialData());
        credential.setCount(registrationData.getAttestationObject().getAuthenticatorData().getSignCount());
        credential.setAttestationStatementFormat(registrationData.getAttestationObject().getFormat());

        // Save new webAuthn credential
        WebAuthnCredentialProvider webAuthnCredProvider = (WebAuthnCredentialProvider) this.session.getProvider(CredentialProvider.class, getCredentialProviderId());
        WebAuthnCredentialModel newCredentialModel = webAuthnCredProvider.getCredentialModelFromCredentialInput(credential, label);

        webAuthnCredProvider.createCredential(context.getRealm(), context.getUser(), newCredentialModel);

        String aaguid = newCredentialModel.getWebAuthnCredentialData().getAaguid();
        logger.debugv("WebAuthn credential registration success for user {0}. credentialType = {1}, publicKeyCredentialId = {2}, publicKeyCredentialLabel = {3}, publicKeyCredentialAAGUID = {4}",
                context.getUser().getUsername(), getCredentialType(), publicKeyCredentialId, label, aaguid);
        webAuthnCredProvider.dumpCredentialModel(newCredentialModel, credential);

        context.getEvent()
            .detail(WebAuthnConstants.PUBKEY_CRED_ID_ATTR, publicKeyCredentialId)
            .detail(WebAuthnConstants.PUBKEY_CRED_LABEL_ATTR, label)
            .detail(WebAuthnConstants.PUBKEY_CRED_AAGUID_ATTR, aaguid);
        context.success();
    } catch (WebAuthnException wae) {
        if (logger.isDebugEnabled()) logger.debug(wae.getMessage(), wae);
        setErrorResponse(context, WEBAUTHN_ERROR_REGISTRATION, wae.getMessage());
        return;
    } catch (Exception e) {
        if (logger.isDebugEnabled()) logger.debug(e.getMessage(), e);
        setErrorResponse(context, WEBAUTHN_ERROR_REGISTRATION, e.getMessage());
        return;
    }
}