com.webauthn4j.data.client.Origin Java Examples

The following examples show how to use com.webauthn4j.data.client.Origin. 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: WebAuthnCredentialProviderTest.java    From keycloak-webauthn-authenticator with Apache License 2.0 6 votes vote down vote up
private WebAuthnCredentialModel getValidWebAuthnCredentialModel() {
    // mimic valid model created on Registration
    byte[] clientDataJSON = Base64.getUrlDecoder().decode("eyJjaGFsbGVuZ2UiOiJxOGJfc25BcFFCR0RTbEhLclVQWERBIiwib3JpZ2luIjoiaHR0cDovL2xvY2FsaG9zdDo4MDgwIiwidHlwZSI6IndlYmF1dGhuLmNyZWF0ZSJ9");
    byte[] attestationObject = Base64.getUrlDecoder().decode("o2NmbXRkbm9uZWdhdHRTdG10oGhhdXRoRGF0YVjESZYN5YgOjGh0NBcPZHZgW4_krrmihjLHmVzzuoMdl2NBAAAAAAAAAAAAAAAAAAAAAAAAAAAAQNl5cq57gFloyTRaRzspkmVtaFjseFuas8LzmCa9_M40tZHwnOxuDFLj__IQkmCi9bwtXfxGU8L3IbXoJf-R1v6lAQIDJiABIVggHRj3_pRuFc4STvzzqO3WgO9cnj7u9R4OogbtOc4qA5kiWCAniOpK656_61Qnmx4hkWffohlH4JDbuytCpCtf9jrruA");

    Origin origin = new Origin("http://localhost:8080");
    Challenge challenge = new DefaultChallenge("q8b_snApQBGDSlHKrUPXDA");
    ServerProperty serverProperty = new ServerProperty(origin, "localhost", challenge, null);

    WebAuthnRegistrationContext registrationContext = new WebAuthnRegistrationContext(clientDataJSON, attestationObject, serverProperty, false);
    WebAuthnRegistrationContextValidator webAuthnRegistrationContextValidator = WebAuthnRegistrationContextValidator.createNonStrictRegistrationContextValidator();
    WebAuthnRegistrationContextValidationResponse response = webAuthnRegistrationContextValidator.validate(registrationContext);

    WebAuthnCredentialModel credential = new WebAuthnCredentialModel();
    credential.setAttestedCredentialData(response.getAttestationObject().getAuthenticatorData().getAttestedCredentialData());
    credential.setAttestationStatement(response.getAttestationObject().getAttestationStatement());
    credential.setCount(response.getAttestationObject().getAuthenticatorData().getSignCount());

    return credential;
}
 
Example #2
Source File: WebAuthnCredentialProviderTest.java    From keycloak-webauthn-authenticator with Apache License 2.0 6 votes vote down vote up
private WebAuthnAuthenticationContext getValidWebAuthnAuthenticationContext(String base64UrlCredentialId) {
    // mimic valid or invalid model created on Authentication
    byte[] credentialId = Base64Url.decode(base64UrlCredentialId);
    byte[] clientDataJSON = Base64Url.decode("eyJjaGFsbGVuZ2UiOiJ0R3o3R3RUQVE2T3FwVHpoOEtLQnFRIiwib3JpZ2luIjoiaHR0cDovL2xvY2FsaG9zdDo4MDgwIiwidHlwZSI6IndlYmF1dGhuLmdldCJ9");
    byte[] authenticatorData = Base64Url.decode("SZYN5YgOjGh0NBcPZHZgW4_krrmihjLHmVzzuoMdl2MBAAAAdg");
    byte[] signature = Base64Url.decode("MEUCIEaZhQ5dXi_C3IxU68ujLLt0DEcyk2EFPz_y45wYUA7AAiEAwkX86OFwpNzPRjSljTaTJVvZ_x9E6xnKhSmsKkUgmlo");
    Origin origin = new Origin("http://localhost:8080");
    Challenge challenge = new DefaultChallenge("tGz7GtTAQ6OqpTzh8KKBqQ");
    ServerProperty server = new ServerProperty(origin, "localhost", challenge, null);
    WebAuthnAuthenticationContext authenticationContext = new WebAuthnAuthenticationContext(
            credentialId,
            clientDataJSON,
            authenticatorData,
            signature,
            server,
            false
    );
    return authenticationContext;
}
 
