diff --git a/esignet-core/src/main/java/io/mosip/esignet/core/util/IdentityProviderUtil.java b/esignet-core/src/main/java/io/mosip/esignet/core/util/IdentityProviderUtil.java index b303b35ad..0510db7ef 100644 --- a/esignet-core/src/main/java/io/mosip/esignet/core/util/IdentityProviderUtil.java +++ b/esignet-core/src/main/java/io/mosip/esignet/core/util/IdentityProviderUtil.java @@ -52,9 +52,6 @@ import org.jose4j.jwk.RsaJsonWebKey; import org.jose4j.keys.X509Util; import org.jose4j.lang.JoseException; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import org.springframework.util.AntPathMatcher; @@ -69,7 +66,6 @@ import io.mosip.esignet.core.constants.ErrorConstants; import io.mosip.esignet.core.exception.EsignetException; import io.mosip.esignet.core.validator.RedirectURLValidator; -import jakarta.annotation.PostConstruct; import jakarta.xml.bind.DatatypeConverter; import lombok.extern.slf4j.Slf4j; @@ -77,35 +73,25 @@ @Component public class IdentityProviderUtil { - @Value("#{${mosip.esignet.public-key-hash.fields}}") - private Map> publicKeyHashFields; - - @Autowired - private RedirectURLValidator springManagedUrlValidator; - - private static final Logger logger = LoggerFactory.getLogger(IdentityProviderUtil.class); public static final String ALGO_SHA3_256 = "SHA3-256"; public static final String ALGO_SHA_256 = "SHA-256"; public static final String ALGO_SHA_1 = "SHA-1"; public static final String ALGO_MD5 = "MD5"; public static final String CHARACTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; - private static Base64.Encoder urlSafeEncoder; - private static Base64.Decoder urlSafeDecoder; - private static PathMatcher pathMatcher; - private static RedirectURLValidator urlValidator; + private static final Base64.Encoder urlSafeEncoder = Base64.getUrlEncoder().withoutPadding(); + private static final Base64.Decoder urlSafeDecoder = Base64.getUrlDecoder(); + private static final PathMatcher pathMatcher = new AntPathMatcher(); private static final ObjectMapper objectMapper = JsonMapper.builder().addModule(new JavaTimeModule()).build(); - static { - urlSafeEncoder = Base64.getUrlEncoder().withoutPadding(); - urlSafeDecoder = Base64.getUrlDecoder(); - pathMatcher = new AntPathMatcher(); - urlValidator = new RedirectURLValidator(new String[0]); // safe default; @PostConstruct replaces with configured bean - } + private final RedirectURLValidator urlValidator; + private final Map> publicKeyHashFields; - @PostConstruct - private void initStaticUrlValidator() { - urlValidator = this.springManagedUrlValidator; + public IdentityProviderUtil( + RedirectURLValidator urlValidator, + @Value("#{${mosip.esignet.public-key-hash.fields}}") Map> publicKeyHashFields) { + this.urlValidator = urlValidator; + this.publicKeyHashFields = publicKeyHashFields; } /** @@ -143,7 +129,7 @@ public static String generateHexEncodedHash(String algorithm, String value) thro byte[] hash = digest.digest(value.getBytes(StandardCharsets.UTF_8)); return Hex.encodeHexString(hash); } catch (NoSuchAlgorithmException ex) { - logger.error("Invalid algorithm : {}", algorithm, ex); + log.error("Invalid algorithm : {}", algorithm, ex); throw new EsignetException(ErrorConstants.INVALID_ALGORITHM); } } @@ -154,7 +140,7 @@ public static String generateB64EncodedHash(String algorithm, String value) thro byte[] hash = digest.digest(value.getBytes(StandardCharsets.UTF_8)); return urlSafeEncoder.encodeToString(hash); } catch (NoSuchAlgorithmException ex) { - logger.error("Invalid algorithm : {}", algorithm, ex); + log.error("Invalid algorithm : {}", algorithm, ex); throw new EsignetException(ErrorConstants.INVALID_ALGORITHM); } } @@ -165,7 +151,7 @@ public static String generateB64EncodedHash(String algorithm, byte[] bytes) thro byte[] hash = digest.digest(bytes); return urlSafeEncoder.encodeToString(hash); } catch (NoSuchAlgorithmException ex) { - logger.error("Invalid algorithm : {}", algorithm, ex); + log.error("Invalid algorithm : {}", algorithm, ex); throw new EsignetException(ErrorConstants.INVALID_ALGORITHM); } } @@ -206,7 +192,7 @@ public static long getEpochSeconds() { return ZonedDateTime.now(ZoneOffset.UTC).toEpochSecond(); } - public static void validateRedirectURI(List registeredRedirectUris, String requestedRedirectUri) throws EsignetException { + public void validateRedirectURI(List registeredRedirectUris, String requestedRedirectUri) throws EsignetException { if(registeredRedirectUris.stream().anyMatch(uri -> matchUri(uri, requestedRedirectUri))) return; @@ -237,17 +223,17 @@ public static String generateRandomAlphaNumeric(int length) { return builder.toString(); } - private static boolean matchUri(String registeredUri, String requestedUri) { + private boolean matchUri(String registeredUri, String requestedUri) { return (urlValidator.isValid(registeredUri, null) && urlValidator.isValid(requestedUri, null)) && pathMatcher.match(registeredUri, requestedUri); } - - public static byte[] generateSalt(int bytes) { - SecureRandom random = new SecureRandom(); - byte[] randomBytes = new byte[bytes]; - random.nextBytes(randomBytes); - return randomBytes; - } + + public static byte[] generateSalt(int bytes) { + SecureRandom random = new SecureRandom(); + byte[] randomBytes = new byte[bytes]; + random.nextBytes(randomBytes); + return randomBytes; + } /** * get JWK string from JWK map diff --git a/esignet-core/src/test/java/io/mosip/esignet/core/IdentityProviderUtilTest.java b/esignet-core/src/test/java/io/mosip/esignet/core/IdentityProviderUtilTest.java index 655a5ef03..8ff593624 100644 --- a/esignet-core/src/test/java/io/mosip/esignet/core/IdentityProviderUtilTest.java +++ b/esignet-core/src/test/java/io/mosip/esignet/core/IdentityProviderUtilTest.java @@ -15,13 +15,19 @@ import java.util.Arrays; import java.util.Date; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.UUID; -import javax.security.auth.x500.X500Principal; - -import org.bouncycastle.x509.X509V3CertificateGenerator; +import org.bouncycastle.asn1.x500.X500Name; +import org.bouncycastle.cert.X509CertificateHolder; +import org.bouncycastle.cert.X509v3CertificateBuilder; +import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter; +import org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder; +import org.bouncycastle.operator.ContentSigner; +import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder; import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import com.nimbusds.jose.jwk.JWK; @@ -31,136 +37,140 @@ import io.mosip.esignet.core.constants.ErrorConstants; import io.mosip.esignet.core.exception.EsignetException; import io.mosip.esignet.core.util.IdentityProviderUtil; +import io.mosip.esignet.core.validator.RedirectURLValidator; public class IdentityProviderUtilTest { + private IdentityProviderUtil identityProviderUtil; + + @BeforeEach + public void setUp() { + RedirectURLValidator validator = new RedirectURLValidator(new String[]{"corp", "internal"}); + Map> hashFields = Map.of( + "RSA", List.of("n"), + "EC", List.of("x", "y") + ); + identityProviderUtil = new IdentityProviderUtil(validator, hashFields); + } @Test public void validateRedirectURIPositiveTest() throws EsignetException { - // Simulate Spring initialisation by wiring a configured RedirectURLValidator into - // the static field via the same @PostConstruct path used at runtime. - IdentityProviderUtil util = new IdentityProviderUtil(); - org.springframework.test.util.ReflectionTestUtils.setField(util, "springManagedUrlValidator", - new io.mosip.esignet.core.validator.RedirectURLValidator( - new String[]{"corp", "internal"})); - org.springframework.test.util.ReflectionTestUtils.invokeMethod(util, "initStaticUrlValidator"); - - IdentityProviderUtil.validateRedirectURI(Arrays.asList("https://api.dev.mosip.net/**"), + identityProviderUtil.validateRedirectURI(Arrays.asList("https://api.dev.mosip.net/**"), "https://api.dev.mosip.net/home/test"); - IdentityProviderUtil.validateRedirectURI(Arrays.asList("https://api.dev.mosip.net/home/test"), + identityProviderUtil.validateRedirectURI(Arrays.asList("https://api.dev.mosip.net/home/test"), "https://api.dev.mosip.net/home/test"); - IdentityProviderUtil.validateRedirectURI(Arrays.asList("https://api.dev.mosip.net/home/test?"), + identityProviderUtil.validateRedirectURI(Arrays.asList("https://api.dev.mosip.net/home/test?"), "https://api.dev.mosip.net/home/test1"); - IdentityProviderUtil.validateRedirectURI(Arrays.asList("https://api.dev.mosip.net/home/*"), + identityProviderUtil.validateRedirectURI(Arrays.asList("https://api.dev.mosip.net/home/*"), "https://api.dev.mosip.net/home/werrrwqfdsfg5fgs34sdffggdfgsdfg?state=reefdf"); - IdentityProviderUtil.validateRedirectURI(Arrays.asList("https://api.dev.mosip.net/home/t*"), + identityProviderUtil.validateRedirectURI(Arrays.asList("https://api.dev.mosip.net/home/t*"), "https://api.dev.mosip.net/home/testament?rr=rrr"); - IdentityProviderUtil.validateRedirectURI(Arrays.asList("io.mosip.residentapp://oauth"), + identityProviderUtil.validateRedirectURI(Arrays.asList("io.mosip.residentapp://oauth"), "io.mosip.residentapp://oauth"); - IdentityProviderUtil.validateRedirectURI(Arrays.asList("https://sso.idp.corp/callback"), + identityProviderUtil.validateRedirectURI(Arrays.asList("https://sso.idp.corp/callback"), "https://sso.idp.corp/callback"); - IdentityProviderUtil.validateRedirectURI(Arrays.asList("https://portal.company.internal/**"), + identityProviderUtil.validateRedirectURI(Arrays.asList("https://portal.company.internal/**"), "https://portal.company.internal/auth/callback"); } @Test public void validateRedirectURINegativeTest() { try { - IdentityProviderUtil.validateRedirectURI(Arrays.asList("https://api.dev.mosip.net/home/test1"), + identityProviderUtil.validateRedirectURI(Arrays.asList("https://api.dev.mosip.net/home/test1"), "https://api.dev.mosip.net/home/test"); Assertions.fail(); } catch (EsignetException e) {} try { - IdentityProviderUtil.validateRedirectURI(Arrays.asList("https://api.dev.mosip.net/home/test1"), + identityProviderUtil.validateRedirectURI(Arrays.asList("https://api.dev.mosip.net/home/test1"), "https://api.dev.mosip.net/home/TEST1"); Assertions.fail(); } catch (EsignetException e) {} try { - IdentityProviderUtil.validateRedirectURI(Arrays.asList("https://api.dev.mosip.net/home**"), + identityProviderUtil.validateRedirectURI(Arrays.asList("https://api.dev.mosip.net/home**"), "https://api.dev.mosip.net/home/TEST1"); Assertions.fail(); } catch (EsignetException e) {} try { - IdentityProviderUtil.validateRedirectURI(Arrays.asList("https://api.dev.mosip.net/*"), + identityProviderUtil.validateRedirectURI(Arrays.asList("https://api.dev.mosip.net/*"), "https://api.dev.mosip.net/home/TEST1"); Assertions.fail(); } catch (EsignetException e) {} try { - IdentityProviderUtil.validateRedirectURI(Arrays.asList("https://api.dev.mosip.net/home/t*"), + identityProviderUtil.validateRedirectURI(Arrays.asList("https://api.dev.mosip.net/home/t*"), "https://api.dev.mosip.net/home/TEST1"); Assertions.fail(); } catch (EsignetException e) {} - + try { - IdentityProviderUtil.validateRedirectURI(Arrays.asList("test-url"), + identityProviderUtil.validateRedirectURI(Arrays.asList("test-url"), "https://api.dev.mosip.net/home/TEST1"); Assertions.fail(); } catch (EsignetException e) {} try { - IdentityProviderUtil.validateRedirectURI(Arrays.asList("HTTPS://DEV.MOSIP.NET/home"), - "https://dev.mosip.net/home"); + identityProviderUtil.validateRedirectURI(Arrays.asList("HTTPS://DEV.MOSIP.NET/home"), + "https://dev.mosip.net/home"); Assertions.fail(); } catch (EsignetException e) {} } - + @Test public void test_dateTime() { - Assertions.assertNotNull(IdentityProviderUtil.getUTCDateTime()); - Assertions.assertNotNull(IdentityProviderUtil.getUTCDateTimeWithNanoSeconds()); - Assertions.assertTrue(IdentityProviderUtil.getEpochSeconds() > 0); + Assertions.assertNotNull(IdentityProviderUtil.getUTCDateTime()); + Assertions.assertNotNull(IdentityProviderUtil.getUTCDateTimeWithNanoSeconds()); + Assertions.assertTrue(IdentityProviderUtil.getEpochSeconds() > 0); } - + @Test public void test_splitAndTrimValue() { - Assertions.assertTrue(IdentityProviderUtil.splitAndTrimValue("test split", " ").length == 2); - Assertions.assertTrue(IdentityProviderUtil.splitAndTrimValue(null, " ").length == 0); + Assertions.assertTrue(IdentityProviderUtil.splitAndTrimValue("test split", " ").length == 2); + Assertions.assertTrue(IdentityProviderUtil.splitAndTrimValue(null, " ").length == 0); } - + @Test public void test_generateHexEncodedHash() { - Assertions.assertNotNull(IdentityProviderUtil.generateHexEncodedHash("sha-256", "test-hexencoded-hash")); - try { - IdentityProviderUtil.generateHexEncodedHash("test-algorithm", "test"); + Assertions.assertNotNull(IdentityProviderUtil.generateHexEncodedHash("sha-256", "test-hexencoded-hash")); + try { + IdentityProviderUtil.generateHexEncodedHash("test-algorithm", "test"); Assertions.fail(); } catch (EsignetException e) {} } - + @Test public void test_generateB64EncodedHash() { - Assertions.assertNotNull(IdentityProviderUtil.generateB64EncodedHash("sha-256", "test-b64-hash")); - try { - IdentityProviderUtil.generateB64EncodedHash("test-algorithm", "test"); + Assertions.assertNotNull(IdentityProviderUtil.generateB64EncodedHash("sha-256", "test-b64-hash")); + try { + IdentityProviderUtil.generateB64EncodedHash("test-algorithm", "test"); Assertions.fail(); } catch (EsignetException e) {} } - + @Test public void test_encodeDecode() { - Assertions.assertNotNull(IdentityProviderUtil.b64Encode("test-encode-string")); - Assertions.assertNotNull(IdentityProviderUtil.b64Encode("test-bytes".getBytes())); - Assertions.assertNotNull(IdentityProviderUtil.b64Decode("test-decode-string")); + Assertions.assertNotNull(IdentityProviderUtil.b64Encode("test-encode-string")); + Assertions.assertNotNull(IdentityProviderUtil.b64Encode("test-bytes".getBytes())); + Assertions.assertNotNull(IdentityProviderUtil.b64Decode("test-decode-string")); } - + @Test public void test_generateOIDCAtHash() { - Assertions.assertNotNull(IdentityProviderUtil.generateOIDCAtHash("test-access-token")); + Assertions.assertNotNull(IdentityProviderUtil.generateOIDCAtHash("test-access-token")); } - + @Test public void test_createTransactionId() { - Assertions.assertNotNull(IdentityProviderUtil.createTransactionId(null)); - Assertions.assertNotNull(IdentityProviderUtil.createTransactionId(IdentityProviderUtil.getUTCDateTimeWithNanoSeconds())); + Assertions.assertNotNull(IdentityProviderUtil.createTransactionId(null)); + Assertions.assertNotNull(IdentityProviderUtil.createTransactionId(IdentityProviderUtil.getUTCDateTimeWithNanoSeconds())); } - + @Test public void test_generateSalt() { - Assertions.assertNotNull(IdentityProviderUtil.generateSalt(2048)); + Assertions.assertNotNull(IdentityProviderUtil.generateSalt(2048)); } - + @Test public void getJWKString_withValidAndMissingKty_thenFail() { Map jwk = new HashMap<>(); @@ -207,7 +217,7 @@ public void getJWKString_withMissingUse_thenFail() { @Test public void getJWKString_withUnsupportedKty_thenFail() { Map jwkMap = new HashMap<>(); - jwkMap.put("kty", "OCT"); // Unsupported key type + jwkMap.put("kty", "OCT"); try { IdentityProviderUtil.getJWKString(jwkMap); Assertions.fail("Expected EsignetException was not thrown"); @@ -293,22 +303,22 @@ public void getJWKString_withValidECKey_thenPass() { String jwkJson = IdentityProviderUtil.getJWKString(jwkMap); Assertions.assertTrue(jwkJson.contains("\"kty\":\"EC\"")); } - + @Test public void test_getCertificateThumbprint() throws Exception { - Assertions.assertNotNull(IdentityProviderUtil.getCertificateThumbprint("SHA-256", getCertificate())); - try { - IdentityProviderUtil.getCertificateThumbprint("test", getCertificate()); - Assertions.fail(); + Assertions.assertNotNull(IdentityProviderUtil.getCertificateThumbprint("SHA-256", getCertificate())); + try { + IdentityProviderUtil.getCertificateThumbprint("test", getCertificate()); + Assertions.fail(); } catch (EsignetException e) { - Assertions.assertEquals(e.getMessage(),ErrorConstants.INVALID_ALGORITHM); + Assertions.assertEquals(e.getMessage(), ErrorConstants.INVALID_ALGORITHM); } } @Test - public void test_generateThumbprintByCertificate()throws EsignetException{ - String thumbprint="YfRxd-cG6urE1r_Ij7yRwMzt0JHoIadZ-lqkdlE0FYo"; - String certificateString=""" + public void test_generateThumbprintByCertificate() throws EsignetException { + String thumbprint = "YfRxd-cG6urE1r_Ij7yRwMzt0JHoIadZ-lqkdlE0FYo"; + String certificateString = """ -----BEGIN CERTIFICATE----- MIICrzCCAZegAwIBAgIGAYohPDZlMA0GCSqGSIb3DQEBCwUAMBMxETAPBgNVBAMT CE1vY2stSURBMB4XDTIzMDgyMzAxNDE0OFoXDTIzMDkwMjAxNDE0OFowHjEcMBoG @@ -327,24 +337,22 @@ public void test_generateThumbprintByCertificate()throws EsignetException{ dHnX5TRuFoits1+jx3cNSBHmjA== -----END CERTIFICATE----- """; - Assertions.assertEquals(thumbprint,IdentityProviderUtil.generateCertificateThumbprint(certificateString)); + Assertions.assertEquals(thumbprint, IdentityProviderUtil.generateCertificateThumbprint(certificateString)); try { IdentityProviderUtil.generateCertificateThumbprint("test"); Assertions.fail(); } catch (EsignetException e) { - Assertions.assertEquals(e.getMessage(),ErrorConstants.INVALID_CERTIFICATE); + Assertions.assertEquals(e.getMessage(), ErrorConstants.INVALID_CERTIFICATE); } } - + public static JWK generateJWK_RSA() { - // Generate the RSA key pair try { KeyPairGenerator gen = KeyPairGenerator.getInstance("RSA"); gen.initialize(2048); KeyPair keyPair = gen.generateKeyPair(); - // Convert public key to JWK format - return new RSAKey.Builder((RSAPublicKey)keyPair.getPublic()) - .privateKey((RSAPrivateKey)keyPair.getPrivate()) + return new RSAKey.Builder((RSAPublicKey) keyPair.getPublic()) + .privateKey((RSAPrivateKey) keyPair.getPrivate()) .keyUse(KeyUse.SIGNATURE) .keyID(UUID.randomUUID().toString()) .build(); @@ -352,17 +360,21 @@ public static JWK generateJWK_RSA() { return null; } } - + private X509Certificate getCertificate() throws Exception { - X509V3CertificateGenerator generator = new X509V3CertificateGenerator(); - X500Principal dnName = new X500Principal("CN=Test"); - generator.setSubjectDN(dnName); - generator.setIssuerDN(dnName); // use the same - generator.setNotBefore(new Date(System.currentTimeMillis() - 24 * 60 * 60 * 1000)); - generator.setNotAfter(new Date(System.currentTimeMillis() + 24 * 365 * 24 * 60 * 60 * 1000)); - generator.setPublicKey(generateJWK_RSA().toRSAKey().toPublicKey()); - generator.setSignatureAlgorithm("SHA256WITHRSA"); - generator.setSerialNumber(new BigInteger(String.valueOf(System.currentTimeMillis()))); - return generator.generate(generateJWK_RSA().toRSAKey().toPrivateKey()); - } -} \ No newline at end of file + KeyPairGenerator gen = KeyPairGenerator.getInstance("RSA"); + gen.initialize(2048); + KeyPair keyPair = gen.generateKeyPair(); + + X500Name issuer = new X500Name("CN=Test"); + BigInteger serialNumber = BigInteger.valueOf(System.currentTimeMillis()); + Date notBefore = new Date(System.currentTimeMillis() - 24 * 60 * 60 * 1000); + Date notAfter = new Date(System.currentTimeMillis() + 365L * 24 * 60 * 60 * 1000); + + X509v3CertificateBuilder certBuilder = new JcaX509v3CertificateBuilder( + issuer, serialNumber, notBefore, notAfter, issuer, keyPair.getPublic()); + ContentSigner signer = new JcaContentSignerBuilder("SHA256withRSA").build(keyPair.getPrivate()); + X509CertificateHolder certHolder = certBuilder.build(signer); + return new JcaX509CertificateConverter().getCertificate(certHolder); + } +} 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 2bccc3e44..56d9e3e8e 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 @@ -123,13 +123,16 @@ public class AuthorizationServiceImpl implements AuthorizationService { @Autowired private ServerProfile serverProfile; + @Autowired + private IdentityProviderUtil identityProviderUtil; + @Override public OAuthDetailResponseV1 getOauthDetails(OAuthDetailRequest oauthDetailReqDto) throws EsignetException { ClientDetail clientDetailDto = clientManagementService.getClientDetails(oauthDetailReqDto.getClientId()); assertPARRequiredIsFalse(clientDetailDto); log.info("nonce : {} Valid client id found, proceeding to validate redirect URI", oauthDetailReqDto.getNonce()); - IdentityProviderUtil.validateRedirectURI(clientDetailDto.getRedirectUris(), oauthDetailReqDto.getRedirectUri()); + identityProviderUtil.validateRedirectURI(clientDetailDto.getRedirectUris(), oauthDetailReqDto.getRedirectUri()); OAuthDetailResponseV1 oAuthDetailResponseV1 = new OAuthDetailResponseV1(); Pair pair = checkAndBuildOIDCTransaction(oauthDetailReqDto, clientDetailDto, oAuthDetailResponseV1); oAuthDetailResponseV1 = (OAuthDetailResponseV1) pair.getFirst(); @@ -146,7 +149,7 @@ public OAuthDetailResponseV2 getOauthDetailsV2(OAuthDetailRequestV2 oauthDetailR ClientDetail clientDetailDto = clientManagementService.getClientDetails(oauthDetailReqDto.getClientId()); assertPARRequiredIsFalse(clientDetailDto); log.info("nonce : {} Valid client id found, proceeding to validate redirect URI", oauthDetailReqDto.getNonce()); - IdentityProviderUtil.validateRedirectURI(clientDetailDto.getRedirectUris(), oauthDetailReqDto.getRedirectUri()); + identityProviderUtil.validateRedirectURI(clientDetailDto.getRedirectUris(), oauthDetailReqDto.getRedirectUri()); OAuthDetailResponseV2 oAuthDetailResponseV2 = new OAuthDetailResponseV2(); // V2 path does not validate id_token_hint -> pass null for HttpServletRequest return buildTransactionAndOAuthDetailResponse(oauthDetailReqDto, clientDetailDto, oAuthDetailResponseV2, null, null); @@ -157,7 +160,7 @@ public OAuthDetailResponseV2 getOauthDetailsV3(OAuthDetailRequestV3 oauthDetailR ClientDetail clientDetailDto = clientManagementService.getClientDetails(oauthDetailReqDto.getClientId()); assertPARRequiredIsFalse(clientDetailDto); log.info("nonce : {} Valid client id found, proceeding to validate redirect URI", oauthDetailReqDto.getNonce()); - IdentityProviderUtil.validateRedirectURI(clientDetailDto.getRedirectUris(), oauthDetailReqDto.getRedirectUri()); + identityProviderUtil.validateRedirectURI(clientDetailDto.getRedirectUris(), oauthDetailReqDto.getRedirectUri()); OAuthDetailResponseV2 oAuthDetailResponseV2 = new OAuthDetailResponseV2(); return buildTransactionAndOAuthDetailResponse(oauthDetailReqDto, clientDetailDto, oAuthDetailResponseV2, oauthDetailReqDto.getIdTokenHint(), httpServletRequest); } diff --git a/oidc-service-impl/src/main/java/io/mosip/esignet/services/OAuthServiceImpl.java b/oidc-service-impl/src/main/java/io/mosip/esignet/services/OAuthServiceImpl.java index c3d714d8f..058cb84e3 100644 --- a/oidc-service-impl/src/main/java/io/mosip/esignet/services/OAuthServiceImpl.java +++ b/oidc-service-impl/src/main/java/io/mosip/esignet/services/OAuthServiceImpl.java @@ -79,6 +79,9 @@ public class OAuthServiceImpl implements OAuthService { @Autowired private ObjectMapper objectMapper; + @Autowired + private IdentityProviderUtil identityProviderUtil; + @Value("${mosip.esignet.access-token-expire-seconds:60}") private int accessTokenExpireSeconds; @@ -109,7 +112,7 @@ public TokenResponse getTokens(TokenRequestV2 tokenRequest, String dpopHeader, b validateRequestParametersWithTransaction(tokenRequest, transaction); - IdentityProviderUtil.validateRedirectURI(Collections.singletonList(transaction.getRedirectUri()), tokenRequest.getRedirect_uri()); + identityProviderUtil.validateRedirectURI(Collections.singletonList(transaction.getRedirectUri()), tokenRequest.getRedirect_uri()); if (dpopHeader != null || transaction.isDpopBoundAccessToken()) { if (dpopHeader == null) throw new EsignetException(INVALID_REQUEST); @@ -192,7 +195,7 @@ public PushedAuthorizationResponse authorize(PushedAuthorizationRequest pushedAu } log.info("nonce : {} Valid client id found, proceeding to validate redirect URI", pushedAuthorizationRequest.getNonce()); - IdentityProviderUtil.validateRedirectURI(clientDetailDto.getRedirectUris(), pushedAuthorizationRequest.getRedirect_uri()); + identityProviderUtil.validateRedirectURI(clientDetailDto.getRedirectUris(), pushedAuthorizationRequest.getRedirect_uri()); List validAudience = List.of((String) oauthServerDiscoveryMap.get(PAR_ENDPOINT), (String) oauthServerDiscoveryMap.get(TOKEN_ENDPOINT), (String) discoveryMap.get(ISSUER)); 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 4054b3729..9900eb335 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 @@ -34,6 +34,7 @@ import io.mosip.esignet.core.spi.TokenService; import io.mosip.esignet.core.util.AuthenticationContextClassRefUtil; import io.mosip.esignet.core.util.CaptchaHelper; +import io.mosip.esignet.core.util.IdentityProviderUtil; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -115,6 +116,9 @@ public class AuthorizationServiceTest { @Mock private ServerProfile serverProfile; + @Mock + IdentityProviderUtil identityProviderUtil; + private final ObjectMapper objectMapper = new ObjectMapper(); private static final String CONFIG_KEY = "auth.factor.kbi.field-details"; @@ -199,6 +203,8 @@ public void getOauthDetails_withInvalidRedirectUri_throwsException() throws Esig oauthDetailRequest.setRedirectUri("http://localhost:8088/v2/idp"); oauthDetailRequest.setNonce("test-nonce"); when(clientManagementService.getClientDetails(oauthDetailRequest.getClientId())).thenReturn(clientDetail); + doThrow(new EsignetException(ErrorConstants.INVALID_REDIRECT_URI)) + .when(identityProviderUtil).validateRedirectURI(any(), any()); try { authorizationServiceImpl.getOauthDetails(oauthDetailRequest); @@ -669,6 +675,8 @@ public void getOauthDetailsV2_withInvalidRedirectUri_throwsException() throws Es oauthDetailRequest.setRedirectUri("http://localhost:8088/v2/idp"); oauthDetailRequest.setNonce("test-nonce"); when(clientManagementService.getClientDetails(oauthDetailRequest.getClientId())).thenReturn(clientDetail); + doThrow(new EsignetException(ErrorConstants.INVALID_REDIRECT_URI)) + .when(identityProviderUtil).validateRedirectURI(any(), any()); try { authorizationServiceImpl.getOauthDetailsV2(oauthDetailRequest); diff --git a/oidc-service-impl/src/test/java/io/mosip/esignet/services/OAuthServiceTest.java b/oidc-service-impl/src/test/java/io/mosip/esignet/services/OAuthServiceTest.java index 05498d3fe..9d2ff370e 100644 --- a/oidc-service-impl/src/test/java/io/mosip/esignet/services/OAuthServiceTest.java +++ b/oidc-service-impl/src/test/java/io/mosip/esignet/services/OAuthServiceTest.java @@ -29,6 +29,7 @@ import io.mosip.esignet.core.exception.EsignetException; import io.mosip.esignet.core.spi.ClientManagementService; import io.mosip.esignet.core.spi.TokenService; +import io.mosip.esignet.core.util.IdentityProviderUtil; import io.mosip.esignet.core.util.SecurityHelperService; import io.mosip.kernel.keymanagerservice.dto.AllCertificatesDataResponseDto; import io.mosip.kernel.keymanagerservice.dto.CertificateDataResponseDto; @@ -49,9 +50,9 @@ import static io.mosip.esignet.core.constants.Constants.BEARER; import static io.mosip.esignet.core.constants.ErrorConstants.*; import static io.mosip.esignet.core.spi.OAuthService.JWT_BEARER_TYPE; +import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.mock; -import static org.mockito.ArgumentMatchers.any; import static io.mosip.esignet.core.constants.ErrorConstants.INVALID_DPOP_PROOF; @ExtendWith(MockitoExtension.class) @@ -84,6 +85,9 @@ public class OAuthServiceTest { @Mock private SecurityHelperService securityHelperService; + @Mock + private IdentityProviderUtil identityProviderUtil; + private ObjectMapper objectMapper = new ObjectMapper(); @BeforeEach