diff --git a/components/org.wso2.carbon.identity.recovery/src/main/java/org/wso2/carbon/identity/recovery/internal/service/impl/password/PasswordRecoveryManagerImpl.java b/components/org.wso2.carbon.identity.recovery/src/main/java/org/wso2/carbon/identity/recovery/internal/service/impl/password/PasswordRecoveryManagerImpl.java index 0ae64b3092..0b1eb93bad 100644 --- a/components/org.wso2.carbon.identity.recovery/src/main/java/org/wso2/carbon/identity/recovery/internal/service/impl/password/PasswordRecoveryManagerImpl.java +++ b/components/org.wso2.carbon.identity.recovery/src/main/java/org/wso2/carbon/identity/recovery/internal/service/impl/password/PasswordRecoveryManagerImpl.java @@ -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); } } @@ -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. @@ -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); } diff --git a/components/org.wso2.carbon.identity.recovery/src/main/java/org/wso2/carbon/identity/recovery/password/NotificationPasswordRecoveryManager.java b/components/org.wso2.carbon.identity.recovery/src/main/java/org/wso2/carbon/identity/recovery/password/NotificationPasswordRecoveryManager.java index 196811355a..8ff31ae33d 100644 --- a/components/org.wso2.carbon.identity.recovery/src/main/java/org/wso2/carbon/identity/recovery/password/NotificationPasswordRecoveryManager.java +++ b/components/org.wso2.carbon.identity.recovery/src/main/java/org/wso2/carbon/identity/recovery/password/NotificationPasswordRecoveryManager.java @@ -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); } @@ -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. @@ -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); } diff --git a/components/org.wso2.carbon.identity.recovery/src/main/java/org/wso2/carbon/identity/recovery/util/Utils.java b/components/org.wso2.carbon.identity.recovery/src/main/java/org/wso2/carbon/identity/recovery/util/Utils.java index 36692ba562..43a4d57e6e 100644 --- a/components/org.wso2.carbon.identity.recovery/src/main/java/org/wso2/carbon/identity/recovery/util/Utils.java +++ b/components/org.wso2.carbon.identity.recovery/src/main/java/org/wso2/carbon/identity/recovery/util/Utils.java @@ -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;