Example #3
Source File: PackedAttestationStatementValidatorTest.java    From webauthn4j with Apache License 2.0 6 votes vote down vote up
private void validate(byte[] clientDataBytes, AttestationObject attestationObject) {

        byte[] attestationObjectBytes = new AttestationObjectConverter(objectConverter).convertToBytes(attestationObject);

        Origin origin = new Origin(originUrl);
        Challenge challenge = (Challenge) () -> Base64UrlUtil.decode(challengeString);

        CollectedClientData collectedClientData = new CollectedClientDataConverter(objectConverter).convert(clientDataBytes);
        Set<AuthenticatorTransport> transports = Collections.emptySet();
        AuthenticationExtensionsClientOutputs<RegistrationExtensionClientOutput<?>> authenticationExtensionsClientOutputs = new AuthenticationExtensionsClientOutputs<>();

        RegistrationObject registrationObject = new RegistrationObject(
                attestationObject,
                attestationObjectBytes,
                collectedClientData,
                clientDataBytes,
                authenticationExtensionsClientOutputs,
                transports,
                new ServerProperty(origin, rpId, challenge, tokenBindingId)
        );

        validator.validate(registrationObject);
    }
 
Example #4
Source File: ServerPropertyProviderImplTest.java    From webauthn4j-spring-security with Apache License 2.0 6 votes vote down vote up
@Test
public void provide_test() {
    MockHttpServletRequest request = new MockHttpServletRequest();
    request.setScheme("https");
    request.setServerName("origin.example.com");
    request.setServerPort(443);
    Challenge mockChallenge = new DefaultChallenge();
    when(challengeRepository.loadOrGenerateChallenge(request)).thenReturn(mockChallenge);
    when(optionsProvider.getEffectiveRpId(request)).thenReturn("rpid.example.com");

    ServerProperty serverProperty = target.provide(request);

    assertThat(serverProperty.getRpId()).isEqualTo("rpid.example.com");
    assertThat(serverProperty.getOrigin()).isEqualTo(new Origin("https://origin.example.com"));
    assertThat(serverProperty.getChallenge()).isEqualTo(mockChallenge);
}
 
Example #5
Source File: RegistrationParametersTest.java    From webauthn4j with Apache License 2.0 6 votes vote down vote up
@Test
void equals_hashCode_test() {
    // Server properties
    Origin origin = null /* set origin */;
    String rpId = null /* set rpId */;
    Challenge challenge = null /* set challenge */;
    byte[] tokenBindingId = null /* set tokenBindingId */;
    ServerProperty serverProperty = new ServerProperty(origin, rpId, challenge, tokenBindingId);

    // expectations
    boolean userVerificationRequired = true;

    RegistrationParameters instanceA =
            new RegistrationParameters(
                    serverProperty,
                    userVerificationRequired
            );
    RegistrationParameters instanceB =
            new RegistrationParameters(
                    serverProperty,
                    userVerificationRequired
            );

    assertThat(instanceA).isEqualTo(instanceB);
    assertThat(instanceA).hasSameHashCodeAs(instanceB);
}
 
Example #6
Source File: WebAuthnRegistrationContextValidatorSample.java    From webauthn4j with Apache License 2.0 5 votes vote down vote up
public void athenticationValidationSample() {
    // Client properties
    byte[] credentialId = null /* set credentialId */;
    byte[] clientDataJSON = null /* set clientDataJSON */;
    byte[] authenticatorData = null /* set authenticatorData */;
    byte[] signature = null /* set signature */;

    // Server properties
    Origin origin = null /* set origin */;
    String rpId = null /* set rpId */;
    Challenge challenge = null /* set challenge */;
    byte[] tokenBindingId = null /* set tokenBindingId */;
    ServerProperty serverProperty = new ServerProperty(origin, rpId, challenge, tokenBindingId);
    Authenticator authenticator = load(credentialId); // please load authenticator object persisted in the registration process in your manner
    boolean userVerificationRequired = true;

    AuthenticationRequest authenticationRequest =
            new AuthenticationRequest(
                    credentialId,
                    authenticatorData,
                    clientDataJSON,
                    signature
            );
    AuthenticationParameters authenticationParameters =
            new AuthenticationParameters(
                    serverProperty,
                    authenticator,
                    userVerificationRequired
            );

    WebAuthnManager webAuthnManager = WebAuthnManager.createNonStrictWebAuthnManager();

    AuthenticationData response = webAuthnManager.validate(authenticationRequest, authenticationParameters);

    // please update the counter of the authenticator record
    updateCounter(
            response.getCredentialId(),
            response.getAuthenticatorData().getSignCount()
    );
}
 
