Search in sources :

Example 31 with CollectedClientData

use of com.webauthn4j.data.client.CollectedClientData in project webauthn4j by webauthn4j.

the class RegistrationDataValidator method validate.

// as null check is done by BeanAssertUtil#validate
@SuppressWarnings("ConstantConditions")
public void validate(@NonNull RegistrationData registrationData, @NonNull RegistrationParameters registrationParameters) {
    // spec| Step1
    // spec| Let options be a new PublicKeyCredentialCreationOptions structure configured to the Relying Party's needs for the ceremony.
    // (This step is done on client slide and out of WebAuthn4J responsibility.)
    // spec| Step2
    // spec| Call navigator.credentials.create() and pass options as the publicKey option. Let credential be the result of the successfully resolved promise.
    // spec| If the promise is rejected, abort the ceremony with a user-visible error,
    // spec| or otherwise guide the user experience as might be determinable from the context available in the rejected promise.
    // spec| For example if the promise is rejected with an error code equivalent to "InvalidStateError",
    // spec| the user might be instructed to use a different authenticator.
    // spec| For information on different error contexts and the circumstances leading to them, see § 6.3.2 The authenticatorMakeCredential Operation.
    // (This step is done on client slide and out of WebAuthn4J responsibility.)
    // spec| Step3
    // spec| Let response be credential.response. If response is not an instance of AuthenticatorAttestationResponse, abort the ceremony with a user-visible error.
    // (This step is done on client slide and out of WebAuthn4J responsibility.)
    // spec| Step4
    // spec| Let clientExtensionResults be the result of calling credential.getClientExtensionResults().
    // spec| Step5
    // spec| Let JSONtext be the result of running UTF-8 decode on the value of response.clientDataJSON.
    // (This step is done on caller.)
    BeanAssertUtil.validate(registrationData);
    AssertUtil.notNull(registrationParameters, "registrationParameters must not be null");
    byte[] clientDataBytes = registrationData.getCollectedClientDataBytes();
    byte[] attestationObjectBytes = registrationData.getAttestationObjectBytes();
    // spec| Step6
    // spec| Let C, the client data claimed as collected during the credential creation,
    // spec| be the result of running an implementation-specific JSON parser on JSONtext.
    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| Verify that the value of C.type is webauthn.create.
    if (!Objects.equals(collectedClientData.getType(), ClientDataType.WEBAUTHN_CREATE)) {
        throw new InconsistentClientDataTypeException("ClientData.type must be 'create' on registration, but it isn't.");
    }
    // spec| Step8
    // spec| Verify that the value of C.challenge equals the base64url encoding of options.challenge.
    challengeValidator.validate(collectedClientData, serverProperty);
    // spec| Step9
    // spec| Verify that the value of C.origin matches the Relying Party's origin.
    originValidator.validate(registrationObject);
    // spec| Step10
    // 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| Step11
    // spec| Let hash be the result of computing a hash over response.clientDataJSON using SHA-256.
    // spec| Step12
    // 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.
    // (This step is done on caller.)
    // spec| Step13
    // spec| Verify that the rpIdHash in authData is the SHA-256 hash of the RP ID expected by the Relying Party.
    rpIdHashValidator.validate(authenticatorData.getRpIdHash(), serverProperty);
    // spec| Step14, 15
    // spec| Verify that the User Present bit of the flags in authData is set.
    // spec| If user verification is required for this registration, verify that the User Verified bit of the flags in authData is set.
    validateUVUPFlags(authenticatorData, registrationParameters.isUserVerificationRequired(), registrationParameters.isUserPresenceRequired());
    // spec| Step16
    // spec| Verify that the "alg" parameter in the credential public key in authData matches the alg attribute of one of the items in options.pubKeyCredParams.
    COSEAlgorithmIdentifier alg = authenticatorData.getAttestedCredentialData().getCOSEKey().getAlgorithm();
    List<PublicKeyCredentialParameters> pubKeyCredParams = registrationParameters.getPubKeyCredParams();
    validateAlg(alg, pubKeyCredParams);
    // spec| Step17
    // spec| Verify that the values of the client extension outputs in clientExtensionResults and the authenticator extension outputs in the extensions in authData are as expected,
    // spec| considering the client extension input values that were given in options.extensions and any specific policy of the Relying Party regarding unsolicited extensions,
    // spec| i.e., those that were not specified as part of options.extensions.
    // 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();
    clientExtensionValidator.validate(clientExtensions);
    authenticatorExtensionValidator.validate(authenticationExtensionsAuthenticatorOutputs);
    // spec| Step18-21
    attestationValidator.validate(registrationObject);
    // validate with custom logic
    for (CustomRegistrationValidator customRegistrationValidator : customRegistrationValidators) {
        customRegistrationValidator.validate(registrationObject);
    }
}
Also used : ServerProperty(com.webauthn4j.server.ServerProperty) RegistrationExtensionAuthenticatorOutput(com.webauthn4j.data.extension.authenticator.RegistrationExtensionAuthenticatorOutput) RegistrationExtensionClientOutput(com.webauthn4j.data.extension.client.RegistrationExtensionClientOutput) CollectedClientData(com.webauthn4j.data.client.CollectedClientData) PublicKeyCredentialParameters(com.webauthn4j.data.PublicKeyCredentialParameters) COSEAlgorithmIdentifier(com.webauthn4j.data.attestation.statement.COSEAlgorithmIdentifier) AttestationObject(com.webauthn4j.data.attestation.AttestationObject) AuthenticatorTransport(com.webauthn4j.data.AuthenticatorTransport)

