From a64f7f53bf1ec89cf81270f63d669ab6a590d396 Mon Sep 17 00:00:00 2001 From: antonioT90 <34568575+antonioT90@users.noreply.github.com> Date: Wed, 29 May 2024 11:29:10 +0200 Subject: [PATCH] fix: P4ADEV-398 refactor design (#10) --- .../auth/controller/AuthControllerImpl.java | 2 +- .../payhub/auth/service/AuthService.java | 2 +- .../payhub/auth/service/AuthServiceImpl.java | 30 ++---- .../exchange/ExchangeTokenService.java | 5 + .../exchange/ExchangeTokenServiceImpl.java | 18 ++++ .../exchange/ValidateTokenService.java | 37 +++++++ .../auth/controller/AuthControllerTest.java | 4 +- .../payhub/auth/service/AuthServiceTest.java | 93 ++++-------------- .../exchange/ExchangeTokenServiceTest.java | 42 ++++++++ .../exchange/ValidateTokenServiceTest.java | 96 +++++++++++++++++++ 10 files changed, 228 insertions(+), 101 deletions(-) create mode 100644 src/main/java/it/gov/pagopa/payhub/auth/service/exchange/ExchangeTokenService.java create mode 100644 src/main/java/it/gov/pagopa/payhub/auth/service/exchange/ExchangeTokenServiceImpl.java create mode 100644 src/main/java/it/gov/pagopa/payhub/auth/service/exchange/ValidateTokenService.java create mode 100644 src/test/java/it/gov/pagopa/payhub/auth/service/exchange/ExchangeTokenServiceTest.java create mode 100644 src/test/java/it/gov/pagopa/payhub/auth/service/exchange/ValidateTokenServiceTest.java diff --git a/src/main/java/it/gov/pagopa/payhub/auth/controller/AuthControllerImpl.java b/src/main/java/it/gov/pagopa/payhub/auth/controller/AuthControllerImpl.java index bd1877d8..098a35e7 100644 --- a/src/main/java/it/gov/pagopa/payhub/auth/controller/AuthControllerImpl.java +++ b/src/main/java/it/gov/pagopa/payhub/auth/controller/AuthControllerImpl.java @@ -18,7 +18,7 @@ public AuthControllerImpl(AuthService authService) { @Override public ResponseEntity postToken(String clientId, String grantType, String subjectToken, String subjectIssuer, String subjectTokenType, String scope) { - authService.authToken(subjectToken); + authService.postToken(subjectToken); return new ResponseEntity<>(HttpStatus.OK); } } diff --git a/src/main/java/it/gov/pagopa/payhub/auth/service/AuthService.java b/src/main/java/it/gov/pagopa/payhub/auth/service/AuthService.java index 61d281ad..f65b9a7f 100644 --- a/src/main/java/it/gov/pagopa/payhub/auth/service/AuthService.java +++ b/src/main/java/it/gov/pagopa/payhub/auth/service/AuthService.java @@ -2,5 +2,5 @@ public interface AuthService { - void authToken(String token); + void postToken(String token); } diff --git a/src/main/java/it/gov/pagopa/payhub/auth/service/AuthServiceImpl.java b/src/main/java/it/gov/pagopa/payhub/auth/service/AuthServiceImpl.java index 29a01cc6..a523f87a 100644 --- a/src/main/java/it/gov/pagopa/payhub/auth/service/AuthServiceImpl.java +++ b/src/main/java/it/gov/pagopa/payhub/auth/service/AuthServiceImpl.java @@ -1,38 +1,20 @@ package it.gov.pagopa.payhub.auth.service; -import io.jsonwebtoken.Claims; -import it.gov.pagopa.payhub.auth.exception.custom.InvalidTokenException; -import it.gov.pagopa.payhub.auth.utils.JWTValidator; +import it.gov.pagopa.payhub.auth.service.exchange.ExchangeTokenService; import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; -import java.util.Map; - @Slf4j @Service public class AuthServiceImpl implements AuthService{ - private final String audience; - private final String issuer; - private final String urlJwkProvider; - private final JWTValidator jwtValidator; + private final ExchangeTokenService exchangeTokenService; - public AuthServiceImpl(@Value("${jwt.token.audience:}")String audience, - @Value("${jwt.token.issuer:}")String issuer, - @Value("${jwt.token.jwk:}")String urlJwkProvider, - JWTValidator jwtValidator) { - this.audience = audience; - this.issuer = issuer; - this.urlJwkProvider = urlJwkProvider; - this.jwtValidator = jwtValidator; + public AuthServiceImpl(ExchangeTokenService exchangeTokenService) { + this.exchangeTokenService = exchangeTokenService; } @Override - public void authToken(String token) { - Map data = jwtValidator.validate(token, urlJwkProvider); - if (!(data.get(Claims.AUDIENCE).equals(audience) && data.get(Claims.ISSUER).equals(issuer))){ - throw new InvalidTokenException("Invalid audience or issuer in the token"); - } - log.info("Token validated successfully"); + public void postToken(String token) { + exchangeTokenService.postToken(token); } } diff --git a/src/main/java/it/gov/pagopa/payhub/auth/service/exchange/ExchangeTokenService.java b/src/main/java/it/gov/pagopa/payhub/auth/service/exchange/ExchangeTokenService.java new file mode 100644 index 00000000..c536e558 --- /dev/null +++ b/src/main/java/it/gov/pagopa/payhub/auth/service/exchange/ExchangeTokenService.java @@ -0,0 +1,5 @@ +package it.gov.pagopa.payhub.auth.service.exchange; + +public interface ExchangeTokenService { + void postToken(String token); +} diff --git a/src/main/java/it/gov/pagopa/payhub/auth/service/exchange/ExchangeTokenServiceImpl.java b/src/main/java/it/gov/pagopa/payhub/auth/service/exchange/ExchangeTokenServiceImpl.java new file mode 100644 index 00000000..361b4490 --- /dev/null +++ b/src/main/java/it/gov/pagopa/payhub/auth/service/exchange/ExchangeTokenServiceImpl.java @@ -0,0 +1,18 @@ +package it.gov.pagopa.payhub.auth.service.exchange; + +import org.springframework.stereotype.Service; + +@Service +public class ExchangeTokenServiceImpl implements ExchangeTokenService{ + + private final ValidateTokenService validateTokenService; + + public ExchangeTokenServiceImpl(ValidateTokenService validateTokenService) { + this.validateTokenService = validateTokenService; + } + + @Override + public void postToken(String token) { + validateTokenService.validate(token); + } +} diff --git a/src/main/java/it/gov/pagopa/payhub/auth/service/exchange/ValidateTokenService.java b/src/main/java/it/gov/pagopa/payhub/auth/service/exchange/ValidateTokenService.java new file mode 100644 index 00000000..17139c3f --- /dev/null +++ b/src/main/java/it/gov/pagopa/payhub/auth/service/exchange/ValidateTokenService.java @@ -0,0 +1,37 @@ +package it.gov.pagopa.payhub.auth.service.exchange; + +import io.jsonwebtoken.Claims; +import it.gov.pagopa.payhub.auth.exception.custom.InvalidTokenException; +import it.gov.pagopa.payhub.auth.utils.JWTValidator; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; + +import java.util.Map; + +@Service +@Slf4j +class ValidateTokenService { + private final String audience; + private final String issuer; + private final String urlJwkProvider; + private final JWTValidator jwtValidator; + + public ValidateTokenService(@Value("${jwt.token.audience:}")String audience, + @Value("${jwt.token.issuer:}")String issuer, + @Value("${jwt.token.jwk:}")String urlJwkProvider, + JWTValidator jwtValidator) { + this.audience = audience; + this.issuer = issuer; + this.urlJwkProvider = urlJwkProvider; + this.jwtValidator = jwtValidator; + } + + public void validate(String token) { + Map data = jwtValidator.validate(token, urlJwkProvider); + if (!(data.get(Claims.AUDIENCE).equals(audience) && data.get(Claims.ISSUER).equals(issuer))){ + throw new InvalidTokenException("Invalid audience or issuer in the token"); + } + log.info("Token validated successfully"); + } +} diff --git a/src/test/java/it/gov/pagopa/payhub/auth/controller/AuthControllerTest.java b/src/test/java/it/gov/pagopa/payhub/auth/controller/AuthControllerTest.java index 3e575957..25179fa8 100644 --- a/src/test/java/it/gov/pagopa/payhub/auth/controller/AuthControllerTest.java +++ b/src/test/java/it/gov/pagopa/payhub/auth/controller/AuthControllerTest.java @@ -32,7 +32,7 @@ class AuthControllerTest { @Test void givenExpectedAuthTokenThenOk() throws Exception { - doNothing().when(authServiceMock).authToken("token"); + doNothing().when(authServiceMock).postToken("token"); MvcResult result = mockMvc.perform( post("/payhub/auth/token") @@ -49,7 +49,7 @@ void givenExpectedAuthTokenThenOk() throws Exception { @Test void givenRequestWithoutAuthTokenThenBadRequest() throws Exception { - doNothing().when(authServiceMock).authToken("token"); + doNothing().when(authServiceMock).postToken("token"); MvcResult result = mockMvc.perform( post("/payhub/auth/token") diff --git a/src/test/java/it/gov/pagopa/payhub/auth/service/AuthServiceTest.java b/src/test/java/it/gov/pagopa/payhub/auth/service/AuthServiceTest.java index d830ee44..1104df4f 100644 --- a/src/test/java/it/gov/pagopa/payhub/auth/service/AuthServiceTest.java +++ b/src/test/java/it/gov/pagopa/payhub/auth/service/AuthServiceTest.java @@ -1,96 +1,43 @@ package it.gov.pagopa.payhub.auth.service; -import com.github.tomakehurst.wiremock.WireMockServer; -import it.gov.pagopa.payhub.auth.exception.custom.InvalidTokenException; -import it.gov.pagopa.payhub.auth.utils.JWTValidator; -import it.gov.pagopa.payhub.auth.utils.JWTValidatorUtils; +import it.gov.pagopa.payhub.auth.service.exchange.ExchangeTokenService; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.Mock; import org.mockito.Mockito; -import org.springframework.test.context.junit.jupiter.SpringExtension; +import org.mockito.junit.jupiter.MockitoExtension; -import java.util.Date; -import java.util.HashMap; -import java.util.Map; - -import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.when; - -@ExtendWith(SpringExtension.class) -public class AuthServiceTest { - - public static final Date EXPIRES_AT = new Date(System.currentTimeMillis() + 3600000); - private static final String AUD = "AUD"; - private static final String ISS = "ISS"; - - private AuthService authService; - private WireMockServer wireMockServer; - private JWTValidatorUtils utils; +@ExtendWith(MockitoExtension.class) +class AuthServiceTest { @Mock - private JWTValidator jwtValidator; + private ExchangeTokenService exchangeTokenServiceMock; + + private AuthService service; @BeforeEach - void setup(){ - wireMockServer = new WireMockServer(wireMockConfig().dynamicPort()); - wireMockServer.start(); - utils = new JWTValidatorUtils(wireMockServer); - authService = new AuthServiceImpl(AUD, ISS, utils.getUrlJwkProvider(), jwtValidator); + void init(){ + service = new AuthServiceImpl(exchangeTokenServiceMock); } @AfterEach - void clean(){ - wireMockServer.stop(); - } - @Test - void authTokenOk() throws Exception { - String token = utils.generateJWK(EXPIRES_AT); - Map claimsMap = createJWKClaims(ISS, AUD); - - String wireMockUrl = utils.getUrlJwkProvider(); - when(jwtValidator.validate(token, wireMockUrl)).thenReturn(claimsMap); - - authService.authToken(token); - Mockito.verify(jwtValidator, times(1)).validate(token, wireMockUrl); + void verifyNotMoreInteractions(){ + Mockito.verifyNoMoreInteractions( + exchangeTokenServiceMock + ); } @Test - void authTokenWrongIss() throws Exception { - String token = utils.generateJWK(EXPIRES_AT); - Map claimsMap = createJWKClaims("ISS_FAKE", AUD); + void whenPostTokenThenCallExchangeService(){ + // Given + String token = "TOKEN"; - String wireMockUrl = utils.getUrlJwkProvider(); - when(jwtValidator.validate(token, wireMockUrl)).thenReturn(claimsMap); - - assertThrows(InvalidTokenException.class, () -> - authService.authToken(token)); - - } - - @Test - void authTokenWrongAud() throws Exception { - String token = utils.generateJWK(EXPIRES_AT); - Map claimsMap = createJWKClaims(ISS, "AUD_FAKE"); - - String wireMockUrl = utils.getUrlJwkProvider(); - when(jwtValidator.validate(token, wireMockUrl)).thenReturn(claimsMap); - - assertThrows(InvalidTokenException.class, () -> - authService.authToken(token)); - - } + // When + service.postToken(token); - private Map createJWKClaims (String iss, String aud){ - Map claims = new HashMap<>(); - claims.put("iss", iss); - claims.put("aud", aud); - claims.put("exp", "1715267318"); - claims.put("jti", "my-key-id"); - return claims; + // Then + Mockito.verify(exchangeTokenServiceMock).postToken(token); } } diff --git a/src/test/java/it/gov/pagopa/payhub/auth/service/exchange/ExchangeTokenServiceTest.java b/src/test/java/it/gov/pagopa/payhub/auth/service/exchange/ExchangeTokenServiceTest.java new file mode 100644 index 00000000..fda32714 --- /dev/null +++ b/src/test/java/it/gov/pagopa/payhub/auth/service/exchange/ExchangeTokenServiceTest.java @@ -0,0 +1,42 @@ +package it.gov.pagopa.payhub.auth.service.exchange; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.jupiter.MockitoExtension; + +@ExtendWith(MockitoExtension.class) +class ExchangeTokenServiceTest { + + @Mock + private ValidateTokenService validateTokenServiceMock; + + private ExchangeTokenService service; + + @BeforeEach + void init(){ + service = new ExchangeTokenServiceImpl(validateTokenServiceMock); + } + + @AfterEach + void verifyNotMoreInteractions(){ + Mockito.verifyNoMoreInteractions( + validateTokenServiceMock + ); + } + + @Test + void givenValidTokenWhenPostTokenThenSuccess(){ + // Given + String token = "TOKEN"; + + // When + service.postToken(token); + + // Then + Mockito.verify(validateTokenServiceMock).validate(token); + } +} diff --git a/src/test/java/it/gov/pagopa/payhub/auth/service/exchange/ValidateTokenServiceTest.java b/src/test/java/it/gov/pagopa/payhub/auth/service/exchange/ValidateTokenServiceTest.java new file mode 100644 index 00000000..112cdcf8 --- /dev/null +++ b/src/test/java/it/gov/pagopa/payhub/auth/service/exchange/ValidateTokenServiceTest.java @@ -0,0 +1,96 @@ +package it.gov.pagopa.payhub.auth.service.exchange; + +import com.github.tomakehurst.wiremock.WireMockServer; +import it.gov.pagopa.payhub.auth.exception.custom.InvalidTokenException; +import it.gov.pagopa.payhub.auth.utils.JWTValidator; +import it.gov.pagopa.payhub.auth.utils.JWTValidatorUtils; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +import java.util.Date; +import java.util.HashMap; +import java.util.Map; + +import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.when; + +@ExtendWith(SpringExtension.class) +class ValidateTokenServiceTest { + + public static final Date EXPIRES_AT = new Date(System.currentTimeMillis() + 3600000); + private static final String AUD = "AUD"; + private static final String ISS = "ISS"; + + private ValidateTokenService validateTokenService; + private WireMockServer wireMockServer; + private JWTValidatorUtils utils; + + @Mock + private JWTValidator jwtValidator; + + @BeforeEach + void setup(){ + wireMockServer = new WireMockServer(wireMockConfig().dynamicPort()); + wireMockServer.start(); + utils = new JWTValidatorUtils(wireMockServer); + validateTokenService = new ValidateTokenService(AUD, ISS, utils.getUrlJwkProvider(), jwtValidator); + } + + @AfterEach + void clean(){ + wireMockServer.stop(); + } + @Test + void authTokenOk() throws Exception { + String token = utils.generateJWK(EXPIRES_AT); + Map claimsMap = createJWKClaims(ISS, AUD); + + String wireMockUrl = utils.getUrlJwkProvider(); + when(jwtValidator.validate(token, wireMockUrl)).thenReturn(claimsMap); + + validateTokenService.validate(token); + Mockito.verify(jwtValidator, times(1)).validate(token, wireMockUrl); + } + + @Test + void authTokenWrongIss() throws Exception { + String token = utils.generateJWK(EXPIRES_AT); + Map claimsMap = createJWKClaims("ISS_FAKE", AUD); + + String wireMockUrl = utils.getUrlJwkProvider(); + when(jwtValidator.validate(token, wireMockUrl)).thenReturn(claimsMap); + + assertThrows(InvalidTokenException.class, () -> + validateTokenService.validate(token)); + + } + + @Test + void authTokenWrongAud() throws Exception { + String token = utils.generateJWK(EXPIRES_AT); + Map claimsMap = createJWKClaims(ISS, "AUD_FAKE"); + + String wireMockUrl = utils.getUrlJwkProvider(); + when(jwtValidator.validate(token, wireMockUrl)).thenReturn(claimsMap); + + assertThrows(InvalidTokenException.class, () -> + validateTokenService.validate(token)); + + } + + private Map createJWKClaims (String iss, String aud){ + Map claims = new HashMap<>(); + claims.put("iss", iss); + claims.put("aud", aud); + claims.put("exp", "1715267318"); + claims.put("jti", "my-key-id"); + return claims; + } +}