diff --git a/api-test/src/main/java/io/mosip/testrig/apirig/auth/testrunner/MosipTestRunner.java b/api-test/src/main/java/io/mosip/testrig/apirig/auth/testrunner/MosipTestRunner.java index e4b1ce0428..f836240a23 100644 --- a/api-test/src/main/java/io/mosip/testrig/apirig/auth/testrunner/MosipTestRunner.java +++ b/api-test/src/main/java/io/mosip/testrig/apirig/auth/testrunner/MosipTestRunner.java @@ -110,6 +110,13 @@ public static void main(String[] arg) { String partnerKeyURL = ""; String updatedPartnerKeyURL = ""; String ekycPartnerKeyURL = ""; + String policyTokenPartnerKeyURL = ""; + String policyToken2PartnerKeyURL = ""; + String policyToken3PartnerKeyURL = ""; + String partnerToken2KeyURL = ""; + String randomTokenPartnerKeyURL = ""; + String randomToken2PartnerKeyURL = ""; + String randomToken3PartnerKeyURL = ""; PartnerRegistration.deleteCertificates(); CertificateGenerationUtil.getThumbprints(); @@ -118,6 +125,31 @@ public static void main(String[] arg) { partnerKeyURL = PartnerRegistration.generateAndGetPartnerKeyUrl(); updatedPartnerKeyURL = PartnerRegistration.generateAndGetUpdatedPartnerKeyUrl(); + IdAuthenticationUtil.createAndPublishPolicyWithPolicyTokenType(); + policyTokenPartnerKeyURL = IdAuthenticationUtil.generateAndGetPolicyTokenPartnerKeyUrl(); + LOGGER.info("policyTokenPartnerKeyURL generated"); + + IdAuthenticationUtil.registerSecondPolicyTokenPartner(); + policyToken2PartnerKeyURL = IdAuthenticationUtil.generateAndGetSecondPolicyTokenPartnerKeyUrl(); + LOGGER.info("policyToken2PartnerKeyURL generated"); + + partnerToken2KeyURL = IdAuthenticationUtil.generateAndGetPartnerToken2KeyUrl(); + LOGGER.info("partnerToken2KeyURL generated"); + + IdAuthenticationUtil.registerThirdPolicyTokenPartner(); + policyToken3PartnerKeyURL = IdAuthenticationUtil.generateAndGetThirdPolicyTokenPartnerKeyUrl(); + LOGGER.info("policyToken3PartnerKeyURL generated"); + + IdAuthenticationUtil.createAndPublishPolicyWithRandomTokenType(); + randomTokenPartnerKeyURL = IdAuthenticationUtil.generateAndGetRandomTokenPartnerKeyUrl(); + LOGGER.info("randomTokenPartnerKeyURL generated"); + + randomToken2PartnerKeyURL = IdAuthenticationUtil.generateAndGetRandomToken2PartnerKeyUrl(); + LOGGER.info("randomToken2PartnerKeyURL generated"); + + randomToken3PartnerKeyURL = IdAuthenticationUtil.generateAndGetRandomToken3PartnerKeyUrl(); + LOGGER.info("randomToken3PartnerKeyURL generated"); + AdminTestUtil.createAndPublishPolicyForKyc(); ekycPartnerKeyURL = PartnerRegistration.generateAndGetEkycPartnerKeyUrl(); diff --git a/api-test/src/main/java/io/mosip/testrig/apirig/auth/testscripts/DemoAuth.java b/api-test/src/main/java/io/mosip/testrig/apirig/auth/testscripts/DemoAuth.java index e2b7e57131..75247e7c42 100644 --- a/api-test/src/main/java/io/mosip/testrig/apirig/auth/testscripts/DemoAuth.java +++ b/api-test/src/main/java/io/mosip/testrig/apirig/auth/testscripts/DemoAuth.java @@ -1,6 +1,7 @@ package io.mosip.testrig.apirig.auth.testscripts; +import java.util.HashMap; import java.util.List; import java.util.Map; @@ -100,12 +101,45 @@ public void test(TestCaseDTO testCaseDTO) throws AuthenticationTestException, Ad testCaseDTO.setEndPoint(testCaseDTO.getEndPoint().replace("$UpdatedPartnerKeyURL$", PartnerRegistration.updatedpartnerKeyUrl)); } + if (testCaseDTO.getEndPoint().contains("$PolicyTokenPartnerKeyURL$")) { + testCaseDTO.setEndPoint(testCaseDTO.getEndPoint().replace("$PolicyTokenPartnerKeyURL$", + policyTokenPartnerKeyUrl)); + } + if (testCaseDTO.getEndPoint().contains("$PolicyToken2PartnerKeyURL$")) { + testCaseDTO.setEndPoint(testCaseDTO.getEndPoint().replace("$PolicyToken2PartnerKeyURL$", + policyToken2PartnerKeyUrl)); + } + if (testCaseDTO.getEndPoint().contains("$PolicyToken3PartnerKeyURL$")) { + testCaseDTO.setEndPoint(testCaseDTO.getEndPoint().replace("$PolicyToken3PartnerKeyURL$", + policyToken3PartnerKeyUrl)); + } + if (testCaseDTO.getEndPoint().contains("$PartnerToken2KeyURL$")) { + testCaseDTO.setEndPoint(testCaseDTO.getEndPoint().replace("$PartnerToken2KeyURL$", + partnerToken2KeyUrl)); + } + if (testCaseDTO.getEndPoint().contains("$RandomTokenPartnerKeyURL$")) { + testCaseDTO.setEndPoint(testCaseDTO.getEndPoint().replace("$RandomTokenPartnerKeyURL$", + randomTokenPartnerKeyUrl)); + } + if (testCaseDTO.getEndPoint().contains("$RandomToken2PartnerKeyURL$")) { + testCaseDTO.setEndPoint(testCaseDTO.getEndPoint().replace("$RandomToken2PartnerKeyURL$", + randomToken2PartnerKeyUrl)); + } + if (testCaseDTO.getEndPoint().contains("$RandomToken3PartnerKeyURL$")) { + testCaseDTO.setEndPoint(testCaseDTO.getEndPoint().replace("$RandomToken3PartnerKeyURL$", + randomToken3PartnerKeyUrl)); + } JSONObject request = new JSONObject(testCaseDTO.getInput()); - String identityRequest = null, identityRequestTemplate = null; + String identityRequest = null, identityRequestTemplate = null; if(request.has("identityRequest")) { identityRequest = request.get("identityRequest").toString(); request.remove("identityRequest"); } + String invalidThumbprint = null; + if (request.has("invalidThumbprint")) { + invalidThumbprint = request.getString("invalidThumbprint"); + request.remove("invalidThumbprint"); + } if (identityRequest.contains("$PRIMARYLANG$")) identityRequest = identityRequest.replace("$PRIMARYLANG$", BaseTestCase.languageList.get(0)); @@ -135,6 +169,10 @@ public void test(TestCaseDTO testCaseDTO) throws AuthenticationTestException, Ad identityRequest = inputJsonKeyWordHandeler(identityRequest, testCaseName); identityRequest = JsonPrecondtion.parseAndReturnJsonContent(identityRequest, generateCurrentUTCTimeStamp(), "timestamp"); Map demoAuthTempMap = encryptDecryptUtil.getEncryptSessionKeyValue(identityRequest); + if (invalidThumbprint != null) { + demoAuthTempMap = new HashMap<>(demoAuthTempMap); + demoAuthTempMap.put("thumbprint", invalidThumbprint); + } String authRequest = getJsonFromTemplate(request.toString(), testCaseDTO.getInputTemplate()); logger.info("************* Modification of demo auth request ******************"); Reporter.log("Modification of demo auth request"); @@ -168,8 +206,12 @@ public void test(TestCaseDTO testCaseDTO) throws AuthenticationTestException, Ad writeAutoGeneratedId(response, idKeyName, testCaseName); } + String expectedOutput = testCaseDTO.getOutput(); + if (expectedOutput.contains("$ID:")) { + expectedOutput = inputJsonKeyWordHandeler(expectedOutput, testCaseName); + } Map> ouputValid = OutputValidationUtil - .doJsonOutputValidation(response.asString(), getJsonFromTemplate(testCaseDTO.getOutput(), testCaseDTO.getOutputTemplate())); + .doJsonOutputValidation(response.asString(), getJsonFromTemplate(expectedOutput, testCaseDTO.getOutputTemplate())); Reporter.log(ReportUtil.getOutputValidationReport(ouputValid)); if (!OutputValidationUtil.publishOutputResult(ouputValid)) diff --git a/api-test/src/main/java/io/mosip/testrig/apirig/auth/utils/IdAuthenticationUtil.java b/api-test/src/main/java/io/mosip/testrig/apirig/auth/utils/IdAuthenticationUtil.java index 87c0dc4eee..d60d2596c3 100644 --- a/api-test/src/main/java/io/mosip/testrig/apirig/auth/utils/IdAuthenticationUtil.java +++ b/api-test/src/main/java/io/mosip/testrig/apirig/auth/utils/IdAuthenticationUtil.java @@ -1,11 +1,16 @@ package io.mosip.testrig.apirig.auth.utils; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; + +import javax.ws.rs.core.MediaType; import org.apache.log4j.Level; import org.apache.log4j.Logger; import org.json.JSONArray; +import org.json.JSONObject; import org.testng.SkipException; import io.mosip.testrig.apirig.auth.testrunner.MosipTestRunner; @@ -16,9 +21,12 @@ import io.mosip.testrig.apirig.utils.ConfigManager; import io.mosip.testrig.apirig.utils.GlobalConstants; import io.mosip.testrig.apirig.utils.JWKKeyUtil; +import io.mosip.testrig.apirig.utils.KeyCloakUserAndAPIKeyGeneration; import io.mosip.testrig.apirig.utils.KeycloakUserManager; import io.mosip.testrig.apirig.utils.PartnerRegistration; +import io.mosip.testrig.apirig.utils.RestClient; import io.mosip.testrig.apirig.utils.SkipTestCaseHandler; +import io.restassured.response.Response; public class IdAuthenticationUtil extends AdminTestUtil { @@ -190,5 +198,319 @@ public static String replaceKeywordValue(String jsonString, String keyword, Stri } } - + + /** + * Fails fast with a SkipException when a setup REST call did not succeed, + * instead of letting the caller hit an opaque JSONException while parsing + * an error response, or silently continuing with an invalid/empty token. + */ + private static void assertSuccessStatusCode(Response response, String failureMessage) { + if (response == null) { + throw new SkipException(failureMessage + ": null response"); + } + int statusCode = response.getStatusCode(); + if (statusCode < 200 || statusCode >= 300) { + throw new SkipException(failureMessage + ": HTTP " + statusCode + " - " + response.asString()); + } + } + + /** + * Creates and publishes an additional auth policy (under the same policy + * group as the main auth partner) using the given allowed-auth-types + * attributes file (which determines, among other things, the authTokenType + * of the policy), and returns the created policy id. + */ + @SuppressWarnings("unchecked") + private static String createAndPublishPolicy(String policyNameToCreate, String attrFilePath) { + String token = kernelAuthLib.getTokenByRole(GlobalConstants.PARTNER); + + String url = ApplnURI + properties.getProperty("authPolicyUrl"); + org.json.simple.JSONObject actualrequestBody = getRequestJson(AUTH_POLICY_BODY); + org.json.simple.JSONObject actualrequest2 = getRequestJson(AUTH_POLICY_REQUEST); + org.json.simple.JSONObject actualrequestAttr = getRequestJson(attrFilePath); + + actualrequest2.put("name", policyNameToCreate); + actualrequest2.put("policyGroupName", PartnerRegistration.policyGroup); + actualrequest2.put("policies", actualrequestAttr); + actualrequestBody.put(GlobalConstants.REQUEST, actualrequest2); + actualrequestBody.put(GlobalConstants.REQUESTTIME, generateCurrentUTCTimeStamp()); + + Response response = RestClient.postRequestWithCookie(url, actualrequestBody, MediaType.APPLICATION_JSON, + MediaType.APPLICATION_JSON, GlobalConstants.AUTHORIZATION, token); + assertSuccessStatusCode(response, "Failed to create auth policy"); + String responseBody = response.getBody().asString(); + String createdPolicyId = new JSONObject(responseBody).getJSONObject(GlobalConstants.RESPONSE) + .getString("id"); + + String publishPolicyURL = ApplnURI + properties.getProperty("publishPolicyurl"); + if (publishPolicyURL.contains("POLICYID")) { + publishPolicyURL = publishPolicyURL.replace("POLICYID", createdPolicyId); + publishPolicyURL = publishPolicyURL.replace("POLICYGROUPID", policygroupId); + } + + Response publishResponse = RestClient.postRequestWithCookie(publishPolicyURL, MediaType.APPLICATION_JSON, + MediaType.APPLICATION_JSON, GlobalConstants.AUTHORIZATION, token); + assertSuccessStatusCode(publishResponse, "Failed to publish auth policy"); + + return createdPolicyId; + } + + /** + * Logs in as the given partner (PMS internal userid/password auth, the same + * way {@code KernelAuthentication.getAuthForNewPartner()} logs in as the main + * partner) and returns the auth token. Generating an API key is a partner + * self-service action in PMS - it has to be done as that partner's own + * Keycloak user, not via a generic admin/role token, otherwise PMS rejects + * it with "User not authorized" (PMS_PRT_055). + */ + private static String loginAsPartner(String partnerId) { + Map kernelProps = AdminTestUtil.readProperty("Kernel"); + String authenticationInternalEndpoint = kernelProps.get("authenticationInternal"); + + org.json.simple.JSONObject actualrequest = getRequestJson("config/Authorization/internalAuthRequest.json"); + org.json.simple.JSONObject request = new org.json.simple.JSONObject(); + request.put(GlobalConstants.APPID, ConfigManager.getPmsAppId()); + request.put(GlobalConstants.PASSWORD, GlobalConstants.MOSIP123); + request.put(GlobalConstants.USER_NAME, partnerId); + request.put(GlobalConstants.CLIENTID, ConfigManager.getPmsClientId()); + request.put(GlobalConstants.CLIENTSECRET, ConfigManager.getPmsClientSecret()); + actualrequest.put(GlobalConstants.REQUEST, request); + + Response response = AdminTestUtil.postWithJson(authenticationInternalEndpoint, actualrequest); + assertSuccessStatusCode(response, "Failed to fetch admin token for partner " + partnerId); + return new JSONObject(response.getBody().asString()).getJSONObject(GlobalConstants.RESPONSE) + .getString(GlobalConstants.TOKEN); + } + + /** + * Maps the given partner to the given policy, approves that mapping, and + * generates the resulting API key. {@code submitPartnerAndGetMappingKey} + * alone only returns a mapping key (not an API key) for an unapproved + * mapping; using it as-is in a partner key URL is why IDA used to reject + * these calls with "Partner is not registered" (IDA-MPA-009) - the mapping + * was never approved and no API key was ever generated for it. + */ + private static String mapPartnerToPolicyAndGenerateApiKey(String partnerId, String policyNameToUse) { + KeycloakUserManager.createKeyCloakUsers(partnerId, partnerId + "@mosip.net", PartnerRegistration.partnerType); + + String mappingKey = KeyCloakUserAndAPIKeyGeneration.submitPartnerAndGetMappingKey(partnerId, policyNameToUse); + KeyCloakUserAndAPIKeyGeneration.approvePartnerAPIKey(mappingKey); + + String url = ApplnURI + "/v1/partnermanager/partners/" + partnerId + "/generate/apikey"; + String token = loginAsPartner(partnerId); + + HashMap requestBody = new HashMap<>(); + requestBody.put("policyName", policyNameToUse); + requestBody.put("label", generateRandomAlphabeticString(4).toUpperCase()); + + HashMap body = new HashMap<>(); + body.put("id", GlobalConstants.STRING); + body.put(GlobalConstants.METADATA, new HashMap<>()); + body.put(GlobalConstants.REQUEST, requestBody); + body.put(GlobalConstants.REQUESTTIME, generateCurrentUTCTimeStamp()); + body.put(GlobalConstants.VERSION, GlobalConstants.STRING); + + Response response = RestClient.patchRequestWithCookie(url, body, MediaType.APPLICATION_JSON, + MediaType.APPLICATION_JSON, GlobalConstants.AUTHORIZATION, token); + assertSuccessStatusCode(response, "Failed to generate API key for partner " + partnerId); + JSONObject responseValue = new JSONObject(response.asString()).getJSONObject(GlobalConstants.RESPONSE); + + return responseValue.getString(GlobalConstants.APIKEY); + } + + private static final String AUTH_POLICY_FOR_POLICY_TOKEN_REQUEST_ATTR = "config/AuthPolicyForPolicyTokenAllowedAuthTypes.json"; + private static final String policyNameForPolicyToken = "mosip auth policy for policy token " + + BaseTestCase.runContext + System.currentTimeMillis(); + public static String policyIdForPolicyToken = ""; + public static String policyTokenPartnerKeyUrl = ""; + + /** + * Creates and publishes a second auth policy (under the same policy group as + * the main auth partner) whose authTokenType is "policy", so that the + * generated authToken is derived from the policy id and the UIN rather than + * the partner id. + */ + public static void createAndPublishPolicyWithPolicyTokenType() { + policyIdForPolicyToken = createAndPublishPolicy(policyNameForPolicyToken, + AUTH_POLICY_FOR_POLICY_TOKEN_REQUEST_ATTR); + } + + /** + * Maps the existing auth partner to the policy-token policy (created via + * {@link #createAndPublishPolicyWithPolicyTokenType()}) and builds the + * partner key URL that exercises that mapping. + */ + public static String generateAndGetPolicyTokenPartnerKeyUrl() { + String policyTokenApiKey = mapPartnerToPolicyAndGenerateApiKey(PartnerRegistration.partnerId, + policyNameForPolicyToken); + policyTokenPartnerKeyUrl = PartnerRegistration.mispLicKey + "/" + PartnerRegistration.partnerId + "/" + + policyTokenApiKey; + return policyTokenPartnerKeyUrl; + } + + private static final String AUTH_POLICY_FOR_RANDOM_TOKEN_REQUEST_ATTR = "config/AuthPolicyForRandomTokenAllowedAuthTypes.json"; + private static final String policyNameForRandomToken = "mosip auth policy for random token " + + BaseTestCase.runContext + System.currentTimeMillis(); + public static String policyIdForRandomToken = ""; + public static String randomTokenPartnerKeyUrl = ""; + + /** + * Creates and publishes a third auth policy (under the same policy group as + * the main auth partner) whose authTokenType is "random", so that a new, + * unrelated authToken is generated on every authentication call regardless + * of the UIN or partner. + */ + public static void createAndPublishPolicyWithRandomTokenType() { + policyIdForRandomToken = createAndPublishPolicy(policyNameForRandomToken, + AUTH_POLICY_FOR_RANDOM_TOKEN_REQUEST_ATTR); + } + + /** + * Maps the existing auth partner to the random-token policy (created via + * {@link #createAndPublishPolicyWithRandomTokenType()}) and builds the + * partner key URL that exercises that mapping. + */ + public static String generateAndGetRandomTokenPartnerKeyUrl() { + String randomTokenApiKey = mapPartnerToPolicyAndGenerateApiKey(PartnerRegistration.partnerId, + policyNameForRandomToken); + randomTokenPartnerKeyUrl = PartnerRegistration.mispLicKey + "/" + PartnerRegistration.partnerId + "/" + + randomTokenApiKey; + return randomTokenPartnerKeyUrl; + } + + /** + * Registers an additional, independent auth partner (its own + * certificates/keys) under the same policy group as the main partner, so + * that it can later be mapped to the same policy-token policy as the main + * partner. Used to verify that a "policy" authTokenType token depends only + * on the policy id and the UIN, not on which partner under that policy made + * the call. + */ + private static void registerAdditionalPolicyTokenPartner(String partnerId, String organizationName, + String emailId) { + String url = ApplnURI + properties.getProperty("putPartnerRegistrationUrl"); + String token = kernelAuthLib.getTokenByRole(GlobalConstants.PARTNER); + + HashMap requestBody = new HashMap<>(); + requestBody.put("address", "Bangalore"); + requestBody.put("contactNumber", "8553967572"); + requestBody.put("emailId", emailId); + requestBody.put("organizationName", organizationName); + requestBody.put(GlobalConstants.PARTNERID, partnerId); + requestBody.put("partnerType", PartnerRegistration.partnerType); + requestBody.put("policyGroup", PartnerRegistration.policyGroup); + + HashMap body = new HashMap<>(); + body.put("id", GlobalConstants.STRING); + body.put(GlobalConstants.METADATA, new HashMap<>()); + body.put(GlobalConstants.REQUEST, requestBody); + body.put(GlobalConstants.REQUESTTIME, generateCurrentUTCTimeStamp()); + body.put(GlobalConstants.VERSION, "LTS"); + + Response response = RestClient.postRequestWithCookie(url, body, MediaType.APPLICATION_JSON, + MediaType.APPLICATION_JSON, GlobalConstants.AUTHORIZATION, token); + assertSuccessStatusCode(response, "Failed to register partner " + partnerId); + + JSONObject certificateValue = PartnerRegistration.getCertificates(partnerId, "RELYING_PARTY"); + String caCertValue = certificateValue.getString("caCertificate"); + String interCertValue = certificateValue.getString("interCertificate"); + String partnerCertValue = certificateValue.getString("partnerCertificate"); + + PartnerRegistration.uploadCACertificate(caCertValue, "Auth"); + PartnerRegistration.uploadIntermediateCertificate(interCertValue, "Auth"); + + JSONObject signedcertificateValue = PartnerRegistration.uploadPartnerCertificate(partnerCertValue, "Auth", + partnerId); + String certValueSigned = signedcertificateValue.getString("signedCertificateData"); + + PartnerRegistration.uploadSignedCertificate(certValueSigned, "RELYING_PARTY", partnerId, true); + } + + /** + * Maps the given partner to the given policy and builds its partner key URL + * for that mapping. A partner can be mapped to several different policies + * (each mapping mints its own API key), which is how the same partner + * entity is reused across the policy/partner/random token type tests + * instead of registering a fresh partner for every combination. + */ + private static String mapPartnerToPolicyAndGetKeyUrl(String partnerId, String policyNameToUse) { + String apiKey = mapPartnerToPolicyAndGenerateApiKey(partnerId, policyNameToUse); + return PartnerRegistration.mispLicKey + "/" + partnerId + "/" + apiKey; + } + + private static String mapToPolicyTokenPolicyAndGetKeyUrl(String partnerId) { + return mapPartnerToPolicyAndGetKeyUrl(partnerId, policyNameForPolicyToken); + } + + private static final String policyToken2OrganizationName = BaseTestCase.currentModule + "_policy2_pid"; + public static String policyToken2PartnerId = policyToken2OrganizationName; + private static final String policyToken2EmailId = "mosip_policy2_" + System.currentTimeMillis() + "@gmail.com"; + public static String policyToken2PartnerKeyUrl = ""; + + public static void registerSecondPolicyTokenPartner() { + registerAdditionalPolicyTokenPartner(policyToken2PartnerId, policyToken2OrganizationName, + policyToken2EmailId); + } + + public static String generateAndGetSecondPolicyTokenPartnerKeyUrl() { + policyToken2PartnerKeyUrl = mapToPolicyTokenPolicyAndGetKeyUrl(policyToken2PartnerId); + return policyToken2PartnerKeyUrl; + } + + private static final String policyToken3OrganizationName = BaseTestCase.currentModule + "_policy3_pid"; + public static String policyToken3PartnerId = policyToken3OrganizationName; + private static final String policyToken3EmailId = "mosip_policy3_" + System.currentTimeMillis() + "@gmail.com"; + public static String policyToken3PartnerKeyUrl = ""; + + /** + * Registers a third partner mapped to the same policy-token policy, so that + * the "same token for the same UIN regardless of partner" property can be + * verified across more than just a single pair of partners. + */ + public static void registerThirdPolicyTokenPartner() { + registerAdditionalPolicyTokenPartner(policyToken3PartnerId, policyToken3OrganizationName, + policyToken3EmailId); + } + + public static String generateAndGetThirdPolicyTokenPartnerKeyUrl() { + policyToken3PartnerKeyUrl = mapToPolicyTokenPolicyAndGetKeyUrl(policyToken3PartnerId); + return policyToken3PartnerKeyUrl; + } + + public static String partnerToken2KeyUrl = ""; + + /** + * Maps the second partner (already registered for the policy-token tests via + * {@link #registerSecondPolicyTokenPartner()}) to the default policy, whose + * authTokenType is "partner", instead of the policy-token policy. This gives + * a second, independent partner under the SAME authTokenType=partner policy + * as the main partner, so the resulting authToken (which is derived from + * partnerId and UIN) can be compared against the main partner's token for + * the same UIN and shown to differ. + */ + public static String generateAndGetPartnerToken2KeyUrl() { + partnerToken2KeyUrl = mapPartnerToPolicyAndGetKeyUrl(policyToken2PartnerId, policyName); + return partnerToken2KeyUrl; + } + + public static String randomToken2PartnerKeyUrl = ""; + public static String randomToken3PartnerKeyUrl = ""; + + /** + * Maps the second and third partners (already registered for the + * policy-token tests) to the random-token policy created via + * {@link #createAndPublishPolicyWithRandomTokenType()}, so that the + * "a new random token every call, regardless of partner" property can be + * verified across multiple different partners sharing the same policy. + */ + public static String generateAndGetRandomToken2PartnerKeyUrl() { + randomToken2PartnerKeyUrl = mapPartnerToPolicyAndGetKeyUrl(policyToken2PartnerId, policyNameForRandomToken); + return randomToken2PartnerKeyUrl; + } + + public static String generateAndGetRandomToken3PartnerKeyUrl() { + randomToken3PartnerKeyUrl = mapPartnerToPolicyAndGetKeyUrl(policyToken3PartnerId, policyNameForRandomToken); + return randomToken3PartnerKeyUrl; + } + } \ No newline at end of file diff --git a/api-test/src/main/resources/config/AuthPolicyForPolicyTokenAllowedAuthTypes.json b/api-test/src/main/resources/config/AuthPolicyForPolicyTokenAllowedAuthTypes.json new file mode 100644 index 0000000000..5fa69f1675 --- /dev/null +++ b/api-test/src/main/resources/config/AuthPolicyForPolicyTokenAllowedAuthTypes.json @@ -0,0 +1,117 @@ +{ + "allowedAuthTypes": [ + { + "authSubType": "IRIS", + "authType": "bio", + "mandatory": false + }, + { + "authSubType": "FINGER", + "authType": "bio", + "mandatory": false + }, + { + "authSubType": "", + "authType": "otp", + "mandatory": false + }, + { + "authSubType": "FACE", + "authType": "bio", + "mandatory": false + }, + { + "authSubType": "", + "authType": "otp-request", + "mandatory": false + }, + { + "authSubType": "", + "authType": "kyc", + "mandatory": false + }, + { + "authSubType": "", + "authType": "demo", + "mandatory": false + }, + { + "authSubType": "", + "authType": "kycauth", + "mandatory": false + }, + { + "authSubType": "", + "authType": "kycexchange", + "mandatory": false + }, + { + "authSubType": "", + "authType": "keybinding", + "mandatory": false + }, + { + "authSubType": "", + "authType": "kbt", + "mandatory": false + }, + { + "authSubType": "", + "authType": "wla", + "mandatory": false + }, + { + "authSubType": "", + "authType": "vciexchange", + "mandatory": false + }, + { + "authSubType": "", + "authType": "pwd", + "mandatory": false + } + ], + "kycLanguages": [ + "ara", + "eng" + ], + "allowedKycAttributes": [ + { + "attributeName": "fullName" + }, + { + "attributeName": "gender" + }, + { + "attributeName": "residenceStatus" + }, + { + "attributeName": "dateOfBirth" + }, + { + "attributeName": "photo" + }, + { + "attributeName": "firstName" + }, + { + "attributeName": "province" + }, + { + "attributeName": "city" + }, + { + "attributeName": "zone" + }, + { + "attributeName": "postalCode" + }, + { + "attributeName": "phone" + }, + { + "attributeName": "email" + } + ], + "authTokenType": "policy" + } diff --git a/api-test/src/main/resources/config/AuthPolicyForRandomTokenAllowedAuthTypes.json b/api-test/src/main/resources/config/AuthPolicyForRandomTokenAllowedAuthTypes.json new file mode 100644 index 0000000000..8887e8756c --- /dev/null +++ b/api-test/src/main/resources/config/AuthPolicyForRandomTokenAllowedAuthTypes.json @@ -0,0 +1,117 @@ +{ + "allowedAuthTypes": [ + { + "authSubType": "IRIS", + "authType": "bio", + "mandatory": false + }, + { + "authSubType": "FINGER", + "authType": "bio", + "mandatory": false + }, + { + "authSubType": "", + "authType": "otp", + "mandatory": false + }, + { + "authSubType": "FACE", + "authType": "bio", + "mandatory": false + }, + { + "authSubType": "", + "authType": "otp-request", + "mandatory": false + }, + { + "authSubType": "", + "authType": "kyc", + "mandatory": false + }, + { + "authSubType": "", + "authType": "demo", + "mandatory": false + }, + { + "authSubType": "", + "authType": "kycauth", + "mandatory": false + }, + { + "authSubType": "", + "authType": "kycexchange", + "mandatory": false + }, + { + "authSubType": "", + "authType": "keybinding", + "mandatory": false + }, + { + "authSubType": "", + "authType": "kbt", + "mandatory": false + }, + { + "authSubType": "", + "authType": "wla", + "mandatory": false + }, + { + "authSubType": "", + "authType": "vciexchange", + "mandatory": false + }, + { + "authSubType": "", + "authType": "pwd", + "mandatory": false + } + ], + "kycLanguages": [ + "ara", + "eng" + ], + "allowedKycAttributes": [ + { + "attributeName": "fullName" + }, + { + "attributeName": "gender" + }, + { + "attributeName": "residenceStatus" + }, + { + "attributeName": "dateOfBirth" + }, + { + "attributeName": "photo" + }, + { + "attributeName": "firstName" + }, + { + "attributeName": "province" + }, + { + "attributeName": "city" + }, + { + "attributeName": "zone" + }, + { + "attributeName": "postalCode" + }, + { + "attributeName": "phone" + }, + { + "attributeName": "email" + } + ], + "authTokenType": "random" + } diff --git a/api-test/src/main/resources/ida/AddIdentity/AddIdentity.yml b/api-test/src/main/resources/ida/AddIdentity/AddIdentity.yml index 855e933dbb..f18b108cd0 100644 --- a/api-test/src/main/resources/ida/AddIdentity/AddIdentity.yml +++ b/api-test/src/main/resources/ida/AddIdentity/AddIdentity.yml @@ -2294,4 +2294,4 @@ AddIdentity: }' output: '{ "status":"ACTIVATED" -}' \ No newline at end of file +}' diff --git a/api-test/src/main/resources/ida/DemoAuth/DemoAuth2.yml b/api-test/src/main/resources/ida/DemoAuth/DemoAuth2.yml index 5932b93b78..5ef20bfbe2 100644 --- a/api-test/src/main/resources/ida/DemoAuth/DemoAuth2.yml +++ b/api-test/src/main/resources/ida/DemoAuth/DemoAuth2.yml @@ -23,6 +23,357 @@ DemoAuthNew: }' output: '{ "authStatus": "true" +}' + auth_DemoAuth_authToken_Based_On_Policy_UIN_Pos: + endPoint: /idauthentication/v1/auth/$partnerKeyURL$ + uniqueIdentifier: TC_IDA_DemoAuth_75 + description: IDA_TC_0450 - Verify authToken field in the authentication response based on policy + role: resident + restMethod: post + inputTemplate: ida/DemoAuth/DemoAuth + outputTemplate: ida/DemoAuth/DemoAuthResultWithAuthToken + input: '{ + "requestTime": "$TIMESTAMP$", + "individualId": "$ID:AddIdentity_withValidParameters_smoke_Pos_UIN$", + "transactionId": "1234567890", + "individualIdType": "UIN", + "bio": false, + "demo": true, + "otp": false, + "identityRequest":{ + "value": "1970/07/08", +"key": "dob", + "identityRequestTemplate": "ida/DemoAuth/DemoIdentityEncrypt" + } + }' + output: '{ + "authStatus": "true", + "authToken": "$REGEXP:^(?!null).+$" +}' + auth_DemoAuth_authToken_PolicyToken_First_Call_sid_Pos: + endPoint: /idauthentication/v1/auth/$PolicyTokenPartnerKeyURL$ + uniqueIdentifier: TC_IDA_DemoAuth_76 + description: IDA_TC_0451 - Demo auth via a partner mapped to a policy with authTokenType policy, first call to capture the authToken + role: resident + restMethod: post + inputTemplate: ida/DemoAuth/DemoAuth + outputTemplate: ida/DemoAuth/DemoAuthResultWithAuthToken + input: '{ + "requestTime": "$TIMESTAMP$", + "individualId": "$ID:AddIdentity_withValidParameters_smoke_Pos_UIN$", + "transactionId": "1234567890", + "individualIdType": "UIN", + "bio": false, + "demo": true, + "otp": false, + "identityRequest":{ + "value": "1970/07/08", +"key": "dob", + "identityRequestTemplate": "ida/DemoAuth/DemoIdentityEncrypt" + } + }' + output: '{ + "authStatus": "true", + "authToken": "$REGEXP:^(?!null).+$" +}' + auth_DemoAuth_authToken_PolicyToken_Matches_For_Same_UIN_Pos: + endPoint: /idauthentication/v1/auth/$PolicyTokenPartnerKeyURL$ + uniqueIdentifier: TC_IDA_DemoAuth_77 + description: IDA_TC_0451 - Verify authToken for a policy-type policy is derived from policyId and UIN, i.e. it is the same on a second demo auth call for the same UIN + role: resident + restMethod: post + additionalDependencies: TC_IDA_DemoAuth_76 + inputTemplate: ida/DemoAuth/DemoAuth + outputTemplate: ida/DemoAuth/DemoAuthResultWithAuthToken + input: '{ + "requestTime": "$TIMESTAMP$", + "individualId": "$ID:AddIdentity_withValidParameters_smoke_Pos_UIN$", + "transactionId": "1234567890", + "individualIdType": "UIN", + "bio": false, + "demo": true, + "otp": false, + "identityRequest":{ + "value": "1970/07/08", +"key": "dob", + "identityRequestTemplate": "ida/DemoAuth/DemoIdentityEncrypt" + } + }' + output: '{ + "authStatus": "true", + "authToken": "$ID:DemoAuth_authToken_PolicyToken_First_Call_sid_Pos_authToken$" +}' + auth_DemoAuth_authToken_PolicyToken_Matches_Across_Partners_Pos: + endPoint: /idauthentication/v1/auth/$PolicyToken2PartnerKeyURL$ + uniqueIdentifier: TC_IDA_DemoAuth_78 + description: IDA_TC_0452 - Verify authToken is the same for a demo auth done by a different partner mapped to the same policy with authTokenType policy + role: resident + restMethod: post + additionalDependencies: TC_IDA_DemoAuth_76 + inputTemplate: ida/DemoAuth/DemoAuth + outputTemplate: ida/DemoAuth/DemoAuthResultWithAuthToken + input: '{ + "requestTime": "$TIMESTAMP$", + "individualId": "$ID:AddIdentity_withValidParameters_smoke_Pos_UIN$", + "transactionId": "1234567890", + "individualIdType": "UIN", + "bio": false, + "demo": true, + "otp": false, + "identityRequest":{ + "value": "1970/07/08", +"key": "dob", + "identityRequestTemplate": "ida/DemoAuth/DemoIdentityEncrypt" + } + }' + output: '{ + "authStatus": "true", + "authToken": "$ID:DemoAuth_authToken_PolicyToken_First_Call_sid_Pos_authToken$" +}' + auth_DemoAuth_authToken_PolicyToken_Matches_Across_Multiple_Partners_Pos: + endPoint: /idauthentication/v1/auth/$PolicyToken3PartnerKeyURL$ + uniqueIdentifier: TC_IDA_DemoAuth_79 + description: IDA_TC_0453 - Verify authToken is the same for a demo auth done by multiple different partners mapped to the same policy with authTokenType policy + role: resident + restMethod: post + additionalDependencies: TC_IDA_DemoAuth_76 + inputTemplate: ida/DemoAuth/DemoAuth + outputTemplate: ida/DemoAuth/DemoAuthResultWithAuthToken + input: '{ + "requestTime": "$TIMESTAMP$", + "individualId": "$ID:AddIdentity_withValidParameters_smoke_Pos_UIN$", + "transactionId": "1234567890", + "individualIdType": "UIN", + "bio": false, + "demo": true, + "otp": false, + "identityRequest":{ + "value": "1970/07/08", +"key": "dob", + "identityRequestTemplate": "ida/DemoAuth/DemoIdentityEncrypt" + } + }' + output: '{ + "authStatus": "true", + "authToken": "$ID:DemoAuth_authToken_PolicyToken_First_Call_sid_Pos_authToken$" +}' + auth_DemoAuth_authToken_PartnerToken_First_Call_sid_Pos: + endPoint: /idauthentication/v1/auth/$partnerKeyURL$ + uniqueIdentifier: TC_IDA_DemoAuth_80 + description: IDA_TC_0454 - Demo auth via the default partner whose policy has authTokenType partner, first call to capture the authToken + role: resident + restMethod: post + inputTemplate: ida/DemoAuth/DemoAuth + outputTemplate: ida/DemoAuth/DemoAuthResultWithAuthToken + input: '{ + "requestTime": "$TIMESTAMP$", + "individualId": "$ID:AddIdentity_withValidParameters_smoke_Pos_UIN$", + "transactionId": "1234567890", + "individualIdType": "UIN", + "bio": false, + "demo": true, + "otp": false, + "identityRequest":{ + "value": "1970/07/08", +"key": "dob", + "identityRequestTemplate": "ida/DemoAuth/DemoIdentityEncrypt" + } + }' + output: '{ + "authStatus": "true", + "authToken": "$REGEXP:^(?!null).+$" +}' + auth_DemoAuth_authToken_PartnerToken_Matches_For_Same_UIN_Pos: + endPoint: /idauthentication/v1/auth/$partnerKeyURL$ + uniqueIdentifier: TC_IDA_DemoAuth_81 + description: IDA_TC_0454 - Verify authToken for a partner-type policy is derived from partnerId and UIN, i.e. it is the same on a second demo auth call for the same UIN via the same partner + role: resident + restMethod: post + additionalDependencies: TC_IDA_DemoAuth_80 + inputTemplate: ida/DemoAuth/DemoAuth + outputTemplate: ida/DemoAuth/DemoAuthResultWithAuthToken + input: '{ + "requestTime": "$TIMESTAMP$", + "individualId": "$ID:AddIdentity_withValidParameters_smoke_Pos_UIN$", + "transactionId": "1234567890", + "individualIdType": "UIN", + "bio": false, + "demo": true, + "otp": false, + "identityRequest":{ + "value": "1970/07/08", +"key": "dob", + "identityRequestTemplate": "ida/DemoAuth/DemoIdentityEncrypt" + } + }' + output: '{ + "authStatus": "true", + "authToken": "$ID:DemoAuth_authToken_PartnerToken_First_Call_sid_Pos_authToken$" +}' + auth_DemoAuth_authToken_PartnerToken_Differs_Across_Partners_Pos: + endPoint: /idauthentication/v1/auth/$PartnerToken2KeyURL$ + uniqueIdentifier: TC_IDA_DemoAuth_82 + description: IDA_TC_0455 - Verify authToken differs for a demo auth done by a different partner mapped to the same policy with authTokenType partner, since the token is derived from partnerId and UIN, not the policy + role: resident + restMethod: post + additionalDependencies: TC_IDA_DemoAuth_80 + inputTemplate: ida/DemoAuth/DemoAuth + outputTemplate: ida/DemoAuth/DemoAuthResultWithAuthToken + input: '{ + "requestTime": "$TIMESTAMP$", + "individualId": "$ID:AddIdentity_withValidParameters_smoke_Pos_UIN$", + "transactionId": "1234567890", + "individualIdType": "UIN", + "bio": false, + "demo": true, + "otp": false, + "identityRequest":{ + "value": "1970/07/08", +"key": "dob", + "identityRequestTemplate": "ida/DemoAuth/DemoIdentityEncrypt" + } + }' + output: '{ + "authStatus": "true", + "authToken": "$REGEXP:^((?!$ID:DemoAuth_authToken_PartnerToken_First_Call_sid_Pos_authToken$).+)$" +}' + auth_DemoAuth_authToken_RandomToken_First_Call_sid_Pos: + endPoint: /idauthentication/v1/auth/$RandomTokenPartnerKeyURL$ + uniqueIdentifier: TC_IDA_DemoAuth_83 + description: IDA_TC_0456 - Demo auth via a partner mapped to a policy with authTokenType random, first call to capture the authToken + role: resident + restMethod: post + inputTemplate: ida/DemoAuth/DemoAuth + outputTemplate: ida/DemoAuth/DemoAuthResultWithAuthToken + input: '{ + "requestTime": "$TIMESTAMP$", + "individualId": "$ID:AddIdentity_withValidParameters_smoke_Pos_UIN$", + "transactionId": "1234567890", + "individualIdType": "UIN", + "bio": false, + "demo": true, + "otp": false, + "identityRequest":{ + "value": "1970/07/08", +"key": "dob", + "identityRequestTemplate": "ida/DemoAuth/DemoIdentityEncrypt" + } + }' + output: '{ + "authStatus": "true", + "authToken": "$REGEXP:^(?!null).+$" +}' + auth_DemoAuth_authToken_RandomToken_Differs_On_Repeat_Call_Pos: + endPoint: /idauthentication/v1/auth/$RandomTokenPartnerKeyURL$ + uniqueIdentifier: TC_IDA_DemoAuth_84 + description: IDA_TC_0456 - Verify authToken for a random-type policy differs on every demo auth call for the same UIN via the same partner, since a new random token is generated each time + role: resident + restMethod: post + additionalDependencies: TC_IDA_DemoAuth_83 + inputTemplate: ida/DemoAuth/DemoAuth + outputTemplate: ida/DemoAuth/DemoAuthResultWithAuthToken + input: '{ + "requestTime": "$TIMESTAMP$", + "individualId": "$ID:AddIdentity_withValidParameters_smoke_Pos_UIN$", + "transactionId": "1234567890", + "individualIdType": "UIN", + "bio": false, + "demo": true, + "otp": false, + "identityRequest":{ + "value": "1970/07/08", +"key": "dob", + "identityRequestTemplate": "ida/DemoAuth/DemoIdentityEncrypt" + } + }' + output: '{ + "authStatus": "true", + "authToken": "$REGEXP:^((?!$ID:DemoAuth_authToken_RandomToken_First_Call_sid_Pos_authToken$).+)$" +}' + auth_DemoAuth_authToken_RandomToken_Differs_Across_Partners_Pos: + endPoint: /idauthentication/v1/auth/$RandomToken2PartnerKeyURL$ + uniqueIdentifier: TC_IDA_DemoAuth_85 + description: IDA_TC_0457 - Verify authToken differs for a demo auth done by a different partner mapped to the same policy with authTokenType random, since a new random token is generated each time regardless of partner + role: resident + restMethod: post + additionalDependencies: TC_IDA_DemoAuth_83 + inputTemplate: ida/DemoAuth/DemoAuth + outputTemplate: ida/DemoAuth/DemoAuthResultWithAuthToken + input: '{ + "requestTime": "$TIMESTAMP$", + "individualId": "$ID:AddIdentity_withValidParameters_smoke_Pos_UIN$", + "transactionId": "1234567890", + "individualIdType": "UIN", + "bio": false, + "demo": true, + "otp": false, + "identityRequest":{ + "value": "1970/07/08", +"key": "dob", + "identityRequestTemplate": "ida/DemoAuth/DemoIdentityEncrypt" + } + }' + output: '{ + "authStatus": "true", + "authToken": "$REGEXP:^((?!$ID:DemoAuth_authToken_RandomToken_First_Call_sid_Pos_authToken$).+)$" +}' + auth_DemoAuth_authToken_RandomToken_Differs_Across_Multiple_Partners_Pos: + endPoint: /idauthentication/v1/auth/$RandomToken3PartnerKeyURL$ + uniqueIdentifier: TC_IDA_DemoAuth_86 + description: IDA_TC_0457 - Verify authToken differs for a demo auth done by multiple different partners mapped to the same policy with authTokenType random + role: resident + restMethod: post + additionalDependencies: TC_IDA_DemoAuth_83 + inputTemplate: ida/DemoAuth/DemoAuth + outputTemplate: ida/DemoAuth/DemoAuthResultWithAuthToken + input: '{ + "requestTime": "$TIMESTAMP$", + "individualId": "$ID:AddIdentity_withValidParameters_smoke_Pos_UIN$", + "transactionId": "1234567890", + "individualIdType": "UIN", + "bio": false, + "demo": true, + "otp": false, + "identityRequest":{ + "value": "1970/07/08", +"key": "dob", + "identityRequestTemplate": "ida/DemoAuth/DemoIdentityEncrypt" + } + }' + output: '{ + "authStatus": "true", + "authToken": "$REGEXP:^((?!$ID:DemoAuth_authToken_RandomToken_First_Call_sid_Pos_authToken$).+)$" +}' + auth_DemoAuth_DOB_Invalid_Thumbprint_UIN_Neg: + endPoint: /idauthentication/v1/auth/$partnerKeyURL$ + uniqueIdentifier: TC_IDA_DemoAuth_74 + description: IDA_TC_0298 - Verify that demo authentication fails with a decryption error when an incorrect thumbprint is given in the IDA request + role: resident + restMethod: post + inputTemplate: ida/DemoAuth/DemoAuth + outputTemplate: ida/DemoAuth/error + input: '{ + "requestTime": "$TIMESTAMP$", + "individualId": "$ID:AddIdentity_withValidParameters_smoke_Pos_UIN$", + "transactionId": "1234567890", + "individualIdType": "UIN", + "bio": false, + "demo": true, + "otp": false, + "invalidThumbprint": "1111111111111111111111111111111111111111111111111111111111111111", + "identityRequest":{ + "value": "1970/07/08", +"key": "dob", + "identityRequestTemplate": "ida/DemoAuth/DemoIdentityEncrypt" + } + }' + output: '{ + "authStatus": "false", + "errors": [ + { + "errorCode": "IDA-MPA-003" + } + ] }' auth_DemoAuth_DOB_InValid_UIN_Neg: endPoint: /idauthentication/v1/auth/$partnerKeyURL$ diff --git a/api-test/src/main/resources/ida/DemoAuth/DemoAuthResultWithAuthToken.hbs b/api-test/src/main/resources/ida/DemoAuth/DemoAuthResultWithAuthToken.hbs new file mode 100644 index 0000000000..a90af0d07b --- /dev/null +++ b/api-test/src/main/resources/ida/DemoAuth/DemoAuthResultWithAuthToken.hbs @@ -0,0 +1,10 @@ +{ + "transactionID": "$IGNORE$", + "version": "$IGNORE$", + "id": "$IGNORE$", + "responseTime": "$IGNORE$", + "response": { + "authStatus": "{{authStatus}}", + "authToken": "{{authToken}}" + } +} \ No newline at end of file diff --git a/api-test/src/main/resources/ida/DemoAuthKycExchange/DemoAuthKycExchange.yml b/api-test/src/main/resources/ida/DemoAuthKycExchange/DemoAuthKycExchange.yml index eec36c56c8..04bf750d59 100644 --- a/api-test/src/main/resources/ida/DemoAuthKycExchange/DemoAuthKycExchange.yml +++ b/api-test/src/main/resources/ida/DemoAuthKycExchange/DemoAuthKycExchange.yml @@ -477,5 +477,32 @@ DemoAuthKycExchange: "respType": "JWE" }' output: '{ - + +}' + auth_DemoAuthKycExchange_Without_KycAuth_Neg: + endPoint: /idauthentication/v1/kyc-exchange/delegated/$partialPartnerKeyUrl$/$ID:CreateOIDCClient_Delegated_Valid_Smoke_sid_clientId$ + uniqueIdentifier: TC_IDA_DemoAuthKycExchange_23 + description: IDA_TC_1638 - Verify kyc-exchange fails with an appropriate error when called with a kycToken that was never issued by a prior kyc-auth call + role: resident + restMethod: post + inputTemplate: ida/DemoAuthKycExchange/DemoAuthKycExchange + outputTemplate: ida/DemoAuthKycExchange/DemoAuthKycExchangeError + input: '{ + "requestTime": "$TIMESTAMP$", + "individualId": "$ID:AddIdentity_withValidParameters_forDemoDelegated_Pos_UIN$", + "transactionID": "$TRANSACTIONID$", + "individualIdType": "UIN", + "id": "mosip.identity.kycexchange", + "version": "1.0", + "kycToken": "NeverIssuedByKycAuth_InvalidKycToken_123456789", + "consentObtained": [{consentObtainedValue: "gender"}, {consentObtainedValue: "birthdate"}], + "locales": [{localesValue: "eng"}], + "respType": "JWE" + }' + output: '{ + "errors": [ + { + "errorCode": "IDA-KYE-001" + } + ] }' \ No newline at end of file diff --git a/api-test/src/main/resources/ida/DemoAuthKycExchange/DemoAuthKycExchangeError.hbs b/api-test/src/main/resources/ida/DemoAuthKycExchange/DemoAuthKycExchangeError.hbs new file mode 100644 index 0000000000..05d489b026 --- /dev/null +++ b/api-test/src/main/resources/ida/DemoAuthKycExchange/DemoAuthKycExchangeError.hbs @@ -0,0 +1,16 @@ +{ + "transactionID": "$IGNORE$", + "version": "$IGNORE$", + "id": "$IGNORE$", + "errors": [ + {{#each errors}} + { + "errorCode": "{{errorCode}}", + "errorMessage": "{{errorMessage}}", + "actionMessage": "$IGNORE$" + } + {{#unless @last}},{{/unless}} + {{/each}} + ], + "responseTime": "$IGNORE$" +} \ No newline at end of file