com.webauthn4j.util.exception.WebAuthnException Java Examples

The following examples show how to use com.webauthn4j.util.exception.WebAuthnException. 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: 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 #3
Source File: WebAuthnAuthenticationProvider.java    From webauthn4j-spring-security with Apache License 2.0 5 votes vote down vote up
void doAuthenticate(WebAuthnAssertionAuthenticationToken authenticationToken, Authenticator authenticator, WebAuthnUserDetails user) {

        WebAuthnAuthenticationRequest credentials = authenticationToken.getCredentials();

        boolean userVerificationRequired = isUserVerificationRequired(user, credentials);

        AuthenticationRequest authenticationRequest = new AuthenticationRequest(
                credentials.getCredentialId(),
                credentials.getAuthenticatorData(),
                credentials.getClientDataJSON(),
                credentials.getClientExtensionsJSON(),
                credentials.getSignature()
        );
        AuthenticationParameters authenticationParameters = new AuthenticationParameters(
                credentials.getServerProperty(),
                authenticator,
                userVerificationRequired,
                credentials.isUserPresenceRequired(),
                credentials.getExpectedAuthenticationExtensionIds()
        );

        try {
            webAuthnManager.validate(authenticationRequest, authenticationParameters);
        } catch (WebAuthnException e) {
            throw ExceptionUtil.wrapWithAuthenticationException(e);
        }

    }
 
Example #4
Source File: ExceptionUtilTest.java    From webauthn4j-spring-security with Apache License 2.0 5 votes vote down vote up
@Test
public void wrapWithAuthenticationException_test() {

    Map<WebAuthnException, Class<?>> map = new HashMap<>();
    map.put(new com.webauthn4j.validator.exception.BadAaguidException("dummy"), BadAaguidException.class);
    map.put(new com.webauthn4j.validator.exception.BadAlgorithmException("dummy"), BadAlgorithmException.class);
    map.put(new com.webauthn4j.validator.exception.BadAttestationStatementException("dummy"), BadAttestationStatementException.class);
    map.put(new com.webauthn4j.validator.exception.KeyDescriptionValidationException("dummy"), KeyDescriptionValidationException.class);
    map.put(new com.webauthn4j.validator.exception.BadChallengeException("dummy"), BadChallengeException.class);
    map.put(new com.webauthn4j.validator.exception.BadOriginException("dummy"), BadOriginException.class);
    map.put(new com.webauthn4j.validator.exception.BadRpIdException("dummy"), BadRpIdException.class);
    map.put(new com.webauthn4j.validator.exception.BadSignatureException("dummy"), BadSignatureException.class);
    map.put(new com.webauthn4j.metadata.exception.BadStatusException("dummy"), BadStatusException.class);
    map.put(new com.webauthn4j.validator.exception.CertificateException("dummy"), CertificateException.class);
    map.put(new com.webauthn4j.validator.exception.ConstraintViolationException("dummy"), ConstraintViolationException.class);
    map.put(new com.webauthn4j.validator.exception.MaliciousCounterValueException("dummy"), MaliciousCounterValueException.class);
    map.put(new com.webauthn4j.validator.exception.InconsistentClientDataTypeException("dummy"), InconsistentClientDataTypeException.class);
    map.put(new com.webauthn4j.validator.exception.MissingChallengeException("dummy"), MissingChallengeException.class);
    map.put(new com.webauthn4j.validator.exception.PublicKeyMismatchException("dummy"), PublicKeyMismatchException.class);
    map.put(new com.webauthn4j.validator.exception.SelfAttestationProhibitedException("dummy"), SelfAttestationProhibitedException.class);
    map.put(new com.webauthn4j.validator.exception.TokenBindingException("dummy"), TokenBindingException.class);
    map.put(new com.webauthn4j.validator.exception.TrustAnchorNotFoundException("dummy"), TrustAnchorNotFoundException.class);
    map.put(new com.webauthn4j.validator.exception.UnexpectedExtensionException("dummy"), UnexpectedExtensionException.class);
    map.put(new com.webauthn4j.validator.exception.UserNotPresentException("dummy"), UserNotPresentException.class);
    map.put(new com.webauthn4j.validator.exception.UserNotVerifiedException("dummy"), UserNotVerifiedException.class);
    map.put(new ExceptionUtilTest.UnknownValidationException("dummy"), ValidationException.class);
    map.put(new com.webauthn4j.converter.exception.DataConversionException("dummy"), DataConversionException.class);
    map.put(new com.webauthn4j.util.exception.WebAuthnException("dummy"), AuthenticationServiceException.class);

    for (Map.Entry<WebAuthnException, Class<?>> entry : map.entrySet()) {
        assertThat(ExceptionUtil.wrapWithAuthenticationException(entry.getKey())).isInstanceOf(entry.getValue());
    }
}
 
