From 01686c88969400f8de403941b1dc4b1abc89b120 Mon Sep 17 00:00:00 2001 From: kameshsr Date: Mon, 12 Feb 2024 10:35:48 +0530 Subject: [PATCH 1/2] MOSIP-31314 OTP validation security fix Signed-off-by: kameshsr --- .../service/integration/OTPManager.java | 4 +- .../service/repository/OtpTxnRepository.java | 2 +- .../service/integration/OTPManagerTest.java | 52 +++++++++---------- 3 files changed, 29 insertions(+), 29 deletions(-) diff --git a/authentication/authentication-common/src/main/java/io/mosip/authentication/common/service/integration/OTPManager.java b/authentication/authentication-common/src/main/java/io/mosip/authentication/common/service/integration/OTPManager.java index 17b98531dfe..9ab2ad23395 100644 --- a/authentication/authentication-common/src/main/java/io/mosip/authentication/common/service/integration/OTPManager.java +++ b/authentication/authentication-common/src/main/java/io/mosip/authentication/common/service/integration/OTPManager.java @@ -105,7 +105,7 @@ public boolean sendOtp(OtpRequestDTO otpRequestDTO, String idvid, String idvidTy throws IdAuthenticationBusinessException { String refIdHash = securityManager.hash(idvid); - Optional otpEntityOpt = otpRepo.findFirstByRefIdAndStatusCodeInOrderByGeneratedDtimesDesc(refIdHash, QUERIED_STATUS_CODES); + Optional otpEntityOpt = otpRepo.findFirstByRefIdAndStatusCodeInAndGeneratedDtimesNotNullOrderByGeneratedDtimesDesc(refIdHash, QUERIED_STATUS_CODES); if(otpEntityOpt.isPresent()) { OtpTransaction otpEntity = otpEntityOpt.get(); @@ -214,7 +214,7 @@ private String generateOTP(String uin) throws IdAuthUncheckedException { */ public boolean validateOtp(String pinValue, String otpKey, String individualId) throws IdAuthenticationBusinessException { String refIdHash = securityManager.hash(individualId); - Optional otpEntityOpt = otpRepo.findFirstByRefIdAndStatusCodeInOrderByGeneratedDtimesDesc(refIdHash, QUERIED_STATUS_CODES); + Optional otpEntityOpt = otpRepo.findFirstByRefIdAndStatusCodeInAndGeneratedDtimesNotNullOrderByGeneratedDtimesDesc(refIdHash, QUERIED_STATUS_CODES); if (otpEntityOpt.isEmpty()) { throw new IdAuthenticationBusinessException(IdAuthenticationErrorConstants.OTP_REQUEST_REQUIRED); diff --git a/authentication/authentication-common/src/main/java/io/mosip/authentication/common/service/repository/OtpTxnRepository.java b/authentication/authentication-common/src/main/java/io/mosip/authentication/common/service/repository/OtpTxnRepository.java index 390da32c83b..f5ef11c11a6 100644 --- a/authentication/authentication-common/src/main/java/io/mosip/authentication/common/service/repository/OtpTxnRepository.java +++ b/authentication/authentication-common/src/main/java/io/mosip/authentication/common/service/repository/OtpTxnRepository.java @@ -19,6 +19,6 @@ public interface OtpTxnRepository extends BaseRepository * @param refIdHash the ref id hash * @return the optional */ - Optional findFirstByRefIdAndStatusCodeInOrderByGeneratedDtimesDesc(String refIdHash, List statusCodes); + Optional findFirstByRefIdAndStatusCodeInAndGeneratedDtimesNotNullOrderByGeneratedDtimesDesc(String refIdHash, List statusCodes); } diff --git a/authentication/authentication-common/src/test/java/io/mosip/authentication/common/service/integration/OTPManagerTest.java b/authentication/authentication-common/src/test/java/io/mosip/authentication/common/service/integration/OTPManagerTest.java index f679e354765..15cde441316 100644 --- a/authentication/authentication-common/src/test/java/io/mosip/authentication/common/service/integration/OTPManagerTest.java +++ b/authentication/authentication-common/src/test/java/io/mosip/authentication/common/service/integration/OTPManagerTest.java @@ -168,7 +168,7 @@ public void sendOtpTest_frozen_within30mins() throws RestServiceException, IdAut OtpTransaction entity = new OtpTransaction(); entity.setStatusCode(IdAuthCommonConstants.FROZEN); entity.setUpdDTimes(DateUtils.getUTCCurrentDateTime().minus(30, ChronoUnit.MINUTES)); - when(otpRepo.findFirstByRefIdAndStatusCodeInOrderByGeneratedDtimesDesc(Mockito.anyString(), Mockito.anyList())).thenReturn(Optional.of(entity)); + when(otpRepo.findFirstByRefIdAndStatusCodeInAndGeneratedDtimesNotNullOrderByGeneratedDtimesDesc(Mockito.anyString(), Mockito.anyList())).thenReturn(Optional.of(entity)); try { otpManager.sendOtp(otpRequestDTO, "426789089018", "UIN", valueMap, templateLanguages); } catch(IdAuthenticationBusinessException ex) { @@ -196,7 +196,7 @@ public void sendOtpTest_frozen_In31mins() throws RestServiceException, IdAuthent OtpTransaction entity = new OtpTransaction(); entity.setStatusCode(IdAuthCommonConstants.FROZEN); entity.setUpdDTimes(DateUtils.getUTCCurrentDateTime().minus(31, ChronoUnit.MINUTES)); - when(otpRepo.findFirstByRefIdAndStatusCodeInOrderByGeneratedDtimesDesc(Mockito.anyString(), Mockito.anyList())).thenReturn(Optional.of(entity)); + when(otpRepo.findFirstByRefIdAndStatusCodeInAndGeneratedDtimesNotNullOrderByGeneratedDtimesDesc(Mockito.anyString(), Mockito.anyList())).thenReturn(Optional.of(entity)); try { when(otpRepo.save(Mockito.any())).thenAnswer(invocation -> { assertEquals(IdAuthCommonConstants.ACTIVE_STATUS, ((OtpTransaction)invocation.getArguments()[0]).getStatusCode()); @@ -228,7 +228,7 @@ public void sendOtpTest_USED_entry() throws RestServiceException, IdAuthenticati OtpTransaction entity = new OtpTransaction(); entity.setStatusCode(IdAuthCommonConstants.USED_STATUS); entity.setUpdDTimes(DateUtils.getUTCCurrentDateTime().minus(31, ChronoUnit.MINUTES)); - when(otpRepo.findFirstByRefIdAndStatusCodeInOrderByGeneratedDtimesDesc(Mockito.anyString(), Mockito.anyList())).thenReturn(Optional.of(entity)); + when(otpRepo.findFirstByRefIdAndStatusCodeInAndGeneratedDtimesNotNullOrderByGeneratedDtimesDesc(Mockito.anyString(), Mockito.anyList())).thenReturn(Optional.of(entity)); try { when(otpRepo.save(Mockito.any())).thenAnswer(invocation -> { assertEquals(IdAuthCommonConstants.ACTIVE_STATUS, ((OtpTransaction)invocation.getArguments()[0]).getStatusCode()); @@ -260,7 +260,7 @@ public void sendOtpTest_frozen_within25mins() throws RestServiceException, IdAut OtpTransaction entity = new OtpTransaction(); entity.setStatusCode(IdAuthCommonConstants.FROZEN); entity.setUpdDTimes(DateUtils.getUTCCurrentDateTime().minus(25, ChronoUnit.MINUTES)); - when(otpRepo.findFirstByRefIdAndStatusCodeInOrderByGeneratedDtimesDesc(Mockito.anyString(), Mockito.anyList())).thenReturn(Optional.of(entity)); + when(otpRepo.findFirstByRefIdAndStatusCodeInAndGeneratedDtimesNotNullOrderByGeneratedDtimesDesc(Mockito.anyString(), Mockito.anyList())).thenReturn(Optional.of(entity)); try { otpManager.sendOtp(otpRequestDTO, "426789089018", "UIN", valueMap, templateLanguages); } catch(IdAuthenticationBusinessException ex) { @@ -543,7 +543,7 @@ public void TestOtpAuthFailure() otpEntity.setStatusCode(IdAuthCommonConstants.ACTIVE_STATUS); otpEntity.setOtpHash("otphash"); - Mockito.when(otpRepo.findFirstByRefIdAndStatusCodeInOrderByGeneratedDtimesDesc(Mockito.anyString(), Mockito.anyList())).thenReturn(Optional.of(otpEntity )); + Mockito.when(otpRepo.findFirstByRefIdAndStatusCodeInAndGeneratedDtimesNotNullOrderByGeneratedDtimesDesc(Mockito.anyString(), Mockito.anyList())).thenReturn(Optional.of(otpEntity )); boolean expactedOTP = otpManager.validateOtp("Test123", "123456", "426789089018"); assertFalse(expactedOTP); @@ -765,7 +765,7 @@ public void TestInvalidAttemptWith_UsedEntity() otpEntity.setStatusCode(IdAuthCommonConstants.USED_STATUS); otpEntity.setOtpHash("otphash"); - Mockito.when(otpRepo.findFirstByRefIdAndStatusCodeInOrderByGeneratedDtimesDesc(Mockito.anyString(), Mockito.anyList())).thenReturn(Optional.of(otpEntity )); + Mockito.when(otpRepo.findFirstByRefIdAndStatusCodeInAndGeneratedDtimesNotNullOrderByGeneratedDtimesDesc(Mockito.anyString(), Mockito.anyList())).thenReturn(Optional.of(otpEntity )); try { otpManager.validateOtp("Test123", "123456", "426789089018"); @@ -786,7 +786,7 @@ public void TestInvalidAttemptWith_nullUpdateCount() otpEntity.setStatusCode(IdAuthCommonConstants.ACTIVE_STATUS); otpEntity.setOtpHash("otphash"); - Mockito.when(otpRepo.findFirstByRefIdAndStatusCodeInOrderByGeneratedDtimesDesc(Mockito.anyString(), Mockito.anyList())).thenReturn(Optional.of(otpEntity )); + Mockito.when(otpRepo.findFirstByRefIdAndStatusCodeInAndGeneratedDtimesNotNullOrderByGeneratedDtimesDesc(Mockito.anyString(), Mockito.anyList())).thenReturn(Optional.of(otpEntity )); try { boolean result = otpManager.validateOtp("Test123", "123456", "426789089018"); @@ -812,7 +812,7 @@ public void TestInvalidAttemptWith_1UpdateCount() otpEntity.setValidationRetryCount(1); otpEntity.setOtpHash("otphash"); - Mockito.when(otpRepo.findFirstByRefIdAndStatusCodeInOrderByGeneratedDtimesDesc(Mockito.anyString(), Mockito.anyList())).thenReturn(Optional.of(otpEntity )); + Mockito.when(otpRepo.findFirstByRefIdAndStatusCodeInAndGeneratedDtimesNotNullOrderByGeneratedDtimesDesc(Mockito.anyString(), Mockito.anyList())).thenReturn(Optional.of(otpEntity )); try { boolean result = otpManager.validateOtp("Test123", "123456", "426789089018"); @@ -838,7 +838,7 @@ public void TestInvalidAttemptWith_4UpdateCount() otpEntity.setValidationRetryCount(4); otpEntity.setOtpHash("otphash"); - Mockito.when(otpRepo.findFirstByRefIdAndStatusCodeInOrderByGeneratedDtimesDesc(Mockito.anyString(), Mockito.anyList())).thenReturn(Optional.of(otpEntity )); + Mockito.when(otpRepo.findFirstByRefIdAndStatusCodeInAndGeneratedDtimesNotNullOrderByGeneratedDtimesDesc(Mockito.anyString(), Mockito.anyList())).thenReturn(Optional.of(otpEntity )); try { boolean result = otpManager.validateOtp("Test123", "123456", "426789089018"); @@ -865,7 +865,7 @@ public void TestInvalidAttemptWith_FrozenStatus() otpEntity.setValidationRetryCount(5); otpEntity.setOtpHash("otphash"); - Mockito.when(otpRepo.findFirstByRefIdAndStatusCodeInOrderByGeneratedDtimesDesc(Mockito.anyString(), Mockito.anyList())).thenReturn(Optional.of(otpEntity )); + Mockito.when(otpRepo.findFirstByRefIdAndStatusCodeInAndGeneratedDtimesNotNullOrderByGeneratedDtimesDesc(Mockito.anyString(), Mockito.anyList())).thenReturn(Optional.of(otpEntity )); try { otpManager.validateOtp("Test123", "123456", "426789089018"); @@ -893,7 +893,7 @@ public void TestInvalidAttemptWith_FrozenStatusWithin25Mins() otpEntity.setUpdDTimes(DateUtils.getUTCCurrentDateTime().minus(25, ChronoUnit.MINUTES)); otpEntity.setOtpHash("otphash"); - Mockito.when(otpRepo.findFirstByRefIdAndStatusCodeInOrderByGeneratedDtimesDesc(Mockito.anyString(), Mockito.anyList())).thenReturn(Optional.of(otpEntity )); + Mockito.when(otpRepo.findFirstByRefIdAndStatusCodeInAndGeneratedDtimesNotNullOrderByGeneratedDtimesDesc(Mockito.anyString(), Mockito.anyList())).thenReturn(Optional.of(otpEntity )); try { otpManager.validateOtp("Test123", "123456", "426789089018"); @@ -921,7 +921,7 @@ public void TestInvalidAttemptWith_FrozenStatusWithin29Mins() otpEntity.setUpdDTimes(DateUtils.getUTCCurrentDateTime().minus(29, ChronoUnit.MINUTES)); otpEntity.setOtpHash("otphash"); - Mockito.when(otpRepo.findFirstByRefIdAndStatusCodeInOrderByGeneratedDtimesDesc(Mockito.anyString(), Mockito.anyList())).thenReturn(Optional.of(otpEntity )); + Mockito.when(otpRepo.findFirstByRefIdAndStatusCodeInAndGeneratedDtimesNotNullOrderByGeneratedDtimesDesc(Mockito.anyString(), Mockito.anyList())).thenReturn(Optional.of(otpEntity )); try { otpManager.validateOtp("Test123", "123456", "426789089018"); @@ -949,7 +949,7 @@ public void TestInvalidAttemptWith_FrozenStatusWithin31Mins() otpEntity.setUpdDTimes(DateUtils.getUTCCurrentDateTime().minus(31, ChronoUnit.MINUTES)); otpEntity.setOtpHash("otphash"); - Mockito.when(otpRepo.findFirstByRefIdAndStatusCodeInOrderByGeneratedDtimesDesc(Mockito.anyString(), Mockito.anyList())).thenReturn(Optional.of(otpEntity )); + Mockito.when(otpRepo.findFirstByRefIdAndStatusCodeInAndGeneratedDtimesNotNullOrderByGeneratedDtimesDesc(Mockito.anyString(), Mockito.anyList())).thenReturn(Optional.of(otpEntity )); try { otpManager.validateOtp("Test123", "123456", "426789089018"); @@ -975,7 +975,7 @@ public void TestValidAttemptWith_nullUpdateCount() otpEntity.setOtpHash("313233343536234B45595F53504C49545445522354657374313233"); otpEntity.setExpiryDtimes(DateUtils.getUTCCurrentDateTime().plus(1, ChronoUnit.MINUTES)); - Mockito.when(otpRepo.findFirstByRefIdAndStatusCodeInOrderByGeneratedDtimesDesc(Mockito.anyString(), Mockito.anyList())).thenReturn(Optional.of(otpEntity )); + Mockito.when(otpRepo.findFirstByRefIdAndStatusCodeInAndGeneratedDtimesNotNullOrderByGeneratedDtimesDesc(Mockito.anyString(), Mockito.anyList())).thenReturn(Optional.of(otpEntity )); try { boolean result = otpManager.validateOtp("Test123", "123456", "426789089018"); @@ -1001,7 +1001,7 @@ public void TestValidAttemptWith_1UpdateCount() otpEntity.setOtpHash("313233343536234B45595F53504C49545445522354657374313233"); otpEntity.setExpiryDtimes(DateUtils.getUTCCurrentDateTime().plus(1, ChronoUnit.MINUTES)); - Mockito.when(otpRepo.findFirstByRefIdAndStatusCodeInOrderByGeneratedDtimesDesc(Mockito.anyString(), Mockito.anyList())).thenReturn(Optional.of(otpEntity )); + Mockito.when(otpRepo.findFirstByRefIdAndStatusCodeInAndGeneratedDtimesNotNullOrderByGeneratedDtimesDesc(Mockito.anyString(), Mockito.anyList())).thenReturn(Optional.of(otpEntity )); try { boolean result = otpManager.validateOtp("Test123", "123456", "426789089018"); @@ -1027,7 +1027,7 @@ public void TestValidAttemptWith_4UpdateCount() otpEntity.setOtpHash("313233343536234B45595F53504C49545445522354657374313233"); otpEntity.setExpiryDtimes(DateUtils.getUTCCurrentDateTime().plus(1, ChronoUnit.MINUTES)); - Mockito.when(otpRepo.findFirstByRefIdAndStatusCodeInOrderByGeneratedDtimesDesc(Mockito.anyString(), Mockito.anyList())).thenReturn(Optional.of(otpEntity )); + Mockito.when(otpRepo.findFirstByRefIdAndStatusCodeInAndGeneratedDtimesNotNullOrderByGeneratedDtimesDesc(Mockito.anyString(), Mockito.anyList())).thenReturn(Optional.of(otpEntity )); try { boolean result = otpManager.validateOtp("Test123", "123456", "426789089018"); @@ -1054,7 +1054,7 @@ public void TestValidAttemptWith_FrozenStatus() otpEntity.setOtpHash("313233343536234B45595F53504C49545445522354657374313233"); otpEntity.setExpiryDtimes(DateUtils.getUTCCurrentDateTime().plus(1, ChronoUnit.MINUTES)); - Mockito.when(otpRepo.findFirstByRefIdAndStatusCodeInOrderByGeneratedDtimesDesc(Mockito.anyString(), Mockito.anyList())).thenReturn(Optional.of(otpEntity )); + Mockito.when(otpRepo.findFirstByRefIdAndStatusCodeInAndGeneratedDtimesNotNullOrderByGeneratedDtimesDesc(Mockito.anyString(), Mockito.anyList())).thenReturn(Optional.of(otpEntity )); try { otpManager.validateOtp("Test123", "123456", "426789089018"); @@ -1083,7 +1083,7 @@ public void TestValidAttemptWith_FrozenStatusWithin25Mins() otpEntity.setOtpHash("313233343536234B45595F53504C49545445522354657374313233"); otpEntity.setExpiryDtimes(DateUtils.getUTCCurrentDateTime().plus(1, ChronoUnit.MINUTES)); - Mockito.when(otpRepo.findFirstByRefIdAndStatusCodeInOrderByGeneratedDtimesDesc(Mockito.anyString(), Mockito.anyList())).thenReturn(Optional.of(otpEntity )); + Mockito.when(otpRepo.findFirstByRefIdAndStatusCodeInAndGeneratedDtimesNotNullOrderByGeneratedDtimesDesc(Mockito.anyString(), Mockito.anyList())).thenReturn(Optional.of(otpEntity )); try { otpManager.validateOtp("Test123", "123456", "426789089018"); @@ -1112,7 +1112,7 @@ public void TestValidAttemptWith_FrozenStatusWithin29Mins() otpEntity.setOtpHash("313233343536234B45595F53504C49545445522354657374313233"); otpEntity.setExpiryDtimes(DateUtils.getUTCCurrentDateTime().plus(1, ChronoUnit.MINUTES)); - Mockito.when(otpRepo.findFirstByRefIdAndStatusCodeInOrderByGeneratedDtimesDesc(Mockito.anyString(), Mockito.anyList())).thenReturn(Optional.of(otpEntity )); + Mockito.when(otpRepo.findFirstByRefIdAndStatusCodeInAndGeneratedDtimesNotNullOrderByGeneratedDtimesDesc(Mockito.anyString(), Mockito.anyList())).thenReturn(Optional.of(otpEntity )); try { otpManager.validateOtp("Test123", "123456", "426789089018"); @@ -1141,7 +1141,7 @@ public void TestValidAttemptWith_FrozenStatusWithin31Mins() otpEntity.setOtpHash("313233343536234B45595F53504C49545445522354657374313233"); otpEntity.setExpiryDtimes(DateUtils.getUTCCurrentDateTime().plus(1, ChronoUnit.MINUTES)); - Mockito.when(otpRepo.findFirstByRefIdAndStatusCodeInOrderByGeneratedDtimesDesc(Mockito.anyString(), Mockito.anyList())).thenReturn(Optional.of(otpEntity )); + Mockito.when(otpRepo.findFirstByRefIdAndStatusCodeInAndGeneratedDtimesNotNullOrderByGeneratedDtimesDesc(Mockito.anyString(), Mockito.anyList())).thenReturn(Optional.of(otpEntity )); try { otpManager.validateOtp("Test123", "123456", "426789089018"); @@ -1168,7 +1168,7 @@ public void TestValidAttemptWith_FrozenStatusWithin31Mins_expiredOtp() otpEntity.setOtpHash("313233343536234B45595F53504C49545445522354657374313233"); otpEntity.setExpiryDtimes(DateUtils.getUTCCurrentDateTime().minus(1, ChronoUnit.MINUTES)); - Mockito.when(otpRepo.findFirstByRefIdAndStatusCodeInOrderByGeneratedDtimesDesc(Mockito.anyString(), Mockito.anyList())).thenReturn(Optional.of(otpEntity )); + Mockito.when(otpRepo.findFirstByRefIdAndStatusCodeInAndGeneratedDtimesNotNullOrderByGeneratedDtimesDesc(Mockito.anyString(), Mockito.anyList())).thenReturn(Optional.of(otpEntity )); try { otpManager.validateOtp("Test123", "123456", "426789089018"); @@ -1201,7 +1201,7 @@ public void TestThrowOtpException_UINLocked() otpEntity.setOtpHash("otphash"); otpEntity.setStatusCode(IdAuthCommonConstants.ACTIVE_STATUS); - Mockito.when(otpRepo.findFirstByRefIdAndStatusCodeInOrderByGeneratedDtimesDesc(Mockito.anyString(), Mockito.anyList())).thenReturn(Optional.of(otpEntity )); + Mockito.when(otpRepo.findFirstByRefIdAndStatusCodeInAndGeneratedDtimesNotNullOrderByGeneratedDtimesDesc(Mockito.anyString(), Mockito.anyList())).thenReturn(Optional.of(otpEntity )); try { otpManager.validateOtp("Test123", "123456", "426789089018"); @@ -1229,7 +1229,7 @@ public void TestThrowOtpException_OtpExpired() throws RestServiceException, IdAu otpEntity.setStatusCode(IdAuthCommonConstants.ACTIVE_STATUS); otpEntity.setOtpHash("otphash"); - Mockito.when(otpRepo.findFirstByRefIdAndStatusCodeInOrderByGeneratedDtimesDesc(Mockito.anyString(), Mockito.anyList())).thenReturn(Optional.of(otpEntity )); + Mockito.when(otpRepo.findFirstByRefIdAndStatusCodeInAndGeneratedDtimesNotNullOrderByGeneratedDtimesDesc(Mockito.anyString(), Mockito.anyList())).thenReturn(Optional.of(otpEntity )); try { otpManager.validateOtp("Test123", "123456", "426789089018"); @@ -1257,7 +1257,7 @@ public void TestThrowOtpException_ValidationUnsuccessful() otpEntity.setStatusCode(IdAuthCommonConstants.ACTIVE_STATUS); otpEntity.setOtpHash("otphash"); - Mockito.when(otpRepo.findFirstByRefIdAndStatusCodeInOrderByGeneratedDtimesDesc(Mockito.anyString(), Mockito.anyList())).thenReturn(Optional.of(otpEntity )); + Mockito.when(otpRepo.findFirstByRefIdAndStatusCodeInAndGeneratedDtimesNotNullOrderByGeneratedDtimesDesc(Mockito.anyString(), Mockito.anyList())).thenReturn(Optional.of(otpEntity )); try { otpManager.validateOtp("Test123", "123456", "426789089018"); } catch (IdAuthenticationBusinessException ex) { @@ -1284,7 +1284,7 @@ public void TestThrowOtpException_OtpPresent_Expired() Mockito.when(securityManager.hash(Mockito.anyString())).thenReturn("hash"); otpEntry.setStatusCode(IdAuthCommonConstants.ACTIVE_STATUS); otpEntry.setOtpHash("otphash"); - Mockito.when(otpRepo.findFirstByRefIdAndStatusCodeInOrderByGeneratedDtimesDesc(Mockito.anyString(), Mockito.anyList())).thenReturn(Optional.of(otpEntry)); + Mockito.when(otpRepo.findFirstByRefIdAndStatusCodeInAndGeneratedDtimesNotNullOrderByGeneratedDtimesDesc(Mockito.anyString(), Mockito.anyList())).thenReturn(Optional.of(otpEntry)); try { otpManager.validateOtp("Test123", "123456", "426789089018"); } catch (IdAuthenticationBusinessException ex) { @@ -1311,7 +1311,7 @@ public void TestThrowOtpException_OtpPresent_NotExpired_Valid() Mockito.when(securityManager.hash(Mockito.anyString())).thenReturn("hash"); otpEntry.setStatusCode(IdAuthCommonConstants.ACTIVE_STATUS); otpEntry.setOtpHash("otphash"); - Mockito.when(otpRepo.findFirstByRefIdAndStatusCodeInOrderByGeneratedDtimesDesc(Mockito.anyString(), Mockito.anyList())).thenReturn(Optional.of(otpEntry)); + Mockito.when(otpRepo.findFirstByRefIdAndStatusCodeInAndGeneratedDtimesNotNullOrderByGeneratedDtimesDesc(Mockito.anyString(), Mockito.anyList())).thenReturn(Optional.of(otpEntry)); try { otpManager.validateOtp("Test123", "123456", "426789089018"); } catch (IdAuthenticationBusinessException ex) { From 7156e1faed7df662f6437ed7355c74c676b3a4fc Mon Sep 17 00:00:00 2001 From: kameshsr Date: Mon, 12 Feb 2024 18:39:17 +0530 Subject: [PATCH 2/2] MOSIP-31314 OTP validation security fix Signed-off-by: kameshsr --- .../service/integration/OTPManager.java | 499 +++++++++--------- .../service/integration/OTPManagerTest.java | 144 ++--- 2 files changed, 323 insertions(+), 320 deletions(-) diff --git a/authentication/authentication-common/src/main/java/io/mosip/authentication/common/service/integration/OTPManager.java b/authentication/authentication-common/src/main/java/io/mosip/authentication/common/service/integration/OTPManager.java index 9ab2ad23395..3bc8d047a66 100644 --- a/authentication/authentication-common/src/main/java/io/mosip/authentication/common/service/integration/OTPManager.java +++ b/authentication/authentication-common/src/main/java/io/mosip/authentication/common/service/integration/OTPManager.java @@ -39,7 +39,7 @@ /** * OTPManager handling with OTP-Generation and OTP-Validation. - * + * * @author Rakesh Roshan * @author Dinesh Karuppiah.T * @author Manoj SP @@ -48,251 +48,254 @@ @Component public class OTPManager { - /** The Constant QUERIED_STATUS_CODES. */ - private static final List QUERIED_STATUS_CODES = List.of(IdAuthCommonConstants.ACTIVE_STATUS, IdAuthCommonConstants.FROZEN); - - /** The Constant OTP_EXPIRED. */ - private static final String OTP_EXPIRED = "OTP_EXPIRED"; - - /** The Constant USER_BLOCKED. */ - private static final String USER_BLOCKED = "USER_BLOCKED"; - - /** The rest helper. */ - @Autowired - private RestHelper restHelper; - - /** The rest request factory. */ - @Autowired - private RestRequestFactory restRequestFactory; - - /** The security manager. */ - @Autowired - private IdAuthSecurityManager securityManager; - - /** The otp transaction repo. */ - @Autowired - private OtpTxnRepository otpRepo; - - /** The notification service. */ - @Autowired - private NotificationService notificationService; - - /** The number of validation attempts allowed. */ - @Value("${mosip.ida.otp.validation.attempt.count.threshold:5}") - private int numberOfValidationAttemptsAllowed; - - /** The otp frozen time minutes. */ - @Value("${mosip.ida.otp.frozen.duration.minutes:30}") - private int otpFrozenTimeMinutes; - - /** The logger. */ - private static Logger logger = IdaLogger.getLogger(OTPManager.class); - - /** - * Generate OTP with information of {@link MediaType } and OTP generation - * time-out. - * - * @param otpRequestDTO the otp request DTO - * @param idvid the idvid - * @param idvidType the idvid type - * @param valueMap the value map - * @param templateLanguages the template languages - * @return String(otp) - * @throws IdAuthenticationBusinessException the id authentication business - * exception - */ - public boolean sendOtp(OtpRequestDTO otpRequestDTO, String idvid, String idvidType, Map valueMap, List templateLanguages) - throws IdAuthenticationBusinessException { - - String refIdHash = securityManager.hash(idvid); - Optional otpEntityOpt = otpRepo.findFirstByRefIdAndStatusCodeInAndGeneratedDtimesNotNullOrderByGeneratedDtimesDesc(refIdHash, QUERIED_STATUS_CODES); - - if(otpEntityOpt.isPresent()) { - OtpTransaction otpEntity = otpEntityOpt.get(); - requireOtpNotFrozen(otpEntity, false); - } - - String otp = generateOTP(otpRequestDTO.getIndividualId()); - LocalDateTime otpGenerationTime = DateUtils.getUTCCurrentDateTime(); - String otpHash = IdAuthSecurityManager.digestAsPlainText((otpRequestDTO.getIndividualId() - + EnvUtil.getKeySplitter() + otpRequestDTO.getTransactionID() - + EnvUtil.getKeySplitter() + otp).getBytes()); - - OtpTransaction otpTxn; - if (otpEntityOpt.isPresent() - && (otpTxn = otpEntityOpt.get()).getStatusCode().equals(IdAuthCommonConstants.ACTIVE_STATUS)) { - otpTxn.setOtpHash(otpHash); - otpTxn.setUpdBy(securityManager.getUser()); - otpTxn.setUpdDTimes(otpGenerationTime); - otpTxn.setGeneratedDtimes(otpGenerationTime); - otpTxn.setValidationRetryCount(0); - otpTxn.setExpiryDtimes(otpGenerationTime.plusSeconds(EnvUtil.getOtpExpiryTime())); - otpRepo.save(otpTxn); - } else { - OtpTransaction txn = new OtpTransaction(); - txn.setId(UUID.randomUUID().toString()); - txn.setRefId(securityManager.hash(otpRequestDTO.getIndividualId())); - txn.setOtpHash(otpHash); - txn.setCrBy(securityManager.getUser()); - txn.setCrDtimes(otpGenerationTime); - txn.setGeneratedDtimes(otpGenerationTime); - txn.setExpiryDtimes(otpGenerationTime.plusSeconds( - EnvUtil.getOtpExpiryTime())); - txn.setStatusCode(IdAuthCommonConstants.ACTIVE_STATUS); - otpRepo.save(txn); - } - - String notificationProperty = null; - notificationProperty = otpRequestDTO - .getOtpChannel().stream().map(channel -> NotificationType.getNotificationTypeForChannel(channel) - .stream().map(NotificationType::getName).collect(Collectors.joining())) - .collect(Collectors.joining("|")); - - notificationService.sendOTPNotification(idvid, idvidType, valueMap, templateLanguages, otp, notificationProperty, otpGenerationTime); - - return true; - } - - /** - * Creates the OTP frozen exception. - * - * @return the id authentication business exception - */ - private IdAuthenticationBusinessException createOTPFrozenException() { - return new IdAuthenticationBusinessException(IdAuthenticationErrorConstants.OTP_FROZEN.getErrorCode(), - String.format(IdAuthenticationErrorConstants.OTP_FROZEN.getErrorMessage(), - otpFrozenTimeMinutes + " seconds", numberOfValidationAttemptsAllowed)); - } - - /** - * Generate OTP. - * - * @param uin the uin - * @return the string - * @throws IdAuthUncheckedException the id auth unchecked exception - */ - private String generateOTP(String uin) throws IdAuthUncheckedException { - try { - OtpGenerateRequestDto otpGenerateRequestDto = new OtpGenerateRequestDto(uin); - RequestWrapper reqWrapper = new RequestWrapper<>(); - reqWrapper.setRequesttime(DateUtils.getUTCCurrentDateTime()); - reqWrapper.setRequest(otpGenerateRequestDto); - RestRequestDTO restRequest = restRequestFactory.buildRequest(RestServicesConstants.OTP_GENERATE_SERVICE, - reqWrapper, ResponseWrapper.class); - ResponseWrapper> response = restHelper.requestSync(restRequest); - if ( response!=null && response.getResponse()!=null && response.getResponse().get("status")!=null && response.getResponse().get("status").equals(USER_BLOCKED)) { - logger.error(IdAuthCommonConstants.SESSION_ID, this.getClass().getSimpleName(), - IdAuthenticationErrorConstants.BLOCKED_OTP_VALIDATE.getErrorCode(), USER_BLOCKED); - throw new IdAuthUncheckedException(IdAuthenticationErrorConstants.BLOCKED_OTP_VALIDATE); - } - if(response == null || response.getResponse() == null) { - throw new IdAuthUncheckedException(IdAuthenticationErrorConstants.OTP_GENERATION_FAILED); - } - return response.getResponse().get("otp"); - - } catch (IDDataValidationException e) { - logger.error(IdAuthCommonConstants.SESSION_ID, this.getClass().getSimpleName(), "generateOTP", - e.getMessage()); - throw new IdAuthUncheckedException(IdAuthenticationErrorConstants.UNABLE_TO_PROCESS, e); - } catch (RestServiceException e) { - logger.error(IdAuthCommonConstants.SESSION_ID, this.getClass().getSimpleName(), - IdAuthenticationErrorConstants.SERVER_ERROR.getErrorCode(), - IdAuthenticationErrorConstants.SERVER_ERROR.getErrorMessage()); - throw new IdAuthUncheckedException(IdAuthenticationErrorConstants.SERVER_ERROR, e); - } - } - - /** - * Validate method for OTP Validation. - * - * @param pinValue the pin value - * @param otpKey the otp key - * @param individualId the individual id - * @return true, if successful - * @throws IdAuthenticationBusinessException the id authentication business - * exception - */ - public boolean validateOtp(String pinValue, String otpKey, String individualId) throws IdAuthenticationBusinessException { - String refIdHash = securityManager.hash(individualId); - Optional otpEntityOpt = otpRepo.findFirstByRefIdAndStatusCodeInAndGeneratedDtimesNotNullOrderByGeneratedDtimesDesc(refIdHash, QUERIED_STATUS_CODES); - - if (otpEntityOpt.isEmpty()) { - throw new IdAuthenticationBusinessException(IdAuthenticationErrorConstants.OTP_REQUEST_REQUIRED); - } - - OtpTransaction otpEntity = otpEntityOpt.get(); - requireOtpNotFrozen(otpEntity, true); - - if(otpEntity.getStatusCode().equals(IdAuthCommonConstants.UNFROZEN)) { - throw new IdAuthenticationBusinessException(IdAuthenticationErrorConstants.OTP_REQUEST_REQUIRED); - } - - // At this point it should be active status alone. - // Increment the validation attempt count. - int attemptCount = otpEntity.getValidationRetryCount() == null ? 1 : otpEntity.getValidationRetryCount() + 1; - - String otpHash = getOtpHash(pinValue, otpKey); - if (otpEntity.getOtpHash().equals(otpHash)) { - otpEntity.setUpdDTimes(DateUtils.getUTCCurrentDateTime()); - otpEntity.setStatusCode(IdAuthCommonConstants.USED_STATUS); - otpRepo.save(otpEntity); - if (!otpEntity.getExpiryDtimes().isAfter(DateUtils.getUTCCurrentDateTime())) { - logger.error(IdAuthCommonConstants.SESSION_ID, this.getClass().getSimpleName(), - IdAuthenticationErrorConstants.EXPIRED_OTP.getErrorCode(), OTP_EXPIRED); - throw new IdAuthenticationBusinessException(IdAuthenticationErrorConstants.EXPIRED_OTP); - } - return true; - } else { - //Set the incremented validation attempt count - otpEntity.setValidationRetryCount(attemptCount); - if (attemptCount >= numberOfValidationAttemptsAllowed) { - otpEntity.setStatusCode(IdAuthCommonConstants.FROZEN); - } - otpEntity.setUpdDTimes(DateUtils.getUTCCurrentDateTime()); - otpRepo.save(otpEntity); - return false; - } - } - - /** - * Require otp not frozen. - * - * @param otpEntity the otp entity - * @throws IdAuthenticationBusinessException the id authentication business exception - */ - private void requireOtpNotFrozen(OtpTransaction otpEntity, boolean saveEntity) throws IdAuthenticationBusinessException { - if(otpEntity.getStatusCode().equals(IdAuthCommonConstants.FROZEN)) { - if(!isAfterFrozenDuration(otpEntity)) { - throw createOTPFrozenException(); - } - logger.info("OTP Frozen wait time is over. Allowing further."); - otpEntity.setStatusCode(IdAuthCommonConstants.UNFROZEN); - if(saveEntity) { - otpRepo.save(otpEntity); - } - } - } - - /** - * Checks if the entity is after frozen duration. - * - * @param otpEntity the otp entity - * @return true, if is after frozen duration - */ - private boolean isAfterFrozenDuration(OtpTransaction otpEntity) { - return DateUtils.getUTCCurrentDateTime().isAfter(otpEntity.getUpdDTimes().plus(otpFrozenTimeMinutes, ChronoUnit.MINUTES)); - } - - /** - * Gets the otp hash. - * - * @param pinValue the pin value - * @param otpKey the otp key - * @return the otp hash - */ - private String getOtpHash(String pinValue, String otpKey) { - return IdAuthSecurityManager.digestAsPlainText( - (otpKey + EnvUtil.getKeySplitter() + pinValue).getBytes()); - } - + /** The Constant QUERIED_STATUS_CODES. */ + private static final List QUERIED_STATUS_CODES = List.of(IdAuthCommonConstants.ACTIVE_STATUS, IdAuthCommonConstants.FROZEN); + + /** The Constant OTP_EXPIRED. */ + private static final String OTP_EXPIRED = "OTP_EXPIRED"; + + /** The Constant USER_BLOCKED. */ + private static final String USER_BLOCKED = "USER_BLOCKED"; + + /** The rest helper. */ + @Autowired + private RestHelper restHelper; + + /** The rest request factory. */ + @Autowired + private RestRequestFactory restRequestFactory; + + /** The security manager. */ + @Autowired + private IdAuthSecurityManager securityManager; + + /** The otp transaction repo. */ + @Autowired + private OtpTxnRepository otpRepo; + + /** The notification service. */ + @Autowired + private NotificationService notificationService; + + /** The number of validation attempts allowed. */ + @Value("${mosip.ida.otp.validation.attempt.count.threshold:5}") + private int numberOfValidationAttemptsAllowed; + + /** The otp frozen time minutes. */ + @Value("${mosip.ida.otp.frozen.duration.minutes:30}") + private int otpFrozenTimeMinutes; + + /** The logger. */ + private static Logger logger = IdaLogger.getLogger(OTPManager.class); + + /** + * Generate OTP with information of {@link MediaType } and OTP generation + * time-out. + * + * @param otpRequestDTO the otp request DTO + * @param idvid the idvid + * @param idvidType the idvid type + * @param valueMap the value map + * @param templateLanguages the template languages + * @return String(otp) + * @throws IdAuthenticationBusinessException the id authentication business + * exception + */ + public boolean sendOtp(OtpRequestDTO otpRequestDTO, String idvid, String idvidType, Map valueMap, List templateLanguages) + throws IdAuthenticationBusinessException { + + String refIdHash = securityManager.hash(idvid); + Optional otpEntityOpt = otpRepo.findFirstByRefIdAndStatusCodeInAndGeneratedDtimesNotNullOrderByGeneratedDtimesDesc(refIdHash, QUERIED_STATUS_CODES); + + if(otpEntityOpt.isPresent()) { + OtpTransaction otpEntity = otpEntityOpt.get(); + requireOtpNotFrozen(otpEntity, false); + } + + String otp = generateOTP(otpRequestDTO.getIndividualId()); + LocalDateTime otpGenerationTime = DateUtils.getUTCCurrentDateTime(); + String otpHash = IdAuthSecurityManager.digestAsPlainText((otpRequestDTO.getIndividualId() + + EnvUtil.getKeySplitter() + otpRequestDTO.getTransactionID() + + EnvUtil.getKeySplitter() + otp).getBytes()); + + OtpTransaction otpTxn; + if (otpEntityOpt.isPresent() + && (otpTxn = otpEntityOpt.get()).getStatusCode().equals(IdAuthCommonConstants.ACTIVE_STATUS)) { + otpTxn.setOtpHash(otpHash); + otpTxn.setUpdBy(securityManager.getUser()); + otpTxn.setUpdDTimes(otpGenerationTime); + otpTxn.setGeneratedDtimes(otpGenerationTime); + otpTxn.setValidationRetryCount(0); + otpTxn.setExpiryDtimes(otpGenerationTime.plusSeconds(EnvUtil.getOtpExpiryTime())); + otpRepo.save(otpTxn); + } else { + OtpTransaction txn = new OtpTransaction(); + txn.setId(UUID.randomUUID().toString()); + txn.setRefId(securityManager.hash(otpRequestDTO.getIndividualId())); + txn.setOtpHash(otpHash); + txn.setCrBy(securityManager.getUser()); + txn.setCrDtimes(otpGenerationTime); + txn.setGeneratedDtimes(otpGenerationTime); + txn.setExpiryDtimes(otpGenerationTime.plusSeconds( + EnvUtil.getOtpExpiryTime())); + txn.setStatusCode(IdAuthCommonConstants.ACTIVE_STATUS); + otpRepo.save(txn); + } + + String notificationProperty = null; + notificationProperty = otpRequestDTO + .getOtpChannel().stream().map(channel -> NotificationType.getNotificationTypeForChannel(channel) + .stream().map(NotificationType::getName).collect(Collectors.joining())) + .collect(Collectors.joining("|")); + + notificationService.sendOTPNotification(idvid, idvidType, valueMap, templateLanguages, otp, notificationProperty, otpGenerationTime); + + return true; + } + + /** + * Creates the OTP frozen exception. + * + * @return the id authentication business exception + */ + private IdAuthenticationBusinessException createOTPFrozenException() { + return new IdAuthenticationBusinessException(IdAuthenticationErrorConstants.OTP_FROZEN.getErrorCode(), + String.format(IdAuthenticationErrorConstants.OTP_FROZEN.getErrorMessage(), + otpFrozenTimeMinutes + " seconds", numberOfValidationAttemptsAllowed)); + } + + /** + * Generate OTP. + * + * @param uin the uin + * @return the string + * @throws IdAuthUncheckedException the id auth unchecked exception + */ + private String generateOTP(String uin) throws IdAuthUncheckedException { + try { + OtpGenerateRequestDto otpGenerateRequestDto = new OtpGenerateRequestDto(uin); + RequestWrapper reqWrapper = new RequestWrapper<>(); + reqWrapper.setRequesttime(DateUtils.getUTCCurrentDateTime()); + reqWrapper.setRequest(otpGenerateRequestDto); + RestRequestDTO restRequest = restRequestFactory.buildRequest(RestServicesConstants.OTP_GENERATE_SERVICE, + reqWrapper, ResponseWrapper.class); + ResponseWrapper> response = restHelper.requestSync(restRequest); + if ( response!=null && response.getResponse()!=null && response.getResponse().get("status")!=null && response.getResponse().get("status").equals(USER_BLOCKED)) { + logger.error(IdAuthCommonConstants.SESSION_ID, this.getClass().getSimpleName(), + IdAuthenticationErrorConstants.BLOCKED_OTP_VALIDATE.getErrorCode(), USER_BLOCKED); + throw new IdAuthUncheckedException(IdAuthenticationErrorConstants.BLOCKED_OTP_VALIDATE); + } + if(response == null || response.getResponse() == null) { + throw new IdAuthUncheckedException(IdAuthenticationErrorConstants.OTP_GENERATION_FAILED); + } + return response.getResponse().get("otp"); + + } catch (IDDataValidationException e) { + logger.error(IdAuthCommonConstants.SESSION_ID, this.getClass().getSimpleName(), "generateOTP", + e.getMessage()); + throw new IdAuthUncheckedException(IdAuthenticationErrorConstants.UNABLE_TO_PROCESS, e); + } catch (RestServiceException e) { + logger.error(IdAuthCommonConstants.SESSION_ID, this.getClass().getSimpleName(), + IdAuthenticationErrorConstants.SERVER_ERROR.getErrorCode(), + IdAuthenticationErrorConstants.SERVER_ERROR.getErrorMessage()); + throw new IdAuthUncheckedException(IdAuthenticationErrorConstants.SERVER_ERROR, e); + } + } + + /** + * Validate method for OTP Validation. + * + * @param pinValue the pin value + * @param otpKey the otp key + * @param individualId the individual id + * @return true, if successful + * @throws IdAuthenticationBusinessException the id authentication business + * exception + */ + public boolean validateOtp(String pinValue, String otpKey, String individualId) throws IdAuthenticationBusinessException { + String refIdHash = securityManager.hash(individualId); + Optional otpEntityOpt = otpRepo.findFirstByRefIdAndStatusCodeInAndGeneratedDtimesNotNullOrderByGeneratedDtimesDesc(refIdHash, QUERIED_STATUS_CODES); + + if (otpEntityOpt.isEmpty()) { + throw new IdAuthenticationBusinessException(IdAuthenticationErrorConstants.OTP_REQUEST_REQUIRED); + } + + OtpTransaction otpEntity = otpEntityOpt.get(); + requireOtpNotFrozen(otpEntity, true); + + if(otpEntity.getStatusCode().equals(IdAuthCommonConstants.UNFROZEN)) { + throw new IdAuthenticationBusinessException(IdAuthenticationErrorConstants.OTP_REQUEST_REQUIRED); + } + + // At this point it should be active status alone. + // Increment the validation attempt count. + int attemptCount = otpEntity.getValidationRetryCount() == null ? 1 : otpEntity.getValidationRetryCount() + 1; + + String otpHash = getOtpHash(pinValue, otpKey); + if (otpEntity.getOtpHash().equals(otpHash)) { + otpEntity.setUpdDTimes(DateUtils.getUTCCurrentDateTime()); + otpEntity.setStatusCode(IdAuthCommonConstants.USED_STATUS); + otpRepo.save(otpEntity); + if (!otpEntity.getExpiryDtimes().isAfter(DateUtils.getUTCCurrentDateTime())) { + logger.error(IdAuthCommonConstants.SESSION_ID, this.getClass().getSimpleName(), + IdAuthenticationErrorConstants.EXPIRED_OTP.getErrorCode(), OTP_EXPIRED); + throw new IdAuthenticationBusinessException(IdAuthenticationErrorConstants.EXPIRED_OTP); + } + return true; + } else { + //Set the incremented validation attempt count + otpEntity.setValidationRetryCount(attemptCount); + if (attemptCount >= numberOfValidationAttemptsAllowed) { + otpEntity.setStatusCode(IdAuthCommonConstants.FROZEN); + otpEntity.setUpdDTimes(DateUtils.getUTCCurrentDateTime()); + otpRepo.save(otpEntity); + throw createOTPFrozenException(); + } + otpEntity.setUpdDTimes(DateUtils.getUTCCurrentDateTime()); + otpRepo.save(otpEntity); + return false; + } + } + + /** + * Require otp not frozen. + * + * @param otpEntity the otp entity + * @throws IdAuthenticationBusinessException the id authentication business exception + */ + private void requireOtpNotFrozen(OtpTransaction otpEntity, boolean saveEntity) throws IdAuthenticationBusinessException { + if(otpEntity.getStatusCode().equals(IdAuthCommonConstants.FROZEN)) { + if(!isAfterFrozenDuration(otpEntity)) { + throw createOTPFrozenException(); + } + logger.info("OTP Frozen wait time is over. Allowing further."); + otpEntity.setStatusCode(IdAuthCommonConstants.UNFROZEN); + if(saveEntity) { + otpRepo.save(otpEntity); + } + } + } + + /** + * Checks if the entity is after frozen duration. + * + * @param otpEntity the otp entity + * @return true, if is after frozen duration + */ + private boolean isAfterFrozenDuration(OtpTransaction otpEntity) { + return DateUtils.getUTCCurrentDateTime().isAfter(otpEntity.getUpdDTimes().plus(otpFrozenTimeMinutes, ChronoUnit.MINUTES)); + } + + /** + * Gets the otp hash. + * + * @param pinValue the pin value + * @param otpKey the otp key + * @return the otp hash + */ + private String getOtpHash(String pinValue, String otpKey) { + return IdAuthSecurityManager.digestAsPlainText( + (otpKey + EnvUtil.getKeySplitter() + pinValue).getBytes()); + } + } diff --git a/authentication/authentication-common/src/test/java/io/mosip/authentication/common/service/integration/OTPManagerTest.java b/authentication/authentication-common/src/test/java/io/mosip/authentication/common/service/integration/OTPManagerTest.java index 15cde441316..b569ba19928 100644 --- a/authentication/authentication-common/src/test/java/io/mosip/authentication/common/service/integration/OTPManagerTest.java +++ b/authentication/authentication-common/src/test/java/io/mosip/authentication/common/service/integration/OTPManagerTest.java @@ -148,7 +148,7 @@ public void sendOtpTest() throws RestServiceException, IdAuthenticationBusinessE fail(); } } - + @Test public void sendOtpTest_frozen_within30mins() throws RestServiceException, IdAuthenticationBusinessException { OtpGeneratorRequestDto otpGeneratorRequestDto = getOtpGeneratorRequestDto(); @@ -176,7 +176,7 @@ public void sendOtpTest_frozen_within30mins() throws RestServiceException, IdAut assertEquals(FROZEN_ERROR_MESSAGE, ex.getErrorText()); } } - + @Test public void sendOtpTest_frozen_In31mins() throws RestServiceException, IdAuthenticationBusinessException { OtpGeneratorRequestDto otpGeneratorRequestDto = getOtpGeneratorRequestDto(); @@ -208,7 +208,7 @@ public void sendOtpTest_frozen_In31mins() throws RestServiceException, IdAuthent fail(); } } - + @Test public void sendOtpTest_USED_entry() throws RestServiceException, IdAuthenticationBusinessException { OtpGeneratorRequestDto otpGeneratorRequestDto = getOtpGeneratorRequestDto(); @@ -240,7 +240,7 @@ public void sendOtpTest_USED_entry() throws RestServiceException, IdAuthenticati fail(); } } - + @Test public void sendOtpTest_frozen_within25mins() throws RestServiceException, IdAuthenticationBusinessException { OtpGeneratorRequestDto otpGeneratorRequestDto = getOtpGeneratorRequestDto(); @@ -307,7 +307,7 @@ public void sendOtpTest_existingEntry() throws RestServiceException, IdAuthentic boolean sendOtpResponse = otpManager.sendOtp(otpRequestDTO, "426789089018", "UIN", valueMap, templateLanguages); assertEquals(sendOtpResponse, true); } - + @Test public void sendOtpTest_blockedStatus() throws RestServiceException, IdAuthenticationBusinessException { OtpGeneratorRequestDto otpGeneratorRequestDto = getOtpGeneratorRequestDto(); @@ -542,9 +542,9 @@ public void TestOtpAuthFailure() OtpTransaction otpEntity = new OtpTransaction(); otpEntity.setStatusCode(IdAuthCommonConstants.ACTIVE_STATUS); otpEntity.setOtpHash("otphash"); - + Mockito.when(otpRepo.findFirstByRefIdAndStatusCodeInAndGeneratedDtimesNotNullOrderByGeneratedDtimesDesc(Mockito.anyString(), Mockito.anyList())).thenReturn(Optional.of(otpEntity )); - + boolean expactedOTP = otpManager.validateOtp("Test123", "123456", "426789089018"); assertFalse(expactedOTP); } @@ -736,7 +736,7 @@ public void TestResponseBodyisEmpty() throws RestServiceException, IdAuthenticat valueMap.put("nameSec", "Name in SecondaryLang"); otpManager.sendOtp(otpRequestDTO, "123456", "UIN", valueMap, templateLanguages); } - + @Test public void TestInvalidAttemptWith_noEntity() throws RestServiceException, IdAuthUncheckedException, IdAuthenticationBusinessException { @@ -745,14 +745,14 @@ public void TestInvalidAttemptWith_noEntity() .thenReturn(restRequestDTO); Mockito.when(securityManager.hash(Mockito.anyString())).thenReturn("hash"); - + try { otpManager.validateOtp("Test123", "123456", "426789089018"); } catch (IdAuthenticationBusinessException ex) { assertEquals(IdAuthenticationErrorConstants.OTP_REQUEST_REQUIRED.getErrorCode(), ex.getErrorCode()); } } - + @Test public void TestInvalidAttemptWith_UsedEntity() throws RestServiceException, IdAuthUncheckedException, IdAuthenticationBusinessException { @@ -764,16 +764,16 @@ public void TestInvalidAttemptWith_UsedEntity() OtpTransaction otpEntity = new OtpTransaction(); otpEntity.setStatusCode(IdAuthCommonConstants.USED_STATUS); otpEntity.setOtpHash("otphash"); - + Mockito.when(otpRepo.findFirstByRefIdAndStatusCodeInAndGeneratedDtimesNotNullOrderByGeneratedDtimesDesc(Mockito.anyString(), Mockito.anyList())).thenReturn(Optional.of(otpEntity )); - + try { otpManager.validateOtp("Test123", "123456", "426789089018"); } catch (IdAuthenticationBusinessException ex) { assertEquals(IdAuthenticationErrorConstants.OTP_REQUEST_REQUIRED.getErrorCode(), ex.getErrorCode()); } } - + @Test public void TestInvalidAttemptWith_nullUpdateCount() throws RestServiceException, IdAuthUncheckedException, IdAuthenticationBusinessException { @@ -785,9 +785,9 @@ public void TestInvalidAttemptWith_nullUpdateCount() OtpTransaction otpEntity = new OtpTransaction(); otpEntity.setStatusCode(IdAuthCommonConstants.ACTIVE_STATUS); otpEntity.setOtpHash("otphash"); - + Mockito.when(otpRepo.findFirstByRefIdAndStatusCodeInAndGeneratedDtimesNotNullOrderByGeneratedDtimesDesc(Mockito.anyString(), Mockito.anyList())).thenReturn(Optional.of(otpEntity )); - + try { boolean result = otpManager.validateOtp("Test123", "123456", "426789089018"); assertFalse(result); @@ -798,7 +798,7 @@ public void TestInvalidAttemptWith_nullUpdateCount() fail(); } } - + @Test public void TestInvalidAttemptWith_1UpdateCount() throws RestServiceException, IdAuthUncheckedException, IdAuthenticationBusinessException { @@ -811,9 +811,9 @@ public void TestInvalidAttemptWith_1UpdateCount() otpEntity.setStatusCode(IdAuthCommonConstants.ACTIVE_STATUS); otpEntity.setValidationRetryCount(1); otpEntity.setOtpHash("otphash"); - + Mockito.when(otpRepo.findFirstByRefIdAndStatusCodeInAndGeneratedDtimesNotNullOrderByGeneratedDtimesDesc(Mockito.anyString(), Mockito.anyList())).thenReturn(Optional.of(otpEntity )); - + try { boolean result = otpManager.validateOtp("Test123", "123456", "426789089018"); assertFalse(result); @@ -824,7 +824,7 @@ public void TestInvalidAttemptWith_1UpdateCount() fail(); } } - + @Test public void TestInvalidAttemptWith_4UpdateCount() throws RestServiceException, IdAuthUncheckedException, IdAuthenticationBusinessException { @@ -837,20 +837,20 @@ public void TestInvalidAttemptWith_4UpdateCount() otpEntity.setStatusCode(IdAuthCommonConstants.ACTIVE_STATUS); otpEntity.setValidationRetryCount(4); otpEntity.setOtpHash("otphash"); - + Mockito.when(otpRepo.findFirstByRefIdAndStatusCodeInAndGeneratedDtimesNotNullOrderByGeneratedDtimesDesc(Mockito.anyString(), Mockito.anyList())).thenReturn(Optional.of(otpEntity )); - + try { - boolean result = otpManager.validateOtp("Test123", "123456", "426789089018"); - assertFalse(result); + otpManager.validateOtp("Test123", "123456", "426789089018"); + } catch (IdAuthenticationBusinessException ex) { assertEquals((long)5, (long)otpEntity.getValidationRetryCount()); assertEquals(IdAuthCommonConstants.FROZEN, otpEntity.getStatusCode()); verify(otpRepo, times(1)).save(otpEntity); - } catch (IdAuthenticationBusinessException ex) { - fail(); + assertEquals(IdAuthenticationErrorConstants.OTP_FROZEN.getErrorCode(), ex.getErrorCode()); + assertEquals(FROZEN_ERROR_MESSAGE, ex.getErrorText()); } } - + @Test public void TestInvalidAttemptWith_FrozenStatus() throws RestServiceException, IdAuthUncheckedException, IdAuthenticationBusinessException { @@ -864,9 +864,9 @@ public void TestInvalidAttemptWith_FrozenStatus() otpEntity.setUpdDTimes(DateUtils.getUTCCurrentDateTime().minus(25, ChronoUnit.MINUTES)); otpEntity.setValidationRetryCount(5); otpEntity.setOtpHash("otphash"); - + Mockito.when(otpRepo.findFirstByRefIdAndStatusCodeInAndGeneratedDtimesNotNullOrderByGeneratedDtimesDesc(Mockito.anyString(), Mockito.anyList())).thenReturn(Optional.of(otpEntity )); - + try { otpManager.validateOtp("Test123", "123456", "426789089018"); fail(); @@ -878,7 +878,7 @@ public void TestInvalidAttemptWith_FrozenStatus() assertEquals(FROZEN_ERROR_MESSAGE, ex.getErrorText()); } } - + @Test public void TestInvalidAttemptWith_FrozenStatusWithin25Mins() throws RestServiceException, IdAuthUncheckedException, IdAuthenticationBusinessException { @@ -892,9 +892,9 @@ public void TestInvalidAttemptWith_FrozenStatusWithin25Mins() otpEntity.setValidationRetryCount(5); otpEntity.setUpdDTimes(DateUtils.getUTCCurrentDateTime().minus(25, ChronoUnit.MINUTES)); otpEntity.setOtpHash("otphash"); - + Mockito.when(otpRepo.findFirstByRefIdAndStatusCodeInAndGeneratedDtimesNotNullOrderByGeneratedDtimesDesc(Mockito.anyString(), Mockito.anyList())).thenReturn(Optional.of(otpEntity )); - + try { otpManager.validateOtp("Test123", "123456", "426789089018"); fail(); @@ -906,7 +906,7 @@ public void TestInvalidAttemptWith_FrozenStatusWithin25Mins() assertEquals(FROZEN_ERROR_MESSAGE, ex.getErrorText()); } } - + @Test public void TestInvalidAttemptWith_FrozenStatusWithin29Mins() throws RestServiceException, IdAuthUncheckedException, IdAuthenticationBusinessException { @@ -920,9 +920,9 @@ public void TestInvalidAttemptWith_FrozenStatusWithin29Mins() otpEntity.setValidationRetryCount(5); otpEntity.setUpdDTimes(DateUtils.getUTCCurrentDateTime().minus(29, ChronoUnit.MINUTES)); otpEntity.setOtpHash("otphash"); - + Mockito.when(otpRepo.findFirstByRefIdAndStatusCodeInAndGeneratedDtimesNotNullOrderByGeneratedDtimesDesc(Mockito.anyString(), Mockito.anyList())).thenReturn(Optional.of(otpEntity )); - + try { otpManager.validateOtp("Test123", "123456", "426789089018"); fail(); @@ -934,7 +934,7 @@ public void TestInvalidAttemptWith_FrozenStatusWithin29Mins() assertEquals(FROZEN_ERROR_MESSAGE, ex.getErrorText()); } } - + @Test public void TestInvalidAttemptWith_FrozenStatusWithin31Mins() throws RestServiceException, IdAuthUncheckedException, IdAuthenticationBusinessException { @@ -948,9 +948,9 @@ public void TestInvalidAttemptWith_FrozenStatusWithin31Mins() otpEntity.setValidationRetryCount(5); otpEntity.setUpdDTimes(DateUtils.getUTCCurrentDateTime().minus(31, ChronoUnit.MINUTES)); otpEntity.setOtpHash("otphash"); - + Mockito.when(otpRepo.findFirstByRefIdAndStatusCodeInAndGeneratedDtimesNotNullOrderByGeneratedDtimesDesc(Mockito.anyString(), Mockito.anyList())).thenReturn(Optional.of(otpEntity )); - + try { otpManager.validateOtp("Test123", "123456", "426789089018"); } catch (IdAuthenticationBusinessException ex) { @@ -960,8 +960,8 @@ public void TestInvalidAttemptWith_FrozenStatusWithin31Mins() assertEquals(IdAuthenticationErrorConstants.OTP_REQUEST_REQUIRED.getErrorCode(), ex.getErrorCode()); } } - - + + @Test public void TestValidAttemptWith_nullUpdateCount() throws RestServiceException, IdAuthUncheckedException, IdAuthenticationBusinessException { @@ -974,9 +974,9 @@ public void TestValidAttemptWith_nullUpdateCount() otpEntity.setStatusCode(IdAuthCommonConstants.ACTIVE_STATUS); otpEntity.setOtpHash("313233343536234B45595F53504C49545445522354657374313233"); otpEntity.setExpiryDtimes(DateUtils.getUTCCurrentDateTime().plus(1, ChronoUnit.MINUTES)); - + Mockito.when(otpRepo.findFirstByRefIdAndStatusCodeInAndGeneratedDtimesNotNullOrderByGeneratedDtimesDesc(Mockito.anyString(), Mockito.anyList())).thenReturn(Optional.of(otpEntity )); - + try { boolean result = otpManager.validateOtp("Test123", "123456", "426789089018"); assertTrue(result); @@ -986,7 +986,7 @@ public void TestValidAttemptWith_nullUpdateCount() fail(); } } - + @Test public void TestValidAttemptWith_1UpdateCount() throws RestServiceException, IdAuthUncheckedException, IdAuthenticationBusinessException { @@ -1000,9 +1000,9 @@ public void TestValidAttemptWith_1UpdateCount() otpEntity.setValidationRetryCount(1); otpEntity.setOtpHash("313233343536234B45595F53504C49545445522354657374313233"); otpEntity.setExpiryDtimes(DateUtils.getUTCCurrentDateTime().plus(1, ChronoUnit.MINUTES)); - + Mockito.when(otpRepo.findFirstByRefIdAndStatusCodeInAndGeneratedDtimesNotNullOrderByGeneratedDtimesDesc(Mockito.anyString(), Mockito.anyList())).thenReturn(Optional.of(otpEntity )); - + try { boolean result = otpManager.validateOtp("Test123", "123456", "426789089018"); assertTrue(result); @@ -1012,7 +1012,7 @@ public void TestValidAttemptWith_1UpdateCount() fail(); } } - + @Test public void TestValidAttemptWith_4UpdateCount() throws RestServiceException, IdAuthUncheckedException, IdAuthenticationBusinessException { @@ -1026,9 +1026,9 @@ public void TestValidAttemptWith_4UpdateCount() otpEntity.setValidationRetryCount(4); otpEntity.setOtpHash("313233343536234B45595F53504C49545445522354657374313233"); otpEntity.setExpiryDtimes(DateUtils.getUTCCurrentDateTime().plus(1, ChronoUnit.MINUTES)); - + Mockito.when(otpRepo.findFirstByRefIdAndStatusCodeInAndGeneratedDtimesNotNullOrderByGeneratedDtimesDesc(Mockito.anyString(), Mockito.anyList())).thenReturn(Optional.of(otpEntity )); - + try { boolean result = otpManager.validateOtp("Test123", "123456", "426789089018"); assertTrue(result); @@ -1038,7 +1038,7 @@ public void TestValidAttemptWith_4UpdateCount() fail(); } } - + @Test public void TestValidAttemptWith_FrozenStatus() throws RestServiceException, IdAuthUncheckedException, IdAuthenticationBusinessException { @@ -1053,9 +1053,9 @@ public void TestValidAttemptWith_FrozenStatus() otpEntity.setValidationRetryCount(5); otpEntity.setOtpHash("313233343536234B45595F53504C49545445522354657374313233"); otpEntity.setExpiryDtimes(DateUtils.getUTCCurrentDateTime().plus(1, ChronoUnit.MINUTES)); - + Mockito.when(otpRepo.findFirstByRefIdAndStatusCodeInAndGeneratedDtimesNotNullOrderByGeneratedDtimesDesc(Mockito.anyString(), Mockito.anyList())).thenReturn(Optional.of(otpEntity )); - + try { otpManager.validateOtp("Test123", "123456", "426789089018"); fail(); @@ -1067,7 +1067,7 @@ public void TestValidAttemptWith_FrozenStatus() assertEquals(FROZEN_ERROR_MESSAGE, ex.getErrorText()); } } - + @Test public void TestValidAttemptWith_FrozenStatusWithin25Mins() throws RestServiceException, IdAuthUncheckedException, IdAuthenticationBusinessException { @@ -1082,9 +1082,9 @@ public void TestValidAttemptWith_FrozenStatusWithin25Mins() otpEntity.setUpdDTimes(DateUtils.getUTCCurrentDateTime().minus(25, ChronoUnit.MINUTES)); otpEntity.setOtpHash("313233343536234B45595F53504C49545445522354657374313233"); otpEntity.setExpiryDtimes(DateUtils.getUTCCurrentDateTime().plus(1, ChronoUnit.MINUTES)); - + Mockito.when(otpRepo.findFirstByRefIdAndStatusCodeInAndGeneratedDtimesNotNullOrderByGeneratedDtimesDesc(Mockito.anyString(), Mockito.anyList())).thenReturn(Optional.of(otpEntity )); - + try { otpManager.validateOtp("Test123", "123456", "426789089018"); fail(); @@ -1096,7 +1096,7 @@ public void TestValidAttemptWith_FrozenStatusWithin25Mins() assertEquals(FROZEN_ERROR_MESSAGE, ex.getErrorText()); } } - + @Test public void TestValidAttemptWith_FrozenStatusWithin29Mins() throws RestServiceException, IdAuthUncheckedException, IdAuthenticationBusinessException { @@ -1111,9 +1111,9 @@ public void TestValidAttemptWith_FrozenStatusWithin29Mins() otpEntity.setUpdDTimes(DateUtils.getUTCCurrentDateTime().minus(29, ChronoUnit.MINUTES)); otpEntity.setOtpHash("313233343536234B45595F53504C49545445522354657374313233"); otpEntity.setExpiryDtimes(DateUtils.getUTCCurrentDateTime().plus(1, ChronoUnit.MINUTES)); - + Mockito.when(otpRepo.findFirstByRefIdAndStatusCodeInAndGeneratedDtimesNotNullOrderByGeneratedDtimesDesc(Mockito.anyString(), Mockito.anyList())).thenReturn(Optional.of(otpEntity )); - + try { otpManager.validateOtp("Test123", "123456", "426789089018"); fail(); @@ -1125,7 +1125,7 @@ public void TestValidAttemptWith_FrozenStatusWithin29Mins() assertEquals(FROZEN_ERROR_MESSAGE, ex.getErrorText()); } } - + @Test public void TestValidAttemptWith_FrozenStatusWithin31Mins() throws RestServiceException, IdAuthUncheckedException, IdAuthenticationBusinessException { @@ -1140,9 +1140,9 @@ public void TestValidAttemptWith_FrozenStatusWithin31Mins() otpEntity.setUpdDTimes(DateUtils.getUTCCurrentDateTime().minus(31, ChronoUnit.MINUTES)); otpEntity.setOtpHash("313233343536234B45595F53504C49545445522354657374313233"); otpEntity.setExpiryDtimes(DateUtils.getUTCCurrentDateTime().plus(1, ChronoUnit.MINUTES)); - + Mockito.when(otpRepo.findFirstByRefIdAndStatusCodeInAndGeneratedDtimesNotNullOrderByGeneratedDtimesDesc(Mockito.anyString(), Mockito.anyList())).thenReturn(Optional.of(otpEntity )); - + try { otpManager.validateOtp("Test123", "123456", "426789089018"); } catch (IdAuthenticationBusinessException ex) { @@ -1152,7 +1152,7 @@ public void TestValidAttemptWith_FrozenStatusWithin31Mins() assertEquals(IdAuthenticationErrorConstants.OTP_REQUEST_REQUIRED.getErrorCode(), ex.getErrorCode()); } } - + @Test public void TestValidAttemptWith_FrozenStatusWithin31Mins_expiredOtp() throws RestServiceException, IdAuthUncheckedException, IdAuthenticationBusinessException { @@ -1167,9 +1167,9 @@ public void TestValidAttemptWith_FrozenStatusWithin31Mins_expiredOtp() otpEntity.setUpdDTimes(DateUtils.getUTCCurrentDateTime().minus(31, ChronoUnit.MINUTES)); otpEntity.setOtpHash("313233343536234B45595F53504C49545445522354657374313233"); otpEntity.setExpiryDtimes(DateUtils.getUTCCurrentDateTime().minus(1, ChronoUnit.MINUTES)); - + Mockito.when(otpRepo.findFirstByRefIdAndStatusCodeInAndGeneratedDtimesNotNullOrderByGeneratedDtimesDesc(Mockito.anyString(), Mockito.anyList())).thenReturn(Optional.of(otpEntity )); - + try { otpManager.validateOtp("Test123", "123456", "426789089018"); } catch (IdAuthenticationBusinessException ex) { @@ -1179,7 +1179,7 @@ public void TestValidAttemptWith_FrozenStatusWithin31Mins_expiredOtp() assertEquals(IdAuthenticationErrorConstants.OTP_REQUEST_REQUIRED.getErrorCode(), ex.getErrorCode()); } } - + @Test public void TestThrowOtpException_UINLocked() throws RestServiceException, IdAuthUncheckedException, IdAuthenticationBusinessException { @@ -1195,14 +1195,14 @@ public void TestThrowOtpException_UINLocked() Mockito.when(restHelper.requestSync(Mockito.any())).thenThrow(new RestServiceException( IdRepoErrorConstants.CLIENT_ERROR, responseMap.toString(), (Object) responseMap)); - + Mockito.when(securityManager.hash(Mockito.anyString())).thenReturn("hash"); OtpTransaction otpEntity = new OtpTransaction(); otpEntity.setOtpHash("otphash"); otpEntity.setStatusCode(IdAuthCommonConstants.ACTIVE_STATUS); - + Mockito.when(otpRepo.findFirstByRefIdAndStatusCodeInAndGeneratedDtimesNotNullOrderByGeneratedDtimesDesc(Mockito.anyString(), Mockito.anyList())).thenReturn(Optional.of(otpEntity )); - + try { otpManager.validateOtp("Test123", "123456", "426789089018"); } catch (IdAuthenticationBusinessException ex) { @@ -1223,14 +1223,14 @@ public void TestThrowOtpException_OtpExpired() throws RestServiceException, IdAu responseMap.put("response", valueMap); Mockito.when(restHelper.requestSync(Mockito.any())).thenThrow(new RestServiceException( IdRepoErrorConstants.CLIENT_ERROR, responseMap.toString(), (Object) responseMap)); - + Mockito.when(securityManager.hash(Mockito.anyString())).thenReturn("hash"); OtpTransaction otpEntity = new OtpTransaction(); otpEntity.setStatusCode(IdAuthCommonConstants.ACTIVE_STATUS); otpEntity.setOtpHash("otphash"); - + Mockito.when(otpRepo.findFirstByRefIdAndStatusCodeInAndGeneratedDtimesNotNullOrderByGeneratedDtimesDesc(Mockito.anyString(), Mockito.anyList())).thenReturn(Optional.of(otpEntity )); - + try { otpManager.validateOtp("Test123", "123456", "426789089018"); } catch (IdAuthenticationBusinessException ex) { @@ -1256,7 +1256,7 @@ public void TestThrowOtpException_ValidationUnsuccessful() OtpTransaction otpEntity = new OtpTransaction(); otpEntity.setStatusCode(IdAuthCommonConstants.ACTIVE_STATUS); otpEntity.setOtpHash("otphash"); - + Mockito.when(otpRepo.findFirstByRefIdAndStatusCodeInAndGeneratedDtimesNotNullOrderByGeneratedDtimesDesc(Mockito.anyString(), Mockito.anyList())).thenReturn(Optional.of(otpEntity )); try { otpManager.validateOtp("Test123", "123456", "426789089018"); @@ -1265,7 +1265,7 @@ public void TestThrowOtpException_ValidationUnsuccessful() assertEquals(IdAuthenticationErrorConstants.INVALID_OTP.getErrorMessage(), ex.getErrorText()); } } - + @Test public void TestThrowOtpException_OtpPresent_Expired() throws RestServiceException, IdAuthenticationBusinessException { @@ -1292,7 +1292,7 @@ public void TestThrowOtpException_OtpPresent_Expired() assertEquals(IdAuthenticationErrorConstants.EXPIRED_OTP.getErrorMessage(), ex.getErrorText()); } } - + @Test public void TestThrowOtpException_OtpPresent_NotExpired_Valid() throws RestServiceException, IdAuthenticationBusinessException {