diff --git a/.github/workflows/junit.yml b/.github/workflows/junit.yml index 32bf8fd46..7ae63d690 100644 --- a/.github/workflows/junit.yml +++ b/.github/workflows/junit.yml @@ -16,6 +16,7 @@ jobs: fail-fast: false matrix: jdk-version: [8,11,17] + max-parallel: 1 steps: - uses: actions/checkout@v4 @@ -25,4 +26,10 @@ jobs: distribution: 'zulu' java-version: ${{ matrix.jdk-version }} architecture: x64 + - uses: actions/cache@v4 + with: + path: ~/.m2/repository + key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} + restore-keys: | + ${{ runner.os }}-maven- - run: mvn test -B -pl yoti-sdk-api -Ddependency-check.skip=true diff --git a/README.md b/README.md index 6d4715c49..278c4bb0d 100644 --- a/README.md +++ b/README.md @@ -101,13 +101,13 @@ If you are using Maven, you need to add the following dependency: com.yoti yoti-sdk-api - 3.12.0 + 4.0.0 ``` If you are using Gradle, here is the dependency to add: -`compile group: 'com.yoti', name: 'yoti-sdk-api', version: '3.12.0'` +`compile group: 'com.yoti', name: 'yoti-sdk-api', version: '4.0.0'` You will find all classes packaged under `com.yoti.api` @@ -294,6 +294,10 @@ Instructions on how to run the Spring example projects can be found at the follo This major update does not have any major updates to the API, but instead builds upon and standardizes our implementation. +## Breaking changes and enhancements made in v4.0.0 + +- Creating an Identity Profile session now uses strongly typed classes, instead of a Map + ### Dropped support for Java 7 Minimum supported Java version is now 8. diff --git a/examples/doc-scan/pom.xml b/examples/doc-scan/pom.xml index 3437b01cc..73adc9d6c 100644 --- a/examples/doc-scan/pom.xml +++ b/examples/doc-scan/pom.xml @@ -53,7 +53,7 @@ com.yoti yoti-sdk-api - 3.12.0 + 4.0.0 diff --git a/examples/doc-scan/src/main/resources/templates/success.html b/examples/doc-scan/src/main/resources/templates/success.html index 1d85831f9..2ddeb6f4a 100644 --- a/examples/doc-scan/src/main/resources/templates/success.html +++ b/examples/doc-scan/src/main/resources/templates/success.html @@ -965,6 +965,14 @@

Identity Profile

+ +
+ Generated Profile Media: + +
+
+
diff --git a/pom.xml b/pom.xml index 58299e883..83355e89f 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ com.yoti yoti-sdk pom - 3.12.0 + 4.0.0 Yoti SDK Java SDK for simple integration with the Yoti platform https://github.com/getyoti/yoti-java-sdk @@ -13,6 +13,7 @@ yoti-sdk-parent yoti-sdk-api + yoti-sdk-auth yoti-sdk-sandbox yoti-sdk-spring-boot-auto-config yoti-sdk-spring-security diff --git a/yoti-sdk-api/pom.xml b/yoti-sdk-api/pom.xml index 18bcca29a..78eb438d1 100644 --- a/yoti-sdk-api/pom.xml +++ b/yoti-sdk-api/pom.xml @@ -11,7 +11,7 @@ com.yoti yoti-sdk-parent - 3.12.0 + 4.0.0 ../yoti-sdk-parent diff --git a/yoti-sdk-api/spotbugs/exclude-filter.xml b/yoti-sdk-api/spotbugs/exclude-filter.xml index 827443487..af1625f33 100644 --- a/yoti-sdk-api/spotbugs/exclude-filter.xml +++ b/yoti-sdk-api/spotbugs/exclude-filter.xml @@ -27,12 +27,12 @@ - + - + diff --git a/yoti-sdk-api/src/main/java/com/yoti/api/client/DigitalIdentityClient.java b/yoti-sdk-api/src/main/java/com/yoti/api/client/DigitalIdentityClient.java index 1690a9835..d66520776 100644 --- a/yoti-sdk-api/src/main/java/com/yoti/api/client/DigitalIdentityClient.java +++ b/yoti-sdk-api/src/main/java/com/yoti/api/client/DigitalIdentityClient.java @@ -23,49 +23,36 @@ public class DigitalIdentityClient { Security.addProvider(new BouncyCastleProvider()); } - private final String sdkId; private final KeyPair keyPair; private final DigitalIdentityService identityService; - DigitalIdentityClient(String sdkId, KeyPairSource keyPair, DigitalIdentityService identityService) { - Validation.notNullOrEmpty(sdkId, "SDK ID"); - Validation.notNull(keyPair, "Application Key Pair"); - - this.sdkId = sdkId; - this.keyPair = loadKeyPair(keyPair); + private DigitalIdentityClient(KeyPair keyPair, DigitalIdentityService identityService) { + this.keyPair = keyPair; this.identityService = identityService; } public ShareSession createShareSession(ShareSessionRequest request) throws DigitalIdentityException { - return identityService.createShareSession(sdkId, keyPair, request); + return identityService.createShareSession(request); } public ShareSession fetchShareSession(String sessionId) throws DigitalIdentityException { - return identityService.fetchShareSession(sdkId, keyPair, sessionId); + return identityService.fetchShareSession(sessionId); } public ShareSessionQrCode createShareQrCode(String sessionId) throws DigitalIdentityException { - return identityService.createShareQrCode(sdkId, keyPair, sessionId); + return identityService.createShareQrCode(sessionId); } public ShareSessionQrCode fetchShareQrCode(String qrCodeId) throws DigitalIdentityException { - return identityService.fetchShareQrCode(sdkId, keyPair, qrCodeId); + return identityService.fetchShareQrCode(qrCodeId); } public Receipt fetchShareReceipt(String receiptId) throws DigitalIdentityException { - return identityService.fetchShareReceipt(sdkId, keyPair, receiptId); + return identityService.fetchShareReceipt(keyPair, receiptId); } public MatchResult fetchMatch(MatchRequest request) throws DigitalIdentityException { - return identityService.fetchMatch(sdkId, keyPair, request); - } - - private KeyPair loadKeyPair(KeyPairSource keyPairSource) throws InitialisationException { - try { - return keyPairSource.getFromStream(new KeyStreamVisitor()); - } catch (IOException ex) { - throw new InitialisationException("Cannot load Key Pair", ex); - } + return identityService.fetchMatch(request); } public static Builder builder() { @@ -94,7 +81,19 @@ public Builder withKeyPairSource(KeyPairSource keyPairSource) { } public DigitalIdentityClient build() { - return new DigitalIdentityClient(sdkId, keyPairSource, DigitalIdentityService.newInstance()); + Validation.notNullOrEmpty(sdkId, "SDK ID"); + Validation.notNull(keyPairSource, "Application Key Pair"); + + KeyPair keyPair = loadKeyPair(keyPairSource); + return new DigitalIdentityClient(keyPair, DigitalIdentityService.newInstance(keyPair, sdkId)); + } + + private KeyPair loadKeyPair(KeyPairSource keyPairSource) throws InitialisationException { + try { + return keyPairSource.getFromStream(new KeyStreamVisitor()); + } catch (IOException ex) { + throw new InitialisationException("Cannot load Key Pair", ex); + } } } diff --git a/yoti-sdk-api/src/main/java/com/yoti/api/client/YotiClient.java b/yoti-sdk-api/src/main/java/com/yoti/api/client/YotiClient.java index c4dfce3ae..7d627caab 100644 --- a/yoti-sdk-api/src/main/java/com/yoti/api/client/YotiClient.java +++ b/yoti-sdk-api/src/main/java/com/yoti/api/client/YotiClient.java @@ -46,13 +46,13 @@ public class YotiClient { private final DynamicSharingService dynamicSharingService; YotiClient(String applicationId, - KeyPairSource kpSource, + KeyPair keyPair, ReceiptFetcher receiptFetcher, - ActivityDetailsFactory activityDetailsFactory, RemoteAmlService remoteAmlService, + ActivityDetailsFactory activityDetailsFactory, DynamicSharingService dynamicSharingService) throws InitialisationException { this.appId = notNull(applicationId, "Application id"); - this.keyPair = loadKeyPair(notNull(kpSource, "Key pair source")); + this.keyPair = keyPair; this.receiptFetcher = notNull(receiptFetcher, "receiptFetcher"); this.remoteAmlService = notNull(remoteAmlService, "amlService"); this.activityDetailsFactory = notNull(activityDetailsFactory, "activityDetailsFactory"); @@ -80,7 +80,7 @@ public static YotiClient.Builder builder() { * @throws ProfileException aggregate exception signalling issues during the call */ public ActivityDetails getActivityDetails(String encryptedYotiToken) throws ProfileException { - Receipt receipt = receiptFetcher.fetch(encryptedYotiToken, keyPair, appId); + Receipt receipt = receiptFetcher.fetch(encryptedYotiToken, keyPair); return activityDetailsFactory.create(receipt, keyPair.getPrivate()); } @@ -96,7 +96,7 @@ public ActivityDetails getActivityDetails(String encryptedYotiToken) throws Prof */ public AmlResult performAmlCheck(AmlProfile amlProfile) throws AmlException { LOG.debug("Performing aml check..."); - return remoteAmlService.performCheck(keyPair, appId, amlProfile); + return remoteAmlService.performCheck(amlProfile); } /** @@ -113,15 +113,7 @@ public AmlResult performAmlCheck(AmlProfile amlProfile) throws AmlException { */ public ShareUrlResult createShareUrl(DynamicScenario dynamicScenario) throws DynamicShareException { LOG.debug("Request a share url for a dynamicScenario..."); - return dynamicSharingService.createShareUrl(appId, keyPair, dynamicScenario); - } - - private KeyPair loadKeyPair(KeyPairSource kpSource) throws InitialisationException { - try { - return kpSource.getFromStream(new KeyStreamVisitor()); - } catch (IOException e) { - throw new InitialisationException("Cannot load key pair", e); - } + return dynamicSharingService.createShareUrl(appId, dynamicScenario); } public static class Builder { @@ -144,14 +136,15 @@ public Builder withKeyPair(KeyPairSource keyPairSource) { public YotiClient build() { checkBuilderState(); + KeyPair keyPair = loadKeyPair(notNull(keyPairSource, "Key pair source")); return new YotiClient( sdkId, - keyPairSource, - ReceiptFetcher.newInstance(), + keyPair, + ReceiptFetcher.newInstance(keyPair, sdkId), + RemoteAmlService.newInstance(keyPair, sdkId), ActivityDetailsFactory.newInstance(), - RemoteAmlService.newInstance(), - DynamicSharingService.newInstance() + DynamicSharingService.newInstance(keyPair) ); } @@ -164,6 +157,14 @@ private void checkBuilderState() { } } + private KeyPair loadKeyPair(KeyPairSource kpSource) throws InitialisationException { + try { + return kpSource.getFromStream(new KeyStreamVisitor()); + } catch (IOException e) { + throw new InitialisationException("Cannot load key pair", e); + } + } + } } diff --git a/yoti-sdk-api/src/main/java/com/yoti/api/client/aml/AmlAddress.java b/yoti-sdk-api/src/main/java/com/yoti/api/client/aml/AmlAddress.java index 712f19e86..1e1ed6d00 100644 --- a/yoti-sdk-api/src/main/java/com/yoti/api/client/aml/AmlAddress.java +++ b/yoti-sdk-api/src/main/java/com/yoti/api/client/aml/AmlAddress.java @@ -10,7 +10,7 @@ public class AmlAddress { @JsonProperty("country") private final String country; - public AmlAddress(String postCode, String country) { + private AmlAddress(String postCode, String country) { this.postCode = postCode; this.country = country; } diff --git a/yoti-sdk-api/src/main/java/com/yoti/api/client/aml/AmlProfile.java b/yoti-sdk-api/src/main/java/com/yoti/api/client/aml/AmlProfile.java index 84342af2f..9cb4a0aab 100644 --- a/yoti-sdk-api/src/main/java/com/yoti/api/client/aml/AmlProfile.java +++ b/yoti-sdk-api/src/main/java/com/yoti/api/client/aml/AmlProfile.java @@ -16,7 +16,7 @@ public class AmlProfile { @JsonProperty("address") private final AmlAddress amlAddress; - AmlProfile(String givenNames, String familyName, String ssn, AmlAddress amlAddress) { + private AmlProfile(String givenNames, String familyName, String ssn, AmlAddress amlAddress) { this.givenNames = givenNames; this.familyName = familyName; this.ssn = ssn; diff --git a/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/DocScanClient.java b/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/DocScanClient.java index 4faf0d89e..c1deb1014 100644 --- a/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/DocScanClient.java +++ b/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/DocScanClient.java @@ -1,8 +1,5 @@ package com.yoti.api.client.docs; -import static com.yoti.api.client.spi.remote.util.Validation.notNull; -import static com.yoti.api.client.spi.remote.util.Validation.notNullOrEmpty; - import java.io.IOException; import java.security.KeyPair; import java.security.Security; @@ -24,6 +21,9 @@ import com.yoti.api.client.docs.session.retrieve.instructions.InstructionsResponse; import com.yoti.api.client.docs.support.SupportedDocumentsResponse; import com.yoti.api.client.spi.remote.KeyStreamVisitor; +import com.yoti.api.client.spi.remote.call.factory.AuthStrategy; +import com.yoti.api.client.spi.remote.call.factory.AuthTokenStrategy; +import com.yoti.api.client.spi.remote.call.factory.DocsSignedRequestStrategy; import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.slf4j.Logger; @@ -42,16 +42,11 @@ public class DocScanClient { Security.addProvider(new BouncyCastleProvider()); } - private final String sdkId; - private final KeyPair keyPair; - + private final AuthStrategy authStrategy; private final DocScanService docScanService; - DocScanClient(final String sdkId, - final KeyPairSource keyPairSource, - DocScanService docScanService) { - this.sdkId = sdkId; - this.keyPair = loadKeyPair(keyPairSource); + private DocScanClient(AuthStrategy authStrategy, DocScanService docScanService) { + this.authStrategy = authStrategy; this.docScanService = docScanService; } @@ -68,7 +63,7 @@ public static DocScanClient.Builder builder() { */ public CreateSessionResult createSession(SessionSpec sessionSpec) throws DocScanException { LOG.debug("Creating a YotiDocs session..."); - return docScanService.createSession(sdkId, keyPair, sessionSpec); + return docScanService.createSession(authStrategy, sessionSpec); } /** @@ -80,7 +75,7 @@ public CreateSessionResult createSession(SessionSpec sessionSpec) throws DocScan */ public GetSessionResult getSession(String sessionId) throws DocScanException { LOG.debug("Retrieving session '{}'", sessionId); - return docScanService.retrieveSession(sdkId, keyPair, sessionId); + return docScanService.retrieveSession(authStrategy, sessionId); } /** @@ -92,7 +87,7 @@ public GetSessionResult getSession(String sessionId) throws DocScanException { */ public void deleteSession(String sessionId) throws DocScanException { LOG.debug("Deleting session '{}'", sessionId); - docScanService.deleteSession(sdkId, keyPair, sessionId); + docScanService.deleteSession(authStrategy, sessionId); } /** @@ -106,7 +101,7 @@ public void deleteSession(String sessionId) throws DocScanException { */ public Media getMediaContent(String sessionId, String mediaId) throws DocScanException { LOG.debug("Retrieving media content '{}' in session '{}'", mediaId, sessionId); - return docScanService.getMediaContent(sdkId, keyPair, sessionId, mediaId); + return docScanService.getMediaContent(authStrategy, sessionId, mediaId); } /** @@ -119,7 +114,7 @@ public Media getMediaContent(String sessionId, String mediaId) throws DocScanExc */ public void deleteMediaContent(String sessionId, String mediaId) throws DocScanException { LOG.debug("Deleting media content '{}' in session '{}'", mediaId, sessionId); - docScanService.deleteMediaContent(sdkId, keyPair, sessionId, mediaId); + docScanService.deleteMediaContent(authStrategy, sessionId, mediaId); } /** @@ -131,7 +126,7 @@ public void deleteMediaContent(String sessionId, String mediaId) throws DocScanE */ public void putIbvInstructions(String sessionId, Instructions instructions) throws DocScanException { LOG.debug("Setting IBV instructions for session '{}'", sessionId); - docScanService.putIbvInstructions(sdkId, keyPair, sessionId, instructions); + docScanService.putIbvInstructions(authStrategy, sessionId, instructions); } /** @@ -143,7 +138,7 @@ public void putIbvInstructions(String sessionId, Instructions instructions) thro */ public Media getIbvInstructionsPdf(String sessionId) throws DocScanException { LOG.debug("Retrieving IBV instructions PDF in session '{}'", sessionId); - return docScanService.getIbvInstructionsPdf(sdkId, keyPair, sessionId); + return docScanService.getIbvInstructionsPdf(authStrategy, sessionId); } /** @@ -155,7 +150,7 @@ public Media getIbvInstructionsPdf(String sessionId) throws DocScanException { */ public ContactProfileResponse fetchInstructionsContactProfile(String sessionId) throws DocScanException { LOG.debug("Fetching instructions contact profile in session '{}'", sessionId); - return docScanService.fetchInstructionsContactProfile(sdkId, keyPair, sessionId); + return docScanService.fetchInstructionsContactProfile(authStrategy, sessionId); } /** @@ -169,7 +164,7 @@ public ContactProfileResponse fetchInstructionsContactProfile(String sessionId) */ public CreateFaceCaptureResourceResponse createFaceCaptureResource(String sessionId, CreateFaceCaptureResourcePayload createFaceCaptureResourcePayload) throws DocScanException { LOG.debug("Creating Face Capture resource in session '{}' for requirement '{}'", sessionId, createFaceCaptureResourcePayload.getRequirementId()); - return docScanService.createFaceCaptureResource(sdkId, keyPair, sessionId, createFaceCaptureResourcePayload); + return docScanService.createFaceCaptureResource(authStrategy, sessionId, createFaceCaptureResourcePayload); } /** @@ -181,7 +176,7 @@ public CreateFaceCaptureResourceResponse createFaceCaptureResource(String sessio */ public void uploadFaceCaptureImage(String sessionId, String resourceId, UploadFaceCaptureImagePayload uploadFaceCaptureImagePayload) throws DocScanException { LOG.debug("Uploading image to Face Capture resource '{}' for session '{}'", resourceId, sessionId); - docScanService.uploadFaceCaptureImage(sdkId, keyPair, sessionId, resourceId, uploadFaceCaptureImagePayload); + docScanService.uploadFaceCaptureImage(authStrategy, sessionId, resourceId, uploadFaceCaptureImagePayload); } /** @@ -193,7 +188,7 @@ public void uploadFaceCaptureImage(String sessionId, String resourceId, UploadFa */ public SupportedDocumentsResponse getSupportedDocuments(boolean includeNonLatin) throws DocScanException { LOG.debug("Getting all supported documents"); - return docScanService.getSupportedDocuments(keyPair, includeNonLatin); + return docScanService.getSupportedDocuments(includeNonLatin); } /** @@ -214,7 +209,7 @@ public SupportedDocumentsResponse getSupportedDocuments() throws DocScanExceptio */ public InstructionsResponse getIbvInstructions(String sessionId) throws DocScanException { LOG.debug("Fetching instructions for session '{}'", sessionId); - return docScanService.getIbvInstructions(sdkId, keyPair, sessionId); + return docScanService.getIbvInstructions(authStrategy, sessionId); } /** @@ -228,7 +223,7 @@ public InstructionsResponse getIbvInstructions(String sessionId) throws DocScanE */ public void triggerIbvEmailNotification(String sessionId) throws DocScanException { LOG.debug("Triggering IBV email notification for session '{}'", sessionId); - docScanService.triggerIbvEmailNotification(sdkId, keyPair, sessionId); + docScanService.triggerIbvEmailNotification(authStrategy, sessionId); } /** @@ -241,7 +236,7 @@ public void triggerIbvEmailNotification(String sessionId) throws DocScanExceptio */ public SessionConfigurationResponse getSessionConfiguration(String sessionId) throws DocScanException { LOG.debug("Fetching configuration for session '{}'", sessionId); - return docScanService.fetchSessionConfiguration(sdkId, keyPair, sessionId); + return docScanService.fetchSessionConfiguration(authStrategy, sessionId); } /** @@ -254,7 +249,7 @@ public SessionConfigurationResponse getSessionConfiguration(String sessionId) th */ public List getTrackedDevices(String sessionId) throws DocScanException { LOG.debug("Fetching tracked devices for session '{}'", sessionId); - return docScanService.getTrackedDevices(sdkId, keyPair, sessionId); + return docScanService.getTrackedDevices(authStrategy, sessionId); } /** @@ -266,25 +261,22 @@ public List getTrackedDevices(String sessionId) throws DocScan */ public void deleteTrackedDevices(String sessionId) throws DocScanException { LOG.debug("Deleting tracked devices for session '{}'", sessionId); - docScanService.deleteTrackedDevices(sdkId, keyPair, sessionId); - } - - private KeyPair loadKeyPair(KeyPairSource kpSource) throws InitialisationException { - try { - LOG.debug("Loading key pair from '{}'", kpSource); - return kpSource.getFromStream(new KeyStreamVisitor()); - } catch (IOException e) { - throw new InitialisationException("Cannot load key pair", e); - } + docScanService.deleteTrackedDevices(authStrategy, sessionId); } public static class Builder { private static final DocScanService docScanService = DocScanService.newInstance(); + private String authenticationToken; private String sdkId; private KeyPairSource keyPairSource; + public Builder withAuthenticationToken(String authenticationToken) { + this.authenticationToken = authenticationToken; + return this; + } + public Builder withClientSdkId(String sdkId) { this.sdkId = sdkId; return this; @@ -296,15 +288,37 @@ public Builder withKeyPairSource(KeyPairSource kps) { } public DocScanClient build() { - notNullOrEmpty(sdkId, "SDK ID"); - notNull(keyPairSource, "Application key Pair"); - - return new DocScanClient( - sdkId, - keyPairSource, - docScanService - ); + if (authenticationToken == null) { + validateForSignedRequest(); + KeyPair keyPair = loadKeyPair(keyPairSource); + return new DocScanClient(new DocsSignedRequestStrategy(keyPair, sdkId), docScanService); + } else { + validateAuthToken(); + return new DocScanClient(new AuthTokenStrategy(authenticationToken), docScanService); + } } + + private void validateForSignedRequest() { + if (sdkId == null || sdkId.isEmpty() || keyPairSource == null) { + throw new IllegalStateException("An sdkId and KeyPairSource must be provided when not using an authentication token"); + } + } + + private KeyPair loadKeyPair(KeyPairSource kpSource) throws InitialisationException { + try { + LOG.debug("Loading key pair from '{}'", kpSource); + return kpSource.getFromStream(new KeyStreamVisitor()); + } catch (IOException e) { + throw new InitialisationException("Cannot load key pair", e); + } + } + + private void validateAuthToken() { + if (sdkId != null || keyPairSource != null) { + throw new IllegalStateException("Must not supply sdkId or KeyPairSource when using an authentication token"); + } + } + } } diff --git a/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/DocScanConstants.java b/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/DocScanConstants.java index 9ae74306d..5db1774a8 100644 --- a/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/DocScanConstants.java +++ b/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/DocScanConstants.java @@ -36,6 +36,8 @@ private DocScanConstants() { } public static final String SUPPLEMENTARY_DOCUMENT_TEXT_DATA_CHECK = "SUPPLEMENTARY_DOCUMENT_TEXT_DATA_CHECK"; public static final String SUPPLEMENTARY_DOCUMENT_TEXT_DATA_EXTRACTION = "SUPPLEMENTARY_DOCUMENT_TEXT_DATA_EXTRACTION"; + public static final String VERIFY_SHARE_CODE_TASK = "VERIFY_SHARE_CODE_TASK"; + public static final String LIVENESS = "LIVENESS"; public static final String ZOOM = "ZOOM"; public static final String STATIC = "STATIC"; diff --git a/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/DocScanService.java b/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/DocScanService.java index e586b6b8c..3799b760f 100644 --- a/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/DocScanService.java +++ b/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/DocScanService.java @@ -14,7 +14,6 @@ import java.io.IOException; import java.net.URISyntaxException; import java.security.GeneralSecurityException; -import java.security.KeyPair; import java.util.List; import java.util.Locale; import java.util.Map; @@ -34,9 +33,11 @@ import com.yoti.api.client.docs.support.SupportedDocumentsResponse; import com.yoti.api.client.spi.remote.MediaValue; import com.yoti.api.client.spi.remote.call.ResourceException; -import com.yoti.api.client.spi.remote.call.SignedRequest; -import com.yoti.api.client.spi.remote.call.SignedRequestBuilderFactory; -import com.yoti.api.client.spi.remote.call.SignedRequestResponse; +import com.yoti.api.client.spi.remote.call.YotiHttpRequest; +import com.yoti.api.client.spi.remote.call.YotiHttpRequestBuilderFactory; +import com.yoti.api.client.spi.remote.call.YotiHttpResponse; +import com.yoti.api.client.spi.remote.call.factory.AuthStrategy; +import com.yoti.api.client.spi.remote.call.factory.NoAuthStrategy; import com.yoti.api.client.spi.remote.call.factory.UnsignedPathFactory; import com.fasterxml.jackson.annotation.JsonInclude; @@ -62,51 +63,49 @@ final class DocScanService { private final UnsignedPathFactory unsignedPathFactory; private final ObjectMapper objectMapper; - private final SignedRequestBuilderFactory signedRequestBuilderFactory; + private final YotiHttpRequestBuilderFactory yotiHttpRequestBuilderFactory; private final String apiUrl; private DocScanService(UnsignedPathFactory pathFactory, ObjectMapper objectMapper, - SignedRequestBuilderFactory signedRequestBuilderFactory) { + YotiHttpRequestBuilderFactory yotiHttpRequestBuilderFactory) { this.unsignedPathFactory = pathFactory; this.objectMapper = objectMapper; - this.signedRequestBuilderFactory = signedRequestBuilderFactory; + this.yotiHttpRequestBuilderFactory = yotiHttpRequestBuilderFactory; apiUrl = System.getProperty(PROPERTY_YOTI_DOCS_URL, DEFAULT_YOTI_DOCS_URL); } - public static DocScanService newInstance() { + static DocScanService newInstance() { ObjectMapper objectMapper = new ObjectMapper(); objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false); objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false); objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); objectMapper.registerModule(new JavaTimeModule()); - return new DocScanService(new UnsignedPathFactory(), objectMapper, new SignedRequestBuilderFactory()); + return new DocScanService(new UnsignedPathFactory(), objectMapper, new YotiHttpRequestBuilderFactory()); } /** * Uses the supplied session specification to create a session * - * @param sdkId the SDK ID - * @param keyPair the {@code KeyPair} - * @param sessionSpec the {@code SessionSpec} + * @param authStrategy the {@code AuthStrategy} + * @param sessionSpec the {@code SessionSpec} * @return the session creation result * @throws DocScanException if there was an error */ - public CreateSessionResult createSession(String sdkId, KeyPair keyPair, SessionSpec sessionSpec) throws DocScanException { - notNullOrEmpty(sdkId, "SDK ID"); - notNull(keyPair, "Application key Pair"); + CreateSessionResult createSession(AuthStrategy authStrategy, SessionSpec sessionSpec) throws DocScanException { + notNull(authStrategy, "authStrategy"); notNull(sessionSpec, "sessionSpec"); - String path = unsignedPathFactory.createNewYotiDocsSessionPath(sdkId); + String path = unsignedPathFactory.createNewYotiDocsSessionPath(); LOG.info("Creating session at '{}'", path); try { byte[] payload = objectMapper.writeValueAsBytes(sessionSpec); - SignedRequest signedRequest = signedRequestBuilderFactory.create() - .withKeyPair(keyPair) + YotiHttpRequest yotiHttpRequest = yotiHttpRequestBuilderFactory.create() + .withAuthStrategy(authStrategy) .withBaseUrl(apiUrl) .withEndpoint(path) .withHttpMethod(HTTP_POST) @@ -114,7 +113,7 @@ public CreateSessionResult createSession(String sdkId, KeyPair keyPair, SessionS .withHeader(CONTENT_TYPE, CONTENT_TYPE_JSON) .build(); - return signedRequest.execute(CreateSessionResult.class); + return yotiHttpRequest.execute(CreateSessionResult.class); } catch (GeneralSecurityException ex) { throw new DocScanException("Error signing the request: " + ex.getMessage(), ex); } catch (ResourceException ex) { @@ -129,29 +128,27 @@ public CreateSessionResult createSession(String sdkId, KeyPair keyPair, SessionS /** * Retrieves the current state of a given session * - * @param sdkId the SDK ID - * @param keyPair the {@code KeyPair} - * @param sessionId the session ID + * @param authStrategy the {@code AuthStrategy} + * @param sessionId the session ID * @return the session state * @throws DocScanException if there was an error */ - public GetSessionResult retrieveSession(String sdkId, KeyPair keyPair, String sessionId) throws DocScanException { - notNullOrEmpty(sdkId, "SDK ID"); - notNull(keyPair, "Application key Pair"); + GetSessionResult retrieveSession(AuthStrategy authStrategy, String sessionId) throws DocScanException { + notNull(authStrategy, "authStrategy"); notNullOrEmpty(sessionId, "sessionId"); - String path = unsignedPathFactory.createYotiDocsSessionPath(sdkId, sessionId); + String path = unsignedPathFactory.createYotiDocsSessionPath(sessionId); LOG.info("Fetching session from '{}'", path); try { - SignedRequest signedRequest = signedRequestBuilderFactory.create() - .withKeyPair(keyPair) + YotiHttpRequest yotiHttpRequest = yotiHttpRequestBuilderFactory.create() + .withAuthStrategy(authStrategy) .withBaseUrl(apiUrl) .withEndpoint(path) .withHttpMethod(HTTP_GET) .build(); - return signedRequest.execute(GetSessionResult.class); + return yotiHttpRequest.execute(GetSessionResult.class); } catch (GeneralSecurityException ex) { throw new DocScanException("Error signing the request: " + ex.getMessage(), ex); } catch (ResourceException ex) { @@ -166,28 +163,26 @@ public GetSessionResult retrieveSession(String sdkId, KeyPair keyPair, String se /** * Deletes a session and all of its associated content * - * @param sdkId the SDK ID - * @param keyPair the {@code KeyPair} - * @param sessionId the session ID + * @param authStrategy the {@code AuthStrategy} + * @param sessionId the session ID * @throws DocScanException if there was an error */ - public void deleteSession(String sdkId, KeyPair keyPair, String sessionId) throws DocScanException { - notNullOrEmpty(sdkId, "SDK ID"); - notNull(keyPair, "Application key Pair"); + void deleteSession(AuthStrategy authStrategy, String sessionId) throws DocScanException { + notNull(authStrategy, "authStrategy"); notNullOrEmpty(sessionId, "sessionId"); - String path = unsignedPathFactory.createYotiDocsSessionPath(sdkId, sessionId); + String path = unsignedPathFactory.createYotiDocsSessionPath(sessionId); LOG.info("Deleting session from '{}'", path); try { - SignedRequest signedRequest = signedRequestBuilderFactory.create() - .withKeyPair(keyPair) + YotiHttpRequest yotiHttpRequest = yotiHttpRequestBuilderFactory.create() + .withAuthStrategy(authStrategy) .withBaseUrl(apiUrl) .withEndpoint(path) .withHttpMethod(HTTP_DELETE) .build(); - signedRequest.execute(); + yotiHttpRequest.execute(); } catch (GeneralSecurityException ex) { throw new DocScanException("Error signing the request: " + ex.getMessage(), ex); } catch (ResourceException ex) { @@ -202,30 +197,28 @@ public void deleteSession(String sdkId, KeyPair keyPair, String sessionId) throw /** * Retrieves {@link Media} content for a given session and media ID * - * @param sdkId the SDK ID - * @param keyPair the {@code KeyPair} - * @param sessionId the session ID - * @param mediaId the media ID + * @param authStrategy the {@code AuthStrategy} + * @param sessionId the session ID + * @param mediaId the media ID * @return the {@code Media} content, null if 204 No Content * @throws DocScanException if there was an error */ - public Media getMediaContent(String sdkId, KeyPair keyPair, String sessionId, String mediaId) throws DocScanException { - notNullOrEmpty(sdkId, "SDK ID"); - notNull(keyPair, "Application key Pair"); + Media getMediaContent(AuthStrategy authStrategy, String sessionId, String mediaId) throws DocScanException { + notNull(authStrategy, "authStrategy"); notNullOrEmpty(sessionId, "sessionId"); notNullOrEmpty(mediaId, "mediaId"); - String path = unsignedPathFactory.createMediaContentPath(sdkId, sessionId, mediaId); + String path = unsignedPathFactory.createMediaContentPath(sessionId, mediaId); LOG.info("Fetching media from '{}'", path); try { - SignedRequest signedRequest = signedRequestBuilderFactory.create() - .withKeyPair(keyPair) + YotiHttpRequest yotiHttpRequest = yotiHttpRequestBuilderFactory.create() + .withAuthStrategy(authStrategy) .withBaseUrl(apiUrl) .withEndpoint(path) .withHttpMethod(HTTP_GET) .build(); - SignedRequestResponse response = signedRequest.execute(); + YotiHttpResponse response = yotiHttpRequest.execute(); if (response.getResponseCode() == HTTP_STATUS_NO_CONTENT) { return null; @@ -243,30 +236,28 @@ public Media getMediaContent(String sdkId, KeyPair keyPair, String sessionId, St /** * Deletes media content for a given session and media ID * - * @param sdkId the SDK ID - * @param keyPair the {@code KeyPair} - * @param sessionId the session ID - * @param mediaId the media ID + * @param authStrategy the {@code AuthStrategy} + * @param sessionId the session ID + * @param mediaId the media ID * @throws DocScanException if there was an error */ - public void deleteMediaContent(String sdkId, KeyPair keyPair, String sessionId, String mediaId) throws DocScanException { - notNullOrEmpty(sdkId, "SDK ID"); - notNull(keyPair, "Application key Pair"); + void deleteMediaContent(AuthStrategy authStrategy, String sessionId, String mediaId) throws DocScanException { + notNull(authStrategy, "authStrategy"); notNullOrEmpty(sessionId, "sessionId"); notNullOrEmpty(mediaId, "mediaId"); - String path = unsignedPathFactory.createMediaContentPath(sdkId, sessionId, mediaId); + String path = unsignedPathFactory.createMediaContentPath(sessionId, mediaId); LOG.info("Deleting media at '{}'", path); try { - SignedRequest signedRequest = signedRequestBuilderFactory.create() - .withKeyPair(keyPair) + YotiHttpRequest yotiHttpRequest = yotiHttpRequestBuilderFactory.create() + .withAuthStrategy(authStrategy) .withBaseUrl(apiUrl) .withEndpoint(path) .withHttpMethod(HTTP_DELETE) .build(); - signedRequest.execute(); + yotiHttpRequest.execute(); } catch (GeneralSecurityException ex) { throw new DocScanException("Error signing the request: " + ex.getMessage(), ex); } catch (ResourceException ex) { @@ -276,27 +267,26 @@ public void deleteMediaContent(String sdkId, KeyPair keyPair, String sessionId, } } - public void putIbvInstructions(String sdkId, KeyPair keyPair, String sessionId, Instructions instructions) throws DocScanException { - notNullOrEmpty(sdkId, "SDK ID"); - notNull(keyPair, "Application key Pair"); + void putIbvInstructions(AuthStrategy authStrategy, String sessionId, Instructions instructions) throws DocScanException { + notNull(authStrategy, "authStrategy"); notNullOrEmpty(sessionId, "sessionId"); notNull(instructions, "instructions"); - String path = unsignedPathFactory.createPutIbvInstructionsPath(sdkId, sessionId); + String path = unsignedPathFactory.createPutIbvInstructionsPath(sessionId); LOG.info("Setting IBV instructions at '{}'", path); try { byte[] payload = objectMapper.writeValueAsBytes(instructions); - SignedRequest signedRequest = signedRequestBuilderFactory.create() - .withKeyPair(keyPair) + YotiHttpRequest yotiHttpRequest = yotiHttpRequestBuilderFactory.create() + .withAuthStrategy(authStrategy) .withBaseUrl(apiUrl) .withEndpoint(path) .withHttpMethod(HTTP_PUT) .withPayload(payload) .build(); - signedRequest.execute(); + yotiHttpRequest.execute(); } catch (GeneralSecurityException ex) { throw new DocScanException("Error signing the request: " + ex.getMessage(), ex); } catch (ResourceException ex) { @@ -306,23 +296,22 @@ public void putIbvInstructions(String sdkId, KeyPair keyPair, String sessionId, } } - public InstructionsResponse getIbvInstructions(String sdkId, KeyPair keyPair, String sessionId) throws DocScanException { - notNullOrEmpty(sdkId, "SDK ID"); - notNull(keyPair, "Application key Pair"); + InstructionsResponse getIbvInstructions(AuthStrategy authStrategy, String sessionId) throws DocScanException { + notNull(authStrategy, "authStrategy"); notNullOrEmpty(sessionId, "sessionId"); - String path = unsignedPathFactory.createFetchIbvInstructionsPath(sdkId, sessionId); + String path = unsignedPathFactory.createFetchIbvInstructionsPath(sessionId); LOG.info("Fetching IBV instructions at '{}'", path); try { - SignedRequest signedRequest = signedRequestBuilderFactory.create() - .withKeyPair(keyPair) + YotiHttpRequest yotiHttpRequest = yotiHttpRequestBuilderFactory.create() + .withAuthStrategy(authStrategy) .withBaseUrl(apiUrl) .withEndpoint(path) .withHttpMethod(HTTP_GET) .build(); - return signedRequest.execute(InstructionsResponse.class); + return yotiHttpRequest.execute(InstructionsResponse.class); } catch (GeneralSecurityException ex) { throw new DocScanException("Error signing the request: " + ex.getMessage(), ex); } catch (ResourceException ex) { @@ -335,29 +324,27 @@ public InstructionsResponse getIbvInstructions(String sdkId, KeyPair keyPair, St /** * Retrieves the current state of a given session * - * @param sdkId the SDK ID - * @param keyPair the {@code KeyPair} - * @param sessionId the session ID + * @param authStrategy the {@code AuthStrategy} + * @param sessionId the session ID * @return the session state * @throws DocScanException if there was an error */ - public ContactProfileResponse fetchInstructionsContactProfile(String sdkId, KeyPair keyPair, String sessionId) throws DocScanException { - notNullOrEmpty(sdkId, "SDK ID"); - notNull(keyPair, "Application key Pair"); + ContactProfileResponse fetchInstructionsContactProfile(AuthStrategy authStrategy, String sessionId) throws DocScanException { + notNull(authStrategy, "authStrategy"); notNullOrEmpty(sessionId, "sessionId"); - String path = unsignedPathFactory.createFetchInstructionsContactProfilePath(sdkId, sessionId); + String path = unsignedPathFactory.createFetchInstructionsContactProfilePath(sessionId); LOG.info("Fetching instruction contact profile from '{}'", path); try { - SignedRequest signedRequest = signedRequestBuilderFactory.create() - .withKeyPair(keyPair) + YotiHttpRequest yotiHttpRequest = yotiHttpRequestBuilderFactory.create() + .withAuthStrategy(authStrategy) .withBaseUrl(apiUrl) .withEndpoint(path) .withHttpMethod(HTTP_GET) .build(); - return signedRequest.execute(ContactProfileResponse.class); + return yotiHttpRequest.execute(ContactProfileResponse.class); } catch (GeneralSecurityException ex) { throw new DocScanException("Error signing the request: " + ex.getMessage(), ex); } catch (ResourceException ex) { @@ -367,22 +354,21 @@ public ContactProfileResponse fetchInstructionsContactProfile(String sdkId, KeyP } } - public Media getIbvInstructionsPdf(String sdkId, KeyPair keyPair, String sessionId) throws DocScanException { - notNullOrEmpty(sdkId, "SDK ID"); - notNull(keyPair, "Application key Pair"); + Media getIbvInstructionsPdf(AuthStrategy authStrategy, String sessionId) throws DocScanException { + notNull(authStrategy, "authStrategy"); notNullOrEmpty(sessionId, "sessionId"); - String path = unsignedPathFactory.createFetchIbvInstructionsPdfPath(sdkId, sessionId); + String path = unsignedPathFactory.createFetchIbvInstructionsPdfPath(sessionId); LOG.info("Fetching instructions PDF at '{}'", path); try { - SignedRequest signedRequest = signedRequestBuilderFactory.create() - .withKeyPair(keyPair) + YotiHttpRequest yotiHttpRequest = yotiHttpRequestBuilderFactory.create() + .withAuthStrategy(authStrategy) .withBaseUrl(apiUrl) .withEndpoint(path) .withHttpMethod(HTTP_GET) .build(); - SignedRequestResponse response = signedRequest.execute(); + YotiHttpResponse response = yotiHttpRequest.execute(); if (response.getResponseCode() == HTTP_STATUS_NO_CONTENT) { return null; @@ -397,23 +383,22 @@ public Media getIbvInstructionsPdf(String sdkId, KeyPair keyPair, String session } } - public SessionConfigurationResponse fetchSessionConfiguration(String sdkId, KeyPair keyPair, String sessionId) throws DocScanException { - notNullOrEmpty(sdkId, "SDK ID"); - notNull(keyPair, "Application key Pair"); + SessionConfigurationResponse fetchSessionConfiguration(AuthStrategy authStrategy, String sessionId) throws DocScanException { + notNull(authStrategy, "authStrategy"); notNullOrEmpty(sessionId, "sessionId"); - String path = unsignedPathFactory.createFetchSessionConfigurationPath(sdkId, sessionId); + String path = unsignedPathFactory.createFetchSessionConfigurationPath(sessionId); LOG.info("Fetching session configuration from '{}'", path); try { - SignedRequest signedRequest = signedRequestBuilderFactory.create() - .withKeyPair(keyPair) + YotiHttpRequest yotiHttpRequest = yotiHttpRequestBuilderFactory.create() + .withAuthStrategy(authStrategy) .withBaseUrl(apiUrl) .withEndpoint(path) .withHttpMethod(HTTP_GET) .build(); - return signedRequest.execute(SessionConfigurationResponse.class); + return yotiHttpRequest.execute(SessionConfigurationResponse.class); } catch (GeneralSecurityException ex) { throw new DocScanException("Error signing the request: " + ex.getMessage(), ex); } catch (ResourceException ex) { @@ -423,30 +408,28 @@ public SessionConfigurationResponse fetchSessionConfiguration(String sdkId, KeyP } } - public CreateFaceCaptureResourceResponse createFaceCaptureResource(String sdkId, - KeyPair keyPair, + CreateFaceCaptureResourceResponse createFaceCaptureResource(AuthStrategy authStrategy, String sessionId, CreateFaceCaptureResourcePayload createFaceCaptureResourcePayload) throws DocScanException { - notNullOrEmpty(sdkId, "SDK ID"); - notNull(keyPair, "Application key Pair"); + notNull(authStrategy, "authStrategy"); notNullOrEmpty(sessionId, "sessionId"); notNull(createFaceCaptureResourcePayload, "createFaceCaptureResourcePayload"); - String path = unsignedPathFactory.createNewFaceCaptureResourcePath(sdkId, sessionId); + String path = unsignedPathFactory.createNewFaceCaptureResourcePath(sessionId); LOG.info("Creating new Face Capture resource at '{}'", path); try { byte[] payload = objectMapper.writeValueAsBytes(createFaceCaptureResourcePayload); - SignedRequest signedRequest = signedRequestBuilderFactory.create() - .withKeyPair(keyPair) + YotiHttpRequest yotiHttpRequest = yotiHttpRequestBuilderFactory.create() + .withAuthStrategy(authStrategy) .withBaseUrl(apiUrl) .withEndpoint(path) .withPayload(payload) .withHttpMethod(HTTP_POST) .build(); - return signedRequest.execute(CreateFaceCaptureResourceResponse.class); + return yotiHttpRequest.execute(CreateFaceCaptureResourceResponse.class); } catch (GeneralSecurityException ex) { throw new DocScanException("Error signing the request: " + ex.getMessage(), ex); } catch (ResourceException ex) { @@ -456,26 +439,25 @@ public CreateFaceCaptureResourceResponse createFaceCaptureResource(String sdkId, } } - public void uploadFaceCaptureImage(String sdkId, KeyPair keyPair, String sessionId, String resourceId, UploadFaceCaptureImagePayload faceCaptureImagePayload) + void uploadFaceCaptureImage(AuthStrategy authStrategy, String sessionId, String resourceId, UploadFaceCaptureImagePayload faceCaptureImagePayload) throws DocScanException { - notNullOrEmpty(sdkId, "SDK ID"); - notNull(keyPair, "Application key Pair"); + notNull(authStrategy, "authStrategy"); notNullOrEmpty(sessionId, "sessionId"); notNullOrEmpty(resourceId, "resourceId"); notNull(faceCaptureImagePayload, "faceCaptureImagePayload"); - String path = unsignedPathFactory.createUploadFaceCaptureImagePath(sdkId, sessionId, resourceId); + String path = unsignedPathFactory.createUploadFaceCaptureImagePath(sessionId, resourceId); LOG.info("Uploading image to Face Capture resource at '{}'", path); try { - signedRequestBuilderFactory.create() + yotiHttpRequestBuilderFactory.create() .withMultipartBoundary(YOTI_MULTIPART_BOUNDARY) .withMultipartBinaryBody( "binary-content", faceCaptureImagePayload.getImageContents(), ContentType.parse(faceCaptureImagePayload.getImageContentType()), "face-capture-image") - .withKeyPair(keyPair) + .withAuthStrategy(authStrategy) .withBaseUrl(apiUrl) .withEndpoint(path) .withHttpMethod(HTTP_PUT) @@ -488,20 +470,17 @@ public void uploadFaceCaptureImage(String sdkId, KeyPair keyPair, String session } } - public SupportedDocumentsResponse getSupportedDocuments(KeyPair keyPair, boolean includeNonLatin) throws DocScanException { - notNull(keyPair, "Application key Pair"); - + SupportedDocumentsResponse getSupportedDocuments(boolean includeNonLatin) throws DocScanException { String path = unsignedPathFactory.createGetSupportedDocumentsPath(includeNonLatin); try { - SignedRequest signedRequest = signedRequestBuilderFactory.create() - .withKeyPair(keyPair) + YotiHttpRequest yotiHttpRequest = yotiHttpRequestBuilderFactory.create() + .withAuthStrategy(new NoAuthStrategy()) .withBaseUrl(apiUrl) .withEndpoint(path) .withHttpMethod(HTTP_GET) .build(); - - return signedRequest.execute(SupportedDocumentsResponse.class); + return yotiHttpRequest.execute(SupportedDocumentsResponse.class); } catch (GeneralSecurityException | ResourceException ex) { throw new DocScanException("Error executing the GET: " + ex.getMessage(), ex); } catch (IOException | URISyntaxException ex) { @@ -509,17 +488,16 @@ public SupportedDocumentsResponse getSupportedDocuments(KeyPair keyPair, boolean } } - public void triggerIbvEmailNotification(String sdkId, KeyPair keyPair, String sessionId) throws DocScanException { - notNullOrEmpty(sdkId, "SDK ID"); - notNull(keyPair, "Application key Pair"); + void triggerIbvEmailNotification(AuthStrategy authStrategy, String sessionId) throws DocScanException { + notNull(authStrategy, "authStrategy"); notNullOrEmpty(sessionId, "sessionId"); - String path = unsignedPathFactory.createTriggerIbvEmailNotificationPath(sdkId, sessionId); + String path = unsignedPathFactory.createTriggerIbvEmailNotificationPath(sessionId); LOG.info("Triggering IBV email notification at '{}'", path); try { - signedRequestBuilderFactory.create() - .withKeyPair(keyPair) + yotiHttpRequestBuilderFactory.create() + .withAuthStrategy(authStrategy) .withBaseUrl(apiUrl) .withEndpoint(path) .withHttpMethod(HTTP_POST) @@ -532,23 +510,22 @@ public void triggerIbvEmailNotification(String sdkId, KeyPair keyPair, String se } } - public List getTrackedDevices(String sdkId, KeyPair keyPair, String sessionId) throws DocScanException { - notNullOrEmpty(sdkId, "SDK ID"); - notNull(keyPair, "Application key Pair"); + List getTrackedDevices(AuthStrategy authStrategy, String sessionId) throws DocScanException { + notNull(authStrategy, "authStrategy"); notNullOrEmpty(sessionId, "sessionId"); - String path = unsignedPathFactory.createFetchTrackedDevices(sdkId, sessionId); + String path = unsignedPathFactory.createFetchTrackedDevices(sessionId); LOG.info("Fetching tracked devices at '{}'", path); try { - SignedRequest signedRequest = signedRequestBuilderFactory.create() - .withKeyPair(keyPair) + YotiHttpRequest yotiHttpRequest = yotiHttpRequestBuilderFactory.create() + .withAuthStrategy(authStrategy) .withBaseUrl(apiUrl) .withEndpoint(path) .withHttpMethod(HTTP_GET) .build(); - return signedRequest.execute(METADATA_RESPONSE_TYPE_REF); + return yotiHttpRequest.execute(METADATA_RESPONSE_TYPE_REF); } catch (GeneralSecurityException | ResourceException ex) { throw new DocScanException("Error executing the GET: " + ex.getMessage(), ex); } catch (IOException | URISyntaxException ex) { @@ -556,17 +533,16 @@ public List getTrackedDevices(String sdkId, KeyPair keyPair, S } } - public void deleteTrackedDevices(String sdkId, KeyPair keyPair, String sessionId) throws DocScanException { - notNullOrEmpty(sdkId, "SDK ID"); - notNull(keyPair, "Application key Pair"); + void deleteTrackedDevices(AuthStrategy authStrategy, String sessionId) throws DocScanException { + notNull(authStrategy, "authStrategy"); notNullOrEmpty(sessionId, "sessionId"); - String path = unsignedPathFactory.createDeleteTrackedDevices(sdkId, sessionId); + String path = unsignedPathFactory.createDeleteTrackedDevices(sessionId); LOG.info("Deleting tracked devices at '{}'", path); try { - signedRequestBuilderFactory.create() - .withKeyPair(keyPair) + yotiHttpRequestBuilderFactory.create() + .withAuthStrategy(authStrategy) .withBaseUrl(apiUrl) .withEndpoint(path) .withHttpMethod(HTTP_DELETE) @@ -579,7 +555,7 @@ public void deleteTrackedDevices(String sdkId, KeyPair keyPair, String sessionId } } - private String findContentType(SignedRequestResponse response) { + private String findContentType(YotiHttpResponse response) { List contentTypeValues = null; for (Map.Entry> entry : response.getResponseHeaders().entrySet()) { if (entry.getKey() != null && entry.getKey().toLowerCase(Locale.ENGLISH).equals(CONTENT_TYPE.toLowerCase(Locale.ENGLISH))) { @@ -590,5 +566,4 @@ private String findContentType(SignedRequestResponse response) { return contentTypeValues == null || contentTypeValues.isEmpty() ? "" : contentTypeValues.get(0); } - } diff --git a/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/create/IbvOptions.java b/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/create/IbvOptions.java index 669697fda..3551278ec 100644 --- a/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/create/IbvOptions.java +++ b/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/create/IbvOptions.java @@ -6,13 +6,13 @@ public class IbvOptions { - @JsonProperty(Property.SUPPORT) + @JsonProperty("support") private final String support; - @JsonProperty(Property.GUIDANCE_URL) + @JsonProperty("guidance_url") private final String guidanceUrl; - @JsonProperty(Property.USER_PRICE) + @JsonProperty("user_price") private final UserPrice userPrice; private IbvOptions(String support, String guidanceUrl, UserPrice userPrice) { @@ -102,14 +102,4 @@ public IbvOptions build() { } - private static final class Property { - - private static final String SUPPORT = "support"; - private static final String GUIDANCE_URL = "guidance_url"; - private static final String USER_PRICE = "user_price"; - - private Property() { } - - } - } diff --git a/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/create/ImportTokenPayload.java b/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/create/ImportTokenPayload.java index 8bc94b341..c34058b6e 100644 --- a/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/create/ImportTokenPayload.java +++ b/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/create/ImportTokenPayload.java @@ -7,7 +7,7 @@ public class ImportTokenPayload { @JsonProperty("ttl") private Integer ttl; - ImportTokenPayload(Integer ttl) { + private ImportTokenPayload(Integer ttl) { this.ttl = ttl; } diff --git a/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/create/NotificationConfig.java b/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/create/NotificationConfig.java index 51871ea46..2a5161fb4 100644 --- a/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/create/NotificationConfig.java +++ b/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/create/NotificationConfig.java @@ -26,7 +26,7 @@ public class NotificationConfig { @JsonProperty("topics") private final List topics; - NotificationConfig(String authToken, String authType, String endpoint, List topics) { + private NotificationConfig(String authToken, String authType, String endpoint, List topics) { this.authToken = authToken; this.authType = authType; this.endpoint = endpoint; diff --git a/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/create/SdkConfig.java b/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/create/SdkConfig.java index 56253bbec..4cd26deca 100644 --- a/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/create/SdkConfig.java +++ b/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/create/SdkConfig.java @@ -12,55 +12,55 @@ */ public class SdkConfig { - @JsonProperty(Property.ALLOWED_CAPTURE_METHODS) + @JsonProperty("allowed_capture_methods") private final String allowedCaptureMethods; - @JsonProperty(Property.PRIMARY_COLOUR) + @JsonProperty("primary_colour") private final String primaryColour; - @JsonProperty(Property.PRIMARY_COLOUR_DARK_MODE) + @JsonProperty("primary_colour_dark_mode") private final String primaryColourDarkMode; - @JsonProperty(Property.SECONDARY_COLOUR) + @JsonProperty("secondary_colour") private final String secondaryColour; - @JsonProperty(Property.FONT_COLOUR) + @JsonProperty("font_colour") private final String fontColour; - @JsonProperty(Property.DARK_MODE) + @JsonProperty("dark_mode") private final String darkMode; - @JsonProperty(Property.LOCALE) + @JsonProperty("locale") private final String locale; - @JsonProperty(Property.PRESET_ISSUING_COUNTRY) + @JsonProperty("preset_issuing_country") private final String presetIssuingCountry; - @JsonProperty(Property.SUCCESS_URL) + @JsonProperty("success_url") private final String successUrl; - @JsonProperty(Property.ERROR_URL) + @JsonProperty("error_url") private final String errorUrl; - @JsonProperty(Property.PRIVACY_POLICY_URL) + @JsonProperty("privacy_policy_url") private final String privacyPolicyUrl; - @JsonProperty(Property.ALLOW_HANDOFF) + @JsonProperty("allow_handoff") private final Boolean allowHandoff; - @JsonProperty(Property.ATTEMPTS_CONFIGURATION) + @JsonProperty("attempts_configuration") private final AttemptsConfiguration attemptsConfiguration; - @JsonProperty(Property.BRAND_ID) + @JsonProperty("brand_id") private final String brandId; - @JsonProperty(Property.BIOMETRIC_CONSENT_FLOW) + @JsonProperty("biometric_consent_flow") private final String biometricConsentFlow; - @JsonProperty(Property.SUPPRESSED_SCREENS) + @JsonProperty("suppressed_screens") private final List suppressedScreens; - SdkConfig(String allowedCaptureMethods, + private SdkConfig(String allowedCaptureMethods, String primaryColour, String primaryColourDarkMode, String secondaryColour, @@ -536,27 +536,4 @@ public SdkConfig build() { } } - private static final class Property { - - private static final String ALLOWED_CAPTURE_METHODS = "allowed_capture_methods"; - private static final String PRIMARY_COLOUR = "primary_colour"; - private static final String PRIMARY_COLOUR_DARK_MODE = "primary_colour_dark_mode"; - private static final String SECONDARY_COLOUR = "secondary_colour"; - private static final String FONT_COLOUR = "font_colour"; - private static final String DARK_MODE = "dark_mode"; - private static final String LOCALE = "locale"; - private static final String PRESET_ISSUING_COUNTRY = "preset_issuing_country"; - private static final String SUCCESS_URL = "success_url"; - private static final String ERROR_URL = "error_url"; - private static final String PRIVACY_POLICY_URL = "privacy_policy_url"; - private static final String ALLOW_HANDOFF = "allow_handoff"; - private static final String ATTEMPTS_CONFIGURATION = "attempts_configuration"; - private static final String BRAND_ID = "brand_id"; - private static final String BIOMETRIC_CONSENT_FLOW = "biometric_consent_flow"; - private static final String SUPPRESSED_SCREENS = "suppressed_screens"; - - private Property() {} - - } - } diff --git a/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/create/SessionSpec.java b/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/create/SessionSpec.java index b7a0a763a..960cbd920 100644 --- a/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/create/SessionSpec.java +++ b/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/create/SessionSpec.java @@ -3,11 +3,11 @@ import java.time.ZonedDateTime; import java.util.ArrayList; import java.util.List; -import java.util.Map; import com.yoti.api.client.docs.session.create.check.RequestedCheck; import com.yoti.api.client.docs.session.create.filters.RequiredDocument; import com.yoti.api.client.docs.session.create.identityprofile.advanced.AdvancedIdentityProfileRequirementsPayload; +import com.yoti.api.client.docs.session.create.identityprofile.simple.IdentityProfileRequirementsPayload; import com.yoti.api.client.docs.session.create.resources.ResourceCreationContainer; import com.yoti.api.client.docs.session.create.task.RequestedTask; @@ -18,58 +18,58 @@ */ public class SessionSpec { - @JsonProperty(Property.CLIENT_SESSION_TOKEN_TTL) + @JsonProperty("client_session_token_ttl") private final Integer clientSessionTokenTtl; - @JsonProperty(Property.SESSION_DEADLINE) + @JsonProperty("session_deadline") private final ZonedDateTime sessionDeadline; - @JsonProperty(Property.RESOURCES_TTL) + @JsonProperty("resources_ttl") private final Integer resourcesTtl; - @JsonProperty(Property.IMPORT_TOKEN) + @JsonProperty("import_token") private final ImportTokenPayload importToken; - @JsonProperty(Property.USER_TRACKING_ID) + @JsonProperty("user_tracking_id") private final String userTrackingId; - @JsonProperty(Property.NOTIFICATIONS) + @JsonProperty("notifications") private final NotificationConfig notifications; - @JsonProperty(Property.REQUESTED_CHECKS) + @JsonProperty("requested_checks") private final List> requestedChecks; - @JsonProperty(Property.REQUESTED_TASKS) + @JsonProperty("requested_tasks") private final List> requestedTasks; - @JsonProperty(Property.SDK_CONFIG) + @JsonProperty("sdk_config") private final SdkConfig sdkConfig; - @JsonProperty(Property.REQUIRED_DOCUMENTS) + @JsonProperty("required_documents") private final List requiredDocuments; - @JsonProperty(Property.BLOCK_BIOMETRIC_CONSENT) + @JsonProperty("block_biometric_consent") private final Boolean blockBiometricConsent; - @JsonProperty(Property.IBV_OPTIONS) + @JsonProperty("ibv_options") private final IbvOptions ibvOptions; - @JsonProperty(Property.IDENTITY_PROFILE_REQUIREMENTS) - private final Map identityProfile; + @JsonProperty("identity_profile_requirements") + private final IdentityProfileRequirementsPayload identityProfile; - @JsonProperty(Property.ADVANCED_IDENTITY_PROFILE_REQUIREMENTS) + @JsonProperty("advanced_identity_profile_requirements") private final AdvancedIdentityProfileRequirementsPayload advancedIdentityProfileRequirements; - @JsonProperty(Property.SUBJECT) - private final Map subject; + @JsonProperty("subject") + private final SubjectPayload subject; - @JsonProperty(Property.RESOURCES) + @JsonProperty("resources") private final ResourceCreationContainer resources; - @JsonProperty(Property.CREATE_IDENTITY_PROFILE_PREVIEW) + @JsonProperty("create_identity_profile_preview") private final Boolean createIdentityProfilePreview; - SessionSpec(Integer clientSessionTokenTtl, + private SessionSpec(Integer clientSessionTokenTtl, Integer resourcesTtl, ImportTokenPayload importToken, String userTrackingId, @@ -81,8 +81,8 @@ public class SessionSpec { Boolean blockBiometricConsent, IbvOptions ibvOptions, ZonedDateTime sessionDeadline, - Map identityProfile, - Map subject, + IdentityProfileRequirementsPayload identityProfile, + SubjectPayload subject, ResourceCreationContainer resources, Boolean createIdentityProfilePreview, AdvancedIdentityProfileRequirementsPayload advancedIdentityProfileRequirements) { @@ -223,7 +223,7 @@ public ZonedDateTime getSessionDeadline() { * * @return Identity Profile */ - public Object getIdentityProfile() { + public IdentityProfileRequirementsPayload getIdentityProfile() { return identityProfile; } @@ -232,7 +232,7 @@ public Object getIdentityProfile() { * * @return subject */ - public Map getSubject() { + public SubjectPayload getSubject() { return subject; } @@ -277,9 +277,9 @@ public static class Builder { private Boolean blockBiometricConsent; private IbvOptions ibvOptions; private ZonedDateTime sessionDeadline; - private Map identityProfile; + private IdentityProfileRequirementsPayload identityProfile; private AdvancedIdentityProfileRequirementsPayload advancedIdentityProfileRequirementsPayload; - private Map subject; + private SubjectPayload subject; private ResourceCreationContainer resources; private Boolean createIdentityProfilePreview; @@ -428,7 +428,7 @@ public Builder withSessionDeadline(ZonedDateTime sessionDeadline) { * @param identityProfile the Identity Profile * @return the Builder */ - public Builder withIdentityProfile(Map identityProfile) { + public Builder withIdentityProfile(IdentityProfileRequirementsPayload identityProfile) { this.identityProfile = identityProfile; return this; } @@ -439,7 +439,7 @@ public Builder withIdentityProfile(Map identityProfile) { * @param subject the subject * @return the Builder */ - public Builder withSubject(Map subject) { + public Builder withSubject(SubjectPayload subject) { this.subject = subject; return this; } @@ -504,28 +504,4 @@ public SessionSpec build() { } } - private static final class Property { - - private static final String CLIENT_SESSION_TOKEN_TTL = "client_session_token_ttl"; - private static final String SESSION_DEADLINE = "session_deadline"; - private static final String RESOURCES_TTL = "resources_ttl"; - private static final String USER_TRACKING_ID = "user_tracking_id"; - private static final String NOTIFICATIONS = "notifications"; - private static final String REQUESTED_CHECKS = "requested_checks"; - private static final String REQUESTED_TASKS = "requested_tasks"; - private static final String SDK_CONFIG = "sdk_config"; - private static final String REQUIRED_DOCUMENTS = "required_documents"; - private static final String BLOCK_BIOMETRIC_CONSENT = "block_biometric_consent"; - private static final String IBV_OPTIONS = "ibv_options"; - private static final String IDENTITY_PROFILE_REQUIREMENTS = "identity_profile_requirements"; - private static final String ADVANCED_IDENTITY_PROFILE_REQUIREMENTS = "advanced_identity_profile_requirements"; - private static final String SUBJECT = "subject"; - private static final String RESOURCES = "resources"; - private static final String CREATE_IDENTITY_PROFILE_PREVIEW = "create_identity_profile_preview"; - private static final String IMPORT_TOKEN = "import_token"; - - private Property() { } - - } - } diff --git a/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/create/SubjectPayload.java b/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/create/SubjectPayload.java new file mode 100644 index 000000000..64e6a6c51 --- /dev/null +++ b/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/create/SubjectPayload.java @@ -0,0 +1,45 @@ +package com.yoti.api.client.docs.session.create; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public class SubjectPayload { + + @JsonProperty("subject_id") + private final String subjectId; + + private SubjectPayload(String subjectId) { + this.subjectId = subjectId; + } + + public static Builder builder() { + return new Builder(); + } + + public String getSubjectId() { + return subjectId; + } + + public static class Builder { + + private String subjectId; + + Builder() {} + + /** + * Sets the subject ID for the Identity Profile requirement + * + * @param subjectId the subject ID + * @return the builder + */ + public Builder withSubjectId(String subjectId) { + this.subjectId = subjectId; + return this; + } + + public SubjectPayload build() { + return new SubjectPayload(subjectId); + } + + } + +} diff --git a/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/create/UserPrice.java b/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/create/UserPrice.java index 38d1a745c..90c651a78 100644 --- a/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/create/UserPrice.java +++ b/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/create/UserPrice.java @@ -6,10 +6,10 @@ public class UserPrice { - @JsonProperty(Property.AMOUNT) + @JsonProperty("amount") private final String amount; - @JsonProperty(Property.CURRENCY) + @JsonProperty("currency") private final String currency; private UserPrice(String amount, String currency) { @@ -78,13 +78,4 @@ public UserPrice build() { } - private static final class Property { - - private static final String AMOUNT = "amount"; - private static final String CURRENCY = "currency"; - - private Property() { } - - } - } diff --git a/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/create/check/RequestedCustomAccountWatchlistAdvancedCaConfig.java b/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/create/check/RequestedCustomAccountWatchlistAdvancedCaConfig.java index 857bbdd4a..8d630bd8b 100644 --- a/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/create/check/RequestedCustomAccountWatchlistAdvancedCaConfig.java +++ b/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/create/check/RequestedCustomAccountWatchlistAdvancedCaConfig.java @@ -21,7 +21,7 @@ public class RequestedCustomAccountWatchlistAdvancedCaConfig extends RequestedWa @JsonProperty("client_ref") private final String clientRef; - RequestedCustomAccountWatchlistAdvancedCaConfig(Boolean removeDeceased, + private RequestedCustomAccountWatchlistAdvancedCaConfig(Boolean removeDeceased, Boolean shareUrl, RequestedCaSources sources, RequestedCaMatchingStrategy matchingStrategy, diff --git a/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/create/check/RequestedDocumentAuthenticityCheck.java b/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/create/check/RequestedDocumentAuthenticityCheck.java index 8f03996c5..f9f2f33f0 100644 --- a/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/create/check/RequestedDocumentAuthenticityCheck.java +++ b/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/create/check/RequestedDocumentAuthenticityCheck.java @@ -10,7 +10,7 @@ public class RequestedDocumentAuthenticityCheck extends RequestedCheck categories; - RequestedWatchlistScreeningConfig(List categories) { + private RequestedWatchlistScreeningConfig(List categories) { this.categories = categories; } diff --git a/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/create/check/RequestedYotiAccountWatchlistAdvancedCaConfig.java b/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/create/check/RequestedYotiAccountWatchlistAdvancedCaConfig.java index 3b7aaa60b..8a46a17aa 100644 --- a/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/create/check/RequestedYotiAccountWatchlistAdvancedCaConfig.java +++ b/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/create/check/RequestedYotiAccountWatchlistAdvancedCaConfig.java @@ -5,7 +5,7 @@ public class RequestedYotiAccountWatchlistAdvancedCaConfig extends RequestedWatchlistAdvancedCaConfig { - RequestedYotiAccountWatchlistAdvancedCaConfig(Boolean removeDeceased, + private RequestedYotiAccountWatchlistAdvancedCaConfig(Boolean removeDeceased, Boolean shareUrl, RequestedCaSources sources, RequestedCaMatchingStrategy matchingStrategy) { diff --git a/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/create/check/advanced/RequestedFuzzyMatchingStrategy.java b/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/create/check/advanced/RequestedFuzzyMatchingStrategy.java index 4ec1a4e30..9976ebbb5 100644 --- a/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/create/check/advanced/RequestedFuzzyMatchingStrategy.java +++ b/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/create/check/advanced/RequestedFuzzyMatchingStrategy.java @@ -7,7 +7,7 @@ public class RequestedFuzzyMatchingStrategy extends RequestedCaMatchingStrategy @JsonProperty("fuzziness") private final Double fuzziness; - RequestedFuzzyMatchingStrategy(Double fuzziness) { + private RequestedFuzzyMatchingStrategy(Double fuzziness) { this.fuzziness = fuzziness; } diff --git a/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/create/check/advanced/RequestedSearchProfileSources.java b/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/create/check/advanced/RequestedSearchProfileSources.java index c9ca00c75..5e2a2e20f 100644 --- a/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/create/check/advanced/RequestedSearchProfileSources.java +++ b/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/create/check/advanced/RequestedSearchProfileSources.java @@ -7,7 +7,7 @@ public class RequestedSearchProfileSources extends RequestedCaSources { @JsonProperty("search_profile") private final String searchProfile; - RequestedSearchProfileSources(String searchProfile) { + private RequestedSearchProfileSources(String searchProfile) { this.searchProfile = searchProfile; } diff --git a/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/create/check/advanced/RequestedTypeListSources.java b/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/create/check/advanced/RequestedTypeListSources.java index be6397225..ce40c4d9f 100644 --- a/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/create/check/advanced/RequestedTypeListSources.java +++ b/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/create/check/advanced/RequestedTypeListSources.java @@ -9,7 +9,7 @@ public class RequestedTypeListSources extends RequestedCaSources { @JsonProperty("types") private final List types; - RequestedTypeListSources(List types) { + private RequestedTypeListSources(List types) { this.types = types; } diff --git a/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/create/filters/DocumentRestrictionsFilter.java b/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/create/filters/DocumentRestrictionsFilter.java index fc97d5c61..30fcc216f 100644 --- a/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/create/filters/DocumentRestrictionsFilter.java +++ b/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/create/filters/DocumentRestrictionsFilter.java @@ -17,7 +17,7 @@ public class DocumentRestrictionsFilter extends DocumentFilter { @JsonProperty("documents") private final List documents; - DocumentRestrictionsFilter(String inclusion, List documents, Boolean allowNonLatinDocuments, Boolean allowExpiredDocuments) { + private DocumentRestrictionsFilter(String inclusion, List documents, Boolean allowNonLatinDocuments, Boolean allowExpiredDocuments) { super(DocScanConstants.DOCUMENT_RESTRICTIONS, allowNonLatinDocuments, allowExpiredDocuments); this.inclusion = inclusion; this.documents = documents; diff --git a/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/create/filters/OrthogonalRestrictionsFilter.java b/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/create/filters/OrthogonalRestrictionsFilter.java index 728fc63e0..bba774e5c 100644 --- a/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/create/filters/OrthogonalRestrictionsFilter.java +++ b/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/create/filters/OrthogonalRestrictionsFilter.java @@ -14,7 +14,7 @@ public class OrthogonalRestrictionsFilter extends DocumentFilter { @JsonProperty("type_restriction") private final TypeRestriction typeRestriction; - OrthogonalRestrictionsFilter(CountryRestriction countryRestriction, TypeRestriction typeRestriction, Boolean allowNonLatinDocuments, Boolean allowExpiredDocuments) { + private OrthogonalRestrictionsFilter(CountryRestriction countryRestriction, TypeRestriction typeRestriction, Boolean allowNonLatinDocuments, Boolean allowExpiredDocuments) { super(DocScanConstants.ORTHOGONAL_RESTRICTIONS, allowNonLatinDocuments, allowExpiredDocuments); this.countryRestriction = countryRestriction; this.typeRestriction = typeRestriction; diff --git a/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/create/filters/RequiredIdDocument.java b/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/create/filters/RequiredIdDocument.java index f316149e8..db7ffa399 100644 --- a/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/create/filters/RequiredIdDocument.java +++ b/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/create/filters/RequiredIdDocument.java @@ -12,7 +12,7 @@ public class RequiredIdDocument extends RequiredDocument { @JsonProperty("filter") private final DocumentFilter filter; - RequiredIdDocument(DocumentFilter filter) { + private RequiredIdDocument(DocumentFilter filter) { this.filter = filter; } diff --git a/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/create/filters/RequiredSupplementaryDocument.java b/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/create/filters/RequiredSupplementaryDocument.java index fe13ced15..94ad4f66b 100644 --- a/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/create/filters/RequiredSupplementaryDocument.java +++ b/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/create/filters/RequiredSupplementaryDocument.java @@ -20,7 +20,7 @@ public class RequiredSupplementaryDocument extends RequiredDocument { @JsonProperty("country_codes") private final List countryCodes; - RequiredSupplementaryDocument(Objective objective, List documentTypes, List countryCodes) { + private RequiredSupplementaryDocument(Objective objective, List documentTypes, List countryCodes) { this.objective = objective; this.documentTypes = documentTypes; this.countryCodes = countryCodes; diff --git a/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/create/identityprofile/simple/IdentityProfileRequirementsPayload.java b/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/create/identityprofile/simple/IdentityProfileRequirementsPayload.java new file mode 100644 index 000000000..14d413230 --- /dev/null +++ b/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/create/identityprofile/simple/IdentityProfileRequirementsPayload.java @@ -0,0 +1,67 @@ +package com.yoti.api.client.docs.session.create.identityprofile.simple; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonInclude(JsonInclude.Include.NON_NULL) +public class IdentityProfileRequirementsPayload { + + @JsonProperty("trust_framework") + private final String trustFramework; + + @JsonProperty("scheme") + private final IdentityProfileSchemePayload scheme; + + private IdentityProfileRequirementsPayload(String trustFramework, IdentityProfileSchemePayload scheme) { + this.trustFramework = trustFramework; + this.scheme = scheme; + } + + public static Builder builder() { + return new Builder(); + } + + public String getTrustFramework() { + return trustFramework; + } + + public IdentityProfileSchemePayload getScheme() { + return scheme; + } + + public static class Builder { + + private String trustFramework; + private IdentityProfileSchemePayload scheme; + + Builder() {} + + /** + * Sets the trust framework name for the Identity Profile requirement + * + * @param trustFramework the name of the trust framework + * @return the builder + */ + public Builder withTrustFramework(String trustFramework) { + this.trustFramework = trustFramework; + return this; + } + + /** + * Sets the scheme for the Identity Profile requirement + * + * @param scheme the scheme + * @return the builder + */ + public Builder withScheme(IdentityProfileSchemePayload scheme) { + this.scheme = scheme; + return this; + } + + public IdentityProfileRequirementsPayload build() { + return new IdentityProfileRequirementsPayload(trustFramework, scheme); + } + + } + +} diff --git a/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/create/identityprofile/simple/IdentityProfileSchemePayload.java b/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/create/identityprofile/simple/IdentityProfileSchemePayload.java new file mode 100644 index 000000000..b91ee5441 --- /dev/null +++ b/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/create/identityprofile/simple/IdentityProfileSchemePayload.java @@ -0,0 +1,67 @@ +package com.yoti.api.client.docs.session.create.identityprofile.simple; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; + +@JsonInclude(JsonInclude.Include.NON_NULL) +public class IdentityProfileSchemePayload { + + @JsonProperty("type") + private final String type; + + @JsonProperty("objective") + private final String objective; + + private IdentityProfileSchemePayload(String type, String objective) { + this.type = type; + this.objective = objective; + } + + public static Builder builder() { + return new Builder(); + } + + public String getType() { + return type; + } + + public String getObjective() { + return objective; + } + + public static class Builder { + + private String type; + private String objective; + + Builder() {} + + /** + * Sets the type of the scheme for the Identity Profile + * + * @param type the type of scheme + * @return the builder + */ + public Builder withType(String type) { + this.type = type; + return this; + } + + /** + * Sets the objective of the scheme for the Identity Profile + * + * @param objective the objective of the scheme + * @return the builder + */ + public Builder withObjective(String objective) { + this.objective = objective; + return this; + } + + public IdentityProfileSchemePayload build() { + return new IdentityProfileSchemePayload(type, objective); + } + + } + +} diff --git a/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/create/objective/ProofOfAddressObjective.java b/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/create/objective/ProofOfAddressObjective.java index 3bb6db30a..9e93df047 100644 --- a/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/create/objective/ProofOfAddressObjective.java +++ b/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/create/objective/ProofOfAddressObjective.java @@ -4,7 +4,7 @@ public class ProofOfAddressObjective extends Objective { - ProofOfAddressObjective() { + private ProofOfAddressObjective() { super(DocScanConstants.PROOF_OF_ADDRESS); } diff --git a/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/create/task/RequestedIdDocTextExtractionTask.java b/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/create/task/RequestedIdDocTextExtractionTask.java index 51bbbed09..46339848c 100644 --- a/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/create/task/RequestedIdDocTextExtractionTask.java +++ b/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/create/task/RequestedIdDocTextExtractionTask.java @@ -9,7 +9,7 @@ public class RequestedIdDocTextExtractionTask extends RequestedTask details; + @JsonProperty("process") + private String process; + public String getSubCheck() { return subCheck; } @@ -27,4 +30,8 @@ public List getDetails() { return details; } + public String getProcess() { + return process; + } + } diff --git a/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/retrieve/GetSessionResult.java b/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/retrieve/GetSessionResult.java index 87e2f233b..00e81162d 100644 --- a/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/retrieve/GetSessionResult.java +++ b/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/retrieve/GetSessionResult.java @@ -3,49 +3,51 @@ import java.util.List; import java.util.stream.Collectors; +import com.yoti.api.client.docs.session.retrieve.identityprofile.IdentityProfilePreviewResponse; +import com.yoti.api.client.docs.session.retrieve.identityprofile.IdentityProfileResponse; import com.yoti.api.client.docs.session.retrieve.identityprofile.advanced.AdvancedIdentityProfileResponse; import com.fasterxml.jackson.annotation.JsonProperty; public class GetSessionResult { - @JsonProperty(Property.CLIENT_SESSION_TOKEN_TTL) + @JsonProperty("client_session_token_ttl") private long clientSessionTokenTtl; - @JsonProperty(Property.SESSION_ID) + @JsonProperty("session_id") private String sessionId; - @JsonProperty(Property.USER_TRACKING_ID) + @JsonProperty("user_tracking_id") private String userTrackingId; - @JsonProperty(Property.STATE) + @JsonProperty("state") private String state; - @JsonProperty(Property.CLIENT_SESSION_TOKEN) + @JsonProperty("client_session_token") private String clientSessionToken; - @JsonProperty(Property.BIOMETRIC_CONSENT) + @JsonProperty("biometric_consent") private String biometricConsent; - @JsonProperty(Property.CHECKS) + @JsonProperty("checks") private List checks; - @JsonProperty(Property.RESOURCES) + @JsonProperty("resources") private ResourceContainer resources; - @JsonProperty(Property.IDENTITY_PROFILE) + @JsonProperty("identity_profile") private IdentityProfileResponse identityProfile; - @JsonProperty(Property.ADVANCED_IDENTITY_PROFILE) + @JsonProperty("advanced_identity_profile") private AdvancedIdentityProfileResponse advancedIdentityProfile; - @JsonProperty(Property.IDENTITY_PROFILE_PREVIEW) + @JsonProperty("identity_profile_preview") private IdentityProfilePreviewResponse identityProfilePreview; - @JsonProperty(Property.ADVANCED_IDENTITY_PROFILE_PREVIEW) + @JsonProperty("advanced_identity_profile_preview") private IdentityProfilePreviewResponse advancedIdentityProfilePreview; - @JsonProperty(Property.IMPORT_TOKEN) + @JsonProperty("import_token") private ImportTokenResponse importToken; public long getClientSessionTokenTtl() { @@ -175,24 +177,4 @@ private List filterChecksByType(Class clazz) { .collect(Collectors.toList()); } - private static final class Property { - - private static final String CLIENT_SESSION_TOKEN_TTL = "client_session_token_ttl"; - private static final String SESSION_ID = "session_id"; - private static final String USER_TRACKING_ID = "user_tracking_id"; - private static final String STATE = "state"; - private static final String CLIENT_SESSION_TOKEN = "client_session_token"; - private static final String BIOMETRIC_CONSENT = "biometric_consent"; - private static final String CHECKS = "checks"; - private static final String RESOURCES = "resources"; - private static final String IDENTITY_PROFILE = "identity_profile"; - private static final String ADVANCED_IDENTITY_PROFILE = "advanced_identity_profile"; - private static final String IDENTITY_PROFILE_PREVIEW = "identity_profile_preview"; - private static final String ADVANCED_IDENTITY_PROFILE_PREVIEW = "advanced_identity_profile_preview"; - private static final String IMPORT_TOKEN = "import_token"; - - private Property() { } - - } - } diff --git a/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/retrieve/IdentityProfilePreviewResponse.java b/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/retrieve/IdPhotoResponse.java similarity index 83% rename from yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/retrieve/IdentityProfilePreviewResponse.java rename to yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/retrieve/IdPhotoResponse.java index fd9698aaa..ca0a394e4 100644 --- a/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/retrieve/IdentityProfilePreviewResponse.java +++ b/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/retrieve/IdPhotoResponse.java @@ -2,7 +2,7 @@ import com.fasterxml.jackson.annotation.JsonProperty; -public class IdentityProfilePreviewResponse { +public class IdPhotoResponse { @JsonProperty("media") private MediaResponse media; diff --git a/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/retrieve/IdentityProfileResponse.java b/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/retrieve/IdentityProfileResponse.java deleted file mode 100644 index 896e56223..000000000 --- a/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/retrieve/IdentityProfileResponse.java +++ /dev/null @@ -1,48 +0,0 @@ -package com.yoti.api.client.docs.session.retrieve; - -import java.util.Map; - -import com.fasterxml.jackson.annotation.JsonProperty; - -public class IdentityProfileResponse { - - @JsonProperty(Property.SUBJECT_ID) - private String subjectId; - - @JsonProperty(Property.RESULT) - private String result; - - @JsonProperty(Property.FAILURE_REASON) - private IdentityProfileFailureResponse failureReason; - - @JsonProperty(Property.IDENTITY_PROFILE_REPORT) - private Map identityProfileReport; - - public String getSubjectId() { - return subjectId; - } - - public String getResult() { - return result; - } - - public IdentityProfileFailureResponse getFailureReason() { - return failureReason; - } - - public Map getIdentityProfileReport() { - return identityProfileReport; - } - - private static final class Property { - - private static final String SUBJECT_ID = "subject_id"; - private static final String RESULT = "result"; - private static final String FAILURE_REASON = "failure_reason"; - private static final String IDENTITY_PROFILE_REPORT = "identity_profile_report"; - - private Property() { } - - } - -} diff --git a/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/retrieve/ImportTokenResponse.java b/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/retrieve/ImportTokenResponse.java index 73e30650e..2cffb878d 100644 --- a/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/retrieve/ImportTokenResponse.java +++ b/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/retrieve/ImportTokenResponse.java @@ -4,10 +4,10 @@ public class ImportTokenResponse { - @JsonProperty(Property.MEDIA) + @JsonProperty("media") private MediaResponse media; - @JsonProperty(Property.FAILURE_REASON) + @JsonProperty("failure_reason") private String failureReason; public MediaResponse getMedia() { @@ -18,13 +18,4 @@ public String getFailureReason() { return failureReason; } - private static final class Property { - - private static final String MEDIA = "media"; - private static final String FAILURE_REASON = "failure_reason"; - - private Property() { } - - } - } diff --git a/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/retrieve/LookupProfileResponse.java b/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/retrieve/LookupProfileResponse.java new file mode 100644 index 000000000..450904b1d --- /dev/null +++ b/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/retrieve/LookupProfileResponse.java @@ -0,0 +1,14 @@ +package com.yoti.api.client.docs.session.retrieve; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public class LookupProfileResponse { + + @JsonProperty("media") + private MediaResponse media; + + public MediaResponse getMedia() { + return media; + } + +} diff --git a/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/retrieve/ResourceContainer.java b/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/retrieve/ResourceContainer.java index 8d25c591c..1bf7bc810 100644 --- a/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/retrieve/ResourceContainer.java +++ b/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/retrieve/ResourceContainer.java @@ -23,6 +23,9 @@ public class ResourceContainer { @JsonProperty("applicant_profiles") private List applicantProfiles; + @JsonProperty("share_codes") + private List shareCodes; + /** * Returns ID documents that were uploaded by the user * @@ -97,6 +100,15 @@ public List getApplicantProfiles() { return applicantProfiles; } + /** + * Returns ShareCode resources uploaded by the user + * + * @return the list of Share Code resources + */ + public List getShareCodes() { + return shareCodes; + } + ResourceContainer filterForCheck(CheckResponse checkResponse) { ResourceContainer newResourceContainer = new ResourceContainer(); newResourceContainer.idDocuments = filterResources(this.idDocuments, checkResponse.getResourcesUsed()); diff --git a/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/retrieve/ReturnedProfileResponse.java b/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/retrieve/ReturnedProfileResponse.java new file mode 100644 index 000000000..ad2b90356 --- /dev/null +++ b/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/retrieve/ReturnedProfileResponse.java @@ -0,0 +1,14 @@ +package com.yoti.api.client.docs.session.retrieve; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public class ReturnedProfileResponse { + + @JsonProperty("media") + private MediaResponse media; + + public MediaResponse getMedia() { + return media; + } + +} diff --git a/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/retrieve/ShareCodeResourceResponse.java b/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/retrieve/ShareCodeResourceResponse.java new file mode 100644 index 000000000..12ff8bb4e --- /dev/null +++ b/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/retrieve/ShareCodeResourceResponse.java @@ -0,0 +1,41 @@ +package com.yoti.api.client.docs.session.retrieve; + +import java.util.List; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public class ShareCodeResourceResponse extends ResourceResponse { + + @JsonProperty("lookup_profile") + private LookupProfileResponse lookupProfile; + + @JsonProperty("returned_profile") + private ReturnedProfileResponse returnedProfile; + + @JsonProperty("id_photo") + private IdPhotoResponse idPhoto; + + @JsonProperty("file") + private FileResponse file; + + public LookupProfileResponse getLookupProfile() { + return lookupProfile; + } + + public ReturnedProfileResponse getReturnedProfile() { + return returnedProfile; + } + + public IdPhotoResponse getIdPhoto() { + return idPhoto; + } + + public FileResponse getFile() { + return file; + } + + public List getVerifyShareCodeTasks() { + return filterTasksByType(ShareCodeTaskResponse.class); + } + +} diff --git a/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/retrieve/ShareCodeTaskResponse.java b/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/retrieve/ShareCodeTaskResponse.java new file mode 100644 index 000000000..575089725 --- /dev/null +++ b/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/retrieve/ShareCodeTaskResponse.java @@ -0,0 +1,4 @@ +package com.yoti.api.client.docs.session.retrieve; + +public class ShareCodeTaskResponse extends TaskResponse { +} diff --git a/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/retrieve/StaticLivenessResourceResponse.java b/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/retrieve/StaticLivenessResourceResponse.java index b6e2bf6c8..50d8f7782 100644 --- a/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/retrieve/StaticLivenessResourceResponse.java +++ b/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/retrieve/StaticLivenessResourceResponse.java @@ -7,8 +7,15 @@ public class StaticLivenessResourceResponse extends LivenessResourceResponse { @JsonProperty("image") private ImageResponse image; + @JsonProperty("capture_type") + private String captureType; + public ImageResponse getImage() { return image; } + public String getCaptureType() { + return captureType; + } + } diff --git a/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/retrieve/TaskResponse.java b/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/retrieve/TaskResponse.java index 1078753b8..f5e4ec59b 100644 --- a/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/retrieve/TaskResponse.java +++ b/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/retrieve/TaskResponse.java @@ -13,6 +13,7 @@ @JsonSubTypes({ @JsonSubTypes.Type(value = IdDocTextExtractionTaskResponse.class, name = DocScanConstants.ID_DOCUMENT_TEXT_DATA_EXTRACTION), @JsonSubTypes.Type(value = SupplementaryDocumentTextExtractionTaskResponse.class, name = DocScanConstants.SUPPLEMENTARY_DOCUMENT_TEXT_DATA_EXTRACTION), + @JsonSubTypes.Type(value = ShareCodeTaskResponse.class, name = DocScanConstants.VERIFY_SHARE_CODE_TASK) }) public class TaskResponse { diff --git a/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/retrieve/configuration/capture/liveness/UnknownRequiredLivenessResourceResponse.java b/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/retrieve/configuration/capture/liveness/UnknownRequiredLivenessResourceResponse.java index 8a5c79677..375aa50ed 100644 --- a/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/retrieve/configuration/capture/liveness/UnknownRequiredLivenessResourceResponse.java +++ b/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/retrieve/configuration/capture/liveness/UnknownRequiredLivenessResourceResponse.java @@ -1,7 +1,5 @@ package com.yoti.api.client.docs.session.retrieve.configuration.capture.liveness; -import com.yoti.api.client.docs.session.retrieve.configuration.capture.liveness.RequiredLivenessResourceResponse; - public class UnknownRequiredLivenessResourceResponse extends RequiredLivenessResourceResponse { } diff --git a/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/retrieve/IdentityProfileFailureResponse.java b/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/retrieve/identityprofile/IdentityProfileFailureResponse.java similarity index 88% rename from yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/retrieve/IdentityProfileFailureResponse.java rename to yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/retrieve/identityprofile/IdentityProfileFailureResponse.java index 8c73a8b0c..f532c3aff 100644 --- a/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/retrieve/IdentityProfileFailureResponse.java +++ b/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/retrieve/identityprofile/IdentityProfileFailureResponse.java @@ -1,4 +1,4 @@ -package com.yoti.api.client.docs.session.retrieve; +package com.yoti.api.client.docs.session.retrieve.identityprofile; import java.util.List; diff --git a/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/retrieve/identityprofile/IdentityProfilePreviewResponse.java b/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/retrieve/identityprofile/IdentityProfilePreviewResponse.java new file mode 100644 index 000000000..0874938ca --- /dev/null +++ b/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/retrieve/identityprofile/IdentityProfilePreviewResponse.java @@ -0,0 +1,16 @@ +package com.yoti.api.client.docs.session.retrieve.identityprofile; + +import com.yoti.api.client.docs.session.retrieve.MediaResponse; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public class IdentityProfilePreviewResponse { + + @JsonProperty("media") + private MediaResponse media; + + public MediaResponse getMedia() { + return media; + } + +} diff --git a/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/retrieve/identityprofile/IdentityProfileReportResponse.java b/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/retrieve/identityprofile/IdentityProfileReportResponse.java new file mode 100644 index 000000000..afecc98ca --- /dev/null +++ b/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/retrieve/identityprofile/IdentityProfileReportResponse.java @@ -0,0 +1,47 @@ +package com.yoti.api.client.docs.session.retrieve.identityprofile; + +import java.util.List; + +import com.yoti.api.client.docs.session.retrieve.MediaResponse; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public class IdentityProfileReportResponse { + + @JsonProperty("trust_framework") + private String trustFramework; + + @JsonProperty("media") + private MediaResponse media; + + @JsonProperty("schemes_compliance") + private List schemesCompliance; + + /** + * The trust framework the report was generated for + * + * @return the trust framework + */ + public String getTrustFramework() { + return trustFramework; + } + + /** + * The media object containing the report + * + * @return the report media + */ + public MediaResponse getMedia() { + return media; + } + + /** + * The list of schemes used in the trust framework + * + * @return the list of schemes + */ + public List getSchemesCompliance() { + return schemesCompliance; + } + +} diff --git a/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/retrieve/identityprofile/IdentityProfileResponse.java b/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/retrieve/identityprofile/IdentityProfileResponse.java new file mode 100644 index 000000000..46c7a1484 --- /dev/null +++ b/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/retrieve/identityprofile/IdentityProfileResponse.java @@ -0,0 +1,35 @@ +package com.yoti.api.client.docs.session.retrieve.identityprofile; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public class IdentityProfileResponse { + + @JsonProperty("subject_id") + private String subjectId; + + @JsonProperty("result") + private String result; + + @JsonProperty("failure_reason") + private IdentityProfileFailureResponse failureReason; + + @JsonProperty("identity_profile_report") + private IdentityProfileReportResponse identityProfileReport; + + public String getSubjectId() { + return subjectId; + } + + public String getResult() { + return result; + } + + public IdentityProfileFailureResponse getFailureReason() { + return failureReason; + } + + public IdentityProfileReportResponse getIdentityProfileReport() { + return identityProfileReport; + } + +} diff --git a/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/retrieve/identityprofile/IdentityProfileSchemeComplianceReportResponse.java b/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/retrieve/identityprofile/IdentityProfileSchemeComplianceReportResponse.java new file mode 100644 index 000000000..babcdb91a --- /dev/null +++ b/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/retrieve/identityprofile/IdentityProfileSchemeComplianceReportResponse.java @@ -0,0 +1,43 @@ +package com.yoti.api.client.docs.session.retrieve.identityprofile; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public class IdentityProfileSchemeComplianceReportResponse { + + @JsonProperty("scheme") + private IdentityProfileSchemeResponse scheme; + + @JsonProperty("requirements_met") + private Boolean requirementsMet; + + @JsonProperty("requirements_not_met_info") + private String requirementsNotMetInfo; + + /** + * The Identity Profile scheme + * + * @return the scheme + */ + public IdentityProfileSchemeResponse getScheme() { + return scheme; + } + + /** + * Whether or not the requirements for the scheme were met + * + * @return boolean + */ + public Boolean getRequirementsMet() { + return requirementsMet; + } + + /** + * Information about why the requirements for the scheme were not met + * + * @return string + */ + public String getRequirementsNotMetInfo() { + return requirementsNotMetInfo; + } + +} diff --git a/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/retrieve/identityprofile/IdentityProfileSchemeResponse.java b/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/retrieve/identityprofile/IdentityProfileSchemeResponse.java new file mode 100644 index 000000000..d2884f3a4 --- /dev/null +++ b/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/retrieve/identityprofile/IdentityProfileSchemeResponse.java @@ -0,0 +1,31 @@ +package com.yoti.api.client.docs.session.retrieve.identityprofile; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public class IdentityProfileSchemeResponse { + + @JsonProperty("type") + private String type; + + @JsonProperty("objective") + private String objective; + + /** + * The type of the scheme + * + * @return the type + */ + public String getType() { + return type; + } + + /** + * The objective of the scheme + * + * @return the objective + */ + public String getObjective() { + return objective; + } + +} diff --git a/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/retrieve/RequirementNotMetDetailsResponse.java b/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/retrieve/identityprofile/RequirementNotMetDetailsResponse.java similarity index 92% rename from yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/retrieve/RequirementNotMetDetailsResponse.java rename to yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/retrieve/identityprofile/RequirementNotMetDetailsResponse.java index 5927ca047..ecbfab8a3 100644 --- a/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/retrieve/RequirementNotMetDetailsResponse.java +++ b/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/retrieve/identityprofile/RequirementNotMetDetailsResponse.java @@ -1,4 +1,4 @@ -package com.yoti.api.client.docs.session.retrieve; +package com.yoti.api.client.docs.session.retrieve.identityprofile; import com.fasterxml.jackson.annotation.JsonProperty; diff --git a/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/retrieve/identityprofile/advanced/AdvancedIdentityProfileResponse.java b/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/retrieve/identityprofile/advanced/AdvancedIdentityProfileResponse.java index 9d1e9c35a..4922dcf1b 100644 --- a/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/retrieve/identityprofile/advanced/AdvancedIdentityProfileResponse.java +++ b/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/retrieve/identityprofile/advanced/AdvancedIdentityProfileResponse.java @@ -1,6 +1,6 @@ package com.yoti.api.client.docs.session.retrieve.identityprofile.advanced; -import com.yoti.api.client.docs.session.retrieve.IdentityProfileFailureResponse; +import com.yoti.api.client.docs.session.retrieve.identityprofile.IdentityProfileFailureResponse; import com.fasterxml.jackson.annotation.JsonProperty; diff --git a/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/ReceiptFetcher.java b/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/ReceiptFetcher.java index e55baeea1..4d3cb63b7 100644 --- a/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/ReceiptFetcher.java +++ b/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/ReceiptFetcher.java @@ -27,17 +27,17 @@ private ReceiptFetcher(ProfileService profileService) { this.profileService = profileService; } - public static ReceiptFetcher newInstance() { - return new ReceiptFetcher(ProfileService.newInstance()); + public static ReceiptFetcher newInstance(KeyPair keyPair, String appId) { + return new ReceiptFetcher(ProfileService.newInstance(keyPair, appId)); } - public Receipt fetch(String encryptedConnectToken, KeyPair keyPair, String appId) throws ProfileException { + public Receipt fetch(String encryptedConnectToken, KeyPair keyPair) throws ProfileException { LOG.debug("Decrypting connect token: '{}'", encryptedConnectToken); String connectToken = decryptConnectToken(encryptedConnectToken, keyPair.getPrivate()); LOG.debug("Connect token decrypted: '{}'", connectToken); - ProfileResponse profile = profileService.getProfile(keyPair, appId, connectToken); + ProfileResponse profile = profileService.getProfile(keyPair, connectToken); validateReceipt(profile, connectToken); return profile.getReceipt(); } diff --git a/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/ImageResourceFetcher.java b/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/ImageResourceFetcher.java index 236339efa..adb9b4c49 100644 --- a/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/ImageResourceFetcher.java +++ b/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/ImageResourceFetcher.java @@ -29,10 +29,10 @@ private ImageResourceFetcher(RawResourceFetcher rawResourceFetcher) { this.rawResourceFetcher = rawResourceFetcher; } - Image doRequest(SignedRequest signedRequest) throws IOException, ResourceException { - SignedRequestResponse signedRequestResponse = rawResourceFetcher.doRequest(signedRequest); - String contentType = getContentType(signedRequestResponse.getResponseHeaders()); - byte[] responseBody = signedRequestResponse.getResponseBody(); + Image doRequest(YotiHttpRequest yotiHttpRequest) throws IOException, ResourceException { + YotiHttpResponse yotiHttpResponse = rawResourceFetcher.doRequest(yotiHttpRequest); + String contentType = getContentType(yotiHttpResponse.getResponseHeaders()); + byte[] responseBody = yotiHttpResponse.getResponseBody(); switch (contentType) { case CONTENT_TYPE_PNG: return new PngAttributeValue(responseBody); @@ -40,7 +40,7 @@ Image doRequest(SignedRequest signedRequest) throws IOException, ResourceExcepti return new JpegAttributeValue(responseBody); default: LOG.error("Failed to convert image of type: (" + contentType + ")"); - throw new ResourceException(signedRequestResponse.getResponseCode(), "Failed to convert image of type: (" + contentType + ")", null); + throw new ResourceException(yotiHttpResponse.getResponseCode(), "Failed to convert image of type: (" + contentType + ")", null); } } diff --git a/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/JsonResourceFetcher.java b/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/JsonResourceFetcher.java index 7f8423823..434baf0d6 100644 --- a/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/JsonResourceFetcher.java +++ b/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/JsonResourceFetcher.java @@ -36,14 +36,14 @@ private JsonResourceFetcher(ObjectMapper objectMapper, } @Override - public T doRequest(SignedRequest signedRequest, Class resourceClass) throws ResourceException, IOException { - SignedRequestResponse signedRequestResponse = rawResourceFetcher.doRequest(signedRequest); - return objectMapper.readValue(signedRequestResponse.getResponseBody(), resourceClass); + public T doRequest(YotiHttpRequest yotiHttpRequest, Class resourceClass) throws ResourceException, IOException { + YotiHttpResponse yotiHttpResponse = rawResourceFetcher.doRequest(yotiHttpRequest); + return objectMapper.readValue(yotiHttpResponse.getResponseBody(), resourceClass); } - public T doRequest(SignedRequest signedRequest, TypeReference resourceClass) throws ResourceException, IOException { - SignedRequestResponse signedRequestResponse = rawResourceFetcher.doRequest(signedRequest); - return objectMapper.readValue(signedRequestResponse.getResponseBody(), resourceClass); + public T doRequest(YotiHttpRequest yotiHttpRequest, TypeReference resourceClass) throws ResourceException, IOException { + YotiHttpResponse yotiHttpResponse = rawResourceFetcher.doRequest(yotiHttpRequest); + return objectMapper.readValue(yotiHttpResponse.getResponseBody(), resourceClass); } } diff --git a/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/ProfileResponse.java b/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/ProfileResponse.java index b3dcc319b..53c9ed8ce 100644 --- a/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/ProfileResponse.java +++ b/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/ProfileResponse.java @@ -6,13 +6,13 @@ public class ProfileResponse { - @JsonProperty(Property.SESSION_DATA) + @JsonProperty("session_data") private String sessionData; - @JsonProperty(Property.RECEIPT) + @JsonProperty("receipt") private Receipt receipt; - @JsonProperty(Property.ERROR_DETAILS) + @JsonProperty("error_details") private ErrorDetails error; public ProfileResponse() { } @@ -105,14 +105,4 @@ public ProfileResponse build() { } - private static final class Property { - - private static final String SESSION_DATA = "session_data"; - private static final String RECEIPT = "receipt"; - private static final String ERROR_DETAILS = "error_details"; - - private Property() { } - - } - } diff --git a/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/ProfileService.java b/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/ProfileService.java index fb2e5ecca..b018efe31 100644 --- a/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/ProfileService.java +++ b/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/ProfileService.java @@ -18,6 +18,7 @@ import java.util.Base64; import com.yoti.api.client.ProfileException; +import com.yoti.api.client.spi.remote.call.factory.ProfileSignedRequestStrategy; import com.yoti.api.client.spi.remote.call.factory.UnsignedPathFactory; import org.bouncycastle.jce.provider.BouncyCastleProvider; @@ -29,52 +30,54 @@ public class ProfileService { private static final Logger LOG = LoggerFactory.getLogger(ProfileService.class); private final UnsignedPathFactory unsignedPathFactory; - private final SignedRequestBuilderFactory signedRequestBuilderFactory; + private final YotiHttpRequestBuilderFactory yotiHttpRequestBuilderFactory; private final String apiUrl; + private final ProfileSignedRequestStrategy profileSignedRequestStrategy; static { Security.addProvider(new BouncyCastleProvider()); } - public static ProfileService newInstance() { + public static ProfileService newInstance(KeyPair keyPair, String appId) { return new ProfileService( new UnsignedPathFactory(), - new SignedRequestBuilderFactory()); + new YotiHttpRequestBuilderFactory(), + new ProfileSignedRequestStrategy(keyPair, appId)); } - ProfileService(UnsignedPathFactory profilePathFactory, SignedRequestBuilderFactory signedRequestBuilderFactory) { - this.unsignedPathFactory = profilePathFactory; - this.signedRequestBuilderFactory = signedRequestBuilderFactory; - + private ProfileService(UnsignedPathFactory unsignedPathFactory, + YotiHttpRequestBuilderFactory yotiHttpRequestBuilderFactory, + ProfileSignedRequestStrategy profileSignedRequestStrategy) { + this.unsignedPathFactory = unsignedPathFactory; + this.yotiHttpRequestBuilderFactory = yotiHttpRequestBuilderFactory; + this.profileSignedRequestStrategy = profileSignedRequestStrategy; apiUrl = System.getProperty(PROPERTY_YOTI_API_URL, DEFAULT_YOTI_API_URL); } - public Receipt getReceipt(KeyPair keyPair, String appId, String connectToken) throws ProfileException { - return getProfile(keyPair, appId, connectToken).getReceipt(); + public Receipt getReceipt(KeyPair keyPair, String connectToken) throws ProfileException { + return getProfile(keyPair, connectToken).getReceipt(); } - public ProfileResponse getProfile(KeyPair keyPair, String appId, String connectToken) throws ProfileException { + public ProfileResponse getProfile(KeyPair keyPair, String connectToken) throws ProfileException { notNull(keyPair, "Key pair"); - notNull(appId, "Application id"); notNull(connectToken, "Connect token"); - String path = unsignedPathFactory.createProfilePath(appId, connectToken); + String path = unsignedPathFactory.createProfilePath(connectToken); try { String authKey = Base64.getEncoder().encodeToString(keyPair.getPublic().getEncoded()); - - SignedRequest signedRequest = createSignedRequest(keyPair, path, authKey); - return fetchReceipt(signedRequest); + YotiHttpRequest yotiHttpRequest = createRequest(path, authKey); + return fetchReceipt(yotiHttpRequest); } catch (IOException ioe) { throw new ProfileException("Error calling service to get profile", ioe); } } - private ProfileResponse fetchReceipt(SignedRequest signedRequest) throws IOException, ProfileException { - LOG.info("Fetching profile from resource at '{}'", signedRequest.getUri()); + private ProfileResponse fetchReceipt(YotiHttpRequest yotiHttpRequest) throws IOException, ProfileException { + LOG.info("Fetching profile from resource at '{}'", yotiHttpRequest.getUri()); try { - return signedRequest.execute(ProfileResponse.class); + return yotiHttpRequest.execute(ProfileResponse.class); } catch (ResourceException ex) { int responseCode = ex.getResponseCode(); switch (responseCode) { @@ -88,10 +91,10 @@ private ProfileResponse fetchReceipt(SignedRequest signedRequest) throws IOExcep } } - SignedRequest createSignedRequest(KeyPair keyPair, String path, String authKey) throws ProfileException { + YotiHttpRequest createRequest(String path, String authKey) throws ProfileException { try { - return signedRequestBuilderFactory.create() - .withKeyPair(keyPair) + return yotiHttpRequestBuilderFactory.create() + .withAuthStrategy(profileSignedRequestStrategy) .withBaseUrl(apiUrl) .withEndpoint(path) .withHttpMethod(HTTP_GET) diff --git a/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/RawResourceFetcher.java b/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/RawResourceFetcher.java index 520898460..4838fbd66 100644 --- a/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/RawResourceFetcher.java +++ b/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/RawResourceFetcher.java @@ -22,12 +22,12 @@ private static Scanner createScanner(InputStream inputStream) { return new Scanner(inputStream, DEFAULT_CHARSET).useDelimiter("\\A"); } - public SignedRequestResponse doRequest(SignedRequest signedRequest) throws IOException, ResourceException { - UrlConnector urlConnector = UrlConnector.get(signedRequest.getUri().toString()); - return doRequest(urlConnector, signedRequest.getMethod(), signedRequest.getData(), signedRequest.getHeaders()); + public YotiHttpResponse doRequest(YotiHttpRequest yotiHttpRequest) throws IOException, ResourceException { + UrlConnector urlConnector = UrlConnector.get(yotiHttpRequest.getUri().toString()); + return doRequest(urlConnector, yotiHttpRequest.getMethod(), yotiHttpRequest.getData(), yotiHttpRequest.getHeaders()); } - public SignedRequestResponse doRequest(UrlConnector urlConnector, String method, byte[] data, Map headers) + public YotiHttpResponse doRequest(UrlConnector urlConnector, String method, byte[] data, Map headers) throws IOException, ResourceException { HttpURLConnection httpUrlConnection = openConnection(urlConnector, method, headers); sendBody(data, httpUrlConnection); @@ -89,13 +89,13 @@ private void sendBody(byte[] body, HttpURLConnection httpUrlConnection) throws I * @throws ResourceException * @throws IOException */ - private SignedRequestResponse parseResponse(HttpURLConnection httpUrlConnection) throws ResourceException, IOException { + private YotiHttpResponse parseResponse(HttpURLConnection httpUrlConnection) throws ResourceException, IOException { int responseCode = httpUrlConnection.getResponseCode(); if (responseCode >= HttpURLConnection.HTTP_BAD_REQUEST) { String responseBody = readError(httpUrlConnection); throw new ResourceException(responseCode, httpUrlConnection.getResponseMessage(), responseBody); } - return new SignedRequestResponse(responseCode, readBody(httpUrlConnection), httpUrlConnection.getHeaderFields()); + return new YotiHttpResponse(responseCode, readBody(httpUrlConnection), httpUrlConnection.getHeaderFields()); } /** diff --git a/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/ResourceFetcher.java b/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/ResourceFetcher.java index d88166020..0de4d0e1d 100644 --- a/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/ResourceFetcher.java +++ b/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/ResourceFetcher.java @@ -1,10 +1,9 @@ package com.yoti.api.client.spi.remote.call; import java.io.IOException; -import java.util.Map; public interface ResourceFetcher { - T doRequest(SignedRequest signedRequest, Class resourceClass) throws ResourceException, IOException; + T doRequest(YotiHttpRequest yotiHttpRequest, Class resourceClass) throws ResourceException, IOException; } diff --git a/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/YotiConstants.java b/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/YotiConstants.java index 965706a3f..4ca63609b 100644 --- a/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/YotiConstants.java +++ b/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/YotiConstants.java @@ -22,6 +22,7 @@ private YotiConstants() {} public static final String DIGEST_HEADER = "X-Yoti-Auth-Digest"; public static final String YOTI_SDK_HEADER = "X-Yoti-SDK"; public static final String YOTI_SDK_VERSION_HEADER = YOTI_SDK_HEADER + "-Version"; + public static final String AUTHORIZATION_HEADER = "Authorization"; public static final String CONTENT_TYPE = "Content-Type"; public static final String CONTENT_TYPE_JSON = "application/json"; @@ -29,7 +30,7 @@ private YotiConstants() {} public static final String CONTENT_TYPE_JPEG = "image/jpeg"; public static final String JAVA = "Java"; - public static final String SDK_VERSION = JAVA + "-3.12.0"; + public static final String SDK_VERSION = JAVA + "-4.0.0"; public static final String SIGNATURE_ALGORITHM = "SHA256withRSA"; public static final String ASYMMETRIC_CIPHER = "RSA/NONE/PKCS1Padding"; public static final String SYMMETRIC_CIPHER = "AES/CBC/PKCS7Padding"; diff --git a/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/SignedRequest.java b/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/YotiHttpRequest.java similarity index 92% rename from yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/SignedRequest.java rename to yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/YotiHttpRequest.java index b971c050c..97649a0f4 100644 --- a/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/SignedRequest.java +++ b/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/YotiHttpRequest.java @@ -8,7 +8,7 @@ import com.fasterxml.jackson.core.type.TypeReference; -public class SignedRequest { +public class YotiHttpRequest { private final URI uri; private final String method; @@ -18,7 +18,7 @@ public class SignedRequest { private final RawResourceFetcher rawResourceFetcher; private final ImageResourceFetcher imageResourceFetcher; - SignedRequest(final URI uri, + YotiHttpRequest(final URI uri, final String method, final byte[] data, final Map headers, @@ -62,7 +62,7 @@ public T execute(TypeReference typeReference) throws ResourceException, I return jsonResourceFetcher.doRequest(this, typeReference); } - public SignedRequestResponse execute() throws ResourceException, IOException { + public YotiHttpResponse execute() throws ResourceException, IOException { return rawResourceFetcher.doRequest(this); } diff --git a/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/SignedRequestBuilder.java b/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/YotiHttpRequestBuilder.java similarity index 62% rename from yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/SignedRequestBuilder.java rename to yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/YotiHttpRequestBuilder.java index 64da85845..9f1c408c7 100644 --- a/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/SignedRequestBuilder.java +++ b/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/YotiHttpRequestBuilder.java @@ -14,20 +14,28 @@ import java.security.GeneralSecurityException; import java.security.KeyPair; import java.util.HashMap; +import java.util.List; import java.util.Map; +import com.yoti.api.client.spi.remote.call.factory.AmlSignedRequestStrategy; +import com.yoti.api.client.spi.remote.call.factory.AuthStrategy; +import com.yoti.api.client.spi.remote.call.factory.AuthTokenStrategy; +import com.yoti.api.client.spi.remote.call.factory.DigitalIdentitySignedRequestStrategy; +import com.yoti.api.client.spi.remote.call.factory.DocsSignedRequestStrategy; import com.yoti.api.client.spi.remote.call.factory.HeadersFactory; -import com.yoti.api.client.spi.remote.call.factory.PathFactory; -import com.yoti.api.client.spi.remote.call.factory.SignedMessageFactory; +import com.yoti.api.client.spi.remote.call.factory.ProfileSignedRequestStrategy; +import com.yoti.api.client.spi.remote.call.factory.SimpleSignedRequestStrategy; import com.yoti.validation.Validation; +import org.apache.http.Header; import org.apache.http.HttpEntity; +import org.apache.http.NameValuePair; import org.apache.http.entity.ContentType; import org.apache.http.entity.mime.MultipartEntityBuilder; -public class SignedRequestBuilder { +public class YotiHttpRequestBuilder { - private KeyPair keyPair; + private AuthStrategy authStrategy; private String baseUrl; private String endpoint; private byte[] payload; @@ -35,22 +43,16 @@ public class SignedRequestBuilder { private final Map headers = new HashMap<>(); private String httpMethod; - private final PathFactory pathFactory; - private final SignedMessageFactory signedMessageFactory; private final HeadersFactory headersFactory; private final JsonResourceFetcher jsonResourceFetcher; private final RawResourceFetcher rawResourceFetcher; private final ImageResourceFetcher imageResourceFetcher; private MultipartEntityBuilder multipartEntityBuilder; - SignedRequestBuilder(PathFactory pathFactory, - SignedMessageFactory signedMessageFactory, - HeadersFactory headersFactory, + YotiHttpRequestBuilder(HeadersFactory headersFactory, JsonResourceFetcher jsonResourceFetcher, RawResourceFetcher rawResourceFetcher, ImageResourceFetcher imageResourceFetcher) { - this.pathFactory = pathFactory; - this.signedMessageFactory = signedMessageFactory; this.headersFactory = headersFactory; this.jsonResourceFetcher = jsonResourceFetcher; this.rawResourceFetcher = rawResourceFetcher; @@ -60,11 +62,41 @@ public class SignedRequestBuilder { /** * Proceed building the signed request with a specific key pair * - * @param keyPair the key pair + * @param authStrategy the key pair * @return the updated builder */ - public SignedRequestBuilder withKeyPair(KeyPair keyPair) { - this.keyPair = keyPair; + public YotiHttpRequestBuilder withAuthStrategy(AuthStrategy authStrategy) { + this.authStrategy = authStrategy; + return this; + } + + public YotiHttpRequestBuilder forAuthTokenRequest(String authToken) { + this.authStrategy = new AuthTokenStrategy(authToken); + return this; + } + + public YotiHttpRequestBuilder forDocsSignedRequest(KeyPair keyPair, String sdkId) { + this.authStrategy = new DocsSignedRequestStrategy(keyPair, sdkId); + return this; + } + + public YotiHttpRequestBuilder forAmlSignedRequest(KeyPair keyPair, String appId) { + this.authStrategy = new AmlSignedRequestStrategy(keyPair, appId); + return this; + } + + public YotiHttpRequestBuilder forProfileRequest(KeyPair keyPair, String appId) { + this.authStrategy = new ProfileSignedRequestStrategy(keyPair, appId); + return this; + } + + public YotiHttpRequestBuilder forDigitalIdentityRequest(KeyPair keyPair, String appId) { + this.authStrategy = new DigitalIdentitySignedRequestStrategy(keyPair, appId); + return this; + } + + public YotiHttpRequestBuilder forSignedRequest(KeyPair keyPair) { + this.authStrategy = new SimpleSignedRequestStrategy(keyPair); return this; } @@ -74,8 +106,14 @@ public SignedRequestBuilder withKeyPair(KeyPair keyPair) { * @param baseUrl the base url * @return the updated builder */ - public SignedRequestBuilder withBaseUrl(String baseUrl) { - this.baseUrl = baseUrl.replaceAll("([/]+)$", ""); + public YotiHttpRequestBuilder withBaseUrl(String baseUrl) { + int index; + for (index = baseUrl.length() - 1; index >= 0; index--) { + if (baseUrl.charAt(index) != '/') { + break; + } + } + this.baseUrl = baseUrl.substring(0, index + 1); return this; } @@ -85,7 +123,7 @@ public SignedRequestBuilder withBaseUrl(String baseUrl) { * @param endpoint the endpoint * @return the updated builder */ - public SignedRequestBuilder withEndpoint(String endpoint) { + public YotiHttpRequestBuilder withEndpoint(String endpoint) { this.endpoint = endpoint; return this; } @@ -96,7 +134,7 @@ public SignedRequestBuilder withEndpoint(String endpoint) { * @param payload the payload * @return the update builder */ - public SignedRequestBuilder withPayload(byte[] payload) { + public YotiHttpRequestBuilder withPayload(byte[] payload) { this.multipartEntityBuilder = null; this.payload = payload; return this; @@ -109,7 +147,7 @@ public SignedRequestBuilder withPayload(byte[] payload) { * @param value the value of the query parameter * @return the updated builder */ - public SignedRequestBuilder withQueryParameter(String name, String value) { + public YotiHttpRequestBuilder withQueryParameter(String name, String value) { this.queryParameters.put(name, value); return this; } @@ -121,7 +159,7 @@ public SignedRequestBuilder withQueryParameter(String name, String value) { * @param value the value of the header * @return the updated builder */ - public SignedRequestBuilder withHeader(String name, String value) { + public YotiHttpRequestBuilder withHeader(String name, String value) { this.headers.put(name, value); return this; } @@ -132,13 +170,13 @@ public SignedRequestBuilder withHeader(String name, String value) { * @param httpMethod the HTTP method * @return the updated builder */ - public SignedRequestBuilder withHttpMethod(String httpMethod) throws IllegalArgumentException { + public YotiHttpRequestBuilder withHttpMethod(String httpMethod) throws IllegalArgumentException { Validation.withinList(httpMethod, SUPPORTED_HTTP_METHODS); this.httpMethod = httpMethod; return this; } - private SignedRequestBuilder forMultipartRequest() { + private YotiHttpRequestBuilder forMultipartRequest() { if (this.multipartEntityBuilder == null) { this.multipartEntityBuilder = MultipartEntityBuilder.create(); } @@ -152,7 +190,7 @@ private SignedRequestBuilder forMultipartRequest() { * @param multipartBoundary the multipart boundary * @return the updated builder */ - public SignedRequestBuilder withMultipartBoundary(String multipartBoundary) { + public YotiHttpRequestBuilder withMultipartBoundary(String multipartBoundary) { Validation.notNullOrEmpty(multipartBoundary, "multipartBoundary"); forMultipartRequest(); multipartEntityBuilder.setBoundary(multipartBoundary); @@ -171,7 +209,7 @@ public SignedRequestBuilder withMultipartBoundary(String multipartBoundary) { * @param fileName the filename of the binary body * @return the updated builder */ - public SignedRequestBuilder withMultipartBinaryBody(String name, byte[] payload, ContentType contentType, String fileName) { + public YotiHttpRequestBuilder withMultipartBinaryBody(String name, byte[] payload, ContentType contentType, String fileName) { Validation.notNullOrEmpty(name, "name"); Validation.notNull(payload, "payload"); Validation.notNull(contentType, "contentType"); @@ -186,16 +224,9 @@ public SignedRequestBuilder withMultipartBinaryBody(String name, byte[] payload, * * @return the signed request */ - public SignedRequest build() throws GeneralSecurityException, UnsupportedEncodingException, URISyntaxException { + public YotiHttpRequest build() throws GeneralSecurityException, UnsupportedEncodingException, URISyntaxException { validateRequest(); - - if (endpoint.contains("?")) { - endpoint = endpoint.concat("&"); - } else { - endpoint = endpoint.concat("?"); - } - - String builtEndpoint = endpoint + createQueryParameterString(queryParameters); + String builtEndpoint = endpoint + createQueryParameterString(); byte[] finalPayload; if (multipartEntityBuilder == null) { @@ -213,10 +244,10 @@ public SignedRequest build() throws GeneralSecurityException, UnsupportedEncodin } } - String digest = createDigest(builtEndpoint, finalPayload); - headers.putAll(headersFactory.create(digest)); + List
authHeaders = authStrategy.createAuthHeaders(httpMethod, builtEndpoint, finalPayload); + headers.putAll(headersFactory.create(authHeaders)); - return new SignedRequest( + return new YotiHttpRequest( new URI(baseUrl + builtEndpoint), httpMethod, finalPayload, @@ -227,30 +258,38 @@ public SignedRequest build() throws GeneralSecurityException, UnsupportedEncodin } private void validateRequest() { - Validation.notNull(keyPair, "keyPair"); + Validation.notNull(authStrategy, "authStrategy"); Validation.notNullOrEmpty(baseUrl, "baseUrl"); Validation.notNullOrEmpty(endpoint, "endpoint"); Validation.notNullOrEmpty(httpMethod, "httpMethod"); } - private String createQueryParameterString(Map queryParameters) throws UnsupportedEncodingException { + private String createQueryParameterString() throws UnsupportedEncodingException { StringBuilder stringBuilder = new StringBuilder(); + for (Map.Entry entry : queryParameters.entrySet()) { + if (stringBuilder.length() > 0) { + stringBuilder.append("&"); + } stringBuilder.append(entry.getKey()); stringBuilder.append("="); stringBuilder.append(URLEncoder.encode(entry.getValue(), StandardCharsets.UTF_8.toString())); - stringBuilder.append("&"); } - stringBuilder.append(pathFactory.createSignatureParams()); - return stringBuilder.toString(); - } - private String createDigest(String endpoint, byte[] payload) throws GeneralSecurityException { - if (payload != null) { - return signedMessageFactory.create(keyPair.getPrivate(), httpMethod, endpoint, payload); - } else { - return signedMessageFactory.create(keyPair.getPrivate(), httpMethod, endpoint); + for (NameValuePair queryParam : authStrategy.createQueryParams()) { + if (stringBuilder.length() > 0) { + stringBuilder.append("&"); + } + stringBuilder.append(queryParam); + } + + String built = stringBuilder.toString(); + if (built.isEmpty()) { + return built; } + + String prefix = endpoint.contains("?") ? "&" : "?"; + return prefix.concat(built); } } diff --git a/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/SignedRequestBuilderFactory.java b/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/YotiHttpRequestBuilderFactory.java similarity index 52% rename from yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/SignedRequestBuilderFactory.java rename to yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/YotiHttpRequestBuilderFactory.java index 54f826865..62116e7a1 100644 --- a/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/SignedRequestBuilderFactory.java +++ b/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/YotiHttpRequestBuilderFactory.java @@ -1,29 +1,23 @@ package com.yoti.api.client.spi.remote.call; import com.yoti.api.client.spi.remote.call.factory.HeadersFactory; -import com.yoti.api.client.spi.remote.call.factory.PathFactory; -import com.yoti.api.client.spi.remote.call.factory.SignedMessageFactory; -public class SignedRequestBuilderFactory { +public class YotiHttpRequestBuilderFactory { - private static final PathFactory pathFactory; - private static final SignedMessageFactory signedMessageFactory; private static final HeadersFactory headersFactory; private static final JsonResourceFetcher jsonResourceFetcher; private static final RawResourceFetcher rawResourceFetcher; private static final ImageResourceFetcher imageResourceFetcher; static { - pathFactory = new PathFactory(); - signedMessageFactory = SignedMessageFactory.newInstance(); headersFactory = new HeadersFactory(); rawResourceFetcher = new RawResourceFetcher(); jsonResourceFetcher = JsonResourceFetcher.newInstance(rawResourceFetcher); imageResourceFetcher = ImageResourceFetcher.newInstance(rawResourceFetcher); } - public SignedRequestBuilder create() { - return new SignedRequestBuilder(pathFactory, signedMessageFactory, headersFactory, jsonResourceFetcher, rawResourceFetcher, imageResourceFetcher); + public YotiHttpRequestBuilder create() { + return new YotiHttpRequestBuilder(headersFactory, jsonResourceFetcher, rawResourceFetcher, imageResourceFetcher); } } diff --git a/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/SignedRequestResponse.java b/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/YotiHttpResponse.java similarity index 80% rename from yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/SignedRequestResponse.java rename to yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/YotiHttpResponse.java index bcad72eaf..120755cff 100644 --- a/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/SignedRequestResponse.java +++ b/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/YotiHttpResponse.java @@ -3,13 +3,13 @@ import java.util.List; import java.util.Map; -public class SignedRequestResponse { +public class YotiHttpResponse { private final int responseCode; private final byte[] responseBody; private final Map> responseHeaders; - public SignedRequestResponse(int responseCode, byte[] responseBody, Map> responseHeaders) { + public YotiHttpResponse(int responseCode, byte[] responseBody, Map> responseHeaders) { this.responseCode = responseCode; this.responseBody = responseBody.clone(); this.responseHeaders = responseHeaders; diff --git a/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/aml/RemoteAmlService.java b/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/aml/RemoteAmlService.java index 033bca436..eeac2314e 100644 --- a/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/aml/RemoteAmlService.java +++ b/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/aml/RemoteAmlService.java @@ -20,8 +20,9 @@ import com.yoti.api.client.aml.AmlProfile; import com.yoti.api.client.aml.AmlResult; import com.yoti.api.client.spi.remote.call.ResourceException; -import com.yoti.api.client.spi.remote.call.SignedRequest; -import com.yoti.api.client.spi.remote.call.SignedRequestBuilderFactory; +import com.yoti.api.client.spi.remote.call.YotiHttpRequest; +import com.yoti.api.client.spi.remote.call.YotiHttpRequestBuilderFactory; +import com.yoti.api.client.spi.remote.call.factory.AmlSignedRequestStrategy; import com.yoti.api.client.spi.remote.call.factory.UnsignedPathFactory; import com.fasterxml.jackson.databind.ObjectMapper; @@ -30,38 +31,40 @@ public class RemoteAmlService { private final UnsignedPathFactory unsignedPathFactory; private final ObjectMapper objectMapper; - private final SignedRequestBuilderFactory signedRequestBuilderFactory; + private final YotiHttpRequestBuilderFactory yotiHttpRequestBuilderFactory; private final String apiUrl; + private final AmlSignedRequestStrategy amlSignedRequestStrategy; - public static RemoteAmlService newInstance() { + public static RemoteAmlService newInstance(KeyPair keyPair, String appId) { return new RemoteAmlService( new UnsignedPathFactory(), new ObjectMapper(), - new SignedRequestBuilderFactory() + new YotiHttpRequestBuilderFactory(), + new AmlSignedRequestStrategy(keyPair, appId) ); } - RemoteAmlService(UnsignedPathFactory unsignedPathFactory, + private RemoteAmlService(UnsignedPathFactory unsignedPathFactory, ObjectMapper objectMapper, - SignedRequestBuilderFactory signedRequestBuilderFactory) { + YotiHttpRequestBuilderFactory yotiHttpRequestBuilderFactory, + AmlSignedRequestStrategy amlSignedRequestStrategy) { this.unsignedPathFactory = unsignedPathFactory; this.objectMapper = objectMapper; - this.signedRequestBuilderFactory = signedRequestBuilderFactory; + this.yotiHttpRequestBuilderFactory = yotiHttpRequestBuilderFactory; + this.amlSignedRequestStrategy = amlSignedRequestStrategy; apiUrl = System.getProperty(PROPERTY_YOTI_API_URL, DEFAULT_YOTI_API_URL); } - public AmlResult performCheck(KeyPair keyPair, String appId, AmlProfile amlProfile) throws AmlException { - notNull(keyPair, "Key pair"); - notNull(appId, "Application id"); + public AmlResult performCheck(AmlProfile amlProfile) throws AmlException { notNull(amlProfile, "amlProfile"); try { - String resourcePath = unsignedPathFactory.createAmlPath(appId); + String resourcePath = unsignedPathFactory.createAmlPath(); byte[] body = objectMapper.writeValueAsString(amlProfile).getBytes(DEFAULT_CHARSET); - SignedRequest signedRequest = createSignedRequest(keyPair, resourcePath, body); - return signedRequest.execute(AmlResult.class); + YotiHttpRequest yotiHttpRequest = createRequest(resourcePath, body); + return yotiHttpRequest.execute(AmlResult.class); } catch (IOException ioException) { throw new AmlException("Error communicating with AML endpoint", ioException); } catch (ResourceException resourceException) { @@ -69,23 +72,23 @@ public AmlResult performCheck(KeyPair keyPair, String appId, AmlProfile amlProfi } } - private AmlException createExceptionFromStatusCode(ResourceException e) { - switch (e.getResponseCode()) { + private AmlException createExceptionFromStatusCode(ResourceException ex) { + switch (ex.getResponseCode()) { case HTTP_BAD_REQUEST: - return new AmlException("Failed validation:\n" + e.getResponseBody(), e); + return new AmlException("Failed validation:\n" + ex.getResponseBody(), ex); case HTTP_UNAUTHORIZED: - return new AmlException("Failed authorization with the given key:\n" + e.getResponseBody(), e); + return new AmlException("Failed authorization with the given key:\n" + ex.getResponseBody(), ex); case HTTP_INTERNAL_ERROR: - return new AmlException("An unexpected error occured on the server:\n" + e.getResponseBody(), e); + return new AmlException("An unexpected error occured on the server:\n" + ex.getResponseBody(), ex); default: - return new AmlException("Unexpected error:\n" + e.getResponseBody(), e); + return new AmlException("Unexpected error:\n" + ex.getResponseBody(), ex); } } - SignedRequest createSignedRequest(KeyPair keyPair, String resourcePath, byte[] body) throws AmlException { + YotiHttpRequest createRequest(String resourcePath, byte[] body) throws AmlException { try { - return signedRequestBuilderFactory.create() - .withKeyPair(keyPair) + return yotiHttpRequestBuilderFactory.create() + .withAuthStrategy(amlSignedRequestStrategy) .withBaseUrl(apiUrl) .withEndpoint(resourcePath) .withPayload(body) diff --git a/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/factory/AmlSignedRequestStrategy.java b/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/factory/AmlSignedRequestStrategy.java new file mode 100644 index 000000000..4682816e9 --- /dev/null +++ b/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/factory/AmlSignedRequestStrategy.java @@ -0,0 +1,35 @@ +package com.yoti.api.client.spi.remote.call.factory; + +import java.security.GeneralSecurityException; +import java.security.KeyPair; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import org.apache.http.Header; +import org.apache.http.NameValuePair; +import org.apache.http.message.BasicNameValuePair; + +public class AmlSignedRequestStrategy extends SignedRequestStrategy { + + private final String sdkId; + + public AmlSignedRequestStrategy(KeyPair keyPair, String sdkId) { + super(keyPair); + this.sdkId = sdkId; + } + + @Override + public List
createAuthHeaders(String httpMethod, String endpoint, byte[] payload) throws GeneralSecurityException { + return Collections.singletonList(createDigestHeader(httpMethod, endpoint, payload)); + } + + @Override + public List createQueryParams() { + List queryParams = new ArrayList<>(); + queryParams.add(new BasicNameValuePair("appId", sdkId)); + queryParams.addAll(createSignedRequestParams()); + return queryParams; + } + +} diff --git a/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/factory/AuthStrategy.java b/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/factory/AuthStrategy.java new file mode 100644 index 000000000..3b675c1c3 --- /dev/null +++ b/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/factory/AuthStrategy.java @@ -0,0 +1,15 @@ +package com.yoti.api.client.spi.remote.call.factory; + +import java.security.GeneralSecurityException; +import java.util.List; + +import org.apache.http.Header; +import org.apache.http.NameValuePair; + +public interface AuthStrategy { + + List
createAuthHeaders(String httpMethod, String endpoint, byte[] payload) throws GeneralSecurityException; + + List createQueryParams(); + +} diff --git a/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/factory/AuthTokenStrategy.java b/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/factory/AuthTokenStrategy.java new file mode 100644 index 000000000..c67be0c98 --- /dev/null +++ b/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/factory/AuthTokenStrategy.java @@ -0,0 +1,30 @@ +package com.yoti.api.client.spi.remote.call.factory; + +import java.util.Collections; +import java.util.List; + +import com.yoti.api.client.spi.remote.call.YotiConstants; + +import org.apache.http.Header; +import org.apache.http.NameValuePair; +import org.apache.http.message.BasicHeader; + +public class AuthTokenStrategy implements AuthStrategy { + + private final String authenticationToken; + + public AuthTokenStrategy(String authenticationToken) { + this.authenticationToken = authenticationToken; + } + + @Override + public List
createAuthHeaders(String httpMethod, String endpoint, byte[] payload) { + return Collections.singletonList(new BasicHeader(YotiConstants.AUTHORIZATION_HEADER, "Bearer " + authenticationToken)); + } + + @Override + public List createQueryParams() { + return Collections.emptyList(); + } + +} diff --git a/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/factory/DigitalIdentitySignedRequestStrategy.java b/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/factory/DigitalIdentitySignedRequestStrategy.java new file mode 100644 index 000000000..9e7a28a50 --- /dev/null +++ b/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/factory/DigitalIdentitySignedRequestStrategy.java @@ -0,0 +1,33 @@ +package com.yoti.api.client.spi.remote.call.factory; + +import static com.yoti.api.client.spi.remote.call.YotiConstants.AUTH_ID_HEADER; + +import java.security.GeneralSecurityException; +import java.security.KeyPair; +import java.util.Arrays; +import java.util.List; + +import org.apache.http.Header; +import org.apache.http.NameValuePair; +import org.apache.http.message.BasicHeader; + +public class DigitalIdentitySignedRequestStrategy extends SignedRequestStrategy { + + private final String sdkId; + + public DigitalIdentitySignedRequestStrategy(KeyPair keyPair, String sdkId) { + super(keyPair); + this.sdkId = sdkId; + } + + @Override + public List
createAuthHeaders(String httpMethod, String endpoint, byte[] payload) throws GeneralSecurityException { + return Arrays.asList(createDigestHeader(httpMethod, endpoint, payload), new BasicHeader(AUTH_ID_HEADER, sdkId)); + } + + @Override + public List createQueryParams() { + return createSignedRequestParams(); + } + +} diff --git a/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/factory/DocsSignedRequestStrategy.java b/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/factory/DocsSignedRequestStrategy.java new file mode 100644 index 000000000..ba0362a85 --- /dev/null +++ b/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/factory/DocsSignedRequestStrategy.java @@ -0,0 +1,35 @@ +package com.yoti.api.client.spi.remote.call.factory; + +import java.security.GeneralSecurityException; +import java.security.KeyPair; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import org.apache.http.Header; +import org.apache.http.NameValuePair; +import org.apache.http.message.BasicNameValuePair; + +public class DocsSignedRequestStrategy extends SignedRequestStrategy { + + private final String sdkId; + + public DocsSignedRequestStrategy(KeyPair keyPair, String sdkId) { + super(keyPair); + this.sdkId = sdkId; + } + + @Override + public List
createAuthHeaders(String httpMethod, String endpoint, byte[] payload) throws GeneralSecurityException { + return Collections.singletonList(createDigestHeader(httpMethod, endpoint, payload)); + } + + @Override + public List createQueryParams() { + List queryParams = new ArrayList<>(); + queryParams.add(new BasicNameValuePair("sdkId", sdkId)); + queryParams.addAll(createSignedRequestParams()); + return queryParams; + } + +} diff --git a/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/factory/HeadersFactory.java b/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/factory/HeadersFactory.java index a359b625c..43a1d4b03 100644 --- a/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/factory/HeadersFactory.java +++ b/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/factory/HeadersFactory.java @@ -1,30 +1,26 @@ package com.yoti.api.client.spi.remote.call.factory; -import static com.yoti.api.client.spi.remote.call.YotiConstants.AUTH_KEY_HEADER; -import static com.yoti.api.client.spi.remote.call.YotiConstants.DIGEST_HEADER; import static com.yoti.api.client.spi.remote.call.YotiConstants.JAVA; import static com.yoti.api.client.spi.remote.call.YotiConstants.SDK_VERSION; import static com.yoti.api.client.spi.remote.call.YotiConstants.YOTI_SDK_HEADER; import static com.yoti.api.client.spi.remote.call.YotiConstants.YOTI_SDK_VERSION_HEADER; import java.util.HashMap; +import java.util.List; import java.util.Map; +import org.apache.http.Header; + public class HeadersFactory { - public Map create(String digest) { + public Map create(List
authHeaders) { Map headers = new HashMap<>(); - headers.put(DIGEST_HEADER, digest); + for (Header authHeader : authHeaders) { + headers.put(authHeader.getName(), authHeader.getValue()); + } headers.put(YOTI_SDK_HEADER, JAVA); headers.put(YOTI_SDK_VERSION_HEADER, SDK_VERSION); return headers; } - @Deprecated - public Map create(String digest, String authKey) { - Map headers = create(digest); - headers.put(AUTH_KEY_HEADER, authKey); - return headers; - } - } diff --git a/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/factory/NoAuthStrategy.java b/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/factory/NoAuthStrategy.java new file mode 100644 index 000000000..0f2f64b49 --- /dev/null +++ b/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/factory/NoAuthStrategy.java @@ -0,0 +1,22 @@ +package com.yoti.api.client.spi.remote.call.factory; + +import java.security.GeneralSecurityException; +import java.util.Collections; +import java.util.List; + +import org.apache.http.Header; +import org.apache.http.NameValuePair; + +public class NoAuthStrategy implements AuthStrategy { + + @Override + public List
createAuthHeaders(String httpMethod, String endpoint, byte[] payload) throws GeneralSecurityException { + return Collections.emptyList(); + } + + @Override + public List createQueryParams() { + return Collections.emptyList(); + } + +} diff --git a/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/factory/PathFactory.java b/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/factory/PathFactory.java deleted file mode 100644 index 9bb9a1fc8..000000000 --- a/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/factory/PathFactory.java +++ /dev/null @@ -1,52 +0,0 @@ -package com.yoti.api.client.spi.remote.call.factory; - -import static java.lang.System.nanoTime; -import static java.util.UUID.randomUUID; - -public class PathFactory { - - private static final String SIGNATURE_PARAMS = "nonce=%s×tamp=%s"; - - private UnsignedPathFactory unsignedPathFactory; - - public PathFactory() { - this.unsignedPathFactory = new UnsignedPathFactory(); - } - - public String createSignatureParams() { - return String.format(SIGNATURE_PARAMS, randomUUID(), createTimestamp()); - } - - public String createProfilePath(String appId, String connectToken) { - return unsignedPathFactory.createProfilePath(appId, connectToken) + "&" + createSignatureParams(); - } - - public String createAmlPath(String appId) { - return unsignedPathFactory.createAmlPath(appId) + "&" + createSignatureParams(); - } - - public String createDynamicSharingPath(String appId) { - return unsignedPathFactory.createDynamicSharingPath(appId) + "?" + createSignatureParams(); - } - - public String createNewYotiDocsSessionPath(String appId) { - return unsignedPathFactory.createNewYotiDocsSessionPath(appId) + "&" + createSignatureParams(); - } - - public String createGetYotiDocsSessionPath(String appId, String sessionId) { - return unsignedPathFactory.createYotiDocsSessionPath(appId, sessionId) + "&" + createSignatureParams(); - } - - public String createMediaContentPath(String appId, String sessionId, String mediaId) { - return unsignedPathFactory.createMediaContentPath(appId, sessionId, mediaId) + "&" + createSignatureParams(); - } - - public String createGetSupportedDocumentsPath(boolean includeNonLatin) { - return unsignedPathFactory.createGetSupportedDocumentsPath(includeNonLatin) + "&" + createSignatureParams(); - } - - protected long createTimestamp() { - return nanoTime() / 1000; - } - -} diff --git a/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/factory/ProfileSignedRequestStrategy.java b/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/factory/ProfileSignedRequestStrategy.java new file mode 100644 index 000000000..f434baee4 --- /dev/null +++ b/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/factory/ProfileSignedRequestStrategy.java @@ -0,0 +1,35 @@ +package com.yoti.api.client.spi.remote.call.factory; + +import java.security.GeneralSecurityException; +import java.security.KeyPair; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import org.apache.http.Header; +import org.apache.http.NameValuePair; +import org.apache.http.message.BasicNameValuePair; + +public class ProfileSignedRequestStrategy extends SignedRequestStrategy { + + private final String sdkId; + + public ProfileSignedRequestStrategy(KeyPair keyPair, String sdkId) { + super(keyPair); + this.sdkId = sdkId; + } + + @Override + public List
createAuthHeaders(String httpMethod, String endpoint, byte[] payload) throws GeneralSecurityException { + return Collections.singletonList(createDigestHeader(httpMethod, endpoint, payload)); + } + + @Override + public List createQueryParams() { + List queryParams = new ArrayList<>(); + queryParams.add(new BasicNameValuePair("appId", sdkId)); + queryParams.addAll(createSignedRequestParams()); + return queryParams; + } + +} diff --git a/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/factory/SignedRequestStrategy.java b/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/factory/SignedRequestStrategy.java new file mode 100644 index 000000000..254a21318 --- /dev/null +++ b/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/factory/SignedRequestStrategy.java @@ -0,0 +1,49 @@ +package com.yoti.api.client.spi.remote.call.factory; + +import static java.lang.System.nanoTime; +import static java.util.UUID.randomUUID; + +import java.security.GeneralSecurityException; +import java.security.KeyPair; +import java.util.ArrayList; +import java.util.List; + +import com.yoti.api.client.spi.remote.call.YotiConstants; + +import org.apache.http.Header; +import org.apache.http.NameValuePair; +import org.apache.http.message.BasicHeader; +import org.apache.http.message.BasicNameValuePair; + +abstract class SignedRequestStrategy implements AuthStrategy { + + private static final SignedMessageFactory signedMessageFactory; + + static { + signedMessageFactory = SignedMessageFactory.newInstance(); + } + + private final KeyPair keyPair; + + SignedRequestStrategy(KeyPair keyPair) { + this.keyPair = keyPair; + } + + protected Header createDigestHeader(String httpMethod, String endpoint, byte[] payload) throws GeneralSecurityException { + String digest; + if (payload == null) { + digest = signedMessageFactory.create(keyPair.getPrivate(), httpMethod, endpoint); + } else { + digest = signedMessageFactory.create(keyPair.getPrivate(), httpMethod, endpoint, payload); + } + return new BasicHeader(YotiConstants.DIGEST_HEADER, digest); + } + + protected List createSignedRequestParams() { + List queryParams = new ArrayList<>(); + queryParams.add(new BasicNameValuePair("nonce", randomUUID().toString())); + queryParams.add(new BasicNameValuePair("timestamp", Long.toString(nanoTime() / 1000))); + return queryParams; + } + +} diff --git a/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/factory/SimpleSignedRequestStrategy.java b/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/factory/SimpleSignedRequestStrategy.java new file mode 100644 index 000000000..8fdf05bce --- /dev/null +++ b/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/factory/SimpleSignedRequestStrategy.java @@ -0,0 +1,27 @@ +package com.yoti.api.client.spi.remote.call.factory; + +import java.security.GeneralSecurityException; +import java.security.KeyPair; +import java.util.Collections; +import java.util.List; + +import org.apache.http.Header; +import org.apache.http.NameValuePair; + +public class SimpleSignedRequestStrategy extends SignedRequestStrategy { + + public SimpleSignedRequestStrategy(KeyPair keyPair) { + super(keyPair); + } + + @Override + public List
createAuthHeaders(String httpMethod, String endpoint, byte[] payload) throws GeneralSecurityException { + return Collections.singletonList(createDigestHeader(httpMethod, endpoint, payload)); + } + + @Override + public List createQueryParams() { + return createSignedRequestParams(); + } + +} diff --git a/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/factory/UnsignedPathFactory.java b/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/factory/UnsignedPathFactory.java index 15ec5eaa6..56e3440ab 100644 --- a/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/factory/UnsignedPathFactory.java +++ b/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/factory/UnsignedPathFactory.java @@ -5,7 +5,7 @@ public class UnsignedPathFactory { // AML - private static final String AML = "/aml-check?appId=%s"; + private static final String AML = "/aml-check"; // Share V2 private static final String IDENTITY_SESSION_CREATION = "/v2/sessions"; @@ -19,26 +19,26 @@ public class UnsignedPathFactory { private static final String DIGITAL_ID_MATCH = "/v1/matches"; // Share V1 - private static final String PROFILE = "/profile/%s?appId=%s"; + private static final String PROFILE = "/profile/%s"; private static final String QR_CODE = "/qrcodes/apps/%s"; // Docs - private static final String DOCS_CREATE_SESSION = "/sessions?sdkId=%s"; - private static final String DOCS_SESSION = "/sessions/%s?sdkId=%s"; - private static final String DOCS_MEDIA_CONTENT = "/sessions/%s/media/%s/content?sdkId=%s"; - private static final String DOCS_PUT_IBV_INSTRUCTIONS = "/sessions/%s/instructions?sdkId=%s"; - private static final String DOCS_FETCH_IBV_INSTRUCTIONS = "/sessions/%s/instructions?sdkId=%s"; - private static final String DOCS_FETCH_IBV_INSTRUCTIONS_PDF = "/sessions/%s/instructions/pdf?sdkId=%s"; + private static final String DOCS_CREATE_SESSION = "/sessions"; + private static final String DOCS_SESSION = "/sessions/%s"; + private static final String DOCS_MEDIA_CONTENT = "/sessions/%s/media/%s/content"; + private static final String DOCS_PUT_IBV_INSTRUCTIONS = "/sessions/%s/instructions"; + private static final String DOCS_FETCH_IBV_INSTRUCTIONS = "/sessions/%s/instructions"; + private static final String DOCS_FETCH_IBV_INSTRUCTIONS_PDF = "/sessions/%s/instructions/pdf"; private static final String DOCS_SUPPORTED_DOCUMENTS = "/supported-documents?includeNonLatin=%s"; - private static final String DOCS_FETCH_INSTRUCTION_CONTACT_PROFILE = "/sessions/%s/instructions/contact-profile?sdkId=%s"; - private static final String DOCS_FETCH_SESSION_CONFIGURATION = "/sessions/%s/configuration?sdkId=%s"; - private static final String DOCS_NEW_FACE_CAPTURE_RESOURCE = "/sessions/%s/resources/face-capture?sdkId=%s"; - private static final String DOCS_UPLOAD_FACE_CAPTURE_IMAGE = "/sessions/%s/resources/face-capture/%s/image?sdkId=%s"; - private static final String DOCS_TRIGGER_IBV_NOTIFICATION = "/sessions/%s/instructions/email?sdkId=%s"; - private static final String DOCS_TRACKED_DEVICES = "/sessions/%s/tracked-devices?sdkId=%s"; + private static final String DOCS_FETCH_INSTRUCTION_CONTACT_PROFILE = "/sessions/%s/instructions/contact-profile"; + private static final String DOCS_FETCH_SESSION_CONFIGURATION = "/sessions/%s/configuration"; + private static final String DOCS_NEW_FACE_CAPTURE_RESOURCE = "/sessions/%s/resources/face-capture"; + private static final String DOCS_UPLOAD_FACE_CAPTURE_IMAGE = "/sessions/%s/resources/face-capture/%s/image"; + private static final String DOCS_TRIGGER_IBV_NOTIFICATION = "/sessions/%s/instructions/email"; + private static final String DOCS_TRACKED_DEVICES = "/sessions/%s/tracked-devices"; - public String createAmlPath(String appId) { - return format(AML, appId); + public String createAmlPath() { + return format(AML); } public String createIdentitySessionPath() { @@ -73,68 +73,68 @@ public String createIdentityMatchPath() { return DIGITAL_ID_MATCH; } - public String createProfilePath(String appId, String connectToken) { - return format(PROFILE, connectToken, appId); + public String createProfilePath(String connectToken) { + return format(PROFILE, connectToken); } public String createDynamicSharingPath(String appId) { return format(QR_CODE, appId); } - public String createNewYotiDocsSessionPath(String appId) { - return format(DOCS_CREATE_SESSION, appId); + public String createNewYotiDocsSessionPath() { + return DOCS_CREATE_SESSION; } - public String createYotiDocsSessionPath(String appId, String sessionId) { - return format(DOCS_SESSION, sessionId, appId); + public String createYotiDocsSessionPath(String sessionId) { + return format(DOCS_SESSION, sessionId); } - public String createMediaContentPath(String appId, String sessionId, String mediaId) { - return format(DOCS_MEDIA_CONTENT, sessionId, mediaId, appId); + public String createMediaContentPath(String sessionId, String mediaId) { + return format(DOCS_MEDIA_CONTENT, sessionId, mediaId); } - public String createPutIbvInstructionsPath(String appId, String sessionId) { - return format(DOCS_PUT_IBV_INSTRUCTIONS, sessionId, appId); + public String createPutIbvInstructionsPath(String sessionId) { + return format(DOCS_PUT_IBV_INSTRUCTIONS, sessionId); } - public String createFetchIbvInstructionsPath(String appId, String sessionId) { - return format(DOCS_FETCH_IBV_INSTRUCTIONS, sessionId, appId); + public String createFetchIbvInstructionsPath(String sessionId) { + return format(DOCS_FETCH_IBV_INSTRUCTIONS, sessionId); } - public String createFetchIbvInstructionsPdfPath(String sdkId, String sessionId) { - return format(DOCS_FETCH_IBV_INSTRUCTIONS_PDF, sessionId, sdkId); + public String createFetchIbvInstructionsPdfPath(String sessionId) { + return format(DOCS_FETCH_IBV_INSTRUCTIONS_PDF, sessionId); } public String createGetSupportedDocumentsPath(boolean includeNonLatin) { return format(DOCS_SUPPORTED_DOCUMENTS, includeNonLatin); } - public String createFetchInstructionsContactProfilePath(String appId, String sessionId) { - return format(DOCS_FETCH_INSTRUCTION_CONTACT_PROFILE, sessionId, appId); + public String createFetchInstructionsContactProfilePath(String sessionId) { + return format(DOCS_FETCH_INSTRUCTION_CONTACT_PROFILE, sessionId); } - public String createFetchSessionConfigurationPath(String sdkId, String sessionId) { - return format(DOCS_FETCH_SESSION_CONFIGURATION, sessionId, sdkId); + public String createFetchSessionConfigurationPath(String sessionId) { + return format(DOCS_FETCH_SESSION_CONFIGURATION, sessionId); } - public String createNewFaceCaptureResourcePath(String sdkId, String sessionId) { - return format(DOCS_NEW_FACE_CAPTURE_RESOURCE, sessionId, sdkId); + public String createNewFaceCaptureResourcePath(String sessionId) { + return format(DOCS_NEW_FACE_CAPTURE_RESOURCE, sessionId); } - public String createUploadFaceCaptureImagePath(String sdkId, String sessionId, String resourceId) { - return format(DOCS_UPLOAD_FACE_CAPTURE_IMAGE, sessionId, resourceId, sdkId); + public String createUploadFaceCaptureImagePath(String sessionId, String resourceId) { + return format(DOCS_UPLOAD_FACE_CAPTURE_IMAGE, sessionId, resourceId); } - public String createTriggerIbvEmailNotificationPath(String sdkId, String sessionId) { - return format(DOCS_TRIGGER_IBV_NOTIFICATION, sessionId, sdkId); + public String createTriggerIbvEmailNotificationPath(String sessionId) { + return format(DOCS_TRIGGER_IBV_NOTIFICATION, sessionId); } - public String createFetchTrackedDevices(String sdkId, String sessionId) { - return format(DOCS_TRACKED_DEVICES, sessionId, sdkId); + public String createFetchTrackedDevices(String sessionId) { + return format(DOCS_TRACKED_DEVICES, sessionId); } - public String createDeleteTrackedDevices(String sdkId, String sessionId) { - return format(DOCS_TRACKED_DEVICES, sessionId, sdkId); + public String createDeleteTrackedDevices(String sessionId) { + return format(DOCS_TRACKED_DEVICES, sessionId); } } diff --git a/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/identity/DigitalIdentityService.java b/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/identity/DigitalIdentityService.java index b79178c00..22a6c4055 100644 --- a/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/identity/DigitalIdentityService.java +++ b/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/identity/DigitalIdentityService.java @@ -2,7 +2,6 @@ import static com.yoti.api.client.spi.remote.call.HttpMethod.HTTP_GET; import static com.yoti.api.client.spi.remote.call.HttpMethod.HTTP_POST; -import static com.yoti.api.client.spi.remote.call.YotiConstants.AUTH_ID_HEADER; import static com.yoti.api.client.spi.remote.call.YotiConstants.CONTENT_TYPE; import static com.yoti.api.client.spi.remote.call.YotiConstants.CONTENT_TYPE_JSON; import static com.yoti.api.client.spi.remote.call.YotiConstants.DEFAULT_IDENTITY_URL; @@ -22,9 +21,10 @@ import com.yoti.api.client.identity.ShareSessionQrCode; import com.yoti.api.client.identity.ShareSessionRequest; import com.yoti.api.client.spi.remote.call.ResourceException; -import com.yoti.api.client.spi.remote.call.SignedRequest; -import com.yoti.api.client.spi.remote.call.SignedRequestBuilder; -import com.yoti.api.client.spi.remote.call.SignedRequestBuilderFactory; +import com.yoti.api.client.spi.remote.call.YotiHttpRequest; +import com.yoti.api.client.spi.remote.call.YotiHttpRequestBuilder; +import com.yoti.api.client.spi.remote.call.YotiHttpRequestBuilderFactory; +import com.yoti.api.client.spi.remote.call.factory.DigitalIdentitySignedRequestStrategy; import com.yoti.api.client.spi.remote.call.factory.UnsignedPathFactory; import com.yoti.json.ResourceMapper; import com.yoti.validation.Validation; @@ -39,43 +39,40 @@ public class DigitalIdentityService { private static final byte[] EMPTY_JSON = "{}".getBytes(StandardCharsets.UTF_8); private final UnsignedPathFactory pathFactory; - private final SignedRequestBuilderFactory requestBuilderFactory; + private final YotiHttpRequestBuilderFactory requestBuilderFactory; private final ReceiptParser receiptParser; - + private final DigitalIdentitySignedRequestStrategy authStrategy; private final String apiUrl; - public DigitalIdentityService( + private DigitalIdentityService( UnsignedPathFactory pathFactory, - SignedRequestBuilderFactory requestBuilderFactory, - ReceiptParser receiptParser) { + YotiHttpRequestBuilderFactory requestBuilderFactory, + ReceiptParser receiptParser, + DigitalIdentitySignedRequestStrategy authStrategy) { this.pathFactory = pathFactory; this.requestBuilderFactory = requestBuilderFactory; this.receiptParser = receiptParser; - + this.authStrategy = authStrategy; this.apiUrl = System.getProperty(PROPERTY_YOTI_API_URL, DEFAULT_IDENTITY_URL); } - public static DigitalIdentityService newInstance() { + public static DigitalIdentityService newInstance(KeyPair keyPair, String sdkId) { return new DigitalIdentityService( new UnsignedPathFactory(), - new SignedRequestBuilderFactory(), - ReceiptParser.newInstance() + new YotiHttpRequestBuilderFactory(), + ReceiptParser.newInstance(), + new DigitalIdentitySignedRequestStrategy(keyPair, sdkId) ); } - public ShareSession createShareSession(String sdkId, KeyPair keyPair, ShareSessionRequest shareSessionRequest) - throws DigitalIdentityException { - Validation.notNullOrEmpty(sdkId, "SDK ID"); - Validation.notNull(keyPair, "Application Key Pair"); + public ShareSession createShareSession(ShareSessionRequest shareSessionRequest) throws DigitalIdentityException { Validation.notNull(shareSessionRequest, "Share Session request"); String path = pathFactory.createIdentitySessionPath(); - LOG.debug("Requesting share session creation for SDK ID '{}' at '{}'", sdkId, path); - try { byte[] payload = ResourceMapper.writeValueAsString(shareSessionRequest); - return createSignedRequest(sdkId, keyPair, path, HTTP_POST, payload).execute(ShareSession.class); + return createRequest(path, HTTP_POST, payload).execute(ShareSession.class); } catch (IOException ex) { throw new DigitalIdentityException("Error while parsing the share session creation request ", ex); } catch (URISyntaxException ex) { @@ -87,18 +84,13 @@ public ShareSession createShareSession(String sdkId, KeyPair keyPair, ShareSessi } } - public ShareSession fetchShareSession(String sdkId, KeyPair keyPair, String sessionId) - throws DigitalIdentityException { - Validation.notNullOrEmpty(sdkId, "SDK ID"); - Validation.notNull(keyPair, "Application Key Pair"); + public ShareSession fetchShareSession(String sessionId) throws DigitalIdentityException { Validation.notNull(sessionId, "Session ID"); - String path = pathFactory.createIdentitySessionRetrievalPath(sessionId); - LOG.debug("Requesting share session '{}' at '{}'", sessionId, path); try { - return createSignedRequest(sdkId, keyPair, path).execute(ShareSession.class); + return createRequest(path).execute(ShareSession.class); } catch (Exception ex) { throw new DigitalIdentityException( String.format("Error while fetching the share session '{%s}' ", sessionId), @@ -107,10 +99,7 @@ public ShareSession fetchShareSession(String sdkId, KeyPair keyPair, String sess } } - public ShareSessionQrCode createShareQrCode(String sdkId, KeyPair keyPair, String sessionId) - throws DigitalIdentityException { - Validation.notNullOrEmpty(sdkId, "SDK ID"); - Validation.notNull(keyPair, "Application Key Pair"); + public ShareSessionQrCode createShareQrCode(String sessionId) throws DigitalIdentityException { Validation.notNullOrEmpty(sessionId, "Session ID"); String path = pathFactory.createIdentitySessionQrCodePath(sessionId); @@ -118,7 +107,7 @@ public ShareSessionQrCode createShareQrCode(String sdkId, KeyPair keyPair, Strin LOG.debug("Requesting share session '{}' QR code creation at '{}'", sessionId, path); try { - return createSignedRequest(sdkId, keyPair, path, HTTP_POST, EMPTY_JSON).execute(ShareSessionQrCode.class); + return createRequest(path, HTTP_POST, EMPTY_JSON).execute(ShareSessionQrCode.class); } catch (GeneralSecurityException ex) { throw new DigitalIdentityException("Error while signing the share QR code creation request ", ex); } catch (IOException | URISyntaxException | ResourceException ex) { @@ -126,10 +115,7 @@ public ShareSessionQrCode createShareQrCode(String sdkId, KeyPair keyPair, Strin } } - public ShareSessionQrCode fetchShareQrCode(String sdkId, KeyPair keyPair, String qrCodeId) - throws DigitalIdentityException { - Validation.notNullOrEmpty(sdkId, "SDK ID"); - Validation.notNull(keyPair, "Application Key Pair"); + public ShareSessionQrCode fetchShareQrCode(String qrCodeId) throws DigitalIdentityException { Validation.notNullOrEmpty(qrCodeId, "QR Code ID"); String path = pathFactory.createIdentitySessionQrCodeRetrievalPath(qrCodeId); @@ -137,7 +123,7 @@ public ShareSessionQrCode fetchShareQrCode(String sdkId, KeyPair keyPair, String LOG.debug("Requesting share session QR code '{} at '{}'", qrCodeId, path); try { - return createSignedRequest(sdkId, keyPair, path).execute(ShareSessionQrCode.class); + return createRequest(path).execute(ShareSessionQrCode.class); } catch (Exception ex) { throw new DigitalIdentityException( String.format("Error while fetching the share session QR code '{%s}' ", qrCodeId), @@ -146,25 +132,24 @@ public ShareSessionQrCode fetchShareQrCode(String sdkId, KeyPair keyPair, String } } - public Receipt fetchShareReceipt(String sdkId, KeyPair keyPair, String receiptId) throws DigitalIdentityException { - WrappedReceipt wrappedReceipt = doFetchShareReceipt(sdkId, keyPair, receiptId); + public Receipt fetchShareReceipt(KeyPair keyPair, String receiptId) throws DigitalIdentityException { + WrappedReceipt wrappedReceipt = doFetchShareReceipt(receiptId); return Optional.ofNullable(wrappedReceipt.getError()) .map(ignored -> receiptParser.create(wrappedReceipt)) .orElseGet(() -> { - ReceiptItemKey receiptKey = fetchShareReceiptKey(sdkId, keyPair, wrappedReceipt); + ReceiptItemKey receiptKey = fetchShareReceiptKey(wrappedReceipt); return receiptParser.create(wrappedReceipt, receiptKey, keyPair.getPrivate()); }); } - private WrappedReceipt doFetchShareReceipt(String sdkId, KeyPair keyPair, String receiptId) { + private WrappedReceipt doFetchShareReceipt(String receiptId) { String path = pathFactory.createIdentitySessionReceiptRetrievalPath(receiptId); - LOG.debug("Requesting share session receipt '{}' at '{}'", receiptId, path); try { - return createSignedRequest(sdkId, keyPair, path).execute(WrappedReceipt.class); + return createRequest(path).execute(WrappedReceipt.class); } catch (Exception ex) { throw new DigitalIdentityException( String.format("Error while fetching the share session QR code '{%s}' ", receiptId), @@ -173,16 +158,13 @@ private WrappedReceipt doFetchShareReceipt(String sdkId, KeyPair keyPair, String } } - private ReceiptItemKey fetchShareReceiptKey(String sdkId, KeyPair keyPair, WrappedReceipt wrappedReceipt) - throws DigitalIdentityException { + private ReceiptItemKey fetchShareReceiptKey(WrappedReceipt wrappedReceipt) throws DigitalIdentityException { String wrappedItemKeyId = wrappedReceipt.getWrappedItemKeyId(); - String path = pathFactory.createIdentitySessionReceiptKeyRetrievalPath(wrappedItemKeyId); - LOG.debug("Requesting share session receipt item key '{}' at '{}'", wrappedItemKeyId, path); try { - return createSignedRequest(sdkId, keyPair, path).execute(ReceiptItemKey.class); + return createRequest(path).execute(ReceiptItemKey.class); } catch (Exception ex) { throw new DigitalIdentityException( String.format("Error while fetching the share session receipt key '{%s}' ", wrappedItemKeyId), @@ -191,19 +173,14 @@ private ReceiptItemKey fetchShareReceiptKey(String sdkId, KeyPair keyPair, Wrapp } } - public MatchResult fetchMatch(String sdkId, KeyPair keyPair, MatchRequest matchRequest) - throws DigitalIdentityException { - Validation.notNullOrEmpty(sdkId, "SDK ID"); - Validation.notNull(keyPair, "Application Key Pair"); + public MatchResult fetchMatch(MatchRequest matchRequest) throws DigitalIdentityException { Validation.notNull(matchRequest, "DID Match request"); String path = pathFactory.createIdentityMatchPath(); - LOG.debug("Requesting digital ID Match for SDK ID '{}' at '{}'", sdkId, path); - try { byte[] payload = ResourceMapper.writeValueAsString(matchRequest); - return createSignedRequest(sdkId, keyPair, path, HTTP_POST, payload).execute(MatchResult.class); + return createRequest(path, HTTP_POST, payload).execute(MatchResult.class); } catch (IOException ex) { throw new DigitalIdentityException("Error while parsing the DID Match request", ex); } catch (URISyntaxException ex) { @@ -215,18 +192,16 @@ public MatchResult fetchMatch(String sdkId, KeyPair keyPair, MatchRequest matchR } } - SignedRequest createSignedRequest(String sdkId, KeyPair keyPair, String path) - throws GeneralSecurityException, UnsupportedEncodingException, URISyntaxException { - return createSignedRequest(sdkId, keyPair, path, HTTP_GET, null); + YotiHttpRequest createRequest(String path) throws GeneralSecurityException, UnsupportedEncodingException, URISyntaxException { + return createRequest(path, HTTP_GET, null); } - SignedRequest createSignedRequest(String sdkId, KeyPair keyPair, String path, String method, byte[] payload) + YotiHttpRequest createRequest(String path, String method, byte[] payload) throws GeneralSecurityException, UnsupportedEncodingException, URISyntaxException { - SignedRequestBuilder request = requestBuilderFactory.create() - .withKeyPair(keyPair) + YotiHttpRequestBuilder request = requestBuilderFactory.create() + .withAuthStrategy(authStrategy) .withBaseUrl(apiUrl) .withEndpoint(path) - .withHeader(AUTH_ID_HEADER, sdkId) .withHttpMethod(method); return Optional.ofNullable(payload) diff --git a/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/qrcode/DynamicSharingService.java b/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/qrcode/DynamicSharingService.java index fc9b47422..55cb0c597 100644 --- a/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/qrcode/DynamicSharingService.java +++ b/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/qrcode/DynamicSharingService.java @@ -15,9 +15,9 @@ import com.yoti.api.client.shareurl.DynamicShareException; import com.yoti.api.client.shareurl.ShareUrlResult; import com.yoti.api.client.spi.remote.call.ResourceException; -import com.yoti.api.client.spi.remote.call.SignedRequest; -import com.yoti.api.client.spi.remote.call.SignedRequestBuilder; -import com.yoti.api.client.spi.remote.call.SignedRequestBuilderFactory; +import com.yoti.api.client.spi.remote.call.YotiHttpRequest; +import com.yoti.api.client.spi.remote.call.YotiHttpRequestBuilderFactory; +import com.yoti.api.client.spi.remote.call.factory.SimpleSignedRequestStrategy; import com.yoti.api.client.spi.remote.call.factory.UnsignedPathFactory; import com.fasterxml.jackson.databind.ObjectMapper; @@ -26,11 +26,12 @@ public final class DynamicSharingService { - public static DynamicSharingService newInstance() { + public static DynamicSharingService newInstance(KeyPair keyPair) { return new DynamicSharingService( new UnsignedPathFactory(), new ObjectMapper(), - new SignedRequestBuilderFactory() + new YotiHttpRequestBuilderFactory(), + new SimpleSignedRequestStrategy(keyPair) ); } @@ -38,23 +39,25 @@ public static DynamicSharingService newInstance() { private final UnsignedPathFactory unsignedPathFactory; private final ObjectMapper objectMapper; - private final SignedRequestBuilderFactory signedRequestBuilderFactory; + private final YotiHttpRequestBuilderFactory yotiHttpRequestBuilderFactory; + private final SimpleSignedRequestStrategy simpleSignedRequestStrategy; private final String apiUrl; - DynamicSharingService(UnsignedPathFactory unsignedPathFactory, + private DynamicSharingService(UnsignedPathFactory unsignedPathFactory, ObjectMapper objectMapper, - SignedRequestBuilderFactory signedRequestBuilderFactory) { + YotiHttpRequestBuilderFactory yotiHttpRequestBuilderFactory, + SimpleSignedRequestStrategy simpleSignedRequestStrategy) { this.unsignedPathFactory = unsignedPathFactory; this.objectMapper = objectMapper; - this.signedRequestBuilderFactory = signedRequestBuilderFactory; + this.yotiHttpRequestBuilderFactory = yotiHttpRequestBuilderFactory; + this.simpleSignedRequestStrategy = simpleSignedRequestStrategy; apiUrl = System.getProperty(PROPERTY_YOTI_API_URL, DEFAULT_YOTI_API_URL); } - public ShareUrlResult createShareUrl(String appId, KeyPair keyPair, DynamicScenario dynamicScenario) throws DynamicShareException { + public ShareUrlResult createShareUrl(String appId, DynamicScenario dynamicScenario) throws DynamicShareException { notNull(appId, "Application id"); - notNull(keyPair, "Application key Pair"); notNull(dynamicScenario, "Dynamic scenario"); String path = unsignedPathFactory.createDynamicSharingPath(appId); @@ -63,9 +66,9 @@ public ShareUrlResult createShareUrl(String appId, KeyPair keyPair, DynamicScena try { byte[] body = objectMapper.writeValueAsString(dynamicScenario).getBytes(DEFAULT_CHARSET); - SignedRequest signedRequest = createSignedRequest(keyPair, path, body); + YotiHttpRequest yotiHttpRequest = createRequest(path, body); - return signedRequest.execute(ShareUrlResult.class); + return yotiHttpRequest.execute(ShareUrlResult.class); } catch (ResourceException ex) { throw new DynamicShareException("Error posting the request: ", ex); } catch (IOException ex) { @@ -73,10 +76,10 @@ public ShareUrlResult createShareUrl(String appId, KeyPair keyPair, DynamicScena } } - SignedRequest createSignedRequest(KeyPair keyPair, String path, byte[] body) throws DynamicShareException { + YotiHttpRequest createRequest(String path, byte[] body) throws DynamicShareException { try { - return signedRequestBuilderFactory.create() - .withKeyPair(keyPair) + return yotiHttpRequestBuilderFactory.create() + .withAuthStrategy(simpleSignedRequestStrategy) .withBaseUrl(apiUrl) .withEndpoint(path) .withPayload(body) diff --git a/yoti-sdk-api/src/test/java/com/yoti/api/client/DigitalIdentityClientTest.java b/yoti-sdk-api/src/test/java/com/yoti/api/client/DigitalIdentityClientTest.java index 4745cfa7f..687b45302 100644 --- a/yoti-sdk-api/src/test/java/com/yoti/api/client/DigitalIdentityClientTest.java +++ b/yoti-sdk-api/src/test/java/com/yoti/api/client/DigitalIdentityClientTest.java @@ -1,12 +1,12 @@ package com.yoti.api.client; import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.*; +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.equalTo; import static org.junit.Assert.assertThrows; import static org.junit.Assert.assertTrue; import static org.mockito.Answers.RETURNS_DEEP_STUBS; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.*; +import static org.mockito.Mockito.when; import java.io.ByteArrayInputStream; import java.io.IOException; @@ -15,16 +15,17 @@ import com.yoti.api.client.identity.MatchRequest; import com.yoti.api.client.identity.ShareSessionRequest; -import com.yoti.api.client.spi.remote.KeyStreamVisitor; import com.yoti.api.client.spi.remote.call.identity.DigitalIdentityException; import com.yoti.api.client.spi.remote.call.identity.DigitalIdentityService; import com.yoti.api.client.spi.remote.util.CryptoUtil; import org.bouncycastle.openssl.PEMException; -import org.junit.*; +import org.junit.Before; +import org.junit.Test; import org.junit.runner.RunWith; -import org.mockito.*; -import org.mockito.junit.*; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnitRunner; @RunWith(MockitoJUnitRunner.class) public class DigitalIdentityClientTest { @@ -34,9 +35,10 @@ public class DigitalIdentityClientTest { private static final String A_SESSION_ID = "aSessionId"; private static final String A_RECEIPT_ID = "aReceiptId"; - @Mock KeyPairSource keyPairSource; - @Mock(answer = RETURNS_DEEP_STUBS) KeyPair keyPair; - @Mock DigitalIdentityService identityService; + @InjectMocks DigitalIdentityClient testObj; + + @Mock(answer = RETURNS_DEEP_STUBS) KeyPair keyPairMock; + @Mock DigitalIdentityService identityServiceMock; @Mock ShareSessionRequest shareSessionRequest; @Mock MatchRequest matchRequest; @@ -118,21 +120,13 @@ public void build_InvalidKeyPair_InitialisationException() { @Test public void client_CreateShareSessionException_DigitalIdentityException() throws IOException { - when(keyPairSource.getFromStream(any(KeyStreamVisitor.class))).thenReturn(keyPair); - - DigitalIdentityClient identityClient = new DigitalIdentityClient( - AN_SDK_ID, - keyPairSource, - identityService - ); - String exMessage = "Create Share Session Error"; - when(identityService.createShareSession(AN_SDK_ID, keyPair, shareSessionRequest)) + when(identityServiceMock.createShareSession(shareSessionRequest)) .thenThrow(new DigitalIdentityException(exMessage)); DigitalIdentityException ex = assertThrows( DigitalIdentityException.class, - () -> identityClient.createShareSession(shareSessionRequest) + () -> testObj.createShareSession(shareSessionRequest) ); assertThat(ex.getMessage(), equalTo(exMessage)); @@ -140,21 +134,13 @@ public void client_CreateShareSessionException_DigitalIdentityException() throws @Test public void client_FetchShareSessionException_DigitalIdentityException() throws IOException { - when(keyPairSource.getFromStream(any(KeyStreamVisitor.class))).thenReturn(keyPair); - - DigitalIdentityClient identityClient = new DigitalIdentityClient( - AN_SDK_ID, - keyPairSource, - identityService - ); - String exMessage = "Fetch Share Session Error"; - when(identityService.fetchShareSession(AN_SDK_ID, keyPair, A_SESSION_ID)) + when(identityServiceMock.fetchShareSession(A_SESSION_ID)) .thenThrow(new DigitalIdentityException(exMessage)); DigitalIdentityException ex = assertThrows( DigitalIdentityException.class, - () -> identityClient.fetchShareSession(A_SESSION_ID) + () -> testObj.fetchShareSession(A_SESSION_ID) ); assertThat(ex.getMessage(), equalTo(exMessage)); @@ -162,21 +148,13 @@ public void client_FetchShareSessionException_DigitalIdentityException() throws @Test public void client_CreateShareQrCodeException_DigitalIdentityException() throws IOException { - when(keyPairSource.getFromStream(any(KeyStreamVisitor.class))).thenReturn(keyPair); - - DigitalIdentityClient identityClient = new DigitalIdentityClient( - AN_SDK_ID, - keyPairSource, - identityService - ); - String exMessage = "Create Share QR Error"; - when(identityService.createShareQrCode(AN_SDK_ID, keyPair, A_SESSION_ID)) + when(identityServiceMock.createShareQrCode(A_SESSION_ID)) .thenThrow(new DigitalIdentityException(exMessage)); DigitalIdentityException ex = assertThrows( DigitalIdentityException.class, - () -> identityClient.createShareQrCode(A_SESSION_ID) + () -> testObj.createShareQrCode(A_SESSION_ID) ); assertThat(ex.getMessage(), equalTo(exMessage)); @@ -184,21 +162,13 @@ public void client_CreateShareQrCodeException_DigitalIdentityException() throws @Test public void client_FetchShareQrCodeException_DigitalIdentityException() throws IOException { - when(keyPairSource.getFromStream(any(KeyStreamVisitor.class))).thenReturn(keyPair); - - DigitalIdentityClient identityClient = new DigitalIdentityClient( - AN_SDK_ID, - keyPairSource, - identityService - ); - String exMessage = "Fetch Share QR Error"; - when(identityService.fetchShareQrCode(AN_SDK_ID, keyPair, A_QR_CODE_ID)) + when(identityServiceMock.fetchShareQrCode(A_QR_CODE_ID)) .thenThrow(new DigitalIdentityException(exMessage)); DigitalIdentityException ex = assertThrows( DigitalIdentityException.class, - () -> identityClient.fetchShareQrCode(A_QR_CODE_ID) + () -> testObj.fetchShareQrCode(A_QR_CODE_ID) ); assertThat(ex.getMessage(), equalTo(exMessage)); @@ -206,21 +176,13 @@ public void client_FetchShareQrCodeException_DigitalIdentityException() throws I @Test public void client_FetchShareReceiptException_DigitalIdentityException() throws IOException { - when(keyPairSource.getFromStream(any(KeyStreamVisitor.class))).thenReturn(keyPair); - - DigitalIdentityClient identityClient = new DigitalIdentityClient( - AN_SDK_ID, - keyPairSource, - identityService - ); - String exMessage = "Fetch Share Receipt Error"; - when(identityService.fetchShareReceipt(AN_SDK_ID, keyPair, A_RECEIPT_ID)) + when(identityServiceMock.fetchShareReceipt(keyPairMock, A_RECEIPT_ID)) .thenThrow(new DigitalIdentityException(exMessage)); DigitalIdentityException ex = assertThrows( DigitalIdentityException.class, - () -> identityClient.fetchShareReceipt(A_RECEIPT_ID) + () -> testObj.fetchShareReceipt(A_RECEIPT_ID) ); assertThat(ex.getMessage(), equalTo(exMessage)); @@ -228,21 +190,13 @@ public void client_FetchShareReceiptException_DigitalIdentityException() throws @Test public void client_FetchDigitalIdMatchException_DigitalIdentityException() throws IOException { - when(keyPairSource.getFromStream(any(KeyStreamVisitor.class))).thenReturn(keyPair); - - DigitalIdentityClient identityClient = new DigitalIdentityClient( - AN_SDK_ID, - keyPairSource, - identityService - ); - String exMessage = "Fetch digital identity match error"; - when(identityService.fetchMatch(AN_SDK_ID, keyPair, matchRequest)) + when(identityServiceMock.fetchMatch(matchRequest)) .thenThrow(new DigitalIdentityException(exMessage)); DigitalIdentityException ex = assertThrows( DigitalIdentityException.class, - () -> identityClient.fetchMatch(matchRequest) + () -> testObj.fetchMatch(matchRequest) ); assertThat(ex.getMessage(), equalTo(exMessage)); diff --git a/yoti-sdk-api/src/test/java/com/yoti/api/client/YotiClientTest.java b/yoti-sdk-api/src/test/java/com/yoti/api/client/YotiClientTest.java index 19a52dbdf..42b1a6132 100644 --- a/yoti-sdk-api/src/test/java/com/yoti/api/client/YotiClientTest.java +++ b/yoti-sdk-api/src/test/java/com/yoti/api/client/YotiClientTest.java @@ -3,11 +3,11 @@ import static com.yoti.api.client.spi.remote.util.CryptoUtil.base64Url; import static com.yoti.api.client.spi.remote.util.CryptoUtil.encryptAsymmetric; import static com.yoti.api.client.spi.remote.util.CryptoUtil.generateKeyPairFrom; -import static com.yoti.api.client.spi.remote.util.CryptoUtil.generateSymmetricKey; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.StringContains.containsString; import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertThrows; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import static org.mockito.ArgumentMatchers.any; @@ -20,9 +20,7 @@ import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; -import java.security.Key; import java.security.KeyPair; -import java.security.PrivateKey; import com.yoti.api.client.spi.remote.ActivityDetailsFactory; import com.yoti.api.client.spi.remote.ReceiptFetcher; @@ -52,30 +50,24 @@ public class YotiClientTest { @Mock Receipt receiptMock; @Mock ActivityDetails activityDetailsMock; String encryptedToken; - KeyPairSource validKeyPairSource; - byte[] validReceiptKey; + @Mock KeyPair keyPairMock; @Before public void setUp() throws Exception { - Key receiptKey = generateSymmetricKey(); KeyPair keyPair = generateKeyPairFrom(CryptoUtil.KEY_PAIR_PEM); - validReceiptKey = encryptAsymmetric(receiptKey.getEncoded(), keyPair.getPublic()); - encryptedToken = base64Url(encryptAsymmetric(TOKEN.getBytes(), keyPair.getPublic())); - validKeyPairSource = new StaticKeyPairSource(CryptoUtil.KEY_PAIR_PEM); } @Test public void getActivityDetails_shouldFailWithExceptionFromReceiptFetcher() throws Exception { ProfileException profileException = new ProfileException("Test exception"); - when(receiptFetcherMock.fetch(eq(encryptedToken), any(KeyPair.class), eq(APP_ID))).thenThrow(profileException); + when(receiptFetcherMock.fetch(eq(encryptedToken), any(KeyPair.class))).thenThrow(profileException); try { - YotiClient testObj = new YotiClient(APP_ID, validKeyPairSource, receiptFetcherMock, activityDetailsFactoryMock, remoteAmlServiceMock, - sharingServiceMock); + YotiClient testObj = new YotiClient(APP_ID, keyPairMock, receiptFetcherMock, remoteAmlServiceMock, activityDetailsFactoryMock, sharingServiceMock); testObj.getActivityDetails(encryptedToken); - } catch (ProfileException e) { - assertSame(profileException, e); + } catch (ProfileException ex) { + assertSame(profileException, ex); return; } fail("Expected an Exception"); @@ -84,65 +76,57 @@ public void getActivityDetails_shouldFailWithExceptionFromReceiptFetcher() throw @Test public void getActivityDetails_shouldFailWithExceptionFromActivityDetailsFactory() throws Exception { ProfileException profileException = new ProfileException("Test exception"); - when(receiptFetcherMock.fetch(eq(encryptedToken), any(KeyPair.class), eq(APP_ID))).thenReturn(receiptMock); - when(activityDetailsFactoryMock.create(eq(receiptMock), any(PrivateKey.class))).thenThrow(profileException); + when(receiptFetcherMock.fetch(encryptedToken, keyPairMock)).thenReturn(receiptMock); + when(activityDetailsFactoryMock.create(receiptMock, keyPairMock.getPrivate())).thenThrow(profileException); - try { - YotiClient testObj = new YotiClient(APP_ID, validKeyPairSource, receiptFetcherMock, activityDetailsFactoryMock, remoteAmlServiceMock, - sharingServiceMock); - testObj.getActivityDetails(encryptedToken); - } catch (ProfileException e) { - assertSame(profileException, e); - verify(activityDetailsFactoryMock).create(eq(receiptMock), any(PrivateKey.class)); - return; - } - fail("Expected an Exception"); + YotiClient testObj = new YotiClient(APP_ID, keyPairMock, receiptFetcherMock, remoteAmlServiceMock, activityDetailsFactoryMock, sharingServiceMock); + ProfileException thrown = assertThrows(ProfileException.class, () -> testObj.getActivityDetails(encryptedToken)); + + assertSame(profileException, thrown); + verify(activityDetailsFactoryMock).create(receiptMock, keyPairMock.getPrivate()); } @Test public void getActivityDetails_shouldReturnActivityDetails() throws Exception { - when(receiptFetcherMock.fetch(eq(encryptedToken), any(KeyPair.class), eq(APP_ID))).thenReturn(receiptMock); - when(activityDetailsFactoryMock.create(eq(receiptMock), any(PrivateKey.class))).thenReturn(activityDetailsMock); + when(receiptFetcherMock.fetch(encryptedToken, keyPairMock)).thenReturn(receiptMock); + when(activityDetailsFactoryMock.create(receiptMock, keyPairMock.getPrivate())).thenReturn(activityDetailsMock); - YotiClient testObj = new YotiClient(APP_ID, validKeyPairSource, receiptFetcherMock, activityDetailsFactoryMock, remoteAmlServiceMock, - sharingServiceMock); + YotiClient testObj = new YotiClient(APP_ID, keyPairMock, receiptFetcherMock, remoteAmlServiceMock, activityDetailsFactoryMock, sharingServiceMock); ActivityDetails result = testObj.getActivityDetails(encryptedToken); assertSame(activityDetailsMock, result); } @Test - public void constructor_shouldFailWhenStreamExceptionLoadingKeys() { + public void builder_shouldFailWhenStreamExceptionLoadingKeys() { KeyPairSource badKeyPairSource = new StaticKeyPairSource(true); + YotiClient.Builder builder = YotiClient.builder() + .withClientSdkId(APP_ID) + .withKeyPair(badKeyPairSource); - try { - new YotiClient(APP_ID, badKeyPairSource, receiptFetcherMock, activityDetailsFactoryMock, remoteAmlServiceMock, sharingServiceMock); - } catch (InitialisationException e) { - assertTrue(e.getCause() instanceof IOException); - assertThat(e.getCause().getMessage(), containsString("Test stream exception")); - return; - } - fail("Expected an Exception"); + InitialisationException thrown = assertThrows(InitialisationException.class, builder::build); + + assertTrue(thrown.getCause() instanceof IOException); + assertThat(thrown.getCause().getMessage(), containsString("Test stream exception")); } @Test - public void constructor_shouldFailWhenKeyPairSourceExceptionLoadingKeys() { + public void builder_shouldFailWhenKeyPairSourceExceptionLoadingKeys() { KeyPairSource badKeyPairSource = new StaticKeyPairSource(false); + YotiClient.Builder builder = YotiClient.builder() + .withClientSdkId(APP_ID) + .withKeyPair(badKeyPairSource); - try { - new YotiClient(APP_ID, badKeyPairSource, receiptFetcherMock, activityDetailsFactoryMock, remoteAmlServiceMock, sharingServiceMock); - } catch (InitialisationException e) { - assertTrue(e.getCause() instanceof IOException); - assertThat(e.getCause().getMessage(), containsString("Test source exception")); - return; - } - fail("Expected an Exception"); + InitialisationException thrown = assertThrows(InitialisationException.class, builder::build); + + assertTrue(thrown.getCause() instanceof IOException); + assertThat(thrown.getCause().getMessage(), containsString("Test source exception")); } @Test public void constructor_shouldFailWithNullApplicationId() { try { - new YotiClient(null, validKeyPairSource, receiptFetcherMock, activityDetailsFactoryMock, remoteAmlServiceMock, sharingServiceMock); + new YotiClient(null, null, null, null, null, null); } catch (IllegalArgumentException e) { assertThat(e.getMessage(), containsString("Application id")); return; @@ -150,21 +134,10 @@ public void constructor_shouldFailWithNullApplicationId() { fail("Expected an Exception"); } - @Test - public void constructor_shouldFailWithNullKeyPairSource() { - try { - new YotiClient(APP_ID, null, receiptFetcherMock, activityDetailsFactoryMock, remoteAmlServiceMock, sharingServiceMock); - } catch (IllegalArgumentException e) { - assertThat(e.getMessage(), containsString("Key pair source")); - return; - } - fail("Expected an Exception"); - } - @Test public void constructor_shouldFailWithNullReceiptFetcher() { try { - new YotiClient(APP_ID, validKeyPairSource, null, activityDetailsFactoryMock, remoteAmlServiceMock, sharingServiceMock); + new YotiClient(APP_ID, keyPairMock, null, null, null, null); } catch (IllegalArgumentException e) { assertThat(e.getMessage(), containsString("receiptFetcher")); return; @@ -175,7 +148,7 @@ public void constructor_shouldFailWithNullReceiptFetcher() { @Test public void constructor_shouldFailWithNullActivityDetailsFactory() { try { - new YotiClient(APP_ID, validKeyPairSource, receiptFetcherMock, null, remoteAmlServiceMock, sharingServiceMock); + new YotiClient(APP_ID, keyPairMock, receiptFetcherMock, remoteAmlServiceMock, null, null); } catch (IllegalArgumentException e) { assertThat(e.getMessage(), containsString("activityDetailsFactory")); return; @@ -186,7 +159,7 @@ public void constructor_shouldFailWithNullActivityDetailsFactory() { @Test public void constructor_shouldFailWithNullAmlService() { try { - new YotiClient(APP_ID, validKeyPairSource, receiptFetcherMock, activityDetailsFactoryMock, null, sharingServiceMock); + new YotiClient(APP_ID, keyPairMock, receiptFetcherMock, null, null, null); } catch (IllegalArgumentException e) { assertThat(e.getMessage(), containsString("amlService")); return; @@ -195,30 +168,28 @@ public void constructor_shouldFailWithNullAmlService() { } @Test - public void constructor_shouldFailWithNoKeyPair() { + public void builder_shouldFailWithNoKeyPair() { KeyPairSource invalidKeyPairSource = new StaticKeyPairSource("no-key-pair-in-file"); + YotiClient.Builder builder = YotiClient.builder() + .withClientSdkId(APP_ID) + .withKeyPair(invalidKeyPairSource); - try { - new YotiClient(APP_ID, invalidKeyPairSource, receiptFetcherMock, activityDetailsFactoryMock, remoteAmlServiceMock, sharingServiceMock); - } catch (InitialisationException e) { - assertThat(e.getMessage(), containsString("No key pair found in the provided source")); - return; - } - fail("Expected an Exception"); + InitialisationException thrown = assertThrows(InitialisationException.class, builder::build); + + assertThat(thrown.getMessage(), containsString("No key pair found in the provided source")); } @Test - public void constructor_shouldFailWithInvalidKeyPair() { + public void builder_shouldFailWithInvalidKeyPair() { KeyPairSource invalidKeyPairSource = new StaticKeyPairSource(CryptoUtil.INVALID_KEY_PAIR_PEM); + YotiClient.Builder builder = YotiClient.builder() + .withClientSdkId(APP_ID) + .withKeyPair(invalidKeyPairSource); - try { - new YotiClient(APP_ID, invalidKeyPairSource, receiptFetcherMock, activityDetailsFactoryMock, remoteAmlServiceMock, sharingServiceMock); - } catch (InitialisationException e) { - assertThat(e.getMessage(), containsString("Cannot load key pair")); - assertTrue(e.getCause() instanceof PEMException); - return; - } - fail("Expected an Exception"); + InitialisationException thrown = assertThrows(InitialisationException.class, builder::build); + + assertThat(thrown.getMessage(), containsString("Cannot load key pair")); + assertTrue(thrown.getCause() instanceof PEMException); } private static class StaticKeyPairSource implements KeyPairSource { diff --git a/yoti-sdk-api/src/test/java/com/yoti/api/client/docs/DocScanClientBuilderTest.java b/yoti-sdk-api/src/test/java/com/yoti/api/client/docs/DocScanClientBuilderTest.java index 21ac4dd6b..e0bc1c24a 100644 --- a/yoti-sdk-api/src/test/java/com/yoti/api/client/docs/DocScanClientBuilderTest.java +++ b/yoti-sdk-api/src/test/java/com/yoti/api/client/docs/DocScanClientBuilderTest.java @@ -5,8 +5,10 @@ import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.notNullValue; import static org.junit.Assert.assertThrows; -import static org.junit.Assert.fail; +import java.io.IOException; + +import com.yoti.api.client.InitialisationException; import com.yoti.api.client.KeyPairSource; import com.yoti.api.client.common.StaticKeyPairSource; import com.yoti.api.client.spi.remote.util.CryptoUtil; @@ -17,6 +19,7 @@ public class DocScanClientBuilderTest { private static final String SOME_APPLICATION_ID = "someAppId"; + private static final String SOME_AUTH_TOKEN = "someAuthToken"; private KeyPairSource validKeyPairSource; @@ -26,30 +29,71 @@ public void setUp() { } @Test - public void build_shouldThrowExceptionWhenSdkIdIsNull() { - IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> DocScanClient.builder().build()); + public void shouldThrowExceptionWhenSdkIdIsNull() { + DocScanClient.Builder builder = DocScanClient.builder(); + + IllegalStateException ex = assertThrows(IllegalStateException.class, builder::build); + + assertThat(ex.getMessage(), containsString("sdkId")); + } + + @Test + public void shouldThrowExceptionWhenSdkIdIsEmpty() { + DocScanClient.Builder builder = DocScanClient.builder() + .withClientSdkId(""); + + IllegalStateException ex = assertThrows(IllegalStateException.class, builder::build); + + assertThat(ex.getMessage(), containsString("sdkId")); + } + + @Test + public void shouldThrowExceptionWhenKeyPairSourceIsNull() { + DocScanClient.Builder builder = DocScanClient.builder() + .withClientSdkId(SOME_APPLICATION_ID); + + IllegalStateException ex = assertThrows(IllegalStateException.class, builder::build); + + assertThat(ex.getMessage(), containsString("KeyPairSource")); + } + + @Test + public void shouldThrowExceptionWhenSdkIdIsGivenAlongWithAuthToken() { + DocScanClient.Builder builder = DocScanClient.builder() + .withClientSdkId(SOME_APPLICATION_ID) + .withAuthenticationToken(SOME_AUTH_TOKEN); + + IllegalStateException ex = assertThrows(IllegalStateException.class, builder::build); - assertThat(ex.getMessage(), containsString("SDK ID")); + assertThat(ex.getMessage(), containsString("sdkId or KeyPairSource")); } @Test - public void build_shouldThrowExceptionWhenSdkIdIsEmpty() { - IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> DocScanClient.builder().withClientSdkId("").build()); + public void shouldThrowExceptionWhenKeyPairSourceIsGivenAlongWithAuthToken() { + DocScanClient.Builder builder = DocScanClient.builder() + .withKeyPairSource(validKeyPairSource) + .withAuthenticationToken(SOME_AUTH_TOKEN); + + IllegalStateException ex = assertThrows(IllegalStateException.class, builder::build); - assertThat(ex.getMessage(), containsString("SDK ID")); + assertThat(ex.getMessage(), containsString("sdkId or KeyPairSource")); } @Test - public void build_shouldThrowExceptionWhenKeyPairSourceIsNull() { - DocScanClient.Builder builder = DocScanClient.builder().withClientSdkId(SOME_APPLICATION_ID); + public void shouldFailWhenStreamExceptionLoadingKeys() { + KeyPairSource badKeyPairSource = new StaticKeyPairSource(true); + DocScanClient.Builder builder = DocScanClient.builder() + .withClientSdkId(SOME_APPLICATION_ID) + .withKeyPairSource(badKeyPairSource); - IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> builder.build()); + InitialisationException ex = assertThrows(InitialisationException.class, builder::build); - assertThat(ex.getMessage(), containsString("Application key Pair")); + IOException ioException = (IOException) ex.getCause(); + assertThat(ioException.getMessage(), containsString("Test stream exception")); } @Test - public void build_shouldCorrectlyBuildDocScanClient() { + public void shouldCorrectlyBuildDocScanClientForUsingSignedRequests() { DocScanClient result = DocScanClient.builder() .withClientSdkId(SOME_APPLICATION_ID) .withKeyPairSource(validKeyPairSource) @@ -58,4 +102,13 @@ public void build_shouldCorrectlyBuildDocScanClient() { assertThat(result, is(notNullValue())); } + @Test + public void shouldCorrectlyBuildDocScanClientForUsingAuthTokens() { + DocScanClient result = DocScanClient.builder() + .withAuthenticationToken(SOME_AUTH_TOKEN) + .build(); + + assertThat(result, is(notNullValue())); + } + } diff --git a/yoti-sdk-api/src/test/java/com/yoti/api/client/docs/DocScanClientTest.java b/yoti-sdk-api/src/test/java/com/yoti/api/client/docs/DocScanClientTest.java index 265275b17..d85ec9184 100644 --- a/yoti-sdk-api/src/test/java/com/yoti/api/client/docs/DocScanClientTest.java +++ b/yoti-sdk-api/src/test/java/com/yoti/api/client/docs/DocScanClientTest.java @@ -1,64 +1,39 @@ package com.yoti.api.client.docs; import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.containsString; -import static org.hamcrest.Matchers.instanceOf; import static org.hamcrest.Matchers.is; import static org.junit.Assert.assertThrows; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.when; -import java.io.IOException; -import java.security.KeyPair; - -import com.yoti.api.client.InitialisationException; -import com.yoti.api.client.KeyPairSource; -import com.yoti.api.client.common.StaticKeyPairSource; import com.yoti.api.client.docs.session.create.SessionSpec; import com.yoti.api.client.docs.session.instructions.Instructions; -import com.yoti.api.client.spi.remote.util.CryptoUtil; +import com.yoti.api.client.spi.remote.call.factory.AuthStrategy; -import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.MockitoJUnitRunner; @RunWith(MockitoJUnitRunner.class) public class DocScanClientTest { - private static final String APP_ID = "appId"; private static final String SOME_SESSION_ID = "someSessionId"; private static final String SOME_MEDIA_ID = "someMediaId"; + @InjectMocks DocScanClient testObj; + @Mock DocScanService docScanServiceMock; + @Mock AuthStrategy authStrategyMock; @Mock SessionSpec sessionSpecMock; @Mock Instructions instructionsMock; - private KeyPairSource validKeyPairSource; - - @Before - public void setUp() { - validKeyPairSource = new StaticKeyPairSource(CryptoUtil.KEY_PAIR_PEM); - } - - @Test - public void constructor_shouldFailWhenStreamExceptionLoadingKeys() { - KeyPairSource badKeyPairSource = new StaticKeyPairSource(true); - - InitialisationException ex = assertThrows(InitialisationException.class, () -> new DocScanClient(APP_ID, badKeyPairSource, docScanServiceMock)); - - assertThat(ex.getCause(), is(instanceOf(IOException.class))); - assertThat(ex.getCause().getMessage(), containsString("Test stream exception")); - } @Test public void createDocScanSession_shouldFailWithExceptionFromYotiDocsService() throws Exception { DocScanException original = new DocScanException("Test exception"); - when(docScanServiceMock.createSession(eq(APP_ID), any(KeyPair.class), eq(sessionSpecMock))).thenThrow(original); - DocScanClient testObj = new DocScanClient(APP_ID, validKeyPairSource, docScanServiceMock); + when(docScanServiceMock.createSession(authStrategyMock, sessionSpecMock)).thenThrow(original); DocScanException thrown = assertThrows(DocScanException.class, () -> testObj.createSession(sessionSpecMock)); @@ -68,8 +43,7 @@ public void createDocScanSession_shouldFailWithExceptionFromYotiDocsService() th @Test public void getDocScanSession_shouldFailWithExceptionFromYotiDocsService() throws Exception { DocScanException original = new DocScanException("Test exception"); - when(docScanServiceMock.retrieveSession(eq(APP_ID), any(KeyPair.class), eq(SOME_SESSION_ID))).thenThrow(original); - DocScanClient testObj = new DocScanClient(APP_ID, validKeyPairSource, docScanServiceMock); + when(docScanServiceMock.retrieveSession(authStrategyMock, SOME_SESSION_ID)).thenThrow(original); DocScanException thrown = assertThrows(DocScanException.class, () -> testObj.getSession(SOME_SESSION_ID)); @@ -79,8 +53,7 @@ public void getDocScanSession_shouldFailWithExceptionFromYotiDocsService() throw @Test public void getDocScanMedia_shouldFailWithExceptionFromYotiDocsService() throws Exception { DocScanException original = new DocScanException("Test exception"); - when(docScanServiceMock.getMediaContent(eq(APP_ID), any(KeyPair.class), eq(SOME_SESSION_ID), eq(SOME_MEDIA_ID))).thenThrow(original); - DocScanClient testObj = new DocScanClient(APP_ID, validKeyPairSource, docScanServiceMock); + when(docScanServiceMock.getMediaContent(authStrategyMock, SOME_SESSION_ID, SOME_MEDIA_ID)).thenThrow(original); DocScanException thrown = assertThrows(DocScanException.class, () -> testObj.getMediaContent(SOME_SESSION_ID, SOME_MEDIA_ID)); @@ -90,8 +63,7 @@ public void getDocScanMedia_shouldFailWithExceptionFromYotiDocsService() throws @Test public void deleteDocScanMedia_shouldFailWithExceptionFromYotiDocsService() throws Exception { DocScanException original = new DocScanException("Test exception"); - doThrow(original).when(docScanServiceMock).deleteMediaContent(eq(APP_ID), any(KeyPair.class), eq(SOME_SESSION_ID), eq(SOME_MEDIA_ID)); - DocScanClient testObj = new DocScanClient(APP_ID, validKeyPairSource, docScanServiceMock); + doThrow(original).when(docScanServiceMock).deleteMediaContent(authStrategyMock, SOME_SESSION_ID, SOME_MEDIA_ID); DocScanException thrown = assertThrows(DocScanException.class, () -> testObj.deleteMediaContent(SOME_SESSION_ID, SOME_MEDIA_ID)); @@ -101,8 +73,7 @@ public void deleteDocScanMedia_shouldFailWithExceptionFromYotiDocsService() thro @Test public void deleteDocScanSession_shouldFailWithExceptionFromYotiDocsService() throws Exception { DocScanException original = new DocScanException("Test exception"); - doThrow(original).when(docScanServiceMock).deleteSession(eq(APP_ID), any(KeyPair.class), eq(SOME_SESSION_ID)); - DocScanClient testObj = new DocScanClient(APP_ID, validKeyPairSource, docScanServiceMock); + doThrow(original).when(docScanServiceMock).deleteSession(authStrategyMock, SOME_SESSION_ID); DocScanException thrown = assertThrows(DocScanException.class, () -> testObj.deleteSession(SOME_SESSION_ID)); @@ -112,8 +83,7 @@ public void deleteDocScanSession_shouldFailWithExceptionFromYotiDocsService() th @Test public void putIbvInstructions_shouldFailWithExceptionFromYotiDocsService() throws Exception { DocScanException original = new DocScanException("Test exception"); - doThrow(original).when(docScanServiceMock).putIbvInstructions(eq(APP_ID), any(KeyPair.class), eq(SOME_SESSION_ID), eq(instructionsMock)); - DocScanClient testObj = new DocScanClient(APP_ID, validKeyPairSource, docScanServiceMock); + doThrow(original).when(docScanServiceMock).putIbvInstructions(authStrategyMock, SOME_SESSION_ID, instructionsMock); DocScanException exception = assertThrows(DocScanException.class, () -> testObj.putIbvInstructions(SOME_SESSION_ID, instructionsMock)); @@ -123,8 +93,7 @@ public void putIbvInstructions_shouldFailWithExceptionFromYotiDocsService() thro @Test public void getIbvInstructions_shouldFailWithExceptionFromYotiDocsService() throws Exception { DocScanException original = new DocScanException("Test exception"); - doThrow(original).when(docScanServiceMock).getIbvInstructions(eq(APP_ID), any(KeyPair.class), eq(SOME_SESSION_ID)); - DocScanClient testObj = new DocScanClient(APP_ID, validKeyPairSource, docScanServiceMock); + doThrow(original).when(docScanServiceMock).getIbvInstructions(authStrategyMock, SOME_SESSION_ID); DocScanException exception = assertThrows(DocScanException.class, () -> testObj.getIbvInstructions(SOME_SESSION_ID)); @@ -134,8 +103,7 @@ public void getIbvInstructions_shouldFailWithExceptionFromYotiDocsService() thro @Test public void getIbvInstructionsPdf_shouldFailWithExceptionFromYotiDocsService() throws Exception { DocScanException original = new DocScanException("Test exception"); - doThrow(original).when(docScanServiceMock).getIbvInstructionsPdf(eq(APP_ID), any(KeyPair.class), eq(SOME_SESSION_ID)); - DocScanClient testObj = new DocScanClient(APP_ID, validKeyPairSource, docScanServiceMock); + doThrow(original).when(docScanServiceMock).getIbvInstructionsPdf(authStrategyMock, SOME_SESSION_ID); DocScanException exception = assertThrows(DocScanException.class, () -> testObj.getIbvInstructionsPdf(SOME_SESSION_ID)); @@ -145,8 +113,7 @@ public void getIbvInstructionsPdf_shouldFailWithExceptionFromYotiDocsService() t @Test public void fetchInstructionsContactProfile_shouldFailWithExceptionFromYotiDocsService() throws Exception { DocScanException original = new DocScanException("Test exception"); - doThrow(original).when(docScanServiceMock).fetchInstructionsContactProfile(eq(APP_ID), any(KeyPair.class), eq(SOME_SESSION_ID)); - DocScanClient testObj = new DocScanClient(APP_ID, validKeyPairSource, docScanServiceMock); + doThrow(original).when(docScanServiceMock).fetchInstructionsContactProfile(authStrategyMock, SOME_SESSION_ID); DocScanException exception = assertThrows(DocScanException.class, () -> testObj.fetchInstructionsContactProfile(SOME_SESSION_ID)); @@ -156,8 +123,7 @@ public void fetchInstructionsContactProfile_shouldFailWithExceptionFromYotiDocsS @Test public void triggerIbvEmailNotification_shouldFailWithExceptionFromYotiDocsService() throws Exception { DocScanException original = new DocScanException("Test exception"); - doThrow(original).when(docScanServiceMock).triggerIbvEmailNotification(eq(APP_ID), any(KeyPair.class), eq(SOME_SESSION_ID)); - DocScanClient testObj = new DocScanClient(APP_ID, validKeyPairSource, docScanServiceMock); + doThrow(original).when(docScanServiceMock).triggerIbvEmailNotification(authStrategyMock, SOME_SESSION_ID); DocScanException exception = assertThrows(DocScanException.class, () -> testObj.triggerIbvEmailNotification(SOME_SESSION_ID)); @@ -167,8 +133,7 @@ public void triggerIbvEmailNotification_shouldFailWithExceptionFromYotiDocsServi @Test public void getSessionConfiguration_shouldFailWithExceptionFromYotiDocsService() throws Exception { DocScanException original = new DocScanException("Test exception"); - doThrow(original).when(docScanServiceMock).fetchSessionConfiguration(eq(APP_ID), any(KeyPair.class), eq(SOME_SESSION_ID)); - DocScanClient testObj = new DocScanClient(APP_ID, validKeyPairSource, docScanServiceMock); + doThrow(original).when(docScanServiceMock).fetchSessionConfiguration(authStrategyMock, SOME_SESSION_ID); DocScanException exception = assertThrows(DocScanException.class, () -> testObj.getSessionConfiguration(SOME_SESSION_ID)); @@ -178,8 +143,7 @@ public void getSessionConfiguration_shouldFailWithExceptionFromYotiDocsService() @Test public void getSupportedDocuments_shouldFailWithExceptionFromYotiDocsService() throws Exception { DocScanException original = new DocScanException("Test exception"); - doThrow(original).when(docScanServiceMock).getSupportedDocuments(any(KeyPair.class), any(Boolean.class)); - DocScanClient testObj = new DocScanClient(APP_ID, validKeyPairSource, docScanServiceMock); + doThrow(original).when(docScanServiceMock).getSupportedDocuments(false); DocScanException thrown = assertThrows(DocScanException.class, () -> testObj.getSupportedDocuments()); @@ -189,8 +153,7 @@ public void getSupportedDocuments_shouldFailWithExceptionFromYotiDocsService() t @Test public void getTrackedDevices_shouldFailWithExceptionFromYotiDocsService() throws Exception { DocScanException original = new DocScanException("Test exception"); - doThrow(original).when(docScanServiceMock).getTrackedDevices(eq(APP_ID), any(KeyPair.class), eq(SOME_SESSION_ID)); - DocScanClient testObj = new DocScanClient(APP_ID, validKeyPairSource, docScanServiceMock); + doThrow(original).when(docScanServiceMock).getTrackedDevices(authStrategyMock, SOME_SESSION_ID); DocScanException thrown = assertThrows(DocScanException.class, () -> testObj.getTrackedDevices(SOME_SESSION_ID)); @@ -200,8 +163,7 @@ public void getTrackedDevices_shouldFailWithExceptionFromYotiDocsService() throw @Test public void deleteTrackedDevices_shouldFailWithExceptionFromYotiDocsService() throws Exception { DocScanException original = new DocScanException("Test exception"); - doThrow(original).when(docScanServiceMock).deleteTrackedDevices(eq(APP_ID), any(KeyPair.class), eq(SOME_SESSION_ID)); - DocScanClient testObj = new DocScanClient(APP_ID, validKeyPairSource, docScanServiceMock); + doThrow(original).when(docScanServiceMock).deleteTrackedDevices(authStrategyMock, SOME_SESSION_ID); DocScanException thrown = assertThrows(DocScanException.class, () -> testObj.deleteTrackedDevices(SOME_SESSION_ID)); diff --git a/yoti-sdk-api/src/test/java/com/yoti/api/client/docs/DocScanServiceTest.java b/yoti-sdk-api/src/test/java/com/yoti/api/client/docs/DocScanServiceTest.java index a945140fb..6840034b0 100644 --- a/yoti-sdk-api/src/test/java/com/yoti/api/client/docs/DocScanServiceTest.java +++ b/yoti-sdk-api/src/test/java/com/yoti/api/client/docs/DocScanServiceTest.java @@ -6,12 +6,9 @@ import static com.yoti.api.client.spi.remote.call.YotiConstants.CONTENT_TYPE_JSON; import static com.yoti.api.client.spi.remote.call.YotiConstants.DEFAULT_YOTI_DOCS_URL; import static com.yoti.api.client.spi.remote.call.YotiConstants.PROPERTY_YOTI_DOCS_URL; -import static com.yoti.api.client.spi.remote.util.CryptoUtil.KEY_PAIR_PEM; -import static com.yoti.api.client.spi.remote.util.CryptoUtil.generateKeyPairFrom; import static junit.framework.TestCase.assertSame; import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.any; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.hasSize; import static org.hamcrest.Matchers.instanceOf; @@ -29,7 +26,6 @@ import java.io.InputStream; import java.net.URISyntaxException; import java.security.GeneralSecurityException; -import java.security.KeyPair; import java.util.Collections; import java.util.HashMap; import java.util.List; @@ -54,16 +50,16 @@ import com.yoti.api.client.docs.support.SupportedDocumentsResponse; import com.yoti.api.client.spi.remote.call.HttpMethod; import com.yoti.api.client.spi.remote.call.ResourceException; -import com.yoti.api.client.spi.remote.call.SignedRequest; -import com.yoti.api.client.spi.remote.call.SignedRequestBuilder; -import com.yoti.api.client.spi.remote.call.SignedRequestBuilderFactory; -import com.yoti.api.client.spi.remote.call.SignedRequestResponse; +import com.yoti.api.client.spi.remote.call.YotiHttpRequest; +import com.yoti.api.client.spi.remote.call.YotiHttpRequestBuilder; +import com.yoti.api.client.spi.remote.call.YotiHttpRequestBuilderFactory; +import com.yoti.api.client.spi.remote.call.YotiHttpResponse; +import com.yoti.api.client.spi.remote.call.factory.AuthStrategy; import com.yoti.api.client.spi.remote.call.factory.UnsignedPathFactory; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; import org.junit.Before; -import org.junit.BeforeClass; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Answers; @@ -76,7 +72,6 @@ @RunWith(MockitoJUnitRunner.class) public class DocScanServiceTest { - private static final String SOME_APP_ID = "someAppId"; private static final String SOME_SESSION_ID = "someSessionId"; private static final String SOME_PATH = "somePath"; private static final String SOME_MEDIA_ID = "someMediaId"; @@ -87,48 +82,36 @@ public class DocScanServiceTest { private static final byte[] IMAGE_BODY = "some-image-body".getBytes(); private static final ObjectMapper MAPPER = new ObjectMapper(); - private static KeyPair KEY_PAIR; - @Spy @InjectMocks DocScanService docScanService; @Mock UnsignedPathFactory unsignedPathFactoryMock; @Mock ObjectMapper objectMapperMock; - @Mock SignedRequest signedRequestMock; - @Mock(answer = Answers.RETURNS_SELF) SignedRequestBuilder signedRequestBuilderMock; - @Mock SignedRequestResponse signedRequestResponseMock; - @Mock SignedRequestBuilderFactory signedRequestBuilderFactoryMock; + @Mock(answer = Answers.RETURNS_SELF) YotiHttpRequestBuilder yotiHttpRequestBuilderMock; + + @Mock AuthStrategy authStrategyMock; + @Mock YotiHttpRequest yotiHttpRequestMock; + @Mock YotiHttpResponse yotiHttpResponseMock; + @Mock YotiHttpRequestBuilderFactory yotiHttpRequestBuilderFactoryMock; @Mock SupportedDocumentsResponse supportedDocumentsResponseMock; @Mock Instructions instructionsMock; @Mock CreateFaceCaptureResourcePayload createFaceCaptureResourcePayloadMock; @Mock UploadFaceCaptureImagePayload uploadFaceCaptureImagePayloadMock; - @BeforeClass - public static void setUpClass() throws Exception { - KEY_PAIR = generateKeyPairFrom(KEY_PAIR_PEM); - } - @Before public void setUp() { - when(signedRequestBuilderFactoryMock.create()).thenReturn(signedRequestBuilderMock); - } - - @Test - public void createSession_shouldThrowExceptionWhenMissingAppId() { - IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.createSession(null, null, null)); - - assertThat(ex.getMessage(), containsString("SDK ID")); + when(yotiHttpRequestBuilderFactoryMock.create()).thenReturn(yotiHttpRequestBuilderMock); } @Test - public void createSession_shouldThrowExceptionWhenMissingKeyPair() { - IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.createSession(SOME_APP_ID, null, null)); + public void createSession_shouldThrowExceptionWhenMissingAuthStrategy() { + IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.createSession(null, null)); - assertThat(ex.getMessage(), containsString("Application key Pair")); + assertThat(ex.getMessage(), containsString("'authStrategy' must not be null.")); } @Test public void createSession_shouldThrowExceptionWhenMissingSessionSpec() { - IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.createSession(SOME_APP_ID, KEY_PAIR, null)); + IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.createSession(authStrategyMock, null)); assertThat(ex.getMessage(), containsString("sessionSpec")); } @@ -137,9 +120,9 @@ public void createSession_shouldThrowExceptionWhenMissingSessionSpec() { public void createSession_shouldWrapGeneralSecurityException() throws Exception { GeneralSecurityException gse = new GeneralSecurityException("some gse"); SessionSpec sessionSpecMock = mock(SessionSpec.class); - when(signedRequestBuilderMock.build()).thenThrow(gse); + when(yotiHttpRequestBuilderMock.build()).thenThrow(gse); - DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.createSession(SOME_APP_ID, KEY_PAIR, sessionSpecMock)); + DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.createSession(authStrategyMock, sessionSpecMock)); assertSame(ex.getCause(), gse); assertThat(ex.getMessage(), containsString("Error signing the request: some gse")); @@ -149,10 +132,10 @@ public void createSession_shouldWrapGeneralSecurityException() throws Exception public void createSession_shouldWrapResourceException() throws Exception { ResourceException resourceException = new ResourceException(400, "Failed Request", "Some response from API"); SessionSpec sessionSpecMock = mock(SessionSpec.class); - when(signedRequestBuilderMock.build()).thenReturn(signedRequestMock); - when(signedRequestMock.execute(CreateSessionResult.class)).thenThrow(resourceException); + when(yotiHttpRequestBuilderMock.build()).thenReturn(yotiHttpRequestMock); + when(yotiHttpRequestMock.execute(CreateSessionResult.class)).thenThrow(resourceException); - DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.createSession(SOME_APP_ID, KEY_PAIR, sessionSpecMock)); + DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.createSession(authStrategyMock, sessionSpecMock)); assertSame(ex.getCause(), resourceException); assertThat(ex.getMessage(), containsString("Error posting the request: Failed Request")); @@ -162,10 +145,10 @@ public void createSession_shouldWrapResourceException() throws Exception { public void createSession_shouldWrapIOException() throws Exception { IOException ioException = new IOException("Some io exception"); SessionSpec sessionSpecMock = mock(SessionSpec.class); - when(signedRequestBuilderMock.build()).thenReturn(signedRequestMock); - when(signedRequestMock.execute(CreateSessionResult.class)).thenThrow(ioException); + when(yotiHttpRequestBuilderMock.build()).thenReturn(yotiHttpRequestMock); + when(yotiHttpRequestMock.execute(CreateSessionResult.class)).thenThrow(ioException); - DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.createSession(SOME_APP_ID, KEY_PAIR, sessionSpecMock)); + DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.createSession(authStrategyMock, sessionSpecMock)); assertSame(ex.getCause(), ioException); assertThat(ex.getMessage(), containsString("Error building the request: Some io exception")); @@ -175,9 +158,9 @@ public void createSession_shouldWrapIOException() throws Exception { public void createSession_shouldWrapURISyntaxException() throws Exception { URISyntaxException uriSyntaxException = new URISyntaxException("someUrl", "Failed to build URI"); SessionSpec sessionSpecMock = mock(SessionSpec.class); - when(signedRequestBuilderMock.build()).thenThrow(uriSyntaxException); + when(yotiHttpRequestBuilderMock.build()).thenThrow(uriSyntaxException); - DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.createSession(SOME_APP_ID, KEY_PAIR, sessionSpecMock)); + DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.createSession(authStrategyMock, sessionSpecMock)); assertSame(ex.getCause(), uriSyntaxException); assertThat(ex.getMessage(), containsString("Error building the request: Failed to build URI: someUrl")); @@ -188,9 +171,9 @@ public void createSession_shouldWrapURISyntaxException() throws Exception { public void createSession_shouldWrapGeneralException() { Exception someException = new Exception("Some exception we weren't expecting"); SessionSpec sessionSpecMock = mock(SessionSpec.class); - doAnswer(i -> {throw someException;}).when(signedRequestBuilderFactoryMock).create(); + doAnswer(i -> {throw someException;}).when(yotiHttpRequestBuilderFactoryMock).create(); - DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.createSession(SOME_APP_ID, KEY_PAIR, sessionSpecMock)); + DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.createSession(authStrategyMock, sessionSpecMock)); assertSame(ex.getCause(), someException); assertThat(ex.getMessage(), containsString("Error creating the session: Some exception we weren't expecting")); @@ -201,52 +184,38 @@ public void createSession_shouldCallSignedRequestBuilderWithCorrectMethods() thr SessionSpec sessionSpecMock = mock(SessionSpec.class); CreateSessionResult createSessionResultMock = mock(CreateSessionResult.class); when(objectMapperMock.writeValueAsBytes(sessionSpecMock)).thenReturn(SOME_SESSION_SPEC_BYTES); - when(signedRequestBuilderMock.build()).thenReturn(signedRequestMock); - when(signedRequestMock.execute(CreateSessionResult.class)).thenReturn(createSessionResultMock); - when(unsignedPathFactoryMock.createNewYotiDocsSessionPath(SOME_APP_ID)).thenReturn(SOME_PATH); + when(yotiHttpRequestBuilderMock.build()).thenReturn(yotiHttpRequestMock); + when(yotiHttpRequestMock.execute(CreateSessionResult.class)).thenReturn(createSessionResultMock); + when(unsignedPathFactoryMock.createNewYotiDocsSessionPath()).thenReturn(SOME_PATH); - CreateSessionResult result = docScanService.createSession(SOME_APP_ID, KEY_PAIR, sessionSpecMock); + CreateSessionResult result = docScanService.createSession(authStrategyMock, sessionSpecMock); assertThat(result, is(createSessionResultMock)); - verify(signedRequestBuilderMock).withKeyPair(KEY_PAIR); - verify(signedRequestBuilderMock).withEndpoint(SOME_PATH); - verify(signedRequestBuilderMock).withBaseUrl(SOME_API_URL); - verify(signedRequestBuilderMock).withHttpMethod(HttpMethod.HTTP_POST); - verify(signedRequestBuilderMock).withPayload(SOME_SESSION_SPEC_BYTES); - verify(signedRequestBuilderMock).withHeader(CONTENT_TYPE, CONTENT_TYPE_JSON); - } - - @Test - public void retrieveSession_shouldThrowExceptionWhenAppIdIsNull() { - IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.retrieveSession(null, null, null)); - - assertThat(ex.getMessage(), containsString("SDK ID")); - } - - @Test - public void retrieveSession_shouldThrowExceptionWhenAppIdIsEmpty() { - IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.retrieveSession("", null, null)); - - assertThat(ex.getMessage(), containsString("SDK ID")); + verify(yotiHttpRequestBuilderMock).withAuthStrategy(authStrategyMock); + verify(yotiHttpRequestBuilderMock).withEndpoint(SOME_PATH); + verify(yotiHttpRequestBuilderMock).withBaseUrl(SOME_API_URL); + verify(yotiHttpRequestBuilderMock).withHttpMethod(HttpMethod.HTTP_POST); + verify(yotiHttpRequestBuilderMock).withPayload(SOME_SESSION_SPEC_BYTES); + verify(yotiHttpRequestBuilderMock).withHeader(CONTENT_TYPE, CONTENT_TYPE_JSON); } @Test - public void retrieveSession_shouldThrowExceptionWhenMissingKeyPair() { - IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.retrieveSession(SOME_APP_ID, null, null)); + public void retrieveSession_shouldThrowExceptionWhenMissingAuthStrategy() { + IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.retrieveSession(null, null)); - assertThat(ex.getMessage(), containsString("Application key Pair")); + assertThat(ex.getMessage(), containsString("'authStrategy' must not be null.")); } @Test public void retrieveSession_shouldThrowExceptionWhenSessionIdIsNull() { - IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.retrieveSession(SOME_APP_ID, KEY_PAIR, null)); + IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.retrieveSession(authStrategyMock, null)); assertThat(ex.getMessage(), containsString("sessionId")); } @Test public void retrieveSession_shouldThrowExceptionWhenSessionIdIsEmpty() { - IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.retrieveSession(SOME_APP_ID, KEY_PAIR, "")); + IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.retrieveSession(authStrategyMock, "")); assertThat(ex.getMessage(), containsString("sessionId")); } @@ -254,9 +223,9 @@ public void retrieveSession_shouldThrowExceptionWhenSessionIdIsEmpty() { @Test public void retrieveSession_shouldWrapGeneralSecurityException() throws Exception { GeneralSecurityException gse = new GeneralSecurityException("some gse"); - when(signedRequestBuilderMock.build()).thenThrow(gse); + when(yotiHttpRequestBuilderMock.build()).thenThrow(gse); - DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.retrieveSession(SOME_APP_ID, KEY_PAIR, SOME_SESSION_ID)); + DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.retrieveSession(authStrategyMock, SOME_SESSION_ID)); assertSame(ex.getCause(), gse); assertThat(ex.getMessage(), containsString("Error signing the request: some gse")); @@ -265,10 +234,10 @@ public void retrieveSession_shouldWrapGeneralSecurityException() throws Exceptio @Test public void retrieveSession_shouldWrapResourceException() throws Exception { ResourceException resourceException = new ResourceException(400, "Failed Request", "Some response from API"); - when(signedRequestBuilderMock.build()).thenReturn(signedRequestMock); - when(signedRequestMock.execute(GetSessionResult.class)).thenThrow(resourceException); + when(yotiHttpRequestBuilderMock.build()).thenReturn(yotiHttpRequestMock); + when(yotiHttpRequestMock.execute(GetSessionResult.class)).thenThrow(resourceException); - DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.retrieveSession(SOME_APP_ID, KEY_PAIR, SOME_SESSION_ID)); + DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.retrieveSession(authStrategyMock, SOME_SESSION_ID)); assertSame(ex.getCause(), resourceException); assertThat(ex.getMessage(), containsString("Error executing the GET: Failed Request")); @@ -277,10 +246,10 @@ public void retrieveSession_shouldWrapResourceException() throws Exception { @Test public void retrieveSession_shouldWrapIOException() throws Exception { IOException ioException = new IOException("Some io exception"); - when(signedRequestBuilderMock.build()).thenReturn(signedRequestMock); - when(signedRequestMock.execute(GetSessionResult.class)).thenThrow(ioException); + when(yotiHttpRequestBuilderMock.build()).thenReturn(yotiHttpRequestMock); + when(yotiHttpRequestMock.execute(GetSessionResult.class)).thenThrow(ioException); - DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.retrieveSession(SOME_APP_ID, KEY_PAIR, SOME_SESSION_ID)); + DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.retrieveSession(authStrategyMock, SOME_SESSION_ID)); assertSame(ex.getCause(), ioException); assertThat(ex.getMessage(), containsString("Error building the request: Some io exception")); @@ -289,9 +258,9 @@ public void retrieveSession_shouldWrapIOException() throws Exception { @Test public void retrieveSession_shouldWrapGeneralException() { Exception someException = new Exception("Some exception we weren't expecting"); - doAnswer(i -> {throw someException;}).when(signedRequestBuilderFactoryMock).create(); + doAnswer(i -> {throw someException;}).when(yotiHttpRequestBuilderFactoryMock).create(); - DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.retrieveSession(SOME_APP_ID, KEY_PAIR, SOME_SESSION_ID)); + DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.retrieveSession(authStrategyMock, SOME_SESSION_ID)); assertSame(ex.getCause(), someException); assertThat(ex.getMessage(), containsString("Error retrieving the session: Some exception we weren't expecting")); @@ -300,50 +269,36 @@ public void retrieveSession_shouldWrapGeneralException() { @Test public void retrieveSession_shouldCallSignedRequestBuilderWithCorrectMethods() throws Exception { GetSessionResult docScanSessionResponseMock = mock(GetSessionResult.class); - when(signedRequestBuilderMock.build()).thenReturn(signedRequestMock); - when(signedRequestMock.execute(GetSessionResult.class)).thenReturn(docScanSessionResponseMock); - when(unsignedPathFactoryMock.createYotiDocsSessionPath(SOME_APP_ID, SOME_SESSION_ID)).thenReturn(SOME_PATH); + when(yotiHttpRequestBuilderMock.build()).thenReturn(yotiHttpRequestMock); + when(yotiHttpRequestMock.execute(GetSessionResult.class)).thenReturn(docScanSessionResponseMock); + when(unsignedPathFactoryMock.createYotiDocsSessionPath(SOME_SESSION_ID)).thenReturn(SOME_PATH); - GetSessionResult result = docScanService.retrieveSession(SOME_APP_ID, KEY_PAIR, SOME_SESSION_ID); + GetSessionResult result = docScanService.retrieveSession(authStrategyMock, SOME_SESSION_ID); assertThat(result, is(docScanSessionResponseMock)); - verify(signedRequestBuilderMock).withKeyPair(KEY_PAIR); - verify(signedRequestBuilderMock).withEndpoint(SOME_PATH); - verify(signedRequestBuilderMock).withBaseUrl(SOME_API_URL); - verify(signedRequestBuilderMock).withHttpMethod(HttpMethod.HTTP_GET); - } - - @Test - public void deleteSession_shouldThrowExceptionWhenAppIdIsNull() { - IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.deleteSession(null, null, null)); - - assertThat(ex.getMessage(), containsString("SDK ID")); + verify(yotiHttpRequestBuilderMock).withAuthStrategy(authStrategyMock); + verify(yotiHttpRequestBuilderMock).withEndpoint(SOME_PATH); + verify(yotiHttpRequestBuilderMock).withBaseUrl(SOME_API_URL); + verify(yotiHttpRequestBuilderMock).withHttpMethod(HttpMethod.HTTP_GET); } @Test - public void deleteSession_shouldThrowExceptionWhenAppIdIsEmpty() { - IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.deleteSession("", null, null)); + public void deleteSession_shouldThrowExceptionWhenAuthStrategyIsNull() { + IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.deleteSession(null, null)); - assertThat(ex.getMessage(), containsString("SDK ID")); - } - - @Test - public void deleteSession_shouldThrowExceptionWhenKeyPairIsNull() { - IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.deleteSession(SOME_APP_ID, null, null)); - - assertThat(ex.getMessage(), containsString("Application key Pair")); + assertThat(ex.getMessage(), containsString("'authStrategy' must not be null.")); } @Test public void deleteSession_shouldThrowExceptionWhenSessionIdIsNull() { - IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.deleteSession(SOME_APP_ID, KEY_PAIR, null)); + IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.deleteSession(authStrategyMock, null)); assertThat(ex.getMessage(), containsString("sessionId")); } @Test public void deleteSession_shouldThrowExceptionWhenSessionIdIsEmpty() { - IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.deleteSession(SOME_APP_ID, KEY_PAIR, "")); + IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.deleteSession(authStrategyMock, "")); assertThat(ex.getMessage(), containsString("sessionId")); } @@ -351,9 +306,9 @@ public void deleteSession_shouldThrowExceptionWhenSessionIdIsEmpty() { @Test public void deleteSession_shouldWrapGeneralSecurityException() throws Exception { GeneralSecurityException gse = new GeneralSecurityException("some gse"); - when(signedRequestBuilderMock.build()).thenThrow(gse); + when(yotiHttpRequestBuilderMock.build()).thenThrow(gse); - DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.deleteSession(SOME_APP_ID, KEY_PAIR, SOME_SESSION_ID)); + DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.deleteSession(authStrategyMock, SOME_SESSION_ID)); assertSame(ex.getCause(), gse); assertThat(ex.getMessage(), containsString("Error signing the request: some gse")); @@ -362,10 +317,10 @@ public void deleteSession_shouldWrapGeneralSecurityException() throws Exception @Test public void deleteSession_shouldWrapResourceException() throws Exception { ResourceException resourceException = new ResourceException(400, "Failed Request", "Some response from API"); - when(signedRequestBuilderMock.build()).thenReturn(signedRequestMock); - when(signedRequestMock.execute()).thenThrow(resourceException); + when(yotiHttpRequestBuilderMock.build()).thenReturn(yotiHttpRequestMock); + when(yotiHttpRequestMock.execute()).thenThrow(resourceException); - DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.deleteSession(SOME_APP_ID, KEY_PAIR, SOME_SESSION_ID)); + DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.deleteSession(authStrategyMock, SOME_SESSION_ID)); assertSame(ex.getCause(), resourceException); assertThat(ex.getMessage(), containsString("Error executing the DELETE: Failed Request")); @@ -374,10 +329,10 @@ public void deleteSession_shouldWrapResourceException() throws Exception { @Test public void deleteSession_shouldWrapIOException() throws Exception { IOException ioException = new IOException("Some io exception"); - when(signedRequestBuilderMock.build()).thenReturn(signedRequestMock); - when(signedRequestMock.execute()).thenThrow(ioException); + when(yotiHttpRequestBuilderMock.build()).thenReturn(yotiHttpRequestMock); + when(yotiHttpRequestMock.execute()).thenThrow(ioException); - DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.deleteSession(SOME_APP_ID, KEY_PAIR, SOME_SESSION_ID)); + DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.deleteSession(authStrategyMock, SOME_SESSION_ID)); assertSame(ex.getCause(), ioException); assertThat(ex.getMessage(), containsString("Error building the request: Some io exception")); @@ -386,9 +341,9 @@ public void deleteSession_shouldWrapIOException() throws Exception { @Test public void deleteSession_shouldWrapGeneralException() { Exception someException = new Exception("Some exception we weren't expecting"); - doAnswer(i -> {throw someException;}).when(signedRequestBuilderFactoryMock).create(); + doAnswer(i -> {throw someException;}).when(yotiHttpRequestBuilderFactoryMock).create(); - DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.deleteSession(SOME_APP_ID, KEY_PAIR, SOME_SESSION_ID)); + DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.deleteSession(authStrategyMock, SOME_SESSION_ID)); assertSame(ex.getCause(), someException); assertThat(ex.getMessage(), containsString("Error deleting the session: Some exception we weren't expecting")); @@ -396,62 +351,48 @@ public void deleteSession_shouldWrapGeneralException() { @Test public void deleteSession_shouldBuildSignedRequest() throws Exception { - when(signedRequestBuilderMock.build()).thenReturn(signedRequestMock); - when(unsignedPathFactoryMock.createYotiDocsSessionPath(SOME_APP_ID, SOME_SESSION_ID)).thenReturn(SOME_PATH); - - docScanService.deleteSession(SOME_APP_ID, KEY_PAIR, SOME_SESSION_ID); - - verify(signedRequestBuilderMock).withKeyPair(KEY_PAIR); - verify(signedRequestBuilderMock).withEndpoint(SOME_PATH); - verify(signedRequestBuilderMock).withBaseUrl(SOME_API_URL); - verify(signedRequestBuilderMock).withHttpMethod(HttpMethod.HTTP_DELETE); - } - - @Test - public void getMediaContent_shouldThrowExceptionWhenApplicationIdIsNull() { - IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.getMediaContent(null, null, null, null)); - - assertThat(ex.getMessage(), containsString("SDK ID")); - } + when(yotiHttpRequestBuilderMock.build()).thenReturn(yotiHttpRequestMock); + when(unsignedPathFactoryMock.createYotiDocsSessionPath(SOME_SESSION_ID)).thenReturn(SOME_PATH); - @Test - public void getMediaContent_shouldThrowExceptionWhenApplicationIdIsEmpty() { - IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.getMediaContent("", null, null, null)); + docScanService.deleteSession(authStrategyMock, SOME_SESSION_ID); - assertThat(ex.getMessage(), containsString("SDK ID")); + verify(yotiHttpRequestBuilderMock).withAuthStrategy(authStrategyMock); + verify(yotiHttpRequestBuilderMock).withEndpoint(SOME_PATH); + verify(yotiHttpRequestBuilderMock).withBaseUrl(SOME_API_URL); + verify(yotiHttpRequestBuilderMock).withHttpMethod(HttpMethod.HTTP_DELETE); } @Test - public void getMediaContent_shouldThrowExceptionWhenKeyPairIsNull() { - IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.getMediaContent(SOME_APP_ID, null, null, null)); + public void getMediaContent_shouldThrowExceptionWhenAuthStrategyIsNull() { + IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.getMediaContent(null, null, null)); - assertThat(ex.getMessage(), containsString("Application key Pair")); + assertThat(ex.getMessage(), containsString("'authStrategy' must not be null.")); } @Test public void getMediaContent_shouldThrowExceptionWhenSessionIdIsNull() { - IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.getMediaContent(SOME_APP_ID, KEY_PAIR, null, null)); + IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.getMediaContent(authStrategyMock, null, null)); assertThat(ex.getMessage(), containsString("sessionId")); } @Test public void getMediaContent_shouldThrowExceptionWhenSessionIdIsEmpty() { - IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.getMediaContent(SOME_APP_ID, KEY_PAIR, "", null)); + IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.getMediaContent(authStrategyMock, "", null)); assertThat(ex.getMessage(), containsString("sessionId")); } @Test public void getMediaContent_shouldThrowExceptionWhenMediaIdIsNull() { - IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.getMediaContent(SOME_APP_ID, KEY_PAIR, SOME_SESSION_ID, null)); + IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.getMediaContent(authStrategyMock, SOME_SESSION_ID, null)); assertThat(ex.getMessage(), containsString("mediaId")); } @Test public void getMediaContent_shouldThrowExceptionWhenMediaIdIsEmpty() { - IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.getMediaContent(SOME_APP_ID, KEY_PAIR, SOME_SESSION_ID, "")); + IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.getMediaContent(authStrategyMock, SOME_SESSION_ID, "")); assertThat(ex.getMessage(), containsString("mediaId")); } @@ -459,9 +400,9 @@ public void getMediaContent_shouldThrowExceptionWhenMediaIdIsEmpty() { @Test public void getMediaContent_shouldWrapGeneralSecurityException() throws Exception { GeneralSecurityException gse = new GeneralSecurityException("some gse"); - when(signedRequestBuilderMock.build()).thenThrow(gse); + when(yotiHttpRequestBuilderMock.build()).thenThrow(gse); - DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.getMediaContent(SOME_APP_ID, KEY_PAIR, SOME_SESSION_ID, SOME_MEDIA_ID)); + DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.getMediaContent(authStrategyMock, SOME_SESSION_ID, SOME_MEDIA_ID)); assertSame(ex.getCause(), gse); assertThat(ex.getMessage(), containsString("Error signing the request: some gse")); @@ -470,10 +411,10 @@ public void getMediaContent_shouldWrapGeneralSecurityException() throws Exceptio @Test public void getMediaContent_shouldWrapResourceException() throws Exception { ResourceException resourceException = new ResourceException(400, "Failed Request", "Some response from API"); - when(signedRequestBuilderMock.build()).thenReturn(signedRequestMock); - when(signedRequestMock.execute()).thenThrow(resourceException); + when(yotiHttpRequestBuilderMock.build()).thenReturn(yotiHttpRequestMock); + when(yotiHttpRequestMock.execute()).thenThrow(resourceException); - DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.getMediaContent(SOME_APP_ID, KEY_PAIR, SOME_SESSION_ID, SOME_MEDIA_ID)); + DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.getMediaContent(authStrategyMock, SOME_SESSION_ID, SOME_MEDIA_ID)); assertSame(ex.getCause(), resourceException); assertThat(ex.getMessage(), containsString("Error executing the GET: Failed Request")); @@ -482,10 +423,10 @@ public void getMediaContent_shouldWrapResourceException() throws Exception { @Test public void getMediaContent_shouldWrapIOException() throws Exception { IOException ioException = new IOException("Some io exception"); - when(signedRequestBuilderMock.build()).thenReturn(signedRequestMock); - when(signedRequestMock.execute()).thenThrow(ioException); + when(yotiHttpRequestBuilderMock.build()).thenReturn(yotiHttpRequestMock); + when(yotiHttpRequestMock.execute()).thenThrow(ioException); - DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.getMediaContent(SOME_APP_ID, KEY_PAIR, SOME_SESSION_ID, SOME_MEDIA_ID)); + DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.getMediaContent(authStrategyMock, SOME_SESSION_ID, SOME_MEDIA_ID)); assertSame(ex.getCause(), ioException); assertThat(ex.getMessage(), containsString("Error building the request: Some io exception")); @@ -494,9 +435,9 @@ public void getMediaContent_shouldWrapIOException() throws Exception { @Test public void getMediaContent_shouldWrapURISyntaxException() throws Exception { URISyntaxException uriSyntaxException = new URISyntaxException("someUrl", "Failed to build URI"); - when(signedRequestBuilderMock.build()).thenThrow(uriSyntaxException); + when(yotiHttpRequestBuilderMock.build()).thenThrow(uriSyntaxException); - DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.getMediaContent(SOME_APP_ID, KEY_PAIR, SOME_SESSION_ID, SOME_MEDIA_ID)); + DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.getMediaContent(authStrategyMock, SOME_SESSION_ID, SOME_MEDIA_ID)); assertSame(ex.getCause(), uriSyntaxException); assertThat(ex.getMessage(), containsString("Error building the request: Failed to build URI: someUrl")); @@ -504,28 +445,28 @@ public void getMediaContent_shouldWrapURISyntaxException() throws Exception { @Test public void getMediaContent_shouldBuildSignedRequest() throws Exception { - when(signedRequestBuilderMock.build()).thenReturn(signedRequestMock); - SignedRequestResponse signedRequestResponseMock = mock(SignedRequestResponse.class, RETURNS_DEEP_STUBS); - when(signedRequestMock.execute()).thenReturn(signedRequestResponseMock); - when(unsignedPathFactoryMock.createMediaContentPath(SOME_APP_ID, SOME_SESSION_ID, SOME_MEDIA_ID)).thenReturn(SOME_PATH); + when(yotiHttpRequestBuilderMock.build()).thenReturn(yotiHttpRequestMock); + YotiHttpResponse yotiHttpResponseMock = mock(YotiHttpResponse.class, RETURNS_DEEP_STUBS); + when(yotiHttpRequestMock.execute()).thenReturn(yotiHttpResponseMock); + when(unsignedPathFactoryMock.createMediaContentPath(SOME_SESSION_ID, SOME_MEDIA_ID)).thenReturn(SOME_PATH); - docScanService.getMediaContent(SOME_APP_ID, KEY_PAIR, SOME_SESSION_ID, SOME_MEDIA_ID); + docScanService.getMediaContent(authStrategyMock, SOME_SESSION_ID, SOME_MEDIA_ID); - verify(signedRequestBuilderMock).withKeyPair(KEY_PAIR); - verify(signedRequestBuilderMock).withEndpoint(SOME_PATH); - verify(signedRequestBuilderMock).withBaseUrl(SOME_API_URL); - verify(signedRequestBuilderMock).withHttpMethod(HttpMethod.HTTP_GET); + verify(yotiHttpRequestBuilderMock).withAuthStrategy(authStrategyMock); + verify(yotiHttpRequestBuilderMock).withEndpoint(SOME_PATH); + verify(yotiHttpRequestBuilderMock).withBaseUrl(SOME_API_URL); + verify(yotiHttpRequestBuilderMock).withHttpMethod(HttpMethod.HTTP_GET); } @Test public void getMediaContent_shouldReturnMedia() throws Exception { - when(signedRequestBuilderMock.build()).thenReturn(signedRequestMock); - when(signedRequestMock.execute()).thenReturn(signedRequestResponseMock); - when(signedRequestResponseMock.getResponseHeaders()).thenReturn(createHeadersMap(CONTENT_TYPE, CONTENT_TYPE_JSON)); - when(signedRequestResponseMock.getResponseBody()).thenReturn(IMAGE_BODY); - when(unsignedPathFactoryMock.createMediaContentPath(SOME_APP_ID, SOME_SESSION_ID, SOME_MEDIA_ID)).thenReturn(SOME_PATH); + when(yotiHttpRequestBuilderMock.build()).thenReturn(yotiHttpRequestMock); + when(yotiHttpRequestMock.execute()).thenReturn(yotiHttpResponseMock); + when(yotiHttpResponseMock.getResponseHeaders()).thenReturn(createHeadersMap(CONTENT_TYPE, CONTENT_TYPE_JSON)); + when(yotiHttpResponseMock.getResponseBody()).thenReturn(IMAGE_BODY); + when(unsignedPathFactoryMock.createMediaContentPath(SOME_SESSION_ID, SOME_MEDIA_ID)).thenReturn(SOME_PATH); - Media result = docScanService.getMediaContent(SOME_APP_ID, KEY_PAIR, SOME_SESSION_ID, SOME_MEDIA_ID); + Media result = docScanService.getMediaContent(authStrategyMock, SOME_SESSION_ID, SOME_MEDIA_ID); assertThat(result.getMimeType(), is(CONTENT_TYPE_JSON)); assertThat(result.getContent(), is(IMAGE_BODY)); @@ -533,25 +474,25 @@ public void getMediaContent_shouldReturnMedia() throws Exception { @Test public void getMediaContent_shouldReturnNullForNoContent() throws Exception { - when(signedRequestBuilderMock.build()).thenReturn(signedRequestMock); - when(signedRequestMock.execute()).thenReturn(signedRequestResponseMock); - when(signedRequestResponseMock.getResponseCode()).thenReturn(204); - when(unsignedPathFactoryMock.createMediaContentPath(SOME_APP_ID, SOME_SESSION_ID, SOME_MEDIA_ID)).thenReturn(SOME_PATH); + when(yotiHttpRequestBuilderMock.build()).thenReturn(yotiHttpRequestMock); + when(yotiHttpRequestMock.execute()).thenReturn(yotiHttpResponseMock); + when(yotiHttpResponseMock.getResponseCode()).thenReturn(204); + when(unsignedPathFactoryMock.createMediaContentPath(SOME_SESSION_ID, SOME_MEDIA_ID)).thenReturn(SOME_PATH); - Media result = docScanService.getMediaContent(SOME_APP_ID, KEY_PAIR, SOME_SESSION_ID, SOME_MEDIA_ID); + Media result = docScanService.getMediaContent(authStrategyMock, SOME_SESSION_ID, SOME_MEDIA_ID); assertThat(result, is(nullValue())); } @Test public void getMediaContent_shouldNotBeCaseSensitive() throws Exception { - when(signedRequestBuilderMock.build()).thenReturn(signedRequestMock); - when(signedRequestMock.execute()).thenReturn(signedRequestResponseMock); - when(signedRequestResponseMock.getResponseHeaders()).thenReturn(createHeadersMap("content-type", "image/png")); - when(signedRequestResponseMock.getResponseBody()).thenReturn(IMAGE_BODY); - when(unsignedPathFactoryMock.createMediaContentPath(SOME_APP_ID, SOME_SESSION_ID, SOME_MEDIA_ID)).thenReturn(SOME_PATH); + when(yotiHttpRequestBuilderMock.build()).thenReturn(yotiHttpRequestMock); + when(yotiHttpRequestMock.execute()).thenReturn(yotiHttpResponseMock); + when(yotiHttpResponseMock.getResponseHeaders()).thenReturn(createHeadersMap("content-type", "image/png")); + when(yotiHttpResponseMock.getResponseBody()).thenReturn(IMAGE_BODY); + when(unsignedPathFactoryMock.createMediaContentPath(SOME_SESSION_ID, SOME_MEDIA_ID)).thenReturn(SOME_PATH); - Media result = docScanService.getMediaContent(SOME_APP_ID, KEY_PAIR, SOME_SESSION_ID, SOME_MEDIA_ID); + Media result = docScanService.getMediaContent(authStrategyMock, SOME_SESSION_ID, SOME_MEDIA_ID); assertThat(result.getMimeType(), is("image/png")); assertThat(result.getContent(), is(IMAGE_BODY)); @@ -564,50 +505,36 @@ private Map> createHeadersMap(String key, String value) { } @Test - public void deleteMediaContent_shouldThrowExceptionWhenApplicationIdIsNull() { - IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.deleteMediaContent(null, null, null, null)); - - assertThat(ex.getMessage(), containsString("SDK ID")); - } - - @Test - public void deleteMediaContent_shouldThrowExceptionWhenApplicationIdIsEmpty() { - IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.deleteMediaContent("", null, null, null)); + public void deleteMediaContent_shouldThrowExceptionWhenAuthStrategyIsNull() { + IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.deleteMediaContent(null, null, null)); - assertThat(ex.getMessage(), containsString("SDK ID")); - } - - @Test - public void deleteMediaContent_shouldThrowExceptionWhenKeyPairIsNull() { - IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.deleteMediaContent(SOME_APP_ID, null, null, null)); - - assertThat(ex.getMessage(), containsString("Application key Pair")); + assertThat(ex.getMessage(), containsString("'authStrategy' must not be null.")); } @Test public void deleteMediaContent_shouldThrowExceptionWhenSessionIdIsNull() { - IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.deleteMediaContent(SOME_APP_ID, KEY_PAIR, null, null)); + IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.deleteMediaContent(authStrategyMock, null, null)); assertThat(ex.getMessage(), containsString("sessionId")); } @Test public void deleteMediaContent_shouldThrowExceptionWhenSessionIdIsEmpty() { - IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.deleteMediaContent(SOME_APP_ID, KEY_PAIR, "", null)); + IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.deleteMediaContent(authStrategyMock, "", null)); assertThat(ex.getMessage(), containsString("sessionId")); } @Test public void deleteMediaContent_shouldThrowExceptionWhenMediaIdIsNull() { - IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.deleteMediaContent(SOME_APP_ID, KEY_PAIR, SOME_SESSION_ID, null)); + IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.deleteMediaContent(authStrategyMock, SOME_SESSION_ID, null)); assertThat(ex.getMessage(), containsString("mediaId")); } @Test public void deleteMediaContent_shouldThrowExceptionWhenMediaIdIsEmpty() { - IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.deleteMediaContent(SOME_APP_ID, KEY_PAIR, SOME_SESSION_ID, "")); + IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.deleteMediaContent(authStrategyMock, SOME_SESSION_ID, "")); assertThat(ex.getMessage(), containsString("mediaId")); } @@ -615,9 +542,9 @@ public void deleteMediaContent_shouldThrowExceptionWhenMediaIdIsEmpty() { @Test public void deleteMediaContent_shouldWrapGeneralSecurityException() throws Exception { GeneralSecurityException gse = new GeneralSecurityException("some gse"); - when(signedRequestBuilderMock.build()).thenThrow(gse); + when(yotiHttpRequestBuilderMock.build()).thenThrow(gse); - DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.deleteMediaContent(SOME_APP_ID, KEY_PAIR, SOME_SESSION_ID, SOME_MEDIA_ID)); + DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.deleteMediaContent(authStrategyMock, SOME_SESSION_ID, SOME_MEDIA_ID)); assertSame(ex.getCause(), gse); assertThat(ex.getMessage(), containsString("Error signing the request: some gse")); @@ -626,10 +553,10 @@ public void deleteMediaContent_shouldWrapGeneralSecurityException() throws Excep @Test public void deleteMediaContent_shouldWrapResourceException() throws Exception { ResourceException resourceException = new ResourceException(400, "Failed Request", "Some response from API"); - when(signedRequestBuilderMock.build()).thenReturn(signedRequestMock); - when(signedRequestMock.execute()).thenThrow(resourceException); + when(yotiHttpRequestBuilderMock.build()).thenReturn(yotiHttpRequestMock); + when(yotiHttpRequestMock.execute()).thenThrow(resourceException); - DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.deleteMediaContent(SOME_APP_ID, KEY_PAIR, SOME_SESSION_ID, SOME_MEDIA_ID)); + DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.deleteMediaContent(authStrategyMock, SOME_SESSION_ID, SOME_MEDIA_ID)); assertSame(ex.getCause(), resourceException); assertThat(ex.getMessage(), containsString("Error executing the DELETE: Failed Request")); @@ -638,10 +565,10 @@ public void deleteMediaContent_shouldWrapResourceException() throws Exception { @Test public void deleteMediaContent_shouldWrapIOException() throws Exception { IOException ioException = new IOException("Some io exception"); - when(signedRequestBuilderMock.build()).thenReturn(signedRequestMock); - when(signedRequestMock.execute()).thenThrow(ioException); + when(yotiHttpRequestBuilderMock.build()).thenReturn(yotiHttpRequestMock); + when(yotiHttpRequestMock.execute()).thenThrow(ioException); - DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.deleteMediaContent(SOME_APP_ID, KEY_PAIR, SOME_SESSION_ID, SOME_MEDIA_ID)); + DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.deleteMediaContent(authStrategyMock, SOME_SESSION_ID, SOME_MEDIA_ID)); assertSame(ex.getCause(), ioException); assertThat(ex.getMessage(), containsString("Error building the request: Some io exception")); @@ -650,9 +577,9 @@ public void deleteMediaContent_shouldWrapIOException() throws Exception { @Test public void deleteMediaContent_shouldWrapURISyntaxException() throws Exception { URISyntaxException uriSyntaxException = new URISyntaxException("someUrl", "Failed to build URI"); - when(signedRequestBuilderMock.build()).thenThrow(uriSyntaxException); + when(yotiHttpRequestBuilderMock.build()).thenThrow(uriSyntaxException); - DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.deleteMediaContent(SOME_APP_ID, KEY_PAIR, SOME_SESSION_ID, SOME_MEDIA_ID)); + DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.deleteMediaContent(authStrategyMock, SOME_SESSION_ID, SOME_MEDIA_ID)); assertSame(ex.getCause(), uriSyntaxException); assertThat(ex.getMessage(), containsString("Error building the request: Failed to build URI: someUrl")); @@ -660,15 +587,15 @@ public void deleteMediaContent_shouldWrapURISyntaxException() throws Exception { @Test public void deleteMediaContent_shouldBuildSignedRequest() throws Exception { - when(signedRequestBuilderMock.build()).thenReturn(signedRequestMock); - when(unsignedPathFactoryMock.createMediaContentPath(SOME_APP_ID, SOME_SESSION_ID, SOME_MEDIA_ID)).thenReturn(SOME_PATH); + when(yotiHttpRequestBuilderMock.build()).thenReturn(yotiHttpRequestMock); + when(unsignedPathFactoryMock.createMediaContentPath(SOME_SESSION_ID, SOME_MEDIA_ID)).thenReturn(SOME_PATH); - docScanService.deleteMediaContent(SOME_APP_ID, KEY_PAIR, SOME_SESSION_ID, SOME_MEDIA_ID); + docScanService.deleteMediaContent(authStrategyMock, SOME_SESSION_ID, SOME_MEDIA_ID); - verify(signedRequestBuilderMock).withKeyPair(KEY_PAIR); - verify(signedRequestBuilderMock).withEndpoint(SOME_PATH); - verify(signedRequestBuilderMock).withBaseUrl(SOME_API_URL); - verify(signedRequestBuilderMock).withHttpMethod(HttpMethod.HTTP_DELETE); + verify(yotiHttpRequestBuilderMock).withAuthStrategy(authStrategyMock); + verify(yotiHttpRequestBuilderMock).withEndpoint(SOME_PATH); + verify(yotiHttpRequestBuilderMock).withBaseUrl(SOME_API_URL); + verify(yotiHttpRequestBuilderMock).withHttpMethod(HttpMethod.HTTP_DELETE); } @Test @@ -694,43 +621,29 @@ public void shouldNotFailForUnknownChecks() throws Exception { } @Test - public void putIbvInstructions_shouldThrowExceptionWhenSdkIdIsNull() { - IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.putIbvInstructions(null, KEY_PAIR, SOME_SESSION_ID, instructionsMock)); - - assertThat(ex.getMessage(), containsString("SDK ID")); - } - - @Test - public void putIbvInstructions_shouldThrowExceptionWhenSdkIdIsEmpty() { - IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.putIbvInstructions("", KEY_PAIR, SOME_SESSION_ID, instructionsMock)); - - assertThat(ex.getMessage(), containsString("SDK ID")); - } - - @Test - public void putIbvInstructions_shouldThrowExceptionWhenKeyPairIsNull() { - IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.putIbvInstructions(SOME_APP_ID, null, SOME_SESSION_ID, instructionsMock)); + public void putIbvInstructions_shouldThrowExceptionWhenAuthStrategyIsNull() { + IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.putIbvInstructions(null, SOME_SESSION_ID, instructionsMock)); - assertThat(ex.getMessage(), containsString("Application key Pair")); + assertThat(ex.getMessage(), containsString("'authStrategy' must not be null.")); } @Test public void putIbvInstructions_shouldThrowExceptionWhenSessionIdIsNull() { - IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.putIbvInstructions(SOME_APP_ID, KEY_PAIR, null, instructionsMock)); + IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.putIbvInstructions(authStrategyMock, null, instructionsMock)); assertThat(ex.getMessage(), containsString("sessionId")); } @Test public void putIbvInstructions_shouldThrowExceptionWhenSessionIdIsEmpty() { - IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.putIbvInstructions(SOME_APP_ID, KEY_PAIR, "", instructionsMock)); + IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.putIbvInstructions(authStrategyMock, "", instructionsMock)); assertThat(ex.getMessage(), containsString("sessionId")); } @Test public void putIbvInstructions_shouldThrowExceptionWhenInstructionsIsNull() { - IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.putIbvInstructions(SOME_APP_ID, KEY_PAIR, SOME_SESSION_ID, null)); + IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.putIbvInstructions(authStrategyMock, SOME_SESSION_ID, null)); assertThat(ex.getMessage(), containsString("instructions")); } @@ -738,9 +651,9 @@ public void putIbvInstructions_shouldThrowExceptionWhenInstructionsIsNull() { @Test public void putIbvInstructions_shouldWrapGeneralSecurityException() throws Exception { GeneralSecurityException gse = new GeneralSecurityException("some gse"); - when(signedRequestBuilderMock.build()).thenThrow(gse); + when(yotiHttpRequestBuilderMock.build()).thenThrow(gse); - DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.putIbvInstructions(SOME_APP_ID, KEY_PAIR, SOME_SESSION_ID, instructionsMock)); + DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.putIbvInstructions(authStrategyMock, SOME_SESSION_ID, instructionsMock)); assertThat(ex.getMessage(), containsString("Error signing the request: some gse")); } @@ -748,10 +661,10 @@ public void putIbvInstructions_shouldWrapGeneralSecurityException() throws Excep @Test public void putIbvInstructions_shouldWrapResourceException() throws Exception { ResourceException resourceException = new ResourceException(400, "Failed Request", "Some response from API"); - when(signedRequestBuilderMock.build()).thenReturn(signedRequestMock); - when(signedRequestMock.execute()).thenThrow(resourceException); + when(yotiHttpRequestBuilderMock.build()).thenReturn(yotiHttpRequestMock); + when(yotiHttpRequestMock.execute()).thenThrow(resourceException); - DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.putIbvInstructions(SOME_APP_ID, KEY_PAIR, SOME_SESSION_ID, instructionsMock)); + DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.putIbvInstructions(authStrategyMock, SOME_SESSION_ID, instructionsMock)); assertThat(ex.getMessage(), containsString("Error executing the PUT: Failed Request")); } @@ -759,10 +672,10 @@ public void putIbvInstructions_shouldWrapResourceException() throws Exception { @Test public void putIbvInstructions_shouldWrapIOException() throws Exception { IOException ioException = new IOException("Some io exception"); - when(signedRequestBuilderMock.build()).thenReturn(signedRequestMock); - when(signedRequestMock.execute()).thenThrow(ioException); + when(yotiHttpRequestBuilderMock.build()).thenReturn(yotiHttpRequestMock); + when(yotiHttpRequestMock.execute()).thenThrow(ioException); - DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.putIbvInstructions(SOME_APP_ID, KEY_PAIR, SOME_SESSION_ID, instructionsMock)); + DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.putIbvInstructions(authStrategyMock, SOME_SESSION_ID, instructionsMock)); assertThat(ex.getMessage(), containsString("Error building the request: Some io exception")); } @@ -770,44 +683,30 @@ public void putIbvInstructions_shouldWrapIOException() throws Exception { @Test public void putIbvInstructions_shouldWrapURISyntaxException() throws Exception { URISyntaxException uriSyntaxException = new URISyntaxException("someUrl", "Failed to build URI"); - when(signedRequestBuilderMock.build()).thenThrow(uriSyntaxException); + when(yotiHttpRequestBuilderMock.build()).thenThrow(uriSyntaxException); - DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.putIbvInstructions(SOME_APP_ID, KEY_PAIR, SOME_SESSION_ID, instructionsMock)); + DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.putIbvInstructions(authStrategyMock, SOME_SESSION_ID, instructionsMock)); assertThat(ex.getMessage(), containsString("Error building the request: Failed to build URI: someUrl")); } @Test - public void getIbvInstructions_shouldThrowExceptionWhenSdkIdIsNull() { - IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.getIbvInstructions(null, KEY_PAIR, SOME_SESSION_ID)); - - assertThat(ex.getMessage(), containsString("SDK ID")); - } - - @Test - public void getIbvInstructions_shouldThrowExceptionWhenSdkIdIsEmpty() { - IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.getIbvInstructions("", KEY_PAIR, SOME_SESSION_ID)); + public void getIbvInstructions_shouldThrowExceptionWhenAuthStrategyIsNull() { + IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.getIbvInstructions(null, SOME_SESSION_ID)); - assertThat(ex.getMessage(), containsString("SDK ID")); - } - - @Test - public void getIbvInstructions_shouldThrowExceptionWhenKeyPairIsNull() { - IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.getIbvInstructions(SOME_APP_ID, null, SOME_SESSION_ID)); - - assertThat(ex.getMessage(), containsString("Application key Pair")); + assertThat(ex.getMessage(), containsString("'authStrategy' must not be null.")); } @Test public void getIbvInstructions_shouldThrowExceptionWhenSessionIdIsNull() { - IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.getIbvInstructions(SOME_APP_ID, KEY_PAIR, null)); + IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.getIbvInstructions(authStrategyMock, null)); assertThat(ex.getMessage(), containsString("sessionId")); } @Test public void getIbvInstructions_shouldThrowExceptionWhenSessionIdIsEmpty() { - IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.getIbvInstructions(SOME_APP_ID, KEY_PAIR, "")); + IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.getIbvInstructions(authStrategyMock, "")); assertThat(ex.getMessage(), containsString("sessionId")); } @@ -815,9 +714,9 @@ public void getIbvInstructions_shouldThrowExceptionWhenSessionIdIsEmpty() { @Test public void getIbvInstructions_shouldWrapGeneralSecurityException() throws Exception { GeneralSecurityException gse = new GeneralSecurityException("some gse"); - when(signedRequestBuilderMock.build()).thenThrow(gse); + when(yotiHttpRequestBuilderMock.build()).thenThrow(gse); - DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.getIbvInstructions(SOME_APP_ID, KEY_PAIR, SOME_SESSION_ID)); + DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.getIbvInstructions(authStrategyMock, SOME_SESSION_ID)); assertThat(ex.getMessage(), containsString("Error signing the request: some gse")); } @@ -825,10 +724,10 @@ public void getIbvInstructions_shouldWrapGeneralSecurityException() throws Excep @Test public void getIbvInstructions_shouldWrapResourceException() throws Exception { ResourceException resourceException = new ResourceException(400, "Failed Request", "Some response from API"); - when(signedRequestBuilderMock.build()).thenReturn(signedRequestMock); - when(signedRequestMock.execute(InstructionsResponse.class)).thenThrow(resourceException); + when(yotiHttpRequestBuilderMock.build()).thenReturn(yotiHttpRequestMock); + when(yotiHttpRequestMock.execute(InstructionsResponse.class)).thenThrow(resourceException); - DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.getIbvInstructions(SOME_APP_ID, KEY_PAIR, SOME_SESSION_ID)); + DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.getIbvInstructions(authStrategyMock, SOME_SESSION_ID)); assertThat(ex.getMessage(), containsString("Error executing the GET: Failed Request")); } @@ -836,10 +735,10 @@ public void getIbvInstructions_shouldWrapResourceException() throws Exception { @Test public void getIbvInstructions_shouldWrapIOException() throws Exception { IOException ioException = new IOException("Some io exception"); - when(signedRequestBuilderMock.build()).thenReturn(signedRequestMock); - when(signedRequestMock.execute(InstructionsResponse.class)).thenThrow(ioException); + when(yotiHttpRequestBuilderMock.build()).thenReturn(yotiHttpRequestMock); + when(yotiHttpRequestMock.execute(InstructionsResponse.class)).thenThrow(ioException); - DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.getIbvInstructions(SOME_APP_ID, KEY_PAIR, SOME_SESSION_ID)); + DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.getIbvInstructions(authStrategyMock, SOME_SESSION_ID)); assertThat(ex.getMessage(), containsString("Error building the request: Some io exception")); } @@ -847,44 +746,32 @@ public void getIbvInstructions_shouldWrapIOException() throws Exception { @Test public void getIbvInstructions_shouldWrapURISyntaxException() throws Exception { URISyntaxException uriSyntaxException = new URISyntaxException("someUrl", "Failed to build URI"); - when(signedRequestBuilderMock.build()).thenThrow(uriSyntaxException); + when(yotiHttpRequestBuilderMock.build()).thenThrow(uriSyntaxException); - DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.getIbvInstructions(SOME_APP_ID, KEY_PAIR, SOME_SESSION_ID)); + DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.getIbvInstructions(authStrategyMock, SOME_SESSION_ID)); assertThat(ex.getMessage(), containsString("Error building the request: Failed to build URI: someUrl")); } @Test - public void getIbvInstructionsPdf_shouldThrowExceptionWhenSdkIdIsNull() { - IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.getIbvInstructionsPdf(null, KEY_PAIR, SOME_SESSION_ID)); - - assertThat(ex.getMessage(), containsString("SDK ID")); - } - - @Test - public void getIbvInstructionsPdf_shouldThrowExceptionWhenSdkIdIsEmpty() { - IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.getIbvInstructionsPdf("", KEY_PAIR, SOME_SESSION_ID)); + public void getIbvInstructionsPdf_shouldThrowExceptionWhenAuthStrategyIsNull() { + IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.getIbvInstructionsPdf(null, SOME_SESSION_ID)); - assertThat(ex.getMessage(), containsString("SDK ID")); - } - - @Test - public void getIbvInstructionsPdf_shouldThrowExceptionWhenKeyPairIsNull() { - IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.getIbvInstructionsPdf(SOME_APP_ID, null, SOME_SESSION_ID)); - - assertThat(ex.getMessage(), containsString("Application key Pair")); + assertThat(ex.getMessage(), containsString("'authStrategy' must not be null.")); } @Test public void getIbvInstructionsPdf_shouldThrowExceptionWhenSessionIdIsNull() { - IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.getIbvInstructionsPdf(SOME_APP_ID, KEY_PAIR, null)); + IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.getIbvInstructionsPdf( + authStrategyMock, null)); assertThat(ex.getMessage(), containsString("sessionId")); } @Test public void getIbvInstructionsPdf_shouldThrowExceptionWhenSessionIdIsEmpty() { - IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.getIbvInstructionsPdf(SOME_APP_ID, KEY_PAIR, "")); + IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.getIbvInstructionsPdf( + authStrategyMock, "")); assertThat(ex.getMessage(), containsString("sessionId")); } @@ -892,9 +779,9 @@ public void getIbvInstructionsPdf_shouldThrowExceptionWhenSessionIdIsEmpty() { @Test public void getIbvInstructionsPdf_shouldWrapGeneralSecurityException() throws Exception { GeneralSecurityException gse = new GeneralSecurityException("some gse"); - when(signedRequestBuilderMock.build()).thenThrow(gse); + when(yotiHttpRequestBuilderMock.build()).thenThrow(gse); - DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.getIbvInstructionsPdf(SOME_APP_ID, KEY_PAIR, SOME_SESSION_ID)); + DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.getIbvInstructionsPdf(authStrategyMock, SOME_SESSION_ID)); assertThat(ex.getMessage(), containsString("Error signing the request: some gse")); } @@ -902,10 +789,10 @@ public void getIbvInstructionsPdf_shouldWrapGeneralSecurityException() throws Ex @Test public void getIbvInstructionsPdf_shouldWrapResourceException() throws Exception { ResourceException resourceException = new ResourceException(400, "Failed Request", "Some response from API"); - when(signedRequestBuilderMock.build()).thenReturn(signedRequestMock); - when(signedRequestMock.execute()).thenThrow(resourceException); + when(yotiHttpRequestBuilderMock.build()).thenReturn(yotiHttpRequestMock); + when(yotiHttpRequestMock.execute()).thenThrow(resourceException); - DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.getIbvInstructionsPdf(SOME_APP_ID, KEY_PAIR, SOME_SESSION_ID)); + DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.getIbvInstructionsPdf(authStrategyMock, SOME_SESSION_ID)); assertThat(ex.getMessage(), containsString("Error executing the GET: Failed Request")); } @@ -913,10 +800,10 @@ public void getIbvInstructionsPdf_shouldWrapResourceException() throws Exception @Test public void getIbvInstructionsPdf_shouldWrapIOException() throws Exception { IOException ioException = new IOException("Some io exception"); - when(signedRequestBuilderMock.build()).thenReturn(signedRequestMock); - when(signedRequestMock.execute()).thenThrow(ioException); + when(yotiHttpRequestBuilderMock.build()).thenReturn(yotiHttpRequestMock); + when(yotiHttpRequestMock.execute()).thenThrow(ioException); - DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.getIbvInstructionsPdf(SOME_APP_ID, KEY_PAIR, SOME_SESSION_ID)); + DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.getIbvInstructionsPdf(authStrategyMock, SOME_SESSION_ID)); assertThat(ex.getMessage(), containsString("Error building the request: Some io exception")); } @@ -924,22 +811,22 @@ public void getIbvInstructionsPdf_shouldWrapIOException() throws Exception { @Test public void getIbvInstructionsPdf_shouldWrapURISyntaxException() throws Exception { URISyntaxException uriSyntaxException = new URISyntaxException("someUrl", "Failed to build URI"); - when(signedRequestBuilderMock.build()).thenThrow(uriSyntaxException); + when(yotiHttpRequestBuilderMock.build()).thenThrow(uriSyntaxException); - DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.getIbvInstructionsPdf(SOME_APP_ID, KEY_PAIR, SOME_SESSION_ID)); + DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.getIbvInstructionsPdf(authStrategyMock, SOME_SESSION_ID)); assertThat(ex.getMessage(), containsString("Error building the request: Failed to build URI: someUrl")); } @Test public void getIbvInstructionsPdf_shouldReturnMedia() throws Exception { - when(signedRequestBuilderMock.build()).thenReturn(signedRequestMock); - when(signedRequestMock.execute()).thenReturn(signedRequestResponseMock); - when(signedRequestResponseMock.getResponseHeaders()).thenReturn(createHeadersMap(CONTENT_TYPE, CONTENT_TYPE_JSON)); - when(signedRequestResponseMock.getResponseBody()).thenReturn(IMAGE_BODY); - when(unsignedPathFactoryMock.createFetchIbvInstructionsPdfPath(SOME_APP_ID, SOME_SESSION_ID)).thenReturn(SOME_PATH); + when(yotiHttpRequestBuilderMock.build()).thenReturn(yotiHttpRequestMock); + when(yotiHttpRequestMock.execute()).thenReturn(yotiHttpResponseMock); + when(yotiHttpResponseMock.getResponseHeaders()).thenReturn(createHeadersMap(CONTENT_TYPE, CONTENT_TYPE_JSON)); + when(yotiHttpResponseMock.getResponseBody()).thenReturn(IMAGE_BODY); + when(unsignedPathFactoryMock.createFetchIbvInstructionsPdfPath(SOME_SESSION_ID)).thenReturn(SOME_PATH); - Media result = docScanService.getIbvInstructionsPdf(SOME_APP_ID, KEY_PAIR, SOME_SESSION_ID); + Media result = docScanService.getIbvInstructionsPdf(authStrategyMock, SOME_SESSION_ID); assertThat(result.getMimeType(), is(CONTENT_TYPE_JSON)); assertThat(result.getContent(), is(IMAGE_BODY)); @@ -947,47 +834,35 @@ public void getIbvInstructionsPdf_shouldReturnMedia() throws Exception { @Test public void getIbvInstructionsPdf_shouldReturnNullForNoContent() throws Exception { - when(signedRequestBuilderMock.build()).thenReturn(signedRequestMock); - when(signedRequestMock.execute()).thenReturn(signedRequestResponseMock); - when(signedRequestResponseMock.getResponseCode()).thenReturn(204); - when(unsignedPathFactoryMock.createFetchIbvInstructionsPdfPath(SOME_APP_ID, SOME_SESSION_ID)).thenReturn(SOME_PATH); + when(yotiHttpRequestBuilderMock.build()).thenReturn(yotiHttpRequestMock); + when(yotiHttpRequestMock.execute()).thenReturn(yotiHttpResponseMock); + when(yotiHttpResponseMock.getResponseCode()).thenReturn(204); + when(unsignedPathFactoryMock.createFetchIbvInstructionsPdfPath(SOME_SESSION_ID)).thenReturn(SOME_PATH); - Media result = docScanService.getIbvInstructionsPdf(SOME_APP_ID, KEY_PAIR, SOME_SESSION_ID); + Media result = docScanService.getIbvInstructionsPdf(authStrategyMock, SOME_SESSION_ID); assertThat(result, is(nullValue())); } @Test - public void fetchInstructionsContactProfile_shouldThrowExceptionWhenSdkIdIsNull() { - IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.fetchInstructionsContactProfile(null, KEY_PAIR, SOME_SESSION_ID)); - - assertThat(ex.getMessage(), containsString("SDK ID")); - } - - @Test - public void fetchInstructionsContactProfile_shouldThrowExceptionWhenSdkIdIsEmpty() { - IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.fetchInstructionsContactProfile("", KEY_PAIR, SOME_SESSION_ID)); + public void fetchInstructionsContactProfile_shouldThrowExceptionWhenAuthStrategyIsNull() { + IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.fetchInstructionsContactProfile(null, SOME_SESSION_ID)); - assertThat(ex.getMessage(), containsString("SDK ID")); - } - - @Test - public void fetchInstructionsContactProfile_shouldThrowExceptionWhenKeyPairIsNull() { - IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.fetchInstructionsContactProfile(SOME_APP_ID, null, SOME_SESSION_ID)); - - assertThat(ex.getMessage(), containsString("Application key Pair")); + assertThat(ex.getMessage(), containsString("'authStrategy' must not be null.")); } @Test public void fetchInstructionsContactProfile_shouldThrowExceptionWhenSessionIdIsNull() { - IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.fetchInstructionsContactProfile(SOME_APP_ID, KEY_PAIR, null)); + IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.fetchInstructionsContactProfile( + authStrategyMock, null)); assertThat(ex.getMessage(), containsString("sessionId")); } @Test public void fetchInstructionsContactProfile_shouldThrowExceptionWhenSessionIdIsEmpty() { - IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.fetchInstructionsContactProfile(SOME_APP_ID, KEY_PAIR, "")); + IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.fetchInstructionsContactProfile( + authStrategyMock, "")); assertThat(ex.getMessage(), containsString("sessionId")); } @@ -995,9 +870,9 @@ public void fetchInstructionsContactProfile_shouldThrowExceptionWhenSessionIdIsE @Test public void fetchInstructionsContactProfile_shouldWrapGeneralSecurityException() throws Exception { GeneralSecurityException gse = new GeneralSecurityException("some gse"); - when(signedRequestBuilderMock.build()).thenThrow(gse); + when(yotiHttpRequestBuilderMock.build()).thenThrow(gse); - DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.fetchInstructionsContactProfile(SOME_APP_ID, KEY_PAIR, SOME_SESSION_ID)); + DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.fetchInstructionsContactProfile(authStrategyMock, SOME_SESSION_ID)); assertThat(ex.getMessage(), containsString("Error signing the request: some gse")); } @@ -1005,10 +880,10 @@ public void fetchInstructionsContactProfile_shouldWrapGeneralSecurityException() @Test public void fetchInstructionsContactProfile_shouldWrapResourceException() throws Exception { ResourceException resourceException = new ResourceException(400, "Failed Request", "Some response from API"); - when(signedRequestBuilderMock.build()).thenReturn(signedRequestMock); - when(signedRequestMock.execute(ContactProfileResponse.class)).thenThrow(resourceException); + when(yotiHttpRequestBuilderMock.build()).thenReturn(yotiHttpRequestMock); + when(yotiHttpRequestMock.execute(ContactProfileResponse.class)).thenThrow(resourceException); - DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.fetchInstructionsContactProfile(SOME_APP_ID, KEY_PAIR, SOME_SESSION_ID)); + DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.fetchInstructionsContactProfile(authStrategyMock, SOME_SESSION_ID)); assertThat(ex.getMessage(), containsString("Error executing the GET: Failed Request")); } @@ -1016,10 +891,10 @@ public void fetchInstructionsContactProfile_shouldWrapResourceException() throws @Test public void fetchInstructionsContactProfile_shouldWrapIOException() throws Exception { IOException ioException = new IOException("Some io exception"); - when(signedRequestBuilderMock.build()).thenReturn(signedRequestMock); - when(signedRequestMock.execute(ContactProfileResponse.class)).thenThrow(ioException); + when(yotiHttpRequestBuilderMock.build()).thenReturn(yotiHttpRequestMock); + when(yotiHttpRequestMock.execute(ContactProfileResponse.class)).thenThrow(ioException); - DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.fetchInstructionsContactProfile(SOME_APP_ID, KEY_PAIR, SOME_SESSION_ID)); + DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.fetchInstructionsContactProfile(authStrategyMock, SOME_SESSION_ID)); assertThat(ex.getMessage(), containsString("Error building the request: Some io exception")); } @@ -1027,44 +902,32 @@ public void fetchInstructionsContactProfile_shouldWrapIOException() throws Excep @Test public void fetchInstructionsContactProfile_shouldWrapURISyntaxException() throws Exception { URISyntaxException uriSyntaxException = new URISyntaxException("someUrl", "Failed to build URI"); - when(signedRequestBuilderMock.build()).thenThrow(uriSyntaxException); + when(yotiHttpRequestBuilderMock.build()).thenThrow(uriSyntaxException); - DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.fetchInstructionsContactProfile(SOME_APP_ID, KEY_PAIR, SOME_SESSION_ID)); + DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.fetchInstructionsContactProfile(authStrategyMock, SOME_SESSION_ID)); assertThat(ex.getMessage(), containsString("Error building the request: Failed to build URI: someUrl")); } @Test - public void fetchSessionConfiguration_shouldThrowExceptionWhenSdkIdIsNull() { - IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.fetchSessionConfiguration(null, KEY_PAIR, SOME_SESSION_ID)); - - assertThat(ex.getMessage(), containsString("SDK ID")); - } - - @Test - public void fetchSessionConfiguration_shouldThrowExceptionWhenSdkIdIsEmpty() { - IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.fetchSessionConfiguration("", KEY_PAIR, SOME_SESSION_ID)); - - assertThat(ex.getMessage(), containsString("SDK ID")); - } - - @Test - public void fetchSessionConfiguration_shouldThrowExceptionWhenKeyPairIsNull() { - IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.fetchSessionConfiguration(SOME_APP_ID, null, SOME_SESSION_ID)); + public void fetchSessionConfiguration_shouldThrowExceptionWhenAuthStrategyIsNull() { + IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.fetchSessionConfiguration(null, SOME_SESSION_ID)); - assertThat(ex.getMessage(), containsString("Application key Pair")); + assertThat(ex.getMessage(), containsString("'authStrategy' must not be null.")); } @Test public void fetchSessionConfiguration_shouldThrowExceptionWhenSessionIdIsNull() { - IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.fetchSessionConfiguration(SOME_APP_ID, KEY_PAIR, null)); + IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.fetchSessionConfiguration( + authStrategyMock, null)); assertThat(ex.getMessage(), containsString("sessionId")); } @Test public void fetchSessionConfiguration_shouldThrowExceptionWhenSessionIdIsEmpty() { - IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.fetchSessionConfiguration(SOME_APP_ID, KEY_PAIR, "")); + IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.fetchSessionConfiguration( + authStrategyMock, "")); assertThat(ex.getMessage(), containsString("sessionId")); } @@ -1072,9 +935,9 @@ public void fetchSessionConfiguration_shouldThrowExceptionWhenSessionIdIsEmpty() @Test public void fetchSessionConfiguration_shouldWrapGeneralSecurityException() throws Exception { GeneralSecurityException gse = new GeneralSecurityException("some gse"); - when(signedRequestBuilderMock.build()).thenThrow(gse); + when(yotiHttpRequestBuilderMock.build()).thenThrow(gse); - DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.fetchSessionConfiguration(SOME_APP_ID, KEY_PAIR, SOME_SESSION_ID)); + DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.fetchSessionConfiguration(authStrategyMock, SOME_SESSION_ID)); assertThat(ex.getMessage(), containsString("Error signing the request: some gse")); } @@ -1082,10 +945,10 @@ public void fetchSessionConfiguration_shouldWrapGeneralSecurityException() throw @Test public void fetchSessionConfiguration_shouldWrapResourceException() throws Exception { ResourceException resourceException = new ResourceException(400, "Failed Request", "Some response from API"); - when(signedRequestBuilderMock.build()).thenReturn(signedRequestMock); - when(signedRequestMock.execute(SessionConfigurationResponse.class)).thenThrow(resourceException); + when(yotiHttpRequestBuilderMock.build()).thenReturn(yotiHttpRequestMock); + when(yotiHttpRequestMock.execute(SessionConfigurationResponse.class)).thenThrow(resourceException); - DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.fetchSessionConfiguration(SOME_APP_ID, KEY_PAIR, SOME_SESSION_ID)); + DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.fetchSessionConfiguration(authStrategyMock, SOME_SESSION_ID)); assertThat(ex.getMessage(), containsString("Error executing the GET: Failed Request")); } @@ -1093,10 +956,10 @@ public void fetchSessionConfiguration_shouldWrapResourceException() throws Excep @Test public void fetchSessionConfiguration_shouldWrapIOException() throws Exception { IOException ioException = new IOException("Some io exception"); - when(signedRequestBuilderMock.build()).thenReturn(signedRequestMock); - when(signedRequestMock.execute(SessionConfigurationResponse.class)).thenThrow(ioException); + when(yotiHttpRequestBuilderMock.build()).thenReturn(yotiHttpRequestMock); + when(yotiHttpRequestMock.execute(SessionConfigurationResponse.class)).thenThrow(ioException); - DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.fetchSessionConfiguration(SOME_APP_ID, KEY_PAIR, SOME_SESSION_ID)); + DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.fetchSessionConfiguration(authStrategyMock, SOME_SESSION_ID)); assertThat(ex.getMessage(), containsString("Error building the request: Some io exception")); } @@ -1104,51 +967,40 @@ public void fetchSessionConfiguration_shouldWrapIOException() throws Exception { @Test public void fetchSessionConfiguration_shouldWrapURISyntaxException() throws Exception { URISyntaxException uriSyntaxException = new URISyntaxException("someUrl", "Failed to build URI"); - when(signedRequestBuilderMock.build()).thenThrow(uriSyntaxException); + when(yotiHttpRequestBuilderMock.build()).thenThrow(uriSyntaxException); - DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.fetchSessionConfiguration(SOME_APP_ID, KEY_PAIR, SOME_SESSION_ID)); + DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.fetchSessionConfiguration(authStrategyMock, SOME_SESSION_ID)); assertThat(ex.getMessage(), containsString("Error building the request: Failed to build URI: someUrl")); } @Test - public void createFaceCaptureResource_shouldThrowExceptionWhenSdkIdIsNull() { - IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.createFaceCaptureResource(null, KEY_PAIR, SOME_SESSION_ID, createFaceCaptureResourcePayloadMock)); + public void createFaceCaptureResource_shouldThrowExceptionWhenAuthStrategyIsNull() { + IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.createFaceCaptureResource(null, SOME_SESSION_ID, createFaceCaptureResourcePayloadMock)); - assertThat(ex.getMessage(), containsString("SDK ID")); - } - - @Test - public void createFaceCaptureResource_shouldThrowExceptionWhenSdkIdIsEmpty() { - IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.createFaceCaptureResource("", KEY_PAIR, SOME_SESSION_ID, createFaceCaptureResourcePayloadMock)); - - assertThat(ex.getMessage(), containsString("SDK ID")); - } - - @Test - public void createFaceCaptureResource_shouldThrowExceptionWhenKeyPairIsNull() { - IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.createFaceCaptureResource(SOME_APP_ID, null, SOME_SESSION_ID, createFaceCaptureResourcePayloadMock)); - - assertThat(ex.getMessage(), containsString("Application key Pair")); + assertThat(ex.getMessage(), containsString("'authStrategy' must not be null.")); } @Test public void createFaceCaptureResource_shouldThrowExceptionWhenSessionIdIsNull() { - IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.createFaceCaptureResource(SOME_APP_ID, KEY_PAIR, null, createFaceCaptureResourcePayloadMock)); + IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.createFaceCaptureResource( + authStrategyMock, null, createFaceCaptureResourcePayloadMock)); assertThat(ex.getMessage(), containsString("sessionId")); } @Test public void createFaceCaptureResource_shouldThrowExceptionWhenSessionIdIsEmpty() { - IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.createFaceCaptureResource(SOME_APP_ID, KEY_PAIR, "", createFaceCaptureResourcePayloadMock)); + IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.createFaceCaptureResource( + authStrategyMock, "", createFaceCaptureResourcePayloadMock)); assertThat(ex.getMessage(), containsString("sessionId")); } @Test public void createFaceCaptureResource_shouldThrowExceptionWhenPayloadIsNull() { - IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.createFaceCaptureResource(SOME_APP_ID, KEY_PAIR, SOME_SESSION_ID, null)); + IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.createFaceCaptureResource( + authStrategyMock, SOME_SESSION_ID, null)); assertThat(ex.getMessage(), containsString("createFaceCaptureResourcePayload")); } @@ -1156,9 +1008,9 @@ public void createFaceCaptureResource_shouldThrowExceptionWhenPayloadIsNull() { @Test public void createFaceCaptureResource_shouldWrapGeneralSecurityException() throws Exception { GeneralSecurityException gse = new GeneralSecurityException("some gse"); - when(signedRequestBuilderMock.build()).thenThrow(gse); + when(yotiHttpRequestBuilderMock.build()).thenThrow(gse); - DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.createFaceCaptureResource(SOME_APP_ID, KEY_PAIR, SOME_SESSION_ID, createFaceCaptureResourcePayloadMock)); + DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.createFaceCaptureResource(authStrategyMock, SOME_SESSION_ID, createFaceCaptureResourcePayloadMock)); assertThat(ex.getMessage(), containsString("Error signing the request: some gse")); } @@ -1166,10 +1018,10 @@ public void createFaceCaptureResource_shouldWrapGeneralSecurityException() throw @Test public void createFaceCaptureResource_shouldWrapResourceException() throws Exception { ResourceException resourceException = new ResourceException(400, "Failed Request", "Some response from API"); - when(signedRequestBuilderMock.build()).thenReturn(signedRequestMock); - when(signedRequestMock.execute(CreateFaceCaptureResourceResponse.class)).thenThrow(resourceException); + when(yotiHttpRequestBuilderMock.build()).thenReturn(yotiHttpRequestMock); + when(yotiHttpRequestMock.execute(CreateFaceCaptureResourceResponse.class)).thenThrow(resourceException); - DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.createFaceCaptureResource(SOME_APP_ID, KEY_PAIR, SOME_SESSION_ID, createFaceCaptureResourcePayloadMock)); + DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.createFaceCaptureResource(authStrategyMock, SOME_SESSION_ID, createFaceCaptureResourcePayloadMock)); assertThat(ex.getMessage(), containsString("Error executing the POST: Failed Request")); } @@ -1177,10 +1029,10 @@ public void createFaceCaptureResource_shouldWrapResourceException() throws Excep @Test public void createFaceCaptureResource_shouldWrapIOException() throws Exception { IOException ioException = new IOException("Some io exception"); - when(signedRequestBuilderMock.build()).thenReturn(signedRequestMock); - when(signedRequestMock.execute(CreateFaceCaptureResourceResponse.class)).thenThrow(ioException); + when(yotiHttpRequestBuilderMock.build()).thenReturn(yotiHttpRequestMock); + when(yotiHttpRequestMock.execute(CreateFaceCaptureResourceResponse.class)).thenThrow(ioException); - DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.createFaceCaptureResource(SOME_APP_ID, KEY_PAIR, SOME_SESSION_ID, createFaceCaptureResourcePayloadMock)); + DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.createFaceCaptureResource(authStrategyMock, SOME_SESSION_ID, createFaceCaptureResourcePayloadMock)); assertThat(ex.getMessage(), containsString("Error building the request: Some io exception")); } @@ -1188,65 +1040,56 @@ public void createFaceCaptureResource_shouldWrapIOException() throws Exception { @Test public void createFaceCaptureResource_shouldWrapURISyntaxException() throws Exception { URISyntaxException uriSyntaxException = new URISyntaxException("someUrl", "Failed to build URI"); - when(signedRequestBuilderMock.build()).thenThrow(uriSyntaxException); + when(yotiHttpRequestBuilderMock.build()).thenThrow(uriSyntaxException); - DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.createFaceCaptureResource(SOME_APP_ID, KEY_PAIR, SOME_SESSION_ID, createFaceCaptureResourcePayloadMock)); + DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.createFaceCaptureResource(authStrategyMock, SOME_SESSION_ID, createFaceCaptureResourcePayloadMock)); assertThat(ex.getMessage(), containsString("Error building the request: Failed to build URI: someUrl")); } @Test - public void uploadFaceCaptureImage_shouldFailForNullSdkId() { - IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.uploadFaceCaptureImage(null, null, null, null, null)); - - assertThat(ex.getMessage(), containsString("SDK ID")); - } - - @Test - public void uploadFaceCaptureImage_shouldFailForEmptySdkId() { - IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.uploadFaceCaptureImage("", null, null, null, null)); - - assertThat(ex.getMessage(), containsString("SDK ID")); - } - - @Test - public void uploadFaceCaptureImage_shouldFailForNullKeyPair() { - IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.uploadFaceCaptureImage(SOME_APP_ID, null, null, null, null)); + public void uploadFaceCaptureImage_shouldFailForNullAuthStrategy() { + IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.uploadFaceCaptureImage(null, null, null, null)); - assertThat(ex.getMessage(), containsString("Application key Pair")); + assertThat(ex.getMessage(), containsString("'authStrategy' must not be null.")); } @Test public void uploadFaceCaptureImage_shouldFailForNullSessionId() { - IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.uploadFaceCaptureImage(SOME_APP_ID, KEY_PAIR, null, null,null)); + IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.uploadFaceCaptureImage( + authStrategyMock, null, null,null)); assertThat(ex.getMessage(), containsString("sessionId")); } @Test public void uploadFaceCaptureImage_shouldFailForEmptySessionId() { - IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.uploadFaceCaptureImage(SOME_APP_ID, KEY_PAIR, "", null, null)); + IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.uploadFaceCaptureImage( + authStrategyMock, "", null, null)); assertThat(ex.getMessage(), containsString("sessionId")); } @Test public void uploadFaceCaptureImage_shouldFailForNullResourceId() { - IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.uploadFaceCaptureImage(SOME_APP_ID, KEY_PAIR, SOME_SESSION_ID, null,null)); + IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.uploadFaceCaptureImage( + authStrategyMock, SOME_SESSION_ID, null,null)); assertThat(ex.getMessage(), containsString("resourceId")); } @Test public void uploadFaceCaptureImage_shouldFailForEmptyResourceId() { - IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.uploadFaceCaptureImage(SOME_APP_ID, KEY_PAIR, SOME_SESSION_ID, "", null)); + IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.uploadFaceCaptureImage( + authStrategyMock, SOME_SESSION_ID, "", null)); assertThat(ex.getMessage(), containsString("resourceId")); } @Test public void uploadFaceCaptureImage_shouldFailForNullPayload() { - IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.uploadFaceCaptureImage(SOME_APP_ID, KEY_PAIR, SOME_SESSION_ID, SOME_RESOURCE_ID, null)); + IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.uploadFaceCaptureImage( + authStrategyMock, SOME_SESSION_ID, SOME_RESOURCE_ID, null)); assertThat(ex.getMessage(), containsString("faceCaptureImagePayload")); } @@ -1255,11 +1098,11 @@ public void uploadFaceCaptureImage_shouldFailForNullPayload() { public void uploadFaceCaptureImage_shouldWrapGeneralSecurityException() throws Exception { when(uploadFaceCaptureImagePayloadMock.getImageContents()).thenReturn(IMAGE_BODY); when(uploadFaceCaptureImagePayloadMock.getImageContentType()).thenReturn(SOME_IMAGE_CONTENT_TYPE); - when(unsignedPathFactoryMock.createUploadFaceCaptureImagePath(SOME_APP_ID, SOME_SESSION_ID, SOME_RESOURCE_ID)).thenReturn(SOME_PATH); + when(unsignedPathFactoryMock.createUploadFaceCaptureImagePath(SOME_SESSION_ID, SOME_RESOURCE_ID)).thenReturn(SOME_PATH); GeneralSecurityException gse = new GeneralSecurityException("some gse"); - when(signedRequestBuilderMock.build()).thenThrow(gse); + when(yotiHttpRequestBuilderMock.build()).thenThrow(gse); - DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.uploadFaceCaptureImage(SOME_APP_ID, KEY_PAIR, SOME_SESSION_ID, SOME_RESOURCE_ID, uploadFaceCaptureImagePayloadMock)); + DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.uploadFaceCaptureImage(authStrategyMock, SOME_SESSION_ID, SOME_RESOURCE_ID, uploadFaceCaptureImagePayloadMock)); assertSame(ex.getCause(), gse); assertThat(ex.getMessage(), containsString("Error executing the PUT: some gse")); @@ -1269,11 +1112,11 @@ public void uploadFaceCaptureImage_shouldWrapGeneralSecurityException() throws E public void uploadFaceCaptureImage_shouldWrapURISyntaxException() throws Exception { when(uploadFaceCaptureImagePayloadMock.getImageContents()).thenReturn(IMAGE_BODY); when(uploadFaceCaptureImagePayloadMock.getImageContentType()).thenReturn(SOME_IMAGE_CONTENT_TYPE); - when(unsignedPathFactoryMock.createUploadFaceCaptureImagePath(SOME_APP_ID, SOME_SESSION_ID, SOME_RESOURCE_ID)).thenReturn(SOME_PATH); + when(unsignedPathFactoryMock.createUploadFaceCaptureImagePath(SOME_SESSION_ID, SOME_RESOURCE_ID)).thenReturn(SOME_PATH); URISyntaxException uriSyntaxException = new URISyntaxException("someUrl", "Failed to build URI"); - when(signedRequestBuilderMock.build()).thenThrow(uriSyntaxException); + when(yotiHttpRequestBuilderMock.build()).thenThrow(uriSyntaxException); - DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.uploadFaceCaptureImage(SOME_APP_ID, KEY_PAIR, SOME_SESSION_ID, SOME_RESOURCE_ID, uploadFaceCaptureImagePayloadMock)); + DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.uploadFaceCaptureImage(authStrategyMock, SOME_SESSION_ID, SOME_RESOURCE_ID, uploadFaceCaptureImagePayloadMock)); assertSame(ex.getCause(), uriSyntaxException); assertThat(ex.getMessage(), containsString("Error building the request: Failed to build URI: someUrl")); @@ -1283,12 +1126,12 @@ public void uploadFaceCaptureImage_shouldWrapURISyntaxException() throws Excepti public void uploadFaceCaptureImage_shouldWrapIOException() throws Exception { when(uploadFaceCaptureImagePayloadMock.getImageContents()).thenReturn(IMAGE_BODY); when(uploadFaceCaptureImagePayloadMock.getImageContentType()).thenReturn(SOME_IMAGE_CONTENT_TYPE); - when(unsignedPathFactoryMock.createUploadFaceCaptureImagePath(SOME_APP_ID, SOME_SESSION_ID, SOME_RESOURCE_ID)).thenReturn(SOME_PATH); + when(unsignedPathFactoryMock.createUploadFaceCaptureImagePath(SOME_SESSION_ID, SOME_RESOURCE_ID)).thenReturn(SOME_PATH); IOException ioException = new IOException("some IO exception"); - when(signedRequestBuilderMock.build()).thenReturn(signedRequestMock); - when(signedRequestMock.execute()).thenThrow(ioException); + when(yotiHttpRequestBuilderMock.build()).thenReturn(yotiHttpRequestMock); + when(yotiHttpRequestMock.execute()).thenThrow(ioException); - DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.uploadFaceCaptureImage(SOME_APP_ID, KEY_PAIR, SOME_SESSION_ID, SOME_RESOURCE_ID, uploadFaceCaptureImagePayloadMock)); + DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.uploadFaceCaptureImage(authStrategyMock, SOME_SESSION_ID, SOME_RESOURCE_ID, uploadFaceCaptureImagePayloadMock)); assertSame(ex.getCause(), ioException); assertThat(ex.getMessage(), containsString("Error building the request: some IO exception")); @@ -1298,48 +1141,36 @@ public void uploadFaceCaptureImage_shouldWrapIOException() throws Exception { public void uploadFaceCaptureImage_shouldWrapResourceException() throws Exception { when(uploadFaceCaptureImagePayloadMock.getImageContents()).thenReturn(IMAGE_BODY); when(uploadFaceCaptureImagePayloadMock.getImageContentType()).thenReturn(SOME_IMAGE_CONTENT_TYPE); - when(unsignedPathFactoryMock.createUploadFaceCaptureImagePath(SOME_APP_ID, SOME_SESSION_ID, SOME_RESOURCE_ID)).thenReturn(SOME_PATH); + when(unsignedPathFactoryMock.createUploadFaceCaptureImagePath(SOME_SESSION_ID, SOME_RESOURCE_ID)).thenReturn(SOME_PATH); ResourceException resourceException = new ResourceException(400, "Failed Request", "Some response from API"); - when(signedRequestBuilderMock.build()).thenReturn(signedRequestMock); - when(signedRequestMock.execute()).thenThrow(resourceException); + when(yotiHttpRequestBuilderMock.build()).thenReturn(yotiHttpRequestMock); + when(yotiHttpRequestMock.execute()).thenThrow(resourceException); - DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.uploadFaceCaptureImage(SOME_APP_ID, KEY_PAIR, SOME_SESSION_ID, SOME_RESOURCE_ID, uploadFaceCaptureImagePayloadMock)); + DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.uploadFaceCaptureImage(authStrategyMock, SOME_SESSION_ID, SOME_RESOURCE_ID, uploadFaceCaptureImagePayloadMock)); assertSame(ex.getCause(), resourceException); assertThat(ex.getMessage(), containsString("Error executing the PUT: Failed Request")); } @Test - public void triggerIbvEmailNotification_shouldThrowExceptionWhenSdkIdIsNull() { - IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.triggerIbvEmailNotification(null, KEY_PAIR, SOME_SESSION_ID)); + public void triggerIbvEmailNotification_shouldThrowExceptionWhenAuthStrategyIsNull() { + IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.triggerIbvEmailNotification(null, SOME_SESSION_ID)); - assertThat(ex.getMessage(), containsString("SDK ID")); - } - - @Test - public void triggerIbvEmailNotification_shouldThrowExceptionWhenSdkIdIsEmpty() { - IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.triggerIbvEmailNotification("", KEY_PAIR, SOME_SESSION_ID)); - - assertThat(ex.getMessage(), containsString("SDK ID")); - } - - @Test - public void triggerIbvEmailNotification_shouldThrowExceptionWhenKeyPairIsNull() { - IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.triggerIbvEmailNotification(SOME_APP_ID, null, SOME_SESSION_ID)); - - assertThat(ex.getMessage(), containsString("Application key Pair")); + assertThat(ex.getMessage(), containsString("'authStrategy' must not be null.")); } @Test public void triggerIbvEmailNotification_shouldThrowExceptionWhenSessionIdIsNull() { - IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.triggerIbvEmailNotification(SOME_APP_ID, KEY_PAIR, null)); + IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.triggerIbvEmailNotification( + authStrategyMock, null)); assertThat(ex.getMessage(), containsString("sessionId")); } @Test public void triggerIbvEmailNotification_shouldThrowExceptionWhenSessionIdIsEmpty() { - IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.triggerIbvEmailNotification(SOME_APP_ID, KEY_PAIR, "")); + IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.triggerIbvEmailNotification( + authStrategyMock, "")); assertThat(ex.getMessage(), containsString("sessionId")); } @@ -1347,9 +1178,9 @@ public void triggerIbvEmailNotification_shouldThrowExceptionWhenSessionIdIsEmpty @Test public void triggerIbvEmailNotification_shouldWrapGeneralSecurityException() throws Exception { GeneralSecurityException gse = new GeneralSecurityException("some gse"); - when(signedRequestBuilderMock.build()).thenThrow(gse); + when(yotiHttpRequestBuilderMock.build()).thenThrow(gse); - DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.triggerIbvEmailNotification(SOME_APP_ID, KEY_PAIR, SOME_SESSION_ID)); + DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.triggerIbvEmailNotification(authStrategyMock, SOME_SESSION_ID)); assertThat(ex.getMessage(), containsString("Error executing the POST: some gse")); } @@ -1357,10 +1188,10 @@ public void triggerIbvEmailNotification_shouldWrapGeneralSecurityException() thr @Test public void triggerIbvEmailNotification_shouldWrapResourceException() throws Exception { ResourceException resourceException = new ResourceException(400, "Failed Request", "Some response from API"); - when(signedRequestBuilderMock.build()).thenReturn(signedRequestMock); - when(signedRequestMock.execute()).thenThrow(resourceException); + when(yotiHttpRequestBuilderMock.build()).thenReturn(yotiHttpRequestMock); + when(yotiHttpRequestMock.execute()).thenThrow(resourceException); - DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.triggerIbvEmailNotification(SOME_APP_ID, KEY_PAIR, SOME_SESSION_ID)); + DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.triggerIbvEmailNotification(authStrategyMock, SOME_SESSION_ID)); assertThat(ex.getMessage(), containsString("Error executing the POST: Failed Request")); } @@ -1368,10 +1199,10 @@ public void triggerIbvEmailNotification_shouldWrapResourceException() throws Exc @Test public void triggerIbvEmailNotification_shouldWrapIOException() throws Exception { IOException ioException = new IOException("Some io exception"); - when(signedRequestBuilderMock.build()).thenReturn(signedRequestMock); - when(signedRequestMock.execute()).thenThrow(ioException); + when(yotiHttpRequestBuilderMock.build()).thenReturn(yotiHttpRequestMock); + when(yotiHttpRequestMock.execute()).thenThrow(ioException); - DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.triggerIbvEmailNotification(SOME_APP_ID, KEY_PAIR, SOME_SESSION_ID)); + DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.triggerIbvEmailNotification(authStrategyMock, SOME_SESSION_ID)); assertThat(ex.getMessage(), containsString("Error building the request: Some io exception")); } @@ -1379,26 +1210,19 @@ public void triggerIbvEmailNotification_shouldWrapIOException() throws Exception @Test public void triggerIbvEmailNotification_shouldWrapURISyntaxException() throws Exception { URISyntaxException uriSyntaxException = new URISyntaxException("someUrl", "Failed to build URI"); - when(signedRequestBuilderMock.build()).thenThrow(uriSyntaxException); + when(yotiHttpRequestBuilderMock.build()).thenThrow(uriSyntaxException); - DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.triggerIbvEmailNotification(SOME_APP_ID, KEY_PAIR, SOME_SESSION_ID)); + DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.triggerIbvEmailNotification(authStrategyMock, SOME_SESSION_ID)); assertThat(ex.getMessage(), containsString("Error building the request: Failed to build URI: someUrl")); } - @Test - public void getSupportedDocuments_shouldThrowExceptionWhenKeyPairIsNull() { - IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> docScanService.getSupportedDocuments(null, false)); - - assertThat(ex.getMessage(), containsString("Application key Pair")); - } - @Test public void getSupportedDocuments_shouldWrapGeneralSecurityException() throws Exception { GeneralSecurityException gse = new GeneralSecurityException("some gse"); - when(signedRequestBuilderMock.build()).thenThrow(gse); + when(yotiHttpRequestBuilderMock.build()).thenThrow(gse); - DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.getSupportedDocuments(KEY_PAIR, false)); + DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.getSupportedDocuments(false)); assertSame(ex.getCause(), gse); assertThat(ex.getMessage(), containsString("Error executing the GET: some gse")); @@ -1407,10 +1231,10 @@ public void getSupportedDocuments_shouldWrapGeneralSecurityException() throws Ex @Test public void getSupportedDocuments_shouldWrapResourceException() throws Exception { ResourceException resourceException = new ResourceException(400, "Failed Request", "Some response from API"); - when(signedRequestBuilderMock.build()).thenReturn(signedRequestMock); - when(signedRequestMock.execute(SupportedDocumentsResponse.class)).thenThrow(resourceException); + when(yotiHttpRequestBuilderMock.build()).thenReturn(yotiHttpRequestMock); + when(yotiHttpRequestMock.execute(SupportedDocumentsResponse.class)).thenThrow(resourceException); - DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.getSupportedDocuments(KEY_PAIR, false)); + DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.getSupportedDocuments(false)); assertSame(ex.getCause(), resourceException); assertThat(ex.getMessage(), containsString("Error executing the GET: Failed Request")); @@ -1419,10 +1243,10 @@ public void getSupportedDocuments_shouldWrapResourceException() throws Exception @Test public void getSupportedDocuments_shouldWrapIOException() throws Exception { IOException ioException = new IOException("Some io exception"); - when(signedRequestBuilderMock.build()).thenReturn(signedRequestMock); - when(signedRequestMock.execute(SupportedDocumentsResponse.class)).thenThrow(ioException); + when(yotiHttpRequestBuilderMock.build()).thenReturn(yotiHttpRequestMock); + when(yotiHttpRequestMock.execute(SupportedDocumentsResponse.class)).thenThrow(ioException); - DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.getSupportedDocuments(KEY_PAIR, false)); + DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.getSupportedDocuments(false)); assertSame(ex.getCause(), ioException); assertThat(ex.getMessage(), containsString("Error building the request: Some io exception")); @@ -1431,9 +1255,9 @@ public void getSupportedDocuments_shouldWrapIOException() throws Exception { @Test public void getSupportedDocuments_shouldWrapURISyntaxException() throws Exception { URISyntaxException uriSyntaxException = new URISyntaxException("someUrl", "Failed to build URI"); - when(signedRequestBuilderMock.build()).thenThrow(uriSyntaxException); + when(yotiHttpRequestBuilderMock.build()).thenThrow(uriSyntaxException); - DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.getSupportedDocuments(KEY_PAIR, false)); + DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.getSupportedDocuments(false)); assertSame(ex.getCause(), uriSyntaxException); assertThat(ex.getMessage(), containsString("Error building the request: Failed to build URI: someUrl")); @@ -1441,51 +1265,41 @@ public void getSupportedDocuments_shouldWrapURISyntaxException() throws Exceptio @Test public void getSupportedDocuments_shouldReturnSupportedDocuments() throws Exception { - when(signedRequestBuilderMock.build()).thenReturn(signedRequestMock); - when(signedRequestMock.execute(SupportedDocumentsResponse.class)).thenReturn(supportedDocumentsResponseMock); + when(yotiHttpRequestBuilderMock.build()).thenReturn(yotiHttpRequestMock); + when(yotiHttpRequestMock.execute(SupportedDocumentsResponse.class)).thenReturn(supportedDocumentsResponseMock); when(unsignedPathFactoryMock.createGetSupportedDocumentsPath(false)).thenReturn(SOME_PATH); - SupportedDocumentsResponse result = docScanService.getSupportedDocuments(KEY_PAIR, false); + SupportedDocumentsResponse result = docScanService.getSupportedDocuments(false); assertThat(result, is(instanceOf(SupportedDocumentsResponse.class))); } @Test - public void getTrackedDevices_shouldThrowExceptionWhenSdkIdIsNull() { - IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> docScanService.getTrackedDevices(null, KEY_PAIR, SOME_SESSION_ID)); - assertThat(exception.getMessage(), containsString("SDK ID")); - } - - @Test - public void getTrackedDevices_shouldThrowExceptionWhenSdkIdIsEmpty() { - IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> docScanService.getTrackedDevices("", KEY_PAIR, SOME_SESSION_ID)); - assertThat(exception.getMessage(), containsString("SDK ID")); - } - - @Test - public void getTrackedDevices_shouldThrowExceptionWhenKeyPairIsNull() { - IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> docScanService.getTrackedDevices(SOME_APP_ID, null, SOME_SESSION_ID)); - assertThat(exception.getMessage(), containsString("Application key Pair")); + public void getTrackedDevices_shouldThrowExceptionWhenAuthStrategyIsNull() { + IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> docScanService.getTrackedDevices(null, SOME_SESSION_ID)); + assertThat(exception.getMessage(), containsString("'authStrategy' must not be null.")); } @Test public void getTrackedDevices_shouldThrowExceptionWhenSessionIdIsNull() { - IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> docScanService.getTrackedDevices(SOME_APP_ID, KEY_PAIR, null)); + IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> docScanService.getTrackedDevices( + authStrategyMock, null)); assertThat(exception.getMessage(), containsString("sessionId")); } @Test public void getTrackedDevices_shouldThrowExceptionWhenSessionIdIsEmpty() { - IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> docScanService.getTrackedDevices(SOME_APP_ID, KEY_PAIR, "")); + IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> docScanService.getTrackedDevices( + authStrategyMock, "")); assertThat(exception.getMessage(), containsString("sessionId")); } @Test public void getTrackedDevices_shouldWrapGeneralSecurityException() throws Exception { GeneralSecurityException gse = new GeneralSecurityException("some gse"); - when(signedRequestBuilderMock.build()).thenThrow(gse); + when(yotiHttpRequestBuilderMock.build()).thenThrow(gse); - DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.getTrackedDevices(SOME_APP_ID, KEY_PAIR, SOME_SESSION_ID)); + DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.getTrackedDevices(authStrategyMock, SOME_SESSION_ID)); assertSame(ex.getCause(), gse); assertThat(ex.getMessage(), containsString("Error executing the GET: some gse")); @@ -1494,10 +1308,10 @@ public void getTrackedDevices_shouldWrapGeneralSecurityException() throws Except @Test public void getTrackedDevices_shouldWrapResourceException() throws Exception { ResourceException resourceException = new ResourceException(400, "Failed Request", "Some response from API"); - when(signedRequestBuilderMock.build()).thenReturn(signedRequestMock); - when(signedRequestMock.execute(ArgumentMatchers.any(TypeReference.class))).thenThrow(resourceException); + when(yotiHttpRequestBuilderMock.build()).thenReturn(yotiHttpRequestMock); + when(yotiHttpRequestMock.execute(ArgumentMatchers.any(TypeReference.class))).thenThrow(resourceException); - DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.getTrackedDevices(SOME_APP_ID, KEY_PAIR, SOME_SESSION_ID)); + DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.getTrackedDevices(authStrategyMock, SOME_SESSION_ID)); assertSame(ex.getCause(), resourceException); assertThat(ex.getMessage(), containsString("Error executing the GET: Failed Request")); @@ -1506,10 +1320,10 @@ public void getTrackedDevices_shouldWrapResourceException() throws Exception { @Test public void getTrackedDevices_shouldWrapIOException() throws Exception { IOException ioException = new IOException("Some io exception"); - when(signedRequestBuilderMock.build()).thenReturn(signedRequestMock); - when(signedRequestMock.execute(ArgumentMatchers.any(TypeReference.class))).thenThrow(ioException); + when(yotiHttpRequestBuilderMock.build()).thenReturn(yotiHttpRequestMock); + when(yotiHttpRequestMock.execute(ArgumentMatchers.any(TypeReference.class))).thenThrow(ioException); - DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.getTrackedDevices(SOME_APP_ID, KEY_PAIR, SOME_SESSION_ID)); + DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.getTrackedDevices(authStrategyMock, SOME_SESSION_ID)); assertSame(ex.getCause(), ioException); assertThat(ex.getMessage(), containsString("Error building the request: Some io exception")); @@ -1518,9 +1332,9 @@ public void getTrackedDevices_shouldWrapIOException() throws Exception { @Test public void getTrackedDevices_shouldWrapURISyntaxException() throws Exception { URISyntaxException uriSyntaxException = new URISyntaxException("someUrl", "Failed to build URI"); - when(signedRequestBuilderMock.build()).thenThrow(uriSyntaxException); + when(yotiHttpRequestBuilderMock.build()).thenThrow(uriSyntaxException); - DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.getTrackedDevices(SOME_APP_ID, KEY_PAIR, SOME_SESSION_ID)); + DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.getTrackedDevices(authStrategyMock, SOME_SESSION_ID)); assertSame(ex.getCause(), uriSyntaxException); assertThat(ex.getMessage(), containsString("Error building the request: Failed to build URI: someUrl")); @@ -1528,52 +1342,42 @@ public void getTrackedDevices_shouldWrapURISyntaxException() throws Exception { @Test public void getTrackedDevices_shouldReturnTrackedDevices() throws Exception { - when(signedRequestBuilderMock.build()).thenReturn(signedRequestMock); + when(yotiHttpRequestBuilderMock.build()).thenReturn(yotiHttpRequestMock); MetadataResponse metadataResponseMock = mock(MetadataResponse.class); - when(signedRequestMock.execute(ArgumentMatchers.any(TypeReference.class))).thenReturn(Collections.singletonList(metadataResponseMock)); - when(unsignedPathFactoryMock.createFetchTrackedDevices(SOME_APP_ID, SOME_SESSION_ID)).thenReturn(SOME_PATH); + when(yotiHttpRequestMock.execute(ArgumentMatchers.any(TypeReference.class))).thenReturn(Collections.singletonList(metadataResponseMock)); + when(unsignedPathFactoryMock.createFetchTrackedDevices(SOME_SESSION_ID)).thenReturn(SOME_PATH); - List result = docScanService.getTrackedDevices(SOME_APP_ID, KEY_PAIR, SOME_SESSION_ID); + List result = docScanService.getTrackedDevices(authStrategyMock, SOME_SESSION_ID); assertThat(result.get(0), is(metadataResponseMock)); } @Test - public void deleteTrackedDevices_shouldThrowExceptionWhenSdkIdIsNull() { - IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> docScanService.deleteTrackedDevices(null, KEY_PAIR, SOME_SESSION_ID)); - assertThat(exception.getMessage(), containsString("SDK ID")); - } - - @Test - public void deleteTrackedDevices_shouldThrowExceptionWhenSdkIdIsEmpty() { - IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> docScanService.deleteTrackedDevices("", KEY_PAIR, SOME_SESSION_ID)); - assertThat(exception.getMessage(), containsString("SDK ID")); - } - - @Test - public void deleteTrackedDevices_shouldThrowExceptionWhenKeyPairIsNull() { - IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> docScanService.deleteTrackedDevices(SOME_APP_ID, null, SOME_SESSION_ID)); - assertThat(exception.getMessage(), containsString("Application key Pair")); + public void deleteTrackedDevices_shouldThrowExceptionWhenAuthStrategyIsNull() { + IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> docScanService.deleteTrackedDevices(null, SOME_SESSION_ID)); + assertThat(exception.getMessage(), containsString("'authStrategy' must not be null.")); } @Test public void deleteTrackedDevices_shouldThrowExceptionWhenSessionIdIsNull() { - IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> docScanService.deleteTrackedDevices(SOME_APP_ID, KEY_PAIR, null)); + IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> docScanService.deleteTrackedDevices( + authStrategyMock, null)); assertThat(exception.getMessage(), containsString("sessionId")); } @Test public void deleteTrackedDevices_shouldThrowExceptionWhenSessionIdIsEmpty() { - IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> docScanService.deleteTrackedDevices(SOME_APP_ID, KEY_PAIR, "")); + IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> docScanService.deleteTrackedDevices( + authStrategyMock, "")); assertThat(exception.getMessage(), containsString("sessionId")); } @Test public void deleteTrackedDevices_shouldWrapGeneralSecurityException() throws Exception { GeneralSecurityException gse = new GeneralSecurityException("some gse"); - when(signedRequestBuilderMock.build()).thenThrow(gse); + when(yotiHttpRequestBuilderMock.build()).thenThrow(gse); - DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.deleteTrackedDevices(SOME_APP_ID, KEY_PAIR, SOME_SESSION_ID)); + DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.deleteTrackedDevices(authStrategyMock, SOME_SESSION_ID)); assertSame(ex.getCause(), gse); assertThat(ex.getMessage(), containsString("Error executing the GET: some gse")); @@ -1582,10 +1386,10 @@ public void deleteTrackedDevices_shouldWrapGeneralSecurityException() throws Exc @Test public void deleteTrackedDevices_shouldWrapResourceException() throws Exception { ResourceException resourceException = new ResourceException(400, "Failed Request", "Some response from API"); - when(signedRequestBuilderMock.build()).thenReturn(signedRequestMock); - when(signedRequestMock.execute()).thenThrow(resourceException); + when(yotiHttpRequestBuilderMock.build()).thenReturn(yotiHttpRequestMock); + when(yotiHttpRequestMock.execute()).thenThrow(resourceException); - DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.deleteTrackedDevices(SOME_APP_ID, KEY_PAIR, SOME_SESSION_ID)); + DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.deleteTrackedDevices(authStrategyMock, SOME_SESSION_ID)); assertSame(ex.getCause(), resourceException); assertThat(ex.getMessage(), containsString("Error executing the GET: Failed Request")); @@ -1594,10 +1398,10 @@ public void deleteTrackedDevices_shouldWrapResourceException() throws Exception @Test public void deleteTrackedDevices_shouldWrapIOException() throws Exception { IOException ioException = new IOException("Some io exception"); - when(signedRequestBuilderMock.build()).thenReturn(signedRequestMock); - when(signedRequestMock.execute()).thenThrow(ioException); + when(yotiHttpRequestBuilderMock.build()).thenReturn(yotiHttpRequestMock); + when(yotiHttpRequestMock.execute()).thenThrow(ioException); - DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.deleteTrackedDevices(SOME_APP_ID, KEY_PAIR, SOME_SESSION_ID)); + DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.deleteTrackedDevices(authStrategyMock, SOME_SESSION_ID)); assertSame(ex.getCause(), ioException); assertThat(ex.getMessage(), containsString("Error building the request: Some io exception")); @@ -1606,9 +1410,9 @@ public void deleteTrackedDevices_shouldWrapIOException() throws Exception { @Test public void deleteTrackedDevices_shouldWrapURISyntaxException() throws Exception { URISyntaxException uriSyntaxException = new URISyntaxException("someUrl", "Failed to build URI"); - when(signedRequestBuilderMock.build()).thenThrow(uriSyntaxException); + when(yotiHttpRequestBuilderMock.build()).thenThrow(uriSyntaxException); - DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.deleteTrackedDevices(SOME_APP_ID, KEY_PAIR, SOME_SESSION_ID)); + DocScanException ex = assertThrows(DocScanException.class, () -> docScanService.deleteTrackedDevices(authStrategyMock, SOME_SESSION_ID)); assertSame(ex.getCause(), uriSyntaxException); assertThat(ex.getMessage(), containsString("Error building the request: Failed to build URI: someUrl")); diff --git a/yoti-sdk-api/src/test/java/com/yoti/api/client/docs/session/create/SessionSpecTest.java b/yoti-sdk-api/src/test/java/com/yoti/api/client/docs/session/create/SessionSpecTest.java index d0bb1463f..5a78a9dd5 100644 --- a/yoti-sdk-api/src/test/java/com/yoti/api/client/docs/session/create/SessionSpecTest.java +++ b/yoti-sdk-api/src/test/java/com/yoti/api/client/docs/session/create/SessionSpecTest.java @@ -1,10 +1,8 @@ package com.yoti.api.client.docs.session.create; -import static com.yoti.api.client.spi.remote.call.YotiConstants.DEFAULT_CHARSET; - import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.contains; -import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.containsInRelativeOrder; import static org.hamcrest.Matchers.hasItems; import static org.hamcrest.Matchers.hasSize; import static org.hamcrest.Matchers.instanceOf; @@ -12,20 +10,15 @@ import static org.hamcrest.Matchers.notNullValue; import static org.hamcrest.Matchers.nullValue; -import java.io.IOException; import java.time.ZonedDateTime; -import java.util.HashMap; -import java.util.Map; import com.yoti.api.client.docs.session.create.check.RequestedDocumentAuthenticityCheck; import com.yoti.api.client.docs.session.create.check.RequestedLivenessCheck; import com.yoti.api.client.docs.session.create.filters.RequiredDocument; +import com.yoti.api.client.docs.session.create.identityprofile.simple.IdentityProfileRequirementsPayload; import com.yoti.api.client.docs.session.create.resources.ResourceCreationContainer; import com.yoti.api.client.docs.session.create.task.RequestedIdDocTextExtractionTask; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import org.hamcrest.Matchers; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; @@ -50,13 +43,13 @@ public class SessionSpecTest { private static final String SOME_SDK_CONFIG_SUCCESS_URL = "https://yourdomain.com/some/success/endpoint"; private static final String SOME_SDK_CONFIG_ERROR_URL = "https://yourdomain.com/some/error/endpoint"; - private static final ObjectMapper MAPPER = new ObjectMapper(); - @Mock RequiredDocument requiredDocumentMock; @Mock IbvOptions ibvOptionsMock; @Mock ZonedDateTime sessionDeadlineMock; @Mock ResourceCreationContainer resourceCreationContainerMock; @Mock ImportTokenPayload importTokenMock; + @Mock IdentityProfileRequirementsPayload identityProfileRequirementsPayloadMock; + @Mock SubjectPayload subjectPayloadMock; @Test public void shouldBuildWithMinimalConfiguration() { @@ -215,51 +208,21 @@ public void withSessionDeadline_shouldSetTheSessionDeadline() { } @Test - public void shouldBuildWithIdentityProfileRequirements() throws IOException { - Map scheme = new HashMap<>(); - scheme.put(IdentityProperty.TYPE, "A_TYPE"); - scheme.put(IdentityProperty.OBJECTIVE, "AN_OBJECTIVE"); - - Map identityProfile = new HashMap<>(); - identityProfile.put(IdentityProperty.TRUST_FRAMEWORK, "A_FRAMEWORK"); - identityProfile.put(IdentityProperty.SCHEME, scheme); - - JsonNode json = toSessionSpecJson(identityProfile); - - assertThat( - json.get(IdentityProperty.TRUST_FRAMEWORK).asText(), - is(equalTo(identityProfile.get(IdentityProperty.TRUST_FRAMEWORK))) - ); - - JsonNode schemeJsonNode = json.get(IdentityProperty.SCHEME); - assertThat(schemeJsonNode.get(IdentityProperty.TYPE).asText(), is(equalTo(scheme.get(IdentityProperty.TYPE)))); - assertThat(schemeJsonNode.get(IdentityProperty.OBJECTIVE).asText(), is(equalTo(scheme.get(IdentityProperty.OBJECTIVE)))); - } - - private static JsonNode toSessionSpecJson(Map obj) throws IOException { - SessionSpec session = SessionSpec.builder() - .withIdentityProfile(obj) + public void withIdentityProfile_shouldSetTheIdentityProfile() { + SessionSpec result = SessionSpec.builder() + .withIdentityProfile(identityProfileRequirementsPayloadMock) .build(); - return MAPPER.readTree(MAPPER.writeValueAsString(session.getIdentityProfile()).getBytes(DEFAULT_CHARSET)); + assertThat(result.getIdentityProfile(), is(identityProfileRequirementsPayloadMock)); } @Test - public void shouldBuildWithSubject() throws IOException { - Map subject = new HashMap<>(); - subject.put(SubjectProperty.SUBJECT_ID, "A_SUBJECT_ID"); - - SessionSpec session = SessionSpec.builder() - .withSubject(subject) + public void withSubject_shouldSetTheSubject() { + SessionSpec result = SessionSpec.builder() + .withSubject(subjectPayloadMock) .build(); - ObjectMapper mapper = new ObjectMapper(); - - JsonNode json = mapper.readTree( - mapper.writeValueAsString(session.getSubject()).getBytes(DEFAULT_CHARSET) - ); - - assertThat(json.get("subject_id").asText(), is(Matchers.equalTo(subject.get(SubjectProperty.SUBJECT_ID)))); + assertThat(result.getSubject(), is(subjectPayloadMock)); } @Test @@ -289,23 +252,4 @@ public void shouldBuildWithImportToken() { assertThat(sessionSpec.getImportToken(), is(importTokenMock)); } - private static final class IdentityProperty { - - private static final String TYPE = "type"; - private static final String SCHEME = "scheme"; - private static final String OBJECTIVE = "objective"; - private static final String TRUST_FRAMEWORK = "trust_framework"; - - private IdentityProperty() { } - - } - - private static final class SubjectProperty { - - private static final String SUBJECT_ID = "subject_id"; - - private SubjectProperty() {} - - } - } diff --git a/yoti-sdk-api/src/test/java/com/yoti/api/client/spi/remote/ReceiptFetcherTest.java b/yoti-sdk-api/src/test/java/com/yoti/api/client/spi/remote/ReceiptFetcherTest.java index 5ee4bc815..4b6a2911a 100644 --- a/yoti-sdk-api/src/test/java/com/yoti/api/client/spi/remote/ReceiptFetcherTest.java +++ b/yoti-sdk-api/src/test/java/com/yoti/api/client/spi/remote/ReceiptFetcherTest.java @@ -6,14 +6,16 @@ import static org.bouncycastle.util.encoders.Base64.decode; import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.*; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.not; import static org.hamcrest.core.StringContains.containsString; import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.*; -import static org.mockito.Mockito.*; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.when; import java.security.KeyPair; import java.security.PublicKey; @@ -30,10 +32,12 @@ import com.yoti.api.client.spi.remote.util.CryptoUtil; import com.fasterxml.jackson.databind.ObjectMapper; -import org.junit.*; +import org.junit.Before; +import org.junit.Test; import org.junit.runner.RunWith; -import org.mockito.*; -import org.mockito.junit.*; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnitRunner; @RunWith(MockitoJUnitRunner.class) public class ReceiptFetcherTest { @@ -62,7 +66,7 @@ public void setUp() throws Exception { @Test public void shouldFailForNullToken() { try { - testObj.fetch(null, keyPair, APP_ID); + testObj.fetch(null, keyPair); } catch (ProfileException ex) { assertThat(ex.getMessage(), containsString("Cannot decrypt connect token")); assertTrue(ex.getCause() instanceof NullPointerException); @@ -74,7 +78,7 @@ public void shouldFailForNullToken() { @Test public void shouldFailForNonBase64Token() { try { - testObj.fetch(TOKEN, keyPair, APP_ID); + testObj.fetch(TOKEN, keyPair); } catch (ProfileException ex) { assertThat(ex.getMessage(), containsString("Cannot decrypt connect token")); assertTrue(ex.getCause() instanceof IllegalArgumentException); @@ -86,7 +90,7 @@ public void shouldFailForNonBase64Token() { @Test public void shouldFailForBadlyEncryptedToken() { try { - testObj.fetch(Base64.getEncoder().encodeToString(TOKEN.getBytes()), keyPair, APP_ID); + testObj.fetch(Base64.getEncoder().encodeToString(TOKEN.getBytes()), keyPair); } catch (ProfileException ex) { assertThat(ex.getMessage(), containsString("Cannot decrypt connect token")); assertTrue(ex.getCause() instanceof ProfileException); @@ -99,10 +103,10 @@ public void shouldFailForBadlyEncryptedToken() { @Test public void shouldFailWithExceptionFromProfileService() throws Exception { ProfileException profileException = new ProfileException("Test exception"); - when(profileService.getProfile(any(KeyPair.class), anyString(), anyString())).thenThrow(profileException); + when(profileService.getProfile(any(KeyPair.class), anyString())).thenThrow(profileException); try { - testObj.fetch(encryptedToken, keyPair, APP_ID); + testObj.fetch(encryptedToken, keyPair); } catch (ProfileException ex) { assertSame(profileException, ex); return; @@ -112,10 +116,10 @@ public void shouldFailWithExceptionFromProfileService() throws Exception { @Test public void shouldFailWhenNoProfileReturned() throws Exception { - when(profileService.getProfile(any(KeyPair.class), anyString(), anyString())).thenReturn(null); + when(profileService.getProfile(any(KeyPair.class), anyString())).thenReturn(null); try { - testObj.fetch(encryptedToken, keyPair, APP_ID); + testObj.fetch(encryptedToken, keyPair); } catch (ProfileException e) { assertThat(e.getMessage(), containsString("No profile")); assertThat(e.getMessage(), containsString(TOKEN)); @@ -126,11 +130,11 @@ public void shouldFailWhenNoProfileReturned() throws Exception { @Test public void shouldFailWhenNoReceiptReturned() throws Exception { - when(profileService.getProfile(any(KeyPair.class), anyString(), anyString())) + when(profileService.getProfile(any(KeyPair.class), anyString())) .thenReturn(new ProfileResponse.ProfileResponseBuilder().build()); try { - testObj.fetch(encryptedToken, keyPair, APP_ID); + testObj.fetch(encryptedToken, keyPair); } catch (ProfileException e) { assertThat(e.getMessage(), containsString("No profile")); assertThat(e.getMessage(), containsString(TOKEN)); @@ -154,10 +158,10 @@ public void shouldFailForFailureReceiptWithErrorCode() throws Exception { .setReceipt(receipt) .setError(error) .build(); - when(profileService.getProfile(keyPair, APP_ID, TOKEN)).thenReturn(profileResponse); + when(profileService.getProfile(keyPair, TOKEN)).thenReturn(profileResponse); try { - testObj.fetch(encryptedToken, keyPair, APP_ID); + testObj.fetch(encryptedToken, keyPair); } catch (ActivityFailureException ex) { String exMsg = ex.getMessage(); assertThat(exMsg, containsString(ENCODED_RECEIPT_STRING)); @@ -182,10 +186,10 @@ public void shouldFailForFailureReceiptWithNoErrorCode() throws Exception { .build(); ProfileResponse profileResponse = new ProfileResponse.ProfileResponseBuilder().setReceipt(receipt).build(); - when(profileService.getProfile(keyPair, APP_ID, TOKEN)).thenReturn(profileResponse); + when(profileService.getProfile(keyPair, TOKEN)).thenReturn(profileResponse); try { - testObj.fetch(encryptedToken, keyPair, APP_ID); + testObj.fetch(encryptedToken, keyPair); } catch (ActivityFailureException ex) { assertThat(ex.getMessage(), containsString(ENCODED_RECEIPT_STRING)); assertThat(ex.getMessage(), not(containsString("error"))); @@ -215,10 +219,10 @@ public void shouldFailForFailureReceiptWithErrorReason() throws Exception { .setReceipt(receipt) .setError(error) .build(); - when(profileService.getProfile(keyPair, APP_ID, TOKEN)).thenReturn(profileResponse); + when(profileService.getProfile(keyPair, TOKEN)).thenReturn(profileResponse); try { - testObj.fetch(encryptedToken, keyPair, APP_ID); + testObj.fetch(encryptedToken, keyPair); } catch (ActivityFailureException ex) { String exMsg = ex.getMessage(); assertThat(exMsg, containsString(ENCODED_RECEIPT_STRING)); @@ -242,9 +246,9 @@ public void shouldReturnSuccessReceipt() throws Exception { .build(); ProfileResponse profileResponse = new ProfileResponse.ProfileResponseBuilder().setReceipt(receipt).build(); - when(profileService.getProfile(keyPair, APP_ID, TOKEN)).thenReturn(profileResponse); + when(profileService.getProfile(keyPair, TOKEN)).thenReturn(profileResponse); - Receipt result = testObj.fetch(encryptedToken, keyPair, APP_ID); + Receipt result = testObj.fetch(encryptedToken, keyPair); assertSame(result, receipt); } diff --git a/yoti-sdk-api/src/test/java/com/yoti/api/client/spi/remote/call/ImageResourceFetcherTest.java b/yoti-sdk-api/src/test/java/com/yoti/api/client/spi/remote/call/ImageResourceFetcherTest.java index e3494d70a..c45c1ca08 100644 --- a/yoti-sdk-api/src/test/java/com/yoti/api/client/spi/remote/call/ImageResourceFetcherTest.java +++ b/yoti-sdk-api/src/test/java/com/yoti/api/client/spi/remote/call/ImageResourceFetcherTest.java @@ -29,7 +29,7 @@ public class ImageResourceFetcherTest { @InjectMocks ImageResourceFetcher testObj; @Mock RawResourceFetcher rawResourceFetcherMock; - @Mock SignedRequest signedRequestMock; + @Mock YotiHttpRequest yotiHttpRequestMock; private Map> createResponseHeaderMap(String name, List values) { HashMap> result = new HashMap<>(); @@ -40,10 +40,10 @@ private Map> createResponseHeaderMap(String name, List> headersMap = createResponseHeaderMap("Content-Type", asList(YotiConstants.CONTENT_TYPE_PNG)); - SignedRequestResponse signedRequestResponse = new SignedRequestResponse(SOME_OK_STATUS_CODE, SOME_RESPONSE_BODY, headersMap); - when(rawResourceFetcherMock.doRequest(signedRequestMock)).thenReturn(signedRequestResponse); + YotiHttpResponse yotiHttpResponse = new YotiHttpResponse(SOME_OK_STATUS_CODE, SOME_RESPONSE_BODY, headersMap); + when(rawResourceFetcherMock.doRequest(yotiHttpRequestMock)).thenReturn(yotiHttpResponse); - Image result = testObj.doRequest(signedRequestMock); + Image result = testObj.doRequest(yotiHttpRequestMock); assertThat(result.getMimeType(), is(YotiConstants.CONTENT_TYPE_PNG)); assertTrue(Arrays.equals(result.getContent(), SOME_RESPONSE_BODY)); @@ -52,10 +52,10 @@ public void doRequest_shouldReturnPngImage() throws Exception { @Test public void doRequest_shouldReturnJpegImage() throws Exception { Map> headersMap = createResponseHeaderMap("Content-Type", asList(YotiConstants.CONTENT_TYPE_JPEG)); - SignedRequestResponse signedRequestResponse = new SignedRequestResponse(SOME_OK_STATUS_CODE, SOME_RESPONSE_BODY, headersMap); - when(rawResourceFetcherMock.doRequest(signedRequestMock)).thenReturn(signedRequestResponse); + YotiHttpResponse yotiHttpResponse = new YotiHttpResponse(SOME_OK_STATUS_CODE, SOME_RESPONSE_BODY, headersMap); + when(rawResourceFetcherMock.doRequest(yotiHttpRequestMock)).thenReturn(yotiHttpResponse); - Image result = testObj.doRequest(signedRequestMock); + Image result = testObj.doRequest(yotiHttpRequestMock); String mimeType = result.getMimeType(); byte[] content = result.getContent(); @@ -67,10 +67,10 @@ public void doRequest_shouldReturnJpegImage() throws Exception { @Test(expected = ResourceException.class) public void doRequest_shouldThrowResourceExceptionForUnsupportedImageType() throws Exception { Map> headersMap = createResponseHeaderMap("Content-Type", asList("image/webp")); - SignedRequestResponse signedRequestResponse = new SignedRequestResponse(SOME_OK_STATUS_CODE, SOME_RESPONSE_BODY, headersMap); - when(rawResourceFetcherMock.doRequest(signedRequestMock)).thenReturn(signedRequestResponse); + YotiHttpResponse yotiHttpResponse = new YotiHttpResponse(SOME_OK_STATUS_CODE, SOME_RESPONSE_BODY, headersMap); + when(rawResourceFetcherMock.doRequest(yotiHttpRequestMock)).thenReturn(yotiHttpResponse); - testObj.doRequest(signedRequestMock); + testObj.doRequest(yotiHttpRequestMock); } } diff --git a/yoti-sdk-api/src/test/java/com/yoti/api/client/spi/remote/call/JsonResourceFetcherTest.java b/yoti-sdk-api/src/test/java/com/yoti/api/client/spi/remote/call/JsonResourceFetcherTest.java index 1253590be..9dfb79c7a 100644 --- a/yoti-sdk-api/src/test/java/com/yoti/api/client/spi/remote/call/JsonResourceFetcherTest.java +++ b/yoti-sdk-api/src/test/java/com/yoti/api/client/spi/remote/call/JsonResourceFetcherTest.java @@ -21,46 +21,46 @@ public class JsonResourceFetcherTest { @Mock ObjectMapper objectMapperMock; @Mock RawResourceFetcher rawResourceFetcherMock; - @Mock SignedRequest signedRequestMock; - @Mock SignedRequestResponse signedRequestResponseMock; + @Mock YotiHttpRequest yotiHttpRequestMock; + @Mock YotiHttpResponse yotiHttpResponseMock; Object parsedResponse = new Object(); @Before public void setUp() throws Exception { - when(rawResourceFetcherMock.doRequest(signedRequestMock)).thenReturn(signedRequestResponseMock); + when(rawResourceFetcherMock.doRequest(yotiHttpRequestMock)).thenReturn(yotiHttpResponseMock); } @Test public void fetchResource_shouldReturnResource() throws Exception { - when(objectMapperMock.readValue(signedRequestResponseMock.getResponseBody(), Object.class)).thenReturn(parsedResponse); + when(objectMapperMock.readValue(yotiHttpResponseMock.getResponseBody(), Object.class)).thenReturn(parsedResponse); - Object result = testObj.doRequest(signedRequestMock, Object.class); + Object result = testObj.doRequest(yotiHttpRequestMock, Object.class); assertSame(parsedResponse, result); } @Test(expected = IOException.class) public void fetchResource_shouldThrowIOExceptionForInvalidResponse() throws Exception { - when(objectMapperMock.readValue(signedRequestResponseMock.getResponseBody(), Object.class)).thenThrow(new IOException()); + when(objectMapperMock.readValue(yotiHttpResponseMock.getResponseBody(), Object.class)).thenThrow(new IOException()); - testObj.doRequest(signedRequestMock, Object.class); + testObj.doRequest(yotiHttpRequestMock, Object.class); } @Test public void doRequest_shouldReturnResource() throws Exception { - when(objectMapperMock.readValue(signedRequestResponseMock.getResponseBody(), Object.class)).thenReturn(parsedResponse); + when(objectMapperMock.readValue(yotiHttpResponseMock.getResponseBody(), Object.class)).thenReturn(parsedResponse); - Object result = testObj.doRequest(signedRequestMock, Object.class); + Object result = testObj.doRequest(yotiHttpRequestMock, Object.class); assertSame(parsedResponse, result); } @Test(expected = IOException.class) public void doRequest_shouldThrowIOExceptionForInvalidResponse() throws Exception { - when(objectMapperMock.readValue(signedRequestResponseMock.getResponseBody(), Object.class)).thenThrow(new IOException()); + when(objectMapperMock.readValue(yotiHttpResponseMock.getResponseBody(), Object.class)).thenThrow(new IOException()); - testObj.doRequest(signedRequestMock, Object.class); + testObj.doRequest(yotiHttpRequestMock, Object.class); } } diff --git a/yoti-sdk-api/src/test/java/com/yoti/api/client/spi/remote/call/ProfileServiceTest.java b/yoti-sdk-api/src/test/java/com/yoti/api/client/spi/remote/call/ProfileServiceTest.java index e95ce4e43..0b50dca59 100644 --- a/yoti-sdk-api/src/test/java/com/yoti/api/client/spi/remote/call/ProfileServiceTest.java +++ b/yoti-sdk-api/src/test/java/com/yoti/api/client/spi/remote/call/ProfileServiceTest.java @@ -5,19 +5,25 @@ import static org.junit.Assert.assertSame; import static org.junit.Assert.fail; -import static org.mockito.Mockito.*; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.when; import java.io.IOException; import java.security.KeyPair; import java.util.Base64; import com.yoti.api.client.ProfileException; +import com.yoti.api.client.spi.remote.call.factory.ProfileSignedRequestStrategy; import com.yoti.api.client.spi.remote.call.factory.UnsignedPathFactory; -import org.junit.*; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; import org.junit.runner.RunWith; -import org.mockito.*; -import org.mockito.junit.*; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Spy; +import org.mockito.junit.MockitoJUnitRunner; @RunWith(MockitoJUnitRunner.class) public class ProfileServiceTest { @@ -40,7 +46,8 @@ public class ProfileServiceTest { @Mock UnsignedPathFactory unsignedPathFactory; - @Mock SignedRequest signedRequest; + @Mock ProfileSignedRequestStrategy profileSignedRequestStrategyMock; + @Mock YotiHttpRequest yotiHttpRequest; @BeforeClass public static void setUpClass() throws Exception { @@ -50,26 +57,27 @@ public static void setUpClass() throws Exception { @Before public void setUp() { - when(unsignedPathFactory.createProfilePath(APP_ID, TOKEN)).thenReturn(GENERATED_PROFILE_PATH); + when(unsignedPathFactory.createProfilePath(TOKEN)).thenReturn(GENERATED_PROFILE_PATH); } @Test public void shouldReturnReceiptForCorrectRequest() throws Exception { - doReturn(signedRequest).when(testObj).createSignedRequest(KEY_PAIR, GENERATED_PROFILE_PATH, B64_PUBLIC_KEY); - when(signedRequest.execute(ProfileResponse.class)).thenReturn(PROFILE_RESPONSE); + doReturn(yotiHttpRequest).when(testObj).createRequest(GENERATED_PROFILE_PATH, B64_PUBLIC_KEY); + when(yotiHttpRequest.execute(ProfileResponse.class)).thenReturn(PROFILE_RESPONSE); + + Receipt result = testObj.getReceipt(KEY_PAIR, TOKEN); - Receipt result = testObj.getReceipt(KEY_PAIR, APP_ID, TOKEN); assertSame(RECEIPT, result); } @Test public void shouldThrowExceptionForIOError() throws Exception { IOException ioException = new IOException("Test exception"); - doReturn(signedRequest).when(testObj).createSignedRequest(KEY_PAIR, GENERATED_PROFILE_PATH, B64_PUBLIC_KEY); - when(signedRequest.execute(ProfileResponse.class)).thenThrow(ioException); + doReturn(yotiHttpRequest).when(testObj).createRequest(GENERATED_PROFILE_PATH, B64_PUBLIC_KEY); + when(yotiHttpRequest.execute(ProfileResponse.class)).thenThrow(ioException); try { - testObj.getReceipt(KEY_PAIR, APP_ID, TOKEN); + testObj.getReceipt(KEY_PAIR, TOKEN); fail("Expected a ProfileException"); } catch (ProfileException e) { assertSame(ioException, e.getCause()); @@ -79,11 +87,11 @@ public void shouldThrowExceptionForIOError() throws Exception { @Test public void shouldThrowExceptionWithResourceExceptionCause() throws Throwable { ResourceException resourceException = new ResourceException(404, "Not Found", "Test exception"); - doReturn(signedRequest).when(testObj).createSignedRequest(KEY_PAIR, GENERATED_PROFILE_PATH, B64_PUBLIC_KEY); - when(signedRequest.execute(ProfileResponse.class)).thenThrow(resourceException); + doReturn(yotiHttpRequest).when(testObj).createRequest(GENERATED_PROFILE_PATH, B64_PUBLIC_KEY); + when(yotiHttpRequest.execute(ProfileResponse.class)).thenThrow(resourceException); try { - testObj.getReceipt(KEY_PAIR, APP_ID, TOKEN); + testObj.getReceipt(KEY_PAIR, TOKEN); fail("Expected a ProfileException"); } catch (ProfileException e) { assertSame(resourceException, e.getCause()); @@ -92,17 +100,12 @@ public void shouldThrowExceptionWithResourceExceptionCause() throws Throwable { @Test(expected = IllegalArgumentException.class) public void shouldFailWithNullKeyPair() throws Exception { - testObj.getReceipt(null, APP_ID, TOKEN); - } - - @Test(expected = IllegalArgumentException.class) - public void shouldFailWithNullAppId() throws Exception { - testObj.getReceipt(KEY_PAIR, null, TOKEN); + testObj.getReceipt(null, TOKEN); } @Test(expected = IllegalArgumentException.class) public void shouldFailWithNullConnectToken() throws Exception { - testObj.getReceipt(KEY_PAIR, APP_ID, null); + testObj.getReceipt(KEY_PAIR, null); } } diff --git a/yoti-sdk-api/src/test/java/com/yoti/api/client/spi/remote/call/RawResourceFetcherTest.java b/yoti-sdk-api/src/test/java/com/yoti/api/client/spi/remote/call/RawResourceFetcherTest.java index 492346298..fb0e965b2 100644 --- a/yoti-sdk-api/src/test/java/com/yoti/api/client/spi/remote/call/RawResourceFetcherTest.java +++ b/yoti-sdk-api/src/test/java/com/yoti/api/client/spi/remote/call/RawResourceFetcherTest.java @@ -66,7 +66,7 @@ public void doRequest_shouldReturnByteArray() throws Exception { when(httpURLConnectionMock.getInputStream()).thenReturn(inputStreamSpy); when(httpURLConnectionMock.getResponseCode()).thenReturn(HTTP_OK); - SignedRequestResponse result = testObj.doRequest(urlConnectorMock, HttpMethod.HTTP_GET, null, TEST_HEADERS); + YotiHttpResponse result = testObj.doRequest(urlConnectorMock, HttpMethod.HTTP_GET, null, TEST_HEADERS); verify(httpURLConnectionMock).setRequestMethod("GET"); verify(httpURLConnectionMock).setRequestProperty(TEST_HEADER_KEY, TEST_HEADER_VALUE); @@ -82,7 +82,7 @@ public void chunkRead_shouldHandleInputStreamSmallerThanDefaultChunkSize() throw when(httpURLConnectionMock.getInputStream()).thenReturn(smallerSizeByteArray); when(httpURLConnectionMock.getResponseCode()).thenReturn(HTTP_OK); - SignedRequestResponse result = testObj.doRequest(urlConnectorMock, HttpMethod.HTTP_GET, null, TEST_HEADERS); + YotiHttpResponse result = testObj.doRequest(urlConnectorMock, HttpMethod.HTTP_GET, null, TEST_HEADERS); verify(httpURLConnectionMock).setRequestMethod("GET"); verify(httpURLConnectionMock).setRequestProperty(TEST_HEADER_KEY, TEST_HEADER_VALUE); @@ -98,7 +98,7 @@ public void chunkRead_shouldHandleInputStreamLargerThanDefaultChunkSize() throws when(httpURLConnectionMock.getInputStream()).thenReturn(largerSizeByteArray); when(httpURLConnectionMock.getResponseCode()).thenReturn(HTTP_OK); - SignedRequestResponse result = testObj.doRequest(urlConnectorMock, HttpMethod.HTTP_GET, null, TEST_HEADERS); + YotiHttpResponse result = testObj.doRequest(urlConnectorMock, HttpMethod.HTTP_GET, null, TEST_HEADERS); verify(httpURLConnectionMock).setRequestMethod("GET"); verify(httpURLConnectionMock).setRequestProperty(TEST_HEADER_KEY, TEST_HEADER_VALUE); @@ -165,7 +165,7 @@ public void doRequest_shouldSendBodyAndReturnResponse() throws Exception { when(httpURLConnectionMock.getResponseCode()).thenReturn(HTTP_OK); when(httpURLConnectionMock.getInputStream()).thenReturn(inputStreamSpy); - SignedRequestResponse result = testObj.doRequest(urlConnectorMock, HttpMethod.HTTP_POST, requestBody, TEST_HEADERS); + YotiHttpResponse result = testObj.doRequest(urlConnectorMock, HttpMethod.HTTP_POST, requestBody, TEST_HEADERS); verify(httpURLConnectionMock).setRequestMethod("POST"); verify(httpURLConnectionMock).setRequestProperty(TEST_HEADER_KEY, TEST_HEADER_VALUE); diff --git a/yoti-sdk-api/src/test/java/com/yoti/api/client/spi/remote/call/SignedRequestBuilderTest.java b/yoti-sdk-api/src/test/java/com/yoti/api/client/spi/remote/call/YotiHttpRequestBuilderTest.java similarity index 66% rename from yoti-sdk-api/src/test/java/com/yoti/api/client/spi/remote/call/SignedRequestBuilderTest.java rename to yoti-sdk-api/src/test/java/com/yoti/api/client/spi/remote/call/YotiHttpRequestBuilderTest.java index ff15ad7f6..c6dc3fc17 100644 --- a/yoti-sdk-api/src/test/java/com/yoti/api/client/spi/remote/call/SignedRequestBuilderTest.java +++ b/yoti-sdk-api/src/test/java/com/yoti/api/client/spi/remote/call/YotiHttpRequestBuilderTest.java @@ -1,11 +1,11 @@ package com.yoti.api.client.spi.remote.call; +import static java.util.Arrays.asList; + import static com.yoti.api.client.spi.remote.call.HttpMethod.HTTP_GET; import static com.yoti.api.client.spi.remote.call.YotiConstants.CONTENT_TYPE; import static com.yoti.api.client.spi.remote.call.YotiConstants.DEFAULT_YOTI_API_URL; import static com.yoti.api.client.spi.remote.call.YotiConstants.DIGEST_HEADER; -import static com.yoti.api.client.spi.remote.util.CryptoUtil.KEY_PAIR_PEM; -import static com.yoti.api.client.spi.remote.util.CryptoUtil.generateKeyPairFrom; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.MatcherAssert.assertThat; @@ -15,49 +15,56 @@ import static org.junit.Assert.assertNull; import static org.junit.Assert.assertThrows; import static org.junit.Assert.fail; -import static org.mockito.ArgumentMatchers.*; -import static org.mockito.Mockito.*; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; import java.io.IOException; import java.io.OutputStream; -import java.security.KeyPair; -import java.security.PrivateKey; import java.security.Security; +import java.util.Collections; import java.util.HashMap; +import java.util.List; import java.util.Map; +import com.yoti.api.client.spi.remote.call.factory.AuthStrategy; import com.yoti.api.client.spi.remote.call.factory.HeadersFactory; -import com.yoti.api.client.spi.remote.call.factory.PathFactory; -import com.yoti.api.client.spi.remote.call.factory.SignedMessageFactory; import org.apache.http.Header; -import org.apache.http.HeaderElement; import org.apache.http.HttpEntity; import org.apache.http.entity.ContentType; import org.apache.http.entity.mime.MultipartEntityBuilder; +import org.apache.http.message.BasicHeader; +import org.apache.http.message.BasicNameValuePair; import org.bouncycastle.jce.provider.BouncyCastleProvider; -import org.junit.*; +import org.junit.Test; import org.junit.runner.RunWith; -import org.mockito.*; -import org.mockito.junit.*; +import org.mockito.Answers; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockedStatic; +import org.mockito.Mockito; +import org.mockito.junit.MockitoJUnitRunner; import org.mockito.stubbing.Answer; @RunWith(MockitoJUnitRunner.class) -public class SignedRequestBuilderTest { +public class YotiHttpRequestBuilderTest { private static final String SOME_ENDPOINT = "/someEndpoint"; private static final String SOME_SIGNATURE = "someSignature"; private static final Map SIGNED_REQUEST_HEADERS; private static final String SOME_BASE_URL = "someBaseUrl"; private static final byte[] SOME_BYTES = "someBytes".getBytes(); - private static final String SIGNATURE_PARAMS_STRING = "nonce=someNonce×tamp=someTimestamp"; + private static final String SIGNATURE_PARAMS_STRING = "timestamp=someTimestamp"; private static final String SOME_MULTIPART_BODY_NAME = "someMultipartBodyName"; private static final byte[] SOME_MULTIPART_BODY = new byte[]{ 1, 2, 3, 4 }; private static final ContentType SOME_MULTIPART_CONTENT_TYPE = ContentType.IMAGE_JPEG; private static final String SOME_MULTIPART_FILE_NAME = "someMultipartFileName"; private static final String SOME_MULTIPART_BOUNDARY = "someMultipartBoundary"; private static final byte[] SOME_BUILT_MULTIPART_BODY = new byte[]{ 5, 6, 7, 8 }; - private static KeyPair KEY_PAIR; static { Security.addProvider(new BouncyCastleProvider()); @@ -66,27 +73,19 @@ public class SignedRequestBuilderTest { SIGNED_REQUEST_HEADERS.put(YotiConstants.DIGEST_HEADER, SOME_SIGNATURE); } - @BeforeClass - public static void setUpClass() throws Exception { - KEY_PAIR = generateKeyPairFrom(KEY_PAIR_PEM); - } - - @InjectMocks SignedRequestBuilder signedRequestBuilder; + @InjectMocks YotiHttpRequestBuilder yotiHttpRequestBuilder; - @Mock PathFactory pathFactoryMock; - @Mock SignedMessageFactory signedMessageFactoryMock; @Mock HeadersFactory headersFactoryMock; @Mock MultipartEntityBuilder multipartEntityBuilderMock; - @Captor ArgumentCaptor pathCaptor; @Mock(answer = Answers.RETURNS_SELF) HttpEntity httpEntityMock; - @Mock Header headerMock; - @Mock HeaderElement headerElementMock; + List
authHeaders = Collections.singletonList(mock(Header.class)); + @Mock AuthStrategy authStrategyMock; @Test public void withHttpMethod_shouldThrowExceptionWhenSuppliedWithUnsupportedHttpMethod() { try { - signedRequestBuilder.withHttpMethod("someNonsenseHere"); + yotiHttpRequestBuilder.withHttpMethod("someNonsenseHere"); } catch (IllegalArgumentException e) { assertThat(e.getMessage(), containsString("someNonsenseHere")); return; @@ -96,11 +95,11 @@ public void withHttpMethod_shouldThrowExceptionWhenSuppliedWithUnsupportedHttpMe } @Test - public void build_shouldThrowExceptionWhenMissingKeyPair() throws Exception { + public void build_shouldThrowExceptionWhenMissingAuthStrategy() throws Exception { try { - signedRequestBuilder.build(); + yotiHttpRequestBuilder.build(); } catch (IllegalArgumentException e) { - assertThat(e.getMessage(), containsString("keyPair")); + assertThat(e.getMessage(), containsString("'authStrategy' must not be null")); return; } fail("Expected an IllegalArgumentException"); @@ -109,7 +108,7 @@ public void build_shouldThrowExceptionWhenMissingKeyPair() throws Exception { @Test public void build_shouldThrowExceptionWhenMissingBaseUrl() throws Exception { try { - signedRequestBuilder.withKeyPair(KEY_PAIR) + yotiHttpRequestBuilder.withAuthStrategy(authStrategyMock) .build(); } catch (IllegalArgumentException e) { assertThat(e.getMessage(), containsString("baseUrl")); @@ -121,7 +120,7 @@ public void build_shouldThrowExceptionWhenMissingBaseUrl() throws Exception { @Test public void build_shouldThrowExceptionWhenMissingEndpoint() throws Exception { try { - signedRequestBuilder.withKeyPair(KEY_PAIR) + yotiHttpRequestBuilder.withAuthStrategy(authStrategyMock) .withBaseUrl(SOME_BASE_URL) .build(); } catch (IllegalArgumentException e) { @@ -134,7 +133,7 @@ public void build_shouldThrowExceptionWhenMissingEndpoint() throws Exception { @Test public void build_shouldThrowExceptionWhenMissingHttpMethod() throws Exception { try { - signedRequestBuilder.withKeyPair(KEY_PAIR) + yotiHttpRequestBuilder.withAuthStrategy(authStrategyMock) .withBaseUrl(SOME_BASE_URL) .withEndpoint(SOME_ENDPOINT) .build(); @@ -147,9 +146,9 @@ public void build_shouldThrowExceptionWhenMissingHttpMethod() throws Exception { @Test public void build_shouldCreateSignedRequestWithCustomQueryParameter() throws Exception { - when(pathFactoryMock.createSignatureParams()).thenReturn(SIGNATURE_PARAMS_STRING); + when(authStrategyMock.createQueryParams()).thenReturn(asList(new BasicNameValuePair("timestamp", "someTimestamp"))); - SignedRequest result = signedRequestBuilder.withKeyPair(KEY_PAIR) + YotiHttpRequest result = yotiHttpRequestBuilder.withAuthStrategy(authStrategyMock) .withBaseUrl(SOME_BASE_URL) .withEndpoint(SOME_ENDPOINT) .withHttpMethod(HTTP_GET) @@ -157,11 +156,12 @@ public void build_shouldCreateSignedRequestWithCustomQueryParameter() throws Exc .build(); assertThat(result.getUri().getQuery(), containsString(SIGNATURE_PARAMS_STRING)); + assertThat(result.getUri().getQuery(), containsString("someQueryParam=someParamValue")); } @Test public void build_shouldCreateSignedRequestWithProvidedHttpHeader() throws Exception { - SignedRequest result = signedRequestBuilder.withKeyPair(KEY_PAIR) + YotiHttpRequest result = yotiHttpRequestBuilder.withAuthStrategy(authStrategyMock) .withBaseUrl(DEFAULT_YOTI_API_URL) .withEndpoint(SOME_ENDPOINT) .withHttpMethod(HTTP_GET) @@ -172,103 +172,103 @@ public void build_shouldCreateSignedRequestWithProvidedHttpHeader() throws Excep } @Test - public void build_shouldIgnoreAnyProvidedSignedRequestHeaders() throws Exception { - when(pathFactoryMock.createSignatureParams()).thenReturn(SIGNATURE_PARAMS_STRING); - when(signedMessageFactoryMock.create(any(PrivateKey.class), anyString(), anyString())).thenReturn(SOME_SIGNATURE); - when(headersFactoryMock.create(SOME_SIGNATURE)).thenReturn(SIGNED_REQUEST_HEADERS); + public void build_shouldIgnoreAnyProvidedAuthenticationHeaders() throws Exception { + when(authStrategyMock.createQueryParams()).thenReturn(asList(new BasicNameValuePair("timestamp", "someTimestamp"))); + when(authStrategyMock.createAuthHeaders(HTTP_GET, SOME_ENDPOINT + "?" + SIGNATURE_PARAMS_STRING, null)).thenReturn(authHeaders); + when(headersFactoryMock.create(authHeaders)).thenReturn(SIGNED_REQUEST_HEADERS); - SignedRequest result = signedRequestBuilder.withKeyPair(KEY_PAIR) + YotiHttpRequest result = yotiHttpRequestBuilder.withAuthStrategy(authStrategyMock) .withBaseUrl(DEFAULT_YOTI_API_URL) .withEndpoint(SOME_ENDPOINT) .withHttpMethod(HTTP_GET) .withHeader(DIGEST_HEADER, "customHeaderValue") .build(); + verify(authStrategyMock).createAuthHeaders(HTTP_GET, SOME_ENDPOINT + "?" + SIGNATURE_PARAMS_STRING, null); assertThat(result.getHeaders(), hasEntry(DIGEST_HEADER, SOME_SIGNATURE)); } @Test public void withBoundary_shouldThrowWhenBoundaryIsNull() { - IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> signedRequestBuilder.withMultipartBoundary(null)); + IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> yotiHttpRequestBuilder.withMultipartBoundary(null)); assertThat(ex.getMessage(), containsString("multipartBoundary")); } @Test public void withBoundary_shouldThrowWhenBoundaryIsEmpty() { - IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> signedRequestBuilder.withMultipartBoundary("")); + IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> yotiHttpRequestBuilder.withMultipartBoundary("")); assertThat(ex.getMessage(), containsString("multipartBoundary")); } @Test public void withMultipartBinaryBody_shouldThrowWhenNameIsNull() { - IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> signedRequestBuilder.withMultipartBinaryBody(null, null, null, null)); + IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> yotiHttpRequestBuilder.withMultipartBinaryBody(null, null, null, null)); assertThat(ex.getMessage(), containsString("name")); } @Test public void withMultipartBinaryBody_shouldThrowWhenNameIsEmpty() { - IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> signedRequestBuilder.withMultipartBinaryBody("", null, null, null)); + IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> yotiHttpRequestBuilder.withMultipartBinaryBody("", null, null, null)); assertThat(ex.getMessage(), containsString("name")); } @Test public void withMultipartBinaryBody_shouldThrowWhenPayloadIsNull() { - IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> signedRequestBuilder.withMultipartBinaryBody(SOME_MULTIPART_BODY_NAME, null, null, null)); + IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> yotiHttpRequestBuilder.withMultipartBinaryBody(SOME_MULTIPART_BODY_NAME, null, null, null)); assertThat(ex.getMessage(), containsString("payload")); } @Test public void withMultipartBinaryBody_shouldThrowWhenContentTypeIsNull() { - IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> signedRequestBuilder.withMultipartBinaryBody(SOME_MULTIPART_BODY_NAME, SOME_MULTIPART_BODY, null, null)); + IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> yotiHttpRequestBuilder.withMultipartBinaryBody(SOME_MULTIPART_BODY_NAME, SOME_MULTIPART_BODY, null, null)); assertThat(ex.getMessage(), containsString("contentType")); } @Test public void withMultipartBinaryBody_shouldThrowWhenFileNameIsNull() { - IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> signedRequestBuilder.withMultipartBinaryBody(SOME_MULTIPART_BODY_NAME, SOME_MULTIPART_BODY, SOME_MULTIPART_CONTENT_TYPE, null)); + IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> yotiHttpRequestBuilder.withMultipartBinaryBody(SOME_MULTIPART_BODY_NAME, SOME_MULTIPART_BODY, SOME_MULTIPART_CONTENT_TYPE, null)); assertThat(ex.getMessage(), containsString("fileName")); } @Test public void withMultipartBinaryBody_shouldThrowWhenFileNameIsEmpty() { - IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> signedRequestBuilder.withMultipartBinaryBody(SOME_MULTIPART_BODY_NAME, SOME_MULTIPART_BODY, SOME_MULTIPART_CONTENT_TYPE, "")); + IllegalArgumentException ex = assertThrows(IllegalArgumentException.class, () -> yotiHttpRequestBuilder.withMultipartBinaryBody(SOME_MULTIPART_BODY_NAME, SOME_MULTIPART_BODY, SOME_MULTIPART_CONTENT_TYPE, "")); assertThat(ex.getMessage(), containsString("fileName")); } @Test public void shouldRemoveTrailingSlashesFromBaseUrl() throws Exception { - SignedRequest simpleSignedRequest = signedRequestBuilder.withKeyPair(KEY_PAIR) + YotiHttpRequest simpleYotiHttpRequest = yotiHttpRequestBuilder.withAuthStrategy(authStrategyMock) .withBaseUrl(SOME_BASE_URL + "////////////") .withEndpoint(SOME_ENDPOINT) .withHttpMethod(HTTP_GET) .build(); - assertThat(simpleSignedRequest.getUri().toString(), containsString(SOME_BASE_URL + SOME_ENDPOINT)); + assertThat(simpleYotiHttpRequest.getUri().toString(), containsString(SOME_BASE_URL + SOME_ENDPOINT)); } @Test public void shouldCreateSignedRequestSuccessfullyWithRequiredFieldsOnly() throws Exception { - when(pathFactoryMock.createSignatureParams()).thenReturn(SIGNATURE_PARAMS_STRING); - when(signedMessageFactoryMock.create(any(PrivateKey.class), anyString(), anyString())).thenReturn(SOME_SIGNATURE); - when(headersFactoryMock.create(SOME_SIGNATURE)).thenReturn(SIGNED_REQUEST_HEADERS); + when(authStrategyMock.createQueryParams()).thenReturn(asList(new BasicNameValuePair("timestamp", "someTimestamp"))); + String fullPath = SOME_ENDPOINT + "?" + SIGNATURE_PARAMS_STRING; + when(authStrategyMock.createAuthHeaders(HTTP_GET, fullPath, null)).thenReturn(authHeaders); + when(headersFactoryMock.create(authHeaders)).thenReturn(SIGNED_REQUEST_HEADERS); - SignedRequest result = signedRequestBuilder.withKeyPair(KEY_PAIR) + YotiHttpRequest result = yotiHttpRequestBuilder.withAuthStrategy(authStrategyMock) .withBaseUrl(SOME_BASE_URL) .withEndpoint(SOME_ENDPOINT) .withHttpMethod(HTTP_GET) .build(); - verify(signedMessageFactoryMock).create(eq(KEY_PAIR.getPrivate()), eq(HTTP_GET), pathCaptor.capture()); - assertThat(pathCaptor.getValue(), is(SOME_ENDPOINT + "?" + SIGNATURE_PARAMS_STRING)); - assertThat(result.getUri().toString(), is(SOME_BASE_URL + pathCaptor.getValue())); + assertThat(result.getUri().toString(), is(SOME_BASE_URL + fullPath)); assertThat(result.getMethod(), is(HTTP_GET)); assertThat(result.getHeaders().get(DIGEST_HEADER), containsString(SOME_SIGNATURE)); assertThat(result.getHeaders(), hasEntry(DIGEST_HEADER, SOME_SIGNATURE)); @@ -276,12 +276,13 @@ public void shouldCreateSignedRequestSuccessfullyWithRequiredFieldsOnly() throws } @Test - public void shouldCreatedSignedRequestSuccessfullyWithAllProperties() throws Exception { - when(pathFactoryMock.createSignatureParams()).thenReturn(SIGNATURE_PARAMS_STRING); - when(signedMessageFactoryMock.create(any(PrivateKey.class), anyString(), anyString(), any(byte[].class))).thenReturn(SOME_SIGNATURE); - when(headersFactoryMock.create(SOME_SIGNATURE)).thenReturn(SIGNED_REQUEST_HEADERS); + public void shouldCreateSignedRequestSuccessfullyWithAllProperties() throws Exception { + String fullPath = SOME_ENDPOINT + "?someQueryParam=someParamValue&someKey=someValue"; + when(authStrategyMock.createAuthHeaders(HTTP_GET, fullPath, SOME_BYTES)).thenReturn(authHeaders); + when(authStrategyMock.createQueryParams()).thenReturn(asList(new BasicNameValuePair("someKey","someValue"))); + when(headersFactoryMock.create(authHeaders)).thenReturn(SIGNED_REQUEST_HEADERS); - SignedRequest result = signedRequestBuilder.withKeyPair(KEY_PAIR) + YotiHttpRequest result = yotiHttpRequestBuilder.withAuthStrategy(authStrategyMock) .withBaseUrl(SOME_BASE_URL) .withEndpoint(SOME_ENDPOINT) .withHttpMethod(HTTP_GET) @@ -290,9 +291,7 @@ public void shouldCreatedSignedRequestSuccessfullyWithAllProperties() throws Exc .withPayload(SOME_BYTES) .build(); - verify(signedMessageFactoryMock).create(eq(KEY_PAIR.getPrivate()), eq(HTTP_GET), pathCaptor.capture(), eq(SOME_BYTES)); - assertThat(pathCaptor.getValue(), is(SOME_ENDPOINT + "?someQueryParam=someParamValue&" + SIGNATURE_PARAMS_STRING)); - assertThat(result.getUri().toString(), is(SOME_BASE_URL + pathCaptor.getValue())); + assertThat(result.getUri().toString(), is(SOME_BASE_URL + fullPath)); assertThat(result.getMethod(), is(HTTP_GET)); assertThat(result.getHeaders().get(DIGEST_HEADER), containsString(SOME_SIGNATURE)); assertThat(result.getHeaders(), hasEntry(DIGEST_HEADER, SOME_SIGNATURE)); @@ -302,14 +301,8 @@ public void shouldCreatedSignedRequestSuccessfullyWithAllProperties() throws Exc @Test public void shouldSetContentTypeToMultipartWhenUserHasSetRequestTypeToMultipart() throws Exception { - when(pathFactoryMock.createSignatureParams()).thenReturn(SIGNATURE_PARAMS_STRING); - when(signedMessageFactoryMock.create(any(PrivateKey.class), anyString(), anyString(), any(byte[].class))).thenReturn(SOME_SIGNATURE); - when(headersFactoryMock.create(SOME_SIGNATURE)).thenReturn(SIGNED_REQUEST_HEADERS); when(multipartEntityBuilderMock.build()).thenReturn(httpEntityMock); - - when(headerElementMock.toString()).thenReturn(SOME_MULTIPART_CONTENT_TYPE.toString()); - when(headerMock.getElements()).thenReturn(new HeaderElement[]{ headerElementMock }); - when(httpEntityMock.getContentType()).thenReturn(headerMock); + when(httpEntityMock.getContentType()).thenReturn(new BasicHeader("Content-Type", SOME_MULTIPART_CONTENT_TYPE.toString())); // This is to overcome where we can't mock the OutputStream // in the getMultipartBodyAsBytes() method @@ -323,7 +316,7 @@ public void shouldSetContentTypeToMultipartWhenUserHasSetRequestTypeToMultipart( try (MockedStatic ms = Mockito.mockStatic(MultipartEntityBuilder.class)) { ms.when(MultipartEntityBuilder::create).thenReturn(multipartEntityBuilderMock); - SignedRequest result = signedRequestBuilder.withKeyPair(KEY_PAIR) + YotiHttpRequest result = yotiHttpRequestBuilder.withAuthStrategy(authStrategyMock) .withMultipartBoundary(SOME_MULTIPART_BOUNDARY) .withMultipartBinaryBody(SOME_MULTIPART_BODY_NAME, SOME_MULTIPART_BODY, SOME_MULTIPART_CONTENT_TYPE, SOME_MULTIPART_FILE_NAME) .withBaseUrl(SOME_BASE_URL) @@ -338,12 +331,8 @@ public void shouldSetContentTypeToMultipartWhenUserHasSetRequestTypeToMultipart( @Test public void shouldThrowIllegalArgumentExceptionWhenThereIsAnErrorBuildingTheMultipartBody() throws Exception { - when(pathFactoryMock.createSignatureParams()).thenReturn(SIGNATURE_PARAMS_STRING); when(multipartEntityBuilderMock.build()).thenReturn(httpEntityMock); - - when(headerElementMock.toString()).thenReturn(SOME_MULTIPART_CONTENT_TYPE.toString()); - when(headerMock.getElements()).thenReturn(new HeaderElement[]{headerElementMock}); - when(httpEntityMock.getContentType()).thenReturn(headerMock); + when(httpEntityMock.getContentType()).thenReturn(new BasicHeader(CONTENT_TYPE, SOME_MULTIPART_CONTENT_TYPE.toString())); IOException ioException = new IOException(); doThrow(ioException).when(httpEntityMock).writeTo(any(OutputStream.class)); @@ -352,7 +341,7 @@ public void shouldThrowIllegalArgumentExceptionWhenThereIsAnErrorBuildingTheMult ms.when(MultipartEntityBuilder::create).thenReturn(multipartEntityBuilderMock); IllegalStateException exception = assertThrows(IllegalStateException.class, () -> { - signedRequestBuilder.withKeyPair(KEY_PAIR) + yotiHttpRequestBuilder.withAuthStrategy(authStrategyMock) .withMultipartBoundary(SOME_MULTIPART_BOUNDARY) .withMultipartBinaryBody(SOME_MULTIPART_BODY_NAME, SOME_MULTIPART_BODY, SOME_MULTIPART_CONTENT_TYPE, SOME_MULTIPART_FILE_NAME) .withBaseUrl(SOME_BASE_URL) diff --git a/yoti-sdk-api/src/test/java/com/yoti/api/client/spi/remote/call/aml/AmlTest.java b/yoti-sdk-api/src/test/java/com/yoti/api/client/spi/remote/call/aml/AmlTest.java index 6d236317c..5d0237fd2 100644 --- a/yoti-sdk-api/src/test/java/com/yoti/api/client/spi/remote/call/aml/AmlTest.java +++ b/yoti-sdk-api/src/test/java/com/yoti/api/client/spi/remote/call/aml/AmlTest.java @@ -60,7 +60,10 @@ public void factoryShouldReturnValidAmlProfile() { @Test public void shouldReturnAmlAddress() { - AmlAddress amlAddress = new AmlAddress(SOME_POSTCODE, SOME_COUNTRY); + AmlAddress amlAddress = AmlAddress.builder() + .withPostCode(SOME_POSTCODE) + .withCountry(SOME_COUNTRY) + .build(); assertNotNull(amlAddress); assertThat(amlAddress.getPostCode(), is(SOME_POSTCODE)); diff --git a/yoti-sdk-api/src/test/java/com/yoti/api/client/spi/remote/call/aml/RemoteAmlServiceTest.java b/yoti-sdk-api/src/test/java/com/yoti/api/client/spi/remote/call/aml/RemoteAmlServiceTest.java index 3f032bdf6..52dee5455 100644 --- a/yoti-sdk-api/src/test/java/com/yoti/api/client/spi/remote/call/aml/RemoteAmlServiceTest.java +++ b/yoti-sdk-api/src/test/java/com/yoti/api/client/spi/remote/call/aml/RemoteAmlServiceTest.java @@ -4,12 +4,10 @@ import static org.junit.Assert.assertSame; import static org.junit.Assert.fail; -import static org.mockito.Answers.RETURNS_DEEP_STUBS; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.when; import java.io.IOException; -import java.security.KeyPair; import java.util.HashMap; import java.util.Map; @@ -17,7 +15,7 @@ import com.yoti.api.client.aml.AmlProfile; import com.yoti.api.client.aml.AmlResult; import com.yoti.api.client.spi.remote.call.ResourceException; -import com.yoti.api.client.spi.remote.call.SignedRequest; +import com.yoti.api.client.spi.remote.call.YotiHttpRequest; import com.yoti.api.client.spi.remote.call.factory.UnsignedPathFactory; import com.fasterxml.jackson.core.JsonProcessingException; @@ -34,7 +32,6 @@ @RunWith(MockitoJUnitRunner.class) public class RemoteAmlServiceTest { - private static final String SOME_APP_ID = "someAppId"; private static final String GENERATED_PATH = "generatedPath"; private static final String SERIALIZED_BODY = "serializedBody"; private static final byte[] BODY_BYTES = SERIALIZED_BODY.getBytes(); @@ -46,8 +43,7 @@ public class RemoteAmlServiceTest { @Mock ObjectMapper objectMapperMock; @Mock AmlProfile amlProfileMock; - @Mock(answer = RETURNS_DEEP_STUBS) KeyPair keyPairMock; - @Mock SignedRequest signedRequestMock; + @Mock YotiHttpRequest yotiHttpRequestMock; @Mock AmlResult amlResultMock; @BeforeClass @@ -57,16 +53,16 @@ public static void setUpClass() { @Before public void setUp() { - when(unsignedPathFactoryMock.createAmlPath(SOME_APP_ID)).thenReturn(GENERATED_PATH); + when(unsignedPathFactoryMock.createAmlPath()).thenReturn(GENERATED_PATH); } @Test public void shouldPerformAmlCheck() throws Exception { when(objectMapperMock.writeValueAsString(amlProfileMock)).thenReturn(SERIALIZED_BODY); - doReturn(signedRequestMock).when(testObj).createSignedRequest(keyPairMock, GENERATED_PATH, BODY_BYTES); - when(signedRequestMock.execute(AmlResult.class)).thenReturn(amlResultMock); + doReturn(yotiHttpRequestMock).when(testObj).createRequest(GENERATED_PATH, BODY_BYTES); + when(yotiHttpRequestMock.execute(AmlResult.class)).thenReturn(amlResultMock); - AmlResult result = testObj.performCheck(keyPairMock, SOME_APP_ID, amlProfileMock); + AmlResult result = testObj.performCheck(amlProfileMock); assertSame(result, amlResultMock); } @@ -75,11 +71,11 @@ public void shouldPerformAmlCheck() throws Exception { public void shouldWrapIOException() throws Exception { IOException ioException = new IOException(); when(objectMapperMock.writeValueAsString(amlProfileMock)).thenReturn(SERIALIZED_BODY); - doReturn(signedRequestMock).when(testObj).createSignedRequest(keyPairMock, GENERATED_PATH, BODY_BYTES); - when(signedRequestMock.execute(AmlResult.class)).thenThrow(ioException); + doReturn(yotiHttpRequestMock).when(testObj).createRequest(GENERATED_PATH, BODY_BYTES); + when(yotiHttpRequestMock.execute(AmlResult.class)).thenThrow(ioException); try { - testObj.performCheck(keyPairMock, SOME_APP_ID, amlProfileMock); + testObj.performCheck(amlProfileMock); fail("Expected AmlException"); } catch (AmlException e) { assertSame(ioException, e.getCause()); @@ -90,11 +86,11 @@ public void shouldWrapIOException() throws Exception { public void shouldWrapResourceException() throws Exception { ResourceException resourceException = new ResourceException(HTTP_UNAUTHORIZED, "Unauthorized", "failed verification"); when(objectMapperMock.writeValueAsString(amlProfileMock)).thenReturn(SERIALIZED_BODY); - doReturn(signedRequestMock).when(testObj).createSignedRequest(keyPairMock, GENERATED_PATH, BODY_BYTES); - when(signedRequestMock.execute(AmlResult.class)).thenThrow(resourceException); + doReturn(yotiHttpRequestMock).when(testObj).createRequest(GENERATED_PATH, BODY_BYTES); + when(yotiHttpRequestMock.execute(AmlResult.class)).thenThrow(resourceException); try { - testObj.performCheck(keyPairMock, SOME_APP_ID, amlProfileMock); + testObj.performCheck(amlProfileMock); fail("Expected AmlException"); } catch (AmlException e) { assertSame(resourceException, e.getCause()); @@ -107,26 +103,16 @@ public void shouldWrapJsonProcessingException() throws Exception { when(objectMapperMock.writeValueAsString(amlProfileMock)).thenThrow(jsonProcessingException); try { - testObj.performCheck(keyPairMock, SOME_APP_ID, amlProfileMock); + testObj.performCheck(amlProfileMock); fail("Expected AmlException"); } catch (AmlException e) { assertSame(jsonProcessingException, e.getCause()); } } - @Test(expected = IllegalArgumentException.class) - public void shouldFailWithNullKeyPair() throws Exception { - testObj.performCheck(null, SOME_APP_ID, amlProfileMock); - } - - @Test(expected = IllegalArgumentException.class) - public void shouldFailWithNullAppId() throws Exception { - testObj.performCheck(keyPairMock, null, amlProfileMock); - } - @Test(expected = IllegalArgumentException.class) public void shouldFailWithNullAmlProfile() throws Exception { - testObj.performCheck(keyPairMock, SOME_APP_ID, null); + testObj.performCheck(null); } } diff --git a/yoti-sdk-api/src/test/java/com/yoti/api/client/spi/remote/call/factory/HeadersFactoryTest.java b/yoti-sdk-api/src/test/java/com/yoti/api/client/spi/remote/call/factory/HeadersFactoryTest.java index 8f7d97ecb..aab3d3d4b 100644 --- a/yoti-sdk-api/src/test/java/com/yoti/api/client/spi/remote/call/factory/HeadersFactoryTest.java +++ b/yoti-sdk-api/src/test/java/com/yoti/api/client/spi/remote/call/factory/HeadersFactoryTest.java @@ -1,7 +1,5 @@ package com.yoti.api.client.spi.remote.call.factory; -import static com.yoti.api.client.spi.remote.call.YotiConstants.AUTH_KEY_HEADER; -import static com.yoti.api.client.spi.remote.call.YotiConstants.DIGEST_HEADER; import static com.yoti.api.client.spi.remote.call.YotiConstants.JAVA; import static com.yoti.api.client.spi.remote.call.YotiConstants.SDK_VERSION; import static com.yoti.api.client.spi.remote.call.YotiConstants.YOTI_SDK_HEADER; @@ -10,34 +8,29 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.collection.IsMapContaining.hasEntry; +import java.util.Collections; import java.util.Map; -import org.junit.*; +import org.apache.http.Header; +import org.apache.http.message.BasicHeader; +import org.junit.Test; public class HeadersFactoryTest { - private static final String SOME_DIGEST = "someDigest"; private static final String SOME_KEY = "someKey"; + private static final String SOME_VALUE = "someValue"; HeadersFactory testObj = new HeadersFactory(); @Test - public void shouldCreateWithDigest() { - Map result = testObj.create(SOME_DIGEST); + public void shouldCreate() { + Header header = new BasicHeader(SOME_KEY, SOME_VALUE); - assertThat(result, hasEntry(DIGEST_HEADER, SOME_DIGEST)); - assertThat(result, hasEntry(YOTI_SDK_HEADER, JAVA)); - assertThat(result, hasEntry(YOTI_SDK_VERSION_HEADER, SDK_VERSION)); - } - - @Test - public void shouldCreateWithDigestAndKey() { - Map result = testObj.create(SOME_DIGEST, SOME_KEY); + Map result = testObj.create(Collections.singletonList(header)); - assertThat(result, hasEntry(DIGEST_HEADER, SOME_DIGEST)); + assertThat(result, hasEntry(SOME_KEY, SOME_VALUE)); assertThat(result, hasEntry(YOTI_SDK_HEADER, JAVA)); assertThat(result, hasEntry(YOTI_SDK_VERSION_HEADER, SDK_VERSION)); - assertThat(result, hasEntry(AUTH_KEY_HEADER, SOME_KEY)); } } diff --git a/yoti-sdk-api/src/test/java/com/yoti/api/client/spi/remote/call/factory/PathFactoryTest.java b/yoti-sdk-api/src/test/java/com/yoti/api/client/spi/remote/call/factory/PathFactoryTest.java deleted file mode 100644 index 0c36f4874..000000000 --- a/yoti-sdk-api/src/test/java/com/yoti/api/client/spi/remote/call/factory/PathFactoryTest.java +++ /dev/null @@ -1,95 +0,0 @@ -package com.yoti.api.client.spi.remote.call.factory; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; - -import java.net.URI; - -import org.junit.Test; - -public class PathFactoryTest { - - private static final String SOME_APP_ID = "someAppId"; - private static final String SOME_TOKEN = "someToken"; - private static final String SOME_SESSION_ID = "someSessionId"; - private static final String SOME_MEDIA_ID = "someMediaId"; - - private static PathFactory testObj = new PathFactory(); - - @Test - public void shouldCreateProfilePath() { - String result = testObj.createProfilePath(SOME_APP_ID, SOME_TOKEN); - - URI uri = URI.create(result); - assertEquals("/profile/" + SOME_TOKEN, uri.getPath()); - assertTrue(uri.getQuery().contains("appId=" + SOME_APP_ID)); - assertTrue(uri.getQuery().matches("(.*)nonce=(?i)[A-F0-9]{8}-[A-F0-9]{4}-[A-F0-9]{4}-[A-F0-9]{4}-[A-F0-9]{12}(.*)")); - assertTrue(uri.getQuery().contains("timestamp=")); - } - - @Test - public void shouldCreateAmlPath() { - String result = testObj.createAmlPath(SOME_APP_ID); - - URI uri = URI.create(result); - assertEquals("/aml-check", uri.getPath()); - assertTrue(uri.getQuery().contains("appId=" + SOME_APP_ID)); - assertTrue(uri.getQuery().matches("(.*)nonce=(?i)[A-F0-9]{8}-[A-F0-9]{4}-[A-F0-9]{4}-[A-F0-9]{4}-[A-F0-9]{12}(.*)")); - assertTrue(uri.getQuery().contains("timestamp=")); - } - - @Test - public void shouldCreateDynamicSharingPath() { - String result = testObj.createDynamicSharingPath(SOME_APP_ID); - - URI uri = URI.create(result); - assertEquals("/qrcodes/apps/" + SOME_APP_ID, uri.getPath()); - assertTrue(uri.getQuery().matches("(.*)nonce=(?i)[A-F0-9]{8}-[A-F0-9]{4}-[A-F0-9]{4}-[A-F0-9]{4}-[A-F0-9]{12}(.*)")); - assertTrue(uri.getQuery().contains("timestamp=")); - } - - @Test - public void shouldCreateNewYotiDocsSessionPath() { - String result = testObj.createNewYotiDocsSessionPath(SOME_APP_ID); - - URI uri = URI.create(result); - assertEquals("/sessions", uri.getPath()); - assertTrue(uri.getQuery().contains("sdkId=" + SOME_APP_ID)); - assertTrue(uri.getQuery().matches("(.*)nonce=(?i)[A-F0-9]{8}-[A-F0-9]{4}-[A-F0-9]{4}-[A-F0-9]{4}-[A-F0-9]{12}(.*)")); - assertTrue(uri.getQuery().contains("timestamp=")); - } - - @Test - public void shouldCreateYotiDocsSessionPath() { - String result = testObj.createGetYotiDocsSessionPath(SOME_APP_ID, SOME_SESSION_ID); - - URI uri = URI.create(result); - assertEquals("/sessions/" + SOME_SESSION_ID, uri.getPath()); - assertTrue(uri.getQuery().contains("sdkId=" + SOME_APP_ID)); - assertTrue(uri.getQuery().matches("(.*)nonce=(?i)[A-F0-9]{8}-[A-F0-9]{4}-[A-F0-9]{4}-[A-F0-9]{4}-[A-F0-9]{12}(.*)")); - assertTrue(uri.getQuery().contains("timestamp=")); - } - - @Test - public void shouldCreateMediaContentPath() { - String result = testObj.createMediaContentPath(SOME_APP_ID, SOME_SESSION_ID, SOME_MEDIA_ID); - - URI uri = URI.create(result); - assertEquals("/sessions/" + SOME_SESSION_ID + "/media/" + SOME_MEDIA_ID + "/content", uri.getPath()); - assertTrue(uri.getQuery().contains("sdkId=" + SOME_APP_ID)); - assertTrue(uri.getQuery().matches("(.*)nonce=(?i)[A-F0-9]{8}-[A-F0-9]{4}-[A-F0-9]{4}-[A-F0-9]{4}-[A-F0-9]{12}(.*)")); - assertTrue(uri.getQuery().contains("timestamp=")); - } - - @Test - public void shouldCreateSupportedDocumentsPath() { - String result = testObj.createGetSupportedDocumentsPath(true); - - URI uri = URI.create(result); - assertEquals("/supported-documents", uri.getPath()); - assertTrue(uri.getQuery().contains("includeNonLatin=true")); - assertTrue(uri.getQuery().matches("(.*)nonce=(?i)[A-F0-9]{8}-[A-F0-9]{4}-[A-F0-9]{4}-[A-F0-9]{4}-[A-F0-9]{12}(.*)")); - assertTrue(uri.getQuery().contains("timestamp=")); - } - -} diff --git a/yoti-sdk-api/src/test/java/com/yoti/api/client/spi/remote/call/identity/DigitalIdentityServiceTest.java b/yoti-sdk-api/src/test/java/com/yoti/api/client/spi/remote/call/identity/DigitalIdentityServiceTest.java index 8e3cacdbf..bdf8fd93c 100644 --- a/yoti-sdk-api/src/test/java/com/yoti/api/client/spi/remote/call/identity/DigitalIdentityServiceTest.java +++ b/yoti-sdk-api/src/test/java/com/yoti/api/client/spi/remote/call/identity/DigitalIdentityServiceTest.java @@ -1,102 +1,73 @@ package com.yoti.api.client.spi.remote.call.identity; import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.*; +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.notNullValue; import static org.junit.Assert.assertSame; import static org.junit.Assert.assertThrows; import static org.junit.Assert.assertTrue; import static org.mockito.Answers.RETURNS_DEEP_STUBS; -import static org.mockito.Mockito.*; +import static org.mockito.Mockito.when; import java.io.UnsupportedEncodingException; import java.net.URISyntaxException; import java.nio.charset.StandardCharsets; import java.security.GeneralSecurityException; -import java.security.KeyPair; import com.yoti.api.client.identity.MatchRequest; import com.yoti.api.client.identity.MatchResult; import com.yoti.api.client.identity.ShareSession; import com.yoti.api.client.identity.ShareSessionRequest; -import com.yoti.api.client.spi.remote.call.SignedRequest; -import com.yoti.api.client.spi.remote.call.SignedRequestBuilder; -import com.yoti.api.client.spi.remote.call.SignedRequestBuilderFactory; +import com.yoti.api.client.spi.remote.call.YotiHttpRequest; +import com.yoti.api.client.spi.remote.call.YotiHttpRequestBuilder; +import com.yoti.api.client.spi.remote.call.YotiHttpRequestBuilderFactory; import com.yoti.api.client.spi.remote.call.factory.UnsignedPathFactory; import com.yoti.json.ResourceMapper; import com.fasterxml.jackson.core.JsonProcessingException; -import org.junit.*; +import org.junit.Before; +import org.junit.Test; import org.junit.runner.RunWith; -import org.mockito.*; -import org.mockito.junit.*; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockedStatic; +import org.mockito.Mockito; +import org.mockito.junit.MockitoJUnitRunner; @RunWith(MockitoJUnitRunner.class) public class DigitalIdentityServiceTest { - private static final String SDK_ID = "anSdkId"; - private static final String SESSION_ID = "aSessionId"; - private static final String QR_CODE_ID = "aQrCodeId"; private static final String SESSION_CREATION_PATH = "aSessionCreationPath"; private static final String DIGITAL_ID_MATCH_PATH = "aDigitalIdMatchPath"; private static final String POST = "POST"; private static final byte[] A_BODY_BYTES = "aBody".getBytes(StandardCharsets.UTF_8); - @Spy @InjectMocks DigitalIdentityService identityService; + @InjectMocks DigitalIdentityService testObj; - @Mock UnsignedPathFactory unsignedPathFactory; - @Mock(answer = RETURNS_DEEP_STUBS) SignedRequestBuilder signedRequestBuilder; - @Mock SignedRequestBuilderFactory requestBuilderFactory; + @Mock UnsignedPathFactory unsignedPathFactoryMock; + @Mock YotiHttpRequestBuilderFactory requestBuilderFactoryMock; - @Mock(answer = RETURNS_DEEP_STUBS) KeyPair keyPair; - @Mock SignedRequest signedRequest; + @Mock(answer = RETURNS_DEEP_STUBS) YotiHttpRequestBuilder yotiHttpRequestBuilder; + @Mock YotiHttpRequest yotiHttpRequest; @Mock ShareSessionRequest shareSessionRequest; @Mock ShareSession shareSession; - @Mock MatchRequest matchRequest; @Mock MatchResult matchResult; @Before public void setUp() { - when(unsignedPathFactory.createIdentitySessionPath()).thenReturn(SESSION_CREATION_PATH); - when(unsignedPathFactory.createIdentityMatchPath()).thenReturn(DIGITAL_ID_MATCH_PATH); - } - - @Test - public void createShareSession_NullSdkId_Exception() { - IllegalArgumentException ex = assertThrows( - IllegalArgumentException.class, - () -> identityService.createShareSession(null, keyPair, shareSessionRequest) - ); - - assertThat(ex.getMessage(), containsString("SDK ID")); - } - - @Test - public void createShareSession_EmptySdkId_Exception() { - IllegalArgumentException ex = assertThrows( - IllegalArgumentException.class, - () -> identityService.createShareSession("", keyPair, shareSessionRequest) - ); - - assertThat(ex.getMessage(), containsString("SDK ID")); - } - - @Test - public void createShareSession_NullKeyPair_Exception() { - IllegalArgumentException ex = assertThrows( - IllegalArgumentException.class, - () -> identityService.createShareSession(SDK_ID, null, shareSessionRequest) - ); + when(requestBuilderFactoryMock.create()).thenReturn(yotiHttpRequestBuilder); - assertThat(ex.getMessage(), containsString("Application Key Pair")); + when(unsignedPathFactoryMock.createIdentitySessionPath()).thenReturn(SESSION_CREATION_PATH); + when(unsignedPathFactoryMock.createIdentityMatchPath()).thenReturn(DIGITAL_ID_MATCH_PATH); } @Test public void createShareSession_NullShareSessionRequest_Exception() { IllegalArgumentException ex = assertThrows( IllegalArgumentException.class, - () -> identityService.createShareSession(SDK_ID, keyPair, null) + () -> testObj.createShareSession(null) ); assertThat(ex.getMessage(), containsString("Share Session request")); @@ -111,7 +82,7 @@ public void createShareSession_SerializingWrongPayload_Exception() { DigitalIdentityException ex = assertThrows( DigitalIdentityException.class, - () -> identityService.createShareSession(SDK_ID, keyPair, shareSessionRequest) + () -> testObj.createShareSession(shareSessionRequest) ); Throwable cause = ex.getCause(); @@ -124,16 +95,14 @@ public void createShareSession_SerializingWrongPayload_Exception() { public void createShareSession_BuildingRequestWithWrongUri_Exception() throws Exception { try (MockedStatic mapper = Mockito.mockStatic(ResourceMapper.class)) { mapper.when(() -> ResourceMapper.writeValueAsString(shareSessionRequest)).thenReturn(A_BODY_BYTES); - when(requestBuilderFactory.create()).thenReturn(signedRequestBuilder); String exMessage = "URI wrong format"; URISyntaxException causeEx = new URISyntaxException("", exMessage); - when(identityService.createSignedRequest(SDK_ID, keyPair, SESSION_CREATION_PATH, POST, A_BODY_BYTES)) - .thenThrow(causeEx); + when(testObj.createRequest(SESSION_CREATION_PATH, POST, A_BODY_BYTES)).thenThrow(causeEx); DigitalIdentityException ex = assertThrows( DigitalIdentityException.class, - () -> identityService.createShareSession(SDK_ID, keyPair, shareSessionRequest) + () -> testObj.createShareSession(shareSessionRequest) ); Throwable cause = ex.getCause(); @@ -147,16 +116,13 @@ public void createShareSession_BuildingRequestWithWrongQueryParams_Exception() t try (MockedStatic mapper = Mockito.mockStatic(ResourceMapper.class)) { mapper.when(() -> ResourceMapper.writeValueAsString(shareSessionRequest)).thenReturn(A_BODY_BYTES); - when(requestBuilderFactory.create()).thenReturn(signedRequestBuilder); - String exMessage = "Wrong query params format"; UnsupportedEncodingException causeEx = new UnsupportedEncodingException(exMessage); - when(identityService.createSignedRequest(SDK_ID, keyPair, SESSION_CREATION_PATH, POST, A_BODY_BYTES)) - .thenThrow(causeEx); + when(testObj.createRequest(SESSION_CREATION_PATH, POST, A_BODY_BYTES)).thenThrow(causeEx); DigitalIdentityException ex = assertThrows( DigitalIdentityException.class, - () -> identityService.createShareSession(SDK_ID, keyPair, shareSessionRequest) + () -> testObj.createShareSession(shareSessionRequest) ); Throwable cause = ex.getCause(); @@ -170,16 +136,13 @@ public void createShareSession_BuildingRequestWithWrongDigest_Exception() throws try (MockedStatic mapper = Mockito.mockStatic(ResourceMapper.class)) { mapper.when(() -> ResourceMapper.writeValueAsString(shareSessionRequest)).thenReturn(A_BODY_BYTES); - when(requestBuilderFactory.create()).thenReturn(signedRequestBuilder); - String exMessage = "Wrong digest"; GeneralSecurityException causeEx = new GeneralSecurityException(exMessage); - when(identityService.createSignedRequest(SDK_ID, keyPair, SESSION_CREATION_PATH, POST, A_BODY_BYTES)) - .thenThrow(causeEx); + when(testObj.createRequest(SESSION_CREATION_PATH, POST, A_BODY_BYTES)).thenThrow(causeEx); DigitalIdentityException ex = assertThrows( DigitalIdentityException.class, - () -> identityService.createShareSession(SDK_ID, keyPair, shareSessionRequest) + () -> testObj.createShareSession(shareSessionRequest) ); Throwable cause = ex.getCause(); @@ -193,133 +156,40 @@ public void createShareSession_SessionRequest_exception() throws Exception { try (MockedStatic mapper = Mockito.mockStatic(ResourceMapper.class)) { mapper.when(() -> ResourceMapper.writeValueAsString(shareSessionRequest)).thenReturn(A_BODY_BYTES); - when(requestBuilderFactory.create()).thenReturn(signedRequestBuilder); - - when(identityService.createSignedRequest(SDK_ID, keyPair, SESSION_CREATION_PATH, POST, A_BODY_BYTES)) - .thenReturn(signedRequest); + when(testObj.createRequest(SESSION_CREATION_PATH, POST, A_BODY_BYTES)).thenReturn(yotiHttpRequest); + when(yotiHttpRequest.execute(ShareSession.class)).thenReturn(shareSession); - when(signedRequest.execute(ShareSession.class)).thenReturn(shareSession); + ShareSession result = testObj.createShareSession(shareSessionRequest); - ShareSession result = identityService.createShareSession(SDK_ID, keyPair, shareSessionRequest); assertSame(shareSession, result); } } - @Test - public void createShareQrCode_NullSdkId_Exception() { - IllegalArgumentException ex = assertThrows( - IllegalArgumentException.class, - () -> identityService.createShareQrCode(null, keyPair, SESSION_ID) - ); - - assertThat(ex.getMessage(), containsString("SDK ID")); - } - - @Test - public void createShareQrCode_EmptySdkId_Exception() { - IllegalArgumentException ex = assertThrows( - IllegalArgumentException.class, - () -> identityService.createShareQrCode("", keyPair, SESSION_ID) - ); - - assertThat(ex.getMessage(), containsString("SDK ID")); - } - - @Test - public void createShareQrCode_NullKeyPair_Exception() { - IllegalArgumentException ex = assertThrows( - IllegalArgumentException.class, - () -> identityService.createShareQrCode(SDK_ID, null, SESSION_ID) - ); - - assertThat(ex.getMessage(), containsString("Application Key Pair")); - } - @Test public void createShareQrCode_NullSessionId_Exception() { IllegalArgumentException ex = assertThrows( IllegalArgumentException.class, - () -> identityService.createShareQrCode(SDK_ID, keyPair, null) + () -> testObj.createShareQrCode(null) ); assertThat(ex.getMessage(), containsString("Session ID")); } - @Test - public void fetchShareQrCode_NullSdkId_Exception() { - IllegalArgumentException ex = assertThrows( - IllegalArgumentException.class, - () -> identityService.fetchShareQrCode(null, keyPair, QR_CODE_ID) - ); - - assertThat(ex.getMessage(), containsString("SDK ID")); - } - - @Test - public void fetchShareQrCode_EmptySdkId_Exception() { - IllegalArgumentException ex = assertThrows( - IllegalArgumentException.class, - () -> identityService.fetchShareQrCode("", keyPair, QR_CODE_ID) - ); - - assertThat(ex.getMessage(), containsString("SDK ID")); - } - - @Test - public void fetchShareQrCode_NullKeyPair_Exception() { - IllegalArgumentException ex = assertThrows( - IllegalArgumentException.class, - () -> identityService.fetchShareQrCode(SDK_ID, null, QR_CODE_ID) - ); - - assertThat(ex.getMessage(), containsString("Application Key Pair")); - } - @Test public void fetchShareQrCode_NullSessionId_Exception() { IllegalArgumentException ex = assertThrows( IllegalArgumentException.class, - () -> identityService.fetchShareQrCode(SDK_ID, keyPair, null) + () -> testObj.fetchShareQrCode(null) ); assertThat(ex.getMessage(), containsString("QR Code ID")); } - @Test - public void fetchMatch_NullSdkId_Exception() { - IllegalArgumentException ex = assertThrows( - IllegalArgumentException.class, - () -> identityService.fetchMatch(null, keyPair, matchRequest) - ); - - assertThat(ex.getMessage(), containsString("SDK ID")); - } - - @Test - public void fetchMatch_EmptySdkId_Exception() { - IllegalArgumentException ex = assertThrows( - IllegalArgumentException.class, - () -> identityService.fetchMatch("", keyPair, matchRequest) - ); - - assertThat(ex.getMessage(), containsString("SDK ID")); - } - - @Test - public void fetchMatch_NullKeyPair_Exception() { - IllegalArgumentException ex = assertThrows( - IllegalArgumentException.class, - () -> identityService.fetchMatch(SDK_ID, null, matchRequest) - ); - - assertThat(ex.getMessage(), containsString("Application Key Pair")); - } - @Test public void fetchMatch_NullMatchRequest_Exception() { IllegalArgumentException ex = assertThrows( IllegalArgumentException.class, - () -> identityService.fetchMatch(SDK_ID, keyPair, null) + () -> testObj.fetchMatch(null) ); assertThat(ex.getMessage(), notNullValue()); @@ -334,7 +204,7 @@ public void fetchMatch_SerializingWrongPayload_Exception() { DigitalIdentityException ex = assertThrows( DigitalIdentityException.class, - () -> identityService.fetchMatch(SDK_ID, keyPair, matchRequest) + () -> testObj.fetchMatch(matchRequest) ); Throwable cause = ex.getCause(); @@ -347,16 +217,14 @@ public void fetchMatch_SerializingWrongPayload_Exception() { public void fetchMatch_BuildingRequestWithWrongEndpoint_Exception() throws Exception { try (MockedStatic mapper = Mockito.mockStatic(ResourceMapper.class)) { mapper.when(() -> ResourceMapper.writeValueAsString(matchRequest)).thenReturn(A_BODY_BYTES); - when(requestBuilderFactory.create()).thenReturn(signedRequestBuilder); String exMessage = "URI wrong format"; URISyntaxException causeEx = new URISyntaxException("", exMessage); - when(identityService.createSignedRequest(SDK_ID, keyPair, DIGITAL_ID_MATCH_PATH, POST, A_BODY_BYTES)) - .thenThrow(causeEx); + when(testObj.createRequest(DIGITAL_ID_MATCH_PATH, POST, A_BODY_BYTES)).thenThrow(causeEx); DigitalIdentityException ex = assertThrows( DigitalIdentityException.class, - () -> identityService.fetchMatch(SDK_ID, keyPair, matchRequest) + () -> testObj.fetchMatch(matchRequest) ); Throwable cause = ex.getCause(); @@ -370,16 +238,14 @@ public void fetchMatch_BuildingRequestWithWrongQueryParams_Exception() throws Ex try (MockedStatic mapper = Mockito.mockStatic(ResourceMapper.class)) { mapper.when(() -> ResourceMapper.writeValueAsString(matchRequest)).thenReturn(A_BODY_BYTES); - when(requestBuilderFactory.create()).thenReturn(signedRequestBuilder); - String exMessage = "Wrong query params format"; UnsupportedEncodingException causeEx = new UnsupportedEncodingException(exMessage); - when(identityService.createSignedRequest(SDK_ID, keyPair, DIGITAL_ID_MATCH_PATH, POST, A_BODY_BYTES)) + when(testObj.createRequest(DIGITAL_ID_MATCH_PATH, POST, A_BODY_BYTES)) .thenThrow(causeEx); DigitalIdentityException ex = assertThrows( DigitalIdentityException.class, - () -> identityService.fetchMatch(SDK_ID, keyPair, matchRequest) + () -> testObj.fetchMatch(matchRequest) ); Throwable cause = ex.getCause(); @@ -393,16 +259,14 @@ public void fetchMatch_BuildingRequestWithWrongDigest_Exception() throws Excepti try (MockedStatic mapper = Mockito.mockStatic(ResourceMapper.class)) { mapper.when(() -> ResourceMapper.writeValueAsString(matchRequest)).thenReturn(A_BODY_BYTES); - when(requestBuilderFactory.create()).thenReturn(signedRequestBuilder); - String exMessage = "Wrong digest"; GeneralSecurityException causeEx = new GeneralSecurityException(exMessage); - when(identityService.createSignedRequest(SDK_ID, keyPair, DIGITAL_ID_MATCH_PATH, POST, A_BODY_BYTES)) + when(testObj.createRequest(DIGITAL_ID_MATCH_PATH, POST, A_BODY_BYTES)) .thenThrow(causeEx); DigitalIdentityException ex = assertThrows( DigitalIdentityException.class, - () -> identityService.fetchMatch(SDK_ID, keyPair, matchRequest) + () -> testObj.fetchMatch(matchRequest) ); Throwable cause = ex.getCause(); @@ -416,14 +280,12 @@ public void fetchMatch_SessionRequest_exception() throws Exception { try (MockedStatic mapper = Mockito.mockStatic(ResourceMapper.class)) { mapper.when(() -> ResourceMapper.writeValueAsString(matchRequest)).thenReturn(A_BODY_BYTES); - when(requestBuilderFactory.create()).thenReturn(signedRequestBuilder); - - when(identityService.createSignedRequest(SDK_ID, keyPair, DIGITAL_ID_MATCH_PATH, POST, A_BODY_BYTES)) - .thenReturn(signedRequest); + when(testObj.createRequest(DIGITAL_ID_MATCH_PATH, POST, A_BODY_BYTES)) + .thenReturn(yotiHttpRequest); + when(yotiHttpRequest.execute(MatchResult.class)).thenReturn(matchResult); - when(signedRequest.execute(MatchResult.class)).thenReturn(matchResult); + MatchResult result = testObj.fetchMatch(matchRequest); - MatchResult result = identityService.fetchMatch(SDK_ID, keyPair, matchRequest); assertSame(matchResult, result); } } diff --git a/yoti-sdk-api/src/test/java/com/yoti/api/client/spi/remote/call/qrcode/DynamicSharingServiceTest.java b/yoti-sdk-api/src/test/java/com/yoti/api/client/spi/remote/call/qrcode/DynamicSharingServiceTest.java index 55ff43d29..6d7c79f5b 100644 --- a/yoti-sdk-api/src/test/java/com/yoti/api/client/spi/remote/call/qrcode/DynamicSharingServiceTest.java +++ b/yoti-sdk-api/src/test/java/com/yoti/api/client/spi/remote/call/qrcode/DynamicSharingServiceTest.java @@ -15,7 +15,7 @@ import com.yoti.api.client.shareurl.DynamicShareException; import com.yoti.api.client.shareurl.ShareUrlResult; import com.yoti.api.client.spi.remote.call.ResourceException; -import com.yoti.api.client.spi.remote.call.SignedRequest; +import com.yoti.api.client.spi.remote.call.YotiHttpRequest; import com.yoti.api.client.spi.remote.call.factory.UnsignedPathFactory; import com.fasterxml.jackson.core.JsonProcessingException; @@ -44,7 +44,7 @@ public class DynamicSharingServiceTest { @Mock ObjectMapper objectMapperMock; @Mock DynamicScenario simpleDynamicScenarioMock; - @Mock SignedRequest signedRequestMock; + @Mock YotiHttpRequest yotiHttpRequestMock; @Mock(answer = RETURNS_DEEP_STUBS) KeyPair keyPairMock; @Mock ShareUrlResult shareUrlResultMock; @@ -60,17 +60,12 @@ public void setUp() { @Test(expected = IllegalArgumentException.class) public void shouldFailWithNullAppId() throws Exception { - testObj.createShareUrl(null, keyPairMock, simpleDynamicScenarioMock); - } - - @Test(expected = IllegalArgumentException.class) - public void shouldFailWithNullKeyPair() throws Exception { - testObj.createShareUrl(APP_ID, null, simpleDynamicScenarioMock); + testObj.createShareUrl(null, simpleDynamicScenarioMock); } @Test(expected = IllegalArgumentException.class) public void shouldFailWithNullDynamicScenario() throws Exception { - testObj.createShareUrl(APP_ID, keyPairMock, null); + testObj.createShareUrl(APP_ID, null); } @Test @@ -79,7 +74,7 @@ public void shouldThrowDynamicShareExceptionWhenParsingFails() throws Exception when(objectMapperMock.writeValueAsString(simpleDynamicScenarioMock)).thenThrow(jsonProcessingException); try { - testObj.createShareUrl(APP_ID, keyPairMock, simpleDynamicScenarioMock); + testObj.createShareUrl(APP_ID, simpleDynamicScenarioMock); fail("Expected a DynamicShareException"); } catch (DynamicShareException ex) { assertSame(jsonProcessingException, ex.getCause()); @@ -90,11 +85,11 @@ public void shouldThrowDynamicShareExceptionWhenParsingFails() throws Exception public void shouldThrowExceptionForIOError() throws Exception { when(objectMapperMock.writeValueAsString(simpleDynamicScenarioMock)).thenReturn(SOME_BODY); IOException ioException = new IOException(); - doReturn(signedRequestMock).when(testObj).createSignedRequest(keyPairMock, DYNAMIC_QRCODE_PATH, SOME_BODY_BYTES); - when(signedRequestMock.execute(ShareUrlResult.class)).thenThrow(ioException); + doReturn(yotiHttpRequestMock).when(testObj).createRequest(DYNAMIC_QRCODE_PATH, SOME_BODY_BYTES); + when(yotiHttpRequestMock.execute(ShareUrlResult.class)).thenThrow(ioException); try { - testObj.createShareUrl(APP_ID, keyPairMock, simpleDynamicScenarioMock); + testObj.createShareUrl(APP_ID, simpleDynamicScenarioMock); fail("Expected a DynamicShareException"); } catch (DynamicShareException ex) { assertSame(ioException, ex.getCause()); @@ -105,11 +100,11 @@ public void shouldThrowExceptionForIOError() throws Exception { public void shouldThrowExceptionWithResourceExceptionCause() throws Exception { when(objectMapperMock.writeValueAsString(simpleDynamicScenarioMock)).thenReturn(SOME_BODY); ResourceException resourceException = new ResourceException(404, "Not Found", "Test exception"); - doReturn(signedRequestMock).when(testObj).createSignedRequest(keyPairMock, DYNAMIC_QRCODE_PATH, SOME_BODY_BYTES); - when(signedRequestMock.execute(ShareUrlResult.class)).thenThrow(resourceException); + doReturn(yotiHttpRequestMock).when(testObj).createRequest(DYNAMIC_QRCODE_PATH, SOME_BODY_BYTES); + when(yotiHttpRequestMock.execute(ShareUrlResult.class)).thenThrow(resourceException); try { - testObj.createShareUrl(APP_ID, keyPairMock, simpleDynamicScenarioMock); + testObj.createShareUrl(APP_ID, simpleDynamicScenarioMock); fail("Expected a DynamicShareException"); } catch (DynamicShareException ex) { assertSame(resourceException, ex.getCause()); @@ -119,10 +114,10 @@ public void shouldThrowExceptionWithResourceExceptionCause() throws Exception { @Test public void shouldReturnReceiptForCorrectRequest() throws Exception { when(objectMapperMock.writeValueAsString(simpleDynamicScenarioMock)).thenReturn(SOME_BODY); - doReturn(signedRequestMock).when(testObj).createSignedRequest(keyPairMock, DYNAMIC_QRCODE_PATH, SOME_BODY_BYTES); - when(signedRequestMock.execute(ShareUrlResult.class)).thenReturn(shareUrlResultMock); + doReturn(yotiHttpRequestMock).when(testObj).createRequest(DYNAMIC_QRCODE_PATH, SOME_BODY_BYTES); + when(yotiHttpRequestMock.execute(ShareUrlResult.class)).thenReturn(shareUrlResultMock); - ShareUrlResult result = testObj.createShareUrl(APP_ID, keyPairMock, simpleDynamicScenarioMock); + ShareUrlResult result = testObj.createShareUrl(APP_ID, simpleDynamicScenarioMock); assertSame(shareUrlResultMock, result); } diff --git a/yoti-sdk-auth/pom.xml b/yoti-sdk-auth/pom.xml new file mode 100644 index 000000000..4ce1c511d --- /dev/null +++ b/yoti-sdk-auth/pom.xml @@ -0,0 +1,113 @@ + + + 4.0.0 + + + com.yoti + yoti-sdk-parent + 4.0.0 + ../yoti-sdk-parent + + + yoti-sdk-auth + + + 0.13.0 + + + + + org.bouncycastle + bcpkix-jdk18on + + + com.yoti + yoti-sdk-api + + + io.jsonwebtoken + jjwt-api + ${jjwt.version} + + + com.fasterxml.jackson.core + jackson-databind + + + commons-logging + commons-logging + 1.1.1 + + + io.jsonwebtoken + jjwt-impl + ${jjwt.version} + runtime + + + io.jsonwebtoken + jjwt-jackson + ${jjwt.version} + runtime + + + + + org.hamcrest + hamcrest-library + test + + + junit + junit + test + + + org.mockito + mockito-core + test + + + + + + + + org.owasp + dependency-check-maven + + + org.codehaus.mojo + animal-sniffer-maven-plugin + + + maven-enforcer-plugin + + + maven-compiler-plugin + ${maven-compiler-plugin.version} + + + maven-source-plugin + + + maven-javadoc-plugin + + + org.jacoco + jacoco-maven-plugin + + + + + + + + maven-project-info-reports-plugin + + + + + diff --git a/yoti-sdk-auth/src/main/java/com/yoti/auth/AuthenticationTokenGenerator.java b/yoti-sdk-auth/src/main/java/com/yoti/auth/AuthenticationTokenGenerator.java new file mode 100644 index 000000000..8a0cf0369 --- /dev/null +++ b/yoti-sdk-auth/src/main/java/com/yoti/auth/AuthenticationTokenGenerator.java @@ -0,0 +1,193 @@ +package com.yoti.auth; + +import static com.yoti.validation.Validation.notNull; +import static com.yoti.validation.Validation.notNullOrEmpty; + +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URL; +import java.security.KeyPair; +import java.time.OffsetDateTime; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; +import java.util.function.Supplier; + +import com.yoti.api.client.InitialisationException; +import com.yoti.api.client.KeyPairSource; +import com.yoti.api.client.spi.remote.KeyStreamVisitor; +import com.yoti.api.client.spi.remote.call.ResourceException; + +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import io.jsonwebtoken.Jwts; + +/** + * The {@link AuthenticationTokenGenerator} is used for generation authorization tokens + * that can be used for accessing Yoti services. An authorization token must have + * a unique identifier, and an expiry timestamp. One or more scopes can be provided + * to allow the authorization token access to different parts of Yoti systems. + *

+ * The {@link AuthenticationTokenGenerator.Builder} can be accessed via {@code AuthorizationTokenGenerator.builder()} + * method, and then configured via the fluent API. + */ +public class AuthenticationTokenGenerator { + + private final String sdkId; + private final KeyPair keyPair; + private final Supplier jwtIdSupplier; + private final FormRequestClient formRequestClient; + + private final URL authApiUrl; + private final ObjectMapper objectMapper; + + AuthenticationTokenGenerator( + String sdkId, + KeyPair keyPair, + Supplier jwtIdSupplier, + FormRequestClient formRequestClient, + ObjectMapper objectMapper) { + this.sdkId = sdkId; + this.keyPair = keyPair; + this.jwtIdSupplier = jwtIdSupplier; + this.formRequestClient = formRequestClient; + this.objectMapper = objectMapper; + + try { + authApiUrl = new URL(System.getProperty(Properties.PROPERTY_YOTI_AUTH_URL, Properties.DEFAULT_YOTI_AUTH_URL)); + } catch (MalformedURLException e) { + throw new IllegalStateException("Invalid Yoti auth url", e); + } + } + + /** + * Creates a new instance of {@link AuthenticationTokenGenerator.Builder} + * + * @return the builder + */ + public static AuthenticationTokenGenerator.Builder builder() { + return new AuthenticationTokenGenerator.Builder(); + } + + /** + * Creates a new authentication token, using the supplied scopes and comment. + * + * @param scopes a list of scopes to be used by the authentication token + * @return a {@link CreateAuthenticationTokenResponse} containing information about the created token. + * @throws ResourceException if something was incorrect with the request to the Yoti authentication service + * @throws IOException + */ + public CreateAuthenticationTokenResponse generate(List scopes) throws ResourceException, IOException { + notNullOrEmpty(scopes, "scopes"); + + String jwts = createSignedJwt(sdkId, keyPair, jwtIdSupplier, authApiUrl); + + Map formParams = new HashMap<>(); + formParams.put("grant_type", "client_credentials"); + formParams.put("client_assertion_type", "urn:ietf:params:oauth:client-assertion-type:jwt-bearer"); + formParams.put("scope", String.join(" ", scopes)); + formParams.put("client_assertion", jwts); + + byte[] responseBody = formRequestClient.performRequest(authApiUrl, "POST", formParams); + + return objectMapper.readValue(responseBody, CreateAuthenticationTokenResponse.class); + } + + private String createSignedJwt(String sdkId, KeyPair keyPair, Supplier jwtIdSupplier, URL authApiUrl) { + String sdkIdProperty = String.format("sdk:%s", sdkId); + OffsetDateTime now = OffsetDateTime.now(); + return Jwts.builder() + .issuer(sdkIdProperty) + .subject(sdkIdProperty) + .id(jwtIdSupplier.get()) + .audience() + .add(authApiUrl.toString()) + .and() + .expiration(new Date(now.plusMinutes(5).toInstant().toEpochMilli())) + .issuedAt(new Date(now.toInstant().toEpochMilli())) + .header() + .add("alg", "PS384") + .add("typ", "JWT") + .and() + .signWith(keyPair.getPrivate(), Jwts.SIG.PS384) + .compact(); + } + + public static final class Builder { + + private String sdkId; + private KeyPairSource keyPairSource; + private Supplier jwtIdSupplier = () -> UUID.randomUUID().toString(); + + private Builder() { + } + + /** + * Sets the SDK ID that the authorization token will be generated against. + * + * @param sdkId the SDK ID + * @return the builder for method chaining. + */ + public Builder withSdkId(String sdkId) { + this.sdkId = sdkId; + return this; + } + + /** + * Sets the {@link KeyPairSource} that will be used to load the {@link KeyPair} + * + * @param keyPairSource the key pair source that will be used to load the {@link KeyPair} + * @return the builder for method chaining. + */ + public Builder withKeyPairSource(KeyPairSource keyPairSource) { + this.keyPairSource = keyPairSource; + return this; + } + + /** + * Sets the supplier that will be used to generate a unique ID for the + * authorization token. By default, this will be a UUID v4. + * + * @param jwtIdSupplier the supplier used for generating authorization token ID + * @return the builder for method chaining. + */ + public Builder withJwtIdSupplier(Supplier jwtIdSupplier) { + this.jwtIdSupplier = jwtIdSupplier; + return this; + } + + /** + * Builds an {@link AuthenticationTokenGenerator} using the values supplied to the {@link Builder}. + * + * @return the configured {@link AuthenticationTokenGenerator} + */ + public AuthenticationTokenGenerator build() { + notNullOrEmpty(sdkId, "sdkId"); + notNull(keyPairSource, "keyPairSource"); + notNull(jwtIdSupplier, "jwtIdSupplier"); + + ObjectMapper objectMapper = new ObjectMapper() + .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + + return new AuthenticationTokenGenerator( + sdkId, + loadKeyPair(keyPairSource), + jwtIdSupplier, + new FormRequestClient(), + objectMapper + ); + } + + private KeyPair loadKeyPair(KeyPairSource kpSource) throws InitialisationException { + try { + return kpSource.getFromStream(new KeyStreamVisitor()); + } catch (IOException e) { + throw new InitialisationException("Cannot load key pair", e); + } + } + + } + +} diff --git a/yoti-sdk-auth/src/main/java/com/yoti/auth/CreateAuthenticationTokenResponse.java b/yoti-sdk-auth/src/main/java/com/yoti/auth/CreateAuthenticationTokenResponse.java new file mode 100644 index 000000000..3f4cb439c --- /dev/null +++ b/yoti-sdk-auth/src/main/java/com/yoti/auth/CreateAuthenticationTokenResponse.java @@ -0,0 +1,56 @@ +package com.yoti.auth; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public final class CreateAuthenticationTokenResponse { + + @JsonProperty("access_token") + private String accessToken; + + @JsonProperty("token_type") + private String tokenType; + + @JsonProperty("expires_in") + private Integer expiresIn; + + @JsonProperty("scope") + private String scope; + + /** + * Returns the Yoti Authentication token used to perform requests to other Yoti services. + * + * @return the newly created access token + */ + public String getAccessToken() { + return accessToken; + } + + /** + * Returns the type of the newly generated authentication token. + * + * @return the token type + */ + public String getTokenType() { + return tokenType; + } + + /** + * Returns the amount of time (in seconds) in which the newly generated Authentication Token + * will expire in. + * + * @return the time (in seconds) of when the token will expire + */ + public Integer getExpiresIn() { + return expiresIn; + } + + /** + * A whitespace delimited string of scopes that the Authentication token has. + * + * @return the scopes of the token as a whitespace delimited string + */ + public String getScope() { + return scope; + } + +} diff --git a/yoti-sdk-auth/src/main/java/com/yoti/auth/FormRequestClient.java b/yoti-sdk-auth/src/main/java/com/yoti/auth/FormRequestClient.java new file mode 100644 index 000000000..becfc1dda --- /dev/null +++ b/yoti-sdk-auth/src/main/java/com/yoti/auth/FormRequestClient.java @@ -0,0 +1,84 @@ +package com.yoti.auth; + +import java.io.ByteArrayOutputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.UnsupportedEncodingException; +import java.net.HttpURLConnection; +import java.net.URL; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.util.Map; +import java.util.stream.Collectors; + +import com.yoti.api.client.spi.remote.call.ResourceException; +import com.yoti.api.client.spi.remote.util.QuietCloseable; + +/** + * Internal use only. + *

+ * The {@link FormRequestClient} is used for performing an application/x-www-form-urlencoded + * HTTP request using base Java libraries only. + */ +final class FormRequestClient { + + byte[] performRequest(URL url, String method, Map formParams) throws IOException, ResourceException { + byte[] postData = getData(formParams); + HttpURLConnection connection = (HttpURLConnection) url.openConnection(); + connection.setDoOutput(true); + connection.setRequestMethod(method); + connection.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); + connection.setRequestProperty("Content-Length", Integer.toString(postData.length)); + connection.setRequestProperty("charset", StandardCharsets.UTF_8.toString()); + connection.setUseCaches(false); + connection.setInstanceFollowRedirects(false); + + try (DataOutputStream wr = new DataOutputStream(connection.getOutputStream())) { + wr.write(postData); + } + + return parseResponse(connection); + } + + private byte[] getData(Map params) { + return params.entrySet().stream() + .map(entry -> encode(entry.getKey()) + "=" + encode(entry.getValue())) + .collect(Collectors.joining("&")) + .getBytes(StandardCharsets.UTF_8); + } + + private static String encode(String v) { + try { + return URLEncoder.encode(v, StandardCharsets.UTF_8.toString()); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException(e); + } + } + + private byte[] parseResponse(HttpURLConnection httpUrlConnection) throws ResourceException, IOException { + int responseCode = httpUrlConnection.getResponseCode(); + if (responseCode >= HttpURLConnection.HTTP_BAD_REQUEST) { + byte[] responseBody = readBody(httpUrlConnection.getErrorStream()); + throw new ResourceException(responseCode, httpUrlConnection.getResponseMessage(), new String(responseBody)); + } + return readBody(httpUrlConnection.getInputStream()); + } + + private byte[] readBody(InputStream httpInputStream) throws IOException { + try (QuietCloseable inputStream = new QuietCloseable<>(httpInputStream)) { + return readChunked(inputStream.get()); + } + } + + private byte[] readChunked(InputStream inputStream) throws IOException { + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + byte[] byteChunk = new byte[4096]; + int n; + while ((n = inputStream.read(byteChunk)) > 0) { + byteArrayOutputStream.write(byteChunk, 0, n); + } + return byteArrayOutputStream.toByteArray(); + } + +} diff --git a/yoti-sdk-auth/src/main/java/com/yoti/auth/Properties.java b/yoti-sdk-auth/src/main/java/com/yoti/auth/Properties.java new file mode 100644 index 000000000..d72e30926 --- /dev/null +++ b/yoti-sdk-auth/src/main/java/com/yoti/auth/Properties.java @@ -0,0 +1,17 @@ +package com.yoti.auth; + +/** + * Internal use only. + *

+ * Contains property values used by the `yoti-sdk-auth` module for + * creating Yoti Authentication tokens. + */ +final class Properties { + + private static final String YOTI_AUTH_HOST = "https://auth.api.yoti.com"; + private static final String YOTI_AUTH_PATH_PREFIX = "/v1/oauth/token"; + + public static final String PROPERTY_YOTI_AUTH_URL = "yoti.auth.url"; + public static final String DEFAULT_YOTI_AUTH_URL = YOTI_AUTH_HOST + YOTI_AUTH_PATH_PREFIX; + +} diff --git a/yoti-sdk-auth/src/test/java/com/yoti/auth/AuthenticationTokenGeneratorTest.java b/yoti-sdk-auth/src/test/java/com/yoti/auth/AuthenticationTokenGeneratorTest.java new file mode 100644 index 000000000..cec6eb0af --- /dev/null +++ b/yoti-sdk-auth/src/test/java/com/yoti/auth/AuthenticationTokenGeneratorTest.java @@ -0,0 +1,124 @@ +package com.yoti.auth; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertThrows; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.when; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.security.KeyPair; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.UUID; +import java.util.function.Supplier; + +import com.yoti.api.client.InitialisationException; +import com.yoti.api.client.KeyPairSource; +import com.yoti.auth.util.CryptoUtil; + +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Captor; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.class) +public class AuthenticationTokenGeneratorTest { + + private static final String SOME_AUTH_API_URL = "https://someAuthApiUrl"; + private static final String SOME_SDK_ID = "someSdkId"; + private static final Supplier SOME_JWT_ID_SUPPLIER = () -> UUID.randomUUID().toString(); + private static final byte[] SOME_RESPONSE_BODY = new byte[] { 1, 2, 3 }; + + @Mock FormRequestClient formRequestClientMock; + @Mock ObjectMapper objectMapperMock; + + @Mock KeyPairSource keyPairSourceMock; + @Mock CreateAuthenticationTokenResponse createAuthenticationTokenResponseMock; + + @Captor ArgumentCaptor urlArgumentCaptor; + @Captor ArgumentCaptor> formParamsCaptor; + + private KeyPair validKeyPair; + + @Before + public void setUp() throws IOException { + System.setProperty(Properties.PROPERTY_YOTI_AUTH_URL, SOME_AUTH_API_URL); + validKeyPair = CryptoUtil.generateKeyPairFrom(CryptoUtil.KEY_PAIR_PEM); + } + + @Test + public void builder_shouldThrowIfSdkIdIsNotProvided() { + IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> { + AuthenticationTokenGenerator.builder().build(); + }); + + assertThat(exception.getMessage(), is("'sdkId' must not be empty or null")); + } + + @Test + public void builder_shouldThrowIfKeyPairSourceIsNotProvided() { + IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> { + AuthenticationTokenGenerator.builder() + .withSdkId(SOME_SDK_ID) + .build(); + }); + + assertThat(exception.getMessage(), is("'keyPairSource' must not be null")); + } + + @Test + public void builder_shouldThrowIfKeyPairSourceIsNull() { + IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> { + AuthenticationTokenGenerator.builder() + .withSdkId(SOME_SDK_ID) + .withKeyPairSource(null) + .build(); + }); + + assertThat(exception.getMessage(), is("'keyPairSource' must not be null")); + } + + @Test + public void builder_shouldThrowIfJwtIdSupplierIsNull() { + IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, () -> { + AuthenticationTokenGenerator.builder() + .withSdkId(SOME_SDK_ID) + .withKeyPairSource(keyPairSourceMock) + .withJwtIdSupplier(null) + .build(); + }); + + assertThat(exception.getMessage(), is("'jwtIdSupplier' must not be null")); + } + + @Test + public void shouldJoinScopesCorrectly() throws Exception { + when(formRequestClientMock.performRequest(urlArgumentCaptor.capture(), eq("POST"), formParamsCaptor.capture())).thenReturn(SOME_RESPONSE_BODY); + when(objectMapperMock.readValue(SOME_RESPONSE_BODY, CreateAuthenticationTokenResponse.class)).thenReturn(createAuthenticationTokenResponseMock); + + AuthenticationTokenGenerator tokenGenerator = new AuthenticationTokenGenerator(SOME_SDK_ID, validKeyPair, SOME_JWT_ID_SUPPLIER, formRequestClientMock, objectMapperMock); + + List scopes = Arrays.asList("scope1", "scope2", "scope3:read"); + + CreateAuthenticationTokenResponse result = tokenGenerator.generate(scopes); + + assertThat(result, is(createAuthenticationTokenResponseMock)); + + Map formParams = formParamsCaptor.getValue(); + assertThat(formParams.get("grant_type"), is("client_credentials")); + assertThat(formParams.get("client_assertion_type"), is("urn:ietf:params:oauth:client-assertion-type:jwt-bearer")); + assertThat(formParams.get("scope"), is("scope1 scope2 scope3:read")); + + assertThat(urlArgumentCaptor.getValue().toString(), is(SOME_AUTH_API_URL)); + } + +} diff --git a/yoti-sdk-auth/src/test/java/com/yoti/auth/util/CryptoUtil.java b/yoti-sdk-auth/src/test/java/com/yoti/auth/util/CryptoUtil.java new file mode 100644 index 000000000..c8520df59 --- /dev/null +++ b/yoti-sdk-auth/src/test/java/com/yoti/auth/util/CryptoUtil.java @@ -0,0 +1,64 @@ +package com.yoti.auth.util; + +import java.io.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.security.KeyPair; +import java.security.Security; + +import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.bouncycastle.openssl.PEMKeyPair; +import org.bouncycastle.openssl.PEMParser; +import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter; + +public class CryptoUtil { + + public static final String KEY_PAIR_PEM = "-----BEGIN RSA PRIVATE KEY-----\n" + + "MIIEogIBAAKCAQEAvTGVVGqq2jv9K1BwT8+7GAURqoZOT8gfk2vIT3YKf3ZEB2OG\n" + + "qp9qiAaZZpL4RJKOA9x3uJxC3XVIRa+8TpvWmpUnFJJZMotE/W6jjPvOLiu4V27m\n" + + "H0i1CNy5Icjx7g3Wo2Pj2AUEOqV+bB1we2VSbNhPpJHmN2azmOMRuc7SMyXukWy5\n" + + "EeS2ZlwD2cfm3jJdTmWysV6+D4t02y3DYckjRe3RA/5pOYYg7+qgL/fjtb8eUOx3\n" + + "08fwzlS0dXwuYegX0aJuUd4KOu/drDzg2KDHDKlUmuPgHTKwlKX/mgjaXbldB9ER\n" + + "pTyq68OtJ37TElNgTl/rashfbEaC3LbQtn3lFQIDAQABAoIBADS3XSmhcyvN7VQl\n" + + "XLYQZsxhlTOTqrx2Qb4dGTpy5KfxdzEr3TkrpE50sEexifXpdCLFSqKo/8SfSl0I\n" + + "g4rPx3NZPgNwZ+Q6hCWtr2q4OxIIYpwSLZLn+nGWtwsf57FyL61lRvZJJ42D0X8k\n" + + "kNQBPn9PoplzgddMCZz/IFBKva08WDlib6h9eBMUXxw94/kEpp1WBhWreq4trADg\n" + + "l8l4BHTheT259PmgDq8L83irGjxYbuMrlNrOigXfesgbyX8UBVVkTEqHUWNnNRAR\n" + + "XONm+75GJT8r51ijdpHfEnpy54bNTXT7KHVMaHmPSQIazylvQJQew0WVZ0a9VwvF\n" + + "QZPOngECgYEA9AngQ+GCJW9vC4UCtIpuWZajCw+KNXlw4rfpXJuajnm3O+znfO+q\n" + + "FQn8IA5u1Sw1DimvdLACSavCax0p6vvJtAxjTgPtID6OnBJ3cD0rjqAcqEbZ29Xu\n" + + "YeaAg0dnSRfb5wkpbk0EtK2RkFocwdM/ql1s8WkrFkqs681zRqGLs5UCgYEAxneH\n" + + "nuHkIq8O69h+CI1RmNZpLhQBspseHXbhwTzQIvqzdiIwlPTR9mfZsGrnCokb/0CC\n" + + "BvYih+GLZN62iEaf+aCUA+662BZrNAMwEY/k4Ris+sKFNT0tBNoPDOgqdnygH9gm\n" + + "coKdIDO9sPL0144U/Hq1YsdwuK2SDQcLY3ydC4ECgYA71QALJIsIKp4LMP1MznPn\n" + + "uysWVyUHn1KyA21Pq0blj6oBI0BOPWRx7BTIt0EtOr13T3kZHt4wuc/c+zV/y2PU\n" + + "pQTj58qHkU7drRljh1vaiB7+kwBvCbB8iEsR5LvKC/N6XaCuzmtM8REzVySd0PFX\n" + + "D7jaJ3LM8FodJi4RLyJVUQKBgEy80teACDHQ9jgC0ViFK9Oos6p5Wd6xU4eY+9k3\n" + + "plKgFNvMhHRT5QsdRHKOIx9TvFuJmb0PVnKrprYt1u4CQMDIcfLDT8NVh8XopaFk\n" + + "vd67J8cdh1v6d3m0xrT639BIh7FIZjVIg3B8ERBmIH1oFn05BQFYlCEUG7Cl1KV2\n" + + "/VIBAoGAYin6eHFtBXpPRMddTt4lLOFtpBb9gGp9DxKGAsH0pdfQYgZHz0xKtxrq\n" + + "6l+d2M9sRhtisxw8YevPFWEVtcUWxz+qESM+wzUMrmWSuwwxXyVgjR4rC8untfPM\n" + + "laDBX8dDBwBQ3i0FhvuGR/LEjHWr9hj00faKROHOLFim6wbRIkg=\n" + + "-----END RSA PRIVATE KEY-----"; + + static { + Security.addProvider(new BouncyCastleProvider()); + } + + public static KeyPair generateKeyPairFrom(String keyPairString) throws IOException { + KeyPair keyPair = null; + PEMParser reader = new PEMParser( + new BufferedReader(new InputStreamReader(new ByteArrayInputStream(keyPairString.getBytes())))); + + for (Object o; (o = reader.readObject()) != null; ) { + if (o instanceof PEMKeyPair) { + keyPair = new JcaPEMKeyConverter().getKeyPair((PEMKeyPair) o); + break; + } + } + reader.close(); + return keyPair; + } + +} diff --git a/yoti-sdk-auth/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker b/yoti-sdk-auth/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker new file mode 100644 index 000000000..1f0955d45 --- /dev/null +++ b/yoti-sdk-auth/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker @@ -0,0 +1 @@ +mock-maker-inline diff --git a/yoti-sdk-parent/pom.xml b/yoti-sdk-parent/pom.xml index d1e258d7e..183ed1c9b 100644 --- a/yoti-sdk-parent/pom.xml +++ b/yoti-sdk-parent/pom.xml @@ -5,7 +5,7 @@ com.yoti yoti-sdk-parent pom - 3.12.0 + 4.0.0 Yoti SDK Parent Pom Parent pom for the Java SDK projects https://github.com/getyoti/yoti-java-sdk diff --git a/yoti-sdk-sandbox/pom.xml b/yoti-sdk-sandbox/pom.xml index 768c2913b..878164a2d 100644 --- a/yoti-sdk-sandbox/pom.xml +++ b/yoti-sdk-sandbox/pom.xml @@ -11,7 +11,7 @@ com.yoti yoti-sdk-parent - 3.12.0 + 4.0.0 ../yoti-sdk-parent diff --git a/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/SandboxPathFactory.java b/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/SandboxPathFactory.java index 1cf115f8c..cb5213401 100644 --- a/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/SandboxPathFactory.java +++ b/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/SandboxPathFactory.java @@ -1,16 +1,13 @@ package com.yoti.api.client.sandbox; import static java.lang.String.format; -import static java.util.UUID.randomUUID; -import com.yoti.api.client.spi.remote.call.factory.PathFactory; +public class SandboxPathFactory { -public class SandboxPathFactory extends PathFactory { - - private static final String CREATE_SANDBOX_TOKEN_PATH = "/apps/%s/tokens?timestamp=%s&nonce=%s"; + private static final String CREATE_SANDBOX_TOKEN_PATH = "/apps/%s/tokens"; public String createSandboxPath(String appId) { - return format(CREATE_SANDBOX_TOKEN_PATH, appId, createTimestamp(), randomUUID()); + return format(CREATE_SANDBOX_TOKEN_PATH, appId); } } diff --git a/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/YotiSandboxClient.java b/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/YotiSandboxClient.java index 1f113c752..06be9b5cb 100644 --- a/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/YotiSandboxClient.java +++ b/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/YotiSandboxClient.java @@ -18,11 +18,10 @@ import com.yoti.api.client.spi.remote.call.JsonResourceFetcher; import com.yoti.api.client.spi.remote.call.ResourceException; import com.yoti.api.client.spi.remote.call.ResourceFetcher; -import com.yoti.api.client.spi.remote.call.SignedRequest; -import com.yoti.api.client.spi.remote.call.SignedRequestBuilder; -import com.yoti.api.client.spi.remote.call.SignedRequestBuilderFactory; import com.yoti.api.client.spi.remote.call.YotiConstants; -import com.yoti.api.client.spi.remote.call.factory.SignedMessageFactory; +import com.yoti.api.client.spi.remote.call.YotiHttpRequest; +import com.yoti.api.client.spi.remote.call.YotiHttpRequestBuilderFactory; +import com.yoti.api.client.spi.remote.call.factory.SimpleSignedRequestStrategy; import com.fasterxml.jackson.databind.ObjectMapper; import org.slf4j.Logger; @@ -34,12 +33,12 @@ public class YotiSandboxClient { private static final String DEFAULT_SANDBOX_API_URL = DEFAULT_YOTI_HOST + YOTI_SANDBOX_PATH_PREFIX; private final String appId; - private final KeyPair keyPair; + private final SimpleSignedRequestStrategy authStrategy; private final String sandboxBasePath; private final ObjectMapper mapper; private final SandboxPathFactory sandboxPathFactory; private final ResourceFetcher resourceFetcher; - private final SignedRequestBuilderFactory signedRequestBuilderFactory; + private final YotiHttpRequestBuilderFactory yotiHttpRequestBuilderFactory; public static YotiSandboxClientBuilder builder() { return new YotiSandboxClientBuilder(); @@ -49,13 +48,14 @@ public static YotiSandboxClientBuilder builder() { KeyPair keyPair, SandboxPathFactory pathFactory, ObjectMapper mapper, - ResourceFetcher resourceFetcher, SignedRequestBuilderFactory signedRequestBuilderFactory) { + ResourceFetcher resourceFetcher, + YotiHttpRequestBuilderFactory yotiHttpRequestBuilderFactory) { this.appId = appId; - this.keyPair = keyPair; + this.authStrategy = new SimpleSignedRequestStrategy(keyPair); this.sandboxPathFactory = pathFactory; this.mapper = mapper; this.resourceFetcher = resourceFetcher; - this.signedRequestBuilderFactory = signedRequestBuilderFactory; + this.yotiHttpRequestBuilderFactory = yotiHttpRequestBuilderFactory; this.sandboxBasePath = System.getProperty(YotiConstants.PROPERTY_YOTI_API_URL, DEFAULT_SANDBOX_API_URL); notNullOrEmpty(sandboxBasePath, "Sandbox base path"); @@ -65,14 +65,14 @@ public String setupSharingProfile(YotiTokenRequest yotiTokenRequest) { String requestPath = sandboxPathFactory.createSandboxPath(appId); try { byte[] body = mapper.writeValueAsBytes(yotiTokenRequest); - SignedRequest signedRequest = signedRequestBuilderFactory.create() + YotiHttpRequest yotiHttpRequest = yotiHttpRequestBuilderFactory.create() .withBaseUrl(sandboxBasePath) .withEndpoint(requestPath) - .withKeyPair(keyPair) + .withAuthStrategy(authStrategy) .withHttpMethod(HTTP_POST) .withPayload(body) .build(); - YotiTokenResponse yotiTokenResponse = resourceFetcher.doRequest(signedRequest, YotiTokenResponse.class); + YotiTokenResponse yotiTokenResponse = resourceFetcher.doRequest(yotiHttpRequest, YotiTokenResponse.class); return yotiTokenResponse.getToken(); } catch (IOException | GeneralSecurityException | ResourceException | URISyntaxException e) { throw new SandboxException(e); @@ -108,7 +108,7 @@ public YotiSandboxClient build() { notNullOrEmpty(appId, "appId"); notNull(keyPair, "keyPair"); return new YotiSandboxClient(appId, keyPair, new SandboxPathFactory(), new ObjectMapper(), JsonResourceFetcher.newInstance(), - new SignedRequestBuilderFactory()); + new YotiHttpRequestBuilderFactory()); } } diff --git a/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/DocScanSandboxClient.java b/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/DocScanSandboxClient.java index d70165518..02545d2c4 100644 --- a/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/DocScanSandboxClient.java +++ b/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/DocScanSandboxClient.java @@ -2,8 +2,7 @@ import static com.yoti.api.client.spi.remote.call.YotiConstants.DEFAULT_YOTI_HOST; import static com.yoti.api.client.spi.remote.call.YotiConstants.PROPERTY_YOTI_DOCS_URL; -import static com.yoti.api.client.spi.remote.util.Validation.notNull; -import static com.yoti.api.client.spi.remote.util.Validation.notNullOrEmpty; +import static com.yoti.validation.Validation.notNullOrEmpty; import java.io.IOException; import java.net.URISyntaxException; @@ -17,8 +16,11 @@ import com.yoti.api.client.spi.remote.KeyStreamVisitor; import com.yoti.api.client.spi.remote.call.HttpMethod; import com.yoti.api.client.spi.remote.call.ResourceException; -import com.yoti.api.client.spi.remote.call.SignedRequest; -import com.yoti.api.client.spi.remote.call.SignedRequestBuilderFactory; +import com.yoti.api.client.spi.remote.call.YotiHttpRequest; +import com.yoti.api.client.spi.remote.call.YotiHttpRequestBuilderFactory; +import com.yoti.api.client.spi.remote.call.factory.AuthStrategy; +import com.yoti.api.client.spi.remote.call.factory.AuthTokenStrategy; +import com.yoti.api.client.spi.remote.call.factory.DocsSignedRequestStrategy; import com.fasterxml.jackson.databind.ObjectMapper; import org.slf4j.Logger; @@ -31,18 +33,18 @@ public class DocScanSandboxClient { private final String docScanBaseUrl; private final ObjectMapper mapper; - private final SignedRequestBuilderFactory signedRequestBuilderFactory; + private final YotiHttpRequestBuilderFactory yotiHttpRequestBuilderFactory; private final String sdkId; - private final KeyPair keyPair; + private final AuthStrategy authStrategy; - DocScanSandboxClient(String sdkId, - KeyPair keyPair, + private DocScanSandboxClient(String sdkId, + AuthStrategy authStrategy, ObjectMapper mapper, - SignedRequestBuilderFactory signedRequestBuilderFactory) { + YotiHttpRequestBuilderFactory yotiHttpRequestBuilderFactory) { this.sdkId = sdkId; - this.keyPair = keyPair; + this.authStrategy = authStrategy; this.mapper = mapper; - this.signedRequestBuilderFactory = signedRequestBuilderFactory; + this.yotiHttpRequestBuilderFactory = yotiHttpRequestBuilderFactory; this.docScanBaseUrl = System.getProperty(PROPERTY_YOTI_DOCS_URL, DEFAULT_DOC_SCAN_SANDBOX_API_URL); } @@ -63,16 +65,15 @@ public void configureSessionResponse(String sessionId, ResponseConfig responseCo try { byte[] body = mapper.writeValueAsBytes(responseConfig); - SignedRequest signedRequest = signedRequestBuilderFactory.create() + YotiHttpRequest yotiHttpRequest = yotiHttpRequestBuilderFactory.create() .withBaseUrl(docScanBaseUrl) .withEndpoint(path) - .withKeyPair(keyPair) + .withAuthStrategy(authStrategy) .withHttpMethod(HttpMethod.HTTP_PUT) .withPayload(body) - .withQueryParameter("sdkId", sdkId) .build(); - signedRequest.execute(); + yotiHttpRequest.execute(); } catch (URISyntaxException | GeneralSecurityException | ResourceException | IOException e) { throw new SandboxException(e); } @@ -89,15 +90,15 @@ public void configureApplicationResponse(ResponseConfig sandboxExpectation) thro try { byte[] body = mapper.writeValueAsBytes(sandboxExpectation); - SignedRequest signedRequest = signedRequestBuilderFactory.create() + YotiHttpRequest yotiHttpRequest = yotiHttpRequestBuilderFactory.create() .withBaseUrl(docScanBaseUrl) .withEndpoint(path) - .withKeyPair(keyPair) + .withAuthStrategy(authStrategy) .withHttpMethod(HttpMethod.HTTP_PUT) .withPayload(body) .build(); - signedRequest.execute(); + yotiHttpRequest.execute(); } catch (URISyntaxException | GeneralSecurityException | ResourceException | IOException e) { throw new SandboxException(e); } @@ -107,10 +108,15 @@ public static class Builder { private static final Logger LOGGER = LoggerFactory.getLogger(Builder.class); + private String authToken; private String sdkId; private KeyPair keyPair; - private Builder() { + private Builder() {} + + public Builder withAuthenticationToken(String authenticationToken) { + this.authToken = authenticationToken; + return this; } public Builder withSdkId(String sdkId) { @@ -130,9 +136,28 @@ public Builder withKeyPair(KeyPairSource keyPairSource) { public DocScanSandboxClient build() { notNullOrEmpty(sdkId, "sdkId"); - notNull(keyPair, "keyPair"); - return new DocScanSandboxClient(sdkId, keyPair, new ObjectMapper(), new SignedRequestBuilderFactory()); + if (authToken == null) { + validateForSignedRequest(); + return new DocScanSandboxClient(sdkId, new DocsSignedRequestStrategy(keyPair, sdkId), new ObjectMapper(), new YotiHttpRequestBuilderFactory()); + } else { + validateAuthToken(); + return new DocScanSandboxClient(sdkId, new AuthTokenStrategy(authToken), new ObjectMapper(), new YotiHttpRequestBuilderFactory()); + } + } + + private void validateForSignedRequest() { + if (sdkId == null || sdkId.isEmpty() || keyPair == null) { + throw new IllegalStateException("An sdkId and KeyPairSource must be provided when not using an authentication token"); + } } + + private void validateAuthToken() { + if (keyPair != null) { + throw new IllegalStateException("Must not supply KeyPairSource when using an authentication token"); + } + } + } + } diff --git a/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/ResponseConfig.java b/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/ResponseConfig.java index 2fc3d99dd..8da757373 100644 --- a/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/ResponseConfig.java +++ b/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/ResponseConfig.java @@ -12,7 +12,7 @@ public class ResponseConfig { @JsonProperty("check_reports") private SandboxCheckReports checkReports; - ResponseConfig(SandboxTaskResults taskResults, SandboxCheckReports checkReports) { + private ResponseConfig(SandboxTaskResults taskResults, SandboxCheckReports checkReports) { this.taskResults = taskResults; this.checkReports = checkReports; } diff --git a/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/SandboxCheckReports.java b/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/SandboxCheckReports.java index 1b1c3d097..a6f0b9058 100644 --- a/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/SandboxCheckReports.java +++ b/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/SandboxCheckReports.java @@ -74,7 +74,7 @@ public class SandboxCheckReports { @JsonProperty("async_report_delay") private final Integer asyncReportDelay; - SandboxCheckReports(List documentTextDataChecks, + private SandboxCheckReports(List documentTextDataChecks, List documentAuthenticityChecks, List livenessChecks, List documentFaceMatchChecks, diff --git a/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/SandboxDocumentFilter.java b/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/SandboxDocumentFilter.java index 215c148c7..9d9fb8069 100644 --- a/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/SandboxDocumentFilter.java +++ b/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/SandboxDocumentFilter.java @@ -15,7 +15,7 @@ public class SandboxDocumentFilter { @JsonProperty("country_codes") private final List countryCodes; - SandboxDocumentFilter(List documentTypes, List countryCodes) { + private SandboxDocumentFilter(List documentTypes, List countryCodes) { this.documentTypes = documentTypes; this.countryCodes = countryCodes; } diff --git a/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/SandboxTaskResults.java b/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/SandboxTaskResults.java index 9b07bec39..479405e10 100644 --- a/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/SandboxTaskResults.java +++ b/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/SandboxTaskResults.java @@ -19,7 +19,7 @@ public class SandboxTaskResults { @JsonProperty(DocScanConstants.SUPPLEMENTARY_DOCUMENT_TEXT_DATA_EXTRACTION) private final List supplementaryTextDataExtractionTasks; - SandboxTaskResults(List documentTextDataExtractionTasks, + private SandboxTaskResults(List documentTextDataExtractionTasks, List supplementaryTextDataExtractionTasks) { this.documentTextDataExtractionTasks = documentTextDataExtractionTasks; this.supplementaryTextDataExtractionTasks = supplementaryTextDataExtractionTasks; diff --git a/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/check/SandboxDocumentAuthenticityCheck.java b/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/check/SandboxDocumentAuthenticityCheck.java index a3225442f..1d3e019a1 100644 --- a/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/check/SandboxDocumentAuthenticityCheck.java +++ b/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/check/SandboxDocumentAuthenticityCheck.java @@ -5,7 +5,7 @@ public class SandboxDocumentAuthenticityCheck extends SandboxDocumentCheck { - SandboxDocumentAuthenticityCheck(SandboxCheckResult result, SandboxDocumentFilter documentFilter) { + private SandboxDocumentAuthenticityCheck(SandboxCheckResult result, SandboxDocumentFilter documentFilter) { super(result, documentFilter); } diff --git a/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/check/SandboxDocumentFaceMatchCheck.java b/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/check/SandboxDocumentFaceMatchCheck.java index 80bc3a66f..848cf137c 100644 --- a/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/check/SandboxDocumentFaceMatchCheck.java +++ b/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/check/SandboxDocumentFaceMatchCheck.java @@ -5,7 +5,7 @@ public class SandboxDocumentFaceMatchCheck extends SandboxDocumentCheck { - SandboxDocumentFaceMatchCheck(SandboxCheckResult result, SandboxDocumentFilter documentFilter) { + private SandboxDocumentFaceMatchCheck(SandboxCheckResult result, SandboxDocumentFilter documentFilter) { super(result, documentFilter); } diff --git a/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/check/SandboxDocumentTextDataCheck.java b/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/check/SandboxDocumentTextDataCheck.java index ae5dc902a..132ba01a3 100644 --- a/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/check/SandboxDocumentTextDataCheck.java +++ b/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/check/SandboxDocumentTextDataCheck.java @@ -11,7 +11,7 @@ @JsonInclude(JsonInclude.Include.NON_EMPTY) public class SandboxDocumentTextDataCheck extends SandboxDocumentCheck { - SandboxDocumentTextDataCheck(SandboxDocumentTextDataCheckResult result, SandboxDocumentFilter documentFilter) { + private SandboxDocumentTextDataCheck(SandboxDocumentTextDataCheckResult result, SandboxDocumentFilter documentFilter) { super(result, documentFilter); } diff --git a/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/check/SandboxFaceComparisonCheck.java b/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/check/SandboxFaceComparisonCheck.java index e4dc1cdb5..719064908 100644 --- a/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/check/SandboxFaceComparisonCheck.java +++ b/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/check/SandboxFaceComparisonCheck.java @@ -4,7 +4,7 @@ public class SandboxFaceComparisonCheck extends SandboxCheck { - SandboxFaceComparisonCheck(SandboxCheckResult result) { + private SandboxFaceComparisonCheck(SandboxCheckResult result) { super(result); } diff --git a/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/check/SandboxIdDocumentComparisonCheck.java b/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/check/SandboxIdDocumentComparisonCheck.java index 4a05675b1..1d16c7d90 100644 --- a/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/check/SandboxIdDocumentComparisonCheck.java +++ b/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/check/SandboxIdDocumentComparisonCheck.java @@ -10,7 +10,7 @@ public class SandboxIdDocumentComparisonCheck extends SandboxCheck { @JsonProperty("secondary_document_filter") private final SandboxDocumentFilter secondaryDocumentFilter; - SandboxIdDocumentComparisonCheck(SandboxCheckResult result, SandboxDocumentFilter secondaryDocumentFilter) { + private SandboxIdDocumentComparisonCheck(SandboxCheckResult result, SandboxDocumentFilter secondaryDocumentFilter) { super(result); this.secondaryDocumentFilter = secondaryDocumentFilter; } diff --git a/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/check/SandboxSupplementaryDocumentTextDataCheck.java b/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/check/SandboxSupplementaryDocumentTextDataCheck.java index c03053847..7e2fc98cf 100644 --- a/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/check/SandboxSupplementaryDocumentTextDataCheck.java +++ b/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/check/SandboxSupplementaryDocumentTextDataCheck.java @@ -8,7 +8,7 @@ public class SandboxSupplementaryDocumentTextDataCheck extends SandboxDocumentCheck { - SandboxSupplementaryDocumentTextDataCheck(SandboxSupplementaryDocumentTextDataCheckResult result, SandboxDocumentFilter documentFilter) { + private SandboxSupplementaryDocumentTextDataCheck(SandboxSupplementaryDocumentTextDataCheckResult result, SandboxDocumentFilter documentFilter) { super(result, documentFilter); } diff --git a/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/check/SandboxSynecticsIdentityFraudCheck.java b/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/check/SandboxSynecticsIdentityFraudCheck.java index db3dc0cd7..eecf17702 100644 --- a/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/check/SandboxSynecticsIdentityFraudCheck.java +++ b/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/check/SandboxSynecticsIdentityFraudCheck.java @@ -4,7 +4,7 @@ public class SandboxSynecticsIdentityFraudCheck extends SandboxCheck { - SandboxSynecticsIdentityFraudCheck(SandboxCheckResult result) { + private SandboxSynecticsIdentityFraudCheck(SandboxCheckResult result) { super(result); } diff --git a/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/check/SandboxThirdPartyIdentityCheck.java b/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/check/SandboxThirdPartyIdentityCheck.java index 7df9c8846..07baa5d81 100644 --- a/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/check/SandboxThirdPartyIdentityCheck.java +++ b/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/check/SandboxThirdPartyIdentityCheck.java @@ -4,7 +4,7 @@ public class SandboxThirdPartyIdentityCheck extends SandboxCheck { - SandboxThirdPartyIdentityCheck(SandboxCheckResult result) { + private SandboxThirdPartyIdentityCheck(SandboxCheckResult result) { super(result); } diff --git a/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/check/SandboxThirdPartyIdentityFraudOneCheck.java b/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/check/SandboxThirdPartyIdentityFraudOneCheck.java index c2499643f..4dddc05f9 100644 --- a/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/check/SandboxThirdPartyIdentityFraudOneCheck.java +++ b/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/check/SandboxThirdPartyIdentityFraudOneCheck.java @@ -4,7 +4,7 @@ public class SandboxThirdPartyIdentityFraudOneCheck extends SandboxCheck { - SandboxThirdPartyIdentityFraudOneCheck(SandboxCheckResult result) { + private SandboxThirdPartyIdentityFraudOneCheck(SandboxCheckResult result) { super(result); } diff --git a/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/check/SandboxWatchlistAdvancedCaCheck.java b/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/check/SandboxWatchlistAdvancedCaCheck.java index 477501c96..5b76cf82a 100644 --- a/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/check/SandboxWatchlistAdvancedCaCheck.java +++ b/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/check/SandboxWatchlistAdvancedCaCheck.java @@ -11,7 +11,7 @@ public class SandboxWatchlistAdvancedCaCheck extends SandboxCheck { @JsonProperty("sources_filter") private final SandboxCaSourcesFilter sourcesFilter; - SandboxWatchlistAdvancedCaCheck(SandboxCheckResult result, SandboxCaSourcesFilter sourcesFilter) { + private SandboxWatchlistAdvancedCaCheck(SandboxCheckResult result, SandboxCaSourcesFilter sourcesFilter) { super(result); this.sourcesFilter = sourcesFilter; } diff --git a/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/check/SandboxWatchlistScreeningCheck.java b/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/check/SandboxWatchlistScreeningCheck.java index 5d17d7be3..1b3792824 100644 --- a/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/check/SandboxWatchlistScreeningCheck.java +++ b/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/check/SandboxWatchlistScreeningCheck.java @@ -4,7 +4,7 @@ public class SandboxWatchlistScreeningCheck extends SandboxCheck { - SandboxWatchlistScreeningCheck(SandboxCheckResult result) { + private SandboxWatchlistScreeningCheck(SandboxCheckResult result) { super(result); } diff --git a/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/check/report/SandboxBreakdown.java b/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/check/report/SandboxBreakdown.java index 6a305134b..068d0bd79 100644 --- a/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/check/report/SandboxBreakdown.java +++ b/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/check/report/SandboxBreakdown.java @@ -18,7 +18,7 @@ public class SandboxBreakdown { @JsonProperty("details") private final List details; - SandboxBreakdown(String subCheck, String result, List details) { + private SandboxBreakdown(String subCheck, String result, List details) { this.subCheck = subCheck; this.result = result; this.details = details; diff --git a/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/check/report/SandboxRecommendation.java b/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/check/report/SandboxRecommendation.java index 7b4a3936c..1f03469ca 100644 --- a/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/check/report/SandboxRecommendation.java +++ b/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/check/report/SandboxRecommendation.java @@ -15,7 +15,7 @@ public class SandboxRecommendation { @JsonProperty("recovery_suggestion") private final String recoverySuggestion; - SandboxRecommendation(String value, String reason, String recoverySuggestion) { + private SandboxRecommendation(String value, String reason, String recoverySuggestion) { this.value = value; this.reason = reason; this.recoverySuggestion = recoverySuggestion; diff --git a/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/task/SandboxDocumentTextDataExtractionTask.java b/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/task/SandboxDocumentTextDataExtractionTask.java index ba58ae883..86c1eb844 100644 --- a/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/task/SandboxDocumentTextDataExtractionTask.java +++ b/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/task/SandboxDocumentTextDataExtractionTask.java @@ -26,7 +26,7 @@ public class SandboxDocumentTextDataExtractionTask { @JsonProperty("result_template") private final String resultTemplate; - SandboxDocumentTextDataExtractionTask(SandboxDocumentTextDataExtractionTaskResult result, + private SandboxDocumentTextDataExtractionTask(SandboxDocumentTextDataExtractionTaskResult result, SandboxDocumentFilter documentFilter, Integer responseDelay, String resultTemplate) { diff --git a/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/task/SandboxSupplementaryDocTextDataExtractionTask.java b/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/task/SandboxSupplementaryDocTextDataExtractionTask.java index ff0f7a866..2d2260f94 100644 --- a/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/task/SandboxSupplementaryDocTextDataExtractionTask.java +++ b/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/task/SandboxSupplementaryDocTextDataExtractionTask.java @@ -25,7 +25,7 @@ public class SandboxSupplementaryDocTextDataExtractionTask { @JsonProperty("result_template") private final String resultTemplate; - SandboxSupplementaryDocTextDataExtractionTask(SandboxSupplementaryDocTextDataExtractionTaskResult result, + private SandboxSupplementaryDocTextDataExtractionTask(SandboxSupplementaryDocTextDataExtractionTaskResult result, SandboxDocumentFilter documentFilter, Integer responseDelay, String resultTemplate) { diff --git a/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/task/SandboxTextExtractionTaskReason.java b/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/task/SandboxTextExtractionTaskReason.java index 505b70968..0d98c78d2 100644 --- a/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/task/SandboxTextExtractionTaskReason.java +++ b/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/task/SandboxTextExtractionTaskReason.java @@ -14,7 +14,7 @@ public class SandboxTextExtractionTaskReason { @JsonProperty("detail") private final String detail; - SandboxTextExtractionTaskReason(String value, String detail) { + private SandboxTextExtractionTaskReason(String value, String detail) { this.value = value; this.detail = detail; } diff --git a/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/task/SandboxTextExtractionTaskRecommendation.java b/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/task/SandboxTextExtractionTaskRecommendation.java index c78a89e43..c9019498a 100644 --- a/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/task/SandboxTextExtractionTaskRecommendation.java +++ b/yoti-sdk-sandbox/src/main/java/com/yoti/api/client/sandbox/docs/request/task/SandboxTextExtractionTaskRecommendation.java @@ -14,7 +14,7 @@ public class SandboxTextExtractionTaskRecommendation { @JsonProperty("reason") private final SandboxTextExtractionTaskReason reason; - SandboxTextExtractionTaskRecommendation(String value, SandboxTextExtractionTaskReason reason) { + private SandboxTextExtractionTaskRecommendation(String value, SandboxTextExtractionTaskReason reason) { this.value = value; this.reason = reason; } diff --git a/yoti-sdk-sandbox/src/test/java/com/yoti/api/client/sandbox/YotiSandboxClientTest.java b/yoti-sdk-sandbox/src/test/java/com/yoti/api/client/sandbox/YotiSandboxClientTest.java index 828213aac..a4a9ebda2 100644 --- a/yoti-sdk-sandbox/src/test/java/com/yoti/api/client/sandbox/YotiSandboxClientTest.java +++ b/yoti-sdk-sandbox/src/test/java/com/yoti/api/client/sandbox/YotiSandboxClientTest.java @@ -1,28 +1,16 @@ package com.yoti.api.client.sandbox; -import static com.yoti.api.client.sandbox.YotiSandboxClient.YOTI_SANDBOX_PATH_PREFIX; -import static com.yoti.api.client.spi.remote.call.HttpMethod.HTTP_POST; -import static com.yoti.api.client.spi.remote.call.YotiConstants.DIGEST_HEADER; -import static com.yoti.api.client.spi.remote.call.YotiConstants.JAVA; -import static com.yoti.api.client.spi.remote.call.YotiConstants.SDK_VERSION; -import static com.yoti.api.client.spi.remote.call.YotiConstants.YOTI_SDK_HEADER; -import static com.yoti.api.client.spi.remote.call.YotiConstants.YOTI_SDK_VERSION_HEADER; - import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import static org.mockito.Answers.RETURNS_DEEP_STUBS; import static org.mockito.Answers.RETURNS_SELF; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -import java.net.URL; -import java.security.GeneralSecurityException; import java.security.KeyPair; -import java.util.Map; import com.yoti.api.client.KeyPairSource; import com.yoti.api.client.sandbox.profile.request.YotiTokenRequest; @@ -30,19 +18,15 @@ import com.yoti.api.client.spi.remote.KeyStreamVisitor; import com.yoti.api.client.spi.remote.call.ResourceException; import com.yoti.api.client.spi.remote.call.ResourceFetcher; -import com.yoti.api.client.spi.remote.call.SignedRequest; -import com.yoti.api.client.spi.remote.call.SignedRequestBuilder; -import com.yoti.api.client.spi.remote.call.SignedRequestBuilderFactory; -import com.yoti.api.client.spi.remote.call.UrlConnector; -import com.yoti.api.client.spi.remote.call.factory.SignedMessageFactory; +import com.yoti.api.client.spi.remote.call.YotiHttpRequest; +import com.yoti.api.client.spi.remote.call.YotiHttpRequestBuilder; +import com.yoti.api.client.spi.remote.call.YotiHttpRequestBuilderFactory; import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.ObjectMapper; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; -import org.mockito.ArgumentCaptor; -import org.mockito.Captor; import org.mockito.Mock; import org.mockito.junit.MockitoJUnitRunner; @@ -63,18 +47,18 @@ public class YotiSandboxClientTest { @Mock KeyPairSource keyPairSourceMock; @Mock(answer = RETURNS_DEEP_STUBS) KeyPair keyPairMock; - @Mock SignedRequestBuilderFactory signedRequestBuilderFactoryMock; - @Mock(answer = RETURNS_SELF) SignedRequestBuilder signedRequestBuilderMock; - @Mock SignedRequest signedRequestMock; + @Mock YotiHttpRequestBuilderFactory yotiHttpRequestBuilderFactoryMock; + @Mock(answer = RETURNS_SELF) YotiHttpRequestBuilder yotiHttpRequestBuilderMock; + @Mock YotiHttpRequest yotiHttpRequestMock; @Mock YotiTokenRequest yotiTokenRequestMock; @Mock YotiTokenResponse yotiTokenResponseMock; @Before public void setUp() throws Exception { - when(signedRequestBuilderFactoryMock.create()).thenReturn(signedRequestBuilderMock); - when(signedRequestBuilderMock.build()).thenReturn(signedRequestMock); - testObj = new YotiSandboxClient(SOME_APP_ID, keyPairMock, sandboxPathFactoryMock, objectMapperMock, resourceFetcherMock, signedRequestBuilderFactoryMock); + when(yotiHttpRequestBuilderFactoryMock.create()).thenReturn(yotiHttpRequestBuilderMock); + when(yotiHttpRequestBuilderMock.build()).thenReturn(yotiHttpRequestMock); + testObj = new YotiSandboxClient(SOME_APP_ID, keyPairMock, sandboxPathFactoryMock, objectMapperMock, resourceFetcherMock, yotiHttpRequestBuilderFactoryMock); } @Test @@ -130,7 +114,7 @@ public void setupSharingProfile_shouldWrapIOException() throws Exception { public void setupSharingProfile_shouldWrapResourceException() throws Exception { ResourceException resourceException = new ResourceException(401, null, null); when(objectMapperMock.writeValueAsBytes(yotiTokenRequestMock)).thenReturn(BODY_BYTES); - when(resourceFetcherMock.doRequest(signedRequestMock, YotiTokenResponse.class)).thenThrow(resourceException); + when(resourceFetcherMock.doRequest(yotiHttpRequestMock, YotiTokenResponse.class)).thenThrow(resourceException); try { testObj.setupSharingProfile(yotiTokenRequestMock); @@ -146,12 +130,12 @@ public void setupSharingProfile_shouldWrapResourceException() throws Exception { public void setupSharingProfile_shouldReturnTokenFromSandbox() throws Exception { when(sandboxPathFactoryMock.createSandboxPath(SOME_APP_ID)).thenReturn(SOME_PATH); when(objectMapperMock.writeValueAsBytes(yotiTokenRequestMock)).thenReturn(BODY_BYTES); - when(resourceFetcherMock.doRequest(signedRequestMock, YotiTokenResponse.class)).thenReturn(yotiTokenResponseMock); + when(resourceFetcherMock.doRequest(yotiHttpRequestMock, YotiTokenResponse.class)).thenReturn(yotiTokenResponseMock); when(yotiTokenResponseMock.getToken()).thenReturn(SOME_TOKEN); String result = testObj.setupSharingProfile(yotiTokenRequestMock); - verify(resourceFetcherMock).doRequest(signedRequestMock, YotiTokenResponse.class); + verify(resourceFetcherMock).doRequest(yotiHttpRequestMock, YotiTokenResponse.class); assertEquals(SOME_TOKEN, result); } diff --git a/yoti-sdk-sandbox/src/test/java/com/yoti/api/client/sandbox/docs/DocScanSandboxClientTest.java b/yoti-sdk-sandbox/src/test/java/com/yoti/api/client/sandbox/docs/DocScanSandboxClientTest.java index 3c6b94b85..b6e4b4583 100644 --- a/yoti-sdk-sandbox/src/test/java/com/yoti/api/client/sandbox/docs/DocScanSandboxClientTest.java +++ b/yoti-sdk-sandbox/src/test/java/com/yoti/api/client/sandbox/docs/DocScanSandboxClientTest.java @@ -3,9 +3,10 @@ import static com.yoti.api.client.spi.remote.call.YotiConstants.PROPERTY_YOTI_DOCS_URL; import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.*; -import static org.junit.Assert.fail; -import static org.mockito.Mockito.*; +import static org.hamcrest.Matchers.containsString; +import static org.junit.Assert.assertThrows; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; import java.io.IOException; import java.security.KeyPair; @@ -14,15 +15,19 @@ import com.yoti.api.client.sandbox.docs.request.ResponseConfig; import com.yoti.api.client.sandbox.util.FieldSetter; import com.yoti.api.client.spi.remote.call.ResourceException; -import com.yoti.api.client.spi.remote.call.SignedRequest; -import com.yoti.api.client.spi.remote.call.SignedRequestBuilder; -import com.yoti.api.client.spi.remote.call.SignedRequestBuilderFactory; +import com.yoti.api.client.spi.remote.call.YotiHttpRequest; +import com.yoti.api.client.spi.remote.call.YotiHttpRequestBuilder; +import com.yoti.api.client.spi.remote.call.YotiHttpRequestBuilderFactory; +import com.yoti.api.client.spi.remote.call.factory.DocsSignedRequestStrategy; import com.fasterxml.jackson.databind.ObjectMapper; -import org.junit.*; +import org.junit.Before; +import org.junit.Test; import org.junit.runner.RunWith; -import org.mockito.*; -import org.mockito.junit.*; +import org.mockito.Answers; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnitRunner; @RunWith(MockitoJUnitRunner.class) public class DocScanSandboxClientTest { @@ -32,80 +37,72 @@ public class DocScanSandboxClientTest { private static final String SOME_SDK_ID = "someSdkId"; private static final String SOME_SESSION_ID = "someSessionId"; - @Mock SignedRequestBuilderFactory signedRequestBuilderFactory; - @Mock(answer = Answers.RETURNS_SELF) SignedRequestBuilder signedRequestBuilderMock; - @Mock SignedRequest signedRequestMock; - @Mock ResponseConfig responseConfigMock; + @InjectMocks DocScanSandboxClient testObj; + + @Mock YotiHttpRequestBuilderFactory yotiHttpRequestBuilderFactory; @Mock ObjectMapper objectMapperMock; - @Mock KeyPair keyPairMock; + @Mock DocsSignedRequestStrategy authStrategyMock; - @Spy @InjectMocks DocScanSandboxClient docScanSandboxClient; + @Mock(answer = Answers.RETURNS_SELF) YotiHttpRequestBuilder yotiHttpRequestBuilderMock; + @Mock YotiHttpRequest yotiHttpRequestMock; + @Mock ResponseConfig responseConfigMock; + @Mock KeyPair keyPairMock; @Before public void setUp() { - when(signedRequestBuilderFactory.create()).thenReturn(signedRequestBuilderMock); + when(yotiHttpRequestBuilderFactory.create()).thenReturn(yotiHttpRequestBuilderMock); } @Test public void configureSessionResponse_shouldWrapIoException() throws Exception { IOException ioException = new IOException("Some error"); - when(objectMapperMock.writeValueAsBytes(responseConfigMock)).thenReturn(SOME_BYTES); - when(signedRequestMock.execute()).thenThrow(ioException); - when(signedRequestBuilderMock.build()).thenReturn(signedRequestMock); - - try { - docScanSandboxClient.configureSessionResponse(SOME_SESSION_ID, responseConfigMock); - } catch (SandboxException ex) { - assertThat(ex.getMessage(), containsString("Some error")); - return; - } - fail("Expected an exception"); + when(yotiHttpRequestBuilderMock.build()).thenReturn(yotiHttpRequestMock); + when(yotiHttpRequestMock.execute()).thenThrow(ioException); + + SandboxException thrown = assertThrows(SandboxException.class, () -> testObj.configureSessionResponse(SOME_SESSION_ID, responseConfigMock)); + + assertThat(thrown.getMessage(), containsString("Some error")); } @Test public void configureSessionResponse_shouldWrapResourceException() throws Exception { ResourceException resourceException = new ResourceException(400, "Some error", "There was some error"); - when(objectMapperMock.writeValueAsBytes(responseConfigMock)).thenReturn(SOME_BYTES); - when(signedRequestMock.execute()).thenThrow(resourceException); - when(signedRequestBuilderMock.build()).thenReturn(signedRequestMock); - - try { - docScanSandboxClient.configureSessionResponse(SOME_SESSION_ID, responseConfigMock); - } catch (SandboxException ex) { - assertThat(ex.getMessage(), containsString("Some error")); - return; - } - fail("Expected an exception"); + when(yotiHttpRequestBuilderMock.build()).thenReturn(yotiHttpRequestMock); + when(yotiHttpRequestMock.execute()).thenThrow(resourceException); + + SandboxException thrown = assertThrows(SandboxException.class, () -> testObj.configureSessionResponse(SOME_SESSION_ID, responseConfigMock)); + + assertThat(thrown.getMessage(), containsString("Some error")); } @Test public void configureSessionResponse_shouldCallSignedRequestBuilderWithCorrectValues() throws Exception { when(objectMapperMock.writeValueAsBytes(responseConfigMock)).thenReturn(SOME_BYTES); - when(signedRequestBuilderMock.build()).thenReturn(signedRequestMock); + when(yotiHttpRequestBuilderMock.build()).thenReturn(yotiHttpRequestMock); - docScanSandboxClient.configureSessionResponse(SOME_SESSION_ID, responseConfigMock); + testObj.configureSessionResponse(SOME_SESSION_ID, responseConfigMock); - verify(signedRequestBuilderMock).withBaseUrl(SOME_API_URL); - verify(signedRequestBuilderMock).withKeyPair(keyPairMock); - verify(signedRequestBuilderMock).withEndpoint("/sessions/" + SOME_SESSION_ID + "/response-config"); - verify(signedRequestBuilderMock).withPayload(SOME_BYTES); + verify(yotiHttpRequestBuilderMock).withBaseUrl(SOME_API_URL); + verify(yotiHttpRequestBuilderMock).withAuthStrategy(authStrategyMock); + verify(yotiHttpRequestBuilderMock).withEndpoint("/sessions/" + SOME_SESSION_ID + "/response-config"); + verify(yotiHttpRequestBuilderMock).withPayload(SOME_BYTES); } @Test public void configureApplicationResponse_shouldCallSignedRequestBuilderWithCorrectValues() throws Exception { when(objectMapperMock.writeValueAsBytes(responseConfigMock)).thenReturn(SOME_BYTES); - when(signedRequestBuilderMock.build()).thenReturn(signedRequestMock); + when(yotiHttpRequestBuilderMock.build()).thenReturn(yotiHttpRequestMock); - FieldSetter.setField(docScanSandboxClient, "sdkId", SOME_SDK_ID); + FieldSetter.setField(testObj, "sdkId", SOME_SDK_ID); - docScanSandboxClient.configureApplicationResponse(responseConfigMock); + testObj.configureApplicationResponse(responseConfigMock); - verify(signedRequestBuilderMock).withBaseUrl(SOME_API_URL); - verify(signedRequestBuilderMock).withKeyPair(keyPairMock); - verify(signedRequestBuilderMock).withEndpoint("/apps/" + SOME_SDK_ID + "/response-config"); - verify(signedRequestBuilderMock).withPayload(SOME_BYTES); + verify(yotiHttpRequestBuilderMock).withBaseUrl(SOME_API_URL); + verify(yotiHttpRequestBuilderMock).withAuthStrategy(authStrategyMock); + verify(yotiHttpRequestBuilderMock).withEndpoint("/apps/" + SOME_SDK_ID + "/response-config"); + verify(yotiHttpRequestBuilderMock).withPayload(SOME_BYTES); } } diff --git a/yoti-sdk-spring-boot-auto-config/README.md b/yoti-sdk-spring-boot-auto-config/README.md index 0c84a94cb..05b54ef90 100644 --- a/yoti-sdk-spring-boot-auto-config/README.md +++ b/yoti-sdk-spring-boot-auto-config/README.md @@ -18,7 +18,7 @@ If you are using Maven, you need to add the following dependencies: com.yoti yoti-sdk-spring-boot-auto-config - 3.12.0 + 4.0.0 ``` @@ -26,7 +26,7 @@ If you are using Maven, you need to add the following dependencies: If you are using Gradle, here is the dependency to add: ``` -compile group: 'com.yoti', name: 'yoti-sdk-spring-boot-auto-config', version: '3.12.0' +compile group: 'com.yoti', name: 'yoti-sdk-spring-boot-auto-config', version: '4.0.0' ``` diff --git a/yoti-sdk-spring-boot-auto-config/pom.xml b/yoti-sdk-spring-boot-auto-config/pom.xml index d690e2dfa..548a78a0a 100644 --- a/yoti-sdk-spring-boot-auto-config/pom.xml +++ b/yoti-sdk-spring-boot-auto-config/pom.xml @@ -12,7 +12,7 @@ com.yoti yoti-sdk-parent - 3.12.0 + 4.0.0 ../yoti-sdk-parent diff --git a/yoti-sdk-spring-boot-example/README.md b/yoti-sdk-spring-boot-example/README.md index 0693a3b71..fc2aeb960 100644 --- a/yoti-sdk-spring-boot-example/README.md +++ b/yoti-sdk-spring-boot-example/README.md @@ -17,7 +17,7 @@ Note that: com.yoti yoti-sdk-api - 3.12.0 + 4.0.0 ``` diff --git a/yoti-sdk-spring-boot-example/pom.xml b/yoti-sdk-spring-boot-example/pom.xml index b2f632c91..883ed5b47 100644 --- a/yoti-sdk-spring-boot-example/pom.xml +++ b/yoti-sdk-spring-boot-example/pom.xml @@ -6,7 +6,7 @@ com.yoti yoti-sdk-spring-boot-example Yoti Spring Boot Example - 3.12.0 + 4.0.0 org.springframework.boot diff --git a/yoti-sdk-spring-security/README.md b/yoti-sdk-spring-security/README.md index d401f9090..7b5ccf7ab 100644 --- a/yoti-sdk-spring-security/README.md +++ b/yoti-sdk-spring-security/README.md @@ -25,14 +25,14 @@ If you are using Maven, you need to add the following dependencies: com.yoti yoti-sdk-spring-security - 3.12.0 + 4.0.0 ``` If you are using Gradle, here is the dependency to add: ``` -compile group: 'com.yoti', name: 'yoti-sdk-spring-security', version: '3.12.0' +compile group: 'com.yoti', name: 'yoti-sdk-spring-security', version: '4.0.0' ``` ### Provide a `YotiClient` instance diff --git a/yoti-sdk-spring-security/pom.xml b/yoti-sdk-spring-security/pom.xml index 2fc710f33..9eb70f490 100644 --- a/yoti-sdk-spring-security/pom.xml +++ b/yoti-sdk-spring-security/pom.xml @@ -12,7 +12,7 @@ com.yoti yoti-sdk-parent - 3.12.0 + 4.0.0 ../yoti-sdk-parent