From 77dd67155794080670483f850cf7b2e9993a98a2 Mon Sep 17 00:00:00 2001 From: Md-Humair-KK Date: Wed, 11 Dec 2024 14:31:45 +0530 Subject: [PATCH 1/3] Individual ID is not validated with IDT auth factor Signed-off-by: Md-Humair-KK --- .../services/AuthorizationHelperService.java | 21 ++++++++++++---- .../services/AuthorizationServiceImpl.java | 2 +- .../AuthorizationHelperServiceTest.java | 24 ++++++++++++++++--- 3 files changed, 38 insertions(+), 9 deletions(-) diff --git a/oidc-service-impl/src/main/java/io/mosip/esignet/services/AuthorizationHelperService.java b/oidc-service-impl/src/main/java/io/mosip/esignet/services/AuthorizationHelperService.java index a4095bc2e..12fe6e347 100644 --- a/oidc-service-impl/src/main/java/io/mosip/esignet/services/AuthorizationHelperService.java +++ b/oidc-service-impl/src/main/java/io/mosip/esignet/services/AuthorizationHelperService.java @@ -213,13 +213,15 @@ protected KycAuthResult delegateAuthenticateRequest(String transactionId, String /** * Method validates challenge with "IDT" auth factor - * @param authChallenge - * @param transaction - * @param httpServletRequest - * @return + * + * @param authChallenge {@link AuthChallenge} + * @param individualId individual id from {@link AuthRequestV2} + * @param transaction {@link OIDCTransaction} + * @param httpServletRequest {@link HttpServletRequest} + * @return {@link KycAuthResult} */ protected KycAuthResult handleInternalAuthenticateRequest(@NonNull AuthChallenge authChallenge, - @NonNull OIDCTransaction transaction, HttpServletRequest httpServletRequest) { + @NotNull String individualId, @NonNull OIDCTransaction transaction, HttpServletRequest httpServletRequest) { try { JsonNode jsonNode = objectMapper.readTree(IdentityProviderUtil.b64Decode(authChallenge.getChallenge())); if(jsonNode.isNull() || jsonNode.get("token").isNull()) @@ -228,6 +230,12 @@ protected KycAuthResult handleInternalAuthenticateRequest(@NonNull AuthChallenge tokenService.verifyIdToken(token, signupIDTokenAudience); JWT jwt = JWTParser.parse(token); String subject = jwt.getJWTClaimsSet().getSubject(); + + //compares individual from auth request against subject from jwt token. + if(!individualId.equals(subject)){ + throw new EsignetException(INVALID_INDIVIDUAL_ID); + } + Optional result = Arrays.stream(httpServletRequest.getCookies()) .filter(x -> x.getName().equals(subject)) .findFirst(); @@ -246,6 +254,9 @@ protected KycAuthResult handleInternalAuthenticateRequest(@NonNull AuthChallenge result.isPresent(), haltedTransaction!=null); } catch (Exception e) { log.error("Failed to parse ID token as challenge", e); + if (e instanceof EsignetException && ((EsignetException) e).getErrorCode().equals(INVALID_INDIVIDUAL_ID)) { + throw new EsignetException(INVALID_INDIVIDUAL_ID); + } } throw new EsignetException(AUTH_FAILED); } diff --git a/oidc-service-impl/src/main/java/io/mosip/esignet/services/AuthorizationServiceImpl.java b/oidc-service-impl/src/main/java/io/mosip/esignet/services/AuthorizationServiceImpl.java index 6292e24a3..1113638ea 100644 --- a/oidc-service-impl/src/main/java/io/mosip/esignet/services/AuthorizationServiceImpl.java +++ b/oidc-service-impl/src/main/java/io/mosip/esignet/services/AuthorizationServiceImpl.java @@ -363,7 +363,7 @@ private OIDCTransaction authenticate(AuthRequest authRequest, boolean checkConse KycAuthResult kycAuthResult; if(authRequest.getChallengeList().size() == 1 && authRequest.getChallengeList().get(0).getAuthFactorType().equals("IDT")) { - kycAuthResult = authorizationHelperService.handleInternalAuthenticateRequest(authRequest.getChallengeList().get(0), transaction, + kycAuthResult = authorizationHelperService.handleInternalAuthenticateRequest(authRequest.getChallengeList().get(0),authRequest.getIndividualId(), transaction, httpServletRequest); transaction.setInternalAuthSuccess(true); } diff --git a/oidc-service-impl/src/test/java/io/mosip/esignet/services/AuthorizationHelperServiceTest.java b/oidc-service-impl/src/test/java/io/mosip/esignet/services/AuthorizationHelperServiceTest.java index 39d5180ce..d12b30197 100644 --- a/oidc-service-impl/src/test/java/io/mosip/esignet/services/AuthorizationHelperServiceTest.java +++ b/oidc-service-impl/src/test/java/io/mosip/esignet/services/AuthorizationHelperServiceTest.java @@ -515,7 +515,7 @@ public void testHandleInternalAuthenticateRequest_ValidDetails_thenPass(){ haltedTransaction.setServerNonce("subject"); Mockito.when(cacheUtilService.getHaltedTransaction(Mockito.anyString())).thenReturn(haltedTransaction); - KycAuthResult result = authorizationHelperService.handleInternalAuthenticateRequest(authChallenge, transaction, httpServletRequest); + KycAuthResult result = authorizationHelperService.handleInternalAuthenticateRequest(authChallenge, "subject", transaction, httpServletRequest); Assert.assertNotNull(result); Assert.assertEquals("subject", result.getKycToken()); @@ -523,6 +523,24 @@ public void testHandleInternalAuthenticateRequest_ValidDetails_thenPass(){ Assert.assertEquals("individualId", transaction.getIndividualId()); } + @Test + public void testHandleInternalAuthenticateRequest_InvalidIndividualId_thenFail(){ + ReflectionTestUtils.setField(authorizationHelperService, "objectMapper",objectMapper); + + AuthChallenge authChallenge = new AuthChallenge(); + authChallenge.setChallenge("eyJ0b2tlbiI6ImV5SmhiR2NpT2lKSVV6STFOaUo5LmV5SnpkV0lpT2lKemRXSnFaV04wSW4wLjl0MG5GMkNtVWZaeTlCYlA3cjM4bElhSlJSeTNaSk41MnBRNlpLSl9qVWMifQ=="); + OIDCTransaction transaction = new OIDCTransaction(); + transaction.setIndividualId("individualId"); + Mockito.doNothing().when(tokenService).verifyIdToken(any(), any()); + + try{ + authorizationHelperService.handleInternalAuthenticateRequest(authChallenge, + "invalid_individualId", transaction, httpServletRequest); + }catch(EsignetException e){ + Assert.assertEquals(INVALID_INDIVIDUAL_ID,e.getErrorCode()); + } + } + @Test public void testHandleInternalAuthenticateRequest_NoCookie_thenFail() { @@ -531,7 +549,7 @@ public void testHandleInternalAuthenticateRequest_NoCookie_thenFail() { OIDCTransaction transaction = new OIDCTransaction(); HttpServletRequest httpServletRequest = Mockito.mock(HttpServletRequest.class); try{ - authorizationHelperService.handleInternalAuthenticateRequest(authChallenge, transaction, httpServletRequest); + authorizationHelperService.handleInternalAuthenticateRequest(authChallenge, "individualId", transaction, httpServletRequest); Assert.fail(); }catch(EsignetException e){ Assert.assertEquals("auth_failed",e.getErrorCode()); @@ -544,7 +562,7 @@ public void testHandleInternalAuthenticateRequest_NoHaltedTransaction_thenFail() authChallenge.setChallenge("base64encodedchallenge"); OIDCTransaction transaction = new OIDCTransaction(); try { - authorizationHelperService.handleInternalAuthenticateRequest(authChallenge, transaction, httpServletRequest); + authorizationHelperService.handleInternalAuthenticateRequest(authChallenge, "individualId", transaction, httpServletRequest); Assert.fail(); }catch(EsignetException e) { From b92e792a42a0c9a48c36812f0edb72f63b6ec2de Mon Sep 17 00:00:00 2001 From: Md-Humair-KK Date: Thu, 12 Dec 2024 13:22:44 +0530 Subject: [PATCH 2/3] added EsignetSxception catch block instead of if condition Signed-off-by: Md-Humair-KK --- .../mosip/esignet/services/AuthorizationHelperService.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/oidc-service-impl/src/main/java/io/mosip/esignet/services/AuthorizationHelperService.java b/oidc-service-impl/src/main/java/io/mosip/esignet/services/AuthorizationHelperService.java index 12fe6e347..024a19be9 100644 --- a/oidc-service-impl/src/main/java/io/mosip/esignet/services/AuthorizationHelperService.java +++ b/oidc-service-impl/src/main/java/io/mosip/esignet/services/AuthorizationHelperService.java @@ -252,11 +252,10 @@ protected KycAuthResult handleInternalAuthenticateRequest(@NonNull AuthChallenge } log.error("ID token in the challenge is not matching the required conditions. isCookiePresent: {}, isHaltedTransactionFound: {}", result.isPresent(), haltedTransaction!=null); + } catch (EsignetException e) { + throw new EsignetException(INVALID_INDIVIDUAL_ID); } catch (Exception e) { log.error("Failed to parse ID token as challenge", e); - if (e instanceof EsignetException && ((EsignetException) e).getErrorCode().equals(INVALID_INDIVIDUAL_ID)) { - throw new EsignetException(INVALID_INDIVIDUAL_ID); - } } throw new EsignetException(AUTH_FAILED); } From 6bdef8421a7243e2ffd5efc2de4409a700d8230e Mon Sep 17 00:00:00 2001 From: Md-Humair-KK Date: Thu, 19 Dec 2024 11:28:14 +0530 Subject: [PATCH 3/3] review comments changes and test case fix Signed-off-by: Md-Humair-KK --- .../services/AuthorizationHelperService.java | 2 +- .../services/AuthorizationServiceTest.java | 36 +++++++++++++++++-- 2 files changed, 35 insertions(+), 3 deletions(-) diff --git a/oidc-service-impl/src/main/java/io/mosip/esignet/services/AuthorizationHelperService.java b/oidc-service-impl/src/main/java/io/mosip/esignet/services/AuthorizationHelperService.java index 024a19be9..815e9cb6b 100644 --- a/oidc-service-impl/src/main/java/io/mosip/esignet/services/AuthorizationHelperService.java +++ b/oidc-service-impl/src/main/java/io/mosip/esignet/services/AuthorizationHelperService.java @@ -253,7 +253,7 @@ protected KycAuthResult handleInternalAuthenticateRequest(@NonNull AuthChallenge log.error("ID token in the challenge is not matching the required conditions. isCookiePresent: {}, isHaltedTransactionFound: {}", result.isPresent(), haltedTransaction!=null); } catch (EsignetException e) { - throw new EsignetException(INVALID_INDIVIDUAL_ID); + throw e; } catch (Exception e) { log.error("Failed to parse ID token as challenge", e); } diff --git a/oidc-service-impl/src/test/java/io/mosip/esignet/services/AuthorizationServiceTest.java b/oidc-service-impl/src/test/java/io/mosip/esignet/services/AuthorizationServiceTest.java index c982a6ac9..5446f8a53 100644 --- a/oidc-service-impl/src/test/java/io/mosip/esignet/services/AuthorizationServiceTest.java +++ b/oidc-service-impl/src/test/java/io/mosip/esignet/services/AuthorizationServiceTest.java @@ -1257,7 +1257,7 @@ public void authenticateV3_enableCaptcha_thenPass() throws KycAuthException { } @Test - public void authenticateV3_withIDToken_thenPass() { + public void authenticateV3_withIDTokenInvalidIndividualId_thenFail() { String transactionId = "test-transaction"; String individualId = "23423434234"; when(cacheUtilService.getPreAuthTransaction(transactionId)).thenReturn(createIdpTransaction( @@ -1281,6 +1281,39 @@ public void authenticateV3_withIDToken_thenPass() { authChallenges.add(authChallenge); authRequest.setChallengeList(authChallenges); + try{ + AuthResponseV2 authResponseV2 = authorizationServiceImpl.authenticateUserV3(authRequest, httpServletRequest); + Assert.assertNotNull(authResponseV2); + }catch (EsignetException ex){ + Assert.assertEquals(ErrorConstants.INVALID_INDIVIDUAL_ID,ex.getErrorCode()); + } + } + + @Test + public void authenticateV3_withIDToken_thenPass() { + String transactionId = "test-transaction"; + String individualId = "subject"; + when(cacheUtilService.getPreAuthTransaction(transactionId)).thenReturn(createIdpTransaction( + new String[]{"mosip:idp:acr:id-token"})); + when(cacheUtilService.updateIndividualIdHashInPreAuthCache(transactionId, individualId)).thenReturn(createIdpTransaction( + new String[]{"mosip:idp:acr:id-token"})); + + List> allAuthFactors=new ArrayList<>(); + allAuthFactors.add(getAuthFactors("mosip:idp:acr:id-token")); + when(authenticationContextClassRefUtil.getAuthFactors(new String[]{"mosip:idp:acr:id-token"})).thenReturn(allAuthFactors); + + AuthRequestV2 authRequest = new AuthRequestV2(); + authRequest.setTransactionId(transactionId); + authRequest.setIndividualId(individualId); + authRequest.setCaptchaToken("captcha-token"); + + List authChallenges = new ArrayList<>(); + AuthChallenge authChallenge = new AuthChallenge(); + authChallenge.setAuthFactorType("IDT"); + authChallenge.setChallenge("eyJ0b2tlbiI6ImV5SmhiR2NpT2lKSVV6STFOaUo5LmV5SnpkV0lpT2lKemRXSnFaV04wSW4wLjl0MG5GMkNtVWZaeTlCYlA3cjM4bElhSlJSeTNaSk41MnBRNlpLSl9qVWMifQ=="); + authChallenges.add(authChallenge); + authRequest.setChallengeList(authChallenges); + Mockito.when(httpServletRequest.getCookies()).thenReturn(new Cookie[]{new Cookie("subject", "subject")}); OIDCTransaction haltedTransaction = new OIDCTransaction(); @@ -1294,7 +1327,6 @@ public void authenticateV3_withIDToken_thenPass() { Assert.assertNotNull(authResponseV2); } - @Test public void completeSignupRedirect_withValidTransactionId_thenPass() { String transactionId = "validTransactionId";