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 issue in recovery V2 /confirm API for EXTERNAL channel #770

Merged
merged 3 commits into from
Oct 10, 2023
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
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
Loading