Skip to content

Commit

Permalink
DTSSTCI-885 (#1813)
Browse files Browse the repository at this point in the history
DTSSTCI-885: Configure caching for IDAM token endpoint

Co-authored-by: Tom Elliott <tomelliott@Toms-MacBook-Pro.local>
  • Loading branch information
tomxelliott and Tom Elliott authored Jul 16, 2024
1 parent bb6ab16 commit 9aa9af4
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 43 deletions.
2 changes: 2 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -499,6 +499,8 @@ dependencies {
implementation group: 'org.json', name: 'json', version: '20231013'
implementation group: 'jakarta.enterprise', name: 'jakarta.enterprise.cdi-api', version: '4.0.1'

implementation group: 'com.github.ben-manes.caffeine', name: 'caffeine', version: '3.1.8'

annotationProcessor group: 'org.projectlombok', name: 'lombok', version: versions.lombok
testImplementation 'com.github.hmcts:fortify-client:1.3.0:all'

Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
package uk.gov.hmcts.sptribs.testutil;

import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.test.context.TestPropertySource;
import uk.gov.hmcts.reform.idam.client.IdamClient;
import uk.gov.hmcts.reform.idam.client.models.UserDetails;

import java.util.concurrent.TimeUnit;

@TestPropertySource("classpath:application.yaml")
@Service
public class IdamTokenGenerator {
Expand Down Expand Up @@ -38,24 +42,51 @@ public class IdamTokenGenerator {
@Autowired
private IdamClient idamClient;

private final Cache<String, String> cache = Caffeine.newBuilder().expireAfterWrite(2, TimeUnit.HOURS).build();

public String generateIdamTokenForSolicitor() {
return idamClient.getAccessToken(solicitorUsername, solicitorPassword);
String solicitorUserToken = cache.getIfPresent(solicitorUsername);
if (solicitorUserToken == null) {
solicitorUserToken = idamClient.getAccessToken(solicitorUsername, solicitorPassword);
cache.put(solicitorUsername, solicitorUserToken);
}
return solicitorUserToken;
}

public String generateIdamTokenForCaseworker() {
return idamClient.getAccessToken(caseworkerUsername, caseworkerPassword);
String caseworkerUserToken = cache.getIfPresent(caseworkerUsername);
if (caseworkerUserToken == null) {
caseworkerUserToken = idamClient.getAccessToken(caseworkerUsername, caseworkerPassword);
cache.put(caseworkerUsername, caseworkerUserToken);
}
return caseworkerUserToken;
}

public String generateIdamTokenForSystem() {
return idamClient.getAccessToken(systemUpdateUsername, systemUpdatePassword);
public String generateIdamTokenForSystemUser() {
String systemUserToken = cache.getIfPresent(systemUpdateUsername);
if (systemUserToken == null) {
systemUserToken = idamClient.getAccessToken(systemUpdateUsername, systemUpdatePassword);
cache.put(systemUpdateUsername, systemUserToken);
}
return systemUserToken;
}

public String generateIdamTokenForUser(String username, String password) {
return idamClient.getAccessToken(username, password);
public String generateIdamTokenForCitizen() {
String citizenUserToken = cache.getIfPresent(citizenUsername);
if (citizenUserToken == null) {
citizenUserToken = idamClient.getAccessToken(citizenUsername, citizenPassword);
cache.put(citizenUsername, citizenUserToken);
}
return citizenUserToken;
}

public String generateIdamTokenForCitizen() {
return idamClient.getAccessToken(citizenUsername, citizenPassword);
public String generateIdamTokenForUser(String username, String password) {
String userToken = cache.getIfPresent(username);
if (userToken == null) {
userToken = idamClient.getAccessToken(username, password);
cache.put(username, userToken);
}
return userToken;
}

public UserDetails getUserDetailsFor(final String token) {
Expand Down
17 changes: 14 additions & 3 deletions src/main/java/uk/gov/hmcts/sptribs/idam/IdamService.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package uk.gov.hmcts.sptribs.idam;

import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
Expand All @@ -8,6 +10,8 @@
import uk.gov.hmcts.reform.idam.client.models.User;
import uk.gov.hmcts.reform.idam.client.models.UserDetails;

import java.util.concurrent.TimeUnit;

import static uk.gov.hmcts.sptribs.common.config.ControllerConstants.BEARER_PREFIX;

@Service
Expand All @@ -19,6 +23,8 @@ public class IdamService {

private final IdamClient idamClient;

private final Cache<String, String> cache = Caffeine.newBuilder().expireAfterWrite(2, TimeUnit.HOURS).build();

@Autowired
public IdamService(
@Value("${idam.systemupdate.username}") String systemUpdateUserName,
Expand All @@ -37,11 +43,16 @@ public User retrieveUser(String authorisation) {
}

public User retrieveSystemUpdateUserDetails() {
return retrieveUser(getIdamOauth2Token(systemUpdateUserName, systemUpdatePassword));
return retrieveUser(getCachedIdamOauth2Token(systemUpdateUserName, systemUpdatePassword));
}

private String getIdamOauth2Token(String username, String password) {
return idamClient.getAccessToken(username, password);
private String getCachedIdamOauth2Token(String username, String password) {
String userToken = cache.getIfPresent(username);
if (userToken == null) {
userToken = idamClient.getAccessToken(username, password);
cache.put(username, userToken);
}
return userToken;
}

private String getBearerToken(String token) {
Expand Down
52 changes: 20 additions & 32 deletions src/test/java/uk/gov/hmcts/sptribs/idam/IdamServiceTest.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package uk.gov.hmcts.sptribs.idam;

import feign.FeignException;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
Expand Down Expand Up @@ -35,13 +36,30 @@ public class IdamServiceTest {
@Mock
private IdamClient idamClient;

@BeforeEach
public void setUp() {
ReflectionTestUtils.setField(idamService, "systemUpdateUserName", TEST_SYSTEM_UPDATE_USER_EMAIL);
ReflectionTestUtils.setField(idamService, "systemUpdatePassword", TEST_SYSTEM_USER_PASSWORD);
}

@Test
void shouldRetrieveUserDetails() {
final String bearerToken = TEST_SERVICE_AUTH_TOKEN;
final UserDetails userDetails = userDetails();

when(idamClient.getUserDetails(bearerToken)).thenReturn(userDetails());

final User result = idamService.retrieveUser(bearerToken);

assertEquals(userDetails, result.getUserDetails());
assertEquals(bearerToken, result.getAuthToken());
}

@Test
public void shouldRetrieveUserWhenValidAuthorizationTokenIsPassed() {
//Given
when(idamClient.getUserDetails(SYSTEM_UPDATE_AUTH_TOKEN))
.thenReturn(userDetails());

//When&Then
assertThatCode(() -> idamService.retrieveUser(SYSTEM_UPDATE_AUTH_TOKEN))
.doesNotThrowAnyException();

Expand All @@ -51,7 +69,6 @@ public void shouldRetrieveUserWhenValidAuthorizationTokenIsPassed() {

@Test
public void shouldThrowFeignUnauthorizedExceptionWhenInValidAuthorizationTokenIsPassed() {
//When&Then
doThrow(feignException(401, "Failed to retrieve Idam user"))
.when(idamClient).getUserDetails("Bearer invalid_token");

Expand All @@ -62,16 +79,12 @@ public void shouldThrowFeignUnauthorizedExceptionWhenInValidAuthorizationTokenIs

@Test
public void shouldNotThrowExceptionAndRetrieveSystemUpdateUserSuccessfully() {
//Given
setSystemUserCredentials();

when(idamClient.getAccessToken(TEST_SYSTEM_UPDATE_USER_EMAIL, TEST_SYSTEM_USER_PASSWORD))
.thenReturn(SYSTEM_UPDATE_AUTH_TOKEN);

when(idamClient.getUserDetails(SYSTEM_UPDATE_AUTH_TOKEN))
.thenReturn(userDetails());

//When&Then
assertThatCode(() -> idamService.retrieveSystemUpdateUserDetails())
.doesNotThrowAnyException();

Expand All @@ -82,39 +95,14 @@ public void shouldNotThrowExceptionAndRetrieveSystemUpdateUserSuccessfully() {

@Test
public void shouldThrowFeignUnauthorizedExceptionWhenSystemUpdateUserCredentialsAreInvalid() {
//Given
setSystemUserCredentials();

doThrow(feignException(401, "Failed to retrieve Idam user"))
.when(idamClient).getAccessToken(TEST_SYSTEM_UPDATE_USER_EMAIL, TEST_SYSTEM_USER_PASSWORD);

//When&Then
assertThatThrownBy(() -> idamService.retrieveSystemUpdateUserDetails())
.isExactlyInstanceOf(FeignException.Unauthorized.class)
.hasMessageContaining("Failed to retrieve Idam user");
}

@Test
void shouldRetrieveUserDetails() {
// Given
final String bearerToken = TEST_SERVICE_AUTH_TOKEN;
final UserDetails userDetails = userDetails();

// When
when(idamClient.getUserDetails(bearerToken)).thenReturn(userDetails());

final User result = idamService.retrieveUser(bearerToken);

//Then
assertEquals(userDetails, result.getUserDetails());
assertEquals(bearerToken, result.getAuthToken());
}

private void setSystemUserCredentials() {
ReflectionTestUtils.setField(idamService, "systemUpdateUserName", TEST_SYSTEM_UPDATE_USER_EMAIL);
ReflectionTestUtils.setField(idamService, "systemUpdatePassword", TEST_SYSTEM_USER_PASSWORD);
}

private UserDetails userDetails() {
return UserDetails
.builder()
Expand Down

0 comments on commit 9aa9af4

Please sign in to comment.