From 62868f70320206342f62062ddc7a6fd9aa15d083 Mon Sep 17 00:00:00 2001 From: Dilshani Haputhanthri Date: Tue, 6 Sep 2022 09:12:58 +0530 Subject: [PATCH 1/6] Add feature to send OTPs in e-mail verifications. --- .../governance/IdentityMgtConstants.java | 14 +++ .../internal/IdentityMgtServiceComponent.java | 5 +- .../service/impl/otp/DefaultOTPGenerator.java | 5 +- .../service/impl/otp/OTPGeneratorImpl.java | 112 ++++++++++++++++++ .../recovery/IdentityRecoveryConstants.java | 41 +++++++ .../ResendConfirmationManager.java | 39 +++++- .../connector/LiteRegistrationConfigImpl.java | 101 +++++++++++++--- .../connector/RecoveryConfigImpl.java | 96 ++++++++++++--- .../connector/SelfRegistrationConfigImpl.java | 101 +++++++++++++--- .../connector/UserClaimUpdateConfigImpl.java | 103 ++++++++++++++++ .../UserEmailVerificationConfigImpl.java | 82 +++++++++++++ .../handler/LiteUserRegistrationHandler.java | 4 +- .../MobileNumberVerificationHandler.java | 3 +- .../handler/UserEmailVerificationHandler.java | 21 +++- .../handler/UserSelfRegistrationHandler.java | 4 +- .../NotificationPasswordRecoveryManager.java | 4 +- .../signup/UserSelfRegistrationManager.java | 6 +- .../carbon/identity/recovery/util/Utils.java | 54 +++++++++ .../connector/RecoveryConfigImplTest.java | 51 ++++++-- .../SelfRegistrationConfigImplTest.java | 53 +++++++-- .../UserClaimUpdateConfigImplTest.java | 34 +++++- .../UserEmailVerificationConfigImplTest.java | 42 +++++++ 22 files changed, 885 insertions(+), 90 deletions(-) create mode 100644 components/org.wso2.carbon.identity.governance/src/main/java/org/wso2/carbon/identity/governance/internal/service/impl/otp/OTPGeneratorImpl.java diff --git a/components/org.wso2.carbon.identity.governance/src/main/java/org/wso2/carbon/identity/governance/IdentityMgtConstants.java b/components/org.wso2.carbon.identity.governance/src/main/java/org/wso2/carbon/identity/governance/IdentityMgtConstants.java index 323790e06b..e4e4520854 100644 --- a/components/org.wso2.carbon.identity.governance/src/main/java/org/wso2/carbon/identity/governance/IdentityMgtConstants.java +++ b/components/org.wso2.carbon.identity.governance/src/main/java/org/wso2/carbon/identity/governance/IdentityMgtConstants.java @@ -222,4 +222,18 @@ private AccountStates() { } } + + /** + * OTP generator constants. + */ + public static class OTPGeneratorConstants { + + public static final int OTP_CODE_DEFAULT_LENGTH = 6; + public static final int OTP_CODE_MIN_LENGTH = 4; + public static final int OTP_CODE_MAX_LENGTH = 10; + public static final String OTP_GENERATE_ALPHABET_CHAR_SET_UPPERCASE = "ABCDEFGHJKLMNPRSTUVWXYZ"; + public static final String OTP_GENERATE_ALPHABET_CHAR_SET_LOWERCASE = "abcdefghjkmnpqrstuvwxyz"; + public static final String OTP_GENERATE_NUMERIC_CHAR_SET_WITH_ZERO = "0123456789"; + public static final String OTP_GENERATE_NUMERIC_CHAR_SET_WITHOUT_ZERO = "123456789"; + } } diff --git a/components/org.wso2.carbon.identity.governance/src/main/java/org/wso2/carbon/identity/governance/internal/IdentityMgtServiceComponent.java b/components/org.wso2.carbon.identity.governance/src/main/java/org/wso2/carbon/identity/governance/internal/IdentityMgtServiceComponent.java index 5790ba4a81..b4d1fed8ab 100644 --- a/components/org.wso2.carbon.identity.governance/src/main/java/org/wso2/carbon/identity/governance/internal/IdentityMgtServiceComponent.java +++ b/components/org.wso2.carbon.identity.governance/src/main/java/org/wso2/carbon/identity/governance/internal/IdentityMgtServiceComponent.java @@ -33,6 +33,7 @@ import org.wso2.carbon.identity.governance.common.IdentityConnectorConfig; import org.wso2.carbon.identity.governance.internal.service.impl.notification.DefaultNotificationChannelManager; import org.wso2.carbon.identity.governance.internal.service.impl.otp.DefaultOTPGenerator; +import org.wso2.carbon.identity.governance.internal.service.impl.otp.OTPGeneratorImpl; import org.wso2.carbon.identity.governance.service.notification.NotificationChannelManager; import org.wso2.carbon.identity.governance.listener.IdentityMgtEventListener; import org.wso2.carbon.identity.governance.listener.IdentityStoreEventListener; @@ -64,9 +65,9 @@ protected void activate(ComponentContext context) { new DefaultNotificationChannelManager(); context.getBundleContext() .registerService(NotificationChannelManager.class.getName(), defaultNotificationChannelManager, null); - DefaultOTPGenerator defaultOtpGenerator = new DefaultOTPGenerator(); + OTPGeneratorImpl otpGeneratorImpl = new OTPGeneratorImpl(); context.getBundleContext() - .registerService(OTPGenerator.class.getName(), defaultOtpGenerator, null); + .registerService(OTPGenerator.class.getName(), otpGeneratorImpl, null); if (log.isDebugEnabled()) { log.debug("Identity Management Listener is enabled"); diff --git a/components/org.wso2.carbon.identity.governance/src/main/java/org/wso2/carbon/identity/governance/internal/service/impl/otp/DefaultOTPGenerator.java b/components/org.wso2.carbon.identity.governance/src/main/java/org/wso2/carbon/identity/governance/internal/service/impl/otp/DefaultOTPGenerator.java index 4269892d04..45fde1c40e 100644 --- a/components/org.wso2.carbon.identity.governance/src/main/java/org/wso2/carbon/identity/governance/internal/service/impl/otp/DefaultOTPGenerator.java +++ b/components/org.wso2.carbon.identity.governance/src/main/java/org/wso2/carbon/identity/governance/internal/service/impl/otp/DefaultOTPGenerator.java @@ -26,8 +26,11 @@ import java.security.SecureRandom; /** - * Default class to generate OTP. + * @deprecated + * {@link org.wso2.carbon.identity.governance.internal.service.impl.otp.OTPGeneratorImpl + * This class is deprecated and OTPGeneratorImpl has been introduced as alternative. */ +@Deprecated public class DefaultOTPGenerator implements OTPGenerator { private static final String SMS_OTP_GENERATE_ALPHABET_CHAR_SET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; diff --git a/components/org.wso2.carbon.identity.governance/src/main/java/org/wso2/carbon/identity/governance/internal/service/impl/otp/OTPGeneratorImpl.java b/components/org.wso2.carbon.identity.governance/src/main/java/org/wso2/carbon/identity/governance/internal/service/impl/otp/OTPGeneratorImpl.java new file mode 100644 index 0000000000..16921d52fa --- /dev/null +++ b/components/org.wso2.carbon.identity.governance/src/main/java/org/wso2/carbon/identity/governance/internal/service/impl/otp/OTPGeneratorImpl.java @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2022, WSO2 LLC. (http://www.wso2.com). + * + * WSO2 LLC. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.wso2.carbon.identity.governance.internal.service.impl.otp; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.wso2.carbon.identity.governance.IdentityMgtConstants; +import org.wso2.carbon.identity.governance.service.otp.OTPGenerator; + +import java.security.SecureRandom; + +/** + * Default class to generate OTP. + */ +public class OTPGeneratorImpl implements OTPGenerator { + + private static final Log log = LogFactory.getLog(OTPGeneratorImpl.class); + private static final String OTP_GENERATOR_IMPL = "OTPGeneratorImpl"; + + /** + * Generate the OTP according to given length and pattern. If pattern is not defined default pattern will be used. + * Default pattern is to use all three type characters (uppercase characters, lowercase characters and numerics). + * + * @param useUppercaseLetters Whether uppercase characters should be used for OTP. + * @param useLowercaseLetters Whether lowercase characters should be used for OTP. + * @param useNumeric Whether numeric characters should be used for OTP. + * @param otpLength OTP length. + * @param recoveryScenario Recovery scenario. + * @return Secret key. + */ + @Override + public String generateOTP(boolean useNumeric, boolean useUppercaseLetters, boolean useLowercaseLetters, + int otpLength, String recoveryScenario) { + + if (otpLength < IdentityMgtConstants.OTPGeneratorConstants.OTP_CODE_MIN_LENGTH || + otpLength > IdentityMgtConstants.OTPGeneratorConstants.OTP_CODE_MAX_LENGTH) { + otpLength = IdentityMgtConstants.OTPGeneratorConstants.OTP_CODE_DEFAULT_LENGTH; + if (log.isDebugEnabled()) { + log.debug("Configured OTP length is not in the range of " + + IdentityMgtConstants.OTPGeneratorConstants.OTP_CODE_MIN_LENGTH + "-" + + IdentityMgtConstants.OTPGeneratorConstants.OTP_CODE_MAX_LENGTH + ". Hence using default length for OTP"); + } + } + StringBuilder charSet = new StringBuilder(); + if (!useNumeric && !useUppercaseLetters && !useLowercaseLetters) { + charSet.append(IdentityMgtConstants.OTPGeneratorConstants.OTP_GENERATE_ALPHABET_CHAR_SET_UPPERCASE); + charSet.append(IdentityMgtConstants.OTPGeneratorConstants.OTP_GENERATE_ALPHABET_CHAR_SET_LOWERCASE); + charSet.append(IdentityMgtConstants.OTPGeneratorConstants.OTP_GENERATE_NUMERIC_CHAR_SET_WITHOUT_ZERO); + return generateOTP(charSet.toString(), otpLength, recoveryScenario); + } + if (useUppercaseLetters) { + charSet.append(IdentityMgtConstants.OTPGeneratorConstants.OTP_GENERATE_ALPHABET_CHAR_SET_UPPERCASE); + } + if (useLowercaseLetters) { + charSet.append(IdentityMgtConstants.OTPGeneratorConstants.OTP_GENERATE_ALPHABET_CHAR_SET_LOWERCASE); + } + if (useNumeric) { + if (useUppercaseLetters || useLowercaseLetters) { + charSet.append(IdentityMgtConstants.OTPGeneratorConstants.OTP_GENERATE_NUMERIC_CHAR_SET_WITHOUT_ZERO); + } else { + charSet.append(IdentityMgtConstants.OTPGeneratorConstants.OTP_GENERATE_NUMERIC_CHAR_SET_WITH_ZERO); + } + + } + return generateOTP(charSet.toString(), otpLength, recoveryScenario); + } + + /** + * Generates the OTP based on the provided charSet and length. + * + * @param charSet Character set allowed for OTP. + * @param otpLength Length of OTP. + * @param recoveryScenario Recovery Scenario. + * @return Value of OTP string. + */ + @Override + public String generateOTP(String charSet, int otpLength, String recoveryScenario) { + + SecureRandom secureRandom = new SecureRandom(); + StringBuilder stringBuilder = new StringBuilder(); + char[] otpCharacters = charSet.toCharArray(); + for (int otpCharacterIndex = 0; otpCharacterIndex < otpLength; otpCharacterIndex++) { + stringBuilder.append(otpCharacters[secureRandom.nextInt(otpCharacters.length)]); + } + return stringBuilder.toString(); + } + + /** + * Retrieve the OTP Generator name. + */ + @Override + public String getOTPGeneratorName() { + + return OTP_GENERATOR_IMPL; + } +} diff --git a/components/org.wso2.carbon.identity.recovery/src/main/java/org/wso2/carbon/identity/recovery/IdentityRecoveryConstants.java b/components/org.wso2.carbon.identity.recovery/src/main/java/org/wso2/carbon/identity/recovery/IdentityRecoveryConstants.java index 3b29b93a10..e081d9d280 100644 --- a/components/org.wso2.carbon.identity.recovery/src/main/java/org/wso2/carbon/identity/recovery/IdentityRecoveryConstants.java +++ b/components/org.wso2.carbon.identity.recovery/src/main/java/org/wso2/carbon/identity/recovery/IdentityRecoveryConstants.java @@ -161,6 +161,7 @@ public class IdentityRecoveryConstants { public static final String USER_ACCOUNT_RECOVERY = "UAR"; public static final int SMS_OTP_CODE_LENGTH = 6; + public static final int OTP_CODE_DEFAULT_LENGTH = 6; public static final String ENABLE_DETAILED_ERROR_RESPONSE = "Recovery.ErrorMessage.EnableDetailedErrorMessages"; // Recovery code given at the username and password recovery initiation. public static final int RECOVERY_CODE_DEFAULT_EXPIRY_TIME = 1; @@ -495,6 +496,14 @@ public static class ConnectorConfig { public static final String RECOVERY_CODE_EXPIRY_TIME = "Recovery.Notification.ExpiryTime.RecoveryCode"; public static final String ENABLE_ACCOUNT_LOCK_FOR_VERIFIED_PREFERRED_CHANNEL = "SelfRegistration.EnableAccountLockForVerifiedPreferredChannel"; + public static final String PASSWORD_RECOVERY_SEND_OTP_IN_EMAIL = "Recovery.Notification.Password.OTP.SendOTPInEmail"; + public static final String PASSWORD_RECOVERY_USE_UPPERCASE_CHARACTERS_IN_OTP = "Recovery.Notification.Password." + + "OTP.UseUppercaseCharactersInOTP"; + public static final String PASSWORD_RECOVERY_USE_LOWERCASE_CHARACTERS_IN_OTP = "Recovery.Notification.Password." + + "OTP.UseLowercaseCharactersInOTP"; + public static final String PASSWORD_RECOVERY_USE_NUMBERS_IN_OTP = "Recovery.Notification.Password.OTP." + + "UseNumbersInOTP"; + public static final String PASSWORD_RECOVERY_OTP_LENGTH = "Recovery.Notification.Password.OTP.OTPLength"; public static final String NOTIFICATION_INTERNALLY_MANAGE = "Recovery.Notification.InternallyManage"; public static final String NOTIFY_USER_EXISTENCE = "Recovery.NotifyUserExistence"; public static final String NOTIFY_USER_ACCOUNT_STATUS = "Recovery.NotifyUserAccountStatus"; @@ -515,6 +524,14 @@ public static class ConnectorConfig { public static final String RECOVERY_CALLBACK_REGEX = "Recovery.CallbackRegex"; public static final String ENABLE_SELF_SIGNUP = "SelfRegistration.Enable"; public static final String ACCOUNT_LOCK_ON_CREATION = "SelfRegistration.LockOnCreation"; + public static final String SELF_REGISTRATION_SEND_OTP_IN_EMAIL = "SelfRegistration.OTP.SendOTPInEmail"; + public static final String SELF_REGISTRATION_USE_UPPERCASE_CHARACTERS_IN_OTP = "SelfRegistration.OTP." + + "UseUppercaseCharactersInOTP"; + public static final String SELF_REGISTRATION_USE_LOWERCASE_CHARACTERS_IN_OTP = "SelfRegistration.OTP." + + "UseLowercaseCharactersInOTP"; + public static final String SELF_REGISTRATION_USE_NUMBERS_IN_OTP = "SelfRegistration.OTP." + + "UseNumbersInOTP"; + public static final String SELF_REGISTRATION_OTP_LENGTH = "SelfRegistration.OTP.OTPLength"; public static final String SEND_CONFIRMATION_NOTIFICATION = "SelfRegistration.SendConfirmationOnCreation"; public static final String SIGN_UP_NOTIFICATION_INTERNALLY_MANAGE = "SelfRegistration.Notification" + ".InternallyManage"; @@ -532,6 +549,14 @@ public static class ConnectorConfig { public static final String ENABLE_LITE_SIGN_UP = "LiteRegistration.Enable"; public static final String LITE_ACCOUNT_LOCK_ON_CREATION = "LiteRegistration.LockOnCreation"; //if passwordless + public static final String LITE_REGISTRATION_SEND_OTP_IN_EMAIL = "LiteRegistration.OTP.SendOTPInEmail"; + public static final String LITE_REGISTRATION_USE_UPPERCASE_CHARACTERS_IN_OTP = "LiteRegistration.OTP." + + "UseUppercaseCharactersInOTP"; + public static final String LITE_REGISTRATION_USE_LOWERCASE_CHARACTERS_IN_OTP = "LiteRegistration.OTP." + + "UseLowercaseCharactersInOTP"; + public static final String LITE_REGISTRATION_USE_NUMBERS_IN_OTP = "LiteRegistration.OTP." + + "UseNumbersInOTP"; + public static final String LITE_REGISTRATION_OTP_LENGTH = "LiteRegistration.OTP.OTPLength"; public static final String LITE_SIGN_UP_NOTIFICATION_INTERNALLY_MANAGE = "LiteRegistration.Notification" + ".InternallyManage"; public static final String LITE_REGISTRATION_RE_CAPTCHA = "LiteRegistration.ReCaptcha"; @@ -544,9 +569,25 @@ public static class ConnectorConfig { "LiteRegistration.VerificationCode.SMSOTP.ExpiryTime"; public static final String ENABLE_EMAIL_VERIFICATION = "EmailVerification.Enable"; + public static final String EMAIL_VERIFICATION_SEND_OTP_IN_EMAIL = "EmailVerification.OTP.SendOTPInEmail"; + public static final String EMAIL_VERIFICATION_USE_UPPERCASE_CHARACTERS_IN_OTP = "EmailVerification.OTP." + + "UseUppercaseCharactersInOTP"; + public static final String EMAIL_VERIFICATION_USE_LOWERCASE_CHARACTERS_IN_OTP = "EmailVerification.OTP." + + "UseLowercaseCharactersInOTP"; + public static final String EMAIL_VERIFICATION_USE_NUMBERS_IN_OTP = "EmailVerification.OTP." + + "UseNumbersInOTP"; + public static final String EMAIL_VERIFICATION_OTP_LENGTH = "EmailVerification.OTP.OTPLength"; public static final String EMAIL_VERIFICATION_EXPIRY_TIME = "EmailVerification.ExpiryTime"; public static final String ENABLE_EMAIL_VERIFICATION_ON_UPDATE = "UserClaimUpdate.Email." + "EnableVerification"; + public static final String EMAIL_VERIFICATION_ON_UPDATE_SEND_OTP_IN_EMAIL = "UserClaimUpdate.OTP.SendOTPInEmail"; + public static final String EMAIL_VERIFICATION_ON_UPDATE_USE_UPPERCASE_CHARACTERS_IN_OTP = "UserClaimUpdate." + + "OTP.UseUppercaseCharactersInOTP"; + public static final String EMAIL_VERIFICATION_ON_UPDATE_USE_LOWERCASE_CHARACTERS_IN_OTP = "UserClaimUpdate." + + "OTP.UseLowercaseCharactersInOTP"; + public static final String EMAIL_VERIFICATION_ON_UPDATE_USE_NUMBERS_IN_OTP = "UserClaimUpdate." + + "OTP.UseNumbersInOTP"; + public static final String EMAIL_VERIFICATION_ON_UPDATE_OTP_LENGTH = "UserClaimUpdate.OTP.OTPLength"; public static final String EMAIL_VERIFICATION_ON_UPDATE_EXPIRY_TIME = "UserClaimUpdate.Email.VerificationCode" + ".ExpiryTime"; public static final String ENABLE_NOTIFICATION_ON_EMAIL_UPDATE = "UserClaimUpdate.Email.EnableNotification"; diff --git a/components/org.wso2.carbon.identity.recovery/src/main/java/org/wso2/carbon/identity/recovery/confirmation/ResendConfirmationManager.java b/components/org.wso2.carbon.identity.recovery/src/main/java/org/wso2/carbon/identity/recovery/confirmation/ResendConfirmationManager.java index ebd7e5160c..486702ed21 100644 --- a/components/org.wso2.carbon.identity.recovery/src/main/java/org/wso2/carbon/identity/recovery/confirmation/ResendConfirmationManager.java +++ b/components/org.wso2.carbon.identity.recovery/src/main/java/org/wso2/carbon/identity/recovery/confirmation/ResendConfirmationManager.java @@ -163,7 +163,7 @@ public ResendConfirmationDTO resendConfirmation(String tenantDomain, String rese confirmationCode = confirmationCodeRecoveryData.getSecret(); } else { userRecoveryDataStore.invalidate(user); - confirmationCode = Utils.generateSecretKey(notificationChannel, user.getTenantDomain(), recoveryScenario); + confirmationCode = getSecretKey(notificationChannel, recoveryScenario, tenantDomain); // Store new confirmation code. addRecoveryDataObject(confirmationCode, notificationChannel, scenario, step, user); } @@ -441,6 +441,9 @@ private NotificationResponseBean resendAccountRecoveryNotification(User user, St preferredChannel = NotificationChannels.EXTERNAL_CHANNEL.getChannelType(); } } + if (RecoveryScenarios.EMAIL_VERIFICATION_ON_UPDATE.toString().equals(recoveryScenario)) { + preferredChannel = NotificationChannels.EMAIL_CHANNEL.getChannelType(); + } if (RecoveryScenarios.MOBILE_VERIFICATION_ON_UPDATE.toString().equals(recoveryScenario)) { preferredChannel = NotificationChannels.SMS_CHANNEL.getChannelType(); } @@ -451,7 +454,7 @@ private NotificationResponseBean resendAccountRecoveryNotification(User user, St } else { // Invalid previous confirmation code. userRecoveryDataStore.invalidate(userRecoveryData.getSecret()); - secretKey = Utils.generateSecretKey(preferredChannel, user.getTenantDomain(), recoveryScenario); + secretKey = getSecretKey(preferredChannel, recoveryScenario, user.getTenantDomain()); UserRecoveryData recoveryDataDO = new UserRecoveryData(user, secretKey, RecoveryScenarios .getRecoveryScenario(recoveryScenario), RecoverySteps.getRecoveryStep(recoveryStep)); /* Notified channel is stored in remaining setIds for recovery purposes. Having a EMPTY preferred channel @@ -656,4 +659,36 @@ private void validateWithOldConfirmationCode(String code, String recoveryScenari IdentityRecoveryConstants.ErrorMessages.ERROR_CODE_PROVIDED_CONFIRMATION_CODE_NOT_VALID, code); } } + + private String getSecretKey(String preferredChannel, String recoveryScenario, String tenantDomain) + throws IdentityRecoveryException { + + try { + switch (RecoveryScenarios.getRecoveryScenario(recoveryScenario)) { + case SELF_SIGN_UP: + return Utils.generateSecretKey(preferredChannel, recoveryScenario, tenantDomain, + "SelfRegistration"); + case NOTIFICATION_BASED_PW_RECOVERY: + return Utils.generateSecretKey(preferredChannel, recoveryScenario, tenantDomain, + "Recovery.Notification.Password"); + case EMAIL_VERIFICATION_ON_UPDATE: + case MOBILE_VERIFICATION_ON_UPDATE: + return Utils.generateSecretKey(preferredChannel, recoveryScenario, tenantDomain, + "UserClaimUpdate"); + case ASK_PASSWORD: + return Utils.generateSecretKey(preferredChannel, recoveryScenario, tenantDomain, + "EmailVerification"); + case LITE_SIGN_UP: + return Utils.generateSecretKey(preferredChannel, recoveryScenario, tenantDomain, + "LiteRegistration"); + default: + return Utils.generateSecretKey(preferredChannel, recoveryScenario, tenantDomain, + null); + } + } catch (IdentityRecoveryClientException identityRecoveryClientException) { + throw new IdentityRecoveryException(identityRecoveryClientException.getErrorCode(), + identityRecoveryClientException.getMessage()); + } + + } } diff --git a/components/org.wso2.carbon.identity.recovery/src/main/java/org/wso2/carbon/identity/recovery/connector/LiteRegistrationConfigImpl.java b/components/org.wso2.carbon.identity.recovery/src/main/java/org/wso2/carbon/identity/recovery/connector/LiteRegistrationConfigImpl.java index 3ec177915b..9caeef354f 100644 --- a/components/org.wso2.carbon.identity.recovery/src/main/java/org/wso2/carbon/identity/recovery/connector/LiteRegistrationConfigImpl.java +++ b/components/org.wso2.carbon.identity.recovery/src/main/java/org/wso2/carbon/identity/recovery/connector/LiteRegistrationConfigImpl.java @@ -87,6 +87,16 @@ public Map getPropertyNameMapping() { nameMapping.put(IdentityRecoveryConstants.ConnectorConfig.ENABLE_LITE_SIGN_UP, "Lite user registration"); nameMapping.put(IdentityRecoveryConstants.ConnectorConfig.LITE_ACCOUNT_LOCK_ON_CREATION, "Lock user account on creation"); + nameMapping.put(IdentityRecoveryConstants.ConnectorConfig.LITE_REGISTRATION_SEND_OTP_IN_EMAIL, + "Send OTP in e-mail"); + nameMapping.put(IdentityRecoveryConstants.ConnectorConfig.LITE_REGISTRATION_USE_UPPERCASE_CHARACTERS_IN_OTP, + "Include uppercase characters in OTP"); + nameMapping.put(IdentityRecoveryConstants.ConnectorConfig.LITE_REGISTRATION_USE_LOWERCASE_CHARACTERS_IN_OTP, + "Include lowercase characters in OTP"); + nameMapping.put(IdentityRecoveryConstants.ConnectorConfig.LITE_REGISTRATION_USE_NUMBERS_IN_OTP, + "Include numbers in OTP"); + nameMapping.put(IdentityRecoveryConstants.ConnectorConfig.LITE_REGISTRATION_OTP_LENGTH, + "OTP length"); nameMapping.put(IdentityRecoveryConstants.ConnectorConfig.LITE_SIGN_UP_NOTIFICATION_INTERNALLY_MANAGE, "Manage notifications sending internally"); nameMapping.put(IdentityRecoveryConstants.ConnectorConfig.LITE_REGISTRATION_RE_CAPTCHA, "Prompt reCaptcha"); @@ -95,8 +105,6 @@ public Map getPropertyNameMapping() { nameMapping .put(IdentityRecoveryConstants.ConnectorConfig.LITE_REGISTRATION_SMSOTP_VERIFICATION_CODE_EXPIRY_TIME, "Lite user registration SMS OTP expiry time"); - nameMapping.put(IdentityRecoveryConstants.ConnectorConfig.LITE_REGISTRATION_SMS_OTP_REGEX, - "Lite user registration SMS OTP regex"); nameMapping.put(IdentityRecoveryConstants.ConnectorConfig.LITE_REGISTRATION_CALLBACK_REGEX, "Lite user registration callback URL regex"); nameMapping.put(LIST_PURPOSE_PROPERTY_KEY, "Manage Lite-Sign-Up purposes"); @@ -111,6 +119,18 @@ public Map getPropertyDescriptionMapping() { "Allow user's to self register to the system without a password."); descriptionMapping.put(IdentityRecoveryConstants.ConnectorConfig.LITE_ACCOUNT_LOCK_ON_CREATION, "Lock self registered user account until e-mail verification."); + descriptionMapping.put(IdentityRecoveryConstants.ConnectorConfig.LITE_REGISTRATION_SEND_OTP_IN_EMAIL, + "Enable to send OTP in verification e-mail instead of confirmation code."); + descriptionMapping.put( + IdentityRecoveryConstants.ConnectorConfig.LITE_REGISTRATION_USE_UPPERCASE_CHARACTERS_IN_OTP, + "Enable to include uppercase characters in SMS and e-mail OTPs."); + descriptionMapping.put( + IdentityRecoveryConstants.ConnectorConfig.LITE_REGISTRATION_USE_LOWERCASE_CHARACTERS_IN_OTP, + "Enable to include lowercase characters in SMS and e-mail OTPs."); + descriptionMapping.put(IdentityRecoveryConstants.ConnectorConfig.LITE_REGISTRATION_USE_NUMBERS_IN_OTP, + "Enable to include numbers in SMS and e-mail OTPs."); + descriptionMapping.put(IdentityRecoveryConstants.ConnectorConfig.LITE_REGISTRATION_OTP_LENGTH, + "Length of the OTP for SMS and e-mail verifications. OTP length must be 4-10."); descriptionMapping.put(IdentityRecoveryConstants.ConnectorConfig.LITE_SIGN_UP_NOTIFICATION_INTERNALLY_MANAGE, "Disable if the client application handles notification sending"); descriptionMapping.put(IdentityRecoveryConstants.ConnectorConfig.LITE_REGISTRATION_RE_CAPTCHA, @@ -121,10 +141,6 @@ public Map getPropertyDescriptionMapping() { descriptionMapping.put( IdentityRecoveryConstants.ConnectorConfig.LITE_REGISTRATION_SMSOTP_VERIFICATION_CODE_EXPIRY_TIME, "Specify the expiry time in minutes for the SMS OTP."); - descriptionMapping.put(IdentityRecoveryConstants.ConnectorConfig.LITE_REGISTRATION_SMS_OTP_REGEX, - "Regex for SMS OTP in format [allowed characters]{length}. Supported character " + - "ranges are a-z, A-Z, 0-9. Minimum OTP length is " + - IdentityMgtConstants.MINIMUM_SMS_OTP_LENGTH); descriptionMapping.put(IdentityRecoveryConstants.ConnectorConfig.LITE_REGISTRATION_CALLBACK_REGEX, "This prefix will be used to validate the callback URL."); descriptionMapping.put(LIST_PURPOSE_PROPERTY_KEY, "Click here to manage Lite-Sign-Up purposes"); @@ -137,12 +153,16 @@ public String[] getPropertyNames() { List properties = new ArrayList<>(); properties.add(IdentityRecoveryConstants.ConnectorConfig.ENABLE_LITE_SIGN_UP); properties.add(IdentityRecoveryConstants.ConnectorConfig.LITE_ACCOUNT_LOCK_ON_CREATION); + properties.add(IdentityRecoveryConstants.ConnectorConfig.LITE_REGISTRATION_SEND_OTP_IN_EMAIL); + properties.add(IdentityRecoveryConstants.ConnectorConfig.LITE_REGISTRATION_USE_UPPERCASE_CHARACTERS_IN_OTP); + properties.add(IdentityRecoveryConstants.ConnectorConfig.LITE_REGISTRATION_USE_LOWERCASE_CHARACTERS_IN_OTP); + properties.add(IdentityRecoveryConstants.ConnectorConfig.LITE_REGISTRATION_USE_NUMBERS_IN_OTP); + properties.add(IdentityRecoveryConstants.ConnectorConfig.LITE_REGISTRATION_OTP_LENGTH); properties.add(IdentityRecoveryConstants.ConnectorConfig.LITE_SIGN_UP_NOTIFICATION_INTERNALLY_MANAGE); properties.add(IdentityRecoveryConstants.ConnectorConfig.LITE_REGISTRATION_RE_CAPTCHA); properties.add(IdentityRecoveryConstants.ConnectorConfig.LITE_REGISTRATION_VERIFICATION_CODE_EXPIRY_TIME); properties .add(IdentityRecoveryConstants.ConnectorConfig.LITE_REGISTRATION_SMSOTP_VERIFICATION_CODE_EXPIRY_TIME); - properties.add(IdentityRecoveryConstants.ConnectorConfig.LITE_REGISTRATION_SMS_OTP_REGEX); properties.add(IdentityRecoveryConstants.ConnectorConfig.LITE_REGISTRATION_CALLBACK_REGEX); properties.add(LIST_PURPOSE_PROPERTY_KEY); return properties.toArray(new String[0]); @@ -153,17 +173,31 @@ public Properties getDefaultPropertyValues(String tenantDomain) throws IdentityG String enableLiteSignUp = "false"; String enableAccountLockOnCreation = "true"; + String enableSendOTPInEmail = "false"; + String useUppercaseCharactersInOTP = "true"; + String useLowercaseCharactersInOTP = "true"; + String useNumbersInOTP = "true"; + String otpLength = "6"; String enableNotificationInternallyManage = "true"; String enableLiteRegistrationReCaptcha = "true"; String verificationCodeExpiryTime = "1440"; String verificationSMSOTPExpiryTime = "1"; - String verificationSMSOTPRegex = "[a-zA-Z0-9]{6}"; String liteRegistrationCallbackRegex = IdentityRecoveryConstants.DEFAULT_CALLBACK_REGEX; String liteSignUpProperty = IdentityUtil.getProperty( IdentityRecoveryConstants.ConnectorConfig.ENABLE_LITE_SIGN_UP); String accountLockProperty = IdentityUtil.getProperty( IdentityRecoveryConstants.ConnectorConfig.LITE_ACCOUNT_LOCK_ON_CREATION); + String sendOTPInEmailProperty = IdentityUtil.getProperty( + IdentityRecoveryConstants.ConnectorConfig.LITE_REGISTRATION_SEND_OTP_IN_EMAIL); + String useUppercaseCharactersInOTPProperty = IdentityUtil.getProperty( + IdentityRecoveryConstants.ConnectorConfig.LITE_REGISTRATION_USE_UPPERCASE_CHARACTERS_IN_OTP); + String useLowercaseCharactersInOTPProperty = IdentityUtil.getProperty( + IdentityRecoveryConstants.ConnectorConfig.LITE_REGISTRATION_USE_LOWERCASE_CHARACTERS_IN_OTP); + String useNumbersInOTPProperty = IdentityUtil.getProperty( + IdentityRecoveryConstants.ConnectorConfig.LITE_REGISTRATION_USE_NUMBERS_IN_OTP); + String otpLengthProperty = IdentityUtil.getProperty( + IdentityRecoveryConstants.ConnectorConfig.LITE_REGISTRATION_OTP_LENGTH); String notificationInternallyMangedProperty = IdentityUtil.getProperty( IdentityRecoveryConstants.ConnectorConfig.LITE_SIGN_UP_NOTIFICATION_INTERNALLY_MANAGE); String reCaptchaProperty = IdentityUtil.getProperty( @@ -172,8 +206,6 @@ public Properties getDefaultPropertyValues(String tenantDomain) throws IdentityG IdentityRecoveryConstants.ConnectorConfig.LITE_REGISTRATION_VERIFICATION_CODE_EXPIRY_TIME); String verificationSMSOTPExpiryTimeProperty = IdentityUtil.getProperty( IdentityRecoveryConstants.ConnectorConfig.LITE_REGISTRATION_SMSOTP_VERIFICATION_CODE_EXPIRY_TIME); - String verificationSMSOTPRegexProperty = IdentityUtil.getProperty( - IdentityRecoveryConstants.ConnectorConfig.LITE_REGISTRATION_SMS_OTP_REGEX); String selfRegistrationCallbackRegexProperty = IdentityUtil.getProperty( IdentityRecoveryConstants.ConnectorConfig.LITE_REGISTRATION_CALLBACK_REGEX); @@ -183,6 +215,21 @@ public Properties getDefaultPropertyValues(String tenantDomain) throws IdentityG if (StringUtils.isNotEmpty(accountLockProperty)) { enableAccountLockOnCreation = accountLockProperty; } + if (StringUtils.isNotEmpty(sendOTPInEmailProperty)) { + enableSendOTPInEmail = sendOTPInEmailProperty; + } + if (StringUtils.isNotEmpty(useUppercaseCharactersInOTPProperty)) { + useUppercaseCharactersInOTP = useUppercaseCharactersInOTPProperty; + } + if (StringUtils.isNotEmpty(useLowercaseCharactersInOTPProperty)) { + useLowercaseCharactersInOTP = useLowercaseCharactersInOTPProperty; + } + if (StringUtils.isNotEmpty(useNumbersInOTPProperty)) { + useNumbersInOTP = useNumbersInOTPProperty; + } + if (StringUtils.isNotEmpty(otpLengthProperty)) { + otpLength = otpLengthProperty; + } if (StringUtils.isNotEmpty(notificationInternallyMangedProperty)) { enableNotificationInternallyManage = notificationInternallyMangedProperty; } @@ -195,9 +242,6 @@ public Properties getDefaultPropertyValues(String tenantDomain) throws IdentityG if (StringUtils.isNotEmpty(verificationSMSOTPExpiryTimeProperty)) { verificationSMSOTPExpiryTime = verificationSMSOTPExpiryTimeProperty; } - if (StringUtils.isNotEmpty(verificationSMSOTPRegexProperty)) { - verificationSMSOTPRegex = verificationSMSOTPRegexProperty; - } if (StringUtils.isNotEmpty(selfRegistrationCallbackRegexProperty)) { liteRegistrationCallbackRegex = selfRegistrationCallbackRegexProperty; } @@ -206,6 +250,16 @@ public Properties getDefaultPropertyValues(String tenantDomain) throws IdentityG defaultProperties.put(IdentityRecoveryConstants.ConnectorConfig.ENABLE_LITE_SIGN_UP, enableLiteSignUp); defaultProperties.put(IdentityRecoveryConstants.ConnectorConfig.LITE_ACCOUNT_LOCK_ON_CREATION, enableAccountLockOnCreation); + defaultProperties.put(IdentityRecoveryConstants.ConnectorConfig.LITE_REGISTRATION_SEND_OTP_IN_EMAIL, + enableSendOTPInEmail); + defaultProperties.put(IdentityRecoveryConstants.ConnectorConfig.LITE_REGISTRATION_USE_UPPERCASE_CHARACTERS_IN_OTP, + useUppercaseCharactersInOTP); + defaultProperties.put(IdentityRecoveryConstants.ConnectorConfig.LITE_REGISTRATION_USE_LOWERCASE_CHARACTERS_IN_OTP, + useLowercaseCharactersInOTP); + defaultProperties.put(IdentityRecoveryConstants.ConnectorConfig.LITE_REGISTRATION_USE_NUMBERS_IN_OTP, + useNumbersInOTP); + defaultProperties.put(IdentityRecoveryConstants.ConnectorConfig.LITE_REGISTRATION_OTP_LENGTH, + otpLength); defaultProperties.put(IdentityRecoveryConstants.ConnectorConfig.LITE_SIGN_UP_NOTIFICATION_INTERNALLY_MANAGE, enableNotificationInternallyManage); defaultProperties.put(IdentityRecoveryConstants.ConnectorConfig.LITE_REGISTRATION_RE_CAPTCHA, @@ -216,9 +270,6 @@ public Properties getDefaultPropertyValues(String tenantDomain) throws IdentityG defaultProperties .put(IdentityRecoveryConstants.ConnectorConfig.LITE_REGISTRATION_SMSOTP_VERIFICATION_CODE_EXPIRY_TIME, verificationSMSOTPExpiryTime); - defaultProperties - .put(IdentityRecoveryConstants.ConnectorConfig.LITE_REGISTRATION_SMS_OTP_REGEX, - verificationSMSOTPRegex); try { defaultProperties.put(LIST_PURPOSE_PROPERTY_KEY, consentListURL + "&callback=" + URLEncoder.encode (CALLBACK_URL, StandardCharsets.UTF_8.name())); @@ -251,6 +302,21 @@ public Map getMetaData() { meta.put(IdentityRecoveryConstants.ConnectorConfig.LITE_ACCOUNT_LOCK_ON_CREATION, getPropertyObject(IdentityMgtConstants.DataTypes.BOOLEAN.getValue())); + meta.put(IdentityRecoveryConstants.ConnectorConfig.LITE_REGISTRATION_SEND_OTP_IN_EMAIL, + getPropertyObject(IdentityMgtConstants.DataTypes.BOOLEAN.getValue())); + + meta.put(IdentityRecoveryConstants.ConnectorConfig.LITE_REGISTRATION_USE_UPPERCASE_CHARACTERS_IN_OTP, + getPropertyObject(IdentityMgtConstants.DataTypes.BOOLEAN.getValue())); + + meta.put(IdentityRecoveryConstants.ConnectorConfig.LITE_REGISTRATION_USE_LOWERCASE_CHARACTERS_IN_OTP, + getPropertyObject(IdentityMgtConstants.DataTypes.BOOLEAN.getValue())); + + meta.put(IdentityRecoveryConstants.ConnectorConfig.LITE_REGISTRATION_USE_NUMBERS_IN_OTP, + getPropertyObject(IdentityMgtConstants.DataTypes.BOOLEAN.getValue())); + + meta.put(IdentityRecoveryConstants.ConnectorConfig.LITE_REGISTRATION_OTP_LENGTH, + getPropertyObject(IdentityMgtConstants.DataTypes.STRING.getValue())); + meta.put(IdentityRecoveryConstants.ConnectorConfig.LITE_SIGN_UP_NOTIFICATION_INTERNALLY_MANAGE, getPropertyObject(IdentityMgtConstants.DataTypes.BOOLEAN.getValue())); @@ -263,9 +329,6 @@ public Map getMetaData() { meta.put(IdentityRecoveryConstants.ConnectorConfig.LITE_REGISTRATION_SMSOTP_VERIFICATION_CODE_EXPIRY_TIME, getPropertyObject(IdentityMgtConstants.DataTypes.INTEGER.getValue())); - meta.put(IdentityRecoveryConstants.ConnectorConfig.LITE_REGISTRATION_SMS_OTP_REGEX, - getPropertyObject(IdentityMgtConstants.DataTypes.STRING.getValue())); - meta.put(LIST_PURPOSE_PROPERTY_KEY, getPropertyObject(IdentityMgtConstants.DataTypes.URI.getValue())); meta.put(IdentityRecoveryConstants.ConnectorConfig.LITE_REGISTRATION_CALLBACK_REGEX, diff --git a/components/org.wso2.carbon.identity.recovery/src/main/java/org/wso2/carbon/identity/recovery/connector/RecoveryConfigImpl.java b/components/org.wso2.carbon.identity.recovery/src/main/java/org/wso2/carbon/identity/recovery/connector/RecoveryConfigImpl.java index 3286603bf9..8316d84c17 100644 --- a/components/org.wso2.carbon.identity.recovery/src/main/java/org/wso2/carbon/identity/recovery/connector/RecoveryConfigImpl.java +++ b/components/org.wso2.carbon.identity.recovery/src/main/java/org/wso2/carbon/identity/recovery/connector/RecoveryConfigImpl.java @@ -74,6 +74,16 @@ public Map getPropertyNameMapping() { Map nameMapping = new HashMap<>(); nameMapping.put(IdentityRecoveryConstants.ConnectorConfig.NOTIFICATION_BASED_PW_RECOVERY, "Notification based password recovery"); + nameMapping.put(IdentityRecoveryConstants.ConnectorConfig.PASSWORD_RECOVERY_SEND_OTP_IN_EMAIL, + "Send OTP in e-mail"); + nameMapping.put(IdentityRecoveryConstants.ConnectorConfig.PASSWORD_RECOVERY_USE_UPPERCASE_CHARACTERS_IN_OTP, + "Include uppercase characters in OTP"); + nameMapping.put(IdentityRecoveryConstants.ConnectorConfig.PASSWORD_RECOVERY_USE_LOWERCASE_CHARACTERS_IN_OTP, + "Include lowercase characters in OTP"); + nameMapping.put(IdentityRecoveryConstants.ConnectorConfig.PASSWORD_RECOVERY_USE_NUMBERS_IN_OTP, + "Include numbers in OTP"); + nameMapping.put(IdentityRecoveryConstants.ConnectorConfig.PASSWORD_RECOVERY_OTP_LENGTH, + "OTP length"); nameMapping.put(IdentityRecoveryConstants.ConnectorConfig.NOTIFICATION_INTERNALLY_MANAGE, "Manage notifications sending internally"); nameMapping.put(IdentityRecoveryConstants.ConnectorConfig.PASSWORD_RECOVERY_RECAPTCHA_ENABLE, @@ -92,8 +102,6 @@ public Map getPropertyNameMapping() { nameMapping.put(IdentityRecoveryConstants.ConnectorConfig.EXPIRY_TIME, "Recovery link expiry time in minutes"); nameMapping.put(IdentityRecoveryConstants.ConnectorConfig.PASSWORD_RECOVERY_SMS_OTP_EXPIRY_TIME, "SMS OTP expiry time"); - nameMapping.put(IdentityRecoveryConstants.ConnectorConfig.PASSWORD_RECOVERY_SMS_OTP_REGEX, "SMS OTP regex"); - nameMapping.put(IdentityRecoveryConstants.ConnectorConfig.NOTIFICATION_SEND_RECOVERY_NOTIFICATION_SUCCESS, "Notify when recovery success"); nameMapping.put(IdentityRecoveryConstants.ConnectorConfig.NOTIFICATION_SEND_RECOVERY_SECURITY_START, @@ -121,6 +129,18 @@ public Map getPropertyDescriptionMapping() { Map descriptionMapping = new HashMap<>(); descriptionMapping.put(IdentityRecoveryConstants.ConnectorConfig.NOTIFICATION_INTERNALLY_MANAGE, "Disable if the client application handles notification sending"); + descriptionMapping.put(IdentityRecoveryConstants.ConnectorConfig.PASSWORD_RECOVERY_SEND_OTP_IN_EMAIL, + "Enable to send OTP in verification e-mail instead of confirmation code."); + descriptionMapping.put( + IdentityRecoveryConstants.ConnectorConfig.PASSWORD_RECOVERY_USE_UPPERCASE_CHARACTERS_IN_OTP, + "Enable to include uppercase characters in SMS and e-mail OTPs."); + descriptionMapping.put( + IdentityRecoveryConstants.ConnectorConfig.PASSWORD_RECOVERY_USE_LOWERCASE_CHARACTERS_IN_OTP, + "Enable to include lowercase characters in SMS and e-mail OTPs."); + descriptionMapping.put(IdentityRecoveryConstants.ConnectorConfig.PASSWORD_RECOVERY_USE_NUMBERS_IN_OTP, + "Enable to include numbers in SMS and e-mail OTPs."); + descriptionMapping.put(IdentityRecoveryConstants.ConnectorConfig.PASSWORD_RECOVERY_OTP_LENGTH, + "Length of the OTP for SMS and e-mail verifications. OTP length must be 4-10."); descriptionMapping.put(IdentityRecoveryConstants.ConnectorConfig.CHALLENGE_QUESTION_ANSWER_REGEX, "Security question answer regex"); descriptionMapping.put(IdentityRecoveryConstants.ConnectorConfig.ENFORCE_CHALLENGE_QUESTION_ANSWER_UNIQUENESS, @@ -136,9 +156,6 @@ public Map getPropertyDescriptionMapping() { "Recovery callback URL regex"); descriptionMapping.put(IdentityRecoveryConstants.ConnectorConfig.PASSWORD_RECOVERY_SMS_OTP_EXPIRY_TIME, "Expiration time of the SMS OTP code for password recovery"); - descriptionMapping.put(IdentityRecoveryConstants.ConnectorConfig.PASSWORD_RECOVERY_SMS_OTP_REGEX, "Regex for " - + "SMS OTP in format [allowed characters]{length}. Supported character ranges are a-z, A-Z, 0-9. " + - "Minimum OTP length is " + IdentityMgtConstants.MINIMUM_SMS_OTP_LENGTH); descriptionMapping.put(IdentityRecoveryConstants.ConnectorConfig.ENABLE_AUTO_LGOIN_AFTER_PASSWORD_RESET, "User will be logged in automatically after completing the Password Reset wizard"); return descriptionMapping; @@ -149,6 +166,11 @@ public String[] getPropertyNames() { List properties = new ArrayList<>(); properties.add(IdentityRecoveryConstants.ConnectorConfig.NOTIFICATION_BASED_PW_RECOVERY); + properties.add(IdentityRecoveryConstants.ConnectorConfig.PASSWORD_RECOVERY_SEND_OTP_IN_EMAIL); + properties.add(IdentityRecoveryConstants.ConnectorConfig.PASSWORD_RECOVERY_USE_UPPERCASE_CHARACTERS_IN_OTP); + properties.add(IdentityRecoveryConstants.ConnectorConfig.PASSWORD_RECOVERY_USE_LOWERCASE_CHARACTERS_IN_OTP); + properties.add(IdentityRecoveryConstants.ConnectorConfig.PASSWORD_RECOVERY_USE_NUMBERS_IN_OTP); + properties.add(IdentityRecoveryConstants.ConnectorConfig.PASSWORD_RECOVERY_OTP_LENGTH); properties.add(IdentityRecoveryConstants.ConnectorConfig.PASSWORD_RECOVERY_RECAPTCHA_ENABLE); properties.add(IdentityRecoveryConstants.ConnectorConfig.QUESTION_BASED_PW_RECOVERY); properties.add(IdentityRecoveryConstants.ConnectorConfig.QUESTION_MIN_NO_ANSWER); @@ -163,7 +185,6 @@ public String[] getPropertyNames() { properties.add(IdentityRecoveryConstants.ConnectorConfig.NOTIFICATION_SEND_RECOVERY_SECURITY_START); properties.add(IdentityRecoveryConstants.ConnectorConfig.EXPIRY_TIME); properties.add(IdentityRecoveryConstants.ConnectorConfig.PASSWORD_RECOVERY_SMS_OTP_EXPIRY_TIME); - properties.add(IdentityRecoveryConstants.ConnectorConfig.PASSWORD_RECOVERY_SMS_OTP_REGEX); properties.add(IdentityRecoveryConstants.ConnectorConfig.FORCE_ADD_PW_RECOVERY_QUESTION); properties.add(IdentityRecoveryConstants.ConnectorConfig.FORCE_MIN_NO_QUESTION_ANSWERED); properties.add(IdentityRecoveryConstants.ConnectorConfig.RECOVERY_CALLBACK_REGEX); @@ -175,6 +196,11 @@ public String[] getPropertyNames() { public Properties getDefaultPropertyValues(String tenantDomain) throws IdentityGovernanceException { String enableNotificationBasedPasswordRecovery = "false"; + String enableSendOTPInEmail = "false"; + String useUppercaseCharactersInOTP = "true"; + String useLowercaseCharactersInOTP = "true"; + String useNumbersInOTP = "true"; + String otpLength = "6"; String enableQuestionBasedPasswordRecovery = "false"; String minimumAnswers = "2"; String challengeQuestionAnswerRegex = IdentityRecoveryConstants.DEFAULT_REGEX; @@ -185,7 +211,6 @@ public Properties getDefaultPropertyValues(String tenantDomain) throws IdentityG String enableNotificationInternallyManage = "true"; String expiryTime = "1440"; String expiryTimeSMSOTP = "1"; - String smsOtpRegex = "[a-zA-Z0-9]{6}"; String notifySuccess = "false"; String notifyStart = "false"; String enableForceChallengeQuestions = "false"; @@ -197,6 +222,16 @@ public Properties getDefaultPropertyValues(String tenantDomain) throws IdentityG String notificationBasedPasswordRecovery = IdentityUtil.getProperty( IdentityRecoveryConstants.ConnectorConfig.NOTIFICATION_BASED_PW_RECOVERY); + String sendOTPInEmailProperty = IdentityUtil.getProperty( + IdentityRecoveryConstants.ConnectorConfig.PASSWORD_RECOVERY_SEND_OTP_IN_EMAIL); + String useUppercaseCharactersInOTPProperty = IdentityUtil.getProperty( + IdentityRecoveryConstants.ConnectorConfig.PASSWORD_RECOVERY_USE_UPPERCASE_CHARACTERS_IN_OTP); + String useLowercaseCharactersInOTPProperty = IdentityUtil.getProperty( + IdentityRecoveryConstants.ConnectorConfig.PASSWORD_RECOVERY_USE_LOWERCASE_CHARACTERS_IN_OTP); + String useNumbersInOTPProperty = IdentityUtil.getProperty( + IdentityRecoveryConstants.ConnectorConfig.PASSWORD_RECOVERY_USE_NUMBERS_IN_OTP); + String otpLengthProperty = IdentityUtil.getProperty( + IdentityRecoveryConstants.ConnectorConfig.PASSWORD_RECOVERY_OTP_LENGTH); String questionBasedPasswordRecovery = IdentityUtil.getProperty( IdentityRecoveryConstants.ConnectorConfig.QUESTION_BASED_PW_RECOVERY); String miniMumAnswerProperty = IdentityUtil.getProperty( @@ -216,8 +251,6 @@ public Properties getDefaultPropertyValues(String tenantDomain) throws IdentityG String expiryTimeProperty = IdentityUtil.getProperty(IdentityRecoveryConstants.ConnectorConfig.EXPIRY_TIME); String expiryTimeSMSOTPProperty = IdentityUtil .getProperty(IdentityRecoveryConstants.ConnectorConfig.PASSWORD_RECOVERY_SMS_OTP_EXPIRY_TIME); - String smsOtpRegexProperty = IdentityUtil - .getProperty(IdentityRecoveryConstants.ConnectorConfig.PASSWORD_RECOVERY_SMS_OTP_REGEX); String notifySuccessProperty = IdentityUtil.getProperty( IdentityRecoveryConstants.ConnectorConfig.NOTIFICATION_SEND_RECOVERY_NOTIFICATION_SUCCESS); String notifyStartProperty = IdentityUtil.getProperty( @@ -238,12 +271,24 @@ public Properties getDefaultPropertyValues(String tenantDomain) throws IdentityG if (StringUtils.isNotEmpty(expiryTimeSMSOTPProperty)) { expiryTimeSMSOTP = expiryTimeSMSOTPProperty; } - if (StringUtils.isNotEmpty(smsOtpRegexProperty)) { - smsOtpRegex = smsOtpRegexProperty; - } if (StringUtils.isNotEmpty(notificationBasedPasswordRecovery)) { enableNotificationBasedPasswordRecovery = notificationBasedPasswordRecovery; } + if (StringUtils.isNotEmpty(sendOTPInEmailProperty)) { + enableSendOTPInEmail = sendOTPInEmailProperty; + } + if (StringUtils.isNotEmpty(useUppercaseCharactersInOTPProperty)) { + useUppercaseCharactersInOTP = useUppercaseCharactersInOTPProperty; + } + if (StringUtils.isNotEmpty(useLowercaseCharactersInOTPProperty)) { + useLowercaseCharactersInOTP = useLowercaseCharactersInOTPProperty; + } + if (StringUtils.isNotEmpty(useNumbersInOTPProperty)) { + useNumbersInOTP = useNumbersInOTPProperty; + } + if (StringUtils.isNotEmpty(otpLengthProperty)) { + otpLength = otpLengthProperty; + } if (StringUtils.isNotEmpty(questionBasedPasswordRecovery)) { enableQuestionBasedPasswordRecovery = questionBasedPasswordRecovery; } @@ -299,6 +344,16 @@ public Properties getDefaultPropertyValues(String tenantDomain) throws IdentityG Map defaultProperties = new HashMap<>(); defaultProperties.put(IdentityRecoveryConstants.ConnectorConfig.NOTIFICATION_BASED_PW_RECOVERY, enableNotificationBasedPasswordRecovery); + defaultProperties.put(IdentityRecoveryConstants.ConnectorConfig.PASSWORD_RECOVERY_SEND_OTP_IN_EMAIL, + enableSendOTPInEmail); + defaultProperties.put(IdentityRecoveryConstants.ConnectorConfig.PASSWORD_RECOVERY_USE_UPPERCASE_CHARACTERS_IN_OTP, + useUppercaseCharactersInOTP); + defaultProperties.put(IdentityRecoveryConstants.ConnectorConfig.PASSWORD_RECOVERY_USE_LOWERCASE_CHARACTERS_IN_OTP, + useLowercaseCharactersInOTP); + defaultProperties.put(IdentityRecoveryConstants.ConnectorConfig.PASSWORD_RECOVERY_USE_NUMBERS_IN_OTP, + useNumbersInOTP); + defaultProperties.put(IdentityRecoveryConstants.ConnectorConfig.PASSWORD_RECOVERY_OTP_LENGTH, + otpLength); defaultProperties.put(IdentityRecoveryConstants.ConnectorConfig.PASSWORD_RECOVERY_RECAPTCHA_ENABLE, enablePasswordRecoveryReCaptcha); defaultProperties.put(IdentityRecoveryConstants.ConnectorConfig.QUESTION_BASED_PW_RECOVERY, @@ -323,8 +378,6 @@ public Properties getDefaultPropertyValues(String tenantDomain) throws IdentityG defaultProperties.put(IdentityRecoveryConstants.ConnectorConfig.EXPIRY_TIME, expiryTime); defaultProperties .put(IdentityRecoveryConstants.ConnectorConfig.PASSWORD_RECOVERY_SMS_OTP_EXPIRY_TIME, expiryTimeSMSOTP); - defaultProperties - .put(IdentityRecoveryConstants.ConnectorConfig.PASSWORD_RECOVERY_SMS_OTP_REGEX, smsOtpRegex); defaultProperties.put(IdentityRecoveryConstants.ConnectorConfig.NOTIFICATION_SEND_RECOVERY_NOTIFICATION_SUCCESS, notifySuccess); defaultProperties.put(IdentityRecoveryConstants.ConnectorConfig.NOTIFICATION_SEND_RECOVERY_SECURITY_START, @@ -357,6 +410,21 @@ public Map getMetaData() { meta.put(IdentityRecoveryConstants.ConnectorConfig.NOTIFICATION_BASED_PW_RECOVERY, getPropertyObject(IdentityMgtConstants.DataTypes.BOOLEAN.getValue())); + meta.put(IdentityRecoveryConstants.ConnectorConfig.PASSWORD_RECOVERY_SEND_OTP_IN_EMAIL, + getPropertyObject(IdentityMgtConstants.DataTypes.BOOLEAN.getValue())); + + meta.put(IdentityRecoveryConstants.ConnectorConfig.PASSWORD_RECOVERY_USE_UPPERCASE_CHARACTERS_IN_OTP, + getPropertyObject(IdentityMgtConstants.DataTypes.BOOLEAN.getValue())); + + meta.put(IdentityRecoveryConstants.ConnectorConfig.PASSWORD_RECOVERY_USE_LOWERCASE_CHARACTERS_IN_OTP, + getPropertyObject(IdentityMgtConstants.DataTypes.BOOLEAN.getValue())); + + meta.put(IdentityRecoveryConstants.ConnectorConfig.PASSWORD_RECOVERY_USE_NUMBERS_IN_OTP, + getPropertyObject(IdentityMgtConstants.DataTypes.BOOLEAN.getValue())); + + meta.put(IdentityRecoveryConstants.ConnectorConfig.PASSWORD_RECOVERY_OTP_LENGTH, + getPropertyObject(IdentityMgtConstants.DataTypes.STRING.getValue())); + meta.put(IdentityRecoveryConstants.ConnectorConfig.PASSWORD_RECOVERY_RECAPTCHA_ENABLE, getPropertyObject(IdentityMgtConstants.DataTypes.BOOLEAN.getValue())); diff --git a/components/org.wso2.carbon.identity.recovery/src/main/java/org/wso2/carbon/identity/recovery/connector/SelfRegistrationConfigImpl.java b/components/org.wso2.carbon.identity.recovery/src/main/java/org/wso2/carbon/identity/recovery/connector/SelfRegistrationConfigImpl.java index 05ba6be45f..47f4f63df3 100644 --- a/components/org.wso2.carbon.identity.recovery/src/main/java/org/wso2/carbon/identity/recovery/connector/SelfRegistrationConfigImpl.java +++ b/components/org.wso2.carbon.identity.recovery/src/main/java/org/wso2/carbon/identity/recovery/connector/SelfRegistrationConfigImpl.java @@ -87,6 +87,16 @@ public Map getPropertyNameMapping() { nameMapping.put(IdentityRecoveryConstants.ConnectorConfig.ENABLE_SELF_SIGNUP, "User self registration"); nameMapping.put(IdentityRecoveryConstants.ConnectorConfig.ACCOUNT_LOCK_ON_CREATION, "Lock user account on creation"); + nameMapping.put(IdentityRecoveryConstants.ConnectorConfig.SELF_REGISTRATION_SEND_OTP_IN_EMAIL, + "Send OTP in e-mail"); + nameMapping.put(IdentityRecoveryConstants.ConnectorConfig.SELF_REGISTRATION_USE_UPPERCASE_CHARACTERS_IN_OTP, + "Include uppercase characters in OTP"); + nameMapping.put(IdentityRecoveryConstants.ConnectorConfig.SELF_REGISTRATION_USE_LOWERCASE_CHARACTERS_IN_OTP, + "Include lowercase characters in OTP"); + nameMapping.put(IdentityRecoveryConstants.ConnectorConfig.SELF_REGISTRATION_USE_NUMBERS_IN_OTP, + "Include numbers in OTP"); + nameMapping.put(IdentityRecoveryConstants.ConnectorConfig.SELF_REGISTRATION_OTP_LENGTH, + "OTP length"); nameMapping.put(IdentityRecoveryConstants.ConnectorConfig.SEND_CONFIRMATION_NOTIFICATION, "Enable Account Confirmation On Creation"); nameMapping.put(IdentityRecoveryConstants.ConnectorConfig.SIGN_UP_NOTIFICATION_INTERNALLY_MANAGE, @@ -96,8 +106,6 @@ public Map getPropertyNameMapping() { "User self registration verification link expiry time"); nameMapping.put(IdentityRecoveryConstants.ConnectorConfig.SELF_REGISTRATION_SMSOTP_VERIFICATION_CODE_EXPIRY_TIME, "User self registration SMS OTP expiry time"); - nameMapping.put(IdentityRecoveryConstants.ConnectorConfig.SELF_REGISTRATION_SMS_OTP_REGEX, - "User self registration SMS OTP regex"); nameMapping.put(IdentityRecoveryConstants.ConnectorConfig.SELF_REGISTRATION_CALLBACK_REGEX, "User self registration callback URL regex"); nameMapping.put(LIST_PURPOSE_PROPERTY_KEY, "Manage Self-Sign-Up purposes"); @@ -120,6 +128,18 @@ public Map getPropertyDescriptionMapping() { "Allow user's to self register to the system."); descriptionMapping.put(IdentityRecoveryConstants.ConnectorConfig.ACCOUNT_LOCK_ON_CREATION, "Lock self registered user account until e-mail verification."); + descriptionMapping.put(IdentityRecoveryConstants.ConnectorConfig.SELF_REGISTRATION_SEND_OTP_IN_EMAIL, + "Enable to send OTP in verification e-mail instead of confirmation code."); + descriptionMapping.put( + IdentityRecoveryConstants.ConnectorConfig.SELF_REGISTRATION_USE_UPPERCASE_CHARACTERS_IN_OTP, + "Enable to include uppercase characters in SMS and e-mail OTPs."); + descriptionMapping.put( + IdentityRecoveryConstants.ConnectorConfig.SELF_REGISTRATION_USE_LOWERCASE_CHARACTERS_IN_OTP, + "Enable to include lowercase characters in SMS and e-mail OTPs."); + descriptionMapping.put(IdentityRecoveryConstants.ConnectorConfig.SELF_REGISTRATION_USE_NUMBERS_IN_OTP, + "Enable to include numbers in SMS and e-mail OTPs."); + descriptionMapping.put(IdentityRecoveryConstants.ConnectorConfig.SELF_REGISTRATION_OTP_LENGTH, + "Length of the OTP for SMS and e-mail verifications. OTP length must be 4-10."); descriptionMapping.put(IdentityRecoveryConstants.ConnectorConfig.SEND_CONFIRMATION_NOTIFICATION, "Enable user account confirmation when the user account is not locked on creation"); descriptionMapping.put(IdentityRecoveryConstants.ConnectorConfig.SIGN_UP_NOTIFICATION_INTERNALLY_MANAGE, @@ -132,10 +152,6 @@ public Map getPropertyDescriptionMapping() { descriptionMapping.put( IdentityRecoveryConstants.ConnectorConfig.SELF_REGISTRATION_SMSOTP_VERIFICATION_CODE_EXPIRY_TIME, "Specify the expiry time in minutes for the SMS OTP."); - descriptionMapping.put(IdentityRecoveryConstants.ConnectorConfig.SELF_REGISTRATION_SMS_OTP_REGEX, - "Regex for SMS OTP in format [allowed characters]{length}. Supported character " + - "ranges are a-z, A-Z, 0-9. Minimum OTP length is " + - IdentityMgtConstants.MINIMUM_SMS_OTP_LENGTH); descriptionMapping.put(IdentityRecoveryConstants.ConnectorConfig.SELF_REGISTRATION_CALLBACK_REGEX, "This prefix will be used to validate the callback URL."); descriptionMapping.put(LIST_PURPOSE_PROPERTY_KEY, "Click here to manage Self-Sign-Up purposes"); @@ -156,13 +172,17 @@ public String[] getPropertyNames() { List properties = new ArrayList<>(); properties.add(IdentityRecoveryConstants.ConnectorConfig.ENABLE_SELF_SIGNUP); properties.add(IdentityRecoveryConstants.ConnectorConfig.ACCOUNT_LOCK_ON_CREATION); + properties.add(IdentityRecoveryConstants.ConnectorConfig.SELF_REGISTRATION_SEND_OTP_IN_EMAIL); + properties.add(IdentityRecoveryConstants.ConnectorConfig.SELF_REGISTRATION_USE_UPPERCASE_CHARACTERS_IN_OTP); + properties.add(IdentityRecoveryConstants.ConnectorConfig.SELF_REGISTRATION_USE_LOWERCASE_CHARACTERS_IN_OTP); + properties.add(IdentityRecoveryConstants.ConnectorConfig.SELF_REGISTRATION_USE_NUMBERS_IN_OTP); + properties.add(IdentityRecoveryConstants.ConnectorConfig.SELF_REGISTRATION_OTP_LENGTH); properties.add(IdentityRecoveryConstants.ConnectorConfig.SEND_CONFIRMATION_NOTIFICATION); properties.add(IdentityRecoveryConstants.ConnectorConfig.SIGN_UP_NOTIFICATION_INTERNALLY_MANAGE); properties.add(IdentityRecoveryConstants.ConnectorConfig.SELF_REGISTRATION_RE_CAPTCHA); properties.add(IdentityRecoveryConstants.ConnectorConfig.SELF_REGISTRATION_VERIFICATION_CODE_EXPIRY_TIME); properties .add(IdentityRecoveryConstants.ConnectorConfig.SELF_REGISTRATION_SMSOTP_VERIFICATION_CODE_EXPIRY_TIME); - properties.add(IdentityRecoveryConstants.ConnectorConfig.SELF_REGISTRATION_SMS_OTP_REGEX); properties.add(IdentityRecoveryConstants.ConnectorConfig.SELF_REGISTRATION_CALLBACK_REGEX); properties.add(LIST_PURPOSE_PROPERTY_KEY); properties.add(IdentityRecoveryConstants.ConnectorConfig.SELF_REGISTRATION_NOTIFY_ACCOUNT_CONFIRMATION); @@ -177,12 +197,16 @@ public Properties getDefaultPropertyValues(String tenantDomain) throws IdentityG String enableSelfSignUp = "false"; String enableAccountLockOnCreation = "true"; + String enableSendOTPInEmail = "false"; + String useUppercaseCharactersInOTP = "true"; + String useLowercaseCharactersInOTP = "true"; + String useNumbersInOTP = "true"; + String otpLength = "6"; String enableSendNotificationOnCreation = "false"; String enableNotificationInternallyManage = "true"; String enableSelfRegistrationReCaptcha = "true"; String verificationCodeExpiryTime = "1440"; String verificationSMSOTPExpiryTime = "1"; - String verificationSMSOTPRegex = "[a-zA-Z0-9]{6}"; String selfRegistrationCallbackRegex = IdentityRecoveryConstants.DEFAULT_CALLBACK_REGEX; String enableSelfSignUpConfirmationNotification = "false"; String enableResendConfirmationRecaptcha = "false"; @@ -193,6 +217,16 @@ public Properties getDefaultPropertyValues(String tenantDomain) throws IdentityG IdentityRecoveryConstants.ConnectorConfig.ENABLE_SELF_SIGNUP); String accountLockProperty = IdentityUtil.getProperty( IdentityRecoveryConstants.ConnectorConfig.ACCOUNT_LOCK_ON_CREATION); + String sendOTPInEmailProperty = IdentityUtil.getProperty( + IdentityRecoveryConstants.ConnectorConfig.SELF_REGISTRATION_SEND_OTP_IN_EMAIL); + String useUppercaseCharactersInOTPProperty = IdentityUtil.getProperty( + IdentityRecoveryConstants.ConnectorConfig.SELF_REGISTRATION_USE_UPPERCASE_CHARACTERS_IN_OTP); + String useLowercaseCharactersInOTPProperty = IdentityUtil.getProperty( + IdentityRecoveryConstants.ConnectorConfig.SELF_REGISTRATION_USE_LOWERCASE_CHARACTERS_IN_OTP); + String useNumbersInOTPProperty = IdentityUtil.getProperty( + IdentityRecoveryConstants.ConnectorConfig.SELF_REGISTRATION_USE_NUMBERS_IN_OTP); + String otpLengthProperty = IdentityUtil.getProperty( + IdentityRecoveryConstants.ConnectorConfig.SELF_REGISTRATION_OTP_LENGTH); String sendNotificationOnCreationProperty = IdentityUtil.getProperty( IdentityRecoveryConstants.ConnectorConfig.SEND_CONFIRMATION_NOTIFICATION); String notificationInternallyMangedProperty = IdentityUtil.getProperty( @@ -203,8 +237,6 @@ public Properties getDefaultPropertyValues(String tenantDomain) throws IdentityG IdentityRecoveryConstants.ConnectorConfig.SELF_REGISTRATION_VERIFICATION_CODE_EXPIRY_TIME); String verificationSMSOTPExpiryTimeProperty = IdentityUtil.getProperty( IdentityRecoveryConstants.ConnectorConfig.SELF_REGISTRATION_SMSOTP_VERIFICATION_CODE_EXPIRY_TIME); - String verificationSMSOTPRegexProperty = IdentityUtil.getProperty( - IdentityRecoveryConstants.ConnectorConfig.SELF_REGISTRATION_SMS_OTP_REGEX); String selfRegistrationCallbackRegexProperty = IdentityUtil.getProperty( IdentityRecoveryConstants.ConnectorConfig.SELF_REGISTRATION_CALLBACK_REGEX); String selfSignUpConfirmationNotificationProperty = IdentityUtil.getProperty( @@ -222,6 +254,21 @@ public Properties getDefaultPropertyValues(String tenantDomain) throws IdentityG if (StringUtils.isNotEmpty(accountLockProperty)) { enableAccountLockOnCreation = accountLockProperty; } + if (StringUtils.isNotEmpty(sendOTPInEmailProperty)) { + enableSendOTPInEmail = sendOTPInEmailProperty; + } + if (StringUtils.isNotEmpty(useUppercaseCharactersInOTPProperty)) { + useUppercaseCharactersInOTP = useUppercaseCharactersInOTPProperty; + } + if (StringUtils.isNotEmpty(useLowercaseCharactersInOTPProperty)) { + useLowercaseCharactersInOTP = useLowercaseCharactersInOTPProperty; + } + if (StringUtils.isNotEmpty(useNumbersInOTPProperty)) { + useNumbersInOTP = useNumbersInOTPProperty; + } + if (StringUtils.isNotEmpty(otpLengthProperty)) { + otpLength = otpLengthProperty; + } if (StringUtils.isNotEmpty(sendNotificationOnCreationProperty)) { enableSendNotificationOnCreation = sendNotificationOnCreationProperty; } @@ -237,9 +284,6 @@ public Properties getDefaultPropertyValues(String tenantDomain) throws IdentityG if (StringUtils.isNotEmpty(verificationSMSOTPExpiryTimeProperty)) { verificationSMSOTPExpiryTime = verificationSMSOTPExpiryTimeProperty; } - if (StringUtils.isNotEmpty(verificationSMSOTPRegexProperty)) { - verificationSMSOTPRegex = verificationSMSOTPRegexProperty; - } if (StringUtils.isNotEmpty(selfRegistrationCallbackRegexProperty)) { selfRegistrationCallbackRegex = selfRegistrationCallbackRegexProperty; } @@ -260,6 +304,16 @@ public Properties getDefaultPropertyValues(String tenantDomain) throws IdentityG defaultProperties.put(IdentityRecoveryConstants.ConnectorConfig.ENABLE_SELF_SIGNUP, enableSelfSignUp); defaultProperties.put(IdentityRecoveryConstants.ConnectorConfig.ACCOUNT_LOCK_ON_CREATION, enableAccountLockOnCreation); + defaultProperties.put(IdentityRecoveryConstants.ConnectorConfig.SELF_REGISTRATION_SEND_OTP_IN_EMAIL, + enableSendOTPInEmail); + defaultProperties.put(IdentityRecoveryConstants.ConnectorConfig.SELF_REGISTRATION_USE_UPPERCASE_CHARACTERS_IN_OTP, + useUppercaseCharactersInOTP); + defaultProperties.put(IdentityRecoveryConstants.ConnectorConfig.SELF_REGISTRATION_USE_LOWERCASE_CHARACTERS_IN_OTP, + useLowercaseCharactersInOTP); + defaultProperties.put(IdentityRecoveryConstants.ConnectorConfig.SELF_REGISTRATION_USE_NUMBERS_IN_OTP, + useNumbersInOTP); + defaultProperties.put(IdentityRecoveryConstants.ConnectorConfig.SELF_REGISTRATION_OTP_LENGTH, + otpLength); defaultProperties.put(IdentityRecoveryConstants.ConnectorConfig.SEND_CONFIRMATION_NOTIFICATION, enableSendNotificationOnCreation); defaultProperties.put(IdentityRecoveryConstants.ConnectorConfig.SIGN_UP_NOTIFICATION_INTERNALLY_MANAGE, @@ -272,9 +326,6 @@ public Properties getDefaultPropertyValues(String tenantDomain) throws IdentityG defaultProperties .put(IdentityRecoveryConstants.ConnectorConfig.SELF_REGISTRATION_SMSOTP_VERIFICATION_CODE_EXPIRY_TIME, verificationSMSOTPExpiryTime); - defaultProperties - .put(IdentityRecoveryConstants.ConnectorConfig.SELF_REGISTRATION_SMS_OTP_REGEX, - verificationSMSOTPRegex); defaultProperties.put(IdentityRecoveryConstants.ConnectorConfig.SELF_REGISTRATION_AUTO_LOGIN, enableSelfRegistrationAutoLogin); defaultProperties.put(IdentityRecoveryConstants.ConnectorConfig.SELF_REGISTRATION_AUTO_LOGIN_ALIAS_NAME, @@ -314,6 +365,21 @@ public Map getMetaData() { meta.put(IdentityRecoveryConstants.ConnectorConfig.ACCOUNT_LOCK_ON_CREATION, getPropertyObject(IdentityMgtConstants.DataTypes.BOOLEAN.getValue())); + meta.put(IdentityRecoveryConstants.ConnectorConfig.SELF_REGISTRATION_SEND_OTP_IN_EMAIL, + getPropertyObject(IdentityMgtConstants.DataTypes.BOOLEAN.getValue())); + + meta.put(IdentityRecoveryConstants.ConnectorConfig.SELF_REGISTRATION_USE_UPPERCASE_CHARACTERS_IN_OTP, + getPropertyObject(IdentityMgtConstants.DataTypes.BOOLEAN.getValue())); + + meta.put(IdentityRecoveryConstants.ConnectorConfig.SELF_REGISTRATION_USE_LOWERCASE_CHARACTERS_IN_OTP, + getPropertyObject(IdentityMgtConstants.DataTypes.BOOLEAN.getValue())); + + meta.put(IdentityRecoveryConstants.ConnectorConfig.SELF_REGISTRATION_USE_NUMBERS_IN_OTP, + getPropertyObject(IdentityMgtConstants.DataTypes.BOOLEAN.getValue())); + + meta.put(IdentityRecoveryConstants.ConnectorConfig.SELF_REGISTRATION_OTP_LENGTH, + getPropertyObject(IdentityMgtConstants.DataTypes.STRING.getValue())); + meta.put(IdentityRecoveryConstants.ConnectorConfig.SEND_CONFIRMATION_NOTIFICATION, getPropertyObject(IdentityMgtConstants.DataTypes.BOOLEAN.getValue())); @@ -329,9 +395,6 @@ public Map getMetaData() { meta.put(IdentityRecoveryConstants.ConnectorConfig.SELF_REGISTRATION_SMSOTP_VERIFICATION_CODE_EXPIRY_TIME, getPropertyObject(IdentityMgtConstants.DataTypes.INTEGER.getValue())); - meta.put(IdentityRecoveryConstants.ConnectorConfig.SELF_REGISTRATION_SMS_OTP_REGEX, - getPropertyObject(IdentityMgtConstants.DataTypes.STRING.getValue())); - meta.put(IdentityRecoveryConstants.ConnectorConfig.SELF_REGISTRATION_AUTO_LOGIN, getPropertyObject(IdentityMgtConstants.DataTypes.BOOLEAN.getValue())); diff --git a/components/org.wso2.carbon.identity.recovery/src/main/java/org/wso2/carbon/identity/recovery/connector/UserClaimUpdateConfigImpl.java b/components/org.wso2.carbon.identity.recovery/src/main/java/org/wso2/carbon/identity/recovery/connector/UserClaimUpdateConfigImpl.java index d3dfd2734b..ca899dc8ce 100644 --- a/components/org.wso2.carbon.identity.recovery/src/main/java/org/wso2/carbon/identity/recovery/connector/UserClaimUpdateConfigImpl.java +++ b/components/org.wso2.carbon.identity.recovery/src/main/java/org/wso2/carbon/identity/recovery/connector/UserClaimUpdateConfigImpl.java @@ -47,13 +47,24 @@ public class UserClaimUpdateConfigImpl implements IdentityConnectorConfig { private static final String SUB_CATEGORY = "DEFAULT"; private static final String DEFAULT_EMAIL_VERIFICATION_ON_UPDATE_CODE_EXPIRY_TIME = "1440"; private static final String DEFAULT_ENABLE_VALUE_FOR_EMAIL_VERIFICATION_ON_UPDATE = "false"; + private static final String DEFAULT_EMAIL_VERIFICATION_ON_UPDATE_SEND_OTP_IN_EMAIL = "false"; + private static final String DEFAULT_EMAIL_VERIFICATION_ON_UPDATE_USE_UPPERCASE_CHARACTERS_IN_OTP = "true"; + private static final String DEFAULT_EMAIL_VERIFICATION_ON_UPDATE_USE_LOWERCASE_CHARACTERS_IN_OTP = "true"; + private static final String DEFAULT_EMAIL_VERIFICATION_ON_UPDATE_USE_NUMBERS_IN_OTP = "true"; + private static final String DEFAULT_EMAIL_VERIFICATION_ON_UPDATE_OTP_LENGTH = "6"; private static final String DEFAULT_ENABLE_VALUE_FOR_EMAIL_NOTIFICATION_ON_UPDATE = "false"; private static final String DEFAULT_MOBILE_NUM_VERIFICATION_ON_UPDATE_SMS_OTP_EXPIRY_TIME = "5"; private static final String DEFAULT_ENABLE_VALUE_FOR_MOBILE_NUMBER_VERIFICATION_ON_UPDATE = "false"; private static final String DEFAULT_MOBILE_NUM_VERIFICATION_BY_PRIVILEGED_USERS = "false"; private static final String USER_CLAIM_UPDATE_ELEMENT = "UserClaimUpdate"; private static final String ENABLE_ELEMENT = "Enable"; + private static final String SEND_OTP_IN_EMAIL_ELEMENT = "SendOTPInEmail"; + private static final String USE_UPPERCASE_ELEMENT = "UseUppercaseInOtp"; + private static final String USE_LOWERCASE_ELEMENT = "UseLowercaseInOtp"; + private static final String USE_NUMERIC_ELEMENT = "UseNumericInOtp"; + private static final String OTP_LENGTH_ELEMENT = "OTPLength"; private static final String CLAIM_ELEMENT = "Claim"; + private static final String OTP_ELEMENT = "OTP"; private static final String CLAIM_URI = "uri"; private static final String VERIFICATION_CODE_ELEMENT = "VerificationCode"; private static final String EXPIRY_TIME_ELEMENT = "ExpiryTime"; @@ -61,6 +72,11 @@ public class UserClaimUpdateConfigImpl implements IdentityConnectorConfig { private static final String NOTIFICATION_ON_UPDATE_ELEMENT = "NotificationOnUpdate"; private static final String ENABLE_MOBILE_VERIFICATION_PRIVILEGED_USER = "EnableVerificationByPrivilegedUser"; private static String enableEmailVerificationOnUpdateProperty = null; + private static String enableSendOTPInEmailProperty = null; + private static String useUppercaseCharactersInOTPProperty = null; + private static String useLowercaseCharactersInOTPProperty = null; + private static String useNumbersInOTPProperty = null; + private static String otpLengthProperty = null; private static String emailVerificationOnUpdateCodeExpiryProperty = null; private static String enableEmailNotificationOnUpdateProperty = null; private static String enableMobileNumVerificationOnUpdateProperty = null; @@ -103,6 +119,16 @@ public Map getPropertyNameMapping() { Map nameMapping = new HashMap<>(); nameMapping.put(IdentityRecoveryConstants.ConnectorConfig.ENABLE_EMAIL_VERIFICATION_ON_UPDATE, "Enable user email verification on update"); + nameMapping.put(IdentityRecoveryConstants.ConnectorConfig.EMAIL_VERIFICATION_ON_UPDATE_SEND_OTP_IN_EMAIL, + "Send OTP in e-mail"); + nameMapping.put(IdentityRecoveryConstants.ConnectorConfig.EMAIL_VERIFICATION_ON_UPDATE_USE_UPPERCASE_CHARACTERS_IN_OTP, + "Include uppercase characters in OTP"); + nameMapping.put(IdentityRecoveryConstants.ConnectorConfig.EMAIL_VERIFICATION_ON_UPDATE_USE_LOWERCASE_CHARACTERS_IN_OTP, + "Include lowercase characters in OTP"); + nameMapping.put(IdentityRecoveryConstants.ConnectorConfig.EMAIL_VERIFICATION_ON_UPDATE_USE_NUMBERS_IN_OTP, + "Include numbers in OTP"); + nameMapping.put(IdentityRecoveryConstants.ConnectorConfig.EMAIL_VERIFICATION_ON_UPDATE_OTP_LENGTH, + "OTP length"); nameMapping.put(IdentityRecoveryConstants.ConnectorConfig.EMAIL_VERIFICATION_ON_UPDATE_EXPIRY_TIME, "Email verification on update link expiry time"); nameMapping.put(IdentityRecoveryConstants.ConnectorConfig.ENABLE_NOTIFICATION_ON_EMAIL_UPDATE, @@ -122,6 +148,18 @@ public Map getPropertyDescriptionMapping() { Map descriptionMapping = new HashMap<>(); descriptionMapping.put(IdentityRecoveryConstants.ConnectorConfig.ENABLE_EMAIL_VERIFICATION_ON_UPDATE, "Trigger a verification notification when user's email address is updated."); + descriptionMapping.put(IdentityRecoveryConstants.ConnectorConfig.EMAIL_VERIFICATION_ON_UPDATE_SEND_OTP_IN_EMAIL, + "Enable to send OTP in verification e-mail instead of confirmation code."); + descriptionMapping.put( + IdentityRecoveryConstants.ConnectorConfig.EMAIL_VERIFICATION_ON_UPDATE_USE_UPPERCASE_CHARACTERS_IN_OTP, + "Enable to include uppercase characters in SMS and e-mail OTPs"); + descriptionMapping.put( + IdentityRecoveryConstants.ConnectorConfig.EMAIL_VERIFICATION_ON_UPDATE_USE_LOWERCASE_CHARACTERS_IN_OTP, + "Enable to include lowercase characters in SMS and e-mail OTPs."); + descriptionMapping.put(IdentityRecoveryConstants.ConnectorConfig.EMAIL_VERIFICATION_ON_UPDATE_USE_NUMBERS_IN_OTP, + "Enable to include numbers in SMS and e-mail OTPs."); + descriptionMapping.put(IdentityRecoveryConstants.ConnectorConfig.EMAIL_VERIFICATION_ON_UPDATE_OTP_LENGTH, + "Length of the OTP for SMS and e-mail verifications. OTP length must be 4-10."); descriptionMapping.put(IdentityRecoveryConstants.ConnectorConfig.EMAIL_VERIFICATION_ON_UPDATE_EXPIRY_TIME, "Validity time of the email confirmation link in minutes."); descriptionMapping.put(IdentityRecoveryConstants.ConnectorConfig.ENABLE_NOTIFICATION_ON_EMAIL_UPDATE, @@ -141,6 +179,11 @@ public String[] getPropertyNames() { List properties = new ArrayList<>(); properties.add(IdentityRecoveryConstants.ConnectorConfig.ENABLE_EMAIL_VERIFICATION_ON_UPDATE); + properties.add(IdentityRecoveryConstants.ConnectorConfig.EMAIL_VERIFICATION_ON_UPDATE_SEND_OTP_IN_EMAIL); + properties.add(IdentityRecoveryConstants.ConnectorConfig.EMAIL_VERIFICATION_ON_UPDATE_USE_UPPERCASE_CHARACTERS_IN_OTP); + properties.add(IdentityRecoveryConstants.ConnectorConfig.EMAIL_VERIFICATION_ON_UPDATE_USE_LOWERCASE_CHARACTERS_IN_OTP); + properties.add(IdentityRecoveryConstants.ConnectorConfig.EMAIL_VERIFICATION_ON_UPDATE_USE_NUMBERS_IN_OTP); + properties.add(IdentityRecoveryConstants.ConnectorConfig.EMAIL_VERIFICATION_ON_UPDATE_OTP_LENGTH); properties.add(IdentityRecoveryConstants.ConnectorConfig.EMAIL_VERIFICATION_ON_UPDATE_EXPIRY_TIME); properties.add(IdentityRecoveryConstants.ConnectorConfig.ENABLE_NOTIFICATION_ON_EMAIL_UPDATE); properties.add(IdentityRecoveryConstants.ConnectorConfig.ENABLE_MOBILE_NUM_VERIFICATION_ON_UPDATE); @@ -153,6 +196,11 @@ public String[] getPropertyNames() { public Properties getDefaultPropertyValues(String tenantDomain) { String enableEmailVerificationOnUpdate = DEFAULT_ENABLE_VALUE_FOR_EMAIL_VERIFICATION_ON_UPDATE; + String enableSendOTPInEmail = DEFAULT_EMAIL_VERIFICATION_ON_UPDATE_SEND_OTP_IN_EMAIL; + String useUppercaseCharactersInOTP = DEFAULT_EMAIL_VERIFICATION_ON_UPDATE_USE_UPPERCASE_CHARACTERS_IN_OTP; + String useLowercaseCharactersInOTP = DEFAULT_EMAIL_VERIFICATION_ON_UPDATE_USE_LOWERCASE_CHARACTERS_IN_OTP; + String useNumbersInOTP = DEFAULT_EMAIL_VERIFICATION_ON_UPDATE_USE_NUMBERS_IN_OTP; + String otpLength = DEFAULT_EMAIL_VERIFICATION_ON_UPDATE_OTP_LENGTH; String emailVerificationOnUpdateCodeExpiry = DEFAULT_EMAIL_VERIFICATION_ON_UPDATE_CODE_EXPIRY_TIME; String enableEmailNotificationOnUpdate = DEFAULT_ENABLE_VALUE_FOR_EMAIL_NOTIFICATION_ON_UPDATE; String enableMobileNumVerificationOnUpdate = DEFAULT_ENABLE_VALUE_FOR_MOBILE_NUMBER_VERIFICATION_ON_UPDATE; @@ -164,6 +212,21 @@ public Properties getDefaultPropertyValues(String tenantDomain) { if (StringUtils.isNotBlank(enableEmailVerificationOnUpdateProperty)) { enableEmailVerificationOnUpdate = enableEmailVerificationOnUpdateProperty; } + if (StringUtils.isNotEmpty(enableSendOTPInEmailProperty)) { + enableSendOTPInEmail = enableSendOTPInEmailProperty; + } + if (StringUtils.isNotEmpty(useUppercaseCharactersInOTPProperty)) { + useUppercaseCharactersInOTP = useUppercaseCharactersInOTPProperty; + } + if (StringUtils.isNotEmpty(useLowercaseCharactersInOTPProperty)) { + useLowercaseCharactersInOTP = useLowercaseCharactersInOTPProperty; + } + if (StringUtils.isNotEmpty(useNumbersInOTPProperty)) { + useNumbersInOTP = useNumbersInOTPProperty; + } + if (StringUtils.isNotEmpty(otpLengthProperty)) { + otpLength = otpLengthProperty; + } if (StringUtils.isNotBlank(emailVerificationOnUpdateCodeExpiryProperty)) { emailVerificationOnUpdateCodeExpiry = emailVerificationOnUpdateCodeExpiryProperty; } @@ -183,6 +246,16 @@ public Properties getDefaultPropertyValues(String tenantDomain) { Properties properties = new Properties(); properties.put(IdentityRecoveryConstants.ConnectorConfig.ENABLE_EMAIL_VERIFICATION_ON_UPDATE, enableEmailVerificationOnUpdate); + properties.put(IdentityRecoveryConstants.ConnectorConfig.EMAIL_VERIFICATION_ON_UPDATE_SEND_OTP_IN_EMAIL, + enableSendOTPInEmail); + properties.put(IdentityRecoveryConstants.ConnectorConfig.EMAIL_VERIFICATION_ON_UPDATE_USE_UPPERCASE_CHARACTERS_IN_OTP, + useUppercaseCharactersInOTP); + properties.put(IdentityRecoveryConstants.ConnectorConfig.EMAIL_VERIFICATION_ON_UPDATE_USE_LOWERCASE_CHARACTERS_IN_OTP, + useLowercaseCharactersInOTP); + properties.put(IdentityRecoveryConstants.ConnectorConfig.EMAIL_VERIFICATION_ON_UPDATE_USE_NUMBERS_IN_OTP, + useNumbersInOTP); + properties.put(IdentityRecoveryConstants.ConnectorConfig.EMAIL_VERIFICATION_ON_UPDATE_OTP_LENGTH, + otpLength); properties.put(IdentityRecoveryConstants.ConnectorConfig.EMAIL_VERIFICATION_ON_UPDATE_EXPIRY_TIME, emailVerificationOnUpdateCodeExpiry); properties.put(IdentityRecoveryConstants.ConnectorConfig.ENABLE_NOTIFICATION_ON_EMAIL_UPDATE, @@ -220,9 +293,12 @@ private void loadConfigurations() { // Read configuration values defined in identity.xml. OMElement userClaimUpdate = IdentityConfigParser.getInstance().getConfigElement(USER_CLAIM_UPDATE_ELEMENT); Iterator claims = null; + OMElement otpConfigs = null; if (userClaimUpdate != null) { claims = userClaimUpdate.getChildrenWithName(new QName(IdentityCoreConstants .IDENTITY_DEFAULT_NAMESPACE, CLAIM_ELEMENT)); + otpConfigs = userClaimUpdate.getFirstChildWithName(new QName + (IdentityCoreConstants.IDENTITY_DEFAULT_NAMESPACE, OTP_ELEMENT)); } if (claims != null) { @@ -274,6 +350,18 @@ private void loadConfigurations() { } } } + if (otpConfigs != null) { + enableSendOTPInEmailProperty = otpConfigs.getFirstChildWithName(new QName + (IdentityCoreConstants.IDENTITY_DEFAULT_NAMESPACE, SEND_OTP_IN_EMAIL_ELEMENT)).getText(); + useUppercaseCharactersInOTPProperty = otpConfigs.getFirstChildWithName(new QName + (IdentityCoreConstants.IDENTITY_DEFAULT_NAMESPACE, USE_UPPERCASE_ELEMENT)).getText(); + useLowercaseCharactersInOTPProperty = otpConfigs.getFirstChildWithName(new QName + (IdentityCoreConstants.IDENTITY_DEFAULT_NAMESPACE, USE_LOWERCASE_ELEMENT)).getText(); + useNumbersInOTPProperty = otpConfigs.getFirstChildWithName(new QName + (IdentityCoreConstants.IDENTITY_DEFAULT_NAMESPACE, USE_NUMERIC_ELEMENT)).getText(); + otpLengthProperty = otpConfigs.getFirstChildWithName(new QName + (IdentityCoreConstants.IDENTITY_DEFAULT_NAMESPACE, OTP_LENGTH_ELEMENT)).getText(); + } } @Override @@ -284,6 +372,21 @@ public Map getMetaData() { meta.put(IdentityRecoveryConstants.ConnectorConfig.ENABLE_EMAIL_VERIFICATION_ON_UPDATE, getPropertyObject(IdentityMgtConstants.DataTypes.BOOLEAN.getValue())); + meta.put(IdentityRecoveryConstants.ConnectorConfig.EMAIL_VERIFICATION_ON_UPDATE_SEND_OTP_IN_EMAIL, + getPropertyObject(IdentityMgtConstants.DataTypes.BOOLEAN.getValue())); + + meta.put(IdentityRecoveryConstants.ConnectorConfig.EMAIL_VERIFICATION_ON_UPDATE_USE_UPPERCASE_CHARACTERS_IN_OTP, + getPropertyObject(IdentityMgtConstants.DataTypes.BOOLEAN.getValue())); + + meta.put(IdentityRecoveryConstants.ConnectorConfig.EMAIL_VERIFICATION_ON_UPDATE_USE_LOWERCASE_CHARACTERS_IN_OTP, + getPropertyObject(IdentityMgtConstants.DataTypes.BOOLEAN.getValue())); + + meta.put(IdentityRecoveryConstants.ConnectorConfig.EMAIL_VERIFICATION_ON_UPDATE_USE_NUMBERS_IN_OTP, + getPropertyObject(IdentityMgtConstants.DataTypes.BOOLEAN.getValue())); + + meta.put(IdentityRecoveryConstants.ConnectorConfig.EMAIL_VERIFICATION_ON_UPDATE_OTP_LENGTH, + getPropertyObject(IdentityMgtConstants.DataTypes.STRING.getValue())); + meta.put(IdentityRecoveryConstants.ConnectorConfig.ENABLE_NOTIFICATION_ON_EMAIL_UPDATE, getPropertyObject(IdentityMgtConstants.DataTypes.BOOLEAN.getValue())); diff --git a/components/org.wso2.carbon.identity.recovery/src/main/java/org/wso2/carbon/identity/recovery/connector/UserEmailVerificationConfigImpl.java b/components/org.wso2.carbon.identity.recovery/src/main/java/org/wso2/carbon/identity/recovery/connector/UserEmailVerificationConfigImpl.java index b7ada6f2b9..5807022d9b 100644 --- a/components/org.wso2.carbon.identity.recovery/src/main/java/org/wso2/carbon/identity/recovery/connector/UserEmailVerificationConfigImpl.java +++ b/components/org.wso2.carbon.identity.recovery/src/main/java/org/wso2/carbon/identity/recovery/connector/UserEmailVerificationConfigImpl.java @@ -86,6 +86,16 @@ public Map getPropertyNameMapping() { Map nameMapping = new HashMap<>(); nameMapping.put(IdentityRecoveryConstants.ConnectorConfig.ENABLE_EMAIL_VERIFICATION, "Enable user email verification"); + nameMapping.put(IdentityRecoveryConstants.ConnectorConfig.EMAIL_VERIFICATION_SEND_OTP_IN_EMAIL, + "Send OTP in e-mail"); + nameMapping.put(IdentityRecoveryConstants.ConnectorConfig.EMAIL_VERIFICATION_USE_UPPERCASE_CHARACTERS_IN_OTP, + "Include uppercase characters in OTP"); + nameMapping.put(IdentityRecoveryConstants.ConnectorConfig.EMAIL_VERIFICATION_USE_LOWERCASE_CHARACTERS_IN_OTP, + "Include lowercase characters in OTP"); + nameMapping.put(IdentityRecoveryConstants.ConnectorConfig.EMAIL_VERIFICATION_USE_NUMBERS_IN_OTP, + "Include numbers in OTP"); + nameMapping.put(IdentityRecoveryConstants.ConnectorConfig.EMAIL_VERIFICATION_OTP_LENGTH, + "OTP length"); nameMapping.put(IdentityRecoveryConstants.ConnectorConfig.EMAIL_ACCOUNT_LOCK_ON_CREATION, "Enable account lock on creation"); nameMapping.put(IdentityRecoveryConstants.ConnectorConfig.EMAIL_VERIFICATION_NOTIFICATION_INTERNALLY_MANAGE, @@ -106,6 +116,18 @@ public Map getPropertyDescriptionMapping() { Map descriptionMapping = new HashMap<>(); descriptionMapping.put(IdentityRecoveryConstants.ConnectorConfig.ENABLE_EMAIL_VERIFICATION, "A verification notification will be triggered during user creation."); + descriptionMapping.put(IdentityRecoveryConstants.ConnectorConfig.EMAIL_VERIFICATION_SEND_OTP_IN_EMAIL, + "Enable to send OTP in verification e-mail instead of confirmation code."); + descriptionMapping.put( + IdentityRecoveryConstants.ConnectorConfig.EMAIL_VERIFICATION_USE_UPPERCASE_CHARACTERS_IN_OTP, + "Enable to include uppercase characters in SMS and e-mail OTPs."); + descriptionMapping.put( + IdentityRecoveryConstants.ConnectorConfig.EMAIL_VERIFICATION_USE_LOWERCASE_CHARACTERS_IN_OTP, + "Enable to include lowercase characters in SMS and e-mail OTPs.."); + descriptionMapping.put(IdentityRecoveryConstants.ConnectorConfig.EMAIL_VERIFICATION_USE_NUMBERS_IN_OTP, + "Enable to include numbers in SMS and e-mail OTPs."); + descriptionMapping.put(IdentityRecoveryConstants.ConnectorConfig.EMAIL_VERIFICATION_OTP_LENGTH, + "Length of the OTP for SMS and e-mail verifications. OTP length must be 4-10."); descriptionMapping.put(IdentityRecoveryConstants.ConnectorConfig.EMAIL_ACCOUNT_LOCK_ON_CREATION, "The user account will be locked during user creation."); descriptionMapping.put(IdentityRecoveryConstants.ConnectorConfig.EMAIL_VERIFICATION_NOTIFICATION_INTERNALLY_MANAGE, @@ -128,6 +150,11 @@ public String[] getPropertyNames() { List properties = new ArrayList<>(); properties.add(IdentityRecoveryConstants.ConnectorConfig.ENABLE_EMAIL_VERIFICATION); + properties.add(IdentityRecoveryConstants.ConnectorConfig.EMAIL_VERIFICATION_SEND_OTP_IN_EMAIL); + properties.add(IdentityRecoveryConstants.ConnectorConfig.EMAIL_VERIFICATION_USE_UPPERCASE_CHARACTERS_IN_OTP); + properties.add(IdentityRecoveryConstants.ConnectorConfig.EMAIL_VERIFICATION_USE_LOWERCASE_CHARACTERS_IN_OTP); + properties.add(IdentityRecoveryConstants.ConnectorConfig.EMAIL_VERIFICATION_USE_NUMBERS_IN_OTP); + properties.add(IdentityRecoveryConstants.ConnectorConfig.EMAIL_VERIFICATION_OTP_LENGTH); properties.add(IdentityRecoveryConstants.ConnectorConfig.EMAIL_ACCOUNT_LOCK_ON_CREATION); properties.add(IdentityRecoveryConstants.ConnectorConfig.EMAIL_VERIFICATION_NOTIFICATION_INTERNALLY_MANAGE); properties.add(IdentityRecoveryConstants.ConnectorConfig.EMAIL_VERIFICATION_EXPIRY_TIME); @@ -142,6 +169,11 @@ public String[] getPropertyNames() { public Properties getDefaultPropertyValues(String tenantDomain) throws IdentityGovernanceException { String enableEmailVerification = "false"; + String enableSendOTPInEmail = "false"; + String useUppercaseCharactersInOTP = "true"; + String useLowercaseCharactersInOTP = "true"; + String useNumbersInOTP = "true"; + String otpLength = "6"; String enableEmailAccountLockOnCreation = "true"; String enableNotificationInternallyManage = "true"; String emailVerificationCodeExpiry = "1440"; @@ -150,6 +182,16 @@ public Properties getDefaultPropertyValues(String tenantDomain) throws IdentityG String emailVerificationProperty = IdentityUtil.getProperty( IdentityRecoveryConstants.ConnectorConfig.ENABLE_EMAIL_VERIFICATION); + String sendOTPInEmailProperty = IdentityUtil.getProperty( + IdentityRecoveryConstants.ConnectorConfig.EMAIL_VERIFICATION_SEND_OTP_IN_EMAIL); + String useUppercaseCharactersInOTPProperty = IdentityUtil.getProperty( + IdentityRecoveryConstants.ConnectorConfig.EMAIL_VERIFICATION_USE_UPPERCASE_CHARACTERS_IN_OTP); + String useLowercaseCharactersInOTPProperty = IdentityUtil.getProperty( + IdentityRecoveryConstants.ConnectorConfig.EMAIL_VERIFICATION_USE_LOWERCASE_CHARACTERS_IN_OTP); + String useNumbersInOTPProperty = IdentityUtil.getProperty( + IdentityRecoveryConstants.ConnectorConfig.EMAIL_VERIFICATION_USE_NUMBERS_IN_OTP); + String otpLengthProperty = IdentityUtil.getProperty( + IdentityRecoveryConstants.ConnectorConfig.EMAIL_VERIFICATION_OTP_LENGTH); String emailVerificationCodeExpiryProperty = IdentityUtil.getProperty( IdentityRecoveryConstants.ConnectorConfig.EMAIL_VERIFICATION_EXPIRY_TIME); String askPasswordCodeExpiryProperty = IdentityUtil.getProperty( @@ -164,6 +206,21 @@ public Properties getDefaultPropertyValues(String tenantDomain) throws IdentityG if (StringUtils.isNotEmpty(emailVerificationProperty)) { enableEmailVerification = emailVerificationProperty; } + if (StringUtils.isNotEmpty(sendOTPInEmailProperty)) { + enableSendOTPInEmail = sendOTPInEmailProperty; + } + if (StringUtils.isNotEmpty(useUppercaseCharactersInOTPProperty)) { + useUppercaseCharactersInOTP = useUppercaseCharactersInOTPProperty; + } + if (StringUtils.isNotEmpty(useLowercaseCharactersInOTPProperty)) { + useLowercaseCharactersInOTP = useLowercaseCharactersInOTPProperty; + } + if (StringUtils.isNotEmpty(useNumbersInOTPProperty)) { + useNumbersInOTP = useNumbersInOTPProperty; + } + if (StringUtils.isNotEmpty(otpLengthProperty)) { + otpLength = otpLengthProperty; + } if (StringUtils.isNotEmpty(lockOnCreationProperty)) { enableEmailAccountLockOnCreation = lockOnCreationProperty; } @@ -183,6 +240,16 @@ public Properties getDefaultPropertyValues(String tenantDomain) throws IdentityG Map defaultProperties = new HashMap<>(); defaultProperties.put(IdentityRecoveryConstants.ConnectorConfig.ENABLE_EMAIL_VERIFICATION, enableEmailVerification); + defaultProperties.put(IdentityRecoveryConstants.ConnectorConfig.EMAIL_VERIFICATION_SEND_OTP_IN_EMAIL, + enableSendOTPInEmail); + defaultProperties.put(IdentityRecoveryConstants.ConnectorConfig.EMAIL_VERIFICATION_USE_UPPERCASE_CHARACTERS_IN_OTP, + useUppercaseCharactersInOTP); + defaultProperties.put(IdentityRecoveryConstants.ConnectorConfig.EMAIL_VERIFICATION_USE_LOWERCASE_CHARACTERS_IN_OTP, + useLowercaseCharactersInOTP); + defaultProperties.put(IdentityRecoveryConstants.ConnectorConfig.EMAIL_VERIFICATION_USE_NUMBERS_IN_OTP, + useNumbersInOTP); + defaultProperties.put(IdentityRecoveryConstants.ConnectorConfig.EMAIL_VERIFICATION_OTP_LENGTH, + otpLength); defaultProperties.put(IdentityRecoveryConstants.ConnectorConfig.EMAIL_VERIFICATION_EXPIRY_TIME, emailVerificationCodeExpiry); defaultProperties.put(IdentityRecoveryConstants.ConnectorConfig.ASK_PASSWORD_EXPIRY_TIME, @@ -220,6 +287,21 @@ public Map getMetaData() { meta.put(IdentityRecoveryConstants.ConnectorConfig.ENABLE_EMAIL_VERIFICATION, getPropertyObject(IdentityMgtConstants.DataTypes.BOOLEAN.getValue())); + meta.put(IdentityRecoveryConstants.ConnectorConfig.EMAIL_VERIFICATION_SEND_OTP_IN_EMAIL, + getPropertyObject(IdentityMgtConstants.DataTypes.BOOLEAN.getValue())); + + meta.put(IdentityRecoveryConstants.ConnectorConfig.EMAIL_VERIFICATION_USE_UPPERCASE_CHARACTERS_IN_OTP, + getPropertyObject(IdentityMgtConstants.DataTypes.BOOLEAN.getValue())); + + meta.put(IdentityRecoveryConstants.ConnectorConfig.EMAIL_VERIFICATION_USE_LOWERCASE_CHARACTERS_IN_OTP, + getPropertyObject(IdentityMgtConstants.DataTypes.BOOLEAN.getValue())); + + meta.put(IdentityRecoveryConstants.ConnectorConfig.EMAIL_VERIFICATION_USE_NUMBERS_IN_OTP, + getPropertyObject(IdentityMgtConstants.DataTypes.BOOLEAN.getValue())); + + meta.put(IdentityRecoveryConstants.ConnectorConfig.EMAIL_VERIFICATION_OTP_LENGTH, + getPropertyObject(IdentityMgtConstants.DataTypes.STRING.getValue())); + meta.put(IdentityRecoveryConstants.ConnectorConfig.EMAIL_VERIFICATION_EXPIRY_TIME, getPropertyObject(IdentityMgtConstants.DataTypes.INTEGER.getValue())); diff --git a/components/org.wso2.carbon.identity.recovery/src/main/java/org/wso2/carbon/identity/recovery/handler/LiteUserRegistrationHandler.java b/components/org.wso2.carbon.identity.recovery/src/main/java/org/wso2/carbon/identity/recovery/handler/LiteUserRegistrationHandler.java index fc283e7d58..6d4fbdc8e6 100644 --- a/components/org.wso2.carbon.identity.recovery/src/main/java/org/wso2/carbon/identity/recovery/handler/LiteUserRegistrationHandler.java +++ b/components/org.wso2.carbon.identity.recovery/src/main/java/org/wso2/carbon/identity/recovery/handler/LiteUserRegistrationHandler.java @@ -132,8 +132,8 @@ public void handleEvent(Event event) throws IdentityEventException { userRecoveryDataStore.invalidate(user); // Create a secret key based on the preferred notification channel. - String secretKey = Utils.generateSecretKey(preferredChannel, tenantDomain, - RecoveryScenarios.LITE_SIGN_UP.name()); + String secretKey = Utils.generateSecretKey(preferredChannel, RecoveryScenarios.LITE_SIGN_UP.name(), + tenantDomain, "LiteRegistration"); // Resolve event name. String eventName = resolveEventName(preferredChannel, userName, domainName, tenantDomain); diff --git a/components/org.wso2.carbon.identity.recovery/src/main/java/org/wso2/carbon/identity/recovery/handler/MobileNumberVerificationHandler.java b/components/org.wso2.carbon.identity.recovery/src/main/java/org/wso2/carbon/identity/recovery/handler/MobileNumberVerificationHandler.java index d473b83f56..23c020f104 100644 --- a/components/org.wso2.carbon.identity.recovery/src/main/java/org/wso2/carbon/identity/recovery/handler/MobileNumberVerificationHandler.java +++ b/components/org.wso2.carbon.identity.recovery/src/main/java/org/wso2/carbon/identity/recovery/handler/MobileNumberVerificationHandler.java @@ -145,7 +145,8 @@ private void initNotificationForMobileNumberVerificationOnUpdate(User user, Stri userRecoveryDataStore.invalidate(user, RecoveryScenarios.MOBILE_VERIFICATION_ON_UPDATE, RecoverySteps.VERIFY_MOBILE_NUMBER); String secretKey = Utils.generateSecretKey(NotificationChannels.SMS_CHANNEL.getChannelType(), - user.getTenantDomain(), String.valueOf(RecoveryScenarios.MOBILE_VERIFICATION_ON_UPDATE)); + String.valueOf(RecoveryScenarios.MOBILE_VERIFICATION_ON_UPDATE), user.getTenantDomain(), + "UserClaimUpdate"); UserRecoveryData recoveryDataDO = new UserRecoveryData(user, secretKey, RecoveryScenarios.MOBILE_VERIFICATION_ON_UPDATE, RecoverySteps.VERIFY_MOBILE_NUMBER); /* Mobile number is persisted in remaining set ids to maintain context information about the mobile number diff --git a/components/org.wso2.carbon.identity.recovery/src/main/java/org/wso2/carbon/identity/recovery/handler/UserEmailVerificationHandler.java b/components/org.wso2.carbon.identity.recovery/src/main/java/org/wso2/carbon/identity/recovery/handler/UserEmailVerificationHandler.java index 90d76e1c58..5b37cb1b69 100644 --- a/components/org.wso2.carbon.identity.recovery/src/main/java/org/wso2/carbon/identity/recovery/handler/UserEmailVerificationHandler.java +++ b/components/org.wso2.carbon.identity.recovery/src/main/java/org/wso2/carbon/identity/recovery/handler/UserEmailVerificationHandler.java @@ -32,8 +32,10 @@ import org.wso2.carbon.identity.event.event.Event; import org.wso2.carbon.identity.event.handler.AbstractEventHandler; import org.wso2.carbon.identity.governance.IdentityMgtConstants; +import org.wso2.carbon.identity.governance.service.notification.NotificationChannels; import org.wso2.carbon.identity.recovery.IdentityRecoveryConstants; import org.wso2.carbon.identity.recovery.IdentityRecoveryException; +import org.wso2.carbon.identity.recovery.IdentityRecoveryServerException; import org.wso2.carbon.identity.recovery.RecoveryScenarios; import org.wso2.carbon.identity.recovery.RecoverySteps; import org.wso2.carbon.identity.recovery.internal.IdentityRecoveryServiceDataHolder; @@ -256,8 +258,13 @@ public void lockAccount(User user, UserStoreManager userStoreManager) throws Ide protected void initNotification(User user, Enum recoveryScenario, Enum recoveryStep, String notificationType) throws IdentityEventException { - String secretKey = UUIDGenerator.generateUUID(); - initNotification(user, recoveryScenario, recoveryStep, notificationType, secretKey); + try { + String secretKey = Utils.generateSecretKey(NotificationChannels.EMAIL_CHANNEL.getChannelType(), + recoveryScenario.name(), user.getTenantDomain(), "EmailVerification"); + initNotification(user, recoveryScenario, recoveryStep, notificationType, secretKey); + } catch (IdentityRecoveryServerException e) { + throw new IdentityEventException("Error while fetching the OTP pattern ", e); + } } protected void initNotification(User user, Enum recoveryScenario, Enum recoveryStep, String notificationType, @@ -295,8 +302,14 @@ private static boolean isRandomValueForCredentialsDisabled() { private void initNotificationForEmailVerificationOnUpdate(String verificationPendingEmailAddress, User user) throws IdentityEventException { - String secretKey = UUIDGenerator.generateUUID(); - initNotificationForEmailVerificationOnUpdate(user, secretKey, verificationPendingEmailAddress); + try { + String secretKey = Utils.generateSecretKey(NotificationChannels.EMAIL_CHANNEL.getChannelType(), + RecoveryScenarios.EMAIL_VERIFICATION_ON_UPDATE.name(), user.getTenantDomain(), + "UserClaimUpdate"); + initNotificationForEmailVerificationOnUpdate(user, secretKey, verificationPendingEmailAddress); + } catch (IdentityRecoveryServerException e) { + throw new IdentityEventException("Error while fetching the OTP pattern ", e); + } } private void initNotificationForEmailVerificationOnUpdate(User user, String secretKey, diff --git a/components/org.wso2.carbon.identity.recovery/src/main/java/org/wso2/carbon/identity/recovery/handler/UserSelfRegistrationHandler.java b/components/org.wso2.carbon.identity.recovery/src/main/java/org/wso2/carbon/identity/recovery/handler/UserSelfRegistrationHandler.java index 7bb1082ca6..d75b4e2701 100644 --- a/components/org.wso2.carbon.identity.recovery/src/main/java/org/wso2/carbon/identity/recovery/handler/UserSelfRegistrationHandler.java +++ b/components/org.wso2.carbon.identity.recovery/src/main/java/org/wso2/carbon/identity/recovery/handler/UserSelfRegistrationHandler.java @@ -150,8 +150,8 @@ public void handleEvent(Event event) throws IdentityEventException { userRecoveryDataStore.invalidate(user); // Create a secret key based on the preferred notification channel. - String secretKey = Utils.generateSecretKey(preferredChannel, tenantDomain, - RecoveryScenarios.SELF_SIGN_UP.name()); + String secretKey = Utils.generateSecretKey(preferredChannel, RecoveryScenarios.SELF_SIGN_UP.name(), + tenantDomain, "SelfRegistration"); // Resolve event name. String eventName = resolveEventName(preferredChannel, userName, domainName, tenantDomain); 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 281270d196..fe44c9cc7a 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 @@ -234,8 +234,8 @@ private UserRecoveryData generateNewConfirmationCode(User user, String notificat UserRecoveryDataStore userRecoveryDataStore = JDBCRecoveryDataStore.getInstance(); userRecoveryDataStore.invalidate(user); - String secretKey = Utils.generateSecretKey(notificationChannel, user.getTenantDomain(), - RecoveryScenarios.NOTIFICATION_BASED_PW_RECOVERY.name()); + String secretKey = Utils.generateSecretKey(notificationChannel, RecoveryScenarios.NOTIFICATION_BASED_PW_RECOVERY.name(), + user.getTenantDomain(), "Recovery.Notification.Password"); UserRecoveryData recoveryDataDO = new UserRecoveryData(user, secretKey, RecoveryScenarios.NOTIFICATION_BASED_PW_RECOVERY, RecoverySteps.UPDATE_PASSWORD); diff --git a/components/org.wso2.carbon.identity.recovery/src/main/java/org/wso2/carbon/identity/recovery/signup/UserSelfRegistrationManager.java b/components/org.wso2.carbon.identity.recovery/src/main/java/org/wso2/carbon/identity/recovery/signup/UserSelfRegistrationManager.java index 15f3b6de1f..0e7bd2835e 100644 --- a/components/org.wso2.carbon.identity.recovery/src/main/java/org/wso2/carbon/identity/recovery/signup/UserSelfRegistrationManager.java +++ b/components/org.wso2.carbon.identity.recovery/src/main/java/org/wso2/carbon/identity/recovery/signup/UserSelfRegistrationManager.java @@ -302,7 +302,8 @@ private NotificationResponseBean buildNotificationResponseBean(User user, String UserRecoveryDataStore userRecoveryDataStore = JDBCRecoveryDataStore.getInstance(); userRecoveryDataStore.invalidate(user); - String secretKey = UUIDGenerator.generateUUID(); + String secretKey = Utils.generateSecretKey(preferredChannel, RecoveryScenarios.SELF_SIGN_UP.name(), + user.getTenantDomain(), "SelfRegistration"); UserRecoveryData recoveryDataDO = new UserRecoveryData(user, secretKey, RecoveryScenarios.SELF_SIGN_UP, RecoverySteps.CONFIRM_SIGN_UP); recoveryDataDO.setRemainingSetIds(NotificationChannels.EXTERNAL_CHANNEL.getChannelType()); @@ -1733,7 +1734,8 @@ private NotificationResponseBean buildLiteNotificationResponseBean(User user, St UserRecoveryDataStore userRecoveryDataStore = JDBCRecoveryDataStore.getInstance(); userRecoveryDataStore.invalidate(user); - String secretKey = UUIDGenerator.generateUUID(); + String secretKey = Utils.generateSecretKey(preferredChannel, RecoveryScenarios.LITE_SIGN_UP.name(), + user.getTenantDomain(), "LiteRegistration"); UserRecoveryData recoveryDataDO = new UserRecoveryData(user, secretKey, RecoveryScenarios.LITE_SIGN_UP, RecoverySteps.CONFIRM_LITE_SIGN_UP); recoveryDataDO.setRemainingSetIds(NotificationChannels.EXTERNAL_CHANNEL.getChannelType()); 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 5e1d47d635..30491d10bb 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 @@ -1088,6 +1088,7 @@ public static void createAuditMessage(String action, String target, JSONObject d } /** + * This method is deprecated. * Generate a secret key according to the given channel. Method will generate an OTP for mobile channel and a * UUID for other channels. OTP is generated based on the defined regex. * @@ -1097,6 +1098,7 @@ public static void createAuditMessage(String action, String target, JSONObject d * @return Secret key. * @throws IdentityRecoveryServerException while getting sms otp regex. */ + @Deprecated public static String generateSecretKey(String channel, String tenantDomain, String recoveryScenario) throws IdentityRecoveryServerException { @@ -1152,6 +1154,58 @@ public static String generateSecretKey(String channel, String tenantDomain, Stri } } + /** + * Generate a secret key according to the given channel. Method will generate an OTP for mobile channel, and an OTP + * for e-mail channel when 'sendOTPInEmail' property enabled. For other scenarios method will generate UUID. + * + * @param channel Recovery notification channel. + * @param recoveryScenario Recovery scenario. + * @param tenantDomain Tenant domain. + * @param connectorName Connector name. + * @return Secret key. + * @throws IdentityRecoveryServerException while getting OTP generated. + */ + public static String generateSecretKey(String channel, String recoveryScenario, String tenantDomain, String connectorName) + throws IdentityRecoveryServerException { + + // Set default OTP configuration values, for scenarios that don't have specific OTP configurations. + boolean useUppercase = true; + boolean useLowercase = true; + boolean useNumeric = true; + boolean sendOTPInEmail = false; + int otpLength = IdentityRecoveryConstants.OTP_CODE_DEFAULT_LENGTH; + // Set connector specific OTP configuration values, for connectors that have separate OTP configurations. + if (StringUtils.isNotBlank(connectorName)) { + sendOTPInEmail = Boolean.parseBoolean(getRecoveryConfigs( + connectorName + ".OTP.SendOTPInEmail", tenantDomain)); + useUppercase = Boolean.parseBoolean(getRecoveryConfigs( + connectorName + ".OTP.UseUppercaseCharactersInOTP", tenantDomain)); + useLowercase = Boolean.parseBoolean(getRecoveryConfigs( + connectorName + ".OTP.UseLowercaseCharactersInOTP", tenantDomain)); + useNumeric = Boolean.parseBoolean(getRecoveryConfigs( + connectorName + ".OTP.UseNumbersInOTP", tenantDomain)); + try { + otpLength = Integer.parseInt(Utils.getRecoveryConfigs(connectorName + ".OTP.OTPLength", tenantDomain)); + } catch (NumberFormatException ex) { + log.warn("Configured OTP length is not a number. Hence using default length of " + + IdentityRecoveryConstants.OTP_CODE_DEFAULT_LENGTH + " for OTP."); + } + } + if (NotificationChannels.SMS_CHANNEL.getChannelType().equals(channel) || + RecoveryScenarios.ADMIN_FORCED_PASSWORD_RESET_VIA_OTP.name().equals(recoveryScenario) || + sendOTPInEmail) { + try { + OTPGenerator otpGenerator = IdentityRecoveryServiceDataHolder.getInstance().getOtpGenerator(); + return otpGenerator.generateOTP(useNumeric, useUppercase, useLowercase, otpLength, + recoveryScenario); + } catch (OTPGeneratorException otpGeneratorException) { + throw new IdentityRecoveryServerException(otpGeneratorException.getErrorCode(), + otpGeneratorException.getMessage()); + } + } + return UUIDGenerator.generateUUID(); + } + /** * Return user account state. * diff --git a/components/org.wso2.carbon.identity.recovery/src/test/java/org/wso2/carbon/identity/recovery/connector/RecoveryConfigImplTest.java b/components/org.wso2.carbon.identity.recovery/src/test/java/org/wso2/carbon/identity/recovery/connector/RecoveryConfigImplTest.java index 6782f5b845..c1cfc52bc3 100644 --- a/components/org.wso2.carbon.identity.recovery/src/test/java/org/wso2/carbon/identity/recovery/connector/RecoveryConfigImplTest.java +++ b/components/org.wso2.carbon.identity.recovery/src/test/java/org/wso2/carbon/identity/recovery/connector/RecoveryConfigImplTest.java @@ -82,6 +82,16 @@ public void testGetPropertyNameMapping() { Map nameMappingExpected = new HashMap<>(); nameMappingExpected.put(IdentityRecoveryConstants.ConnectorConfig.NOTIFICATION_BASED_PW_RECOVERY, "Notification based password recovery"); + nameMappingExpected.put(IdentityRecoveryConstants.ConnectorConfig.PASSWORD_RECOVERY_SEND_OTP_IN_EMAIL, + "Send OTP in e-mail"); + nameMappingExpected.put(IdentityRecoveryConstants.ConnectorConfig.PASSWORD_RECOVERY_USE_UPPERCASE_CHARACTERS_IN_OTP, + "Include uppercase characters in OTP"); + nameMappingExpected.put(IdentityRecoveryConstants.ConnectorConfig.PASSWORD_RECOVERY_USE_LOWERCASE_CHARACTERS_IN_OTP, + "Include lowercase characters in OTP"); + nameMappingExpected.put(IdentityRecoveryConstants.ConnectorConfig.PASSWORD_RECOVERY_USE_NUMBERS_IN_OTP, + "Include numbers in OTP"); + nameMappingExpected.put(IdentityRecoveryConstants.ConnectorConfig.PASSWORD_RECOVERY_OTP_LENGTH, + "OTP length"); nameMappingExpected.put(IdentityRecoveryConstants.ConnectorConfig.NOTIFICATION_INTERNALLY_MANAGE, "Manage notifications sending internally"); nameMappingExpected.put(IdentityRecoveryConstants.ConnectorConfig.PASSWORD_RECOVERY_RECAPTCHA_ENABLE, @@ -101,9 +111,6 @@ public void testGetPropertyNameMapping() { "Recovery link expiry time in minutes"); nameMappingExpected.put(IdentityRecoveryConstants.ConnectorConfig.PASSWORD_RECOVERY_SMS_OTP_EXPIRY_TIME, "SMS OTP expiry time"); - nameMappingExpected.put(IdentityRecoveryConstants.ConnectorConfig.PASSWORD_RECOVERY_SMS_OTP_REGEX, - "SMS OTP regex"); - nameMappingExpected.put(IdentityRecoveryConstants.ConnectorConfig.NOTIFICATION_SEND_RECOVERY_NOTIFICATION_SUCCESS, "Notify when recovery success"); nameMappingExpected.put(IdentityRecoveryConstants.ConnectorConfig.NOTIFICATION_SEND_RECOVERY_SECURITY_START, @@ -134,6 +141,18 @@ public void testGetPropertyDescriptionMapping() { Map descriptionMappingExpected = new HashMap(); descriptionMappingExpected.put(IdentityRecoveryConstants.ConnectorConfig.NOTIFICATION_INTERNALLY_MANAGE, "Disable if the client application handles notification sending"); + descriptionMappingExpected.put(IdentityRecoveryConstants.ConnectorConfig.PASSWORD_RECOVERY_SEND_OTP_IN_EMAIL, + "Enable to send OTP in verification e-mail instead of confirmation code."); + descriptionMappingExpected.put( + IdentityRecoveryConstants.ConnectorConfig.PASSWORD_RECOVERY_USE_UPPERCASE_CHARACTERS_IN_OTP, + "Enable to include uppercase characters in SMS and e-mail OTPs."); + descriptionMappingExpected.put( + IdentityRecoveryConstants.ConnectorConfig.PASSWORD_RECOVERY_USE_LOWERCASE_CHARACTERS_IN_OTP, + "Enable to include lowercase characters in SMS and e-mail OTPs."); + descriptionMappingExpected.put(IdentityRecoveryConstants.ConnectorConfig.PASSWORD_RECOVERY_USE_NUMBERS_IN_OTP, + "Enable to include numbers in SMS and e-mail OTPs."); + descriptionMappingExpected.put(IdentityRecoveryConstants.ConnectorConfig.PASSWORD_RECOVERY_OTP_LENGTH, + "Length of the OTP for SMS and e-mail verifications. OTP length must be 4-10."); descriptionMappingExpected.put(IdentityRecoveryConstants.ConnectorConfig.CHALLENGE_QUESTION_ANSWER_REGEX, "Security question answer regex"); descriptionMappingExpected.put(IdentityRecoveryConstants.ConnectorConfig.ENFORCE_CHALLENGE_QUESTION_ANSWER_UNIQUENESS, @@ -149,9 +168,6 @@ public void testGetPropertyDescriptionMapping() { "Recovery callback URL regex"); descriptionMappingExpected.put(IdentityRecoveryConstants.ConnectorConfig.PASSWORD_RECOVERY_SMS_OTP_EXPIRY_TIME, "Expiration time of the SMS OTP code for password recovery"); - descriptionMappingExpected.put(IdentityRecoveryConstants.ConnectorConfig.PASSWORD_RECOVERY_SMS_OTP_REGEX, - "Regex for SMS OTP in format [allowed characters]{length}. Supported character ranges are a-z, A-Z, " + - "0-9. Minimum OTP length is " + IdentityMgtConstants.MINIMUM_SMS_OTP_LENGTH); descriptionMappingExpected.put(IdentityRecoveryConstants.ConnectorConfig.ENABLE_AUTO_LGOIN_AFTER_PASSWORD_RESET, "User will be logged in automatically after completing the Password Reset wizard"); Map descriptionMapping = recoveryConfigImpl.getPropertyDescriptionMapping(); @@ -164,6 +180,11 @@ public void testGetPropertyNames() { List propertiesExpected = new ArrayList<>(); propertiesExpected.add(IdentityRecoveryConstants.ConnectorConfig.NOTIFICATION_BASED_PW_RECOVERY); + propertiesExpected.add(IdentityRecoveryConstants.ConnectorConfig.PASSWORD_RECOVERY_SEND_OTP_IN_EMAIL); + propertiesExpected.add(IdentityRecoveryConstants.ConnectorConfig.PASSWORD_RECOVERY_USE_UPPERCASE_CHARACTERS_IN_OTP); + propertiesExpected.add(IdentityRecoveryConstants.ConnectorConfig.PASSWORD_RECOVERY_USE_LOWERCASE_CHARACTERS_IN_OTP); + propertiesExpected.add(IdentityRecoveryConstants.ConnectorConfig.PASSWORD_RECOVERY_USE_NUMBERS_IN_OTP); + propertiesExpected.add(IdentityRecoveryConstants.ConnectorConfig.PASSWORD_RECOVERY_OTP_LENGTH); propertiesExpected.add(IdentityRecoveryConstants.ConnectorConfig.PASSWORD_RECOVERY_RECAPTCHA_ENABLE); propertiesExpected.add(IdentityRecoveryConstants.ConnectorConfig.QUESTION_BASED_PW_RECOVERY); propertiesExpected.add(IdentityRecoveryConstants.ConnectorConfig.QUESTION_MIN_NO_ANSWER); @@ -178,7 +199,6 @@ public void testGetPropertyNames() { propertiesExpected.add(IdentityRecoveryConstants.ConnectorConfig.NOTIFICATION_SEND_RECOVERY_SECURITY_START); propertiesExpected.add(IdentityRecoveryConstants.ConnectorConfig.EXPIRY_TIME); propertiesExpected.add(IdentityRecoveryConstants.ConnectorConfig.PASSWORD_RECOVERY_SMS_OTP_EXPIRY_TIME); - propertiesExpected.add(IdentityRecoveryConstants.ConnectorConfig.PASSWORD_RECOVERY_SMS_OTP_REGEX); propertiesExpected.add(IdentityRecoveryConstants.ConnectorConfig.FORCE_ADD_PW_RECOVERY_QUESTION); propertiesExpected.add(IdentityRecoveryConstants.ConnectorConfig.FORCE_MIN_NO_QUESTION_ANSWERED); propertiesExpected.add(IdentityRecoveryConstants.ConnectorConfig.RECOVERY_CALLBACK_REGEX); @@ -197,6 +217,11 @@ public void testGetPropertyNames() { public void testGetDefaultPropertyValues() throws IdentityGovernanceException { String testEnableNotificationBasedPasswordRecovery = "false"; + String testEnableSendOTPInEmail = "false"; + String testUseUppercaseCharactersInOTP = StringUtils.EMPTY; + String testUseLowercaseCharactersInOTP = StringUtils.EMPTY; + String testUseNumbersInOTP = StringUtils.EMPTY; + String testOtpLength = "6"; String testEnableQuestionBasedPasswordRecovery = "false"; String testMinimumAnswers = "2"; String testEnableRecoveryQuestionPasswordReCaptcha = "true"; @@ -220,6 +245,16 @@ public void testGetDefaultPropertyValues() throws IdentityGovernanceException { Map defaultPropertiesExpected = new HashMap<>(); defaultPropertiesExpected.put(IdentityRecoveryConstants.ConnectorConfig.NOTIFICATION_BASED_PW_RECOVERY, testEnableNotificationBasedPasswordRecovery); + defaultPropertiesExpected.put(IdentityRecoveryConstants.ConnectorConfig.PASSWORD_RECOVERY_SEND_OTP_IN_EMAIL, + testEnableSendOTPInEmail); + defaultPropertiesExpected.put(IdentityRecoveryConstants.ConnectorConfig.PASSWORD_RECOVERY_USE_UPPERCASE_CHARACTERS_IN_OTP, + testUseUppercaseCharactersInOTP); + defaultPropertiesExpected.put(IdentityRecoveryConstants.ConnectorConfig.PASSWORD_RECOVERY_USE_LOWERCASE_CHARACTERS_IN_OTP, + testUseLowercaseCharactersInOTP); + defaultPropertiesExpected.put(IdentityRecoveryConstants.ConnectorConfig.PASSWORD_RECOVERY_USE_NUMBERS_IN_OTP, + testUseNumbersInOTP); + defaultPropertiesExpected.put(IdentityRecoveryConstants.ConnectorConfig.PASSWORD_RECOVERY_OTP_LENGTH, + testOtpLength); defaultPropertiesExpected.put(IdentityRecoveryConstants.ConnectorConfig.PASSWORD_RECOVERY_RECAPTCHA_ENABLE, enablePasswordRecoveryReCaptcha); defaultPropertiesExpected.put(IdentityRecoveryConstants.ConnectorConfig.QUESTION_BASED_PW_RECOVERY, @@ -240,8 +275,6 @@ public void testGetDefaultPropertyValues() throws IdentityGovernanceException { defaultPropertiesExpected.put(IdentityRecoveryConstants.ConnectorConfig.EXPIRY_TIME, testExpiryTime); defaultPropertiesExpected.put(IdentityRecoveryConstants.ConnectorConfig.PASSWORD_RECOVERY_SMS_OTP_EXPIRY_TIME, testExpiryTimeSMSOTP); - defaultPropertiesExpected - .put(IdentityRecoveryConstants.ConnectorConfig.PASSWORD_RECOVERY_SMS_OTP_REGEX, smsOtpRegex); defaultPropertiesExpected.put(IdentityRecoveryConstants.ConnectorConfig.NOTIFICATION_SEND_RECOVERY_NOTIFICATION_SUCCESS, testNotifySuccess); defaultPropertiesExpected.put(IdentityRecoveryConstants.ConnectorConfig.NOTIFICATION_SEND_RECOVERY_SECURITY_START, diff --git a/components/org.wso2.carbon.identity.recovery/src/test/java/org/wso2/carbon/identity/recovery/connector/SelfRegistrationConfigImplTest.java b/components/org.wso2.carbon.identity.recovery/src/test/java/org/wso2/carbon/identity/recovery/connector/SelfRegistrationConfigImplTest.java index 8a154964d3..706bc0a0cc 100644 --- a/components/org.wso2.carbon.identity.recovery/src/test/java/org/wso2/carbon/identity/recovery/connector/SelfRegistrationConfigImplTest.java +++ b/components/org.wso2.carbon.identity.recovery/src/test/java/org/wso2/carbon/identity/recovery/connector/SelfRegistrationConfigImplTest.java @@ -17,6 +17,7 @@ */ package org.wso2.carbon.identity.recovery.connector; +import org.apache.commons.lang.StringUtils; import org.testng.annotations.BeforeTest; import org.testng.annotations.Test; import org.wso2.carbon.identity.governance.IdentityGovernanceException; @@ -95,6 +96,16 @@ public void testGetPropertyNameMapping() { nameMappingExpected.put(IdentityRecoveryConstants.ConnectorConfig.ENABLE_SELF_SIGNUP, "User self registration"); nameMappingExpected.put(IdentityRecoveryConstants.ConnectorConfig.ACCOUNT_LOCK_ON_CREATION, "Lock user account on creation"); + nameMappingExpected.put(IdentityRecoveryConstants.ConnectorConfig.SELF_REGISTRATION_SEND_OTP_IN_EMAIL, + "Send OTP in e-mail"); + nameMappingExpected.put(IdentityRecoveryConstants.ConnectorConfig.SELF_REGISTRATION_USE_UPPERCASE_CHARACTERS_IN_OTP, + "Include uppercase characters in OTP"); + nameMappingExpected.put(IdentityRecoveryConstants.ConnectorConfig.SELF_REGISTRATION_USE_LOWERCASE_CHARACTERS_IN_OTP, + "Include lowercase characters in OTP"); + nameMappingExpected.put(IdentityRecoveryConstants.ConnectorConfig.SELF_REGISTRATION_USE_NUMBERS_IN_OTP, + "Include numbers in OTP"); + nameMappingExpected.put(IdentityRecoveryConstants.ConnectorConfig.SELF_REGISTRATION_OTP_LENGTH, + "OTP length"); nameMappingExpected.put(IdentityRecoveryConstants.ConnectorConfig.SEND_CONFIRMATION_NOTIFICATION, "Enable Account Confirmation On Creation"); nameMappingExpected.put(IdentityRecoveryConstants.ConnectorConfig.SIGN_UP_NOTIFICATION_INTERNALLY_MANAGE, @@ -104,8 +115,6 @@ public void testGetPropertyNameMapping() { "User self registration verification link expiry time"); nameMappingExpected.put(IdentityRecoveryConstants.ConnectorConfig.SELF_REGISTRATION_SMSOTP_VERIFICATION_CODE_EXPIRY_TIME, "User self registration SMS OTP expiry time"); - nameMappingExpected.put(IdentityRecoveryConstants.ConnectorConfig.SELF_REGISTRATION_SMS_OTP_REGEX, - "User self registration SMS OTP regex"); nameMappingExpected.put(IdentityRecoveryConstants.ConnectorConfig.SELF_REGISTRATION_CALLBACK_REGEX, "User self registration callback URL regex"); nameMappingExpected.put(LIST_PURPOSE_PROPERTY_KEY, "Manage Self-Sign-Up purposes"); @@ -130,6 +139,18 @@ public void testGetPropertyDescriptionMapping() { "Allow user's to self register to the system."); descriptionMappingExpected.put(IdentityRecoveryConstants.ConnectorConfig.ACCOUNT_LOCK_ON_CREATION, "Lock self registered user account until e-mail verification."); + descriptionMappingExpected.put(IdentityRecoveryConstants.ConnectorConfig.SELF_REGISTRATION_SEND_OTP_IN_EMAIL, + "Enable to send OTP in verification e-mail instead of confirmation code."); + descriptionMappingExpected.put( + IdentityRecoveryConstants.ConnectorConfig.SELF_REGISTRATION_USE_UPPERCASE_CHARACTERS_IN_OTP, + "Enable to include uppercase characters in SMS and e-mail OTPs."); + descriptionMappingExpected.put( + IdentityRecoveryConstants.ConnectorConfig.SELF_REGISTRATION_USE_LOWERCASE_CHARACTERS_IN_OTP, + "Enable to include lowercase characters in SMS and e-mail OTPs."); + descriptionMappingExpected.put(IdentityRecoveryConstants.ConnectorConfig.SELF_REGISTRATION_USE_NUMBERS_IN_OTP, + "Enable to include numbers in SMS and e-mail OTPs."); + descriptionMappingExpected.put(IdentityRecoveryConstants.ConnectorConfig.SELF_REGISTRATION_OTP_LENGTH, + "Length of the OTP for SMS and e-mail verifications. OTP length must be 4-10."); descriptionMappingExpected.put(IdentityRecoveryConstants.ConnectorConfig.SEND_CONFIRMATION_NOTIFICATION, "Enable user account confirmation when the user account is not locked on creation"); descriptionMappingExpected.put(IdentityRecoveryConstants.ConnectorConfig.SIGN_UP_NOTIFICATION_INTERNALLY_MANAGE, @@ -142,10 +163,6 @@ public void testGetPropertyDescriptionMapping() { descriptionMappingExpected.put( IdentityRecoveryConstants.ConnectorConfig.SELF_REGISTRATION_SMSOTP_VERIFICATION_CODE_EXPIRY_TIME, "Specify the expiry time in minutes for the SMS OTP."); - descriptionMappingExpected.put(IdentityRecoveryConstants.ConnectorConfig.SELF_REGISTRATION_SMS_OTP_REGEX, - "Regex for SMS OTP in format [allowed characters]{length}. Supported character " + - "ranges are a-z, A-Z, 0-9. Minimum OTP length is " + - IdentityMgtConstants.MINIMUM_SMS_OTP_LENGTH); descriptionMappingExpected.put(IdentityRecoveryConstants.ConnectorConfig.SELF_REGISTRATION_CALLBACK_REGEX, "This prefix will be used to validate the callback URL."); descriptionMappingExpected.put(LIST_PURPOSE_PROPERTY_KEY, "Click here to manage Self-Sign-Up purposes"); @@ -169,6 +186,11 @@ public void testGetPropertyNames() { List propertiesExpected = new ArrayList<>(); propertiesExpected.add(IdentityRecoveryConstants.ConnectorConfig.ENABLE_SELF_SIGNUP); propertiesExpected.add(IdentityRecoveryConstants.ConnectorConfig.ACCOUNT_LOCK_ON_CREATION); + propertiesExpected.add(IdentityRecoveryConstants.ConnectorConfig.SELF_REGISTRATION_SEND_OTP_IN_EMAIL); + propertiesExpected.add(IdentityRecoveryConstants.ConnectorConfig.SELF_REGISTRATION_USE_UPPERCASE_CHARACTERS_IN_OTP); + propertiesExpected.add(IdentityRecoveryConstants.ConnectorConfig.SELF_REGISTRATION_USE_LOWERCASE_CHARACTERS_IN_OTP); + propertiesExpected.add(IdentityRecoveryConstants.ConnectorConfig.SELF_REGISTRATION_USE_NUMBERS_IN_OTP); + propertiesExpected.add(IdentityRecoveryConstants.ConnectorConfig.SELF_REGISTRATION_OTP_LENGTH); propertiesExpected.add(IdentityRecoveryConstants.ConnectorConfig.SEND_CONFIRMATION_NOTIFICATION); propertiesExpected.add(IdentityRecoveryConstants.ConnectorConfig.SIGN_UP_NOTIFICATION_INTERNALLY_MANAGE); propertiesExpected.add(IdentityRecoveryConstants.ConnectorConfig.SELF_REGISTRATION_RE_CAPTCHA); @@ -176,7 +198,6 @@ public void testGetPropertyNames() { .add(IdentityRecoveryConstants.ConnectorConfig.SELF_REGISTRATION_VERIFICATION_CODE_EXPIRY_TIME); propertiesExpected .add(IdentityRecoveryConstants.ConnectorConfig.SELF_REGISTRATION_SMSOTP_VERIFICATION_CODE_EXPIRY_TIME); - propertiesExpected.add(IdentityRecoveryConstants.ConnectorConfig.SELF_REGISTRATION_SMS_OTP_REGEX); propertiesExpected.add(IdentityRecoveryConstants.ConnectorConfig.SELF_REGISTRATION_CALLBACK_REGEX); propertiesExpected.add(LIST_PURPOSE_PROPERTY_KEY); propertiesExpected.add(IdentityRecoveryConstants.ConnectorConfig.SELF_REGISTRATION_NOTIFY_ACCOUNT_CONFIRMATION); @@ -197,12 +218,16 @@ public void testGetDefaultPropertyValues() throws IdentityGovernanceException { String testEnableSelfSignUp = "false"; String testEnableAccountLockOnCreation = "true"; + String testEnableSendOTPInEmail = "false"; + String testUseUppercaseCharactersInOTP = StringUtils.EMPTY; + String testUseLowercaseCharactersInOTP = StringUtils.EMPTY; + String testUseNumbersInOTP = StringUtils.EMPTY; + String testOtpLength = "6"; String testEnableSendNotificationOnCreation = "false"; String testEnableNotificationInternallyManage = "true"; String testEnableSelfRegistrationReCaptcha = "true"; String testVerificationCodeExpiryTime = "1440"; String testVerificationSMSOTPExpiryTime = "1"; - String testVerificationSMSOTPRegex = "[a-zA-Z0-9]{6}"; String selfRegistrationCallbackRegex = IdentityRecoveryConstants.DEFAULT_CALLBACK_REGEX; String enableSelfSignUpConfirmationNotification = "false"; String enableResendConfirmationRecaptcha = "false"; @@ -213,6 +238,16 @@ public void testGetDefaultPropertyValues() throws IdentityGovernanceException { propertiesExpected.put(IdentityRecoveryConstants.ConnectorConfig.ENABLE_SELF_SIGNUP, testEnableSelfSignUp); propertiesExpected.put(IdentityRecoveryConstants.ConnectorConfig.ACCOUNT_LOCK_ON_CREATION, testEnableAccountLockOnCreation); + propertiesExpected.put(IdentityRecoveryConstants.ConnectorConfig.SELF_REGISTRATION_SEND_OTP_IN_EMAIL, + testEnableSendOTPInEmail); + propertiesExpected.put(IdentityRecoveryConstants.ConnectorConfig.SELF_REGISTRATION_USE_UPPERCASE_CHARACTERS_IN_OTP, + testUseUppercaseCharactersInOTP); + propertiesExpected.put(IdentityRecoveryConstants.ConnectorConfig.SELF_REGISTRATION_USE_LOWERCASE_CHARACTERS_IN_OTP, + testUseLowercaseCharactersInOTP); + propertiesExpected.put(IdentityRecoveryConstants.ConnectorConfig.SELF_REGISTRATION_USE_NUMBERS_IN_OTP, + testUseNumbersInOTP); + propertiesExpected.put(IdentityRecoveryConstants.ConnectorConfig.SELF_REGISTRATION_OTP_LENGTH, + testOtpLength); propertiesExpected.put(IdentityRecoveryConstants.ConnectorConfig.SEND_CONFIRMATION_NOTIFICATION, testEnableSendNotificationOnCreation); propertiesExpected.put(IdentityRecoveryConstants.ConnectorConfig.SIGN_UP_NOTIFICATION_INTERNALLY_MANAGE, @@ -222,8 +257,6 @@ public void testGetDefaultPropertyValues() throws IdentityGovernanceException { propertiesExpected.put( IdentityRecoveryConstants.ConnectorConfig.SELF_REGISTRATION_VERIFICATION_CODE_EXPIRY_TIME, testVerificationCodeExpiryTime); - propertiesExpected.put(IdentityRecoveryConstants.ConnectorConfig.SELF_REGISTRATION_SMS_OTP_REGEX, - testVerificationSMSOTPRegex); propertiesExpected.put( IdentityRecoveryConstants.ConnectorConfig.SELF_REGISTRATION_SMSOTP_VERIFICATION_CODE_EXPIRY_TIME, testVerificationSMSOTPExpiryTime); diff --git a/components/org.wso2.carbon.identity.recovery/src/test/java/org/wso2/carbon/identity/recovery/connector/UserClaimUpdateConfigImplTest.java b/components/org.wso2.carbon.identity.recovery/src/test/java/org/wso2/carbon/identity/recovery/connector/UserClaimUpdateConfigImplTest.java index 64ffb1cd8c..4383641b4d 100644 --- a/components/org.wso2.carbon.identity.recovery/src/test/java/org/wso2/carbon/identity/recovery/connector/UserClaimUpdateConfigImplTest.java +++ b/components/org.wso2.carbon.identity.recovery/src/test/java/org/wso2/carbon/identity/recovery/connector/UserClaimUpdateConfigImplTest.java @@ -117,6 +117,16 @@ public void testGetPropertyNameMapping() { Map nameMappingExpected = new HashMap<>(); nameMappingExpected.put(IdentityRecoveryConstants.ConnectorConfig.ENABLE_EMAIL_VERIFICATION_ON_UPDATE, "Enable user email verification on update"); + nameMappingExpected.put(IdentityRecoveryConstants.ConnectorConfig.EMAIL_VERIFICATION_ON_UPDATE_SEND_OTP_IN_EMAIL, + "Send OTP in e-mail"); + nameMappingExpected.put(IdentityRecoveryConstants.ConnectorConfig.EMAIL_VERIFICATION_ON_UPDATE_USE_UPPERCASE_CHARACTERS_IN_OTP, + "Include uppercase characters in OTP"); + nameMappingExpected.put(IdentityRecoveryConstants.ConnectorConfig.EMAIL_VERIFICATION_ON_UPDATE_USE_LOWERCASE_CHARACTERS_IN_OTP, + "Include lowercase characters in OTP"); + nameMappingExpected.put(IdentityRecoveryConstants.ConnectorConfig.EMAIL_VERIFICATION_ON_UPDATE_USE_NUMBERS_IN_OTP, + "Include numbers in OTP"); + nameMappingExpected.put(IdentityRecoveryConstants.ConnectorConfig.EMAIL_VERIFICATION_ON_UPDATE_OTP_LENGTH, + "OTP length"); nameMappingExpected.put(IdentityRecoveryConstants.ConnectorConfig.EMAIL_VERIFICATION_ON_UPDATE_EXPIRY_TIME, "Email verification on update link expiry time"); nameMappingExpected.put(IdentityRecoveryConstants.ConnectorConfig.ENABLE_NOTIFICATION_ON_EMAIL_UPDATE, @@ -137,6 +147,18 @@ public void testGetPropertyDescriptionMapping() { Map descriptionMappingExpected = new HashMap<>(); descriptionMappingExpected.put(IdentityRecoveryConstants.ConnectorConfig.ENABLE_EMAIL_VERIFICATION_ON_UPDATE, "Trigger a verification notification when user's email address is updated."); + descriptionMappingExpected.put(IdentityRecoveryConstants.ConnectorConfig.EMAIL_VERIFICATION_ON_UPDATE_SEND_OTP_IN_EMAIL, + "Enable to send OTP in verification e-mail instead of confirmation code."); + descriptionMappingExpected.put( + IdentityRecoveryConstants.ConnectorConfig.EMAIL_VERIFICATION_ON_UPDATE_USE_UPPERCASE_CHARACTERS_IN_OTP, + "Enable to include uppercase characters in SMS and e-mail OTPs"); + descriptionMappingExpected.put( + IdentityRecoveryConstants.ConnectorConfig.EMAIL_VERIFICATION_ON_UPDATE_USE_LOWERCASE_CHARACTERS_IN_OTP, + "Enable to include lowercase characters in SMS and e-mail OTPs."); + descriptionMappingExpected.put(IdentityRecoveryConstants.ConnectorConfig.EMAIL_VERIFICATION_ON_UPDATE_USE_NUMBERS_IN_OTP, + "Enable to include numbers in SMS and e-mail OTPs."); + descriptionMappingExpected.put(IdentityRecoveryConstants.ConnectorConfig.EMAIL_VERIFICATION_ON_UPDATE_OTP_LENGTH, + "Length of the OTP for SMS and e-mail verifications. OTP length must be 4-10."); descriptionMappingExpected.put(IdentityRecoveryConstants.ConnectorConfig .EMAIL_VERIFICATION_ON_UPDATE_EXPIRY_TIME, "Validity time of the email confirmation link in " + "minutes."); @@ -158,6 +180,11 @@ public void testGetPropertyNames() { List propertiesExpected = new ArrayList<>(); propertiesExpected.add(IdentityRecoveryConstants.ConnectorConfig.ENABLE_EMAIL_VERIFICATION_ON_UPDATE); + propertiesExpected.add(IdentityRecoveryConstants.ConnectorConfig.EMAIL_VERIFICATION_ON_UPDATE_SEND_OTP_IN_EMAIL); + propertiesExpected.add(IdentityRecoveryConstants.ConnectorConfig.EMAIL_VERIFICATION_ON_UPDATE_USE_UPPERCASE_CHARACTERS_IN_OTP); + propertiesExpected.add(IdentityRecoveryConstants.ConnectorConfig.EMAIL_VERIFICATION_ON_UPDATE_USE_LOWERCASE_CHARACTERS_IN_OTP); + propertiesExpected.add(IdentityRecoveryConstants.ConnectorConfig.EMAIL_VERIFICATION_ON_UPDATE_USE_NUMBERS_IN_OTP); + propertiesExpected.add(IdentityRecoveryConstants.ConnectorConfig.EMAIL_VERIFICATION_ON_UPDATE_OTP_LENGTH); propertiesExpected.add(IdentityRecoveryConstants.ConnectorConfig.EMAIL_VERIFICATION_ON_UPDATE_EXPIRY_TIME); propertiesExpected.add(IdentityRecoveryConstants.ConnectorConfig.ENABLE_NOTIFICATION_ON_EMAIL_UPDATE); propertiesExpected.add(IdentityRecoveryConstants.ConnectorConfig.ENABLE_MOBILE_NUM_VERIFICATION_ON_UPDATE); @@ -209,7 +236,12 @@ public void testGetDefaultPropertyValues() throws IdentityGovernanceException { public void testGetDefaultProperties() throws IdentityGovernanceException { String[] propertyNames = new String[]{IdentityRecoveryConstants.ConnectorConfig - .ENABLE_EMAIL_VERIFICATION_ON_UPDATE, IdentityRecoveryConstants.ConnectorConfig + .ENABLE_EMAIL_VERIFICATION_ON_UPDATE, IdentityRecoveryConstants.ConnectorConfig. + EMAIL_VERIFICATION_ON_UPDATE_SEND_OTP_IN_EMAIL, IdentityRecoveryConstants.ConnectorConfig. + EMAIL_VERIFICATION_ON_UPDATE_USE_UPPERCASE_CHARACTERS_IN_OTP, IdentityRecoveryConstants.ConnectorConfig. + EMAIL_VERIFICATION_ON_UPDATE_USE_LOWERCASE_CHARACTERS_IN_OTP, IdentityRecoveryConstants.ConnectorConfig. + EMAIL_VERIFICATION_ON_UPDATE_USE_NUMBERS_IN_OTP, IdentityRecoveryConstants.ConnectorConfig. + EMAIL_VERIFICATION_ON_UPDATE_OTP_LENGTH, IdentityRecoveryConstants.ConnectorConfig .EMAIL_VERIFICATION_ON_UPDATE_EXPIRY_TIME, IdentityRecoveryConstants.ConnectorConfig .ENABLE_MOBILE_NUM_VERIFICATION_ON_UPDATE, IdentityRecoveryConstants.ConnectorConfig .MOBILE_NUM_VERIFICATION_ON_UPDATE_EXPIRY_TIME,"testproperty"}; diff --git a/components/org.wso2.carbon.identity.recovery/src/test/java/org/wso2/carbon/identity/recovery/connector/UserEmailVerificationConfigImplTest.java b/components/org.wso2.carbon.identity.recovery/src/test/java/org/wso2/carbon/identity/recovery/connector/UserEmailVerificationConfigImplTest.java index 04c4fde14f..b65f2dea85 100644 --- a/components/org.wso2.carbon.identity.recovery/src/test/java/org/wso2/carbon/identity/recovery/connector/UserEmailVerificationConfigImplTest.java +++ b/components/org.wso2.carbon.identity.recovery/src/test/java/org/wso2/carbon/identity/recovery/connector/UserEmailVerificationConfigImplTest.java @@ -92,6 +92,16 @@ public void testGetPropertyNameMapping() { Map nameMappingExpected = new HashMap<>(); nameMappingExpected.put(IdentityRecoveryConstants.ConnectorConfig.ENABLE_EMAIL_VERIFICATION, "Enable user email verification"); + nameMappingExpected.put(IdentityRecoveryConstants.ConnectorConfig.EMAIL_VERIFICATION_SEND_OTP_IN_EMAIL, + "Send OTP in e-mail"); + nameMappingExpected.put(IdentityRecoveryConstants.ConnectorConfig.EMAIL_VERIFICATION_USE_UPPERCASE_CHARACTERS_IN_OTP, + "Include uppercase characters in OTP"); + nameMappingExpected.put(IdentityRecoveryConstants.ConnectorConfig.EMAIL_VERIFICATION_USE_LOWERCASE_CHARACTERS_IN_OTP, + "Include lowercase characters in OTP"); + nameMappingExpected.put(IdentityRecoveryConstants.ConnectorConfig.EMAIL_VERIFICATION_USE_NUMBERS_IN_OTP, + "Include numbers in OTP"); + nameMappingExpected.put(IdentityRecoveryConstants.ConnectorConfig.EMAIL_VERIFICATION_OTP_LENGTH, + "OTP length"); nameMappingExpected.put(IdentityRecoveryConstants.ConnectorConfig.EMAIL_ACCOUNT_LOCK_ON_CREATION, "Enable account lock on creation"); nameMappingExpected.put(IdentityRecoveryConstants.ConnectorConfig.EMAIL_VERIFICATION_NOTIFICATION_INTERNALLY_MANAGE, @@ -114,6 +124,18 @@ public void testGetPropertyDescriptionMapping() { Map descriptionMappingExpected = new HashMap<>(); descriptionMappingExpected.put(IdentityRecoveryConstants.ConnectorConfig.ENABLE_EMAIL_VERIFICATION, "A verification notification will be triggered during user creation."); + descriptionMappingExpected.put(IdentityRecoveryConstants.ConnectorConfig.EMAIL_VERIFICATION_SEND_OTP_IN_EMAIL, + "Enable to send OTP in verification e-mail instead of confirmation code."); + descriptionMappingExpected.put( + IdentityRecoveryConstants.ConnectorConfig.EMAIL_VERIFICATION_USE_UPPERCASE_CHARACTERS_IN_OTP, + "Enable to include uppercase characters in SMS and e-mail OTPs."); + descriptionMappingExpected.put( + IdentityRecoveryConstants.ConnectorConfig.EMAIL_VERIFICATION_USE_LOWERCASE_CHARACTERS_IN_OTP, + "Enable to include lowercase characters in SMS and e-mail OTPs.."); + descriptionMappingExpected.put(IdentityRecoveryConstants.ConnectorConfig.EMAIL_VERIFICATION_USE_NUMBERS_IN_OTP, + "Enable to include numbers in SMS and e-mail OTPs."); + descriptionMappingExpected.put(IdentityRecoveryConstants.ConnectorConfig.EMAIL_VERIFICATION_OTP_LENGTH, + "Length of the OTP for SMS and e-mail verifications. OTP length must be 4-10."); descriptionMappingExpected.put(IdentityRecoveryConstants.ConnectorConfig.EMAIL_ACCOUNT_LOCK_ON_CREATION, "The user account will be locked during user creation."); descriptionMappingExpected.put(IdentityRecoveryConstants.ConnectorConfig. @@ -140,6 +162,11 @@ public void testGetPropertyNames() { List propertiesExpected = new ArrayList<>(); propertiesExpected.add(IdentityRecoveryConstants.ConnectorConfig.ENABLE_EMAIL_VERIFICATION); + propertiesExpected.add(IdentityRecoveryConstants.ConnectorConfig.EMAIL_VERIFICATION_SEND_OTP_IN_EMAIL); + propertiesExpected.add(IdentityRecoveryConstants.ConnectorConfig.EMAIL_VERIFICATION_USE_UPPERCASE_CHARACTERS_IN_OTP); + propertiesExpected.add(IdentityRecoveryConstants.ConnectorConfig.EMAIL_VERIFICATION_USE_LOWERCASE_CHARACTERS_IN_OTP); + propertiesExpected.add(IdentityRecoveryConstants.ConnectorConfig.EMAIL_VERIFICATION_USE_NUMBERS_IN_OTP); + propertiesExpected.add(IdentityRecoveryConstants.ConnectorConfig.EMAIL_VERIFICATION_OTP_LENGTH); propertiesExpected.add(IdentityRecoveryConstants.ConnectorConfig.EMAIL_ACCOUNT_LOCK_ON_CREATION); propertiesExpected.add(IdentityRecoveryConstants.ConnectorConfig.EMAIL_VERIFICATION_NOTIFICATION_INTERNALLY_MANAGE); propertiesExpected.add(IdentityRecoveryConstants.ConnectorConfig.EMAIL_VERIFICATION_EXPIRY_TIME); @@ -157,6 +184,11 @@ public void testGetPropertyNames() { public void testGetDefaultPropertyValues() throws IdentityGovernanceException { String testEnableEmailVerification = "false"; + String testEnableSendOTPInEmail = "false"; + String testUseUppercaseCharactersInOTP = "true"; + String testUseLowercaseCharactersInOTP = "true"; + String testUseNumbersInOTP = "true"; + String testOtpLength = "6"; String testEnableEmailAccountLockOnCreation = "true"; String testEnableNotificationInternallyManage = "true"; String testEmailVerificationCodeExpiry = "1440"; @@ -166,6 +198,16 @@ public void testGetDefaultPropertyValues() throws IdentityGovernanceException { Map defaultPropertiesExpected = new HashMap<>(); defaultPropertiesExpected.put(IdentityRecoveryConstants.ConnectorConfig.ENABLE_EMAIL_VERIFICATION, testEnableEmailVerification); + defaultPropertiesExpected.put(IdentityRecoveryConstants.ConnectorConfig.EMAIL_VERIFICATION_SEND_OTP_IN_EMAIL, + testEnableSendOTPInEmail); + defaultPropertiesExpected.put(IdentityRecoveryConstants.ConnectorConfig.EMAIL_VERIFICATION_USE_UPPERCASE_CHARACTERS_IN_OTP, + testUseUppercaseCharactersInOTP); + defaultPropertiesExpected.put(IdentityRecoveryConstants.ConnectorConfig.EMAIL_VERIFICATION_USE_LOWERCASE_CHARACTERS_IN_OTP, + testUseLowercaseCharactersInOTP); + defaultPropertiesExpected.put(IdentityRecoveryConstants.ConnectorConfig.EMAIL_VERIFICATION_USE_NUMBERS_IN_OTP, + testUseNumbersInOTP); + defaultPropertiesExpected.put(IdentityRecoveryConstants.ConnectorConfig.EMAIL_VERIFICATION_OTP_LENGTH, + testOtpLength); defaultPropertiesExpected.put(IdentityRecoveryConstants.ConnectorConfig.EMAIL_VERIFICATION_EXPIRY_TIME, testEmailVerificationCodeExpiry); defaultPropertiesExpected.put(IdentityRecoveryConstants.ConnectorConfig.ASK_PASSWORD_EXPIRY_TIME, From 5ef06190ecd609a82840851671c2e65814aa791a Mon Sep 17 00:00:00 2001 From: shanggeeth Date: Wed, 18 Oct 2023 11:33:36 +0530 Subject: [PATCH 2/6] Use UUID from Java util --- .../main/java/org/wso2/carbon/identity/recovery/util/Utils.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 d254472f46..e111173406 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 @@ -1245,7 +1245,7 @@ public static String generateSecretKey(String channel, String recoveryScenario, otpGeneratorException.getMessage()); } } - return UUIDGenerator.generateUUID(); + return UUID.randomUUID().toString(); } /** From ccfa6d837b599297f25147cd75f12a465eec6946 Mon Sep 17 00:00:00 2001 From: shanggeeth Date: Thu, 19 Oct 2023 10:26:32 +0530 Subject: [PATCH 3/6] Fix test failures --- .../connector/RecoveryConfigImplTest.java | 6 +-- .../SelfRegistrationConfigImplTest.java | 6 +-- .../UserSelfRegistrationManagerTest.java | 47 +++++++++++++++++++ 3 files changed, 53 insertions(+), 6 deletions(-) diff --git a/components/org.wso2.carbon.identity.recovery/src/test/java/org/wso2/carbon/identity/recovery/connector/RecoveryConfigImplTest.java b/components/org.wso2.carbon.identity.recovery/src/test/java/org/wso2/carbon/identity/recovery/connector/RecoveryConfigImplTest.java index 47523dac9b..6e5ba38800 100644 --- a/components/org.wso2.carbon.identity.recovery/src/test/java/org/wso2/carbon/identity/recovery/connector/RecoveryConfigImplTest.java +++ b/components/org.wso2.carbon.identity.recovery/src/test/java/org/wso2/carbon/identity/recovery/connector/RecoveryConfigImplTest.java @@ -222,9 +222,9 @@ public void testGetDefaultPropertyValues() throws IdentityGovernanceException { String testEnableNotificationBasedPasswordRecovery = "false"; String testEnableSendOTPInEmail = "false"; - String testUseUppercaseCharactersInOTP = StringUtils.EMPTY; - String testUseLowercaseCharactersInOTP = StringUtils.EMPTY; - String testUseNumbersInOTP = StringUtils.EMPTY; + String testUseUppercaseCharactersInOTP = "true"; + String testUseLowercaseCharactersInOTP = "true"; + String testUseNumbersInOTP = "true"; String testOtpLength = "6"; String testEnableQuestionBasedPasswordRecovery = "false"; String testMinimumAnswers = "2"; diff --git a/components/org.wso2.carbon.identity.recovery/src/test/java/org/wso2/carbon/identity/recovery/connector/SelfRegistrationConfigImplTest.java b/components/org.wso2.carbon.identity.recovery/src/test/java/org/wso2/carbon/identity/recovery/connector/SelfRegistrationConfigImplTest.java index 706bc0a0cc..ecb25c8089 100644 --- a/components/org.wso2.carbon.identity.recovery/src/test/java/org/wso2/carbon/identity/recovery/connector/SelfRegistrationConfigImplTest.java +++ b/components/org.wso2.carbon.identity.recovery/src/test/java/org/wso2/carbon/identity/recovery/connector/SelfRegistrationConfigImplTest.java @@ -219,9 +219,9 @@ public void testGetDefaultPropertyValues() throws IdentityGovernanceException { String testEnableSelfSignUp = "false"; String testEnableAccountLockOnCreation = "true"; String testEnableSendOTPInEmail = "false"; - String testUseUppercaseCharactersInOTP = StringUtils.EMPTY; - String testUseLowercaseCharactersInOTP = StringUtils.EMPTY; - String testUseNumbersInOTP = StringUtils.EMPTY; + String testUseUppercaseCharactersInOTP = "true"; + String testUseLowercaseCharactersInOTP = "true"; + String testUseNumbersInOTP = "true"; String testOtpLength = "6"; String testEnableSendNotificationOnCreation = "false"; String testEnableNotificationInternallyManage = "true"; diff --git a/components/org.wso2.carbon.identity.recovery/src/test/java/org/wso2/carbon/identity/recovery/signup/UserSelfRegistrationManagerTest.java b/components/org.wso2.carbon.identity.recovery/src/test/java/org/wso2/carbon/identity/recovery/signup/UserSelfRegistrationManagerTest.java index d18ee7e959..7a294db83a 100644 --- a/components/org.wso2.carbon.identity.recovery/src/test/java/org/wso2/carbon/identity/recovery/signup/UserSelfRegistrationManagerTest.java +++ b/components/org.wso2.carbon.identity.recovery/src/test/java/org/wso2/carbon/identity/recovery/signup/UserSelfRegistrationManagerTest.java @@ -78,6 +78,11 @@ import static org.testng.Assert.assertEquals; import static org.wso2.carbon.identity.auth.attribute.handler.AuthAttributeHandlerConstants.ErrorMessages.ERROR_CODE_AUTH_ATTRIBUTE_HANDLER_NOT_FOUND; import static org.wso2.carbon.identity.recovery.IdentityRecoveryConstants.ConnectorConfig.ENABLE_SELF_SIGNUP; +import static org.wso2.carbon.identity.recovery.IdentityRecoveryConstants.ConnectorConfig.SELF_REGISTRATION_SEND_OTP_IN_EMAIL; +import static org.wso2.carbon.identity.recovery.IdentityRecoveryConstants.ConnectorConfig.SELF_REGISTRATION_USE_LOWERCASE_CHARACTERS_IN_OTP; +import static org.wso2.carbon.identity.recovery.IdentityRecoveryConstants.ConnectorConfig.SELF_REGISTRATION_USE_NUMBERS_IN_OTP; +import static org.wso2.carbon.identity.recovery.IdentityRecoveryConstants.ConnectorConfig.SELF_REGISTRATION_USE_UPPERCASE_CHARACTERS_IN_OTP; +import static org.wso2.carbon.identity.recovery.IdentityRecoveryConstants.ConnectorConfig.SELF_REGISTRATION_OTP_LENGTH; import static org.wso2.carbon.identity.recovery.IdentityRecoveryConstants.ConnectorConfig.SELF_REGISTRATION_SMSOTP_VERIFICATION_CODE_EXPIRY_TIME; import static org.wso2.carbon.identity.recovery.IdentityRecoveryConstants.ConnectorConfig.SELF_REGISTRATION_SMS_OTP_REGEX; import static org.wso2.carbon.identity.recovery.IdentityRecoveryConstants.ConnectorConfig.SELF_REGISTRATION_VERIFICATION_CODE_EXPIRY_TIME; @@ -242,6 +247,31 @@ private void mockConfigurations(String enableSelfSignUp, String enableInternalNo notificationConfig.setName(SIGN_UP_NOTIFICATION_INTERNALLY_MANAGE); notificationConfig.setValue(enableInternalNotifications); + org.wso2.carbon.identity.application.common.model.Property sendOtpInEmailConfig = + new org.wso2.carbon.identity.application.common.model.Property(); + sendOtpInEmailConfig.setName(SELF_REGISTRATION_SEND_OTP_IN_EMAIL); + sendOtpInEmailConfig.setValue("false"); + + org.wso2.carbon.identity.application.common.model.Property useLowerCaseConfig = + new org.wso2.carbon.identity.application.common.model.Property(); + useLowerCaseConfig.setName(SELF_REGISTRATION_USE_LOWERCASE_CHARACTERS_IN_OTP); + useLowerCaseConfig.setValue("true"); + + org.wso2.carbon.identity.application.common.model.Property useNumbersConfig = + new org.wso2.carbon.identity.application.common.model.Property(); + useNumbersConfig.setName(SELF_REGISTRATION_USE_NUMBERS_IN_OTP); + useNumbersConfig.setValue("true"); + + org.wso2.carbon.identity.application.common.model.Property useUpperCaseConfig = + new org.wso2.carbon.identity.application.common.model.Property(); + useUpperCaseConfig.setName(SELF_REGISTRATION_USE_UPPERCASE_CHARACTERS_IN_OTP); + useUpperCaseConfig.setValue("true"); + + org.wso2.carbon.identity.application.common.model.Property otpLengthConfig = + new org.wso2.carbon.identity.application.common.model.Property(); + otpLengthConfig.setName(SELF_REGISTRATION_OTP_LENGTH); + otpLengthConfig.setValue("6"); + org.wso2.carbon.identity.application.common.model.Property smsOTPConfig = new org.wso2.carbon.identity.application.common.model.Property(); smsOTPConfig.setName(SELF_REGISTRATION_SMS_OTP_REGEX); @@ -263,6 +293,23 @@ private void mockConfigurations(String enableSelfSignUp, String enableInternalNo when(identityGovernanceService .getConfiguration(new String[]{SIGN_UP_NOTIFICATION_INTERNALLY_MANAGE}, TEST_TENANT_DOMAIN_NAME)) .thenReturn(new org.wso2.carbon.identity.application.common.model.Property[]{notificationConfig}); + when(identityGovernanceService + .getConfiguration(new String[]{SELF_REGISTRATION_SEND_OTP_IN_EMAIL}, TEST_TENANT_DOMAIN_NAME)) + .thenReturn(new org.wso2.carbon.identity.application.common.model.Property[]{sendOtpInEmailConfig}); + when(identityGovernanceService + .getConfiguration(new String[]{SELF_REGISTRATION_USE_LOWERCASE_CHARACTERS_IN_OTP}, + TEST_TENANT_DOMAIN_NAME)) + .thenReturn(new org.wso2.carbon.identity.application.common.model.Property[]{useLowerCaseConfig}); + when(identityGovernanceService + .getConfiguration(new String[]{SELF_REGISTRATION_USE_NUMBERS_IN_OTP}, TEST_TENANT_DOMAIN_NAME)) + .thenReturn(new org.wso2.carbon.identity.application.common.model.Property[]{useNumbersConfig}); + when(identityGovernanceService + .getConfiguration(new String[]{SELF_REGISTRATION_USE_UPPERCASE_CHARACTERS_IN_OTP}, + TEST_TENANT_DOMAIN_NAME)) + .thenReturn(new org.wso2.carbon.identity.application.common.model.Property[]{useUpperCaseConfig}); + when(identityGovernanceService + .getConfiguration(new String[]{SELF_REGISTRATION_OTP_LENGTH}, TEST_TENANT_DOMAIN_NAME)) + .thenReturn(new org.wso2.carbon.identity.application.common.model.Property[]{otpLengthConfig}); when(identityGovernanceService .getConfiguration(new String[]{SELF_REGISTRATION_SMS_OTP_REGEX}, TEST_TENANT_DOMAIN_NAME)) .thenReturn(new org.wso2.carbon.identity.application.common.model.Property[]{smsOTPConfig}); From 8c8c3d4954d2bf5ff6b1c7f34aa3d320cb02ca74 Mon Sep 17 00:00:00 2001 From: shanggeeth Date: Fri, 20 Oct 2023 11:53:42 +0530 Subject: [PATCH 4/6] Send OTP in email in Ask-password flow based on the configuration --- .../recovery/handler/UserEmailVerificationHandler.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/components/org.wso2.carbon.identity.recovery/src/main/java/org/wso2/carbon/identity/recovery/handler/UserEmailVerificationHandler.java b/components/org.wso2.carbon.identity.recovery/src/main/java/org/wso2/carbon/identity/recovery/handler/UserEmailVerificationHandler.java index 18f46a13b5..924cb9cbb1 100644 --- a/components/org.wso2.carbon.identity.recovery/src/main/java/org/wso2/carbon/identity/recovery/handler/UserEmailVerificationHandler.java +++ b/components/org.wso2.carbon.identity.recovery/src/main/java/org/wso2/carbon/identity/recovery/handler/UserEmailVerificationHandler.java @@ -202,7 +202,14 @@ public void handleEvent(Event event) throws IdentityEventException { Utils.publishRecoveryEvent(eventProperties, IdentityEventConstants.Event.POST_VERIFY_EMAIL_CLAIM, confirmationCode); } else if (IdentityRecoveryConstants.ASK_PASSWORD_CLAIM.equals(claim.getClaimUri())) { - String confirmationCode = UUID.randomUUID().toString(); + String confirmationCode; + try { + confirmationCode = Utils.generateSecretKey( + NotificationChannels.EMAIL_CHANNEL.getChannelType(), RecoveryScenarios.ASK_PASSWORD.name(), + user.getTenantDomain(), "EmailVerification"); + } catch (IdentityRecoveryServerException e) { + throw new IdentityEventException("Error while fetching the OTP pattern ", e); + } if (isAccountClaimExist) { setUserClaim(IdentityRecoveryConstants.ACCOUNT_STATE_CLAIM_URI, IdentityRecoveryConstants.PENDING_ASK_PASSWORD, userStoreManager, user); From d73e2435aa46aead0bb24f144a58207fd289297c Mon Sep 17 00:00:00 2001 From: shanggeeth Date: Wed, 25 Oct 2023 15:47:37 +0530 Subject: [PATCH 5/6] Fix text formatting --- .../recovery/connector/UserEmailVerificationConfigImpl.java | 2 +- .../recovery/connector/UserEmailVerificationConfigImplTest.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/components/org.wso2.carbon.identity.recovery/src/main/java/org/wso2/carbon/identity/recovery/connector/UserEmailVerificationConfigImpl.java b/components/org.wso2.carbon.identity.recovery/src/main/java/org/wso2/carbon/identity/recovery/connector/UserEmailVerificationConfigImpl.java index 30c0ed2349..18c088556c 100644 --- a/components/org.wso2.carbon.identity.recovery/src/main/java/org/wso2/carbon/identity/recovery/connector/UserEmailVerificationConfigImpl.java +++ b/components/org.wso2.carbon.identity.recovery/src/main/java/org/wso2/carbon/identity/recovery/connector/UserEmailVerificationConfigImpl.java @@ -125,7 +125,7 @@ public Map getPropertyDescriptionMapping() { "Enable to include uppercase characters in SMS and e-mail OTPs."); descriptionMapping.put( IdentityRecoveryConstants.ConnectorConfig.EMAIL_VERIFICATION_USE_LOWERCASE_CHARACTERS_IN_OTP, - "Enable to include lowercase characters in SMS and e-mail OTPs.."); + "Enable to include lowercase characters in SMS and e-mail OTPs."); descriptionMapping.put(IdentityRecoveryConstants.ConnectorConfig.EMAIL_VERIFICATION_USE_NUMBERS_IN_OTP, "Enable to include numbers in SMS and e-mail OTPs."); descriptionMapping.put(IdentityRecoveryConstants.ConnectorConfig.EMAIL_VERIFICATION_OTP_LENGTH, diff --git a/components/org.wso2.carbon.identity.recovery/src/test/java/org/wso2/carbon/identity/recovery/connector/UserEmailVerificationConfigImplTest.java b/components/org.wso2.carbon.identity.recovery/src/test/java/org/wso2/carbon/identity/recovery/connector/UserEmailVerificationConfigImplTest.java index c7d08c749f..9af43681c3 100644 --- a/components/org.wso2.carbon.identity.recovery/src/test/java/org/wso2/carbon/identity/recovery/connector/UserEmailVerificationConfigImplTest.java +++ b/components/org.wso2.carbon.identity.recovery/src/test/java/org/wso2/carbon/identity/recovery/connector/UserEmailVerificationConfigImplTest.java @@ -133,7 +133,7 @@ public void testGetPropertyDescriptionMapping() { "Enable to include uppercase characters in SMS and e-mail OTPs."); descriptionMappingExpected.put( IdentityRecoveryConstants.ConnectorConfig.EMAIL_VERIFICATION_USE_LOWERCASE_CHARACTERS_IN_OTP, - "Enable to include lowercase characters in SMS and e-mail OTPs.."); + "Enable to include lowercase characters in SMS and e-mail OTPs."); descriptionMappingExpected.put(IdentityRecoveryConstants.ConnectorConfig.EMAIL_VERIFICATION_USE_NUMBERS_IN_OTP, "Enable to include numbers in SMS and e-mail OTPs."); descriptionMappingExpected.put(IdentityRecoveryConstants.ConnectorConfig.EMAIL_VERIFICATION_OTP_LENGTH, From 37a466ec8bc36eb2f5a3a2d160ff5a557ed99a9d Mon Sep 17 00:00:00 2001 From: shanggeeth Date: Thu, 26 Oct 2023 13:50:26 +0530 Subject: [PATCH 6/6] Address review comments --- .../internal/service/impl/otp/OTPGeneratorImpl.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/components/org.wso2.carbon.identity.governance/src/main/java/org/wso2/carbon/identity/governance/internal/service/impl/otp/OTPGeneratorImpl.java b/components/org.wso2.carbon.identity.governance/src/main/java/org/wso2/carbon/identity/governance/internal/service/impl/otp/OTPGeneratorImpl.java index 16921d52fa..cf2dbfb515 100644 --- a/components/org.wso2.carbon.identity.governance/src/main/java/org/wso2/carbon/identity/governance/internal/service/impl/otp/OTPGeneratorImpl.java +++ b/components/org.wso2.carbon.identity.governance/src/main/java/org/wso2/carbon/identity/governance/internal/service/impl/otp/OTPGeneratorImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, WSO2 LLC. (http://www.wso2.com). + * Copyright (c) 2023, WSO2 LLC. (http://www.wso2.com). * * WSO2 LLC. licenses this file to you under the Apache License, * Version 2.0 (the "License"); you may not use this file except @@ -40,7 +40,7 @@ public class OTPGeneratorImpl implements OTPGenerator { * @param useUppercaseLetters Whether uppercase characters should be used for OTP. * @param useLowercaseLetters Whether lowercase characters should be used for OTP. * @param useNumeric Whether numeric characters should be used for OTP. - * @param otpLength OTP length. + * @param otpLength OTP length. * @param recoveryScenario Recovery scenario. * @return Secret key. */