use of com.webauthn4j.data.extension.authenticator.AuthenticationExtensionsAuthenticatorOutputs in project webauthn4j by webauthn4j.
the class WebAuthnModelAuthenticator method getAssertion.
public GetAssertionResponse getAssertion(GetAssertionRequest getAssertionRequest, AuthenticationEmulationOption authenticationEmulationOption) {
byte flags = 0;
// Check if all the supplied parameters are syntactically well-formed and of the correct length.
// If not, return an error code equivalent to "UnknownError" and terminate the operation.
// TODO
// Let credentialOptions be a new empty set of public key credential sources.
List<PublicKeyCredentialSource> credentialOptions = new ArrayList<>();
// If allowCredentialDescriptorList was supplied, then for each descriptor of allowCredentialDescriptorList:
List<PublicKeyCredentialDescriptor> allowCredentialDescriptorList = getAssertionRequest.getAllowCredentialDescriptorList();
if (allowCredentialDescriptorList != null && !allowCredentialDescriptorList.isEmpty()) {
for (PublicKeyCredentialDescriptor credentialDescriptor : getAssertionRequest.getAllowCredentialDescriptorList()) {
// Let credSource be the result of looking up descriptor.id in this authenticator.
PublicKeyCredentialSource credSource = lookup(credentialDescriptor.getId());
if (credSource != null) {
credentialOptions.add(credSource);
}
}
} else // Otherwise (allowCredentialDescriptorList was not supplied),
// for each key -> credSource of this authenticator’s credentials map, append credSource to credentialOptions.
{
for (Map.Entry<CredentialMapKey, PublicKeyCredentialSource> entry : credentialMap.entrySet()) {
credentialOptions.add(entry.getValue());
}
}
// Remove any items from credentialOptions whose rpId is not equal to rpId.
credentialOptions = credentialOptions.stream().filter(item -> item.getRpId().equals(getAssertionRequest.getRpId())).collect(Collectors.toList());
// If credentialOptions is now empty, return an error code equivalent to "NotAllowedError" and terminate the operation.
if (credentialOptions.isEmpty()) {
throw new NotAllowedException("No matching authenticator found");
}
// If requireUserVerification is true, the method of obtaining user consent MUST include user verification.
if (getAssertionRequest.isRequireUserVerification()) {
flags |= BIT_UV;
}
// If requireUserPresence is true, the method of obtaining user consent MUST include a test of user presence.
if (getAssertionRequest.isRequireUserPresence()) {
flags |= BIT_UP;
}
// If the user does not consent, return an error code equivalent to "NotAllowedError" and terminate the operation.
// TODO
PublicKeyCredentialSource selectedCredential = credentialOptions.get(0);
// Let processedExtensions be the result of authenticator extension processing for each supported
// extension identifier -> authenticator extension input in extensions.
AuthenticationExtensionsAuthenticatorOutputs<AuthenticationExtensionAuthenticatorOutput> processedExtensions = new AuthenticationExtensionsAuthenticatorOutputs<>();
if (!processedExtensions.getKeys().isEmpty()) {
flags |= BIT_ED;
}
// Increment the RP ID-associated signature counter or the global signature counter value,
// depending on which approach is implemented by the authenticator, by some positive value.
countUp();
// Let authenticatorData be the byte array specified in §6.1 Authenticator data including processedExtensions,
// if any, as the extensions and excluding attestedCredentialData.
byte[] rpIdHash = MessageDigestUtil.createSHA256().digest(getAssertionRequest.getRpId().getBytes(StandardCharsets.UTF_8));
AuthenticatorData<AuthenticationExtensionAuthenticatorOutput> authenticatorDataObject = new AuthenticatorData<>(rpIdHash, flags, counter, processedExtensions);
byte[] authenticatorData = authenticatorDataConverter.convert(authenticatorDataObject);
// Let signature be the assertion signature of the concatenation authenticatorData || hash using
// the privateKey of selectedCredential as shown in Figure 2, below. A simple, undelimited concatenation is
// safe to use here because the authenticator data describes its own length.
// The hash of the serialized client data (which potentially has a variable length) is always the last element.
byte[] clientDataHash = getAssertionRequest.getHash();
byte[] signedData = ByteBuffer.allocate(authenticatorData.length + clientDataHash.length).put(authenticatorData).put(clientDataHash).array();
byte[] signature = TestDataUtil.calculateSignature(selectedCredential.getPrivateKey().getPrivateKey(), signedData);
// If any error occurred while generating the assertion signature,
// return an error code equivalent to "UnknownError" and terminate the operation.
// Return to the user agent:
GetAssertionResponse getAssertionResponse = new GetAssertionResponse();
getAssertionResponse.setCredentialId(selectedCredential.getId());
getAssertionResponse.setAuthenticatorData(authenticatorData);
getAssertionResponse.setSignature(signature);
getAssertionResponse.setUserHandle(selectedCredential.getUserHandle());
return getAssertionResponse;
}
use of com.webauthn4j.data.extension.authenticator.AuthenticationExtensionsAuthenticatorOutputs in project webauthn4j by webauthn4j.
the class AuthenticatorDataConverter method convertToExtensions.
@Nullable
<T extends ExtensionAuthenticatorOutput> AuthenticationExtensionsAuthenticatorOutputs<T> convertToExtensions(@NonNull ByteBuffer byteBuffer) {
// Since convertToExtensions is called when ED flag is set, return empty AuthenticationExtensionsAuthenticatorOutputs even when remaining is zero.
if (byteBuffer.remaining() == 0) {
return new AuthenticationExtensionsAuthenticatorOutputs<>();
}
byte[] remaining = new byte[byteBuffer.remaining()];
byteBuffer.get(remaining);
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(remaining);
AuthenticationExtensionsAuthenticatorOutputsEnvelope<T> envelope = cborConverter.readValue(byteArrayInputStream, new TypeReference<AuthenticationExtensionsAuthenticatorOutputsEnvelope<T>>() {
});
if (envelope == null) {
return null;
}
int leftoverLength = remaining.length - envelope.getLength();
byteBuffer.position(byteBuffer.position() - leftoverLength);
return envelope.getAuthenticationExtensionsAuthenticatorOutputs();
}
use of com.webauthn4j.data.extension.authenticator.AuthenticationExtensionsAuthenticatorOutputs in project webauthn4j by webauthn4j.
the class AuthenticatorImplTest method getter_setter_test.
@Test
void getter_setter_test() {
AttestedCredentialData attestedCredentialData = TestDataUtil.createAttestedCredentialData();
AttestationStatement attestationStatement = TestAttestationStatementUtil.createFIDOU2FAttestationStatement();
AuthenticatorImpl authenticator = new AuthenticatorImpl(TestDataUtil.createAttestedCredentialData(), TestAttestationStatementUtil.createBasicPackedAttestationStatement(), 0);
AuthenticationExtensionsAuthenticatorOutputs<RegistrationExtensionAuthenticatorOutput> authenticatorExtensions = new AuthenticationExtensionsAuthenticatorOutputs<>();
AuthenticationExtensionsClientOutputs<RegistrationExtensionClientOutput> clientExtensions = new AuthenticationExtensionsClientOutputs<>();
Set<AuthenticatorTransport> transports = Collections.singleton(AuthenticatorTransport.USB);
authenticator.setAttestedCredentialData(attestedCredentialData);
authenticator.setAttestationStatement(attestationStatement);
authenticator.setTransports(transports);
authenticator.setCounter(1);
authenticator.setAuthenticatorExtensions(authenticatorExtensions);
authenticator.setClientExtensions(clientExtensions);
assertAll(() -> assertThat(authenticator.getAttestedCredentialData()).isEqualTo(attestedCredentialData), () -> assertThat(authenticator.getAttestationStatement()).isEqualTo(attestationStatement), () -> assertThat(authenticator.getTransports()).isEqualTo(transports), () -> assertThat(authenticator.getCounter()).isEqualTo(1), () -> assertThat(authenticator.getAuthenticatorExtensions()).isEqualTo(authenticatorExtensions), () -> assertThat(authenticator.getClientExtensions()).isEqualTo(clientExtensions));
}
Aggregations