Example #5
Source File: ExceptionUtil.java    From webauthn4j-spring-security with Apache License 2.0 4 votes vote down vote up
/**
 * Wraps WebAuthnAuthentication to proper {@link RuntimeException} (mainly {@link AuthenticationException} subclass.
 *
 * @param e exception to be wrapped
 * @return wrapping exception
 */
@SuppressWarnings("squid:S3776")
public static RuntimeException wrapWithAuthenticationException(WebAuthnException e) {
    // ValidationExceptions
    if (e instanceof com.webauthn4j.validator.exception.BadAaguidException) {
        return new BadAaguidException(e.getMessage(), e);
    } else if (e instanceof com.webauthn4j.validator.exception.BadAlgorithmException) {
        return new BadAlgorithmException(e.getMessage(), e);
    } else if (e instanceof com.webauthn4j.validator.exception.BadAttestationStatementException) {
        if (e instanceof com.webauthn4j.validator.exception.KeyDescriptionValidationException) {
            return new KeyDescriptionValidationException(e.getMessage(), e);
        } else {
            return new BadAttestationStatementException(e.getMessage(), e);
        }
    } else if (e instanceof com.webauthn4j.validator.exception.BadChallengeException) {
        return new BadChallengeException(e.getMessage(), e);
    } else if (e instanceof com.webauthn4j.validator.exception.BadOriginException) {
        return new BadOriginException(e.getMessage(), e);
    } else if (e instanceof com.webauthn4j.validator.exception.BadRpIdException) {
        return new BadRpIdException(e.getMessage(), e);
    } else if (e instanceof com.webauthn4j.validator.exception.BadSignatureException) {
        return new BadSignatureException(e.getMessage(), e);
    } else if (e instanceof com.webauthn4j.metadata.exception.BadStatusException) {
        return new BadStatusException(e.getMessage(), e);
    } else if (e instanceof com.webauthn4j.validator.exception.CertificateException) {
        return new CertificateException(e.getMessage(), e);
    } else if (e instanceof com.webauthn4j.validator.exception.ConstraintViolationException) {
        return new ConstraintViolationException(e.getMessage(), e);
    } else if (e instanceof com.webauthn4j.validator.exception.MaliciousCounterValueException) {
        return new MaliciousCounterValueException(e.getMessage(), e);
    } else if (e instanceof com.webauthn4j.validator.exception.InconsistentClientDataTypeException) {
        return new InconsistentClientDataTypeException(e.getMessage(), e);
    } else if (e instanceof com.webauthn4j.validator.exception.MissingChallengeException) {
        return new MissingChallengeException(e.getMessage(), e);
    } else if (e instanceof com.webauthn4j.validator.exception.PublicKeyMismatchException) {
        return new PublicKeyMismatchException(e.getMessage(), e);
    } else if (e instanceof com.webauthn4j.validator.exception.SelfAttestationProhibitedException) {
        return new SelfAttestationProhibitedException(e.getMessage(), e);
    } else if (e instanceof com.webauthn4j.validator.exception.TokenBindingException) {
        return new TokenBindingException(e.getMessage(), e);
    } else if (e instanceof com.webauthn4j.validator.exception.TrustAnchorNotFoundException) {
        return new TrustAnchorNotFoundException(e.getMessage(), e);
    } else if (e instanceof com.webauthn4j.validator.exception.UnexpectedExtensionException) {
        return new UnexpectedExtensionException(e.getMessage(), e);
    } else if (e instanceof com.webauthn4j.validator.exception.UserNotPresentException) {
        return new UserNotPresentException(e.getMessage(), e);
    } else if (e instanceof com.webauthn4j.validator.exception.UserNotVerifiedException) {
        return new UserNotVerifiedException(e.getMessage(), e);
    } else if (e instanceof com.webauthn4j.validator.exception.ValidationException) {
        return new ValidationException("WebAuthn validation error", e);
    }
    // DataConversionException
    else if (e instanceof com.webauthn4j.converter.exception.DataConversionException) {
        return new DataConversionException("WebAuthn data conversion error", e);
    } else {
        return new AuthenticationServiceException(null, e);
    }
}
 