Example 32 with CollectedClientData

use of com.webauthn4j.data.client.CollectedClientData in project webauthn4j by webauthn4j.

the class FIDOU2FAuthenticatorRegistrationValidationTest method validate_malicious_client_data_test.

@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");
    // client platform loads phishing site
    ClientPlatform clientPlatform = new ClientPlatform(phishingSiteOrigin, new FIDOU2FAuthenticatorAdaptor());
    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(new byte[32], "username", "displayName"), challenge, Collections.singletonList(publicKeyCredentialParameters), null, Collections.emptyList(), authenticatorSelectionCriteria, AttestationConveyancePreference.DIRECT, extensions);
    AuthenticatorAttestationResponse authenticatorAttestationResponse = clientPlatform.create(credentialCreationOptions).getAuthenticatorResponse();
    CollectedClientData maliciousClientData = new CollectedClientData(ClientDataType.WEBAUTHN_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, null, false, true);
    assertThrows(BadSignatureException.class, () -> target.validate(registrationRequest, registrationParameters));
}
Also used : Origin(com.webauthn4j.data.client.Origin) ServerProperty(com.webauthn4j.server.ServerProperty) ClientPlatform(com.webauthn4j.test.client.ClientPlatform) CollectedClientDataConverter(com.webauthn4j.converter.CollectedClientDataConverter) Challenge(com.webauthn4j.data.client.challenge.Challenge) DefaultChallenge(com.webauthn4j.data.client.challenge.DefaultChallenge) DefaultChallenge(com.webauthn4j.data.client.challenge.DefaultChallenge) CollectedClientData(com.webauthn4j.data.client.CollectedClientData) FIDOU2FAuthenticatorAdaptor(com.webauthn4j.test.authenticator.u2f.FIDOU2FAuthenticatorAdaptor) AuthenticationExtensionsClientInputs(com.webauthn4j.data.extension.client.AuthenticationExtensionsClientInputs) RegistrationExtensionClientInput(com.webauthn4j.data.extension.client.RegistrationExtensionClientInput) Test(org.junit.jupiter.api.Test)

Example 33 with CollectedClientData

use of com.webauthn4j.data.client.CollectedClientData in project webauthn4j by webauthn4j.

the class UserVerifyingAuthenticatorAuthenticationValidationTest method validate_assertion_with_invalid_tokenBinding_test.