Example #7
Source File: CollectedClientDataConverterTest.java    From webauthn4j with Apache License 2.0 5 votes vote down vote up
@Test
void convert_clientDataBase64UrlString_with_new_keys_test() {
    //noinspection SpellCheckingInspection
    String clientDataJson = "{\"challenge\":\"Tgup0LZZQKinvtQcZFYdRw\",\"new_keys_may_be_added_here\":\"do not compare clientDataJSON against a template. See https://goo.gl/yabPex\",\"origin\":\"http://localhost:8080\",\"tokenBinding\":{\"status\":\"not-supported\"},\"type\":\"webauthn.create\"}";
    String clientDataBase64UrlString = Base64UrlUtil.encodeToString(clientDataJson.getBytes(StandardCharsets.UTF_8));
    CollectedClientData collectedClientData = target.convert(clientDataBase64UrlString);
    assertAll(
            () -> assertThat(collectedClientData.getType()).isEqualTo(ClientDataType.CREATE),
            () -> assertThat(collectedClientData.getChallenge()).isEqualTo(new DefaultChallenge("Tgup0LZZQKinvtQcZFYdRw")),
            () -> assertThat(collectedClientData.getOrigin()).isEqualTo(new Origin("http://localhost:8080"))
    );
}
 
Example #8
Source File: CollectedClientDataConverterTest.java    From webauthn4j with Apache License 2.0 5 votes vote down vote up
@Test
void convert_deserialization_test() {
    //noinspection SpellCheckingInspection
    String clientDataJson = "{\"challenge\":\"tk31UH1ETGGTPj33OhOMzw\",\"origin\":\"http://localhost:8080\",\"tokenBinding\":{\"status\":\"not-supported\"},\"type\":\"webauthn.get\"}";
    String clientDataBase64UrlString = Base64UrlUtil.encodeToString(clientDataJson.getBytes(StandardCharsets.UTF_8));
    CollectedClientData collectedClientData = target.convert(clientDataBase64UrlString);
    assertAll(
            () -> assertThat(collectedClientData.getType()).isEqualTo(ClientDataType.GET),
            () -> assertThat(collectedClientData.getChallenge()).isEqualTo(new DefaultChallenge("tk31UH1ETGGTPj33OhOMzw")),
            () -> assertThat(collectedClientData.getOrigin()).isEqualTo(new Origin("http://localhost:8080"))
    );
}
 
Example #9
Source File: OriginValidatorTest.java    From webauthn4j with Apache License 2.0 5 votes vote down vote up
@Test
void test() {
    Origin originA = new Origin("https://example.com:14443");
    Origin originB = new Origin("https://example.com:14443");

    CollectedClientData collectedClientData = new CollectedClientData(ClientDataType.CREATE, TestDataUtil.createChallenge(), originA, null);
    ServerProperty serverProperty = new ServerProperty(originB, "example.com", TestDataUtil.createChallenge(), null);
    target.validate(collectedClientData, serverProperty);
}
 
Example #10
Source File: OriginValidatorTest.java    From webauthn4j with Apache License 2.0 5 votes vote down vote up
@Test
void test_with_not_equal_origins() {
    Origin originA = new Origin("https://example.com:14443");
    Origin originB = new Origin("http://example.com");

    CollectedClientData collectedClientData = new CollectedClientData(ClientDataType.CREATE, TestDataUtil.createChallenge(), originA, null);
    ServerProperty serverProperty = new ServerProperty(originB, "example.com", TestDataUtil.createChallenge(), null);
    assertThrows(BadOriginException.class,
            () -> target.validate(collectedClientData, serverProperty)
    );
}
 
Example #11
Source File: FIDOU2FAuthenticatorRegistrationValidationTest.java    From webauthn4j with Apache License 2.0 5 votes vote down vote up
@Test
void validate_with_bad_origin_test() {
    String rpId = "example.com";
    Challenge challenge = new DefaultChallenge();
    Origin badOrigin = new Origin("http://bad.origin.example.net");
    PublicKeyCredentialParameters publicKeyCredentialParameters
            = new PublicKeyCredentialParameters(PublicKeyCredentialType.PUBLIC_KEY, COSEAlgorithmIdentifier.ES256);
    PublicKeyCredentialCreationOptions credentialCreationOptions = new PublicKeyCredentialCreationOptions(
            new PublicKeyCredentialRpEntity(rpId, "example.com"),
            new PublicKeyCredentialUserEntity(),
            challenge,
            Collections.singletonList(publicKeyCredentialParameters)
    );

    clientPlatform.setOrigin(badOrigin); //bad origin
    AuthenticatorAttestationResponse authenticatorAttestationResponse = clientPlatform.create(credentialCreationOptions).getAuthenticatorResponse();

    Set<String> transports = authenticatorTransportConverter.convertSetToStringSet(authenticatorAttestationResponse.getTransports());
    ServerProperty serverProperty = new ServerProperty(origin, rpId, challenge, null);
    RegistrationRequest registrationRequest
            = new RegistrationRequest(
            authenticatorAttestationResponse.getAttestationObject(),
            authenticatorAttestationResponse.getClientDataJSON(),
            transports
    );
    RegistrationParameters registrationParameters
            = new RegistrationParameters(
            serverProperty,
            false,
            true,
            Collections.emptyList()
    );

    assertThrows(BadOriginException.class,
            () -> target.validate(registrationRequest, registrationParameters)
    );
}
 