Example #6
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;
    }
}
 
Example #7
Source File: WebAuthnAuthenticator.java    From keycloak with Apache License 2.0 4 votes vote down vote up
public void action(AuthenticationFlowContext context) {
    MultivaluedMap<String, String> params = context.getHttpRequest().getDecodedFormParameters();

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

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

    String baseUrl = UriUtils.getOrigin(context.getUriInfo().getBaseUri());
    String rpId = getRpID(context);

    Origin origin = new Origin(baseUrl);
    Challenge challenge = new DefaultChallenge(context.getAuthenticationSession().getAuthNote(WebAuthnConstants.AUTH_CHALLENGE_NOTE));
    ServerProperty server = new ServerProperty(origin, rpId, challenge, null);

    byte[] credentialId = Base64Url.decode(params.getFirst(WebAuthnConstants.CREDENTIAL_ID));
    byte[] clientDataJSON = Base64Url.decode(params.getFirst(WebAuthnConstants.CLIENT_DATA_JSON));
    byte[] authenticatorData = Base64Url.decode(params.getFirst(WebAuthnConstants.AUTHENTICATOR_DATA));
    byte[] signature = Base64Url.decode(params.getFirst(WebAuthnConstants.SIGNATURE));

    final String userHandle = params.getFirst(WebAuthnConstants.USER_HANDLE);
    final String userId;
    // existing User Handle means that the authenticator used Resident Key supported public key credential
    if (userHandle == null || userHandle.isEmpty()) {
        // Resident Key not supported public key credential was used
        // so rely on the user that has already been authenticated
        userId = context.getUser().getId();
    } else {
        // decode using the same charset as it has been encoded (see: WebAuthnRegister.java)
        userId = new String(Base64Url.decode(userHandle), StandardCharsets.UTF_8);
        if (context.getUser() != null) {
            // Resident Key supported public key credential was used,
            // so need to confirm whether the already authenticated user is equals to one authenticated by the webauthn authenticator
            String firstAuthenticatedUserId = context.getUser().getId();
            if (firstAuthenticatedUserId != null && !firstAuthenticatedUserId.equals(userId)) {
                context.getEvent()
                        .detail("first_authenticated_user_id", firstAuthenticatedUserId)
                        .detail("web_authn_authenticator_authenticated_user_id", userId);
                setErrorResponse(context, WEBAUTHN_ERROR_DIFFERENT_USER, null);
                return;
            }
        } else {
            // Resident Key supported public key credential was used,
            // and the user has not yet been identified
            // so rely on the user authenticated by the webauthn authenticator
            // NOP
        }
    }

    boolean isUVFlagChecked = false;
    String userVerificationRequirement = getWebAuthnPolicy(context).getUserVerificationRequirement();
    if (WebAuthnConstants.OPTION_REQUIRED.equals(userVerificationRequirement)) isUVFlagChecked = true;

    UserModel user = session.users().getUserById(userId, context.getRealm());

    AuthenticationRequest authenticationRequest = new AuthenticationRequest(
            credentialId,
            authenticatorData,
            clientDataJSON,
            signature
            );

    AuthenticationParameters authenticationParameters = new AuthenticationParameters(
            server,
            null, // here authenticator cannot be fetched, set it afterwards in WebAuthnCredentialProvider.isValid()
            isUVFlagChecked
            );

    WebAuthnCredentialModelInput cred = new WebAuthnCredentialModelInput(getCredentialType());

    cred.setAuthenticationRequest(authenticationRequest);
    cred.setAuthenticationParameters(authenticationParameters);

    boolean result = false;
    try {
        result = session.userCredentialManager().isValid(context.getRealm(), user, cred);
    } catch (WebAuthnException wae) {
        setErrorResponse(context, WEBAUTHN_ERROR_AUTH_VERIFICATION, wae.getMessage());
        return;
    }
    String encodedCredentialID = Base64Url.encode(credentialId);
    if (result) {
        String isUVChecked = Boolean.toString(isUVFlagChecked);
        logger.debugv("WebAuthn Authentication successed. isUserVerificationChecked = {0}, PublicKeyCredentialID = {1}", isUVChecked, encodedCredentialID);
        context.setUser(user);
        context.getEvent()
            .detail("web_authn_authenticator_user_verification_checked", isUVChecked)
            .detail("public_key_credential_id", encodedCredentialID);
        context.success();
    } else {
        context.getEvent()
            .detail("web_authn_authenticated_user_id", userId)
            .detail("public_key_credential_id", encodedCredentialID);
        setErrorResponse(context, WEBAUTHN_ERROR_USER_NOT_FOUND, null);
        context.cancelLogin();
    }
}
 
