diff --git a/docs/Migration-Instructions.md b/docs/Migration-Instructions.md index 5a054b15a..50e22cd23 100644 --- a/docs/Migration-Instructions.md +++ b/docs/Migration-Instructions.md @@ -2,6 +2,7 @@ This page contains PowerAuth Web Flow migration instructions. +- [PowerAuth Web Flow 1.8.0](./Web-Flow-1.8.0.md) - [PowerAuth Web Flow 1.7.0](./Web-Flow-1.7.0.md) - [PowerAuth Web Flow 1.6.0](./Web-Flow-1.6.0.md) - [PowerAuth Web Flow 1.5.0](./Web-Flow-1.5.0.md) diff --git a/docs/Next-Step-Server-REST-API-Reference.md b/docs/Next-Step-Server-REST-API-Reference.md index 3d3806916..006457ace 100644 --- a/docs/Next-Step-Server-REST-API-Reference.md +++ b/docs/Next-Step-Server-REST-API-Reference.md @@ -8823,7 +8823,6 @@ The list of expected status codes: ```json { "requestObject": { - "credentialName": "RETAIL_CREDENTIAL", "userId": "test1234", "credentialValue": ")wOI6ijUkwYI", "authenticationMode": "MATCH_EXACT", diff --git a/docs/Web-Flow-1.8.0.md b/docs/Web-Flow-1.8.0.md new file mode 100644 index 000000000..e2055ce85 --- /dev/null +++ b/docs/Web-Flow-1.8.0.md @@ -0,0 +1,10 @@ +# Migration from 1.7.0 to 1.8.0 + +This guide contains instructions for migration from PowerAuth WebFlow version `1.7.x` to version `1.8.0`. + +## API + +### Attribute `credentialName` modification + +The attribute `credentialName` has been removed from the request object of the API endpoint `/auth/combined`. This change +was made because the attribute was not utilized in the underlying functionality. diff --git a/powerauth-nextstep-client/src/main/java/io/getlime/security/powerauth/lib/nextstep/client/NextStepClient.java b/powerauth-nextstep-client/src/main/java/io/getlime/security/powerauth/lib/nextstep/client/NextStepClient.java index 8dc2477b2..f5749264d 100644 --- a/powerauth-nextstep-client/src/main/java/io/getlime/security/powerauth/lib/nextstep/client/NextStepClient.java +++ b/powerauth-nextstep-client/src/main/java/io/getlime/security/powerauth/lib/nextstep/client/NextStepClient.java @@ -2416,7 +2416,6 @@ public ObjectResponse authenticateWithCredenti /** * Authenticate using credential and OTP without operation. * - * @param credentialName Credential name. * @param userId User ID. * @param credentialValue Credential value. * @param otpId OTP ID. @@ -2424,10 +2423,9 @@ public ObjectResponse authenticateWithCredenti * @return OTP authentication response. * @throws NextStepClientException Thrown when REST API call fails, including {@link ErrorResponse} with error code. */ - public ObjectResponse authenticateCombined(@NotNull String credentialName, @NotNull String userId, @NotNull String credentialValue, + public ObjectResponse authenticateCombined(@NotNull String userId, @NotNull String credentialValue, String otpId, @NotNull String otpValue) throws NextStepClientException { final CombinedAuthenticationRequest request = new CombinedAuthenticationRequest(); - request.setCredentialName(credentialName); request.setUserId(userId); request.setCredentialValue(credentialValue); request.setOtpId(otpId); @@ -2438,7 +2436,6 @@ public ObjectResponse authenticateCombined(@NotN /** * Authenticate using credential and OTP without operation and with additional details. * - * @param credentialName Credential name. * @param userId User ID. * @param credentialValue Credential value. * @param authenticationMode Authentication mode. @@ -2448,11 +2445,10 @@ public ObjectResponse authenticateCombined(@NotN * @return OTP authentication response. * @throws NextStepClientException Thrown when REST API call fails, including {@link ErrorResponse} with error code. */ - public ObjectResponse authenticateCombined(@NotNull String credentialName, @NotNull String userId, @NotNull String credentialValue, + public ObjectResponse authenticateCombined(@NotNull String userId, @NotNull String credentialValue, CredentialAuthenticationMode authenticationMode, List credentialPositionsToVerify, String otpId, @NotNull String otpValue) throws NextStepClientException { final CombinedAuthenticationRequest request = new CombinedAuthenticationRequest(); - request.setCredentialName(credentialName); request.setUserId(userId); request.setCredentialValue(credentialValue); request.setAuthenticationMode(authenticationMode); @@ -2465,7 +2461,6 @@ public ObjectResponse authenticateCombined(@NotN /** * Authenticate using credential and OTP with operation. * - * @param credentialName Credential name. * @param userId User ID. * @param credentialValue Credential value. * @param otpId OTP ID. @@ -2476,11 +2471,10 @@ public ObjectResponse authenticateCombined(@NotN * @return OTP authentication response. * @throws NextStepClientException Thrown when REST API call fails, including {@link ErrorResponse} with error code. */ - public ObjectResponse authenticateCombined(@NotNull String credentialName, @NotNull String userId, @NotNull String credentialValue, + public ObjectResponse authenticateCombined(@NotNull String userId, @NotNull String credentialValue, String otpId, String operationId, @NotNull String otpValue, boolean updateOperation, AuthMethod authMethod) throws NextStepClientException { final CombinedAuthenticationRequest request = new CombinedAuthenticationRequest(); - request.setCredentialName(credentialName); request.setUserId(userId); request.setCredentialValue(credentialValue); request.setOtpId(otpId); @@ -2494,7 +2488,6 @@ public ObjectResponse authenticateCombined(@NotN /** * Authenticate using credential and OTP with operation and with additional details. * - * @param credentialName Credential name. * @param userId User ID. * @param credentialValue Credential value. * @param authenticationMode Authentication mode. @@ -2507,12 +2500,11 @@ public ObjectResponse authenticateCombined(@NotN * @return OTP authentication response. * @throws NextStepClientException Thrown when REST API call fails, including {@link ErrorResponse} with error code. */ - public ObjectResponse authenticateCombined(@NotNull String credentialName, @NotNull String userId, @NotNull String credentialValue, + public ObjectResponse authenticateCombined(@NotNull String userId, @NotNull String credentialValue, CredentialAuthenticationMode authenticationMode, List credentialPositionsToVerify, String otpId, String operationId, @NotNull String otpValue, boolean updateOperation, AuthMethod authMethod) throws NextStepClientException { final CombinedAuthenticationRequest request = new CombinedAuthenticationRequest(); - request.setCredentialName(credentialName); request.setUserId(userId); request.setCredentialValue(credentialValue); request.setAuthenticationMode(authenticationMode); diff --git a/powerauth-nextstep-model/src/main/java/io/getlime/security/powerauth/lib/nextstep/model/request/CombinedAuthenticationRequest.java b/powerauth-nextstep-model/src/main/java/io/getlime/security/powerauth/lib/nextstep/model/request/CombinedAuthenticationRequest.java index 6cd478b20..1e5c4ce6e 100644 --- a/powerauth-nextstep-model/src/main/java/io/getlime/security/powerauth/lib/nextstep/model/request/CombinedAuthenticationRequest.java +++ b/powerauth-nextstep-model/src/main/java/io/getlime/security/powerauth/lib/nextstep/model/request/CombinedAuthenticationRequest.java @@ -34,9 +34,6 @@ @Data public class CombinedAuthenticationRequest { - @NotBlank - @Size(min = 2, max = 256) - private String credentialName; @NotBlank @Size(min = 1, max = 256) private String userId; diff --git a/powerauth-nextstep/src/main/java/io/getlime/security/powerauth/app/nextstep/service/AuthenticationService.java b/powerauth-nextstep/src/main/java/io/getlime/security/powerauth/app/nextstep/service/AuthenticationService.java index 49fb6bed0..8d2002a61 100644 --- a/powerauth-nextstep/src/main/java/io/getlime/security/powerauth/app/nextstep/service/AuthenticationService.java +++ b/powerauth-nextstep/src/main/java/io/getlime/security/powerauth/app/nextstep/service/AuthenticationService.java @@ -551,6 +551,9 @@ public CombinedAuthenticationResponse authenticateCombined(CombinedAuthenticatio final IdGeneratorService idGeneratorService = serviceCatalogue.getIdGeneratorService(); final OtpEntity otp = otpService.findOtp(request.getOtpId(), request.getOperationId()); + if (otp.getCredentialDefinition() == null || otp.getCredentialDefinition().getName() == null) { + throw new InvalidRequestException("Credential definition is not set for operation with OTP Id and Operation Id: " + request.getOtpId() + ", " + request.getOperationId()); + } if (otp.getOtpDefinition().isDataAdapterProxyEnabled()) { logger.info("Combined authentication proxied through Data Adapter, OTP ID: {}", request.getOtpId()); return authenticateCombinedCustom(otp.getCredentialDefinition(), otp.getOtpId(), request.getOtpValue(), request.getCredentialValue(), otp.getOperation().getOperationId(), otp.getUserId(), request.getAuthMethod()); @@ -577,10 +580,10 @@ public CombinedAuthenticationResponse authenticateCombined(CombinedAuthenticatio operation = operationPersistenceService.getOperation(request.getOperationId()); } if (request.isUpdateOperation() && operation == null) { - throw new InvalidRequestException("Operation not found, however operation update requested for credential and OTP: " + request.getCredentialName() + ", " + otp.getOtpDefinition().getName()); + throw new InvalidRequestException("Operation not found, however operation update requested for credential and OTP: " + otp.getCredentialDefinition().getName() + ", " + otp.getOtpDefinition().getName()); } if (request.getOperationId() != null && !request.getOperationId().equals(otp.getOperation().getOperationId())) { - throw new InvalidRequestException("Operation ID mismatch for credential and OTP: " + request.getCredentialName() + ", " + otp.getOtpDefinition().getName()); + throw new InvalidRequestException("Operation ID mismatch for credential and OTP: " + otp.getCredentialDefinition().getName() + ", " + otp.getOtpDefinition().getName()); } final CredentialEntity credential = credentialService.findCredential(otp.getCredentialDefinition(), user); final CredentialDefinitionEntity credentialDefinition = credential.getCredentialDefinition(); diff --git a/powerauth-nextstep/src/test/java/io/getlime/security/powerauth/app/nextstep/NextStepAuthenticationTest.java b/powerauth-nextstep/src/test/java/io/getlime/security/powerauth/app/nextstep/NextStepAuthenticationTest.java index 216ca1bf8..774fd626a 100644 --- a/powerauth-nextstep/src/test/java/io/getlime/security/powerauth/app/nextstep/NextStepAuthenticationTest.java +++ b/powerauth-nextstep/src/test/java/io/getlime/security/powerauth/app/nextstep/NextStepAuthenticationTest.java @@ -283,7 +283,7 @@ public void testCredentialFailUnknownUser() { @Test public void testCredentialAndOtpSuccessNoOperation() throws NextStepClientException { CreateOtpResponse r1 = nextStepClient.createOtp("test_user_1", "TEST_OTP", "TEST_CREDENTIAL", "TEST_DATA").getResponseObject(); - CombinedAuthenticationResponse r2 = nextStepClient.authenticateCombined("TEST_CREDENTIAL", "test_user_1", "s3cret", r1.getOtpId(), r1.getOtpValue()).getResponseObject(); + CombinedAuthenticationResponse r2 = nextStepClient.authenticateCombined("test_user_1", "s3cret", r1.getOtpId(), r1.getOtpValue()).getResponseObject(); assertEquals(AuthenticationResult.SUCCEEDED, r2.getAuthenticationResult()); } @@ -291,7 +291,7 @@ public void testCredentialAndOtpSuccessNoOperation() throws NextStepClientExcept public void testCredentialAndOtpSuccessWithOperation() throws NextStepClientException { nextStepClient.createOperation("auth_otp", "test_operation_8", "A1", null, null); CreateOtpResponse r1 = nextStepClient.createOtp("test_user_1", "TEST_OTP", "TEST_CREDENTIAL", "TEST_DATA", "test_operation_8").getResponseObject(); - CombinedAuthenticationResponse r2 = nextStepClient.authenticateCombined("TEST_CREDENTIAL", "test_user_1", "s3cret", r1.getOtpId(), "test_operation_8", r1.getOtpValue(), true, null).getResponseObject(); + CombinedAuthenticationResponse r2 = nextStepClient.authenticateCombined("test_user_1", "s3cret", r1.getOtpId(), "test_operation_8", r1.getOtpValue(), true, null).getResponseObject(); assertEquals(AuthenticationResult.SUCCEEDED, r2.getAuthenticationResult()); GetOperationDetailResponse r3 = nextStepClient.getOperationDetail("test_operation_8").getResponseObject(); assertEquals(AuthResult.DONE, r3.getResult()); @@ -300,7 +300,7 @@ public void testCredentialAndOtpSuccessWithOperation() throws NextStepClientExce @Test public void testCredentialAndOtpFailNoOperation1() throws NextStepClientException { CreateOtpResponse r1 = nextStepClient.createOtp("test_user_1", "TEST_OTP", "TEST_CREDENTIAL", "TEST_DATA").getResponseObject(); - CombinedAuthenticationResponse r2 = nextStepClient.authenticateCombined("TEST_CREDENTIAL", "test_user_1", "secret", r1.getOtpId(), r1.getOtpValue()).getResponseObject(); + CombinedAuthenticationResponse r2 = nextStepClient.authenticateCombined("test_user_1", "secret", r1.getOtpId(), r1.getOtpValue()).getResponseObject(); assertEquals(AuthenticationResult.FAILED, r2.getAuthenticationResult()); assertEquals(AuthenticationResult.FAILED, r2.getCredentialAuthenticationResult()); assertEquals(AuthenticationResult.SUCCEEDED, r2.getOtpAuthenticationResult()); @@ -309,7 +309,7 @@ public void testCredentialAndOtpFailNoOperation1() throws NextStepClientExceptio @Test public void testCredentialAndOtpFailNoOperation2() throws NextStepClientException { CreateOtpResponse r1 = nextStepClient.createOtp("test_user_1", "TEST_OTP", "TEST_CREDENTIAL", "TEST_DATA").getResponseObject(); - CombinedAuthenticationResponse r2 = nextStepClient.authenticateCombined("TEST_CREDENTIAL", "test_user_1", "s3cret", r1.getOtpId(), "0000000000").getResponseObject(); + CombinedAuthenticationResponse r2 = nextStepClient.authenticateCombined("test_user_1", "s3cret", r1.getOtpId(), "0000000000").getResponseObject(); assertEquals(AuthenticationResult.FAILED, r2.getAuthenticationResult()); assertEquals(AuthenticationResult.SUCCEEDED, r2.getCredentialAuthenticationResult()); assertEquals(AuthenticationResult.FAILED, r2.getOtpAuthenticationResult()); @@ -319,7 +319,7 @@ public void testCredentialAndOtpFailNoOperation2() throws NextStepClientExceptio public void testCredentialAndOtpFailWithOperation1() throws NextStepClientException { nextStepClient.createOperation("auth_otp", "test_operation_9a", "A1", null, null); CreateOtpResponse r1 = nextStepClient.createOtp("test_user_1", "TEST_OTP", "TEST_CREDENTIAL", "TEST_DATA", "test_operation_9a").getResponseObject(); - CombinedAuthenticationResponse r2 = nextStepClient.authenticateCombined("TEST_CREDENTIAL", "test_user_1", "secret", r1.getOtpId(), "test_operation_9a", r1.getOtpValue(), true, null).getResponseObject(); + CombinedAuthenticationResponse r2 = nextStepClient.authenticateCombined("test_user_1", "secret", r1.getOtpId(), "test_operation_9a", r1.getOtpValue(), true, null).getResponseObject(); assertEquals(AuthenticationResult.FAILED, r2.getAuthenticationResult()); assertEquals(AuthenticationResult.FAILED, r2.getCredentialAuthenticationResult()); assertEquals(AuthenticationResult.SUCCEEDED, r2.getOtpAuthenticationResult()); @@ -331,7 +331,7 @@ public void testCredentialAndOtpFailWithOperation1() throws NextStepClientExcept public void testCredentialAndOtpFailWithOperation2() throws NextStepClientException { nextStepClient.createOperation("auth_otp", "test_operation_9b", "A1", null, null); CreateOtpResponse r1 = nextStepClient.createOtp("test_user_1", "TEST_OTP", "TEST_CREDENTIAL", "TEST_DATA", "test_operation_9b").getResponseObject(); - CombinedAuthenticationResponse r2 = nextStepClient.authenticateCombined("TEST_CREDENTIAL", "test_user_1", "s3cret", r1.getOtpId(), "test_operation_9b", "0000000000", true, null).getResponseObject(); + CombinedAuthenticationResponse r2 = nextStepClient.authenticateCombined("test_user_1", "s3cret", r1.getOtpId(), "test_operation_9b", "0000000000", true, null).getResponseObject(); assertEquals(AuthenticationResult.FAILED, r2.getAuthenticationResult()); assertEquals(AuthenticationResult.SUCCEEDED, r2.getCredentialAuthenticationResult()); assertEquals(AuthenticationResult.FAILED, r2.getOtpAuthenticationResult()); @@ -416,9 +416,9 @@ public void testCredentialVerifyBlockedUser() throws NextStepClientException { @Test public void testOtpAndCredentialVerifyBlockedUser() throws NextStepClientException { - CreateOtpResponse r1 = nextStepClient.createOtp("test_user_1", "TEST_OTP", null, "TEST_DATA").getResponseObject(); + CreateOtpResponse r1 = nextStepClient.createOtp("test_user_1", "TEST_OTP", "TEST_CREDENTIAL", "TEST_DATA").getResponseObject(); nextStepClient.blockUser("test_user_1"); - CombinedAuthenticationResponse r2 = nextStepClient.authenticateCombined("TEST_CREDENTIAL", "test_user_1", "s3cret", r1.getOtpId(), r1.getOtpValue()).getResponseObject(); + CombinedAuthenticationResponse r2 = nextStepClient.authenticateCombined("test_user_1", "s3cret", r1.getOtpId(), r1.getOtpValue()).getResponseObject(); assertEquals(UserIdentityStatus.BLOCKED, r2.getUserIdentityStatus()); assertEquals(AuthenticationResult.FAILED, r2.getAuthenticationResult()); assertEquals(AuthenticationResult.FAILED, r2.getOtpAuthenticationResult()); @@ -534,7 +534,7 @@ public void testOperationMaxAuthFailsCombined() throws NextStepClientException { nextStepClient.createOperation("auth_otp", "test_operation_11", "A1", null, null); for (int i = 0; i < 4; i++) { nextStepClient.createOtp("test_user_1", "TEST_OTP", "TEST_CREDENTIAL", "TEST_DATA", "test_operation_11"); - CombinedAuthenticationResponse r1 = nextStepClient.authenticateCombined("TEST_CREDENTIAL", "test_user_1", "secret", null, "test_operation_11", "0000000000", true, null).getResponseObject(); + CombinedAuthenticationResponse r1 = nextStepClient.authenticateCombined("test_user_1", "secret", null, "test_operation_11", "0000000000", true, null).getResponseObject(); assertEquals(AuthenticationResult.FAILED, r1.getAuthenticationResult()); if (i < 3) { // 2 attempts for OTP, 2 attempts for credential @@ -549,7 +549,7 @@ public void testOperationMaxAuthFailsCombined() throws NextStepClientException { nextStepClient.updateCredentialCounter("test_user_1", "TEST_CREDENTIAL", AuthenticationResult.SUCCEEDED); } // Operation status changes to FAILED due to 5th failed attempt - CombinedAuthenticationResponse r1 = nextStepClient.authenticateCombined("TEST_CREDENTIAL", "test_user_1", "secret", null, "test_operation_11", "0000000000", true, null).getResponseObject(); + CombinedAuthenticationResponse r1 = nextStepClient.authenticateCombined("test_user_1", "secret", null, "test_operation_11", "0000000000", true, null).getResponseObject(); assertEquals(0, (int) r1.getRemainingAttempts()); assertTrue(r1.isOperationFailed()); assertEquals(AuthenticationResult.FAILED, r1.getAuthenticationResult()); diff --git a/powerauth-webflow-authentication-sms/src/main/java/io/getlime/security/powerauth/lib/webflow/authentication/sms/controller/SmsAuthorizationController.java b/powerauth-webflow-authentication-sms/src/main/java/io/getlime/security/powerauth/lib/webflow/authentication/sms/controller/SmsAuthorizationController.java index 6b42c46f6..5012b8c89 100644 --- a/powerauth-webflow-authentication-sms/src/main/java/io/getlime/security/powerauth/lib/webflow/authentication/sms/controller/SmsAuthorizationController.java +++ b/powerauth-webflow-authentication-sms/src/main/java/io/getlime/security/powerauth/lib/webflow/authentication/sms/controller/SmsAuthorizationController.java @@ -137,7 +137,6 @@ protected AuthResultDetail authenticate(SmsAuthorizationRequest request) throws final String otpId = getOtpIdFromHttpSession(); GetOrganizationDetailResponse organization = nextStepClient.getOrganizationDetail(operation.getOrganizationId()).getResponseObject(); String otpName = organization.getDefaultOtpName(); - String credentialName = organization.getDefaultCredentialName(); if (otpName == null) { logger.warn("Default OTP name is not configured for organization: " + operation.getOrganizationId()); throw new AuthStepException("SMS delivery failed", "error.communication"); @@ -217,7 +216,7 @@ protected AuthResultDetail authenticate(SmsAuthorizationRequest request) throws } String protectedPassword = passwordProtection.protect(request.getPassword()); - CombinedAuthenticationResponse authResponse = nextStepClient.authenticateCombined(credentialName, userId, protectedPassword, otpId, operationId, authCode, true, authMethod).getResponseObject(); + CombinedAuthenticationResponse authResponse = nextStepClient.authenticateCombined(userId, protectedPassword, otpId, operationId, authCode, true, authMethod).getResponseObject(); if (authResponse.isOperationFailed()) { logger.info("Step authentication maximum attempts reached for credential and OTP verification (2FA) due to failed operation, operation ID: {}, authentication method: {}", operation.getOperationId(), authMethod); throw new MaxAttemptsExceededException("Maximum number of authentication attempts exceeded");