@Test
void validate_assertion_with_invalid_tokenBinding_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);
    byte[] tokenBindingId = new byte[] { 0x01, 0x23, 0x45 };
    CollectedClientData collectedClientData = clientPlatform.createCollectedClientData(ClientDataType.WEBAUTHN_GET, challenge, tokenBindingId);
    PublicKeyCredential<AuthenticatorAssertionResponse, AuthenticationExtensionClientOutput> credential = clientPlatform.get(credentialRequestOptions, collectedClientData);
    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());
    List<byte[]> allowCredentials = null;
    AuthenticationParameters authenticationParameters = new AuthenticationParameters(serverProperty, authenticator, allowCredentials, true);
    AuthenticationData authenticationData = target.parse(webAuthnAuthenticationRequest);
    assertThrows(TokenBindingException.class, () -> target.validate(authenticationData, authenticationParameters));
}
Also used : ServerProperty(com.webauthn4j.server.ServerProperty) Challenge(com.webauthn4j.data.client.challenge.Challenge) DefaultChallenge(com.webauthn4j.data.client.challenge.DefaultChallenge) DefaultChallenge(com.webauthn4j.data.client.challenge.DefaultChallenge) CollectedClientData(com.webauthn4j.data.client.CollectedClientData) AuthenticationExtensionClientOutput(com.webauthn4j.data.extension.client.AuthenticationExtensionClientOutput) AttestationObject(com.webauthn4j.data.attestation.AttestationObject) Authenticator(com.webauthn4j.authenticator.Authenticator) Test(org.junit.jupiter.api.Test)

Example 34 with CollectedClientData

use of com.webauthn4j.data.client.CollectedClientData in project webauthn4j by webauthn4j.

the class UserVerifyingAuthenticatorAuthenticationValidationTest method validate_assertion_with_tokenBinding_test.

@Test
void validate_assertion_with_tokenBinding_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);
    byte[] tokenBindingId = new byte[] { 0x01, 0x23, 0x45 };
    CollectedClientData collectedClientData = clientPlatform.createCollectedClientData(ClientDataType.WEBAUTHN_GET, challenge, tokenBindingId);
    PublicKeyCredential<AuthenticatorAssertionResponse, AuthenticationExtensionClientOutput> credential = clientPlatform.get(credentialRequestOptions, collectedClientData);
    AuthenticatorAssertionResponse authenticationRequest = credential.getAuthenticatorResponse();
    AuthenticationExtensionsClientOutputs<AuthenticationExtensionClientOutput> clientExtensionResults = credential.getClientExtensionResults();
    String clientExtensionJSON = authenticationExtensionsClientOutputsConverter.convertToString(clientExtensionResults);
    ServerProperty serverProperty = new ServerProperty(origin, rpId, challenge, tokenBindingId);
    Authenticator authenticator = TestDataUtil.createAuthenticator(attestationObject);
    AuthenticationRequest webAuthnAuthenticationRequest = new AuthenticationRequest(credential.getRawId(), authenticationRequest.getAuthenticatorData(), authenticationRequest.getClientDataJSON(), clientExtensionJSON, authenticationRequest.getSignature());
    List<byte[]> allowCredentials = null;
    AuthenticationParameters authenticationParameters = new AuthenticationParameters(serverProperty, authenticator, allowCredentials, true);
    AuthenticationData authenticationData = target.parse(webAuthnAuthenticationRequest);
    target.validate(authenticationData, authenticationParameters);
    assertAll(() -> assertThat(authenticationData.getCollectedClientData()).isNotNull(), () -> assertThat(authenticationData.getAuthenticatorData()).isNotNull(), () -> assertThat(authenticationData.getClientExtensions()).isNotNull());
}
Also used : ServerProperty(com.webauthn4j.server.ServerProperty) Challenge(com.webauthn4j.data.client.challenge.Challenge) DefaultChallenge(com.webauthn4j.data.client.challenge.DefaultChallenge) DefaultChallenge(com.webauthn4j.data.client.challenge.DefaultChallenge) CollectedClientData(com.webauthn4j.data.client.CollectedClientData) AuthenticationExtensionClientOutput(com.webauthn4j.data.extension.client.AuthenticationExtensionClientOutput) AttestationObject(com.webauthn4j.data.attestation.AttestationObject) Authenticator(com.webauthn4j.authenticator.Authenticator) Test(org.junit.jupiter.api.Test)

Example 35 with CollectedClientData