Example #8
Source File: WebAuthnCredentialProvider.java    From keycloak with Apache License 2.0 4 votes vote down vote up
@Override
public boolean isValid(RealmModel realm, UserModel user, CredentialInput input) {
    if (!WebAuthnCredentialModelInput.class.isInstance(input)) return false;

    WebAuthnCredentialModelInput context = WebAuthnCredentialModelInput.class.cast(input);
    List<WebAuthnCredentialModelInput> auths = getWebAuthnCredentialModelList(realm, user);

    WebAuthnAuthenticationManager webAuthnAuthenticationManager = new WebAuthnAuthenticationManager();
    AuthenticationData authenticationData = null;

    try {
        for (WebAuthnCredentialModelInput auth : auths) {

            byte[] credentialId = auth.getAttestedCredentialData().getCredentialId();
            if (Arrays.equals(credentialId, context.getAuthenticationRequest().getCredentialId())) {
                Authenticator authenticator = new AuthenticatorImpl(
                        auth.getAttestedCredentialData(),
                        auth.getAttestationStatement(),
                        auth.getCount()
                );

                // parse
                authenticationData = webAuthnAuthenticationManager.parse(context.getAuthenticationRequest());
                // validate
                AuthenticationParameters authenticationParameters = new AuthenticationParameters(
                        context.getAuthenticationParameters().getServerProperty(),
                        authenticator,
                        context.getAuthenticationParameters().isUserVerificationRequired()
                );
                webAuthnAuthenticationManager.validate(authenticationData, authenticationParameters);


                logger.debugv("response.getAuthenticatorData().getFlags() = {0}", authenticationData.getAuthenticatorData().getFlags());

                // update authenticator counter
                long count = auth.getCount();
                CredentialModel credModel = getCredentialStore().getStoredCredentialById(realm, user, auth.getCredentialDBId());
                WebAuthnCredentialModel webAuthnCredModel = getCredentialFromModel(credModel);
                webAuthnCredModel.updateCounter(count + 1);
                getCredentialStore().updateCredential(realm, user, webAuthnCredModel);

                logger.debugf("Successfully validated WebAuthn credential for user %s", user.getUsername());
                dumpCredentialModel(webAuthnCredModel, auth);

                return true;
            }
        }
    } catch (WebAuthnException wae) {
        wae.printStackTrace();
        throw(wae);
    }
    // no authenticator matched
    return false;
}