Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix #1636: For API /auth/combinded assert credentialName #1637

Merged
merged 7 commits into from
May 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/Migration-Instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
1 change: 0 additions & 1 deletion docs/Next-Step-Server-REST-API-Reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -8823,7 +8823,6 @@ The list of expected status codes:
```json
{
"requestObject": {
"credentialName": "RETAIL_CREDENTIAL",
"userId": "test1234",
"credentialValue": ")wOI6ijUkwYI",
"authenticationMode": "MATCH_EXACT",
Expand Down
10 changes: 10 additions & 0 deletions docs/Web-Flow-1.8.0.md
Original file line number Diff line number Diff line change
@@ -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.
Original file line number Diff line number Diff line change
Expand Up @@ -2416,18 +2416,16 @@ public ObjectResponse<CredentialAuthenticationResponse> authenticateWithCredenti
/**
* Authenticate using credential and OTP without operation.
*
* @param credentialName Credential name.
* @param userId User ID.
* @param credentialValue Credential value.
* @param otpId OTP ID.
* @param otpValue OTP value.
* @return OTP authentication response.
* @throws NextStepClientException Thrown when REST API call fails, including {@link ErrorResponse} with error code.
*/
public ObjectResponse<CombinedAuthenticationResponse> authenticateCombined(@NotNull String credentialName, @NotNull String userId, @NotNull String credentialValue,
public ObjectResponse<CombinedAuthenticationResponse> 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);
Expand All @@ -2438,7 +2436,6 @@ public ObjectResponse<CombinedAuthenticationResponse> 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.
Expand All @@ -2448,11 +2445,10 @@ public ObjectResponse<CombinedAuthenticationResponse> authenticateCombined(@NotN
* @return OTP authentication response.
* @throws NextStepClientException Thrown when REST API call fails, including {@link ErrorResponse} with error code.
*/
public ObjectResponse<CombinedAuthenticationResponse> authenticateCombined(@NotNull String credentialName, @NotNull String userId, @NotNull String credentialValue,
public ObjectResponse<CombinedAuthenticationResponse> authenticateCombined(@NotNull String userId, @NotNull String credentialValue,
CredentialAuthenticationMode authenticationMode, List<Integer> 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);
Expand All @@ -2465,7 +2461,6 @@ public ObjectResponse<CombinedAuthenticationResponse> 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.
Expand All @@ -2476,11 +2471,10 @@ public ObjectResponse<CombinedAuthenticationResponse> authenticateCombined(@NotN
* @return OTP authentication response.
* @throws NextStepClientException Thrown when REST API call fails, including {@link ErrorResponse} with error code.
*/
public ObjectResponse<CombinedAuthenticationResponse> authenticateCombined(@NotNull String credentialName, @NotNull String userId, @NotNull String credentialValue,
public ObjectResponse<CombinedAuthenticationResponse> 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);
Expand All @@ -2494,7 +2488,6 @@ public ObjectResponse<CombinedAuthenticationResponse> 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.
Expand All @@ -2507,12 +2500,11 @@ public ObjectResponse<CombinedAuthenticationResponse> authenticateCombined(@NotN
* @return OTP authentication response.
* @throws NextStepClientException Thrown when REST API call fails, including {@link ErrorResponse} with error code.
*/
public ObjectResponse<CombinedAuthenticationResponse> authenticateCombined(@NotNull String credentialName, @NotNull String userId, @NotNull String credentialValue,
public ObjectResponse<CombinedAuthenticationResponse> authenticateCombined(@NotNull String userId, @NotNull String credentialValue,
CredentialAuthenticationMode authenticationMode, List<Integer> 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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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());
Expand All @@ -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();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -283,15 +283,15 @@ 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());
}

@Test
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());
Expand All @@ -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());
Expand All @@ -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());
Expand All @@ -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());
Expand All @@ -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());
Expand Down Expand Up @@ -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());
Expand Down Expand Up @@ -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
Expand All @@ -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());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down Expand Up @@ -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");
Expand Down
Loading