use of com.webauthn4j.data.client.CollectedClientData in project webauthn4j by webauthn4j.

the class AuthenticatorImplTest method createFromRegistrationData_test.

@Test
void createFromRegistrationData_test() {
    AttestationObject attestationObject = TestDataUtil.createAttestationObjectWithFIDOU2FAttestationStatement();
    byte[] attestationObjectBytes = new byte[32];
    CollectedClientData collectedClientData = mock(CollectedClientData.class);
    byte[] collectedClientDataBytes = new byte[128];
    AuthenticationExtensionsClientOutputs<RegistrationExtensionClientOutput> authenticationExtensionsClientOutputs = new AuthenticationExtensionsClientOutputs.BuilderForRegistration().build();
    Set<AuthenticatorTransport> transports = Collections.emptySet();
    RegistrationData registrationData = new RegistrationData(attestationObject, attestationObjectBytes, collectedClientData, collectedClientDataBytes, authenticationExtensionsClientOutputs, transports);
    AuthenticatorImpl authenticator = AuthenticatorImpl.createFromRegistrationData(registrationData);
    assertThat(authenticator.getAttestedCredentialData()).isEqualTo(attestationObject.getAuthenticatorData().getAttestedCredentialData());
    assertThat(authenticator.getAttestationStatement()).isEqualTo(attestationObject.getAttestationStatement());
    assertThat(authenticator.getTransports()).isEqualTo(transports);
    assertThat(authenticator.getCounter()).isEqualTo(attestationObject.getAuthenticatorData().getSignCount());
    assertThat(authenticator.getAuthenticatorExtensions()).isEqualTo(attestationObject.getAuthenticatorData().getExtensions());
    assertThat(authenticator.getClientExtensions()).isEqualTo(authenticationExtensionsClientOutputs);
}
Also used : RegistrationData(com.webauthn4j.data.RegistrationData) CollectedClientData(com.webauthn4j.data.client.CollectedClientData) AttestationObject(com.webauthn4j.data.attestation.AttestationObject) AuthenticationExtensionsClientOutputs(com.webauthn4j.data.extension.client.AuthenticationExtensionsClientOutputs) RegistrationExtensionClientOutput(com.webauthn4j.data.extension.client.RegistrationExtensionClientOutput) AuthenticatorTransport(com.webauthn4j.data.AuthenticatorTransport) Test(org.junit.jupiter.api.Test)

Aggregations

CollectedClientData (com.webauthn4j.data.client.CollectedClientData)56 Test (org.junit.jupiter.api.Test)33 ServerProperty (com.webauthn4j.server.ServerProperty)30 AttestationObject (com.webauthn4j.data.attestation.AttestationObject)23 RegistrationExtensionClientOutput (com.webauthn4j.data.extension.client.RegistrationExtensionClientOutput)19 Origin (com.webauthn4j.data.client.Origin)17 AuthenticationExtensionsClientOutputs (com.webauthn4j.data.extension.client.AuthenticationExtensionsClientOutputs)16 DefaultChallenge (com.webauthn4j.data.client.challenge.DefaultChallenge)14 AuthenticationExtensionClientOutput (com.webauthn4j.data.extension.client.AuthenticationExtensionClientOutput)11 Challenge (com.webauthn4j.data.client.challenge.Challenge)10 AuthenticatorTransport (com.webauthn4j.data.AuthenticatorTransport)8 RegistrationObject (com.webauthn4j.validator.RegistrationObject)8 ParameterizedTest (org.junit.jupiter.params.ParameterizedTest)8 DCRegistrationObject (com.webauthn4j.appattest.validator.DCRegistrationObject)7 Authenticator (com.webauthn4j.authenticator.Authenticator)7 CollectedClientDataConverter (com.webauthn4j.converter.CollectedClientDataConverter)7 AuthenticationExtensionAuthenticatorOutput (com.webauthn4j.data.extension.authenticator.AuthenticationExtensionAuthenticatorOutput)7 CoreRegistrationObject (com.webauthn4j.validator.CoreRegistrationObject)7 Test (org.junit.Test)5 RegistrationData (com.webauthn4j.data.RegistrationData)4