Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: P4ADEV-398 refactor design #10

Merged
merged 4 commits into from
May 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public AuthControllerImpl(AuthService authService) {

@Override
public ResponseEntity<AccessToken> postToken(String clientId, String grantType, String subjectToken, String subjectIssuer, String subjectTokenType, String scope) {
authService.authToken(subjectToken);
authService.postToken(subjectToken);
return new ResponseEntity<>(HttpStatus.OK);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,5 @@

public interface AuthService {

void authToken(String token);
void postToken(String token);
}
Original file line number Diff line number Diff line change
@@ -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<String, String> 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);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package it.gov.pagopa.payhub.auth.service.exchange;

public interface ExchangeTokenService {
void postToken(String token);
}
Original file line number Diff line number Diff line change
@@ -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);
}
}
Original file line number Diff line number Diff line change
@@ -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<String, String> 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");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand All @@ -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")
Expand Down
Original file line number Diff line number Diff line change
@@ -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<String, String> 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<String, String> 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<String, String> 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<String, String> createJWKClaims (String iss, String aud){
Map<String, String> 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);
}
}
Original file line number Diff line number Diff line change
@@ -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);
}
}
Original file line number Diff line number Diff line change
@@ -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<String, String> 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<String, String> 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<String, String> claimsMap = createJWKClaims(ISS, "AUD_FAKE");

String wireMockUrl = utils.getUrlJwkProvider();
when(jwtValidator.validate(token, wireMockUrl)).thenReturn(claimsMap);

assertThrows(InvalidTokenException.class, () ->
validateTokenService.validate(token));

}

private Map<String, String> createJWKClaims (String iss, String aud){
Map<String, String> claims = new HashMap<>();
claims.put("iss", iss);
claims.put("aud", aud);
claims.put("exp", "1715267318");
claims.put("jti", "my-key-id");
return claims;
}
}