Example #12
Source File: AuthenticationParametersTest.java    From webauthn4j with Apache License 2.0 5 votes vote down vote up
@Test
void constructor_test() {
    // Server properties
    Origin origin = null /* set origin */;
    String rpId = null /* set rpId */;
    Challenge challenge = null /* set challenge */;
    byte[] tokenBindingId = null /* set tokenBindingId */;
    ServerProperty serverProperty = new ServerProperty(origin, rpId, challenge, tokenBindingId);

    Authenticator authenticator = null;

    // expectations
    boolean userVerificationRequired = true;

    AuthenticationParameters authenticationParameters =
            new AuthenticationParameters(
                    serverProperty,
                    authenticator,
                    userVerificationRequired
            );

    assertThat(authenticationParameters.getServerProperty()).isEqualTo(serverProperty);
    assertThat(authenticationParameters.getAuthenticator()).isEqualTo(authenticator);
    assertThat(authenticationParameters.isUserVerificationRequired()).isEqualTo(userVerificationRequired);
    assertThat(authenticationParameters.isUserPresenceRequired()).isTrue();
    assertThat(authenticationParameters.getExpectedExtensionIds()).isNull();
}
 
Example #13
Source File: AuthenticationParametersTest.java    From webauthn4j with Apache License 2.0 5 votes vote down vote up
@Test
void equals_hashCode_test() {
    // Server properties
    Origin origin = null /* set origin */;
    String rpId = null /* set rpId */;
    Challenge challenge = null /* set challenge */;
    byte[] tokenBindingId = null /* set tokenBindingId */;
    ServerProperty serverProperty = new ServerProperty(origin, rpId, challenge, tokenBindingId);

    Authenticator authenticator = null;

    // expectations
    boolean userVerificationRequired = true;
    boolean userPresenceRequired = true;
    List<String> expectedExtensionIds = Collections.emptyList();

    AuthenticationParameters instanceA =
            new AuthenticationParameters(
                    serverProperty,
                    authenticator,
                    userVerificationRequired,
                    userPresenceRequired,
                    expectedExtensionIds
            );
    AuthenticationParameters instanceB =
            new AuthenticationParameters(
                    serverProperty,
                    authenticator,
                    userVerificationRequired,
                    userPresenceRequired,
                    expectedExtensionIds
            );

    assertThat(instanceA).isEqualTo(instanceB);
    assertThat(instanceA).hasSameHashCodeAs(instanceB);

}
 
Example #14
Source File: WebAuthnAuthenticationRequestTest.java    From webauthn4j-spring-security with Apache License 2.0 5 votes vote down vote up
@Test
public void equals_hashCode_test() {
    Challenge challenge = new DefaultChallenge();
    byte[] clientDataJSON = TestDataUtil.createClientDataJSON(ClientDataType.GET);
    byte[] authenticatorData = new AuthenticatorDataConverter(objectConverter).convert(TestDataUtil.createAuthenticatorData());
    WebAuthnAuthenticationRequest requestA = new WebAuthnAuthenticationRequest(
            new byte[]{0x01, 0x23},
            clientDataJSON,
            authenticatorData,
            new byte[]{0x45, 0x56},
            "",
            new ServerProperty(
                    new Origin("https://example.com"),
                    "example.com",
                    challenge,
                    new byte[]{0x43, 0x21}
            ),
            true,
            Collections.singletonList("uvi")
    );
    WebAuthnAuthenticationRequest requestB = new WebAuthnAuthenticationRequest(
            new byte[]{0x01, 0x23},
            clientDataJSON,
            authenticatorData,
            new byte[]{0x45, 0x56},
            "",
            new ServerProperty(
                    new Origin("https://example.com"),
                    "example.com",
                    challenge,
                    new byte[]{0x43, 0x21}
            ),
            true,
            Collections.singletonList("uvi")
    );

    assertThat(requestA).isEqualTo(requestB);
    assertThat(requestA).hasSameHashCodeAs(requestB);
}
 
