Skip to content

Commit

Permalink
Merge pull request #770 from Rashmini/recovery-v2
Browse files Browse the repository at this point in the history
Fix issue in recovery V2 /confirm API for EXTERNAL channel
  • Loading branch information
Rashmini authored Oct 10, 2023
2 parents 3a8726e + 6e6aa31 commit e46aef6
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 26 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -295,8 +295,8 @@ public PasswordResetCodeDTO confirm(String otp, String confirmationCode, String
IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_INVALID_RECOVERY_CODE.getCode(),
IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_INVALID_CODE.getMessage(), code);
} catch (IdentityRecoveryException e) {
/* This is a fallback logic to support already initiated email link based recovery flows using the
recovery V1 API, which do not have recovery flow ids. */
/* This is a fallback logic to support already initiated email link based recovery flows and EXTERNAL
channel based recovery flows using the recovery V1 API, which do not have recovery flow ids. */
return validateConfirmationCode(userAccountRecoveryManager, recoveryFlowId, tenantDomain);
}
}
Expand Down Expand Up @@ -893,9 +893,9 @@ private boolean isMinNoOfRecoveryQuestionsAnswered(String username, String tenan

/**
* This method is to validate the confirmation code when there's no recovery flow id. This is added as a fallback
* logic to handle the already initiated email link based recovery flows which do not have recovery flow ids,
* which were initiated before moving to the Recovery V2 API. This shouldn't be used for any other purpose and
* should be kept for sometime.
* logic to handle the already initiated email link based recovery flows and EXTERNAL channel based recovery flows
* which do not have recovery flow ids, which were initiated before moving to the Recovery V2 API.
* This shouldn't be used for any other purpose and should be kept for sometime.
*
* @param userAccountRecoveryManager UserAccountRecoveryManager.
* @param confirmationCode Confirmation code.
Expand All @@ -910,17 +910,26 @@ private PasswordResetCodeDTO validateConfirmationCode(UserAccountRecoveryManager

UserRecoveryData userRecoveryData;
try {
userRecoveryData = userAccountRecoveryManager.getUserRecoveryData(confirmationCode,
String hashedConfirmationCode = Utils.hashCode(confirmationCode);
userRecoveryData = userAccountRecoveryManager.getUserRecoveryData(hashedConfirmationCode,
RecoverySteps.UPDATE_PASSWORD);
} catch (NoSuchAlgorithmException e) {
throw Utils.handleServerException(
IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_NO_HASHING_ALGO_FOR_CODE, null);
} catch (IdentityRecoveryException e) {
if (IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_INVALID_RECOVERY_CODE.getCode().equals(
e.getErrorCode())) {
e.setErrorCode(IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_INVALID_RECOVERY_FLOW_ID.getCode());
try {
userRecoveryData = userAccountRecoveryManager.getUserRecoveryData(confirmationCode,
RecoverySteps.UPDATE_PASSWORD);
} catch (IdentityRecoveryException ex) {
if (IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_INVALID_RECOVERY_CODE.getCode().equals(
ex.getErrorCode())) {
ex.setErrorCode(IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_INVALID_RECOVERY_FLOW_ID.getCode());
}
throw ex;
}
throw e;
}
if (!StringUtils.equals(userRecoveryData.getRemainingSetIds(),
NotificationChannels.EMAIL_CHANNEL.getChannelType())) {
if (!(NotificationChannels.EMAIL_CHANNEL.getChannelType().equals(userRecoveryData.getRemainingSetIds()) ||
NotificationChannels.EXTERNAL_CHANNEL.getChannelType().equals(userRecoveryData.getRemainingSetIds()))) {
throw Utils.handleClientException(
IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_INVALID_RECOVERY_FLOW_ID, confirmationCode);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -715,8 +715,8 @@ public User updateUserPassword(String code, String confirmationCode, String pass
IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_INVALID_CODE.getMessage(), code);
}
} catch (IdentityRecoveryException e) {
/* This is a fallback logic to support already initiated email link based recovery flows using the
recovery V1 API, which do not have recovery flow ids. */
/* This is a fallback logic to support already initiated email link based recovery flows and EXTERNAL
channel based recovery flows using the recovery V1 API, which do not have recovery flow ids. */
userRecoveryData = validateUserRecoveryDataFromCode(code, confirmationCode, password, properties);
}

