diff --git a/jans-fido2/model/src/main/java/io/jans/fido2/model/assertion/AssertionOptions.java b/jans-fido2/model/src/main/java/io/jans/fido2/model/assertion/AssertionOptions.java index a73b3bb8f5c..4724a802595 100644 --- a/jans-fido2/model/src/main/java/io/jans/fido2/model/assertion/AssertionOptions.java +++ b/jans-fido2/model/src/main/java/io/jans/fido2/model/assertion/AssertionOptions.java @@ -3,10 +3,10 @@ import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.JsonNode; -import io.jans.fido2.model.common.SuperGluuSupport; + import io.jans.orm.model.fido2.UserVerification; @JsonIgnoreProperties(ignoreUnknown = true) -public class AssertionOptions extends SuperGluuSupport { +public class AssertionOptions { private String username; private UserVerification userVerification; private String documentDomain; diff --git a/jans-fido2/model/src/main/java/io/jans/fido2/model/assertion/AssertionResult.java b/jans-fido2/model/src/main/java/io/jans/fido2/model/assertion/AssertionResult.java index 390d7345d3f..04e029f427f 100644 --- a/jans-fido2/model/src/main/java/io/jans/fido2/model/assertion/AssertionResult.java +++ b/jans-fido2/model/src/main/java/io/jans/fido2/model/assertion/AssertionResult.java @@ -2,9 +2,8 @@ import com.google.common.base.Strings; import io.jans.fido2.model.common.PublicKeyCredentialType; -import io.jans.fido2.model.common.SuperGluuSupport; -public class AssertionResult extends SuperGluuSupport { +public class AssertionResult { private String id; private String type = PublicKeyCredentialType.PUBLIC_KEY.getKeyName(); private String rawId; diff --git a/jans-fido2/model/src/main/java/io/jans/fido2/model/attestation/AttestationOptions.java b/jans-fido2/model/src/main/java/io/jans/fido2/model/attestation/AttestationOptions.java index 3657cd9207b..6531ccd0392 100644 --- a/jans-fido2/model/src/main/java/io/jans/fido2/model/attestation/AttestationOptions.java +++ b/jans-fido2/model/src/main/java/io/jans/fido2/model/attestation/AttestationOptions.java @@ -6,11 +6,11 @@ import com.fasterxml.jackson.databind.JsonNode; import io.jans.fido2.ctap.AttestationConveyancePreference; import io.jans.fido2.ctap.AuthenticatorAttachment; -import io.jans.fido2.model.common.SuperGluuSupport; + @JsonIgnoreProperties(ignoreUnknown = true) @JsonInclude(JsonInclude.Include.NON_NULL) -public class AttestationOptions extends SuperGluuSupport { +public class AttestationOptions { private String username ; private String displayName; private AttestationConveyancePreference attestation; diff --git a/jans-fido2/model/src/main/java/io/jans/fido2/model/attestation/AttestationResult.java b/jans-fido2/model/src/main/java/io/jans/fido2/model/attestation/AttestationResult.java index c76526a15dc..4108634ce02 100644 --- a/jans-fido2/model/src/main/java/io/jans/fido2/model/attestation/AttestationResult.java +++ b/jans-fido2/model/src/main/java/io/jans/fido2/model/attestation/AttestationResult.java @@ -1,9 +1,9 @@ package io.jans.fido2.model.attestation; import io.jans.fido2.model.common.PublicKeyCredentialType; -import io.jans.fido2.model.common.SuperGluuSupport; -public class AttestationResult extends SuperGluuSupport { + +public class AttestationResult { private String id; private String type = PublicKeyCredentialType.PUBLIC_KEY.getKeyName(); private Response response; diff --git a/jans-fido2/model/src/main/java/io/jans/fido2/model/common/SuperGluuSupport.java b/jans-fido2/model/src/main/java/io/jans/fido2/model/common/SuperGluuSupport.java deleted file mode 100644 index f585799d86f..00000000000 --- a/jans-fido2/model/src/main/java/io/jans/fido2/model/common/SuperGluuSupport.java +++ /dev/null @@ -1,61 +0,0 @@ -package io.jans.fido2.model.common; - -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.annotation.JsonProperty; - -@JsonInclude(JsonInclude.Include.NON_NULL) -@JsonIgnoreProperties(ignoreUnknown = true) -abstract public class SuperGluuSupport { - - @JsonProperty(value = "super_gluu_app_id") - private String superGluuAppId; - @JsonProperty(value = "super_gluu_request_mode") - private String superGluuRequestMode; - @JsonProperty(value = "super_gluu_request") - private Boolean superGluuRequest; - @JsonProperty(value = "super_gluu_key_handle") - private String superGluuKeyHandle; - @JsonProperty(value = "super_gluu_request_cancel") - private Boolean superGluuRequestCancel; - - public String getSuperGluuAppId() { - return superGluuAppId; - } - - public void setSuperGluuAppId(String superGluuAppId) { - this.superGluuAppId = superGluuAppId; - } - - public String getSuperGluuRequestMode() { - return superGluuRequestMode; - } - - public void setSuperGluuRequestMode(String superGluuRequestMode) { - this.superGluuRequestMode = superGluuRequestMode; - } - - public Boolean getSuperGluuRequest() { - return superGluuRequest; - } - - public void setSuperGluuRequest(Boolean superGluuRequest) { - this.superGluuRequest = superGluuRequest; - } - - public String getSuperGluuKeyHandle() { - return superGluuKeyHandle; - } - - public void setSuperGluuKeyHandle(String superGluuKeyHandle) { - this.superGluuKeyHandle = superGluuKeyHandle; - } - - public Boolean getSuperGluuRequestCancel() { - return superGluuRequestCancel; - } - - public void setSuperGluuRequestCancel(Boolean superGluuRequestCancel) { - this.superGluuRequestCancel = superGluuRequestCancel; - } -} diff --git a/jans-fido2/model/src/main/java/io/jans/fido2/model/conf/AppConfiguration.java b/jans-fido2/model/src/main/java/io/jans/fido2/model/conf/AppConfiguration.java index 80bc7a68769..1908469b886 100644 --- a/jans-fido2/model/src/main/java/io/jans/fido2/model/conf/AppConfiguration.java +++ b/jans-fido2/model/src/main/java/io/jans/fido2/model/conf/AppConfiguration.java @@ -71,8 +71,6 @@ public class AppConfiguration implements Configuration, Serializable { @DocProperty(description = "Custom object class list for dynamic person enrolment") private List personCustomObjectClassList; - @DocProperty(description = "Boolean value to enable disable Super Gluu extension") - private boolean superGluuEnabled; @DocProperty(description = "Boolean value specifying whether to persist session_id in cache", defaultValue = "false") private Boolean sessionIdPersistInCache = false; @@ -197,14 +195,7 @@ public void setFido2Configuration(Fido2Configuration fido2Configuration) { this.fido2Configuration = fido2Configuration; } - public boolean isSuperGluuEnabled() { - return superGluuEnabled; - } - - public void setSuperGluuEnabled(boolean superGluuEnabled) { - this.superGluuEnabled = superGluuEnabled; - } - + public Boolean getSessionIdPersistInCache() { if (sessionIdPersistInCache == null) sessionIdPersistInCache = false; return sessionIdPersistInCache; diff --git a/jans-fido2/model/src/main/java/io/jans/fido2/model/conf/Fido2Configuration.java b/jans-fido2/model/src/main/java/io/jans/fido2/model/conf/Fido2Configuration.java index 2f1b0475bab..e2f656352f1 100644 --- a/jans-fido2/model/src/main/java/io/jans/fido2/model/conf/Fido2Configuration.java +++ b/jans-fido2/model/src/main/java/io/jans/fido2/model/conf/Fido2Configuration.java @@ -216,6 +216,6 @@ public Fido2Configuration(String authenticatorCertsFolder, String mdsAccessToken } - + public Fido2Configuration() {} } diff --git a/jans-fido2/model/src/main/java/io/jans/fido2/sg/SuperGluuMode.java b/jans-fido2/model/src/main/java/io/jans/fido2/sg/SuperGluuMode.java deleted file mode 100644 index 3a84021cfb5..00000000000 --- a/jans-fido2/model/src/main/java/io/jans/fido2/sg/SuperGluuMode.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Janssen Project software is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text. - * - * Copyright (c) 2020, Janssen Project - */ - -package io.jans.fido2.sg; - -import java.util.HashMap; -import java.util.Map; - -/** - * @author Yuriy Movchan - * @version January 24, 2023 - */ -public enum SuperGluuMode { - - ONE_STEP("one_step"), - TWO_STEP("two_step"); - - private final String mode; - - private static Map KEY_MAPPINGS = new HashMap<>(); - - static { - for (SuperGluuMode enumType : values()) { - KEY_MAPPINGS.put(enumType.getMode(), enumType); - } - } - - SuperGluuMode(String mode) { - this.mode = mode; - } - - public String getMode() { - return mode; - } - - public static SuperGluuMode fromModeValue(String attachment) { - return KEY_MAPPINGS.get(attachment); - } - -} diff --git a/jans-fido2/server/src/main/java/io/jans/fido2/service/operation/AssertionService.java b/jans-fido2/server/src/main/java/io/jans/fido2/service/operation/AssertionService.java index f51cc4738d4..7f8f4241a3b 100644 --- a/jans-fido2/server/src/main/java/io/jans/fido2/service/operation/AssertionService.java +++ b/jans-fido2/server/src/main/java/io/jans/fido2/service/operation/AssertionService.java @@ -124,17 +124,10 @@ public AssertionOptionsResponse options(AssertionOptions assertionOptions) { ExternalFido2Context externalFido2InterceptionContext = new ExternalFido2Context(CommonUtilService.toJsonNode(assertionOptions), httpRequest, httpResponse); boolean externalInterceptContext = externalFido2InterceptionService.authenticateAssertionStart(CommonUtilService.toJsonNode(assertionOptions), externalFido2InterceptionContext); - boolean superGluu = commonVerifiers.hasSuperGluu(CommonUtilService.toJsonNode(assertionOptions)); - boolean oneStep = commonVerifiers.isSuperGluuOneStepMode(CommonUtilService.toJsonNode(assertionOptions)); // Verify request parameters - String username = null; - if (!(superGluu && oneStep)) { - commonVerifiers.verifyAssertionOptions(assertionOptions); - - // Get username - username = assertionOptions.getUsername();//commonVerifiers.verifyThatFieldString(params, "username"); - } + String username = assertionOptions.getUsername();//commonVerifiers.verifyThatFieldString(params, "username"); + // Create result object //ObjectNode optionsResponseNode = dataMapperService.createObjectNode(); @@ -156,17 +149,9 @@ public AssertionOptionsResponse options(AssertionOptions assertionOptions) { String applicationId = documentDomain; - if (superGluu && !Strings.isNullOrEmpty(assertionOptions.getSuperGluuAppId())) { - applicationId = assertionOptions.getSuperGluuAppId(); - } - - String requestedKeyHandle = null; - if (superGluu && !Strings.isNullOrEmpty(assertionOptions.getSuperGluuKeyHandle())) { - requestedKeyHandle = assertionOptions.getSuperGluuKeyHandle(); - } - + // Put allowCredentials - Pair, String> allowedCredentialsPair = prepareAllowedCredentials(applicationId, username, requestedKeyHandle, superGluu); + Pair, String> allowedCredentialsPair = prepareAllowedCredentials(applicationId, username); List allowedCredentials = allowedCredentialsPair.getLeft(); if (allowedCredentials.isEmpty()) { throw errorResponseFactory.badRequestException(AssertionErrorResponseType.KEYS_NOT_FOUND, "Can't find associated key(s). Username: " + username); @@ -206,16 +191,13 @@ public AssertionOptionsResponse options(AssertionOptions assertionOptions) { entity.setDomain(documentDomain); entity.setUserVerificationOption(userVerification); entity.setStatus(Fido2AuthenticationStatus.pending); - if (!Strings.isNullOrEmpty(assertionOptions.getSuperGluuAppId())) { - entity.setApplicationId(assertionOptions.getSuperGluuAppId()); - } else { - entity.setApplicationId(documentDomain); - } + entity.setApplicationId(documentDomain); + // Store original request entity.setAssertionRequest(CommonUtilService.toJsonNode(assertionOptions).toString()); - Fido2AuthenticationEntry authenticationEntity = authenticationPersistenceService.buildFido2AuthenticationEntry(entity, oneStep); + Fido2AuthenticationEntry authenticationEntity = authenticationPersistenceService.buildFido2AuthenticationEntry(entity); if (!Strings.isNullOrEmpty(assertionOptions.getSessionId())) { authenticationEntity.setSessionStateId(assertionOptions.getSessionId()); } @@ -277,7 +259,7 @@ public AsserOptGenerateResponse generateOptions(AssertionOptionsGenerate asserti // Store original request entity.setAssertionRequest(CommonUtilService.toJsonNode(assertionOptionsGenerate).toString()); - Fido2AuthenticationEntry authenticationEntity = authenticationPersistenceService.buildFido2AuthenticationEntry(entity, true); + Fido2AuthenticationEntry authenticationEntity = authenticationPersistenceService.buildFido2AuthenticationEntry(entity); if (!Strings.isNullOrEmpty(assertionOptionsGenerate.getSessionId())) { authenticationEntity.setSessionStateId(assertionOptionsGenerate.getSessionId()); } @@ -298,9 +280,6 @@ public AttestationOrAssertionResponse verify(AssertionResult assertionResult) { ExternalFido2Context externalFido2InterceptionContext = new ExternalFido2Context(CommonUtilService.toJsonNode(assertionResult), httpRequest, httpResponse); boolean externalInterceptContext = externalFido2InterceptionService.verifyAssertionStart(CommonUtilService.toJsonNode(assertionResult), externalFido2InterceptionContext); - boolean superGluu = commonVerifiers.hasSuperGluu(CommonUtilService.toJsonNode(assertionResult)); - boolean oneStep = commonVerifiers.isSuperGluuOneStepMode(CommonUtilService.toJsonNode(assertionResult)); - boolean cancelRequest = commonVerifiers.isSuperGluuCancelRequest(CommonUtilService.toJsonNode(assertionResult)); // Verify if there are mandatory request parameters commonVerifiers.verifyBasicPayload(assertionResult); @@ -316,15 +295,13 @@ public AttestationOrAssertionResponse verify(AssertionResult assertionResult) { } // Verify client data JsonNode clientJsonNode = commonVerifiers.verifyClientJSON(response.getClientDataJSON()); - if (!superGluu) { - clientJsonNode = commonVerifiers.verifyClientJSONTypeIsGet(clientJsonNode); - } + // Get challenge String challenge = commonVerifiers.getChallenge(clientJsonNode); // Find authentication entry - Fido2AuthenticationEntry authenticationEntity = authenticationPersistenceService.findByChallenge(challenge, oneStep).parallelStream() + Fido2AuthenticationEntry authenticationEntity = authenticationPersistenceService.findByChallenge(challenge).parallelStream() .findFirst().orElseThrow(() -> new Fido2RuntimeException( String.format("Can't find associated assertion request by challenge '%s'", challenge))); Fido2AuthenticationData authenticationData = authenticationEntity.getAuthenticationData(); @@ -353,29 +330,27 @@ public AttestationOrAssertionResponse verify(AssertionResult assertionResult) { // Store original response authenticationData.setAssertionResponse(CommonUtilService.toJsonNode(assertionResult).toString()); - // Support cancel request - if (cancelRequest) { - authenticationData.setStatus(Fido2AuthenticationStatus.canceled); - } else { - authenticationData.setStatus(Fido2AuthenticationStatus.authenticated); - - String deviceDataStr = response.getDeviceData(); - if (!Strings.isNullOrEmpty(deviceDataStr)) { - try { - Fido2DeviceData deviceData = dataMapperService.readValue( - new String(base64Service.urlDecode(deviceDataStr), StandardCharsets.UTF_8), - Fido2DeviceData.class); - - boolean pushTokenUpdated = !StringHelper.equals(registrationEntry.getDeviceData().getPushToken(), deviceData.getPushToken()); - if (pushTokenUpdated) { - prepareForPushTokenChange(registrationEntry); - } - registrationEntry.setDeviceData(deviceData); - } catch (Exception ex) { - throw errorResponseFactory.invalidRequest(String.format("Device data is invalid: %s", deviceDataStr), ex); - } - } - } + authenticationData.setStatus(Fido2AuthenticationStatus.authenticated); + + //TODO: CHeck with Yuriy Ack if this should be here + String deviceDataStr = response.getDeviceData(); + if (!Strings.isNullOrEmpty(deviceDataStr)) { + try { + Fido2DeviceData deviceData = dataMapperService.readValue( + new String(base64Service.urlDecode(deviceDataStr), StandardCharsets.UTF_8), + Fido2DeviceData.class); + + boolean pushTokenUpdated = !StringHelper.equals(registrationEntry.getDeviceData().getPushToken(), + deviceData.getPushToken()); + if (pushTokenUpdated) { + prepareForPushTokenChange(registrationEntry); + } + registrationEntry.setDeviceData(deviceData); + } catch (Exception ex) { + throw errorResponseFactory.invalidRequest(String.format("Device data is invalid: %s", deviceDataStr), + ex); + } + } // Set expiration int unfinishedRequestExpiration = appConfiguration.getFido2Configuration().getMetadataRefreshInterval(); @@ -393,7 +368,7 @@ public AttestationOrAssertionResponse verify(AssertionResult assertionResult) { if (StringHelper.isNotEmpty(sessionStateId)) { log.debug("There is session id. Setting session id attributes"); - userSessionIdService.updateUserSessionIdOnFinishRequest(sessionStateId, registrationEntry.getUserInum(), registrationEntry, authenticationEntity, false, oneStep); + userSessionIdService.updateUserSessionIdOnFinishRequest(sessionStateId, registrationEntry.getUserInum(), registrationEntry, authenticationEntity, false); } // Create result object @@ -433,42 +408,45 @@ private void prepareForPushTokenChange(Fido2RegistrationEntry registrationEntry) snsEndpointArnHistory.add(snsEndpointArn); } - private Pair, String> prepareAllowedCredentials(String documentDomain, String username, String requestedKeyHandle, boolean superGluu) { + private Pair, String> prepareAllowedCredentials(String documentDomain, + String username) { if (appConfiguration.isOldU2fMigrationEnabled()) { - List existingFidoRegistrations = deviceRegistrationService.findAllRegisteredByUsername(username, - documentDomain); + List existingFidoRegistrations = deviceRegistrationService + .findAllRegisteredByUsername(username, documentDomain); if (existingFidoRegistrations.size() > 0) { deviceRegistrationService.migrateToFido2(existingFidoRegistrations, documentDomain, username); } } List existingFido2Registrations; - if (superGluu && StringHelper.isNotEmpty(requestedKeyHandle)) { - Fido2RegistrationEntry fido2RegistrationEntry = registrationPersistenceService.findByPublicKeyId(username, requestedKeyHandle, documentDomain).orElseThrow(() -> new Fido2RuntimeException( - String.format("Can't find associated key '%s' for application '%s'", requestedKeyHandle, documentDomain))); - existingFido2Registrations = Arrays.asList(fido2RegistrationEntry); - } else { - existingFido2Registrations = registrationPersistenceService.findByRpRegisteredUserDevices(username, superGluu ? documentDomain : null); - } - // f.getRegistrationData().getAttenstationRequest() null check is added to maintain backward compatiblity with U2F devices when U2F devices are migrated to the FIDO2 server + + // TODO: incase of a bug, this the second argument should have been null, see + // old code to understand + existingFido2Registrations = registrationPersistenceService.findByRpRegisteredUserDevices(username, + documentDomain); + + // f.getRegistrationData().getAttenstationRequest() null check is added to + // maintain backward compatiblity with U2F devices when U2F devices are migrated + // to the FIDO2 server List allowedFido2Registrations = existingFido2Registrations.parallelStream() - .filter(f -> StringHelper.isNotEmpty(f.getRegistrationData().getPublicKeyId())).collect(Collectors.toList()); + .filter(f -> StringHelper.isNotEmpty(f.getRegistrationData().getPublicKeyId())) + .collect(Collectors.toList()); - List allowedFido2Keys = new ArrayList<>(allowedFido2Registrations.size()); + List allowedFido2Keys = new ArrayList<>(allowedFido2Registrations.size()); allowedFido2Registrations.forEach((f) -> { log.debug("attestation request:" + f.getRegistrationData().getAttestationRequest()); String transports[]; - if (superGluu) { - transports = new String[] { "net", "qr" }; - } else { - transports = ((f.getRegistrationData().getAttestationType().equalsIgnoreCase(AttestationFormat.apple.getFmt())) || ( f.getRegistrationData().getAttestationRequest() != null && - f.getRegistrationData().getAttestationRequest().contains(AuthenticatorAttachment.PLATFORM.getAttachment()))) - - ? new String[] { "internal" } - : new String[] { "usb", "ble", "nfc" }; - } - PublicKeyCredentialDescriptor descriptor = new PublicKeyCredentialDescriptor( - transports, f.getRegistrationData().getPublicKeyId()); + + transports = ((f.getRegistrationData().getAttestationType() + .equalsIgnoreCase(AttestationFormat.apple.getFmt())) + || (f.getRegistrationData().getAttestationRequest() != null && f.getRegistrationData() + .getAttestationRequest().contains(AuthenticatorAttachment.PLATFORM.getAttachment()))) + + ? new String[] { "internal" } + : new String[] { "usb", "ble", "nfc" }; + + PublicKeyCredentialDescriptor descriptor = new PublicKeyCredentialDescriptor(transports, + f.getRegistrationData().getPublicKeyId()); allowedFido2Keys.add(descriptor); }); @@ -476,10 +454,9 @@ private Pair, String> prepareAllowedCredenti Optional fidoRegistration = allowedFido2Registrations.parallelStream() .filter(f -> StringUtils.isNotEmpty(f.getRegistrationData().getApplicationId())).findAny(); String applicationId = null; + // applicationId should not be sent incase of pure fido2 - if (fidoRegistration.isPresent() && superGluu) { - applicationId = fidoRegistration.get().getRegistrationData().getApplicationId(); - } + applicationId = fidoRegistration.get().getRegistrationData().getApplicationId(); return Pair.of(allowedFido2Keys, applicationId); } diff --git a/jans-fido2/server/src/main/java/io/jans/fido2/service/operation/AttestationService.java b/jans-fido2/server/src/main/java/io/jans/fido2/service/operation/AttestationService.java index 8e6087e768a..359e80992c5 100644 --- a/jans-fido2/server/src/main/java/io/jans/fido2/service/operation/AttestationService.java +++ b/jans-fido2/server/src/main/java/io/jans/fido2/service/operation/AttestationService.java @@ -119,8 +119,6 @@ public PublicKeyCredentialCreationOptions options(AttestationOptions attestation // Verify request parameters commonVerifiers.verifyAttestationOptions(attestationOptions); - boolean oneStep = commonVerifiers.isSuperGluuOneStepMode(CommonUtilService.toJsonNode(attestationOptions)); - // Create result object PublicKeyCredentialCreationOptions credentialCreationOptions = new PublicKeyCredentialCreationOptions(); @@ -157,11 +155,11 @@ public PublicKeyCredentialCreationOptions options(AttestationOptions attestation log.debug("Put user {}", user.toString()); // Put excludeCredentials - if (!oneStep) { - Set excludedCredentials = prepareExcludeCredentials(documentDomain, attestationOptions.getUsername()); - credentialCreationOptions.setExcludeCredentials(excludedCredentials); - excludedCredentials.stream().forEach(ele -> log.debug("Put excludeCredentials {}", ele.toString())); - } + + Set excludedCredentials = prepareExcludeCredentials(documentDomain, attestationOptions.getUsername()); + credentialCreationOptions.setExcludeCredentials(excludedCredentials); + excludedCredentials.stream().forEach(ele -> log.debug("Put excludeCredentials {}", ele.toString())); + // Put authenticatorSelection credentialCreationOptions.setAuthenticatorSelection(new AuthenticatorSelection()); @@ -256,7 +254,7 @@ else if(hints.contains(PublicKeyCredentialHints.SECURITY_KEY.getValue()) || hint // Store original requests entity.setAttestationRequest(CommonUtilService.toJsonNode(attestationOptions).toString()); - Fido2RegistrationEntry registrationEntry = registrationPersistenceService.buildFido2RegistrationEntry(entity, oneStep); + Fido2RegistrationEntry registrationEntry = registrationPersistenceService.buildFido2RegistrationEntry(entity); //if (params.hasNonNull("session_id")) { if (attestationOptions.getSessionId() != null) { registrationEntry.setSessionStateId(attestationOptions.getSessionId()); @@ -283,10 +281,7 @@ public AttestationOrAssertionResponse verify(AttestationResult attestationResult ExternalFido2Context externalFido2InterceptionContext = new ExternalFido2Context(CommonUtilService.toJsonNode(attestationResult), httpRequest, httpResponse); boolean externalInterceptContext = externalFido2InterceptionService.verifyAttestationStart(CommonUtilService.toJsonNode(attestationResult), externalFido2InterceptionContext); - boolean superGluu = commonVerifiers.hasSuperGluu(CommonUtilService.toJsonNode(attestationResult)); - boolean oneStep = commonVerifiers.isSuperGluuOneStepMode(CommonUtilService.toJsonNode(attestationResult)); - boolean cancelRequest = commonVerifiers.isSuperGluuCancelRequest(CommonUtilService.toJsonNode(attestationResult)); - + // Verify if there are mandatory request parameters commonVerifiers.verifyBasicAttestationResultRequest(attestationResult); commonVerifiers.verifyAssertionType(attestationResult.getType()); @@ -296,15 +291,13 @@ public AttestationOrAssertionResponse verify(AttestationResult attestationResult // Verify client data JsonNode clientDataJSONNode = commonVerifiers.verifyClientJSON(attestationResult.getResponse().getClientDataJSON()); - if (!superGluu) { - commonVerifiers.verifyClientJSONTypeIsCreate(clientDataJSONNode); - } + // Get challenge String challenge = commonVerifiers.getChallenge(clientDataJSONNode); // Find registration entry - Fido2RegistrationEntry registrationEntry = registrationPersistenceService.findByChallenge(challenge, oneStep) + Fido2RegistrationEntry registrationEntry = registrationPersistenceService.findByChallenge(challenge) .parallelStream().findAny().orElseThrow(() -> errorResponseFactory.badRequestException(AttestationErrorResponseType.INVALID_CHALLENGE, String.format("Can't find associated attestation request by challenge '%s'", challenge))); Fido2RegistrationData registrationData = registrationEntry.getRegistrationData(); @@ -329,12 +322,7 @@ public AttestationOrAssertionResponse verify(AttestationResult attestationResult registrationData.setBackupEligibilityFlag(attestationData.getBackupEligibilityFlag()); registrationData.setBackupStateFlag(attestationData.getBackupStateFlag()); - // Support cancel request - if (cancelRequest) { - registrationData.setStatus(Fido2RegistrationStatus.canceled); - } else { - registrationData.setStatus(Fido2RegistrationStatus.registered); - } + registrationData.setStatus(Fido2RegistrationStatus.registered); // Store original response registrationData.setAttestationResponse(CommonUtilService.toJsonNode(attestationResult).toString()); @@ -364,13 +352,9 @@ public AttestationOrAssertionResponse verify(AttestationResult attestationResult String sessionStateId = registrationEntry.getSessionStateId(); registrationEntry.setSessionStateId(null); - // Set expiration for one_step entry - if (oneStep) { - int unfinishedRequestExpiration = appConfiguration.getFido2Configuration().getUnfinishedRequestExpiration(); - registrationEntry.setExpiration(unfinishedRequestExpiration); - } else { - registrationEntry.clearExpiration(); - } + + registrationEntry.clearExpiration(); + registrationPersistenceService.update(registrationEntry); @@ -378,7 +362,7 @@ public AttestationOrAssertionResponse verify(AttestationResult attestationResult if (StringHelper.isNotEmpty(sessionStateId)) { log.debug("There is session id. Setting session id attributes"); - userSessionIdService.updateUserSessionIdOnFinishRequest(sessionStateId, registrationEntry.getUserInum(), registrationEntry, true, oneStep); + userSessionIdService.updateUserSessionIdOnFinishRequest(sessionStateId, registrationEntry.getUserInum(), registrationEntry, true); } // Create result object diff --git a/jans-fido2/server/src/main/java/io/jans/fido2/service/persist/AuthenticationPersistenceService.java b/jans-fido2/server/src/main/java/io/jans/fido2/service/persist/AuthenticationPersistenceService.java index 6ea083e6547..b661e583306 100644 --- a/jans-fido2/server/src/main/java/io/jans/fido2/service/persist/AuthenticationPersistenceService.java +++ b/jans-fido2/server/src/main/java/io/jans/fido2/service/persist/AuthenticationPersistenceService.java @@ -64,7 +64,7 @@ public class AuthenticationPersistenceService { private ErrorResponseFactory errorResponseFactory; public void save(Fido2AuthenticationData authenticationData) { - Fido2AuthenticationEntry authenticationEntity = buildFido2AuthenticationEntry(authenticationData, false); + Fido2AuthenticationEntry authenticationEntity = buildFido2AuthenticationEntry(authenticationData); save(authenticationEntity); } @@ -75,27 +75,27 @@ public void save(Fido2AuthenticationEntry authenticationEntity) { persistenceEntryManager.persist(authenticationEntity); } - public Fido2AuthenticationEntry buildFido2AuthenticationEntry(Fido2AuthenticationData authenticationData, boolean oneStep) { + public Fido2AuthenticationEntry buildFido2AuthenticationEntry(Fido2AuthenticationData authenticationData) { String userName = authenticationData.getUsername(); String userInum = null; - if (!oneStep) { - User user = userService.getUser(userName, "inum"); - if (user == null) { - if (appConfiguration.getFido2Configuration().isDebugUserAutoEnrollment()) { - user = userService.addDefaultUser(userName); - } else { - throw errorResponseFactory.badRequestException(AttestationErrorResponseType.USER_AUTO_ENROLLMENT_IS_DISABLED, "Auto user enrollment was disabled. User not exists!"); - } - } - userInum = userService.getUserInum(user); - } + + User user = userService.getUser(userName, "inum"); + if (user == null) { + if (appConfiguration.getFido2Configuration().isDebugUserAutoEnrollment()) { + user = userService.addDefaultUser(userName); + } else { + throw errorResponseFactory.badRequestException(AttestationErrorResponseType.USER_AUTO_ENROLLMENT_IS_DISABLED, "Auto user enrollment was disabled. User not exists!"); + } + } + userInum = userService.getUserInum(user); + Date now = new GregorianCalendar(TimeZone.getTimeZone("UTC")).getTime(); final String id = UUID.randomUUID().toString(); final String challenge = authenticationData.getChallenge(); - String dn = oneStep ? getDnForAuthenticationEntry(null, id) : getDnForAuthenticationEntry(userInum, id); + String dn = getDnForAuthenticationEntry(userInum, id); Fido2AuthenticationEntry authenticationEntity = new Fido2AuthenticationEntry(dn, authenticationData.getId(), now, userInum, authenticationData); authenticationEntity.setAuthenticationStatus(authenticationData.getStatus()); if (StringUtils.isNotEmpty(challenge)) { @@ -145,8 +145,8 @@ public void prepareBranch(final String userInum) { } } - public List findByChallenge(String challenge, boolean oneStep) { - String baseDn = oneStep ? getDnForAuthenticationEntry(null, null) : getBaseDnForFido2AuthenticationEntries(null); + public List findByChallenge(String challenge) { + String baseDn = getBaseDnForFido2AuthenticationEntries(null); Filter codeChallengFilter = Filter.createEqualityFilter("jansCodeChallenge", challenge); Filter codeChallengHashCodeFilter = Filter.createEqualityFilter("jansCodeChallengeHash", challengeGenerator.getChallengeHashCode(challenge)); diff --git a/jans-fido2/server/src/main/java/io/jans/fido2/service/persist/RegistrationPersistenceService.java b/jans-fido2/server/src/main/java/io/jans/fido2/service/persist/RegistrationPersistenceService.java index cbc19998eb8..d025f66dabf 100644 --- a/jans-fido2/server/src/main/java/io/jans/fido2/service/persist/RegistrationPersistenceService.java +++ b/jans-fido2/server/src/main/java/io/jans/fido2/service/persist/RegistrationPersistenceService.java @@ -60,32 +60,32 @@ public class RegistrationPersistenceService extends io.jans.as.common.service.co private ErrorResponseFactory errorResponseFactory; public void save(Fido2RegistrationData registrationData) { - Fido2RegistrationEntry registrationEntry = buildFido2RegistrationEntry(registrationData, false); + Fido2RegistrationEntry registrationEntry = buildFido2RegistrationEntry(registrationData); save(registrationEntry); } - public Fido2RegistrationEntry buildFido2RegistrationEntry(Fido2RegistrationData registrationData, boolean oneStep) { + public Fido2RegistrationEntry buildFido2RegistrationEntry(Fido2RegistrationData registrationData) { String userName = registrationData.getUsername(); String userInum = null; - if (!oneStep) { - User user = userService.getUser(userName, "inum"); - if (user == null) { - if (appConfiguration.getFido2Configuration().isDebugUserAutoEnrollment()) { - user = userService.addDefaultUser(userName); - } else { - throw errorResponseFactory.badRequestException(AttestationErrorResponseType.USER_AUTO_ENROLLMENT_IS_DISABLED, "Auto user enrollment was disabled. User not exists!"); - } - } - userInum = userService.getUserInum(user); - } + + User user = userService.getUser(userName, "inum"); + if (user == null) { + if (appConfiguration.getFido2Configuration().isDebugUserAutoEnrollment()) { + user = userService.addDefaultUser(userName); + } else { + throw errorResponseFactory.badRequestException(AttestationErrorResponseType.USER_AUTO_ENROLLMENT_IS_DISABLED, "Auto user enrollment was disabled. User not exists!"); + } + } + userInum = userService.getUserInum(user); + Date now = new GregorianCalendar(TimeZone.getTimeZone("UTC")).getTime(); final String id = UUID.randomUUID().toString(); final String challenge = registrationData.getChallenge(); - String dn = oneStep ? getDnForRegistrationEntry(null, id) : getDnForRegistrationEntry(userInum, id); + String dn = getDnForRegistrationEntry(userInum, id); Fido2RegistrationEntry registrationEntry = new Fido2RegistrationEntry(dn, id, now, userInum, registrationData, challenge); registrationEntry.setRegistrationStatus(registrationData.getStatus()); if (StringUtils.isNotEmpty(challenge)) { @@ -173,8 +173,8 @@ public List findAllRegisteredByUsername(String username) return fido2RegistrationnEntries; } - public List findByChallenge(String challenge, boolean oneStep) { - String baseDn = oneStep ? getDnForRegistrationEntry(null, null) : getBaseDnForFido2RegistrationEntries(null); + public List findByChallenge(String challenge) { + String baseDn = getBaseDnForFido2RegistrationEntries(null); Filter codeChallengFilter = Filter.createEqualityFilter("jansCodeChallenge", challenge); Filter codeChallengHashCodeFilter = Filter.createEqualityFilter("jansCodeChallengeHash", getChallengeHashCode(challenge)); diff --git a/jans-fido2/server/src/main/java/io/jans/fido2/service/persist/UserSessionIdService.java b/jans-fido2/server/src/main/java/io/jans/fido2/service/persist/UserSessionIdService.java index e45c834f109..498f99a7a62 100644 --- a/jans-fido2/server/src/main/java/io/jans/fido2/service/persist/UserSessionIdService.java +++ b/jans-fido2/server/src/main/java/io/jans/fido2/service/persist/UserSessionIdService.java @@ -71,7 +71,7 @@ public boolean isValidSessionId(String sessionId, String userName) { return true; } - public void updateUserSessionIdOnFinishRequest(String sessionId, String userInum, Fido2RegistrationEntry registrationEntry, boolean enroll, boolean oneStep) { + public void updateUserSessionIdOnFinishRequest(String sessionId, String userInum, Fido2RegistrationEntry registrationEntry, boolean enroll) { SessionId entity = getSessionId(sessionId); if (entity == null) { return; @@ -83,12 +83,10 @@ public void updateUserSessionIdOnFinishRequest(String sessionId, String userInum } else { sessionAttributes.put("session_custom_state", "declined"); } - updateUserSessionAttributes(userInum, registrationEntry, enroll, oneStep, sessionAttributes); - updateSessionId(entity); } - public void updateUserSessionIdOnFinishRequest(String sessionId, String userInum, Fido2RegistrationEntry registrationEntry, Fido2AuthenticationEntry authenticationEntry, boolean enroll, boolean oneStep) { + public void updateUserSessionIdOnFinishRequest(String sessionId, String userInum, Fido2RegistrationEntry registrationEntry, Fido2AuthenticationEntry authenticationEntry, boolean enroll) { SessionId entity = getSessionId(sessionId); if (entity == null) { return; @@ -100,19 +98,11 @@ public void updateUserSessionIdOnFinishRequest(String sessionId, String userInum } else { sessionAttributes.put("session_custom_state", "declined"); } - updateUserSessionAttributes(userInum, registrationEntry, enroll, oneStep, sessionAttributes); + updateSessionId(entity); } - private void updateUserSessionAttributes(String userInum, Fido2RegistrationEntry registrationEntry, boolean enroll, - boolean oneStep, Map sessionAttributes) { - sessionAttributes.put("super_gluu_u2f_device_id", registrationEntry.getId()); - sessionAttributes.put("super_gluu_u2f_device_dn", registrationEntry.getDn()); - sessionAttributes.put("super_gluu_u2f_device_user_inum", userInum); - sessionAttributes.put("super_gluu_u2f_device_enroll", Boolean.toString(enroll)); - sessionAttributes.put("super_gluu_u2f_device_one_step", Boolean.toString(oneStep)); - } public void updateUserSessionIdOnError(String sessionId) { SessionId entity = getSessionId(sessionId); diff --git a/jans-fido2/server/src/main/java/io/jans/fido2/service/sg/converter/AssertionSuperGluuController.java b/jans-fido2/server/src/main/java/io/jans/fido2/service/sg/converter/AssertionSuperGluuController.java deleted file mode 100644 index 5eda9233038..00000000000 --- a/jans-fido2/server/src/main/java/io/jans/fido2/service/sg/converter/AssertionSuperGluuController.java +++ /dev/null @@ -1,256 +0,0 @@ -/* - * Janssen Project software is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text. - * - * Copyright (c) 2020, Janssen Project - */ - -package io.jans.fido2.service.sg.converter; - -import java.io.IOException; -import java.nio.ByteBuffer; -import java.nio.charset.StandardCharsets; - -import io.jans.fido2.model.assertion.*; -import io.jans.fido2.model.common.AttestationOrAssertionResponse; -import io.jans.fido2.model.error.ErrorResponseFactory; -import io.jans.fido2.service.util.CommonUtilService; -import org.apache.commons.lang3.ArrayUtils; -import org.slf4j.Logger; - -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.node.ArrayNode; -import com.fasterxml.jackson.databind.node.ObjectNode; - -import io.jans.as.model.fido.u2f.message.RawAuthenticateResponse; -import io.jans.as.model.fido.u2f.protocol.AuthenticateResponse; -import io.jans.as.model.fido.u2f.protocol.ClientData; -import io.jans.fido2.service.AuthenticatorDataParser; -import io.jans.fido2.service.Base64Service; -import io.jans.fido2.service.DataMapperService; -import io.jans.fido2.service.DigestService; -import io.jans.fido2.service.operation.AssertionService; -import io.jans.fido2.service.persist.UserSessionIdService; -import io.jans.fido2.service.sg.RawAuthenticationService; -import io.jans.fido2.service.verifier.CommonVerifiers; -import io.jans.fido2.sg.SuperGluuMode; -import io.jans.util.StringHelper; -import jakarta.enterprise.context.ApplicationScoped; -import jakarta.inject.Inject; - -/** - * Converters Super Gluu authentication request to U2F V2 request - * - * @author Yuriy Movchan - * @version Jan 26, 2023 - */ -@ApplicationScoped -public class AssertionSuperGluuController { - - @Inject - private Logger log; - - @Inject - private AssertionService assertionService; - - @Inject - private DataMapperService dataMapperService; - - @Inject - private Base64Service base64Service; - - @Inject - private RawAuthenticationService rawAuthenticationService; - - @Inject - private DigestService digestService; - - @Inject - private UserSessionIdService userSessionIdService; - - @Inject - private ErrorResponseFactory errorResponseFactory; - - /* Example for one_step: - * - request: - * username: null - * keyhandle: r4AIBCT_CEi8SWThJ-T5gsxjfZMqzqMdqCeDuK_xTvz_kr5FNNs2j6Tb2dvoXgculthxTzXF5-FI1KWsA_dRLA - * application: https://yurem-emerging-pig.gluu.info/identity/authcode.htm - * session_id: 2994e597-3dc9-4d96-ae7e-84cfcf049db6 - * - response: - * {"authenticateRequests":[{"challenge":"EELAH05XTUfPHrvpqVYhXB8pEmOMaRWY9mBurdhicBU", - * "appId":"https://yurem-emerging-pig.gluu.info/identity/authcode.htm", - * "keyHandle":"r4AIBCT_CEi8SWThJ-T5gsxjfZMqzqMdqCeDuK_xTvz_kr5FNNs2j6Tb2dvoXgculthxTzXF5-FI1KWsA_dRLA","version":"U2F_V2"}]} - * - * Example for two_step: - * - request: - * username: test1 - * keyhandle: null - * application: https://yurem-emerging-pig.gluu.info/identity/authcode.htm - * session_id: 850ff665-02b6-435b-baf8-b018b13043c3 - * - response: - * {"authenticateRequests":[{"challenge":"5QoRtudmej5trcrMRgFBoI5rZ6pzIZiYP3u3bXCvvAE", - * "appId":"https://yurem-emerging-pig.gluu.info/identity/authcode.htm", - * "keyHandle":"YJvWD9n40eIurInJvPKUoxpKzrleUMWgu9w3v_NUBu7BiGAclgkH_Zg88_T5y6Rh78imTxTh0djWFYG4jxOixw","version":"U2F_V2"}]} - */ - public JsonNode startAuthentication(String userName, String keyHandle, String appId, String sessionId) { - AssertionOptions assertionOptions = buildFido2AssertionStartResponse(userName, keyHandle, appId, sessionId); - AssertionOptionsResponse result = assertionService.options(assertionOptions); - - // Build start authentication response - ObjectNode superGluuResult = dataMapperService.createObjectNode(); - ArrayNode authenticateRequests = superGluuResult.putArray("authenticateRequests"); - - String challenge = result.getChallenge(); - String userVerification = result.getUserVerification(); - - if (result.getAllowCredentials() != null) { - result.getAllowCredentials().forEach((f) -> { - ObjectNode item = dataMapperService.createObjectNode(); - item.put("appId", appId); - item.put("userVerification", userVerification); - item.put("challenge", challenge); - item.put("keyHandle", f.getId()); - item.put("version", "U2F_V2"); - - authenticateRequests.add(item); - }); - } - - return superGluuResult; - } - - public AssertionOptions buildFido2AssertionStartResponse(String userName, String keyHandle, String appId, - String sessionId) { - boolean oneStep = StringHelper.isEmpty(userName); - - boolean valid = userSessionIdService.isValidSessionId(sessionId, userName); - if (!valid) { - String reasonError = String.format("session_id '%s' is invalid", sessionId); - throw errorResponseFactory.badRequestException(AssertionErrorResponseType.INVALID_SESSION_ID, reasonError); - } - - if (StringHelper.isEmpty(userName) && StringHelper.isEmpty(keyHandle)) { - String reasonError = "invalid username or keyHandle"; - throw errorResponseFactory.badRequestException(AssertionErrorResponseType.INVALID_USERNAME_OR_KEY_HANDLE, reasonError); - } - AssertionOptions assertionOptions = new AssertionOptions(); - // Add all required parameters from request to allow process U2F request - assertionOptions.setSuperGluuRequest(true); - assertionOptions.setSuperGluuAppId(appId); - assertionOptions.setDocumentDomain(appId); - assertionOptions.setSuperGluuKeyHandle(keyHandle); - assertionOptions.setSuperGluuRequestMode(oneStep ? SuperGluuMode.ONE_STEP.getMode() : SuperGluuMode.TWO_STEP.getMode()); - - assertionOptions.setUsername(userName); - assertionOptions.setSessionId(sessionId); - - log.debug("Prepared U2F_V2 assertions options request: {}", assertionOptions.toString()); - return assertionOptions; - } - - /* Example for one_step: - * - request: - * username: null - * tokenResponse: {"signatureData":"AQAAAAEwRQIhANrCm98JCTz6cqSZ_vwGHdF9uqe3b4z1nCrNIPCObwc-AiAblGdWyky - * LeaTJPzLtbWHMoN9MsKUlgmbfSRsINJEVeA","clientData":"eyJ0eXAiOiJuYXZpZ2F0b3IuaWQuZ2V0QXNzZXJ0aW9uIiwiY - * 2hhbGxlbmdlIjoiRUVMQUgwNVhUVWZQSHJ2cHFWWWhYQjhwRW1PTWFSV1k5bUJ1cmRoaWNCVSIsIm9yaWdpbiI6Imh0dHBzOlwvX - * C95dXJlbS1lbWVyZ2luZy1waWcuZ2x1dS5pbmZvXC9pZGVudGl0eVwvYXV0aGNvZGUuaHRtIn0","keyHandle":"r4AIBCT_CEi - * 8SWThJ-T5gsxjfZMqzqMdqCeDuK_xTvz_kr5FNNs2j6Tb2dvoXgculthxTzXF5-FI1KWsA_dRLA"} - * - response: - * {"status":"success","challenge":"EELAH05XTUfPHrvpqVYhXB8pEmOMaRWY9mBurdhicBU"} - * - * Example for two_step: - * - request: - * username: test1 - * tokenResponse: {"signatureData":"AQAAAAEwRgIhAN4auE9-U2YDhi8ByxIIv3G2hvDeFjEGU_x5SvfcIQyUAiEA4I_xMin - * mYAmH5qk5KMaYATFAryIpoVwARGvEFQTWE2Q","clientData":"eyJ0eXAiOiJuYXZpZ2F0b3IuaWQuZ2V0QXNzZXJ0aW9uIiwi - * Y2hhbGxlbmdlIjoiNVFvUnR1ZG1lajV0cmNyTVJnRkJvSTVyWjZweklaaVlQM3UzYlhDdnZBRSIsIm9yaWdpbiI6Imh0dHBzOlwv - * XC95dXJlbS1lbWVyZ2luZy1waWcuZ2x1dS5pbmZvXC9pZGVudGl0eVwvYXV0aGNvZGUuaHRtIn0","keyHandle":"YJvWD9n40e - * IurInJvPKUoxpKzrleUMWgu9w3v_NUBu7BiGAclgkH_Zg88_T5y6Rh78imTxTh0djWFYG4jxOixw","deviceData":"eyJuYW1l - * IjoiU00tRzk5MUIiLCJvc19uYW1lIjoidGlyYW1pc3UiLCJvc192ZXJzaW9uIjoiMTMiLCJwbGF0Zm9ybSI6ImFuZHJvaWQiLCJw - * dXNoX3Rva2VuIjoicHVzaF90b2tlbiIsInR5cGUiOiJub3JtYWwiLCJ1dWlkIjoidXVpZCJ9"} - * - response: - * {"status":"success","challenge":"5QoRtudmej5trcrMRgFBoI5rZ6pzIZiYP3u3bXCvvAE"} - * - */ - public JsonNode finishAuthentication(String userName, String authenticateResponseString) { - AuthenticateResponse authenticateResponse = parseAuthenticateResponse(authenticateResponseString); - - AssertionResult params = buildFido2AuthenticationVerifyResponse(userName, authenticateResponseString, authenticateResponse); - - AttestationOrAssertionResponse assertionResultResponse = assertionService.verify(params); - ObjectNode result = (ObjectNode)CommonUtilService.toJsonNode(assertionResultResponse); - - result.put("status", "success"); - result.put("challenge", authenticateResponse.getClientData().getChallenge()); - - return result; - } - - public AssertionResult buildFido2AuthenticationVerifyResponse(String userName, String authenticateResponseString, AuthenticateResponse authenticateResponse) { - if (!ArrayUtils.contains(RawAuthenticationService.SUPPORTED_AUTHENTICATE_TYPES, authenticateResponse.getClientData().getTyp())) { - throw errorResponseFactory.badRequestException(AssertionErrorResponseType.UNSUPPORTED_AUTHENTICATION_TYPE, "Invalid options attestation request type"); - } - - boolean oneStep = StringHelper.isEmpty(userName); - - AssertionResult assertionResult = new AssertionResult(); - // Add all required parameters from request to allow process U2F request - assertionResult.setSuperGluuRequest(true); - assertionResult.setSuperGluuRequestMode(oneStep ? SuperGluuMode.ONE_STEP.getMode() : SuperGluuMode.TWO_STEP.getMode()); - assertionResult.setId(authenticateResponse.getKeyHandle()); - assertionResult.setRawId(authenticateResponseString); - - // Convert clientData node to new format - ObjectNode clientData = dataMapperService.createObjectNode(); - clientData.put("type", authenticateResponse.getClientData().getTyp()); - clientData.put("challenge", authenticateResponse.getClientData().getChallenge()); - clientData.put("origin", authenticateResponse.getClientData().getOrigin()); - - // Store cancel type - assertionResult.setSuperGluuRequestCancel(StringHelper.equals(RawAuthenticationService.AUTHENTICATE_CANCEL_TYPE, authenticateResponse.getClientData().getTyp())); - // Add response node - Response response = new Response(); - response.setDeviceData(authenticateResponse.getDeviceData()); - // We have to quote URL to conform bug in Super Gluu - response.setClientDataJSON(base64Service.urlEncodeToString(clientData.toString().replaceAll("/", "\\\\/").getBytes(StandardCharsets.UTF_8))); - // Prepare attestationObject - RawAuthenticateResponse rawAuthenticateResponse = rawAuthenticationService.parseRawAuthenticateResponse(authenticateResponse.getSignatureData()); - response.setSignature(base64Service.urlEncodeToString(rawAuthenticateResponse.getSignature())); - - ObjectNode attestationObject = dataMapperService.createObjectNode(); - - try { - byte[] authData = generateAuthData(authenticateResponse.getClientData(), rawAuthenticateResponse); - response.setAuthenticatorData(base64Service.urlEncodeToString(authData)); - response.setAttestationObject(base64Service.urlEncodeToString(dataMapperService.cborWriteAsBytes(attestationObject))); - } catch (IOException e) { - throw errorResponseFactory.invalidRequest("Failed to prepare attestationObject: " + e.getMessage(), e); - } - assertionResult.setResponse(response); - log.debug("Prepared U2F_V2 assertion verify request: {}", assertionResult.toString()); - return assertionResult; - } - - public AuthenticateResponse parseAuthenticateResponse(String authenticateResponseString) { - AuthenticateResponse authenticateResponse; - try { - authenticateResponse = dataMapperService.readValue(authenticateResponseString, AuthenticateResponse.class); - } catch (Exception ex) { - throw errorResponseFactory.invalidRequest(ex.getMessage()); - } - return authenticateResponse; - } - - private byte[] generateAuthData(ClientData clientData, RawAuthenticateResponse rawAuthenticateResponse) { - byte[] rpIdHash = digestService.hashSha256(clientData.getOrigin()); - byte[] flags = new byte[]{AuthenticatorDataParser.FLAG_USER_PRESENT}; - byte[] counter = ByteBuffer.allocate(4).putInt((int) rawAuthenticateResponse.getCounter()).array(); - - byte[] authData = ByteBuffer - .allocate(rpIdHash.length + flags.length + counter.length) - .put(rpIdHash).put(flags).put(counter).array(); - - return authData; - } -} diff --git a/jans-fido2/server/src/main/java/io/jans/fido2/service/sg/converter/AttestationSuperGluuController.java b/jans-fido2/server/src/main/java/io/jans/fido2/service/sg/converter/AttestationSuperGluuController.java deleted file mode 100644 index 2f5e4db926c..00000000000 --- a/jans-fido2/server/src/main/java/io/jans/fido2/service/sg/converter/AttestationSuperGluuController.java +++ /dev/null @@ -1,285 +0,0 @@ -/* - * Janssen Project software is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text. - * - * Copyright (c) 2020, Janssen Project - */ - -package io.jans.fido2.service.sg.converter; - -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.node.ArrayNode; -import com.fasterxml.jackson.databind.node.ObjectNode; -import io.jans.as.model.fido.u2f.message.RawRegisterResponse; -import io.jans.as.model.fido.u2f.protocol.ClientData; -import io.jans.as.model.fido.u2f.protocol.RegisterResponse; -import io.jans.fido2.ctap.AttestationConveyancePreference; -import io.jans.fido2.ctap.AttestationFormat; -import io.jans.fido2.model.attestation.*; -import io.jans.fido2.model.common.AttestationOrAssertionResponse; -import io.jans.fido2.model.common.PublicKeyCredentialType; -import io.jans.fido2.model.error.ErrorResponseFactory; -import io.jans.fido2.service.*; -import io.jans.fido2.service.operation.AttestationService; -import io.jans.fido2.service.persist.UserSessionIdService; -import io.jans.fido2.service.sg.RawRegistrationService; -import io.jans.fido2.service.util.CommonUtilService; -import io.jans.fido2.sg.SuperGluuMode; -import io.jans.util.StringHelper; -import jakarta.enterprise.context.ApplicationScoped; -import jakarta.inject.Inject; -import org.apache.commons.lang3.ArrayUtils; -import org.slf4j.Logger; - -import java.io.IOException; -import java.nio.ByteBuffer; -import java.nio.charset.StandardCharsets; -import java.security.cert.CertificateEncodingException; - -/** - * Converters Super Gluu registration request to U2F V2 request - * @author Yuriy Movchan - * @version Jan 26, 2023 - */ -@ApplicationScoped -public class AttestationSuperGluuController { - - @Inject - private Logger log; - - @Inject - private AttestationService attestationService; - - @Inject - private DataMapperService dataMapperService; - - @Inject - private Base64Service base64Service; - - @Inject - private RawRegistrationService rawRegistrationService; - - @Inject - private CoseService coseService; - - @Inject - private DigestService digestService; - - @Inject - private UserSessionIdService userSessionIdService; - - @Inject - private ErrorResponseFactory errorResponseFactory; - - /* Example for one_step: - * - request: - * username: null - * application: https://yurem-emerging-pig.gluu.info/identity/authcode.htm - * session_id: a5183b05-dbe0-4173-a794-2334bb864708 - * enrollment_code: null - * - response: - * {"authenticateRequests":[],"registerRequests":[{"challenge":"GU4usvpYfvQ_RCMSqm819gTZMa0qCeLr1Xg2KbvW2To" - * "appId":"https://yurem-emerging-pig.gluu.info/identity/authcode.htm","version":"U2F_V2"}]} - * - * Example for two_step: - * - request: - * username: test1 - * application: https://yurem-emerging-pig.gluu.info/identity/authcode.htm - * session_id: 46c30db8-0339-4459-8ee7-e4960ad75986 - * enrollment_code: null - * - response: - * {"authenticateRequests":[],"registerRequests":[{"challenge":"raPfmqZOHlHF4gXbprd29uwX-bs3Ff5v03quxBD4FkM", - * "appId":"https://yurem-emerging-pig.gluu.info/identity/authcode.htm","version":"U2F_V2"}]} - */ - public JsonNode startRegistration(String userName, String appId, String sessionId, String enrollmentCode) { - AttestationOptions attestationOptions = buildFido2AttestationStartResponse(userName, appId, sessionId); - - PublicKeyCredentialCreationOptions fromPublicKeyCredentialCreationOptions = attestationService.options(attestationOptions); - - ObjectNode result = (ObjectNode)CommonUtilService.toJsonNode(fromPublicKeyCredentialCreationOptions); - // Build start registration response - ObjectNode superGluuResult = dataMapperService.createObjectNode(); - ArrayNode registerRequests = superGluuResult.putArray("registerRequests"); - - result.put("appId", appId); - registerRequests.add(result); - - result.put("version", "U2F_V2"); - - return superGluuResult; - } - - public AttestationOptions buildFido2AttestationStartResponse(String userName, String appId, String sessionId) { - boolean oneStep = StringHelper.isEmpty(userName); - - boolean valid = userSessionIdService.isValidSessionId(sessionId, userName); - if (!valid) { - String reasonError = String.format("session_id '%s' is invalid", sessionId); - throw errorResponseFactory.badRequestException(AttestationErrorResponseType.INVALID_SESSION_ID, reasonError); - } - AttestationOptions attestationOptions = new AttestationOptions(); - // Add all required parameters from request to allow process U2F request - attestationOptions.setSuperGluuRequest(true); - attestationOptions.setSuperGluuRequestMode(oneStep ? SuperGluuMode.ONE_STEP.getMode() : SuperGluuMode.TWO_STEP.getMode()); - attestationOptions.setSuperGluuAppId(appId); - - String useUserName = userName; - if (oneStep) { - useUserName = attestationService.generateUserId(); - } - attestationOptions.setUsername(useUserName); - attestationOptions.setDisplayName(useUserName); - attestationOptions.setSessionId(sessionId); - attestationOptions.setAttestation(AttestationConveyancePreference.direct); - - log.debug("Prepared U2F_V2 attestation options request: {}", CommonUtilService.toJsonNode(attestationOptions).toString()); - return attestationOptions; - } - - /* Example for one_step: - * - request: - * username: null - * tokenResponse: {"registrationData":"BQQTkZFzsbTmuUoS_DS_jqpWRbZHp_J0YV8q4Xb4XTPYbIuvu-TRNubp8U-CKZuB - * 5tDT-l6R3sQvNc6wXjGCmL-OQK-ACAQk_whIvElk4Sfk-YLMY32TKs6jHagng7iv8U78_5K-RTTbNo-k29nb6F4HLpbYcU81xefh - * SNSlrAP3USwwggImMIIBzKADAgECAoGBAPMsD5b5G58AphKuKWl4Yz27sbE_rXFy7nPRqtJ_r4E5DSZbFvfyuos-Db0095ubB0Jo - * yM8ccmSO_eZQ6IekOLPKCR7yC5kes-f7MaxyaphmmD4dEvmuKjF-fRsQP5tQG7zerToto8eIz0XjPaupiZxQXtSHGHHTuPhri2nf - * oZlrMAoGCCqGSM49BAMCMFwxIDAeBgNVBAMTF0dsdXUgb3hQdXNoMiBVMkYgdjEuMC4wMQ0wCwYDVQQKEwRHbHV1MQ8wDQYDVQQH - * EwZBdXN0aW4xCzAJBgNVBAgTAlRYMQswCQYDVQQGEwJVUzAeFw0xNjAzMDExODU5NDZaFw0xOTAzMDExODU5NDZaMFwxIDAeBgNV - * BAMTF0dsdXUgb3hQdXNoMiBVMkYgdjEuMC4wMQ0wCwYDVQQKEwRHbHV1MQ8wDQYDVQQHEwZBdXN0aW4xCzAJBgNVBAgTAlRYMQsw - * CQYDVQQGEwJVUzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABICUKnzCE5PJ7tihiKkYu6E5Uy_sZ-RSqs_MnUJt0tB8G8GSg9nK - * o6P2424iV9lXX9Pil8qw4ofZ-fAXXepbp4MwCgYIKoZIzj0EAwIDSAAwRQIgUWwawAB2udURWQziDXVjSOi_QcuXiRxylqj5thFw - * FhYCIQCGY-CTZFi7JdkhZ05nDpbSYJBTOo1Etckh7k0qcvnO0TBFAiEA1v1jKTwGn5LRRGSab1kNdgEqD6qL08bougoJUNY1A5MC - * IGvtBFSNzhGvhQmdYYj5-XOd5P4ucVk6TmkV1Xu73Dvj","clientData":"eyJ0eXAiOiJuYXZpZ2F0b3IuaWQuZmluaXNoRW5y - * b2xsbWVudCIsImNoYWxsZW5nZSI6IkdVNHVzdnBZZnZRX1JDTVNxbTgxOWdUWk1hMHFDZUxyMVhnMktidlcyVG8iLCJvcmlnaW4i - * OiJodHRwczpcL1wveXVyZW0tZW1lcmdpbmctcGlnLmdsdXUuaW5mbyJ9","deviceData":"eyJuYW1lIjoiU00tRzk5MUIiLCJv - * c19uYW1lIjoidGlyYW1pc3UiLCJvc192ZXJzaW9uIjoiMTMiLCJwbGF0Zm9ybSI6ImFuZHJvaWQiLCJwdXNoX3Rva2VuIjoicHVz - * aF90b2tlbiIsInR5cGUiOiJub3JtYWwiLCJ1dWlkIjoidXVpZCJ9"} - * - response: - * {"status":"success","challenge":"GU4usvpYfvQ_RCMSqm819gTZMa0qCeLr1Xg2KbvW2To"} - * - * Example for two_step: - * - request: - * username: test1 - * tokenResponse: {"registrationData":"BQToXkGAjgXxC4g1NiA-IuRAu40NFBlXXNSu4TEZqGK5TBqwU07ANn4LJ9Hp3aV5 - * PIvCDVsQ2tZJf1xD6LosZNDuQGCb1g_Z-NHiLqyJybzylKMaSs65XlDFoLvcN7_zVAbuwYhgHJYJB_2YPPP0-cukYe_Ipk8U4dHY - * 1hWBuI8ToscwggImMIIBzKADAgECAoGBAPMsD5b5G58AphKuKWl4Yz27sbE_rXFy7nPRqtJ_r4E5DSZbFvfyuos-Db0095ubB0Jo - * yM8ccmSO_eZQ6IekOLPKCR7yC5kes-f7MaxyaphmmD4dEvmuKjF-fRsQP5tQG7zerToto8eIz0XjPaupiZxQXtSHGHHTuPhri2nf - * oZlrMAoGCCqGSM49BAMCMFwxIDAeBgNVBAMTF0dsdXUgb3hQdXNoMiBVMkYgdjEuMC4wMQ0wCwYDVQQKEwRHbHV1MQ8wDQYDVQQH - * EwZBdXN0aW4xCzAJBgNVBAgTAlRYMQswCQYDVQQGEwJVUzAeFw0xNjAzMDExODU5NDZaFw0xOTAzMDExODU5NDZaMFwxIDAeBgNV - * BAMTF0dsdXUgb3hQdXNoMiBVMkYgdjEuMC4wMQ0wCwYDVQQKEwRHbHV1MQ8wDQYDVQQHEwZBdXN0aW4xCzAJBgNVBAgTAlRYMQsw - * CQYDVQQGEwJVUzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABICUKnzCE5PJ7tihiKkYu6E5Uy_sZ-RSqs_MnUJt0tB8G8GSg9nK - * o6P2424iV9lXX9Pil8qw4ofZ-fAXXepbp4MwCgYIKoZIzj0EAwIDSAAwRQIgUWwawAB2udURWQziDXVjSOi_QcuXiRxylqj5thFw - * FhYCIQCGY-CTZFi7JdkhZ05nDpbSYJBTOo1Etckh7k0qcvnO0TBFAiArOYmHd22USw7flCmGXLOXVOrhDi-pkX7Qx_c8oz5hJQIh - * AOslo3LfymoFWT6mxUZjBlxKgxioozd0KmzUwobRcKdW","clientData":"eyJ0eXAiOiJuYXZpZ2F0b3IuaWQuZmluaXNoRW5y - * b2xsbWVudCIsImNoYWxsZW5nZSI6InJhUGZtcVpPSGxIRjRnWGJwcmQyOXV3WC1iczNGZjV2MDNxdXhCRDRGa00iLCJvcmlnaW4i - * OiJodHRwczpcL1wveXVyZW0tZW1lcmdpbmctcGlnLmdsdXUuaW5mbyJ9","deviceData":"eyJuYW1lIjoiU00tRzk5MUIiLCJv - * c19uYW1lIjoidGlyYW1pc3UiLCJvc192ZXJzaW9uIjoiMTMiLCJwbGF0Zm9ybSI6ImFuZHJvaWQiLCJwdXNoX3Rva2VuIjoicHVz - * aF90b2tlbiIsInR5cGUiOiJub3JtYWwiLCJ1dWlkIjoidXVpZCJ9"} - * - response: - * {"status":"success","challenge":"raPfmqZOHlHF4gXbprd29uwX-bs3Ff5v03quxBD4FkM"} - * - */ - public JsonNode finishRegistration(String userName, String registerResponseString) { - RegisterResponse registerResponse = parseRegisterResponse(registerResponseString); - - //ObjectNode params = buildFido2AttestationVerifyResponse(userName, registerResponse); - AttestationResult attestationResult = buildFido2AttestationVerifyResponse(userName, registerResponse); - AttestationOrAssertionResponse attestationResultResponse = attestationService.verify(attestationResult); - ObjectNode result = (ObjectNode)CommonUtilService.toJsonNode(attestationResultResponse); - - result.put("status", "success"); - result.put("challenge", registerResponse.getClientData().getChallenge()); - - return result; - } - - public RegisterResponse parseRegisterResponse(String registerResponseString) { - RegisterResponse registerResponse; - try { - registerResponse = dataMapperService.readValue(registerResponseString, RegisterResponse.class); - } catch (IOException ex) { - throw errorResponseFactory.invalidRequest("Failed to parse options attestation request", ex); - } - - return registerResponse; - } - - public AttestationResult buildFido2AttestationVerifyResponse(String userName, RegisterResponse registerResponse) { - if (!ArrayUtils.contains(RawRegistrationService.SUPPORTED_REGISTER_TYPES, registerResponse.getClientData().getTyp())) { - throw errorResponseFactory.badRequestException(AttestationErrorResponseType.UNSUPPORTED_REGISTER_TYPE, "Invalid options attestation request type"); - } - AttestationResult attestationResult = new AttestationResult(); - attestationResult.setSuperGluuRequest(true); - - // Add all required parameters from request to allow process U2F request - boolean oneStep = StringHelper.isEmpty(userName); - attestationResult.setSuperGluuRequestMode(oneStep ? SuperGluuMode.ONE_STEP.getMode() : SuperGluuMode.TWO_STEP.getMode()); - - // Add response node - Response response = new Response(); - attestationResult.setResponse(response); - attestationResult.getResponse().setDeviceData(registerResponse.getDeviceData()); - - // Convert clientData node to new format - ObjectNode clientData = dataMapperService.createObjectNode(); - clientData.put("challenge", registerResponse.getClientData().getChallenge()); - clientData.put("origin", registerResponse.getClientData().getOrigin()); - clientData.put("type", registerResponse.getClientData().getTyp()); - attestationResult.getResponse().setClientDataJSON(base64Service.urlEncodeToString(clientData.toString().getBytes(StandardCharsets.UTF_8))); - // Store cancel type - attestationResult.setSuperGluuRequestCancel(StringHelper.equals(RawRegistrationService.REGISTER_CANCEL_TYPE, registerResponse.getClientData().getTyp())); - // Prepare attestationObject - RawRegisterResponse rawRegisterResponse = rawRegistrationService.parseRawRegisterResponse(registerResponse.getRegistrationData()); - - attestationResult.setId(base64Service.urlEncodeToString(rawRegisterResponse.getKeyHandle())); - ObjectNode attestationObject = dataMapperService.createObjectNode(); - ObjectNode attStmt = dataMapperService.createObjectNode(); - - try { - ArrayNode x5certs = attStmt.putArray("x5c"); - x5certs.add(base64Service.encodeToString(rawRegisterResponse.getAttestationCertificate().getEncoded())); - attStmt.put("sig", rawRegisterResponse.getSignature()); - - attestationObject.put("fmt", AttestationFormat.fido_u2f_super_gluu.getFmt()); - attestationObject.set("attStmt", attStmt); - - byte[] authData = generateAuthData(registerResponse.getClientData(), rawRegisterResponse); - attestationObject.put("authData", authData); - - attestationResult.getResponse().setAttestationObject(base64Service.urlEncodeToString(dataMapperService.cborWriteAsBytes(attestationObject))); - } catch (CertificateEncodingException e) { - throw errorResponseFactory.invalidRequest("Failed during encoding attestationCertificate", e); - } catch (IOException e) { - throw errorResponseFactory.invalidRequest("Failed to prepare attestationObject", e); - } - - log.debug("Prepared U2F_V2 attestation verify request: {}", attestationResult.toString()); - return attestationResult; - } - - private byte[] generateAuthData(ClientData clientData, RawRegisterResponse rawRegisterResponse) throws IOException { - byte[] rpIdHash = digestService.hashSha256(clientData.getOrigin()); - byte[] flags = new byte[] { AuthenticatorDataParser.FLAG_USER_PRESENT | AuthenticatorDataParser.FLAG_ATTESTED_CREDENTIAL_DATA_INCLUDED }; - byte[] counter = ByteBuffer.allocate(4).putInt(0).array(); - - byte[] aaguid = ByteBuffer.allocate(16).array(); - - byte[] credIDBuffer = rawRegisterResponse.getKeyHandle(); - - byte[] credIDLenBuffer = ByteBuffer.allocate(2).putShort((short) credIDBuffer.length).array(); - - - JsonNode uncompressedECPoint = coseService.convertECKeyToUncompressedPoint( - rawRegisterResponse.getUserPublicKey()); - - byte[] cosePublicKeyBuffer = dataMapperService.cborWriteAsBytes(uncompressedECPoint); - - byte[] authData = ByteBuffer - .allocate(rpIdHash.length + flags.length + counter.length + aaguid.length + credIDLenBuffer.length - + credIDBuffer.length + cosePublicKeyBuffer.length) - .put(rpIdHash).put(flags).put(counter).put(aaguid).put(credIDLenBuffer).put(credIDBuffer) - .put(cosePublicKeyBuffer).array(); - - return authData; - } - -} diff --git a/jans-fido2/server/src/main/java/io/jans/fido2/service/verifier/CommonVerifiers.java b/jans-fido2/server/src/main/java/io/jans/fido2/service/verifier/CommonVerifiers.java index 9da3c319c95..5b18db6c488 100644 --- a/jans-fido2/server/src/main/java/io/jans/fido2/service/verifier/CommonVerifiers.java +++ b/jans-fido2/server/src/main/java/io/jans/fido2/service/verifier/CommonVerifiers.java @@ -40,7 +40,6 @@ import io.jans.fido2.service.Base64Service; import io.jans.fido2.service.DataMapperService; import io.jans.fido2.service.processors.AttestationFormatProcessor; -import io.jans.fido2.sg.SuperGluuMode; import io.jans.orm.model.fido2.UserVerification; import io.jans.service.net.NetworkService; import io.jans.util.StringHelper; @@ -57,12 +56,6 @@ @ApplicationScoped public class CommonVerifiers { - public static final String SUPER_GLUU_REQUEST = "super_gluu_request"; - public static final String SUPER_GLUU_MODE = "super_gluu_request_mode"; - public static final String SUPER_GLUU_REQUEST_CANCEL = "super_gluu_request_cancel"; - public static final String SUPER_GLUU_APP_ID = "super_gluu_app_id"; - public static final String SUPER_GLUU_KEY_HANDLE = "super_gluu_key_handle"; - @Inject private Logger log; @@ -435,45 +428,7 @@ public void verifyThatMetadataIsValid(JsonNode metadata) { } } - public boolean hasSuperGluu(JsonNode params) { - if (params.hasNonNull(SUPER_GLUU_REQUEST)) { - JsonNode node = params.get(SUPER_GLUU_REQUEST); - return node.isBoolean() && node.asBoolean(); - } - - return false; - } - - public void verifyNotUseGluuParameters(JsonNode params) { - // Protect generic U2F/Fido2 from sending requests with Super Gluu parameters - if (params.hasNonNull(SUPER_GLUU_REQUEST) || params.hasNonNull(SUPER_GLUU_MODE) || - params.hasNonNull(SUPER_GLUU_APP_ID) || params.hasNonNull(SUPER_GLUU_KEY_HANDLE) || - params.hasNonNull(SUPER_GLUU_REQUEST_CANCEL)) { - throw errorResponseFactory.badRequestException(AssertionErrorResponseType.CONFLICT_WITH_SUPER_GLUU, "Input request conflicts with Super Gluu parameters"); - } - } - - public boolean isSuperGluuOneStepMode(JsonNode params) { - if (!hasSuperGluu(params)) { - return false; - } - if (!params.hasNonNull(SUPER_GLUU_MODE)) { - return false; - } - JsonNode node = params.get(SUPER_GLUU_MODE); - return SuperGluuMode.ONE_STEP == SuperGluuMode.fromModeValue(node.asText()); - } - - public boolean isSuperGluuCancelRequest(JsonNode params) { - if (!hasSuperGluu(params)) { - return false; - } - if (!params.hasNonNull(SUPER_GLUU_REQUEST_CANCEL)) { - return false; - } - JsonNode node = params.get(SUPER_GLUU_REQUEST_CANCEL); - return node.isBoolean() && node.asBoolean(); - } + private void validateNodeNotNull(JsonNode node) throws Fido2RuntimeException { if ((node == null) || node.isNull()) { diff --git a/jans-fido2/server/src/main/java/io/jans/fido2/ws/rs/controller/AssertionController.java b/jans-fido2/server/src/main/java/io/jans/fido2/ws/rs/controller/AssertionController.java index 647a664be2e..31d7ba243da 100644 --- a/jans-fido2/server/src/main/java/io/jans/fido2/ws/rs/controller/AssertionController.java +++ b/jans-fido2/server/src/main/java/io/jans/fido2/ws/rs/controller/AssertionController.java @@ -13,7 +13,7 @@ import io.jans.fido2.model.error.ErrorResponseFactory; import io.jans.fido2.service.DataMapperService; import io.jans.fido2.service.operation.AssertionService; -import io.jans.fido2.service.sg.converter.AssertionSuperGluuController; + import io.jans.fido2.service.util.CommonUtilService; import io.jans.fido2.service.verifier.CommonVerifiers; import jakarta.enterprise.context.ApplicationScoped; @@ -43,9 +43,6 @@ public class AssertionController { @Inject private DataMapperService dataMapperService; - @Inject - private AssertionSuperGluuController assertionSuperGluuController; - @Inject private AppConfiguration appConfiguration; @@ -64,7 +61,6 @@ public Response authenticate(@NotNull AssertionOptions assertionOptions) { if (appConfiguration.getFido2Configuration() == null) { throw errorResponseFactory.forbiddenException(); } - commonVerifiers.verifyNotUseGluuParameters(CommonUtilService.toJsonNode(assertionOptions)); AssertionOptionsResponse result = assertionService.options(assertionOptions); return Response.ok().entity(result).build(); }); @@ -94,42 +90,14 @@ public Response verify(@NotNull AssertionResult assertionResult) { if (appConfiguration.getFido2Configuration() == null) { throw errorResponseFactory.forbiddenException(); } - commonVerifiers.verifyNotUseGluuParameters(CommonUtilService.toJsonNode(assertionResult)); AttestationOrAssertionResponse result = assertionService.verify(assertionResult); return Response.ok().entity(result).build(); }); } - @GET - @Produces({"application/json"}) - @Path("/authentication") - public Response startAuthentication(@QueryParam("username") String userName, @QueryParam("keyhandle") String keyHandle, @QueryParam("application") String appId, @QueryParam("session_id") String sessionId) { - return processRequest(() -> { - if ((appConfiguration.getFido2Configuration() == null) && !appConfiguration.isSuperGluuEnabled()) { - throw errorResponseFactory.forbiddenException(); - } - log.debug("Start authentication: username = {}, keyhandle = {}, application = {}, session_id = {}", userName, keyHandle, appId, sessionId); - JsonNode result = assertionSuperGluuController.startAuthentication(userName, keyHandle, appId, sessionId); - log.debug("Prepared U2F_V2 authentication options request: {}", result.toString()); - return Response.ok().entity(result).build(); - }); - } - - @POST - @Produces({"application/json"}) - @Path("/authentication") - public Response finishAuthentication(@FormParam("username") String userName, @FormParam("tokenResponse") String authenticateResponseString) { - return processRequest(() -> { - if ((appConfiguration.getFido2Configuration() == null) && !appConfiguration.isSuperGluuEnabled()) { - throw errorResponseFactory.forbiddenException(); - } - log.debug("Finish authentication: username = {}, tokenResponse = {}", userName, authenticateResponseString); - JsonNode result = assertionSuperGluuController.finishAuthentication(userName, authenticateResponseString); - log.debug("Prepared U2F_V2 authentication verify request: {}", result.toString()); - return Response.ok().entity(result).build(); - }); - } + + private Response processRequest(RequestProcessor processor) { try { return processor.process(); diff --git a/jans-fido2/server/src/main/java/io/jans/fido2/ws/rs/controller/AttestationController.java b/jans-fido2/server/src/main/java/io/jans/fido2/ws/rs/controller/AttestationController.java index 7700b5bf8fa..fba1e23434b 100644 --- a/jans-fido2/server/src/main/java/io/jans/fido2/ws/rs/controller/AttestationController.java +++ b/jans-fido2/server/src/main/java/io/jans/fido2/ws/rs/controller/AttestationController.java @@ -15,7 +15,6 @@ import io.jans.fido2.model.error.ErrorResponseFactory; import io.jans.fido2.service.DataMapperService; import io.jans.fido2.service.operation.AttestationService; -import io.jans.fido2.service.sg.converter.AttestationSuperGluuController; import io.jans.fido2.service.util.CommonUtilService; import io.jans.fido2.service.verifier.CommonVerifiers; import jakarta.enterprise.context.ApplicationScoped; @@ -50,9 +49,6 @@ public class AttestationController { @Inject private CommonVerifiers commonVerifiers; - @Inject - private AttestationSuperGluuController attestationSuperGluuController; - @Inject private AppConfiguration appConfiguration; @@ -68,7 +64,6 @@ public Response register(@NotNull AttestationOptions attestationOptions) { if (appConfiguration.getFido2Configuration() == null) { throw errorResponseFactory.forbiddenException(); } - commonVerifiers.verifyNotUseGluuParameters(CommonUtilService.toJsonNode(attestationOptions)); PublicKeyCredentialCreationOptions result = attestationService.options(attestationOptions); return Response.ok().entity(result).build(); }); @@ -83,44 +78,14 @@ public Response verify(@NotNull AttestationResult attestationResult) { if (appConfiguration.getFido2Configuration() == null) { throw errorResponseFactory.forbiddenException(); } - commonVerifiers.verifyNotUseGluuParameters(CommonUtilService.toJsonNode(attestationResult)); AttestationOrAssertionResponse result = attestationService.verify(attestationResult); return Response.ok().entity(result).build(); }); } - @GET - @Produces({"application/json"}) - @Path("/registration") - public Response startRegistration(@QueryParam("username") String userName, - @QueryParam("application") String appId, - @QueryParam("session_id") String sessionId, - @QueryParam("enrollment_code") String enrollmentCode) { - return processRequest(() -> { - if ((appConfiguration.getFido2Configuration() == null) && !appConfiguration.isSuperGluuEnabled()) { - throw errorResponseFactory.forbiddenException(); - } - log.debug("Start registration: username = {}, application = {}, session_id = {}, enrollment_code = {}", userName, appId, sessionId, enrollmentCode); - JsonNode result = attestationSuperGluuController.startRegistration(userName, appId, sessionId, enrollmentCode); - log.debug("Prepared U2F_V2 registration options request: {}", result.toString()); - return Response.ok().entity(result).build(); - }); - } + - @POST - @Produces({"application/json"}) - @Path("/registration") - public Response finishRegistration(@FormParam("username") String userName, @FormParam("tokenResponse") String registerResponseString) { - return processRequest(() -> { - if ((appConfiguration.getFido2Configuration() == null) && !appConfiguration.isSuperGluuEnabled()) { - throw errorResponseFactory.forbiddenException(); - } - log.debug("Finish registration: username = {}, tokenResponse = {}", userName, registerResponseString); - JsonNode result = attestationSuperGluuController.finishRegistration(userName, registerResponseString); - log.debug("Prepared U2F_V2 registration verify request: {}", result.toString()); - return Response.ok().entity(result).build(); - }); - } + private Response processRequest(RequestProcessor processor) { try { diff --git a/jans-fido2/server/src/main/java/io/jans/fido2/ws/rs/controller/ConfigurationController.java b/jans-fido2/server/src/main/java/io/jans/fido2/ws/rs/controller/ConfigurationController.java index 199a53654ec..9de12b5ed7d 100644 --- a/jans-fido2/server/src/main/java/io/jans/fido2/ws/rs/controller/ConfigurationController.java +++ b/jans-fido2/server/src/main/java/io/jans/fido2/ws/rs/controller/ConfigurationController.java @@ -71,11 +71,6 @@ public Response getConfiguration() { */ assertion.put("result_endpoint", baseEndpointUri + "/assertion/result"); - if (appConfiguration.isSuperGluuEnabled()) { - response.put("super_gluu_registration_endpoint", baseEndpointUri + "/attestation/registration"); - response.put("super_gluu_authentication_endpoint", baseEndpointUri + "/assertion/authentication"); - } - ResponseBuilder builder = Response.ok().entity(response.toString()); return builder.build(); } diff --git a/jans-fido2/server/src/main/java/io/jans/u2f/service/persist/DeviceRegistrationService.java b/jans-fido2/server/src/main/java/io/jans/u2f/service/persist/DeviceRegistrationService.java index 352d2ff1516..a233f8052d5 100644 --- a/jans-fido2/server/src/main/java/io/jans/u2f/service/persist/DeviceRegistrationService.java +++ b/jans-fido2/server/src/main/java/io/jans/u2f/service/persist/DeviceRegistrationService.java @@ -123,7 +123,7 @@ public void migrateToFido2(List fidoRegistrations, String do // Save converted Fido2 entry Date enrollmentDate = fidoRegistration.getCreationDate(); - Fido2RegistrationEntry fido2RegistrationEntry = registrationPersistenceService.buildFido2RegistrationEntry(fido2RegistrationData, false); + Fido2RegistrationEntry fido2RegistrationEntry = registrationPersistenceService.buildFido2RegistrationEntry(fido2RegistrationData); // Restore dates modified by buildFido2RegistrationEntry fido2RegistrationEntry.getRegistrationData().setCreatedDate(enrollmentDate); diff --git a/jans-fido2/server/src/test/java/io/jans/fido2/service/sg/FullFlowAndroidTest.java b/jans-fido2/server/src/test/java/io/jans/fido2/service/sg/FullFlowAndroidTest.java deleted file mode 100644 index 47eb45740c5..00000000000 --- a/jans-fido2/server/src/test/java/io/jans/fido2/service/sg/FullFlowAndroidTest.java +++ /dev/null @@ -1,469 +0,0 @@ -/* - * Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. - * - * Copyright (c) 2023, Janssen Project - */ - -package io.jans.fido2.service.sg; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyBoolean; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.ArgumentMatchers.eq; - -import java.util.Arrays; -import java.util.Optional; - -import org.jboss.weld.junit5.auto.ExcludeBean; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.BeforeEach; -import org.mockito.ArgumentCaptor; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.Mockito; -import org.mockito.MockitoAnnotations; - -import io.jans.as.common.model.common.User; -import io.jans.as.model.config.BaseDnConfiguration; -import io.jans.as.model.config.StaticConfiguration; -import io.jans.as.model.fido.u2f.protocol.AuthenticateResponse; -import io.jans.as.model.fido.u2f.protocol.RegisterResponse; -import io.jans.fido2.model.assertion.AssertionOptions; -import io.jans.fido2.model.assertion.AssertionOptionsResponse; -import io.jans.fido2.model.assertion.AssertionResult; -import io.jans.fido2.model.attestation.AttestationOptions; -import io.jans.fido2.model.attestation.AttestationResult; -import io.jans.fido2.model.attestation.PublicKeyCredentialCreationOptions; -import io.jans.fido2.model.common.AttestationOrAssertionResponse; -import io.jans.fido2.model.conf.AppConfiguration; -import io.jans.fido2.model.conf.Fido2Configuration; -import io.jans.fido2.model.error.ErrorResponseFactory; -import io.jans.fido2.service.ChallengeGenerator; -import io.jans.fido2.service.operation.AssertionService; -import io.jans.fido2.service.operation.AttestationService; -import io.jans.fido2.service.persist.AuthenticationPersistenceService; -import io.jans.fido2.service.persist.RegistrationPersistenceService; -import io.jans.fido2.service.persist.UserSessionIdService; -import io.jans.fido2.service.processor.attestation.U2FSuperGluuAttestationProcessor; -import io.jans.fido2.service.sg.converter.AssertionSuperGluuController; -import io.jans.fido2.service.sg.converter.AttestationSuperGluuController; -import io.jans.fido2.service.shared.CustomScriptService; -import io.jans.fido2.service.shared.UserService; -import io.jans.fido2.service.verifier.AssertionVerifier; -import io.jans.fido2.sg.SuperGluuMode; -import io.jans.orm.PersistenceEntryManager; -import io.jans.orm.model.fido2.Fido2AuthenticationEntry; -import io.jans.orm.model.fido2.Fido2AuthenticationStatus; -import io.jans.orm.model.fido2.Fido2RegistrationEntry; -import io.jans.orm.model.fido2.Fido2RegistrationStatus; -import io.jans.u2f.service.persist.DeviceRegistrationService; -import io.jans.util.security.SecurityProviderUtility; -import jakarta.enterprise.context.ApplicationScoped; -import jakarta.enterprise.inject.Produces; -import jakarta.inject.Inject; - -/** - * @author Yuriy Movchan - * @version 0.1, 17/02/2023 - */ -/*@EnableAutoWeld -@ExtendWith(WeldJunit5AutoExtension.class) -@TestMethodOrder(OrderAnnotation.class) -@AddBeanClasses(io.jans.service.util.Resources.class) -@AddBeanClasses(io.jans.service.net.NetworkService.class) -@ExplicitParamInjection*/ -public class FullFlowAndroidTest { - - private String issuer; - private String attestationChallenge; - private String assertionChallenge; - - // Static to store value between tests executions - static Fido2RegistrationEntry registrationEntry; - static Fido2AuthenticationEntry authenticationEntry; - - private AutoCloseable closeable; - - @Inject - AttestationSuperGluuController attestationSuperGluuController; - - @Inject - AssertionSuperGluuController assertionSuperGluuController; - - @Inject - U2FSuperGluuAttestationProcessor attestationProcessor; - - @Inject - AssertionVerifier assertionFormatProcessor; - - @Inject - AttestationService attestationService; - - @Inject - AssertionService assertionService; - - @Mock - @Produces - @ExcludeBean - UserService userService = Mockito.mock(UserService.class); - - @Mock - @Produces - @ExcludeBean - PersistenceEntryManager persistenceEntryManager = Mockito.mock(PersistenceEntryManager.class); - - @Mock - @Produces - @ExcludeBean - CustomScriptService customScriptService = Mockito.mock(CustomScriptService.class); - - @Mock - @Produces - @ExcludeBean - DeviceRegistrationService deviceRegistrationService = Mockito.mock(DeviceRegistrationService.class); - - @Mock - @Produces - @ExcludeBean - ErrorResponseFactory errorResponseFactory = Mockito.mock(ErrorResponseFactory.class); - - @Mock - ChallengeGenerator challengeGenerator = Mockito.mock(ChallengeGenerator.class); - - @InjectMocks - RegistrationPersistenceService registrationPersistenceService = Mockito.mock(RegistrationPersistenceService.class); - - @InjectMocks - AuthenticationPersistenceService authenticationPersistenceService = Mockito.mock(AuthenticationPersistenceService.class); - - @BeforeAll - public static void beforeAll() { - SecurityProviderUtility.installBCProvider(); - } - - @BeforeEach - void initService() { - closeable = MockitoAnnotations.openMocks(this); - } - - @AfterEach - void closeService() throws Exception { - closeable.close(); - } - - @ApplicationScoped - @Produces - StaticConfiguration produceStaticConfiguration() { - StaticConfiguration staticConfiguration = Mockito.mock(StaticConfiguration.class); - - BaseDnConfiguration baseDnConfiguration = new BaseDnConfiguration(); - Mockito.when(staticConfiguration.getBaseDn()).thenReturn(baseDnConfiguration); - - return staticConfiguration; - } - - @ApplicationScoped - @Produces - AppConfiguration produceAppConfiguration() { - AppConfiguration appConfiguration = Mockito.mock(AppConfiguration.class); - - Fido2Configuration fido2Configuration = new Fido2Configuration(); - Mockito.when(appConfiguration.getFido2Configuration()).thenReturn(fido2Configuration); - Mockito.when(appConfiguration.getIssuer()).thenReturn(issuer); - - return appConfiguration; - } - - @ApplicationScoped - @Produces - @ExcludeBean - RegistrationPersistenceService produceRegistrationPersistenceService() { - Mockito.when(registrationPersistenceService.buildFido2RegistrationEntry(any(), anyBoolean())).thenCallRealMethod(); - Mockito.doCallRealMethod().when(registrationPersistenceService).update(any(Fido2RegistrationEntry.class)); - if (registrationEntry != null) { - Mockito.when(registrationPersistenceService.findByChallenge(eq(registrationEntry.getChallange()), anyBoolean())).thenReturn(Arrays.asList(registrationEntry)); - Mockito.when(registrationPersistenceService.findByPublicKeyId(eq(registrationEntry.getPublicKeyId()), eq(registrationEntry.getRpId()))).thenReturn(Optional.of(registrationEntry)); - Mockito.when(registrationPersistenceService.findByPublicKeyId(anyString(), eq(registrationEntry.getPublicKeyId()), eq(registrationEntry.getRpId()))).thenReturn(Optional.of(registrationEntry)); - } - - Mockito.when(userService.getUser(anyString(), any())).thenReturn(new User()); - - return registrationPersistenceService; - } - - @ApplicationScoped - @Produces - @ExcludeBean - AuthenticationPersistenceService produceAuthenticationPersistenceService() { - Mockito.when(authenticationPersistenceService.buildFido2AuthenticationEntry(any(), anyBoolean())).thenCallRealMethod(); - Mockito.doCallRealMethod().when(authenticationPersistenceService).update(any(Fido2AuthenticationEntry.class)); - if (authenticationEntry != null) { - Mockito.when(authenticationPersistenceService.findByChallenge(eq(authenticationEntry.getChallange()), anyBoolean())).thenReturn(Arrays.asList(authenticationEntry)); - } - - return authenticationPersistenceService; - } - - @ApplicationScoped - @Produces - @ExcludeBean - ChallengeGenerator produceChallengeGenerator() { - Mockito.when(challengeGenerator.getAttestationChallenge()).thenReturn(attestationChallenge); - Mockito.when(challengeGenerator.getAssertionChallenge()).thenReturn(assertionChallenge); - - return challengeGenerator; - } - - @ApplicationScoped - @Produces - @ExcludeBean - UserSessionIdService produceUserSessionIdService() { - return Mockito.when(Mockito.mock(UserSessionIdService.class).isValidSessionId(anyString(), anyString())) - .thenReturn(true).getMock(); - } - - public void testStartAttestationTwoStepAndroidImpl(String issuer, String challenge, String userName, - String applicationId, String sessionId) { - this.issuer = issuer; - this.attestationChallenge = challenge; - - AttestationOptions attestationOptions = attestationSuperGluuController.buildFido2AttestationStartResponse(userName, applicationId, sessionId); - System.out.println(attestationOptions.toString()); - assertEquals(true, attestationOptions.getSuperGluuRequest()); - assertEquals(SuperGluuMode.TWO_STEP.getMode(), attestationOptions.getSuperGluuRequestMode()); - assertEquals(applicationId, attestationOptions.getSuperGluuAppId()); - - PublicKeyCredentialCreationOptions response = attestationService.options(attestationOptions); - - // Get saved entry for finish attestation test - ArgumentCaptor captor = ArgumentCaptor.forClass(Fido2RegistrationEntry.class); - Mockito.verify(registrationPersistenceService).save(captor.capture()); - registrationEntry = captor.getValue(); - - assertNotNull(registrationEntry); - assertNotNull(response); - assertEquals(challenge, response.getChallenge()); - - assertEquals(Fido2RegistrationStatus.pending, registrationEntry.getRegistrationStatus()); - } - - public void testFinishAttestationTwoStepAndroidAuthenticatedImpl(String userName, String registerFinishResponse, String registeredPublicKey) { - // Parse register response - RegisterResponse registerResponse = attestationSuperGluuController.parseRegisterResponse(registerFinishResponse); - - AttestationResult request = attestationSuperGluuController.buildFido2AttestationVerifyResponse(userName, registerResponse); - assertEquals(true, request.getSuperGluuRequest()); - assertEquals(SuperGluuMode.TWO_STEP.getMode(), request.getSuperGluuRequestMode()); - - AttestationOrAssertionResponse response = attestationService.verify(request); - - // Get updated entry for checks - ArgumentCaptor captor = ArgumentCaptor.forClass(Fido2RegistrationEntry.class); - Mockito.verify(registrationPersistenceService).update(captor.capture()); - registrationEntry = captor.getValue(); - - assertNotNull(response); - assertEquals("ok", response.getStatus()); - assertEquals(registeredPublicKey, response.getCredentials().getId()); - } - - public void testFinishAttestationTwoStepAndroidAuthenticatedRegistered(String userName, String registerFinishResponse, String registeredPublicKey) { - testFinishAttestationTwoStepAndroidAuthenticatedImpl(userName, registerFinishResponse, registeredPublicKey); - - assertEquals(Fido2RegistrationStatus.registered, registrationEntry.getRegistrationStatus()); - } - - public void testFinishAssertionTwoStepAndroidAuthenticatedCanceled(String userName, String registerFinishResponse, String registeredPublicKey) { - testFinishAttestationTwoStepAndroidAuthenticatedImpl(userName, registerFinishResponse, registeredPublicKey); - - assertEquals(Fido2RegistrationStatus.canceled, registrationEntry.getRegistrationStatus()); - } - - public void testStartAssertionTwoStepAndroidImpl(String issuer, String challenge, String userName, - String applicationId, String sessionId) { - this.issuer = issuer; - this.assertionChallenge = challenge; - - AssertionOptions request = assertionSuperGluuController.buildFido2AssertionStartResponse(userName, registrationEntry.getPublicKeyId(), applicationId, sessionId); - assertEquals(true, request.getSuperGluuRequest()); - assertEquals(SuperGluuMode.TWO_STEP.getMode(), request.getSuperGluuRequestMode()); - assertEquals(registrationEntry.getPublicKeyId(), request.getSuperGluuKeyHandle()); - assertEquals(applicationId, request.getSuperGluuAppId()); - - AssertionOptionsResponse response = assertionService.options(request); - - // Get saved entry for finish authentication test - ArgumentCaptor captor = ArgumentCaptor.forClass(Fido2AuthenticationEntry.class); - Mockito.verify(authenticationPersistenceService).save(captor.capture()); - authenticationEntry = captor.getValue(); - - assertNotNull(authenticationEntry); - assertNotNull(response); - assertTrue(response.getAllowCredentials().size() > 0); - assertEquals(registrationEntry.getPublicKeyId(), response.getAllowCredentials().get(0).getId()); - - assertEquals(Fido2AuthenticationStatus.pending, authenticationEntry.getAuthenticationStatus()); - } - - public void testFinishAssertionTwoStepAndroidImpl(String userName, String authenticateFinishResponse) { - // Parse register response - AuthenticateResponse authenticateResponse = assertionSuperGluuController.parseAuthenticateResponse(authenticateFinishResponse); - - AssertionResult request = assertionSuperGluuController.buildFido2AuthenticationVerifyResponse(userName, authenticateFinishResponse, authenticateResponse); - assertEquals(true, request.getSuperGluuRequest()); - assertEquals(SuperGluuMode.TWO_STEP.getMode(), request.getSuperGluuRequestMode()); - - AttestationOrAssertionResponse response = assertionService.verify(request); - - // Get updated entry for checks - ArgumentCaptor captorAssertion = ArgumentCaptor.forClass(Fido2AuthenticationEntry.class); - Mockito.verify(authenticationPersistenceService).update(captorAssertion.capture()); - authenticationEntry = captorAssertion.getValue(); - - ArgumentCaptor captorAttestation = ArgumentCaptor.forClass(Fido2RegistrationEntry.class); - Mockito.verify(registrationPersistenceService).update(captorAttestation.capture()); - registrationEntry = captorAttestation.getValue(); - - assertNotNull(response); - assertEquals("ok", response.getStatus()); - assertEquals(registrationEntry.getPublicKeyId(), response.getCredentials().getId()); - } - - public void testFinishAssertionTwoStepAndroidAuthenticated(String userName, String authenticateFinishResponse) { - testFinishAssertionTwoStepAndroidImpl(userName, authenticateFinishResponse); - - assertEquals(Fido2AuthenticationStatus.authenticated, authenticationEntry.getAuthenticationStatus()); - } - - public void testFinishAssertionTwoStepAndroidCanceled(String userName, String authenticateFinishResponse) { - testFinishAssertionTwoStepAndroidImpl(userName, authenticateFinishResponse); - - assertEquals(Fido2AuthenticationStatus.canceled, authenticationEntry.getAuthenticationStatus()); - } - - /*@Test - @Order(1) - @ExtendWith(FileParameterExtension.class) - public void testStartAttestationTwoStepAndroid(@Name("attestation.android.two-step.issuer") String issuer, @Name("attestation.android.two-step.challenge") String challenge, - @Name("attestation.android.two-step.userName") String userName, @Name("attestation.android.two-step.applicationId") String applicationId, - @Name("attestation.android.two-step.sessionId") String sessionId, @Name("attestation.android.two-step.enrollmentCode") String enrollmentCode) { - testStartAttestationTwoStepAndroidImpl(issuer, challenge, userName, applicationId, sessionId); - } - - @Test - @Order(2) - @ExtendWith(FileParameterExtension.class) - public void testFinishAttestationTwoStepAndroid(@Name("attestation.android.two-step.userName") String userName, - @Name("attestation.android.two-step.finish.request") String registerFinishResponse, @Name("attestation.android.two-step.finish.publicKeyId") String publicKeyId) { - testFinishAttestationTwoStepAndroidAuthenticatedRegistered(userName, registerFinishResponse, publicKeyId); - } - - @Test - @Order(3) - @ExtendWith(FileParameterExtension.class) - public void testStartAssertionTwoStepAndroid(@Name("attestation.android.two-step.issuer") String issuer, @Name("assertion.android.two-step.challenge") String challenge, - @Name("attestation.android.two-step.userName") String userName, @Name("attestation.android.two-step.applicationId") String applicationId, - @Name("attestation.android.two-step.sessionId") String sessionId) { - - testStartAssertionTwoStepAndroidImpl(issuer, challenge, userName, applicationId, sessionId); - } - - @Test - @Order(4) - @ExtendWith(FileParameterExtension.class) - public void testFinishAssertionTwoStepAndroid(@Name("attestation.android.two-step.userName") String userName, - @Name("assertion.android.two-step.finish.request") String authenticateFinishResponse) { - testFinishAssertionTwoStepAndroidAuthenticated(userName, authenticateFinishResponse); - assertTrue(registrationEntry.getCounter() == 1); - } - - @Test - @Order(5) - @ExtendWith(FileParameterExtension.class) - public void testSecondStartAssertionTwoStepAndroid(@Name("attestation.android.two-step.issuer") String issuer, @Name("assertion.android.two-step.challenge2") String challenge, - @Name("attestation.android.two-step.userName") String userName, @Name("attestation.android.two-step.applicationId") String applicationId, - @Name("attestation.android.two-step.sessionId") String sessionId) { - testStartAssertionTwoStepAndroidImpl(issuer, challenge, userName, applicationId, sessionId); - } - - @Test - @Order(6) - @ExtendWith(FileParameterExtension.class) - public void testSecondFinishAssertionTwoStepAndroid(@Name("attestation.android.two-step.userName") String userName, - @Name("assertion.android.two-step.finish.request2") String authenticateFinishResponse) { - testFinishAssertionTwoStepAndroidAuthenticated(userName, authenticateFinishResponse); - assertTrue(registrationEntry.getCounter() == 2); - } - - @Test - @Order(7) - @ExtendWith(FileParameterExtension.class) - public void testThirdStartAssertionTwoStepCancelAndroid(@Name("attestation.android.two-step.issuer") String issuer, @Name("assertion.android.two-step.cancel.challenge3") String challenge, - @Name("attestation.android.two-step.userName") String userName, @Name("attestation.android.two-step.applicationId") String applicationId, - @Name("attestation.android.two-step.sessionId") String sessionId) { - testStartAssertionTwoStepAndroidImpl(issuer, challenge, userName, applicationId, sessionId); - } - - @Test - @Order(8) - @ExtendWith(FileParameterExtension.class) - public void testThirdFinishAssertionTwoStepCancelAndroid(@Name("attestation.android.two-step.userName") String userName, - @Name("assertion.android.two-step.cancel.finish.request3") String authenticateFinishResponse) { - testFinishAssertionTwoStepAndroidCanceled(userName, authenticateFinishResponse); - assertTrue(registrationEntry.getCounter() == 3); - } - - @Test - @Order(9) - @ExtendWith(FileParameterExtension.class) - public void testFourthStartAssertionTwoStepAndroid(@Name("attestation.android.two-step.issuer") String issuer, @Name("assertion.android.two-step.challenge4") String challenge, - @Name("attestation.android.two-step.userName") String userName, @Name("attestation.android.two-step.applicationId") String applicationId, - @Name("attestation.android.two-step.sessionId") String sessionId) { - testStartAssertionTwoStepAndroidImpl(issuer, challenge, userName, applicationId, sessionId); - } - - @Test - @Order(10) - @ExtendWith(FileParameterExtension.class) - public void tesFourthFinishAssertionTwoStepAndroid(@Name("attestation.android.two-step.userName") String userName, - @Name("assertion.android.two-step.finish.request4") String authenticateFinishResponse) { - testFinishAssertionTwoStepAndroidAuthenticated(userName, authenticateFinishResponse); - assertTrue(registrationEntry.getCounter() == 4); - } - - @Test - @Order(11) - @ExtendWith(FileParameterExtension.class) - public void testSecondReplyFinishAssertionTwoStepAndroid(@Name("attestation.android.two-step.userName") String userName, - @Name("assertion.android.two-step.finish.request4") String authenticateFinishResponse) { - try { - testFinishAssertionTwoStepAndroidAuthenticated(userName, authenticateFinishResponse); - } catch (Fido2RuntimeException ex) { - if (!(ex.getCause() instanceof Fido2CompromisedDevice)) { - throw ex; - } - } - } - - @Test - @Order(12) - @ExtendWith(FileParameterExtension.class) - public void testStartAttestationTwoStepCancelAndroid(@Name("attestation.android.two-step.cancel.issuer") String issuer, @Name("attestation.android.two-step.cancel.challenge") String challenge, - @Name("attestation.android.two-step.cancel.userName") String userName, @Name("attestation.android.two-step.cancel.applicationId") String applicationId, - @Name("attestation.android.two-step.cancel.sessionId") String sessionId, @Name("attestation.android.two-step.cancel.enrollmentCode") String enrollmentCode) { - testStartAttestationTwoStepAndroidImpl(issuer, challenge, userName, applicationId, sessionId); - } - - @Test - @Order(13) - @ExtendWith(FileParameterExtension.class) - public void testFinishAttestationTwoStepCancelAndroid(@Name("attestation.android.two-step.cancel.userName") String userName, - @Name("attestation.android.two-step.cancel.finish.request") String registerFinishResponse, @Name("attestation.android.two-step.cancel.finish.publicKeyId") String publicKeyId) { - testFinishAssertionTwoStepAndroidAuthenticatedCanceled(userName, registerFinishResponse, publicKeyId); - }*/ - -} diff --git a/jans-fido2/server/src/test/java/io/jans/fido2/service/sg/FullFlowAppleTest.java b/jans-fido2/server/src/test/java/io/jans/fido2/service/sg/FullFlowAppleTest.java deleted file mode 100644 index 4e7a7c03f4e..00000000000 --- a/jans-fido2/server/src/test/java/io/jans/fido2/service/sg/FullFlowAppleTest.java +++ /dev/null @@ -1,475 +0,0 @@ -/* - * Janssen Project software is available under the Apache License (2004). See http://www.apache.org/licenses/ for full text. - * - * Copyright (c) 2023, Janssen Project - */ - -package io.jans.fido2.service.sg; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyBoolean; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.ArgumentMatchers.eq; - -import java.util.Arrays; -import java.util.Optional; - -import org.jboss.weld.junit5.ExplicitParamInjection; -import org.jboss.weld.junit5.auto.AddBeanClasses; -import org.jboss.weld.junit5.auto.EnableAutoWeld; -import org.jboss.weld.junit5.auto.ExcludeBean; -import org.jboss.weld.junit5.auto.WeldJunit5AutoExtension; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.MethodOrderer.OrderAnnotation; -import org.junit.jupiter.api.TestMethodOrder; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.ArgumentCaptor; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.Mockito; -import org.mockito.MockitoAnnotations; - -import io.jans.as.common.model.common.User; -import io.jans.as.model.config.BaseDnConfiguration; -import io.jans.as.model.config.StaticConfiguration; -import io.jans.as.model.fido.u2f.protocol.AuthenticateResponse; -import io.jans.as.model.fido.u2f.protocol.RegisterResponse; -import io.jans.fido2.model.assertion.AssertionOptions; -import io.jans.fido2.model.assertion.AssertionOptionsResponse; -import io.jans.fido2.model.assertion.AssertionResult; -import io.jans.fido2.model.attestation.AttestationOptions; -import io.jans.fido2.model.attestation.AttestationResult; -import io.jans.fido2.model.attestation.PublicKeyCredentialCreationOptions; -import io.jans.fido2.model.common.AttestationOrAssertionResponse; -import io.jans.fido2.model.conf.AppConfiguration; -import io.jans.fido2.model.conf.Fido2Configuration; -import io.jans.fido2.model.error.ErrorResponseFactory; -import io.jans.fido2.service.ChallengeGenerator; -import io.jans.fido2.service.operation.AssertionService; -import io.jans.fido2.service.operation.AttestationService; -import io.jans.fido2.service.persist.AuthenticationPersistenceService; -import io.jans.fido2.service.persist.RegistrationPersistenceService; -import io.jans.fido2.service.persist.UserSessionIdService; -import io.jans.fido2.service.processor.attestation.U2FSuperGluuAttestationProcessor; -import io.jans.fido2.service.sg.converter.AssertionSuperGluuController; -import io.jans.fido2.service.sg.converter.AttestationSuperGluuController; -import io.jans.fido2.service.shared.CustomScriptService; -import io.jans.fido2.service.shared.UserService; -import io.jans.fido2.service.verifier.AssertionVerifier; -import io.jans.fido2.sg.SuperGluuMode; -import io.jans.orm.PersistenceEntryManager; -import io.jans.orm.model.fido2.Fido2AuthenticationEntry; -import io.jans.orm.model.fido2.Fido2AuthenticationStatus; -import io.jans.orm.model.fido2.Fido2RegistrationEntry; -import io.jans.orm.model.fido2.Fido2RegistrationStatus; -import io.jans.u2f.service.persist.DeviceRegistrationService; -import io.jans.util.security.SecurityProviderUtility; -import jakarta.enterprise.context.ApplicationScoped; -import jakarta.enterprise.inject.Produces; -import jakarta.inject.Inject; - -/** - * @author Yuriy Movchan - * @version 0.1, 17/02/2023 - */ -@EnableAutoWeld -@ExtendWith(WeldJunit5AutoExtension.class) -@TestMethodOrder(OrderAnnotation.class) -@AddBeanClasses(io.jans.service.util.Resources.class) -@AddBeanClasses(io.jans.service.net.NetworkService.class) -@ExplicitParamInjection -public class FullFlowAppleTest { - - private String issuer; - private String attestationChallenge; - private String assertionChallenge; - - // Static to store value between tests executions - static Fido2RegistrationEntry registrationEntry; - static Fido2AuthenticationEntry authenticationEntry; - - private AutoCloseable closeable; - - @Inject - AttestationSuperGluuController attestationSuperGluuController; - - @Inject - AssertionSuperGluuController assertionSuperGluuController; - - @Inject - U2FSuperGluuAttestationProcessor attestationProcessor; - - @Inject - AssertionVerifier assertionFormatProcessor; - - @Inject - AttestationService attestationService; - - @Inject - AssertionService assertionService; - - @Mock - @Produces - @ExcludeBean - UserService userService = Mockito.mock(UserService.class); - - @Mock - @Produces - @ExcludeBean - PersistenceEntryManager persistenceEntryManager = Mockito.mock(PersistenceEntryManager.class); - - @Mock - @Produces - @ExcludeBean - CustomScriptService customScriptService = Mockito.mock(CustomScriptService.class); - - @Mock - @Produces - @ExcludeBean - DeviceRegistrationService deviceRegistrationService = Mockito.mock(DeviceRegistrationService.class); - - @Mock - @Produces - @ExcludeBean - ErrorResponseFactory errorResponseFactory = Mockito.mock(ErrorResponseFactory.class); - - @Mock - ChallengeGenerator challengeGenerator = Mockito.mock(ChallengeGenerator.class); - - @InjectMocks - RegistrationPersistenceService registrationPersistenceService = Mockito.mock(RegistrationPersistenceService.class); - - @InjectMocks - AuthenticationPersistenceService authenticationPersistenceService = Mockito.mock(AuthenticationPersistenceService.class); - - @BeforeAll - public static void beforeAll() { - SecurityProviderUtility.installBCProvider(); - } - - @BeforeEach - void initService() { - closeable = MockitoAnnotations.openMocks(this); - } - - @AfterEach - void closeService() throws Exception { - closeable.close(); - } - - @ApplicationScoped - @Produces - StaticConfiguration produceStaticConfiguration() { - StaticConfiguration staticConfiguration = Mockito.mock(StaticConfiguration.class); - - BaseDnConfiguration baseDnConfiguration = new BaseDnConfiguration(); - Mockito.when(staticConfiguration.getBaseDn()).thenReturn(baseDnConfiguration); - - return staticConfiguration; - } - - @ApplicationScoped - @Produces - AppConfiguration produceAppConfiguration() { - AppConfiguration appConfiguration = Mockito.mock(AppConfiguration.class); - - Fido2Configuration fido2Configuration = new Fido2Configuration(); - Mockito.when(appConfiguration.getFido2Configuration()).thenReturn(fido2Configuration); - Mockito.when(appConfiguration.getIssuer()).thenReturn(issuer); - - return appConfiguration; - } - - @ApplicationScoped - @Produces - @ExcludeBean - RegistrationPersistenceService produceRegistrationPersistenceService() { - Mockito.when(registrationPersistenceService.buildFido2RegistrationEntry(any(), anyBoolean())).thenCallRealMethod(); - Mockito.doCallRealMethod().when(registrationPersistenceService).update(any(Fido2RegistrationEntry.class)); - if (registrationEntry != null) { - Mockito.when(registrationPersistenceService.findByChallenge(eq(registrationEntry.getChallange()), anyBoolean())).thenReturn(Arrays.asList(registrationEntry)); - Mockito.when(registrationPersistenceService.findByPublicKeyId(eq(registrationEntry.getPublicKeyId()), eq(registrationEntry.getRpId()))).thenReturn(Optional.of(registrationEntry)); - Mockito.when(registrationPersistenceService.findByPublicKeyId(anyString(), eq(registrationEntry.getPublicKeyId()), eq(registrationEntry.getRpId()))).thenReturn(Optional.of(registrationEntry)); - } - - Mockito.when(userService.getUser(anyString(), any())).thenReturn(new User()); - - return registrationPersistenceService; - } - - @ApplicationScoped - @Produces - @ExcludeBean - AuthenticationPersistenceService produceAuthenticationPersistenceService() { - Mockito.when(authenticationPersistenceService.buildFido2AuthenticationEntry(any(), anyBoolean())).thenCallRealMethod(); - Mockito.doCallRealMethod().when(authenticationPersistenceService).update(any(Fido2AuthenticationEntry.class)); - if (authenticationEntry != null) { - Mockito.when(authenticationPersistenceService.findByChallenge(eq(authenticationEntry.getChallange()), anyBoolean())).thenReturn(Arrays.asList(authenticationEntry)); - } - - return authenticationPersistenceService; - } - - @ApplicationScoped - @Produces - @ExcludeBean - ChallengeGenerator produceChallengeGenerator() { - Mockito.when(challengeGenerator.getAttestationChallenge()).thenReturn(attestationChallenge); - Mockito.when(challengeGenerator.getAssertionChallenge()).thenReturn(assertionChallenge); - - return challengeGenerator; - } - - @ApplicationScoped - @Produces - @ExcludeBean - UserSessionIdService produceUserSessionIdService() { - return Mockito.when(Mockito.mock(UserSessionIdService.class).isValidSessionId(anyString(), anyString())) - .thenReturn(true).getMock(); - } - - public void testStartAttestationTwoStepAppleImpl(String issuer, String challenge, String userName, - String applicationId, String sessionId) { - this.issuer = issuer; - this.attestationChallenge = challenge; - - AttestationOptions request = attestationSuperGluuController.buildFido2AttestationStartResponse(userName, applicationId, sessionId); - assertEquals(true, request.getSuperGluuRequest()); - assertEquals(SuperGluuMode.TWO_STEP.getMode(), request.getSuperGluuRequestMode()); - assertEquals(applicationId, request.getSuperGluuAppId()); - - PublicKeyCredentialCreationOptions response = attestationService.options(request); - - // Get saved entry for finish attestation test - ArgumentCaptor captor = ArgumentCaptor.forClass(Fido2RegistrationEntry.class); - Mockito.verify(registrationPersistenceService).save(captor.capture()); - registrationEntry = captor.getValue(); - - assertNotNull(registrationEntry); - assertNotNull(response); - assertEquals(challenge, response.getChallenge()); - - assertEquals(Fido2RegistrationStatus.pending, registrationEntry.getRegistrationStatus()); - } - - public void testFinishAttestationTwoStepAppleAuthenticatedImpl(String userName, String registerFinishResponse, String registeredPublicKey) { - // Parse register response - RegisterResponse registerResponse = attestationSuperGluuController.parseRegisterResponse(registerFinishResponse); - - AttestationResult request = attestationSuperGluuController.buildFido2AttestationVerifyResponse(userName, registerResponse); - assertEquals(true, request.getSuperGluuRequest()); - assertEquals(SuperGluuMode.TWO_STEP.getMode(), request.getSuperGluuRequestMode()); - - AttestationOrAssertionResponse response = attestationService.verify(request); - - // Get updated entry for checks - ArgumentCaptor captor = ArgumentCaptor.forClass(Fido2RegistrationEntry.class); - Mockito.verify(registrationPersistenceService).update(captor.capture()); - registrationEntry = captor.getValue(); - - assertNotNull(response); - assertEquals("ok", response.getStatus()); - assertEquals(registeredPublicKey, response.getCredentials().getId()); - } - - public void testFinishAttestationTwoStepAppleAuthenticatedRegistered(String userName, String registerFinishResponse, String registeredPublicKey) { - testFinishAttestationTwoStepAppleAuthenticatedImpl(userName, registerFinishResponse, registeredPublicKey); - - assertEquals(Fido2RegistrationStatus.registered, registrationEntry.getRegistrationStatus()); - } - - public void testFinishAssertionTwoStepAppleAuthenticatedCanceled(String userName, String registerFinishResponse, String registeredPublicKey) { - testFinishAttestationTwoStepAppleAuthenticatedImpl(userName, registerFinishResponse, registeredPublicKey); - - assertEquals(Fido2RegistrationStatus.canceled, registrationEntry.getRegistrationStatus()); - } - - public void testStartAssertionTwoStepAppleImpl(String issuer, String challenge, String userName, - String applicationId, String sessionId) { - this.issuer = issuer; - this.assertionChallenge = challenge; - - AssertionOptions request = assertionSuperGluuController.buildFido2AssertionStartResponse(userName, registrationEntry.getPublicKeyId(), applicationId, sessionId); - assertEquals(true, request.getSuperGluuRequest()); - assertEquals(SuperGluuMode.TWO_STEP.getMode(), request.getSuperGluuRequestMode()); - assertEquals(registrationEntry.getPublicKeyId(), request.getSuperGluuKeyHandle()); - assertEquals(applicationId, request.getSuperGluuAppId()); - - AssertionOptionsResponse response = assertionService.options(request); - - // Get saved entry for finish authentication test - ArgumentCaptor captor = ArgumentCaptor.forClass(Fido2AuthenticationEntry.class); - Mockito.verify(authenticationPersistenceService).save(captor.capture()); - authenticationEntry = captor.getValue(); - - assertNotNull(authenticationEntry); - assertNotNull(response); - assertTrue(response.getAllowCredentials().size() > 0); - assertEquals(registrationEntry.getPublicKeyId(), response.getAllowCredentials().get(0).getId()); - - assertEquals(Fido2AuthenticationStatus.pending, authenticationEntry.getAuthenticationStatus()); - } - - public void testFinishAssertionTwoStepAppleImpl(String userName, String authenticateFinishResponse) { - // Parse register response - AuthenticateResponse authenticateResponse = assertionSuperGluuController.parseAuthenticateResponse(authenticateFinishResponse); - - AssertionResult request = assertionSuperGluuController.buildFido2AuthenticationVerifyResponse(userName, authenticateFinishResponse, authenticateResponse); - assertEquals(true, request.getSuperGluuRequest()); - assertEquals(SuperGluuMode.TWO_STEP.getMode(), request.getSuperGluuRequestMode()); - - AttestationOrAssertionResponse response = assertionService.verify(request); - - // Get updated entry for checks - ArgumentCaptor captorAssertion = ArgumentCaptor.forClass(Fido2AuthenticationEntry.class); - Mockito.verify(authenticationPersistenceService).update(captorAssertion.capture()); - authenticationEntry = captorAssertion.getValue(); - - ArgumentCaptor captorAttestation = ArgumentCaptor.forClass(Fido2RegistrationEntry.class); - Mockito.verify(registrationPersistenceService).update(captorAttestation.capture()); - registrationEntry = captorAttestation.getValue(); - - assertNotNull(response); - assertEquals("ok", response.getStatus()); - assertEquals(registrationEntry.getPublicKeyId(), response.getCredentials().getId()); - } - - public void testFinishAssertionTwoStepAppleAuthenticated(String userName, String authenticateFinishResponse) { - testFinishAssertionTwoStepAppleImpl(userName, authenticateFinishResponse); - - assertEquals(Fido2AuthenticationStatus.authenticated, authenticationEntry.getAuthenticationStatus()); - } - - public void testFinishAssertionTwoStepAppleCanceled(String userName, String authenticateFinishResponse) { - testFinishAssertionTwoStepAppleImpl(userName, authenticateFinishResponse); - - assertEquals(Fido2AuthenticationStatus.canceled, authenticationEntry.getAuthenticationStatus()); - } - - /*@Test - @Order(1) - @ExtendWith(FileParameterExtension.class) - public void testStartAttestationTwoStepApple(@Name("attestation.apple.two-step.issuer") String issuer, @Name("attestation.apple.two-step.challenge") String challenge, - @Name("attestation.apple.two-step.userName") String userName, @Name("attestation.apple.two-step.applicationId") String applicationId, - @Name("attestation.apple.two-step.sessionId") String sessionId, @Name("attestation.apple.two-step.enrollmentCode") String enrollmentCode) { - testStartAttestationTwoStepAppleImpl(issuer, challenge, userName, applicationId, sessionId); - } - - @Test - @Order(2) - @ExtendWith(FileParameterExtension.class) - public void testFinishAttestationTwoStepApple(@Name("attestation.apple.two-step.userName") String userName, - @Name("attestation.apple.two-step.finish.request") String registerFinishResponse, @Name("attestation.apple.two-step.finish.publicKeyId") String publicKeyId) { - testFinishAttestationTwoStepAppleAuthenticatedRegistered(userName, registerFinishResponse, publicKeyId); - } - - @Test - @Order(3) - @ExtendWith(FileParameterExtension.class) - public void testStartAssertionTwoStepApple(@Name("attestation.apple.two-step.issuer") String issuer, @Name("assertion.apple.two-step.challenge") String challenge, - @Name("attestation.apple.two-step.userName") String userName, @Name("attestation.apple.two-step.applicationId") String applicationId, - @Name("attestation.apple.two-step.sessionId") String sessionId) { - - testStartAssertionTwoStepAppleImpl(issuer, challenge, userName, applicationId, sessionId); - } - - @Test - @Order(4) - @ExtendWith(FileParameterExtension.class) - public void testFinishAssertionTwoStepApple(@Name("attestation.apple.two-step.userName") String userName, - @Name("assertion.apple.two-step.finish.request") String authenticateFinishResponse) { - testFinishAssertionTwoStepAppleAuthenticated(userName, authenticateFinishResponse); - assertTrue(registrationEntry.getCounter() == 1); - } - - @Test - @Order(5) - @ExtendWith(FileParameterExtension.class) - public void testSecondStartAssertionTwoStepApple(@Name("attestation.apple.two-step.issuer") String issuer, @Name("assertion.apple.two-step.challenge2") String challenge, - @Name("attestation.apple.two-step.userName") String userName, @Name("attestation.apple.two-step.applicationId") String applicationId, - @Name("attestation.apple.two-step.sessionId") String sessionId) { - testStartAssertionTwoStepAppleImpl(issuer, challenge, userName, applicationId, sessionId); - } - - @Test - @Order(6) - @ExtendWith(FileParameterExtension.class) - public void testSecondFinishAssertionTwoStepApple(@Name("attestation.apple.two-step.userName") String userName, - @Name("assertion.apple.two-step.finish.request2") String authenticateFinishResponse) { - testFinishAssertionTwoStepAppleAuthenticated(userName, authenticateFinishResponse); - assertTrue(registrationEntry.getCounter() == 2); - } - - @Test - @Order(7) - @ExtendWith(FileParameterExtension.class) - public void testThirdStartAssertionTwoStepCancelApple(@Name("attestation.apple.two-step.issuer") String issuer, @Name("assertion.apple.two-step.cancel.challenge3") String challenge, - @Name("attestation.apple.two-step.userName") String userName, @Name("attestation.apple.two-step.applicationId") String applicationId, - @Name("attestation.apple.two-step.sessionId") String sessionId) { - testStartAssertionTwoStepAppleImpl(issuer, challenge, userName, applicationId, sessionId); - } - - @Test - @Order(8) - @ExtendWith(FileParameterExtension.class) - public void testThirdFinishAssertionTwoStepCancelApple(@Name("attestation.apple.two-step.userName") String userName, - @Name("assertion.apple.two-step.cancel.finish.request3") String authenticateFinishResponse) { - testFinishAssertionTwoStepAppleCanceled(userName, authenticateFinishResponse); - assertTrue(registrationEntry.getCounter() == 3); - } - - @Test - @Order(9) - @ExtendWith(FileParameterExtension.class) - public void testFourthStartAssertionTwoStepApple(@Name("attestation.apple.two-step.issuer") String issuer, @Name("assertion.apple.two-step.challenge4") String challenge, - @Name("attestation.apple.two-step.userName") String userName, @Name("attestation.apple.two-step.applicationId") String applicationId, - @Name("attestation.apple.two-step.sessionId") String sessionId) { - testStartAssertionTwoStepAppleImpl(issuer, challenge, userName, applicationId, sessionId); - } - - @Test - @Order(10) - @ExtendWith(FileParameterExtension.class) - public void tesFourthFinishAssertionTwoStepApple(@Name("attestation.apple.two-step.userName") String userName, - @Name("assertion.apple.two-step.finish.request4") String authenticateFinishResponse) { - testFinishAssertionTwoStepAppleAuthenticated(userName, authenticateFinishResponse); - assertTrue(registrationEntry.getCounter() == 4); - } - - @Test - @Order(11) - @ExtendWith(FileParameterExtension.class) - public void testSecondReplyFinishAssertionTwoStepApple(@Name("attestation.apple.two-step.userName") String userName, - @Name("assertion.apple.two-step.finish.request4") String authenticateFinishResponse) { - try { - testFinishAssertionTwoStepAppleAuthenticated(userName, authenticateFinishResponse); - } catch (Fido2RuntimeException ex) { - if (!(ex.getCause() instanceof Fido2CompromisedDevice)) { - throw ex; - } - } - } - - @Test - @Order(12) - @ExtendWith(FileParameterExtension.class) - public void testStartAttestationTwoStepCancelApple(@Name("attestation.apple.two-step.cancel.issuer") String issuer, @Name("attestation.apple.two-step.cancel.challenge") String challenge, - @Name("attestation.apple.two-step.cancel.userName") String userName, @Name("attestation.apple.two-step.cancel.applicationId") String applicationId, - @Name("attestation.apple.two-step.cancel.sessionId") String sessionId, @Name("attestation.apple.two-step.cancel.enrollmentCode") String enrollmentCode) { - testStartAttestationTwoStepAppleImpl(issuer, challenge, userName, applicationId, sessionId); - } - - @Test - @Order(13) - @ExtendWith(FileParameterExtension.class) - public void testFinishAttestationTwoStepCancelApple(@Name("attestation.apple.two-step.cancel.userName") String userName, - @Name("attestation.apple.two-step.cancel.finish.request") String registerFinishResponse, @Name("attestation.apple.two-step.cancel.finish.publicKeyId") String publicKeyId) { - testFinishAssertionTwoStepAppleAuthenticatedCanceled(userName, registerFinishResponse, publicKeyId); - } -*/ -} diff --git a/jans-fido2/server/src/test/java/io/jans/fido2/service/sg/converter/AssertionSuperGluuControllerTest.java b/jans-fido2/server/src/test/java/io/jans/fido2/service/sg/converter/AssertionSuperGluuControllerTest.java deleted file mode 100644 index 202fc193f08..00000000000 --- a/jans-fido2/server/src/test/java/io/jans/fido2/service/sg/converter/AssertionSuperGluuControllerTest.java +++ /dev/null @@ -1,398 +0,0 @@ -package io.jans.fido2.service.sg.converter; - -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.node.ArrayNode; -import com.fasterxml.jackson.databind.node.ObjectNode; -import com.google.common.base.Strings; -import com.google.common.collect.Lists; -import io.jans.as.model.fido.u2f.message.RawAuthenticateResponse; -import io.jans.as.model.fido.u2f.protocol.AuthenticateResponse; -import io.jans.fido2.model.assertion.AssertionOptions; -import io.jans.fido2.model.assertion.AssertionOptionsResponse; -import io.jans.fido2.model.assertion.AssertionResult; -import io.jans.fido2.model.common.AttestationOrAssertionResponse; -import io.jans.fido2.model.common.PublicKeyCredentialDescriptor; -import io.jans.fido2.model.error.ErrorResponseFactory; -import io.jans.fido2.service.Base64Service; -import io.jans.fido2.service.DataMapperService; -import io.jans.fido2.service.DigestService; -import io.jans.fido2.service.operation.AssertionService; -import io.jans.fido2.service.persist.UserSessionIdService; -import io.jans.fido2.service.sg.RawAuthenticationService; -import jakarta.ws.rs.WebApplicationException; -import jakarta.ws.rs.core.Response; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; -import org.slf4j.Logger; - -import java.io.IOException; -import java.util.List; - -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.Mockito.*; - -@ExtendWith(MockitoExtension.class) -class AssertionSuperGluuControllerTest { - - private final ObjectMapper mapper = new ObjectMapper(); - - @InjectMocks - private AssertionSuperGluuController assertionSuperGluuController; - - @Mock - private Logger log; - - @Mock - private AssertionService assertionService; - - @Mock - private DataMapperService dataMapperService; - - @Mock - private Base64Service base64Service; - - @Mock - private RawAuthenticationService rawAuthenticationService; - - @Mock - private DigestService digestService; - - @Mock - private UserSessionIdService userSessionIdService; - - @Mock - private ErrorResponseFactory errorResponseFactory; - - @Test - void startAuthentication_ifAllowCredentialsIsNull_valid() { - String username = "test_username"; - String keyHandle = "test_key_handle"; - String appId = "test_app_id"; - String sessionId = "session_id"; - - AssertionOptionsResponse assertionOptionsResponse =new AssertionOptionsResponse(); - assertionOptionsResponse.setChallenge("test_challenge"); - assertionOptionsResponse.setUserVerification("test_user_verification"); - - when(assertionService.options(any())).thenReturn(assertionOptionsResponse); - when(dataMapperService.createObjectNode()).thenReturn(mapper.createObjectNode(), mapper.createObjectNode()); - when(userSessionIdService.isValidSessionId(sessionId, username)).thenReturn(true); - - JsonNode response = assertionSuperGluuController.startAuthentication(username, keyHandle, appId, sessionId); - assertNotNull(response); - assertTrue(response.has("authenticateRequests")); - JsonNode authenticateRequestsNode = response.get("authenticateRequests"); - assertTrue(authenticateRequestsNode.isEmpty()); - - verify(assertionService, only()).options(any()); - verify(dataMapperService, times(1)).createObjectNode(); - } - - @Test - void startAuthentication_ifAllowCredentialsContainsValue_valid() { - String username = "test_username"; - String keyHandle = "test_key_handle"; - String appId = "test_app_id"; - String sessionId = "test_session_id"; - - AssertionOptionsResponse assertionOptionsResponse =new AssertionOptionsResponse(); - assertionOptionsResponse.setChallenge("test_challenge"); - assertionOptionsResponse.setUserVerification("test_user_verification"); - - String transports[] = new String[] { "internal" }; - PublicKeyCredentialDescriptor publicKeyCredentialDescriptor = new PublicKeyCredentialDescriptor(transports, "test_id_1"); - List allowCredentials = Lists.newArrayList(publicKeyCredentialDescriptor); - - assertionOptionsResponse.setAllowCredentials(allowCredentials); - - when(assertionService.options(any())).thenReturn(assertionOptionsResponse); - when(dataMapperService.createObjectNode()).thenReturn(mapper.createObjectNode(), mapper.createObjectNode()); - when(userSessionIdService.isValidSessionId(sessionId, username)).thenReturn(true); - - JsonNode response = assertionSuperGluuController.startAuthentication(username, keyHandle, appId, sessionId); - assertNotNull(response); - assertTrue(response.has("authenticateRequests")); - JsonNode authenticateRequestsArray = response.get("authenticateRequests"); - for (JsonNode itemNode : authenticateRequestsArray) { - assertTrue(itemNode.has("appId")); - assertTrue(itemNode.has("userVerification")); - assertTrue(itemNode.has("challenge")); - assertTrue(itemNode.has("keyHandle")); - assertTrue(itemNode.has("version")); - assertEquals(itemNode.get("appId").asText(), appId); - assertEquals(itemNode.get("userVerification").asText(), "test_user_verification"); - assertEquals(itemNode.get("challenge").asText(), "test_challenge"); - assertEquals(itemNode.get("keyHandle").asText(), "test_id_1"); - assertEquals(itemNode.get("version").asText(), "U2F_V2"); - } - - verify(assertionService, only()).options(any()); - verify(dataMapperService, times(2)).createObjectNode(); - } - - @Test - void buildFido2AssertionStartResponse_ifValidIsFalse_webApplicationException() { - String username = "test_username"; - String keyHandle = "test_key_handle"; - String appId = "test_app_id"; - String sessionId = "test_session_id"; - when(userSessionIdService.isValidSessionId(sessionId, username)).thenReturn(false); - when(errorResponseFactory.badRequestException(any(), any())).thenReturn(new WebApplicationException(Response.status(400).entity("test exception").build())); - - WebApplicationException ex = assertThrows(WebApplicationException.class, () -> assertionSuperGluuController.buildFido2AssertionStartResponse(username, keyHandle, appId, sessionId)); - assertNotNull(ex); - assertNotNull(ex.getResponse()); - assertEquals(ex.getResponse().getStatus(), 400); - assertEquals(ex.getResponse().getEntity(), "test exception"); - - verify(userSessionIdService).isValidSessionId(sessionId, username); - verifyNoInteractions(dataMapperService, log); - } - - @Test - void buildFido2AssertionStartResponse_ifUsernameAndKeyHandleIsEmpty_webApplicationException() { - String username = ""; - String keyHandle = ""; - String appId = "test_app_id"; - String sessionId = "test_session_id"; - when(userSessionIdService.isValidSessionId(sessionId, username)).thenReturn(true); - WebApplicationException exception = new WebApplicationException(Response.status(400).entity("test exception").build()); - when(errorResponseFactory.badRequestException(any(), any())).thenReturn(exception); - - WebApplicationException ex = assertThrows(WebApplicationException.class, () -> assertionSuperGluuController.buildFido2AssertionStartResponse(username, keyHandle, appId, sessionId)); - assertNotNull(ex); - assertNotNull(ex.getResponse()); - assertEquals(ex.getResponse().getStatus(), 400); - assertEquals(ex.getResponse().getEntity(), "test exception"); - - verify(userSessionIdService).isValidSessionId(sessionId, username); - verifyNoInteractions(dataMapperService, log); - } - - @Test - void buildFido2AssertionStartResponse_ifOneStep_webApplicationException() { - String username = ""; - String keyHandle = "test_key_handle"; - String appId = "test_app_id"; - String sessionId = "test_session_id"; - when(userSessionIdService.isValidSessionId(sessionId, username)).thenReturn(true); - //when(dataMapperService.createObjectNode()).thenReturn(mapper.createObjectNode()); - - AssertionOptions response = assertionSuperGluuController.buildFido2AssertionStartResponse(username, keyHandle, appId, sessionId); - assertNotNull(response); - assertNotNull(response.getSuperGluuRequest()); - assertNotNull(response.getSuperGluuAppId()); - assertNotNull(response.getDocumentDomain()); - assertNotNull(response.getSuperGluuKeyHandle()); - assertNotNull(response.getSuperGluuRequestMode()); - assertNotNull(response.getUsername()); - assertNotNull(response.getSessionId()); - assertEquals((response.getSuperGluuRequest() == null ? "false" : response.getSuperGluuRequest().toString()),"true"); - assertEquals(response.getSuperGluuAppId(), appId); - assertEquals(response.getDocumentDomain(), appId); - assertEquals(response.getSuperGluuKeyHandle(), keyHandle); - assertEquals(response.getSuperGluuRequestMode(), "one_step"); - assertEquals(response.getUsername(), ""); - assertEquals(response.getSessionId(), sessionId); - - verify(userSessionIdService).isValidSessionId(sessionId, username); -// verify(dataMapperService).createObjectNode(); - verify(log).debug("Prepared U2F_V2 assertions options request: {}", response.toString()); - } - - @Test - void buildFido2AssertionStartResponse_ifTwoStep_webApplicationException() { - String username = "test_username"; - String keyHandle = "test_key_handle"; - String appId = "test_app_id"; - String sessionId = "test_session_id"; - when(userSessionIdService.isValidSessionId(sessionId, username)).thenReturn(true); - - AssertionOptions response = assertionSuperGluuController.buildFido2AssertionStartResponse(username, keyHandle, appId, sessionId); - assertNotNull(response); - assertTrue(response.getSuperGluuRequest()); - assertNotNull(response.getSuperGluuAppId()); - assertNotNull(response.getDocumentDomain()); - assertNotNull(response.getSuperGluuKeyHandle()); - assertNotNull(response.getSuperGluuRequestMode()); - assertNotNull(response.getUsername()); - assertNotNull(response.getSessionId()); - assertEquals((response.getSuperGluuRequest() == null ? "false" : response.getSuperGluuRequest().toString()),"true"); - assertEquals(response.getSuperGluuAppId(), appId); - assertEquals(response.getDocumentDomain(), appId); - assertEquals(response.getSuperGluuKeyHandle(), keyHandle); - assertEquals(response.getSuperGluuRequestMode(), "two_step"); - assertEquals(response.getUsername(), username); - assertEquals(response.getSessionId(), sessionId); - - verify(userSessionIdService).isValidSessionId(sessionId, username); - verify(log).debug("Prepared U2F_V2 assertions options request: {}", response.toString()); - } - - @Test - void finishAuthentication_validValues_valid() throws IOException { - String username = "test_username"; - String authenticateResponseString = "test_authenticate_response_string"; - String clientData = "eyJ0eXAiOiJuYXZpZ2F0b3IuaWQuZ2V0QXNzZXJ0aW9uIiwiY2hhbGxlbmdlIjoidGVzdF9jaGFsbGVuZ2UiLCJvcmlnaW4iOiJ0ZXN0X29yaWdpbiJ9"; - String signatureData = "test_signature_data"; - String keyHandle = "test_key_handle"; - String deviceData = "test_device_data"; - AuthenticateResponse authenticateResponse = new AuthenticateResponse(clientData, signatureData, keyHandle, deviceData); - when(dataMapperService.readValue(authenticateResponseString, AuthenticateResponse.class)).thenReturn(authenticateResponse); - - ObjectNode paramsNode = mapper.createObjectNode(); - ObjectNode clientDataNode = mapper.createObjectNode(); - ObjectNode responseNode = mapper.createObjectNode(); - ObjectNode attestationObjectNode = mapper.createObjectNode(); - when(dataMapperService.createObjectNode()).thenReturn(paramsNode, clientDataNode, responseNode, attestationObjectNode); - when(base64Service.urlEncodeToString(any())).thenReturn("test_client_data_json", "test_signature", "test_authenticator_data", "test_attestation_object"); - when(digestService.hashSha256(anyString())).thenReturn("rp_id_hash".getBytes()); - when(dataMapperService.cborWriteAsBytes(attestationObjectNode)).thenReturn("dGVzdF9hdHRlc3RhdGlvbl9vYmplY3Q".getBytes()); - when(assertionService.verify(any())).thenReturn(mock(AttestationOrAssertionResponse.class)); - - - RawAuthenticateResponse rawAuthenticateResponse = new RawAuthenticateResponse((byte) 1, 0L, "test_signature".getBytes()); - when(rawAuthenticationService.parseRawAuthenticateResponse(authenticateResponse.getSignatureData())).thenReturn(rawAuthenticateResponse); - - JsonNode result = assertionSuperGluuController.finishAuthentication(username, authenticateResponseString); - assertNotNull(result); - assertTrue(result.has("status")); - assertTrue(result.has("challenge")); - assertEquals(result.get("status").asText(), "success"); - assertEquals(result.get("challenge").asText(), "test_challenge"); - - verify(assertionService, times(1)).verify(any()); - } - - @Test - void buildFido2AuthenticationVerifyResponse_ifClientDataUnsupportedRegisterTypes_fido2RuntimeException() { - String username = "test_username"; - String authenticateResponseString = "test_authenticate_response_string"; - String clientData = "eyJ0eXAiOiJ3cm9uZ190eXAiLCJjaGFsbGVuZ2UiOiJ0ZXN0X2NoYWxsZW5nZSIsIm9yaWdpbiI6InRlc3Rfb3JpZ2luIn0"; - String signatureData = "test_signature_data"; - String keyHandle = "test_key_handle"; - String deviceData = "test_device_data"; - AuthenticateResponse authenticateResponse = new AuthenticateResponse(clientData, signatureData, keyHandle, deviceData); - when(errorResponseFactory.badRequestException(any(), contains("Invalid options attestation request type"))).thenReturn(new WebApplicationException(Response.status(400).entity("test exception").build())); - - WebApplicationException ex = assertThrows(WebApplicationException.class, () -> assertionSuperGluuController.buildFido2AuthenticationVerifyResponse(username, authenticateResponseString, authenticateResponse)); - assertNotNull(ex); - assertNotNull(ex.getResponse()); - assertEquals(ex.getResponse().getStatus(), 400); - assertEquals(ex.getResponse().getEntity(), "test exception"); - - verifyNoInteractions(dataMapperService, base64Service, rawAuthenticationService, log); - } - - @Test - void buildFido2AuthenticationVerifyResponse_ifThrowIOException_fido2RuntimeException() throws IOException { - String username = "test_username"; - String authenticateResponseString = "test_authenticate_response_string"; - String clientData = "eyJ0eXAiOiJuYXZpZ2F0b3IuaWQuZ2V0QXNzZXJ0aW9uIiwiY2hhbGxlbmdlIjoidGVzdF9jaGFsbGVuZ2UiLCJvcmlnaW4iOiJ0ZXN0X29yaWdpbiJ9"; - String signatureData = "test_signature_data"; - String keyHandle = "test_key_handle"; - String deviceData = "test_device_data"; - AuthenticateResponse authenticateResponse = new AuthenticateResponse(clientData, signatureData, keyHandle, deviceData); - ObjectNode paramsNode = mapper.createObjectNode(); - ObjectNode clientDataNode = mapper.createObjectNode(); - ObjectNode responseNode = mapper.createObjectNode(); - ObjectNode attestationObjectNode = mapper.createObjectNode(); - when(dataMapperService.createObjectNode()).thenReturn(paramsNode, clientDataNode, responseNode, attestationObjectNode); - when(dataMapperService.cborWriteAsBytes(any())).thenThrow(new IOException("test_io_exception")); - RawAuthenticateResponse rawAuthenticateResponse = new RawAuthenticateResponse((byte) 1, 0L, "test_signature".getBytes()); - when(rawAuthenticationService.parseRawAuthenticateResponse(authenticateResponse.getSignatureData())).thenReturn(rawAuthenticateResponse); - when(base64Service.urlEncodeToString(any())).thenReturn("test_client_data_json", "test_signature", "test_authenticator_data", "test_attestation_object"); - when(digestService.hashSha256(anyString())).thenReturn("rp_id_hash".getBytes()); - when(errorResponseFactory.invalidRequest(contains("Failed to prepare attestationObject"), any())).thenReturn(new WebApplicationException(Response.status(400).entity("test exception").build())); - - WebApplicationException ex = assertThrows(WebApplicationException.class, () -> assertionSuperGluuController.buildFido2AuthenticationVerifyResponse(username, authenticateResponseString, authenticateResponse)); - assertNotNull(ex); - assertNotNull(ex.getResponse()); - assertEquals(ex.getResponse().getStatus(), 400); - assertEquals(ex.getResponse().getEntity(), "test exception"); - - verify(dataMapperService, times(2)).createObjectNode(); - verify(base64Service, times(3)).urlEncodeToString(any()); - verify(rawAuthenticationService).parseRawAuthenticateResponse(any()); - verifyNoInteractions(log); - } - - @Test - void buildFido2AuthenticationVerifyResponse_validValues_valid() throws IOException { - String username = "test_username"; - String authenticateResponseString = "test_authenticate_response_string"; - String clientData = "eyJ0eXAiOiJuYXZpZ2F0b3IuaWQuZ2V0QXNzZXJ0aW9uIiwiY2hhbGxlbmdlIjoidGVzdF9jaGFsbGVuZ2UiLCJvcmlnaW4iOiJ0ZXN0X29yaWdpbiJ9"; - String signatureData = "test_signature_data"; - String keyHandle = "test_key_handle"; - String deviceData = "test_device_data"; - AuthenticateResponse authenticateResponse = new AuthenticateResponse(clientData, signatureData, keyHandle, deviceData); - ObjectNode paramsNode = mapper.createObjectNode(); - ObjectNode clientDataNode = mapper.createObjectNode(); - ObjectNode responseNode = mapper.createObjectNode(); - ObjectNode attestationObjectNode = mapper.createObjectNode(); - when(dataMapperService.createObjectNode()).thenReturn(paramsNode, clientDataNode, responseNode, attestationObjectNode); - when(dataMapperService.cborWriteAsBytes(any())).thenReturn("test_attestation_object".getBytes()); - RawAuthenticateResponse rawAuthenticateResponse = new RawAuthenticateResponse((byte) 1, 0L, "test_signature".getBytes()); - when(rawAuthenticationService.parseRawAuthenticateResponse(authenticateResponse.getSignatureData())).thenReturn(rawAuthenticateResponse); - when(base64Service.urlEncodeToString(any())).thenReturn("test_client_data_json", "test_signature", "test_authenticator_data", "test_attestation_object"); - when(digestService.hashSha256(anyString())).thenReturn("rp_id_hash".getBytes()); - - AssertionResult response = assertionSuperGluuController.buildFido2AuthenticationVerifyResponse(username, authenticateResponseString, authenticateResponse); - assertNotNull(response); - assertNotNull(response.getSuperGluuRequest()); - assertNotNull(response.getSuperGluuRequestMode()); - assertNotNull(response.getSuperGluuRequestCancel()); - assertNotNull(response.getId()); - assertNotNull(response.getRawId()); - assertNotNull(response.getType()); - assertEquals((response.getSuperGluuRequest() == null ? "false" : response.getSuperGluuRequest().toString()),"true"); - assertEquals(response.getSuperGluuRequestMode(), "two_step"); - assertEquals((response.getSuperGluuRequestCancel() == null ? "false" : response.getSuperGluuRequestCancel().toString()),"false"); - assertEquals(response.getId(), "test_key_handle"); - assertEquals(response.getRawId(), "test_authenticate_response_string"); - assertEquals(response.getType(), "public-key"); - - assertNotNull(response.getResponse()); - io.jans.fido2.model.assertion.Response response1 = response.getResponse(); - assertNotNull(response1.getClientDataJSON()); - assertNotNull(response1.getSignature()); - assertNotNull(response1.getAuthenticatorData()); - assertNotNull(response1.getAttestationObject()); - assertEquals(response1.getClientDataJSON(), "test_client_data_json"); - assertEquals(response1.getSignature(), "test_signature"); - assertEquals(response1.getAuthenticatorData(), "test_authenticator_data"); - assertEquals(response1.getAttestationObject(), "test_attestation_object"); - - verify(dataMapperService, times(2)).createObjectNode(); - verify(base64Service, times(4)).urlEncodeToString(any()); - verify(rawAuthenticationService).parseRawAuthenticateResponse(any()); - verify(dataMapperService).cborWriteAsBytes(any()); - verify(log).debug("Prepared U2F_V2 assertion verify request: {}", response.toString()); - } - - @Test - void parseAuthenticateResponse_ifThrowIOException_fido2RpRuntimeException() throws IOException { - String authenticateResponseString = "wrong_authenticate_response_string"; - when(dataMapperService.readValue(authenticateResponseString, AuthenticateResponse.class)).thenThrow(new IOException("test_io_exception")); - when(errorResponseFactory.invalidRequest(any())).thenReturn(new WebApplicationException(Response.status(400).entity("test exception").build())); - - WebApplicationException ex = assertThrows(WebApplicationException.class, () -> assertionSuperGluuController.parseAuthenticateResponse(authenticateResponseString)); - assertNotNull(ex); - assertNotNull(ex.getResponse()); - assertEquals(ex.getResponse().getStatus(), 400); - assertEquals(ex.getResponse().getEntity(), "test exception"); - } - - @Test - void parseAuthenticateResponse_validValues_valid() throws IOException { - String authenticateResponseString = "test_authenticate_response_string"; - when(dataMapperService.readValue(authenticateResponseString, AuthenticateResponse.class)).thenReturn(mock(AuthenticateResponse.class)); - - AuthenticateResponse response = assertionSuperGluuController.parseAuthenticateResponse(authenticateResponseString); - assertNotNull(response); - } -} diff --git a/jans-fido2/server/src/test/java/io/jans/fido2/service/sg/converter/AttestationSuperGluuControllerTest.java b/jans-fido2/server/src/test/java/io/jans/fido2/service/sg/converter/AttestationSuperGluuControllerTest.java deleted file mode 100644 index 66a65e58c7f..00000000000 --- a/jans-fido2/server/src/test/java/io/jans/fido2/service/sg/converter/AttestationSuperGluuControllerTest.java +++ /dev/null @@ -1,388 +0,0 @@ -package io.jans.fido2.service.sg.converter; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyString; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoInteractions; -import static org.mockito.Mockito.verifyNoMoreInteractions; -import static org.mockito.Mockito.when; - -import java.io.IOException; -import java.security.cert.CertificateEncodingException; -import java.security.cert.X509Certificate; - -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; -import org.slf4j.Logger; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.node.ObjectNode; -import com.google.common.base.Strings; - -import io.jans.as.model.fido.u2f.message.RawRegisterResponse; -import io.jans.as.model.fido.u2f.protocol.RegisterResponse; -import io.jans.fido2.model.attestation.AttestationOptions; -import io.jans.fido2.model.attestation.AttestationResult; -import io.jans.fido2.model.attestation.PublicKeyCredentialCreationOptions; -import io.jans.fido2.model.common.AttestationOrAssertionResponse; -import io.jans.fido2.model.error.ErrorResponseFactory; -import io.jans.fido2.service.Base64Service; -import io.jans.fido2.service.CoseService; -import io.jans.fido2.service.DataMapperService; -import io.jans.fido2.service.DigestService; -import io.jans.fido2.service.operation.AttestationService; -import io.jans.fido2.service.persist.UserSessionIdService; -import io.jans.fido2.service.sg.RawRegistrationService; -import io.jans.fido2.service.util.CommonUtilService; -import jakarta.ws.rs.WebApplicationException; -import jakarta.ws.rs.core.Response; - -@ExtendWith(MockitoExtension.class) -class AttestationSuperGluuControllerTest { - - private final ObjectMapper mapper = new ObjectMapper(); - - @InjectMocks - private AttestationSuperGluuController attestationSuperGluuController; - - @Mock - private Logger log; - - @Mock - private AttestationService attestationService; - - @Mock - private DataMapperService dataMapperService; - - @Mock - private Base64Service base64Service; - - @Mock - private RawRegistrationService rawRegistrationService; - - @Mock - private CoseService coseService; - - @Mock - private DigestService digestService; - - @Mock - private UserSessionIdService userSessionIdService; - - @Mock - private ErrorResponseFactory errorResponseFactory; - - @Test - void startRegistration_validValues_valid() { - String username = "test-username"; - String appId = "test-appId"; - String sessionId = "test-sessionId"; - String enrollmentCode = "test-enrollmentCode"; - - when(userSessionIdService.isValidSessionId(sessionId, username)).thenReturn(true); - when(dataMapperService.createObjectNode()).thenReturn(mapper.createObjectNode()); - when(attestationService.options(any())).thenReturn(mock(PublicKeyCredentialCreationOptions.class)); - - JsonNode response = attestationSuperGluuController.startRegistration(username, appId, sessionId, enrollmentCode); - assertNotNull(response); - assertTrue(response.has("registerRequests")); - JsonNode registerRequestsNode = response.get("registerRequests"); - assertNotNull(registerRequestsNode); - assertFalse(registerRequestsNode.isEmpty()); - for (JsonNode itemNode : registerRequestsNode) { - assertTrue(itemNode.has("appId")); - assertTrue(itemNode.has("version")); - assertEquals(itemNode.get("appId").asText(), appId); - assertEquals(itemNode.get("version").asText(), "U2F_V2"); - } - verify(attestationService).options(any()); - verify(dataMapperService, times(1)).createObjectNode(); - } - - @Test - void buildFido2AttestationStartResponse_ifValidIsFalse_fido2ErrorResponseFactory() throws JsonProcessingException { - String username = "test-username"; - String appId = "test-appId"; - String sessionId = "test-sessionId"; - when(userSessionIdService.isValidSessionId(sessionId, username)).thenReturn(false); - when(errorResponseFactory.badRequestException(any(), any())).thenReturn(new WebApplicationException(Response.status(400).entity("test exception").build())); - - WebApplicationException ex = assertThrows(WebApplicationException.class, () -> attestationSuperGluuController.buildFido2AttestationStartResponse(username, appId, sessionId)); - assertNotNull(ex); - assertNotNull(ex.getResponse()); - assertEquals(ex.getResponse().getStatus(), 400); - assertEquals(ex.getResponse().getEntity(), "test exception"); - - verifyNoInteractions(dataMapperService, attestationService, log); - } - - @Test - void buildFido2AttestationStartResponse_ifOneStepIsTrue_valid() { - String username = ""; - String appId = "test-appId"; - String sessionId = "test-sessionId"; - when(userSessionIdService.isValidSessionId(sessionId, username)).thenReturn(true); - when(attestationService.generateUserId()).thenReturn("generate-userId"); - - AttestationOptions response = attestationSuperGluuController.buildFido2AttestationStartResponse(username, appId, sessionId); - assertNotNull(response); - - assertEquals(response.getUsername(), "generate-userId"); - assertEquals(response.getDisplayName(), "generate-userId"); - assertEquals(response.getSessionId(), sessionId); - assertEquals(response.getAttestation().getKeyName(), "direct"); - assertEquals(response.getSuperGluuRequest().toString(), "true"); - assertEquals(response.getSuperGluuRequestMode(), "one_step"); - assertEquals(response.getSuperGluuAppId(), appId); - - verify(userSessionIdService).isValidSessionId(sessionId, username); - //verify(dataMapperService).createObjectNode(); - verify(attestationService).generateUserId(); - verify(log).debug("Prepared U2F_V2 attestation options request: {}", CommonUtilService.toJsonNode(response).toString()); - } - - @Test - void buildFido2AttestationStartResponse_ifOneStepIsFalse_valid() { - String username = "test-username"; - String appId = "test-appId"; - String sessionId = "test-sessionId"; - when(userSessionIdService.isValidSessionId(sessionId, username)).thenReturn(true); - - AttestationOptions response = attestationSuperGluuController.buildFido2AttestationStartResponse(username, appId, sessionId); - assertNotNull(response); - - assertEquals(response.getUsername(), "test-username"); - assertEquals(response.getDisplayName(), "test-username"); - assertEquals(response.getSessionId(), sessionId); - assertEquals(response.getAttestation().getKeyName(), "direct"); - assertEquals(response.getSuperGluuRequest().toString(), "true"); - assertEquals(response.getSuperGluuRequestMode(), "two_step"); - assertEquals(response.getSuperGluuAppId(), appId); - - verify(userSessionIdService).isValidSessionId(sessionId, username); - //verify(dataMapperService).createObjectNode(); - verify(attestationService, never()).generateUserId(); - verify(log).debug("Prepared U2F_V2 attestation options request: {}", CommonUtilService.toJsonNode(response).toString()); - } - - @Test - void finishRegistration_validValues_valid() throws IOException { - String username = "test_username"; - String registerResponseString = "test_response_string"; - String registrationData = "test_registration_data"; - String clientData = "eyJ0eXAiOiJuYXZpZ2F0b3IuaWQuZmluaXNoRW5yb2xsbWVudCIsImNoYWxsZW5nZSI6InRlc3RfY2hhbGxlbmdlIiwib3JpZ2luIjoidGVzdF9vcmlnaW4ifQ"; - String deviceData = "test_device_data"; - RegisterResponse registerResponse = new RegisterResponse(registrationData, clientData, deviceData); - when(dataMapperService.readValue(registerResponseString, RegisterResponse.class)).thenReturn(registerResponse); - ObjectNode paramsNode = mapper.createObjectNode(); - ObjectNode responseNode = mapper.createObjectNode(); - ObjectNode clientDataNode = mapper.createObjectNode(); - ObjectNode attestationObjectNode = mapper.createObjectNode(); - ObjectNode attStmtNode = mapper.createObjectNode(); - when(dataMapperService.createObjectNode()).thenReturn(paramsNode, responseNode, clientDataNode, attestationObjectNode, attStmtNode); - RawRegisterResponse rawRegisterResponse = new RawRegisterResponse( - "test_public_key".getBytes(), - "test_key_handle".getBytes(), - mock(X509Certificate.class), - "test_signature".getBytes() - ); - AttestationOrAssertionResponse attestationResultResponse = new AttestationOrAssertionResponse(); - when(rawRegistrationService.parseRawRegisterResponse(registerResponse.getRegistrationData())).thenReturn(rawRegisterResponse); - when(base64Service.urlEncodeToString(any())).thenReturn("test_key_handle"); - when(digestService.hashSha256(anyString())).thenReturn("test_rp_id_hash".getBytes()); - when(coseService.convertECKeyToUncompressedPoint(any())).thenReturn(mapper.createObjectNode()); - when(dataMapperService.cborWriteAsBytes(any())).thenReturn("test_cose_public_key".getBytes()); - when(attestationService.verify(any())).thenReturn(mock(AttestationOrAssertionResponse.class)); - - JsonNode response = attestationSuperGluuController.finishRegistration(username, registerResponseString); - assertNotNull(response); - assertTrue(response.has("status")); - assertTrue(response.has("challenge")); - assertEquals(response.get("status").asText(), "success"); - assertEquals(response.get("challenge").asText(), "test_challenge"); - - verify(attestationService, times(1)).verify(any()); - } - - @Test - void parseRegisterResponse_ifReadValueThrowException_fido2RpRuntimeException() throws IOException { - String registerResponseString = "wrong_response_string"; - when(dataMapperService.readValue(registerResponseString, RegisterResponse.class)).thenThrow(new IOException("test_io_exception")); - when(errorResponseFactory.invalidRequest(any(), any())).thenReturn(new WebApplicationException(Response.status(400).entity("test exception").build())); - - WebApplicationException ex = assertThrows(WebApplicationException.class, () -> attestationSuperGluuController.parseRegisterResponse(registerResponseString)); - assertNotNull(ex); - assertNotNull(ex.getResponse()); - assertEquals(ex.getResponse().getStatus(), 400); - assertEquals(ex.getResponse().getEntity(), "test exception"); - } - - @Test - void parseRegisterResponse_validValues_valid() throws IOException { - String registerResponseString = "test_response_string"; - when(dataMapperService.readValue(registerResponseString, RegisterResponse.class)).thenReturn(mock(RegisterResponse.class)); - - RegisterResponse response = attestationSuperGluuController.parseRegisterResponse(registerResponseString); - assertNotNull(response); - } - - @Test - void buildFido2AttestationVerifyResponse_ifClientDataUnsupportedRegisterTypes_fido2RuntimeException() { - String username = "test_username"; - String registrationData = "test_registration_data"; - String clientData = "eyJ0eXAiOiJ3cm9uZ190eXBlIiwiY2hhbGxlbmdlIjoidGVzdF9jaGFsbGVuZ2UiLCJvcmlnaW4iOiJ0ZXN0X29yaWdpbiJ9"; - String deviceData = "test_device_data"; - RegisterResponse registerResponse = new RegisterResponse(registrationData, clientData, deviceData); - when(errorResponseFactory.badRequestException(any(), any())).thenReturn(new WebApplicationException(Response.status(400).entity("test exception").build())); - - WebApplicationException ex = assertThrows(WebApplicationException.class, () -> attestationSuperGluuController.buildFido2AttestationVerifyResponse(username, registerResponse)); - assertNotNull(ex); - assertNotNull(ex.getResponse()); - assertEquals(ex.getResponse().getStatus(), 400); - assertEquals(ex.getResponse().getEntity(), "test exception"); - - verifyNoInteractions(dataMapperService, base64Service, rawRegistrationService, log); - } - - @Test - void buildFido2AttestationVerifyResponse_ifThrowCertificateEncodingException_fido2RuntimeException() throws CertificateEncodingException, IOException { - String username = "test_username"; - String registrationData = "test_registration_data"; - String clientData = "eyJ0eXAiOiJuYXZpZ2F0b3IuaWQuZmluaXNoRW5yb2xsbWVudCIsImNoYWxsZW5nZSI6InRlc3RfY2hhbGxlbmdlIiwib3JpZ2luIjoidGVzdF9vcmlnaW4ifQ"; - String deviceData = "test_device_data"; - RegisterResponse registerResponse = new RegisterResponse(registrationData, clientData, deviceData); - ObjectNode paramsNode = mapper.createObjectNode(); - ObjectNode responseNode = mapper.createObjectNode(); - ObjectNode clientDataNode = mapper.createObjectNode(); - ObjectNode attestationObjectNode = mapper.createObjectNode(); - ObjectNode attStmtNode = mapper.createObjectNode(); - when(dataMapperService.createObjectNode()).thenReturn(paramsNode, responseNode, clientDataNode, attestationObjectNode, attStmtNode); - when(base64Service.urlEncodeToString(any())).thenReturn("test_client_data", "test_key_handle"); - X509Certificate x509Certificate = mock(X509Certificate.class); - RawRegisterResponse rawRegisterResponse = new RawRegisterResponse( - "test_public_key".getBytes(), - "test_key_handle".getBytes(), - x509Certificate, - "test_signature".getBytes() - ); - when(rawRegistrationService.parseRawRegisterResponse(registerResponse.getRegistrationData())).thenReturn(rawRegisterResponse); - when(x509Certificate.getEncoded()).thenThrow(new CertificateEncodingException("test_certificate_exception")); - when(errorResponseFactory.invalidRequest(any(), any())).thenReturn(new WebApplicationException(Response.status(400).entity("test exception").build())); - - WebApplicationException ex = assertThrows(WebApplicationException.class, () -> attestationSuperGluuController.buildFido2AttestationVerifyResponse(username, registerResponse)); - assertNotNull(ex); - assertNotNull(ex.getResponse()); - assertEquals(ex.getResponse().getStatus(), 400); - assertEquals(ex.getResponse().getEntity(), "test exception"); - - verify(base64Service, times(2)).urlEncodeToString(any()); - verify(dataMapperService, never()).cborWriteAsBytes(any()); - verifyNoMoreInteractions(base64Service); - verifyNoInteractions(log); - } - - @Test - void buildFido2AttestationVerifyResponse_ifThrowIOException_fido2RuntimeException() throws IOException { - String username = "test_username"; - String registrationData = "test_registration_data"; - String clientData = "eyJ0eXAiOiJuYXZpZ2F0b3IuaWQuZmluaXNoRW5yb2xsbWVudCIsImNoYWxsZW5nZSI6InRlc3RfY2hhbGxlbmdlIiwib3JpZ2luIjoidGVzdF9vcmlnaW4ifQ"; - String deviceData = "test_device_data"; - RegisterResponse registerResponse = new RegisterResponse(registrationData, clientData, deviceData); - ObjectNode paramsNode = mapper.createObjectNode(); - ObjectNode responseNode = mapper.createObjectNode(); - ObjectNode clientDataNode = mapper.createObjectNode(); - ObjectNode attestationObjectNode = mapper.createObjectNode(); - ObjectNode attStmtNode = mapper.createObjectNode(); - when(dataMapperService.createObjectNode()).thenReturn(paramsNode, responseNode, clientDataNode, attestationObjectNode, attStmtNode); - when(base64Service.urlEncodeToString(any())).thenReturn("test_client_data", "test_key_handle"); - when(dataMapperService.cborWriteAsBytes(any())).thenThrow(new IOException("test_io_exception")); - when(base64Service.encodeToString(any())).thenReturn("test_attestation_certificate"); - RawRegisterResponse rawRegisterResponse = new RawRegisterResponse( - "test_public_key".getBytes(), - "test_key_handle".getBytes(), - mock(X509Certificate.class), - "test_signature".getBytes() - ); - when(rawRegistrationService.parseRawRegisterResponse(registerResponse.getRegistrationData())).thenReturn(rawRegisterResponse); - when(errorResponseFactory.invalidRequest(any(), any())).thenReturn(new WebApplicationException(Response.status(400).entity("test exception").build())); - - WebApplicationException ex = assertThrows(WebApplicationException.class, () -> attestationSuperGluuController.buildFido2AttestationVerifyResponse(username, registerResponse)); - assertNotNull(ex); - assertNotNull(ex.getResponse()); - assertEquals(ex.getResponse().getStatus(), 400); - assertEquals(ex.getResponse().getEntity(), "test exception"); - - verify(base64Service, times(2)).urlEncodeToString(any()); - verify(dataMapperService).cborWriteAsBytes(any()); - verifyNoMoreInteractions(base64Service); - verifyNoInteractions(log); - } - - @Test - void buildFido2AttestationVerifyResponse_validValues_valid() throws IOException { - String username = "test_username"; - String registrationData = "test_registration_data"; - String clientData = "eyJ0eXAiOiJuYXZpZ2F0b3IuaWQuZmluaXNoRW5yb2xsbWVudCIsImNoYWxsZW5nZSI6InRlc3RfY2hhbGxlbmdlIiwib3JpZ2luIjoidGVzdF9vcmlnaW4ifQ"; - String deviceData = "test_device_data"; - RegisterResponse registerResponse = new RegisterResponse(registrationData, clientData, deviceData); - ObjectNode paramsNode = mapper.createObjectNode(); - ObjectNode responseNode = mapper.createObjectNode(); - ObjectNode clientDataNode = mapper.createObjectNode(); - ObjectNode attestationObjectNode = mapper.createObjectNode(); - ObjectNode attStmtNode = mapper.createObjectNode(); - when(dataMapperService.createObjectNode()).thenReturn(paramsNode, responseNode, clientDataNode, attestationObjectNode, attStmtNode); - when(base64Service.urlEncodeToString(any())).thenReturn("test_client_data", "test_key_handle"); - when(dataMapperService.cborWriteAsBytes(any())).thenReturn("test_code_public_key".getBytes(), "test_attestation_object".getBytes()); - when(base64Service.encodeToString(any())).thenReturn("test_attestation_certificate"); - RawRegisterResponse rawRegisterResponse = new RawRegisterResponse( - "test_public_key".getBytes(), - "test_key_handle".getBytes(), - mock(X509Certificate.class), - "test_signature".getBytes() - ); - when(rawRegistrationService.parseRawRegisterResponse(registerResponse.getRegistrationData())).thenReturn(rawRegisterResponse); - when(digestService.hashSha256(anyString())).thenReturn("test_rp_id_hash".getBytes()); - when(coseService.convertECKeyToUncompressedPoint(any())).thenReturn(mapper.createObjectNode()); - - AttestationResult attestationResult = attestationSuperGluuController.buildFido2AttestationVerifyResponse(username, registerResponse); - assertNotNull(attestationResult); - assertNotNull(attestationResult.getSuperGluuRequest()); - assertFalse(Strings.isNullOrEmpty(attestationResult.getSuperGluuRequestMode())); - assertNotNull(attestationResult.getSuperGluuRequestCancel()); - assertNotNull(attestationResult.getId()); - assertNotNull(attestationResult.getType()); - assertNotNull(attestationResult.getResponse()); - assertEquals(attestationResult.getSuperGluuRequest().toString(), "true"); - assertEquals(attestationResult.getSuperGluuRequestMode(), "two_step"); - assertEquals(attestationResult.getSuperGluuRequestCancel().toString(), "false"); - assertEquals(attestationResult.getId(), "test_key_handle"); - assertEquals(attestationResult.getType(), "public-key"); - io.jans.fido2.model.attestation.Response response = attestationResult.getResponse(); - assertNotNull(response.getDeviceData()); - assertNotNull(response.getClientDataJSON()); - assertNotNull(response.getAttestationObject()); - assertEquals(response.getDeviceData(), "test_device_data"); - assertEquals(response.getClientDataJSON(), "test_client_data"); - assertEquals(response.getAttestationObject(), "test_key_handle"); - - verify(dataMapperService, times(3)).createObjectNode(); - verify(dataMapperService, times(2)).cborWriteAsBytes(any()); - verify(base64Service, times(3)).urlEncodeToString(any()); - verify(base64Service).encodeToString(any()); - verify(log).debug("Prepared U2F_V2 attestation verify request: {}", attestationResult.toString()); - verify(rawRegistrationService).parseRawRegisterResponse(any()); - } -} diff --git a/jans-fido2/server/src/test/java/io/jans/fido2/ws/rs/controller/AssertionControllerTest.java b/jans-fido2/server/src/test/java/io/jans/fido2/ws/rs/controller/AssertionControllerTest.java index 5b9b84ab4e8..2ea8c3aaf1b 100644 --- a/jans-fido2/server/src/test/java/io/jans/fido2/ws/rs/controller/AssertionControllerTest.java +++ b/jans-fido2/server/src/test/java/io/jans/fido2/ws/rs/controller/AssertionControllerTest.java @@ -1,30 +1,38 @@ package io.jans.fido2.ws.rs.controller; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.node.ObjectNode; -import io.jans.fido2.model.assertion.*; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.contains; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoInteractions; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.Mockito.when; + +import java.io.IOException; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.slf4j.Logger; + +import io.jans.fido2.model.assertion.AssertionOptions; +import io.jans.fido2.model.assertion.AssertionOptionsResponse; +import io.jans.fido2.model.assertion.AssertionResult; import io.jans.fido2.model.common.AttestationOrAssertionResponse; import io.jans.fido2.model.conf.AppConfiguration; import io.jans.fido2.model.conf.Fido2Configuration; import io.jans.fido2.model.error.ErrorResponseFactory; import io.jans.fido2.service.DataMapperService; import io.jans.fido2.service.operation.AssertionService; -import io.jans.fido2.service.sg.converter.AssertionSuperGluuController; import io.jans.fido2.service.verifier.CommonVerifiers; import jakarta.ws.rs.BadRequestException; import jakarta.ws.rs.WebApplicationException; import jakarta.ws.rs.core.Response; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; -import org.slf4j.Logger; - -import java.io.IOException; - -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.Mockito.*; @ExtendWith(MockitoExtension.class) class AssertionControllerTest { @@ -41,9 +49,6 @@ class AssertionControllerTest { @Mock private DataMapperService dataMapperService; - @Mock - private AssertionSuperGluuController assertionSuperGluuController; - @Mock private AppConfiguration appConfiguration; @@ -97,7 +102,6 @@ void authenticate_ifThrownException_unknownError() throws IOException { verify(appConfiguration).getFido2Configuration(); verify(log).error(contains("Unknown Error"), any(), any()); - verify(commonVerifiers).verifyNotUseGluuParameters(any()); verify(assertionService).options(any()); verifyNoMoreInteractions(errorResponseFactory); } @@ -112,7 +116,6 @@ void authenticate_ifValidData_success() throws IOException { assertEquals(response.getStatus(), 200); verify(appConfiguration).getFido2Configuration(); - verify(commonVerifiers).verifyNotUseGluuParameters(any()); verify(assertionService).options(any()); verifyNoInteractions(log, errorResponseFactory); } @@ -215,7 +218,6 @@ void generateAuthenticate_ifValidData_success() throws IOException { assertEquals(response.getStatus(), 200); verify(appConfiguration).getFido2Configuration(); - verify(commonVerifiers).verifyNotUseGluuParameters(any()); verify(assertionService).options(any()); verifyNoInteractions(log, errorResponseFactory); } @@ -265,7 +267,6 @@ void verify_ifThrownException_unknownError() throws IOException { verify(appConfiguration).getFido2Configuration(); verify(log).error(contains("Unknown Error"), any(), any()); - verify(commonVerifiers).verifyNotUseGluuParameters(any()); verify(assertionService).verify(any()); verifyNoMoreInteractions(errorResponseFactory); } @@ -280,139 +281,11 @@ void verify_ifValidData_success() throws IOException { assertEquals(response.getStatus(), 200); verify(appConfiguration).getFido2Configuration(); - verify(commonVerifiers).verifyNotUseGluuParameters(any()); verify(assertionService).verify(any()); verifyNoInteractions(log, errorResponseFactory); } - @Test - void startAuthentication_ifFido2ConfigurationIsNullAndSuperGluuEnabledIsFalse_forbiddenException() { - String userName = "test_username"; - String keyHandle = "test_key_handle"; - String appId = "test_app_id"; - String sessionId = "test_session_id"; - when(appConfiguration.getFido2Configuration()).thenReturn(null); - when(appConfiguration.isSuperGluuEnabled()).thenReturn(false); - when(errorResponseFactory.forbiddenException()).thenReturn(new WebApplicationException(Response.status(500).entity("test exception").build())); - - WebApplicationException ex = assertThrows(WebApplicationException.class, () -> assertionController.startAuthentication(userName, keyHandle, appId, sessionId)); - assertNotNull(ex); - assertNotNull(ex.getResponse()); - assertEquals(ex.getResponse().getStatus(), 500); - assertEquals(ex.getResponse().getEntity(), "test exception"); - - verify(appConfiguration).getFido2Configuration(); - verify(appConfiguration).isSuperGluuEnabled(); - verifyNoInteractions(log, assertionSuperGluuController); - verifyNoMoreInteractions(errorResponseFactory); - } - - @Test - void startAuthentication_ifFidoConfigurationNotNullAndThrownError_unknownError() { - String userName = "test_username"; - String keyHandle = "test_key_handle"; - String appId = "test_app_id"; - String sessionId = "test_session_id"; - when(appConfiguration.getFido2Configuration()).thenReturn(mock(Fido2Configuration.class)); - when(assertionSuperGluuController.startAuthentication(any(), any(), any(), any())).thenThrow(new RuntimeException("Runtime test error")); - when(errorResponseFactory.unknownError(any())).thenReturn(new WebApplicationException(Response.status(500).entity("test exception").build())); - - WebApplicationException ex = assertThrows(WebApplicationException.class, () -> assertionController.startAuthentication(userName, keyHandle, appId, sessionId)); - assertNotNull(ex); - assertNotNull(ex.getResponse()); - assertEquals(ex.getResponse().getStatus(), 500); - assertEquals(ex.getResponse().getEntity(), "test exception"); - - verify(appConfiguration).getFido2Configuration(); - verify(appConfiguration, never()).isSuperGluuEnabled(); - verify(log).debug("Start authentication: username = {}, keyhandle = {}, application = {}, session_id = {}", userName, keyHandle, appId, sessionId); - verify(log).error(contains("Unknown Error"), any(), any()); - verifyNoMoreInteractions(appConfiguration, log); - } - - @Test - void startAuthentication_ifFidoConfigurationIsNullAndSuperGluuEnabledIsTrue_success() { - String userName = "test_username"; - String keyHandle = "test_key_handle"; - String appId = "test_app_id"; - String sessionId = "test_session_id"; - when(appConfiguration.getFido2Configuration()).thenReturn(null); - when(appConfiguration.isSuperGluuEnabled()).thenReturn(true); - when(assertionSuperGluuController.startAuthentication(any(), any(), any(), any())).thenReturn(mock(ObjectNode.class)); - - Response response = assertionController.startAuthentication(userName, keyHandle, appId, sessionId); - assertNotNull(response); - assertEquals(response.getStatus(), 200); - - verify(appConfiguration).getFido2Configuration(); - verify(appConfiguration).isSuperGluuEnabled(); - verify(assertionSuperGluuController).startAuthentication(userName, keyHandle, appId, sessionId); - verify(log).debug("Start authentication: username = {}, keyhandle = {}, application = {}, session_id = {}", userName, keyHandle, appId, sessionId); - verify(log).debug(contains("Prepared U2F_V2 authentication options request"), anyString()); - verifyNoInteractions(errorResponseFactory); - verifyNoMoreInteractions(log); - } + - @Test - void finishAuthentication_ifFido2ConfigurationIsNullAndSuperGluuEnabledIsFalse_forbiddenException() { - String userName = "test_username"; - String authenticateResponseString = "test_authenticate_response_string"; - when(appConfiguration.getFido2Configuration()).thenReturn(null); - when(appConfiguration.isSuperGluuEnabled()).thenReturn(false); - - when(errorResponseFactory.forbiddenException()).thenReturn(new WebApplicationException(Response.status(500).entity("test exception").build())); - - WebApplicationException ex = assertThrows(WebApplicationException.class, () -> assertionController.finishAuthentication(userName, authenticateResponseString)); - assertNotNull(ex); - assertNotNull(ex.getResponse()); - assertEquals(ex.getResponse().getStatus(), 500); - assertEquals(ex.getResponse().getEntity(), "test exception"); - - verify(appConfiguration).getFido2Configuration(); - verify(appConfiguration).isSuperGluuEnabled(); - verifyNoInteractions(log, assertionSuperGluuController); - verifyNoMoreInteractions(errorResponseFactory); - } - - @Test - void finishAuthentication_ifFidoConfigurationNotNullAndThrownError_unknownError() { - String userName = "test_username"; - String authenticateResponseString = "test_authenticate_response_string"; - when(appConfiguration.getFido2Configuration()).thenReturn(mock(Fido2Configuration.class)); - when(assertionSuperGluuController.finishAuthentication(any(), any())).thenThrow(new RuntimeException("Runtime test error")); - when(errorResponseFactory.unknownError(any())).thenReturn(new WebApplicationException(Response.status(500).entity("test exception").build())); - - WebApplicationException ex = assertThrows(WebApplicationException.class, () -> assertionController.finishAuthentication(userName, authenticateResponseString)); - assertNotNull(ex); - assertNotNull(ex.getResponse()); - assertEquals(ex.getResponse().getStatus(), 500); - assertEquals(ex.getResponse().getEntity(), "test exception"); - - verify(appConfiguration).getFido2Configuration(); - verify(appConfiguration, never()).isSuperGluuEnabled(); - verify(log).debug("Finish authentication: username = {}, tokenResponse = {}", userName, authenticateResponseString); - verify(log).error(contains("Unknown Error"), any(), any()); - verifyNoMoreInteractions(appConfiguration, log); - } - - @Test - void finishAuthentication_ifFidoConfigurationIsNullAndSuperGluuEnabledIsTrue_success() { - String userName = "test_username"; - String authenticateResponseString = "test_authenticate_response_string"; - when(appConfiguration.getFido2Configuration()).thenReturn(null); - when(appConfiguration.isSuperGluuEnabled()).thenReturn(true); - when(assertionSuperGluuController.finishAuthentication(any(), any())).thenReturn(mock(ObjectNode.class)); - - Response response = assertionController.finishAuthentication(userName, authenticateResponseString); - assertNotNull(response); - assertEquals(response.getStatus(), 200); - - verify(appConfiguration).getFido2Configuration(); - verify(appConfiguration).isSuperGluuEnabled(); - verify(assertionSuperGluuController).finishAuthentication(userName, authenticateResponseString); - verify(log).debug("Finish authentication: username = {}, tokenResponse = {}", userName, authenticateResponseString); - verify(log).debug(contains("Prepared U2F_V2 authentication verify request"), anyString()); - verifyNoInteractions(errorResponseFactory); - verifyNoMoreInteractions(log); - } + } diff --git a/jans-fido2/server/src/test/java/io/jans/fido2/ws/rs/controller/AttestationControllerTest.java b/jans-fido2/server/src/test/java/io/jans/fido2/ws/rs/controller/AttestationControllerTest.java index 07179b7a306..a328276e354 100644 --- a/jans-fido2/server/src/test/java/io/jans/fido2/ws/rs/controller/AttestationControllerTest.java +++ b/jans-fido2/server/src/test/java/io/jans/fido2/ws/rs/controller/AttestationControllerTest.java @@ -33,7 +33,6 @@ import io.jans.fido2.model.error.ErrorResponseFactory; import io.jans.fido2.service.DataMapperService; import io.jans.fido2.service.operation.AttestationService; -import io.jans.fido2.service.sg.converter.AttestationSuperGluuController; import io.jans.fido2.service.verifier.CommonVerifiers; import jakarta.ws.rs.BadRequestException; import jakarta.ws.rs.WebApplicationException; @@ -57,9 +56,6 @@ class AttestationControllerTest { @Mock private CommonVerifiers commonVerifiers; - @Mock - private AttestationSuperGluuController attestationSuperGluuController; - @Mock private AppConfiguration appConfiguration; @@ -109,7 +105,6 @@ void register_ifThrownException_unknownError() throws IOException { verify(appConfiguration).getFido2Configuration(); verify(log).error(contains("Unknown Error"), any(), any()); - verify(commonVerifiers).verifyNotUseGluuParameters(any()); verify(attestationService).options(any()); verifyNoMoreInteractions(errorResponseFactory); } @@ -124,7 +119,6 @@ void register_ifValidData_success() throws IOException { assertEquals(response.getStatus(), 200); verify(appConfiguration).getFido2Configuration(); - verify(commonVerifiers).verifyNotUseGluuParameters(any()); verify(attestationService).options(any()); verifyNoInteractions(log, errorResponseFactory); } @@ -175,7 +169,6 @@ void verify_ifThrownException_unknownError() throws IOException { verify(appConfiguration).getFido2Configuration(); verify(log).error(contains("Unknown Error"), any(), any()); - verify(commonVerifiers).verifyNotUseGluuParameters(any()); verify(attestationService).verify(any()); verifyNoMoreInteractions(errorResponseFactory); } @@ -190,138 +183,8 @@ void verify_ifValidData_success() throws IOException { assertEquals(response.getStatus(), 200); verify(appConfiguration).getFido2Configuration(); - verify(commonVerifiers).verifyNotUseGluuParameters(any()); verify(attestationService).verify(any()); verifyNoInteractions(log, errorResponseFactory); } - @Test - void startRegistration_ifFido2ConfigurationIsNullAndSuperGluuEnabledIsFalse_forbiddenException() { - String userName = "test_username"; - String appId = "test_app_id"; - String sessionId = "test_session_id"; - String enrollmentCode = "test_enrollment_code"; - when(appConfiguration.getFido2Configuration()).thenReturn(null); - when(appConfiguration.isSuperGluuEnabled()).thenReturn(false); - when(errorResponseFactory.forbiddenException()).thenReturn(new WebApplicationException(Response.status(500).entity("test exception").build())); - - WebApplicationException ex = assertThrows(WebApplicationException.class, () -> attestationController.startRegistration(userName, appId, sessionId, enrollmentCode)); - assertNotNull(ex); - assertNotNull(ex.getResponse()); - assertEquals(ex.getResponse().getStatus(), 500); - assertEquals(ex.getResponse().getEntity(), "test exception"); - - verify(appConfiguration).getFido2Configuration(); - verify(appConfiguration).isSuperGluuEnabled(); - verifyNoInteractions(log, attestationSuperGluuController); - verifyNoMoreInteractions(errorResponseFactory); - } - - @Test - void startRegistration_ifFidoConfigurationNotNullAndThrownError_unknownError() { - String userName = "test_username"; - String appId = "test_app_id"; - String sessionId = "test_session_id"; - String enrollmentCode = "test_enrollment_code"; - when(appConfiguration.getFido2Configuration()).thenReturn(mock(Fido2Configuration.class)); - when(attestationSuperGluuController.startRegistration(any(), any(), any(), any())).thenThrow(new RuntimeException("Runtime test error")); - when(errorResponseFactory.unknownError(any())).thenReturn(new WebApplicationException(Response.status(500).entity("test exception").build())); - - WebApplicationException ex = assertThrows(WebApplicationException.class, () -> attestationController.startRegistration(userName, appId, sessionId, enrollmentCode)); - assertNotNull(ex); - assertNotNull(ex.getResponse()); - assertEquals(ex.getResponse().getStatus(), 500); - assertEquals(ex.getResponse().getEntity(), "test exception"); - - verify(appConfiguration).getFido2Configuration(); - verify(appConfiguration, never()).isSuperGluuEnabled(); - verify(log).debug("Start registration: username = {}, application = {}, session_id = {}, enrollment_code = {}", userName, appId, sessionId, enrollmentCode); - verify(log).error(contains("Unknown Error"), any(), any()); - verifyNoMoreInteractions(appConfiguration, log); - } - - @Test - void startRegistration_ifFidoConfigurationIsNullAndSuperGluuEnabledIsTrue_success() { - String userName = "test_username"; - String appId = "test_app_id"; - String sessionId = "test_session_id"; - String enrollmentCode = "test_enrollment_code"; - when(appConfiguration.getFido2Configuration()).thenReturn(null); - when(appConfiguration.isSuperGluuEnabled()).thenReturn(true); - when(attestationSuperGluuController.startRegistration(any(), any(), any(), any())).thenReturn(mock(ObjectNode.class)); - - Response response = attestationController.startRegistration(userName, appId, sessionId, enrollmentCode); - assertNotNull(response); - assertEquals(response.getStatus(), 200); - - verify(appConfiguration).getFido2Configuration(); - verify(appConfiguration).isSuperGluuEnabled(); - verify(attestationSuperGluuController).startRegistration(userName, appId, sessionId, enrollmentCode); - verify(log).debug("Start registration: username = {}, application = {}, session_id = {}, enrollment_code = {}", userName, appId, sessionId, enrollmentCode); - verify(log).debug(contains("Prepared U2F_V2 registration options request"), anyString()); - verifyNoInteractions(errorResponseFactory); - verifyNoMoreInteractions(log); - } - - @Test - void finishRegistration_ifFido2ConfigurationIsNullAndSuperGluuEnabledIsFalse_forbiddenException() { - String userName = "test_username"; - String authenticateResponseString = "test_authenticate_response_string"; - when(appConfiguration.getFido2Configuration()).thenReturn(null); - when(appConfiguration.isSuperGluuEnabled()).thenReturn(false); - when(errorResponseFactory.forbiddenException()).thenReturn(new WebApplicationException(Response.status(500).entity("test exception").build())); - - WebApplicationException ex = assertThrows(WebApplicationException.class, () -> attestationController.finishRegistration(userName, authenticateResponseString)); - assertNotNull(ex); - assertNotNull(ex.getResponse()); - assertEquals(ex.getResponse().getStatus(), 500); - assertEquals(ex.getResponse().getEntity(), "test exception"); - - verify(appConfiguration).getFido2Configuration(); - verify(appConfiguration).isSuperGluuEnabled(); - verifyNoInteractions(log, attestationSuperGluuController); - verifyNoMoreInteractions(errorResponseFactory); - } - - @Test - void finishRegistration_ifFidoConfigurationNotNullAndThrownError_unknownError() { - String userName = "test_username"; - String authenticateResponseString = "test_authenticate_response_string"; - when(appConfiguration.getFido2Configuration()).thenReturn(mock(Fido2Configuration.class)); - when(attestationSuperGluuController.finishRegistration(any(), any())).thenThrow(new RuntimeException("Runtime test error")); - when(errorResponseFactory.unknownError(any())).thenReturn(new WebApplicationException(Response.status(500).entity("test exception").build())); - - WebApplicationException ex = assertThrows(WebApplicationException.class, () -> attestationController.finishRegistration(userName, authenticateResponseString)); - assertNotNull(ex); - assertNotNull(ex.getResponse()); - assertEquals(ex.getResponse().getStatus(), 500); - assertEquals(ex.getResponse().getEntity(), "test exception"); - - verify(appConfiguration).getFido2Configuration(); - verify(appConfiguration, never()).isSuperGluuEnabled(); - verify(log).debug("Finish registration: username = {}, tokenResponse = {}", userName, authenticateResponseString); - verify(log).error(contains("Unknown Error"), any(), any()); - verifyNoMoreInteractions(appConfiguration, log); - } - - @Test - void finishRegistration_ifFidoConfigurationIsNullAndSuperGluuEnabledIsTrue_success() { - String userName = "test_username"; - String authenticateResponseString = "test_authenticate_response_string"; - when(appConfiguration.getFido2Configuration()).thenReturn(null); - when(appConfiguration.isSuperGluuEnabled()).thenReturn(true); - when(attestationSuperGluuController.finishRegistration(any(), any())).thenReturn(mock(ObjectNode.class)); - - Response response = attestationController.finishRegistration(userName, authenticateResponseString); - assertNotNull(response); - assertEquals(response.getStatus(), 200); - - verify(appConfiguration).getFido2Configuration(); - verify(appConfiguration).isSuperGluuEnabled(); - verify(attestationSuperGluuController).finishRegistration(userName, authenticateResponseString); - verify(log).debug("Finish registration: username = {}, tokenResponse = {}", userName, authenticateResponseString); - verify(log).debug(contains("Prepared U2F_V2 registration verify request"), anyString()); - verifyNoInteractions(errorResponseFactory); - verifyNoMoreInteractions(log); - } }