Example #15
Source File: WebAuthnAuthenticationRequestTest.java    From webauthn4j-spring-security with Apache License 2.0 5 votes vote down vote up
@Test
public void getter_test() {
    Challenge challenge = new DefaultChallenge();
    byte[] clientDataJSON = TestDataUtil.createClientDataJSON(ClientDataType.GET);
    byte[] authenticatorData = new AuthenticatorDataConverter(objectConverter).convert(TestDataUtil.createAuthenticatorData());
    ServerProperty serverProperty = new ServerProperty(
            new Origin("https://example.com"),
            "example.com",
            challenge,
            new byte[]{0x43, 0x21}
    );
    WebAuthnAuthenticationRequest request = new WebAuthnAuthenticationRequest(
            new byte[]{0x01, 0x23},
            clientDataJSON,
            authenticatorData,
            new byte[]{0x45, 0x56},
            "",
            serverProperty,
            true,
            true,
            Collections.singletonList("uvi")
    );
    assertThat(request.getCredentialId()).isEqualTo(new byte[]{0x01, 0x23});
    assertThat(request.getClientDataJSON()).isEqualTo(clientDataJSON);
    assertThat(request.getAuthenticatorData()).isEqualTo(authenticatorData);
    assertThat(request.getSignature()).isEqualTo(new byte[]{0x45, 0x56});
    assertThat(request.getClientExtensionsJSON()).isEqualTo("");
    assertThat(request.getServerProperty()).isEqualTo(serverProperty);
    assertThat(request.isUserVerificationRequired()).isEqualTo(true);
    assertThat(request.isUserPresenceRequired()).isEqualTo(true);
    assertThat(request.getExpectedAuthenticationExtensionIds()).isEqualTo(Collections.singletonList("uvi"));
}
 
Example #16
Source File: ServerPropertyProviderImpl.java    From webauthn4j-spring-security with Apache License 2.0 5 votes vote down vote up
/**
 * {@inheritDoc}
 */
public ServerProperty provide(HttpServletRequest request) {

    Origin origin = ServletUtil.getOrigin(request);
    String effectiveRpId = optionsProvider.getEffectiveRpId(request);
    Challenge challenge = challengeRepository.loadOrGenerateChallenge(request);

    return new ServerProperty(origin, effectiveRpId, challenge, null); // tokenBinding is not supported by Servlet API as of 4.0
}
 
Example #17
Source File: OptionsProviderImpl.java    From webauthn4j-spring-security with Apache License 2.0 5 votes vote down vote up
public String getEffectiveRpId(HttpServletRequest request) {
    String effectiveRpId;
    if (this.rpId != null) {
        effectiveRpId = this.rpId;
    } else {
        Origin origin = ServletUtil.getOrigin(request);
        effectiveRpId = origin.getHost();
    }
    return effectiveRpId;
}
 
Example #18
Source File: WebAuthnRegistrationContextValidatorSample.java    From webauthn4j with Apache License 2.0 4 votes vote down vote up
public void registrationValidationSample() {
    // Client properties
    byte[] clientDataJSON = null /* set clientDataJSON */;
    byte[] attestationObject = null /* set attestationObject */;
    Set<String> transports = null /* set transports */;

    // Server properties
    Origin origin = null /* set origin */;
    String rpId = null /* set rpId */;
    Challenge challenge = null /* set challenge */;
    byte[] tokenBindingId = null /* set tokenBindingId */;
    ServerProperty serverProperty = new ServerProperty(origin, rpId, challenge, tokenBindingId);
    boolean userVerificationRequired = false;

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

    // WebAuthnManager.createNonStrictWebAuthnManager() returns a WebAuthnManager instance
    // which doesn't validate an attestation statement. It is recommended configuration for most web application.
    // If you are building enterprise web application and need to validate the attestation statement, use the constructor of
    // RegistrationContextValidator and provide validators you like
    WebAuthnManager webAuthnManager = WebAuthnManager.createNonStrictWebAuthnManager();

    RegistrationData response = webAuthnManager.validate(registrationRequest, registrationParameters);

    // please persist Authenticator object, which will be used in the authentication process.
    Authenticator authenticator =
            new AuthenticatorImpl( // You may create your own Authenticator implementation to save friendly authenticator name
                    response.getAttestationObject().getAuthenticatorData().getAttestedCredentialData(),
                    response.getAttestationObject().getAttestationStatement(),
                    response.getAttestationObject().getAuthenticatorData().getSignCount()
            );
    save(authenticator); // please persist authenticator in your manner
}
 
