use of uk.gov.di.authentication.shared.entity.RefreshTokenStore in project di-authentication-api by alphagov.
the class TokenHandlerTest method shouldReturn200ForSuccessfulRefreshTokenRequest.
@Test
public void shouldReturn200ForSuccessfulRefreshTokenRequest() throws JOSEException, JsonProcessingException {
SignedJWT signedRefreshToken = createSignedRefreshToken();
KeyPair keyPair = generateRsaKeyPair();
RefreshToken refreshToken = new RefreshToken(signedRefreshToken.serialize());
OIDCTokenResponse tokenResponse = new OIDCTokenResponse(new OIDCTokens(accessToken, refreshToken));
PrivateKeyJWT privateKeyJWT = generatePrivateKeyJWT(keyPair.getPrivate());
ClientRegistry clientRegistry = generateClientRegistry(keyPair);
when(tokenService.validateTokenRequestParams(anyString())).thenReturn(Optional.empty());
when(clientService.getClient(eq(CLIENT_ID))).thenReturn(Optional.of(clientRegistry));
when(tokenService.validatePrivateKeyJWT(anyString(), eq(clientRegistry.getPublicKey()), eq(BASE_URI), eq(CLIENT_ID))).thenReturn(Optional.empty());
when(tokenValidationService.validateRefreshTokenSignatureAndExpiry(refreshToken)).thenReturn(true);
when(tokenValidationService.validateRefreshTokenScopes(SCOPES.toStringList(), SCOPES.toStringList())).thenReturn(true);
RefreshTokenStore tokenStore = new RefreshTokenStore(singletonList(refreshToken.getValue()), INTERNAL_SUBJECT.getValue());
String redisKey = REFRESH_TOKEN_PREFIX + CLIENT_ID + "." + PUBLIC_SUBJECT.getValue();
String tokenStoreString = new ObjectMapper().writeValueAsString(tokenStore);
when(redisConnectionService.getValue(redisKey)).thenReturn(tokenStoreString);
when(tokenService.generateRefreshTokenResponse(eq(CLIENT_ID), eq(INTERNAL_SUBJECT), eq(SCOPES.toStringList()), eq(PUBLIC_SUBJECT))).thenReturn(tokenResponse);
APIGatewayProxyResponseEvent result = generateApiGatewayRefreshRequest(privateKeyJWT, refreshToken.getValue());
assertThat(result, hasStatus(200));
assertTrue(result.getBody().contains(refreshToken.getValue()));
assertTrue(result.getBody().contains(accessToken.getValue()));
verify(redisConnectionService, times(1)).deleteValue(redisKey);
}
use of uk.gov.di.authentication.shared.entity.RefreshTokenStore in project di-authentication-api by alphagov.
the class TokenHandler method processRefreshTokenRequest.
private APIGatewayProxyResponseEvent processRefreshTokenRequest(Map<String, String> requestBody, List<String> clientScopes, RefreshToken currentRefreshToken) {
boolean refreshTokenSignatureValid = tokenValidationService.validateRefreshTokenSignatureAndExpiry(currentRefreshToken);
if (!refreshTokenSignatureValid) {
return generateApiGatewayProxyResponse(400, OAuth2Error.INVALID_GRANT.toJSONObject().toJSONString());
}
Subject publicSubject;
List<String> scopes;
try {
SignedJWT signedJwt = SignedJWT.parse(currentRefreshToken.getValue());
publicSubject = new Subject(signedJwt.getJWTClaimsSet().getSubject());
scopes = (List<String>) signedJwt.getJWTClaimsSet().getClaim("scope");
} catch (java.text.ParseException e) {
LOG.warn("Unable to parse RefreshToken");
return generateApiGatewayProxyResponse(400, new ErrorObject(OAuth2Error.INVALID_GRANT_CODE, "Invalid Refresh token").toJSONObject().toJSONString());
}
boolean areScopesValid = tokenValidationService.validateRefreshTokenScopes(clientScopes, scopes);
if (!areScopesValid) {
return generateApiGatewayProxyResponse(400, OAuth2Error.INVALID_SCOPE.toJSONObject().toJSONString());
}
String clientId = requestBody.get("client_id");
String redisKey = REFRESH_TOKEN_PREFIX + clientId + "." + publicSubject.getValue();
Optional<String> refreshToken = Optional.ofNullable(redisConnectionService.getValue(redisKey));
RefreshTokenStore tokenStore;
try {
tokenStore = new ObjectMapper().readValue(refreshToken.get(), RefreshTokenStore.class);
} catch (JsonProcessingException | NoSuchElementException | IllegalArgumentException e) {
LOG.warn("Refresh token not found with given key");
return generateApiGatewayProxyResponse(400, new ErrorObject(OAuth2Error.INVALID_GRANT_CODE, "Invalid Refresh token").toJSONObject().toJSONString());
}
if (!tokenStore.getRefreshTokens().contains(currentRefreshToken.getValue())) {
LOG.warn("Refresh token store does not contain Refresh token in request");
return generateApiGatewayProxyResponse(400, new ErrorObject(OAuth2Error.INVALID_GRANT_CODE, "Invalid Refresh token").toJSONObject().toJSONString());
}
if (tokenStore.getRefreshTokens().size() > 1) {
LOG.info("Removing Refresh Token from refresh token store");
try {
redisConnectionService.saveWithExpiry(redisKey, new ObjectMapper().writeValueAsString(tokenStore.removeRefreshToken(currentRefreshToken.getValue())), configurationService.getSessionExpiry());
} catch (JsonProcessingException e) {
LOG.error("Unable to serialize refresh token store when updating");
throw new RuntimeException(e);
}
} else {
LOG.info("Deleting refresh token store as no other refresh tokens exist");
redisConnectionService.deleteValue(redisKey);
}
OIDCTokenResponse tokenResponse = tokenService.generateRefreshTokenResponse(clientId, new Subject(tokenStore.getInternalSubjectId()), scopes, publicSubject);
LOG.info("Generating successful RefreshToken response");
return generateApiGatewayProxyResponse(200, tokenResponse.toJSONObject().toJSONString());
}
use of uk.gov.di.authentication.shared.entity.RefreshTokenStore in project di-authentication-api by alphagov.
the class TokenHandlerTest method shouldReturn200ForRefreshTokenRequestWhenMultipleRefreshTokensAreStored.
@Test
public void shouldReturn200ForRefreshTokenRequestWhenMultipleRefreshTokensAreStored() throws JOSEException, JsonProcessingException {
SignedJWT signedRefreshToken = createSignedRefreshToken();
KeyPair keyPair = generateRsaKeyPair();
RefreshToken refreshToken = new RefreshToken(signedRefreshToken.serialize());
RefreshToken refreshToken2 = new RefreshToken();
OIDCTokenResponse tokenResponse = new OIDCTokenResponse(new OIDCTokens(accessToken, refreshToken));
PrivateKeyJWT privateKeyJWT = generatePrivateKeyJWT(keyPair.getPrivate());
ClientRegistry clientRegistry = generateClientRegistry(keyPair);
when(tokenService.validateTokenRequestParams(anyString())).thenReturn(Optional.empty());
when(clientService.getClient(eq(CLIENT_ID))).thenReturn(Optional.of(clientRegistry));
when(tokenService.validatePrivateKeyJWT(anyString(), eq(clientRegistry.getPublicKey()), eq(BASE_URI), eq(CLIENT_ID))).thenReturn(Optional.empty());
when(tokenValidationService.validateRefreshTokenSignatureAndExpiry(refreshToken)).thenReturn(true);
when(tokenValidationService.validateRefreshTokenScopes(SCOPES.toStringList(), SCOPES.toStringList())).thenReturn(true);
RefreshTokenStore tokenStore = new RefreshTokenStore(List.of(refreshToken.getValue(), refreshToken2.getValue()), INTERNAL_SUBJECT.getValue());
String redisKey = REFRESH_TOKEN_PREFIX + CLIENT_ID + "." + PUBLIC_SUBJECT.getValue();
String tokenStoreString = new ObjectMapper().writeValueAsString(tokenStore);
when(redisConnectionService.getValue(redisKey)).thenReturn(tokenStoreString);
when(tokenService.generateRefreshTokenResponse(eq(CLIENT_ID), eq(INTERNAL_SUBJECT), eq(SCOPES.toStringList()), eq(PUBLIC_SUBJECT))).thenReturn(tokenResponse);
APIGatewayProxyResponseEvent result = generateApiGatewayRefreshRequest(privateKeyJWT, refreshToken.getValue());
assertThat(result, hasStatus(200));
assertTrue(result.getBody().contains(refreshToken.getValue()));
assertTrue(result.getBody().contains(accessToken.getValue()));
String updatedTokenstore = new ObjectMapper().writeValueAsString(new RefreshTokenStore(List.of(refreshToken2.getValue()), INTERNAL_SUBJECT.getValue()));
verify(redisConnectionService, times(1)).saveWithExpiry(redisKey, updatedTokenstore, 1234L);
}
use of uk.gov.di.authentication.shared.entity.RefreshTokenStore in project di-authentication-api by alphagov.
the class TokenService method generateAndStoreRefreshToken.
private RefreshToken generateAndStoreRefreshToken(String clientId, Subject internalSubject, List<String> scopes, Subject subject) {
LOG.info("Generating RefreshToken");
Date expiryDate = NowHelper.nowPlus(configService.getSessionExpiry(), ChronoUnit.SECONDS);
var jwtId = IdGenerator.generate();
JWTClaimsSet claimsSet = new JWTClaimsSet.Builder().claim("scope", scopes).issuer(configService.getOidcApiBaseURL().get()).expirationTime(expiryDate).issueTime(NowHelper.now()).claim("client_id", clientId).subject(subject.getValue()).jwtID(jwtId).build();
SignedJWT signedJWT = generateSignedJWT(claimsSet, Optional.empty());
RefreshToken refreshToken = new RefreshToken(signedJWT.serialize());
String redisKey = REFRESH_TOKEN_PREFIX + jwtId;
var store = new RefreshTokenStore(refreshToken.getValue(), internalSubject.toString());
try {
redisConnectionService.saveWithExpiry(redisKey, objectMapper.writeValueAsString(store), configService.getSessionExpiry());
} catch (JsonException e) {
throw new RuntimeException("Error serializing refresh token store", e);
}
return refreshToken;
}
use of uk.gov.di.authentication.shared.entity.RefreshTokenStore in project di-authentication-api by alphagov.
the class TokenHandlerTest method shouldReturn200ForSuccessfulRefreshTokenRequest.
@ParameterizedTest
@NullSource
@ValueSource(strings = { CLIENT_ID })
public void shouldReturn200ForSuccessfulRefreshTokenRequest(String clientId) throws JOSEException, ParseException, Json.JsonException {
SignedJWT signedRefreshToken = createSignedRefreshToken();
KeyPair keyPair = generateRsaKeyPair();
RefreshToken refreshToken = new RefreshToken(signedRefreshToken.serialize());
OIDCTokenResponse tokenResponse = new OIDCTokenResponse(new OIDCTokens(accessToken, refreshToken));
PrivateKeyJWT privateKeyJWT = generatePrivateKeyJWT(keyPair.getPrivate());
ClientRegistry clientRegistry = generateClientRegistry(keyPair, false);
when(tokenService.validateTokenRequestParams(anyString())).thenReturn(Optional.empty());
when(clientService.getClient(eq(CLIENT_ID))).thenReturn(Optional.of(clientRegistry));
when(tokenService.getClientIDFromPrivateKeyJWT(anyString())).thenReturn(Optional.of(CLIENT_ID));
when(tokenService.validatePrivateKeyJWT(anyString(), eq(clientRegistry.getPublicKey()), eq(BASE_URI), eq(CLIENT_ID))).thenReturn(Optional.empty());
when(tokenValidationService.validateRefreshTokenSignatureAndExpiry(refreshToken)).thenReturn(true);
when(tokenValidationService.validateRefreshTokenScopes(SCOPES.toStringList(), SCOPES.toStringList())).thenReturn(true);
RefreshTokenStore tokenStore = new RefreshTokenStore(refreshToken.getValue(), INTERNAL_SUBJECT.getValue());
String tokenStoreString = objectMapper.writeValueAsString(tokenStore);
when(redisConnectionService.popValue(REFRESH_TOKEN_PREFIX + CLIENT_ID + "." + PUBLIC_SUBJECT.getValue())).thenReturn(null);
String redisKey = REFRESH_TOKEN_PREFIX + signedRefreshToken.getJWTClaimsSet().getJWTID();
when(redisConnectionService.popValue(redisKey)).thenReturn(tokenStoreString);
when(tokenService.generateRefreshTokenResponse(eq(CLIENT_ID), eq(INTERNAL_SUBJECT), eq(SCOPES.toStringList()), eq(PUBLIC_SUBJECT))).thenReturn(tokenResponse);
APIGatewayProxyResponseEvent result = generateApiGatewayRefreshRequest(privateKeyJWT, refreshToken.getValue(), clientId);
assertThat(result, hasStatus(200));
assertTrue(result.getBody().contains(refreshToken.getValue()));
assertTrue(result.getBody().contains(accessToken.getValue()));
}
Aggregations