Skip to content

Commit

Permalink
Merge pull request #1359 from /issues/1289-check-duplicate-registration
Browse files Browse the repository at this point in the history
Fix #1289: FIDO2: Do not allow duplicate registration of same authenticator
  • Loading branch information
romanstrobl authored Feb 28, 2024
2 parents c509e3c + 9af222e commit 8079e11
Show file tree
Hide file tree
Showing 3 changed files with 15 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ public RegistrationResponse register(RegistrationRequest requestObject) throws E
throw new Fido2AuthenticationFailedException(error);
}

final String authenticatorId = requestObject.getAuthenticatorParameters().getId();
final AuthenticatorAttestationResponse response = requestObject.getAuthenticatorParameters().getResponse();

final CollectedClientData clientDataJSON = response.getClientDataJSON();
Expand All @@ -130,7 +131,7 @@ public RegistrationResponse register(RegistrationRequest requestObject) throws E
final String fmt = attestationObject.getFmt();
final byte[] aaguid = attestationObject.getAuthData().getAttestedCredentialData().getAaguid();

validateRegistrationRequest(applicationId, fmt, aaguid, challengeValue);
validateRegistrationRequest(applicationId, authenticatorId, fmt, aaguid, challengeValue);

if (Fmt.FMT_PACKED.getValue().equals(fmt)) {
final boolean verifySignature = cryptographyService.verifySignatureForRegistration(applicationId, clientDataJSON, authData, signature, attestedCredentialData);
Expand All @@ -151,8 +152,8 @@ public RegistrationResponse register(RegistrationRequest requestObject) throws E
return registrationConverter.convertRegistrationResponse(authenticatorDetailResponse);
}

private void validateRegistrationRequest(final String applicationId, final String attestationFormat, final byte[] aaguid, final String challengeValue) throws Exception {
if (!registrationProvider.registrationAllowed(applicationId, attestationFormat, aaguid)) {
private void validateRegistrationRequest(final String applicationId, final String authenticatorId, final String attestationFormat, final byte[] aaguid, final String challengeValue) throws Exception {
if (!registrationProvider.registrationAllowed(applicationId, authenticatorId, attestationFormat, aaguid)) {
logger.warn("Invalid request for FIDO2 registration");
// Immediately revoke the challenge
registrationProvider.revokeRegistrationByChallengeValue(applicationId, challengeValue);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,12 @@ public interface RegistrationProvider {
/**
* Verify registration parameters and determine whether registration is allowed.
* @param applicationId Application ID.
* @param authenticatorId Authenticator ID.
* @param attestationFormat FIDO2 registration attestation format.
* @param aaguid FIDO2 registration AAGUID value.
* @return Whether registration is allowed.
* @throws Exception In case any issue occur during processing.
*/
boolean registrationAllowed(String applicationId, String attestationFormat, byte[] aaguid) throws Exception;
boolean registrationAllowed(String applicationId, String authenticatorId, String attestationFormat, byte[] aaguid) throws Exception;

}
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import io.getlime.security.powerauth.app.server.database.model.entity.ActivationRecordEntity;
import io.getlime.security.powerauth.app.server.database.model.entity.ApplicationEntity;
import io.getlime.security.powerauth.app.server.database.model.enumeration.ActivationStatus;
import io.getlime.security.powerauth.app.server.database.repository.ActivationRepository;
import io.getlime.security.powerauth.app.server.service.behavior.ServiceBehaviorCatalogue;
import io.getlime.security.powerauth.app.server.service.behavior.tasks.ApplicationConfigServiceBehavior;
import io.getlime.security.powerauth.app.server.service.exceptions.GenericServiceException;
Expand Down Expand Up @@ -152,7 +153,7 @@ public void revokeRegistrationByChallengeValue(String applicationId, String chal

@Override
@Transactional(readOnly = true)
public boolean registrationAllowed(String applicationId, String attestationFormat, byte[] aaguid) throws Exception {
public boolean registrationAllowed(String applicationId, String authenticatorId, String attestationFormat, byte[] aaguid) throws Exception {
final ApplicationConfigServiceBehavior configService = serviceBehaviorCatalogue.getApplicationConfigServiceBehavior();
final GetApplicationConfigRequest configRequest = new GetApplicationConfigRequest();
configRequest.setApplicationId(applicationId);
Expand All @@ -175,14 +176,20 @@ public boolean registrationAllowed(String applicationId, String attestationForma
.findFirst();

if (configAaguids.isPresent()) {
System.out.println(aaguidStr);
List<String> allowedAaguids = configAaguids.get().getValues();
if (!allowedAaguids.contains(aaguidStr)) {
logger.warn("Rejected AAGUID value for FIDO2 registration: {}", aaguidStr);
return false;
}
}

final ActivationRepository activationRepository = repositoryCatalogue.getActivationRepository();
final List<ActivationRecordEntity> existingActivations = activationRepository.findByExternalId(applicationId, authenticatorId);
if (!existingActivations.isEmpty()) {
logger.warn("Rejected duplicate external ID for registration, application ID: {}, external ID: {}", applicationId, authenticatorId);
return false;
}

return true;
}
}

0 comments on commit 8079e11

Please sign in to comment.