Example #19
Source File: UserVerifyingAuthenticatorAuthenticationValidationTest.java    From webauthn4j with Apache License 2.0 4 votes vote down vote up
@Test
void validate_assertion_with_bad_origin_test() {
    String rpId = "example.com";
    long timeout = 0;
    Challenge challenge = new DefaultChallenge();

    // create
    AttestationObject attestationObject = createAttestationObject(rpId, challenge);

    // get
    PublicKeyCredentialRequestOptions credentialRequestOptions = new PublicKeyCredentialRequestOptions(
            challenge,
            timeout,
            rpId,
            null,
            UserVerificationRequirement.REQUIRED,
            null
    );
    clientPlatform.setOrigin(new Origin("https://bad.origin.example.com")); //bad origin
    PublicKeyCredential<AuthenticatorAssertionResponse, AuthenticationExtensionClientOutput<?>> credential = clientPlatform.get(credentialRequestOptions);
    AuthenticatorAssertionResponse authenticationRequest = credential.getAuthenticatorResponse();

    ServerProperty serverProperty = new ServerProperty(origin, rpId, challenge, null);
    Authenticator authenticator = TestDataUtil.createAuthenticator(attestationObject);
    AuthenticationRequest webAuthnAuthenticationRequest =
            new AuthenticationRequest(
                    credential.getRawId(),
                    authenticationRequest.getAuthenticatorData(),
                    authenticationRequest.getClientDataJSON(),
                    authenticationRequest.getSignature()
            );
    AuthenticationParameters authenticationParameters =
            new AuthenticationParameters(
                    serverProperty,
                    authenticator,
                    true
            );

    AuthenticationData authenticationData = target.parse(webAuthnAuthenticationRequest);
    assertThrows(BadOriginException.class, () -> target.validate(authenticationData, authenticationParameters));
}
 
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;
    }
}
 
Example #21
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 #22
Source File: FIDOU2FAuthenticatorAuthenticationValidationTest.java    From webauthn4j with Apache License 2.0 4 votes vote down vote up
@Test
void validate_assertion_with_bad_origin_test() {
    String rpId = "example.com";
    long timeout = 0;
    Challenge challenge = new DefaultChallenge();

    // create
    AttestationObject attestationObject = createAttestationObject(rpId, challenge);

    // get
    PublicKeyCredentialRequestOptions credentialRequestOptions = new PublicKeyCredentialRequestOptions(
            challenge,
            timeout,
            rpId,
            Collections.singletonList(
                    new PublicKeyCredentialDescriptor(
                            PublicKeyCredentialType.PUBLIC_KEY,
                            attestationObject.getAuthenticatorData().getAttestedCredentialData().getCredentialId(),
                            CollectionUtil.unmodifiableSet(AuthenticatorTransport.USB, AuthenticatorTransport.NFC, AuthenticatorTransport.BLE)
                    )
            ),
            UserVerificationRequirement.DISCOURAGED,
            null
    );
    clientPlatform.setOrigin(new Origin("https://bad.origin.example.com")); //bad origin
    PublicKeyCredential<AuthenticatorAssertionResponse, AuthenticationExtensionClientOutput<?>> credential = clientPlatform.get(credentialRequestOptions);
    AuthenticatorAssertionResponse authenticatorAssertionResponse = credential.getAuthenticatorResponse();

    ServerProperty serverProperty = new ServerProperty(origin, rpId, challenge, null);
    Authenticator authenticator = TestDataUtil.createAuthenticator(attestationObject);

    AuthenticationRequest authenticationRequest =
            new AuthenticationRequest(
                    credential.getRawId(),
                    authenticatorAssertionResponse.getAuthenticatorData(),
                    authenticatorAssertionResponse.getClientDataJSON(),
                    authenticatorAssertionResponse.getSignature()
            );
    AuthenticationParameters authenticationParameters =
            new AuthenticationParameters(
                    serverProperty,
                    authenticator,
                    false
            );

    assertThrows(BadOriginException.class,
            () -> target.validate(authenticationRequest, authenticationParameters)
    );
}
 