Expand Down Expand Up @@ -785,9 +785,9 @@ public User updateUserPassword(String code, String confirmationCode, String pass

/**
* This method is to validate user recovery data using the reset code when there's no recovery flow id.
* This is added as a fallback logic to handle the already initiated email link based recovery flows which do not
* have recovery flow ids, which were initiated before moving to the Recovery V2 API.
* This shouldn't be used for any other purpose and should be kept for sometime.
* This is added as a fallback logic to handle the already initiated email link based recovery flows and EXTERNAL
* channel based recovery flows which do not have recovery flow ids, which were initiated before moving to the
* Recovery V2 API. This shouldn't be used for any other purpose and should be kept for sometime.
*
* @param code Password Reset code.
* @param confirmationCode Confirmation code.
Expand All @@ -803,16 +803,26 @@ private UserRecoveryData validateUserRecoveryDataFromCode(String code, String co
UserRecoveryData userRecoveryData;
UserAccountRecoveryManager userAccountRecoveryManager = UserAccountRecoveryManager.getInstance();
try {
userRecoveryData = userAccountRecoveryManager.getUserRecoveryData(code, RecoverySteps.UPDATE_PASSWORD);
String hashedCode = Utils.hashCode(code);
userRecoveryData = userAccountRecoveryManager.getUserRecoveryData(hashedCode,
RecoverySteps.UPDATE_PASSWORD);
} catch (NoSuchAlgorithmException e) {
throw Utils.handleServerException(
IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_NO_HASHING_ALGO_FOR_CODE, null);
} catch (IdentityRecoveryException e) {
if (IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_INVALID_RECOVERY_CODE.getCode().equals(
e.getErrorCode())) {
e.setErrorCode(IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_INVALID_RECOVERY_FLOW_ID.getCode());
try {
userRecoveryData = userAccountRecoveryManager.getUserRecoveryData(code,
RecoverySteps.UPDATE_PASSWORD);
} catch (IdentityRecoveryException ex) {
if (IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_INVALID_RECOVERY_CODE.getCode().equals(
ex.getErrorCode())) {
ex.setErrorCode(IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_INVALID_RECOVERY_FLOW_ID.getCode());
}
throw ex;
}
throw e;
}
if (!StringUtils.equals(userRecoveryData.getRemainingSetIds(),
NotificationChannels.EMAIL_CHANNEL.getChannelType())) {
if (!(NotificationChannels.EMAIL_CHANNEL.getChannelType().equals(userRecoveryData.getRemainingSetIds()) ||
NotificationChannels.EXTERNAL_CHANNEL.getChannelType().equals(userRecoveryData.getRemainingSetIds()))) {
throw Utils.handleClientException(
IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_INVALID_RECOVERY_FLOW_ID, confirmationCode);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1204,8 +1204,8 @@ public static String generateSecretKey(String channel, String tenantDomain, Stri
*/
public static String concatRecoveryFlowIdWithSecretKey(String recoveryFlowId, String notificationChannel,
String secretKey) {
if (recoveryFlowId != null && StringUtils.equals(notificationChannel,
NotificationChannels.EMAIL_CHANNEL.getChannelType())) {
if (recoveryFlowId != null && (NotificationChannels.EMAIL_CHANNEL.getChannelType().equals(notificationChannel)
|| NotificationChannels.EXTERNAL_CHANNEL.getChannelType().equals(notificationChannel))) {
secretKey = recoveryFlowId + IdentityRecoveryConstants.CONFIRMATION_CODE_SEPARATOR + secretKey;
}
return secretKey;
Expand Down

0 comments on commit e46aef6

Please sign in to comment.