use of com.webauthn4j.data.extension.client.RegistrationExtensionClientOutput in project webauthn4j by webauthn4j.
the class WebAuthnRegistrationManager method parse.
@SuppressWarnings("squid:S1130")
@NonNull
public RegistrationData parse(@NonNull RegistrationRequest registrationRequest) throws DataConversionException {
AssertUtil.notNull(registrationRequest, "registrationRequest must not be null");
byte[] clientDataBytes = registrationRequest.getClientDataJSON();
byte[] attestationObjectBytes = registrationRequest.getAttestationObject();
CollectedClientData collectedClientData = clientDataBytes == null ? null : collectedClientDataConverter.convert(clientDataBytes);
AttestationObject attestationObject = attestationObjectBytes == null ? null : attestationObjectConverter.convert(attestationObjectBytes);
Set<AuthenticatorTransport> transports = registrationRequest.getTransports() == null ? null : authenticatorTransportConverter.convertSet(registrationRequest.getTransports());
AuthenticationExtensionsClientOutputs<RegistrationExtensionClientOutput> clientExtensions = registrationRequest.getClientExtensionsJSON() == null ? null : authenticationExtensionsClientOutputsConverter.convert(registrationRequest.getClientExtensionsJSON());
return new RegistrationData(attestationObject, attestationObjectBytes, collectedClientData, clientDataBytes, clientExtensions, transports);
}
use of com.webauthn4j.data.extension.client.RegistrationExtensionClientOutput in project webauthn4j-spring-security by webauthn4j.
the class WebAuthnRegistrationRequestValidationResponseTest method getter_test.
@Test
public void getter_test() {
CollectedClientData clientData = TestDataUtil.createClientData(ClientDataType.WEBAUTHN_CREATE);
AttestationObject attestationObject = TestDataUtil.createAttestationObjectWithFIDOU2FAttestationStatement();
AuthenticationExtensionsClientOutputs<RegistrationExtensionClientOutput> clientExtensions = new AuthenticationExtensionsClientOutputs<>();
Set<AuthenticatorTransport> transports = new HashSet<>();
WebAuthnRegistrationRequestValidationResponse instance = new WebAuthnRegistrationRequestValidationResponse(clientData, attestationObject, clientExtensions, transports);
assertThat(instance.getCollectedClientData()).isEqualTo(clientData);
assertThat(instance.getAttestationObject()).isEqualTo(attestationObject);
assertThat(instance.getRegistrationExtensionsClientOutputs()).isEqualTo(clientExtensions);
assertThat(instance.getTransports()).isEqualTo(transports);
}
use of com.webauthn4j.data.extension.client.RegistrationExtensionClientOutput in project webauthn4j-spring-security by webauthn4j.
the class WebAuthnRegistrationRequestValidatorTest method validate_test.
@Test
public void validate_test() {
WebAuthnRegistrationRequestValidator target = new WebAuthnRegistrationRequestValidator(webAuthnManager, serverPropertyProvider);
ServerProperty serverProperty = mock(ServerProperty.class);
when(serverPropertyProvider.provide(any())).thenReturn(serverProperty);
CollectedClientData collectedClientData = mock(CollectedClientData.class);
AttestationObject attestationObject = mock(AttestationObject.class);
AuthenticationExtensionsClientOutputs<RegistrationExtensionClientOutput> clientExtensionOutputs = new AuthenticationExtensionsClientOutputs<>();
when(webAuthnManager.validate(any(RegistrationRequest.class), any(RegistrationParameters.class))).thenReturn(new RegistrationData(attestationObject, null, collectedClientData, null, clientExtensionOutputs, null));
MockHttpServletRequest mockHttpServletRequest = new MockHttpServletRequest();
mockHttpServletRequest.setScheme("https");
mockHttpServletRequest.setServerName("example.com");
mockHttpServletRequest.setServerPort(443);
String clientDataBase64 = "clientDataBase64";
String attestationObjectBase64 = "attestationObjectBase64";
Set<String> transports = Collections.emptySet();
String clientExtensionsJSON = "clientExtensionsJSON";
target.validate(mockHttpServletRequest, clientDataBase64, attestationObjectBase64, transports, clientExtensionsJSON);
ArgumentCaptor<RegistrationRequest> registrationRequestArgumentCaptor = ArgumentCaptor.forClass(RegistrationRequest.class);
ArgumentCaptor<RegistrationParameters> registrationParametersArgumentCaptor = ArgumentCaptor.forClass(RegistrationParameters.class);
verify(webAuthnManager).validate(registrationRequestArgumentCaptor.capture(), registrationParametersArgumentCaptor.capture());
RegistrationRequest registrationRequest = registrationRequestArgumentCaptor.getValue();
RegistrationParameters registrationParameters = registrationParametersArgumentCaptor.getValue();
assertThat(registrationRequest.getClientDataJSON()).isEqualTo(Base64UrlUtil.decode(clientDataBase64));
assertThat(registrationRequest.getAttestationObject()).isEqualTo(Base64UrlUtil.decode(attestationObjectBase64));
assertThat(registrationRequest.getClientExtensionsJSON()).isEqualTo(clientExtensionsJSON);
assertThat(registrationParameters.getServerProperty()).isEqualTo(serverProperty);
}
use of com.webauthn4j.data.extension.client.RegistrationExtensionClientOutput 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);
}
}
use of com.webauthn4j.data.extension.client.RegistrationExtensionClientOutput in project webauthn4j by webauthn4j.
the class TPMAuthenticatorRegistrationValidationTest method validate_RegistrationContext_with_tpm_attestation_statement_test.
@Test
void validate_RegistrationContext_with_tpm_attestation_statement_test() {
String rpId = "example.com";
Challenge challenge = new DefaultChallenge();
AuthenticatorSelectionCriteria authenticatorSelectionCriteria = new AuthenticatorSelectionCriteria(AuthenticatorAttachment.CROSS_PLATFORM, true, UserVerificationRequirement.REQUIRED);
PublicKeyCredentialParameters publicKeyCredentialParameters = new PublicKeyCredentialParameters(PublicKeyCredentialType.PUBLIC_KEY, COSEAlgorithmIdentifier.ES256);
PublicKeyCredentialUserEntity publicKeyCredentialUserEntity = new PublicKeyCredentialUserEntity(new byte[32], "username", "displayName");
AuthenticationExtensionsClientInputs<RegistrationExtensionClientInput> extensions = new AuthenticationExtensionsClientInputs<>();
PublicKeyCredentialCreationOptions credentialCreationOptions = new PublicKeyCredentialCreationOptions(new PublicKeyCredentialRpEntity(rpId, "example.com"), publicKeyCredentialUserEntity, challenge, Collections.singletonList(publicKeyCredentialParameters), null, Collections.emptyList(), authenticatorSelectionCriteria, AttestationConveyancePreference.DIRECT, extensions);
PublicKeyCredential<AuthenticatorAttestationResponse, RegistrationExtensionClientOutput> credential = clientPlatform.create(credentialCreationOptions);
AuthenticatorAttestationResponse authenticatorAttestationResponse = credential.getAuthenticatorResponse();
AuthenticationExtensionsClientOutputs<RegistrationExtensionClientOutput> clientExtensionResults = credential.getClientExtensionResults();
Set<String> transports = Collections.emptySet();
String clientExtensionJSON = authenticationExtensionsClientOutputsConverter.convertToString(clientExtensionResults);
ServerProperty serverProperty = new ServerProperty(origin, rpId, challenge, null);
RegistrationRequest registrationRequest = new RegistrationRequest(authenticatorAttestationResponse.getAttestationObject(), authenticatorAttestationResponse.getClientDataJSON(), clientExtensionJSON, transports);
RegistrationParameters registrationParameters = new RegistrationParameters(serverProperty, null, false, true);
RegistrationData response = target.validate(registrationRequest, registrationParameters);
assertAll(() -> assertThat(response.getCollectedClientData()).isNotNull(), () -> assertThat(response.getAttestationObject()).isNotNull(), () -> assertThat(response.getClientExtensions()).isNotNull());
}
Aggregations