Example #23
Source File: FIDOU2FAuthenticatorRegistrationValidationTest.java    From webauthn4j with Apache License 2.0 4 votes vote down vote up
@Test
void validate_malicious_client_data_test() {
    Origin phishingSiteOrigin = new Origin("http://phishing.site.example.com");
    Origin validSiteOrigin = new Origin("http://valid.site.example.com");
    Origin phishingSiteClaimingOrigin = new Origin("http://valid.site.example.com");

    ClientPlatform clientPlatform = new ClientPlatform(phishingSiteOrigin, new FIDOU2FAuthenticatorAdaptor()); // client platform loads phishing site
    String rpId = "valid.site.example.com";
    Challenge challenge = new DefaultChallenge();

    PublicKeyCredentialParameters publicKeyCredentialParameters
            = new PublicKeyCredentialParameters(PublicKeyCredentialType.PUBLIC_KEY, COSEAlgorithmIdentifier.ES256);

    AuthenticatorSelectionCriteria authenticatorSelectionCriteria =
            new AuthenticatorSelectionCriteria(
                    AuthenticatorAttachment.CROSS_PLATFORM,
                    true,
                    UserVerificationRequirement.REQUIRED);

    AuthenticationExtensionsClientInputs<RegistrationExtensionClientInput<?>> extensions = new AuthenticationExtensionsClientInputs<>();
    PublicKeyCredentialCreationOptions credentialCreationOptions = new PublicKeyCredentialCreationOptions(
            new PublicKeyCredentialRpEntity(rpId, "valid.site.example.com"),
            new PublicKeyCredentialUserEntity(),
            challenge,
            Collections.singletonList(publicKeyCredentialParameters),
            null,
            Collections.emptyList(),
            authenticatorSelectionCriteria,
            AttestationConveyancePreference.DIRECT,
            extensions
    );

    AuthenticatorAttestationResponse authenticatorAttestationResponse = clientPlatform.create(credentialCreationOptions).getAuthenticatorResponse();

    CollectedClientData maliciousClientData = new CollectedClientData(ClientDataType.CREATE, challenge, phishingSiteClaimingOrigin, null);
    byte[] maliciousClientDataBytes = new CollectedClientDataConverter(objectConverter).convertToBytes(maliciousClientData);
    Set<String> transports = authenticatorTransportConverter.convertSetToStringSet(authenticatorAttestationResponse.getTransports());
    ServerProperty serverProperty = new ServerProperty(validSiteOrigin, rpId, challenge, null);
    RegistrationRequest registrationRequest
            = new RegistrationRequest(
            authenticatorAttestationResponse.getAttestationObject(),
            maliciousClientDataBytes,
            transports
    );
    RegistrationParameters registrationParameters
            = new RegistrationParameters(
            serverProperty,
            false,
            true,
            Collections.emptyList()
    );

    assertThrows(BadSignatureException.class,
            () -> target.validate(registrationRequest, registrationParameters)
    );
}
 
Example #24
Source File: RegisterAuthenticator.java    From keycloak-webauthn-authenticator with Apache License 2.0 4 votes vote down vote up
@Override
public void processAction(RequiredActionContext context) {

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

    // receive error from navigator.credentials.create()
    String error = params.getFirst(WebAuthnConstants.ERROR);
    if (error != null && !error.isEmpty()) {
        throw new AuthenticationFlowException("exception raised from navigator.credentials.create() : " + error, AuthenticationFlowError.INVALID_CREDENTIALS);
    }

    String baseUrl = UriUtils.getOrigin(context.getUriInfo().getBaseUri());
    String 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(baseUrl);
    Challenge challenge = new DefaultChallenge(context.getAuthenticationSession().getAuthNote(WebAuthnConstants.AUTH_CHALLENGE_NOTE));
    ServerProperty serverProperty = new ServerProperty(origin, rpId, challenge, null);

    try {
        WebAuthnRegistrationContext registrationContext = new WebAuthnRegistrationContext(clientDataJSON, attestationObject, serverProperty, false);
        WebAuthnRegistrationContextValidator webAuthnRegistrationContextValidator = WebAuthnRegistrationContextValidator.createNonStrictRegistrationContextValidator();
        WebAuthnRegistrationContextValidationResponse response = webAuthnRegistrationContextValidator.validate(registrationContext);

        WebAuthnCredentialModel credential = new WebAuthnCredentialModel();

        credential.setAttestedCredentialData(response.getAttestationObject().getAuthenticatorData().getAttestedCredentialData());
        credential.setAttestationStatement(response.getAttestationObject().getAttestationStatement());
        credential.setCount(response.getAttestationObject().getAuthenticatorData().getSignCount());

        this.session.userCredentialManager().updateCredential(context.getRealm(), context.getUser(), credential);

        // store received Credential ID on Registration onto UserModel in order to be used on Authentication
        context.getUser().setSingleAttribute(WebAuthnConstants.PUBKEY_CRED_ID_ATTR, publicKeyCredentialId);
        context.getUser().setSingleAttribute(WebAuthnConstants.PUBKEY_CRED_LABEL_ATTR, label);
        context.getUser().setSingleAttribute(WebAuthnConstants.PUBKEY_CRED_AAGUID_ATTR, response.getAttestationObject().getAuthenticatorData().getAttestedCredentialData().getAaguid().toString());
        logger.infov("publicKeyCredentialId = {0}", context.getUser().getAttribute(WebAuthnConstants.PUBKEY_CRED_ID_ATTR));
        logger.infov("publicKeyCredentialLabel = {0}", context.getUser().getAttribute(WebAuthnConstants.PUBKEY_CRED_LABEL_ATTR));
        logger.infov("publicKeyCredentialAAGUID = {0}", context.getUser().getAttribute(WebAuthnConstants.PUBKEY_CRED_AAGUID_ATTR));

        context.success();
    } catch (Exception me) {
        me.printStackTrace();
        throw new AuthenticationFlowException("failed to update credential.", AuthenticationFlowError.INVALID_CREDENTIALS);
    }
}
 
Example #25
Source File: ServerProperty.java    From webauthn4j with Apache License 2.0 4 votes vote down vote up
public ServerProperty(Origin origin, String rpId, Challenge challenge, byte[] tokenBindingId) {
    this.origin = origin;
    this.rpId = rpId;
    this.challenge = challenge;
    this.tokenBindingId = tokenBindingId;
}
 
Example #26
Source File: OriginSerializer.java    From webauthn4j with Apache License 2.0 4 votes vote down vote up
/**
 * {@inheritDoc}
 */
@Override
public void serialize(Origin value, JsonGenerator gen, SerializerProvider provider) throws IOException {
    gen.writeString(value.toString());
}
 
Example #27
Source File: OriginSerializer.java    From webauthn4j with Apache License 2.0 4 votes vote down vote up
public OriginSerializer() {
    super(Origin.class);
}
 
Example #28
Source File: TestDataUtil.java    From webauthn4j with Apache License 2.0 4 votes vote down vote up
public static Origin createOrigin() {
    return new Origin("https://localhost:8080");
}
 
Example #29
Source File: WebAuthn4jAuthenticator.java    From keycloak-webauthn-authenticator with Apache License 2.0 4 votes vote down vote up
public void action(AuthenticationFlowContext context) {
    MultivaluedMap<String, String> params = context.getHttpRequest().getDecodedFormParameters();

    // receive error from navigator.credentials.get()
    String error = params.getFirst(WebAuthnConstants.ERROR);
    if (error != null && !error.isEmpty()) {
        throw new AuthenticationFlowException("exception raised from navigator.credentials.get() : " + error, AuthenticationFlowError.INVALID_USER);
    }

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

    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));

    String userId = params.getFirst(WebAuthnConstants.USER_HANDLE);
    boolean isUVFlagChecked = true;
    logger.debugv("userId = {0}", userId);

    if (userId == null || userId.isEmpty()) {
        // in 2 Factor with Resident Key not supported Authenticator Scenario
        userId = context.getUser().getId();
        isUVFlagChecked = false;
    } else {
        if (context.getUser() != null) {
            // in 2 Factor with Resident Key supported Authenticator Scenario
            String firstAuthenticatedUserId = context.getUser().getId();
            logger.debugv("firstAuthenticatedUserId = {0}", firstAuthenticatedUserId);
            if (firstAuthenticatedUserId != null && !firstAuthenticatedUserId.equals(userId)) {
                throw new AuthenticationFlowException("First authenticated user is not the one authenticated by 2nd factor authenticator", AuthenticationFlowError.USER_CONFLICT);
            }
        } else {
            // in Passwordless with Resident Key supported Authenticator Scenario
            // NOP
        }
    }
    UserModel user = session.users().getUserById(userId, context.getRealm());
    WebAuthnAuthenticationContext authenticationContext = new WebAuthnAuthenticationContext(
            credentialId,
            clientDataJSON,
            authenticatorData,
            signature,
            server,
            isUVFlagChecked
    );

    WebAuthnCredentialModel cred = new WebAuthnCredentialModel();
    cred.setAuthenticationContext(authenticationContext);

    boolean result = false;
    try {
        result = session.userCredentialManager().isValid(context.getRealm(), user, cred);
    } catch (Exception e) {
        e.printStackTrace();
        throw new AuthenticationFlowException("unknown user authenticated by the authenticator", AuthenticationFlowError.UNKNOWN_USER);
    }
    if (result) {
        context.setUser(user);
        context.success();
    } else {
        context.cancelLogin();
    }
}
 
Example #30
Source File: ServerProperty.java    From webauthn4j with Apache License 2.0 2 votes vote down vote up
/**
 * Returns the {@link Origin}
 *
 * @return the {@link Origin}
 */
public Origin getOrigin() {
    return origin;
}