Search in sources :

Example 1 with RefreshTokenStore

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);
}
Also used : RefreshTokenStore(uk.gov.di.authentication.shared.entity.RefreshTokenStore) KeyPair(java.security.KeyPair) RefreshToken(com.nimbusds.oauth2.sdk.token.RefreshToken) OIDCTokenResponse(com.nimbusds.openid.connect.sdk.OIDCTokenResponse) OIDCTokens(com.nimbusds.openid.connect.sdk.token.OIDCTokens) PrivateKeyJWT(com.nimbusds.oauth2.sdk.auth.PrivateKeyJWT) ClientRegistry(uk.gov.di.authentication.shared.entity.ClientRegistry) SignedJWT(com.nimbusds.jwt.SignedJWT) ArgumentMatchers.anyString(org.mockito.ArgumentMatchers.anyString) APIGatewayProxyResponseEvent(com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent) ObjectMapper(com.fasterxml.jackson.databind.ObjectMapper) Test(org.junit.jupiter.api.Test) ParameterizedTest(org.junit.jupiter.params.ParameterizedTest)

Example 2 with RefreshTokenStore

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());
}
Also used : RefreshTokenStore(uk.gov.di.authentication.shared.entity.RefreshTokenStore) ErrorObject(com.nimbusds.oauth2.sdk.ErrorObject) OIDCTokenResponse(com.nimbusds.openid.connect.sdk.OIDCTokenResponse) SignedJWT(com.nimbusds.jwt.SignedJWT) Subject(com.nimbusds.oauth2.sdk.id.Subject) Context(com.amazonaws.services.lambda.runtime.Context) JsonProcessingException(com.fasterxml.jackson.core.JsonProcessingException) ObjectMapper(com.fasterxml.jackson.databind.ObjectMapper) NoSuchElementException(java.util.NoSuchElementException)

Example 3 with RefreshTokenStore

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);
}
Also used : RefreshTokenStore(uk.gov.di.authentication.shared.entity.RefreshTokenStore) KeyPair(java.security.KeyPair) RefreshToken(com.nimbusds.oauth2.sdk.token.RefreshToken) OIDCTokenResponse(com.nimbusds.openid.connect.sdk.OIDCTokenResponse) OIDCTokens(com.nimbusds.openid.connect.sdk.token.OIDCTokens) PrivateKeyJWT(com.nimbusds.oauth2.sdk.auth.PrivateKeyJWT) ClientRegistry(uk.gov.di.authentication.shared.entity.ClientRegistry) SignedJWT(com.nimbusds.jwt.SignedJWT) ArgumentMatchers.anyString(org.mockito.ArgumentMatchers.anyString) APIGatewayProxyResponseEvent(com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent) ObjectMapper(com.fasterxml.jackson.databind.ObjectMapper) Test(org.junit.jupiter.api.Test) ParameterizedTest(org.junit.jupiter.params.ParameterizedTest)

Example 4 with RefreshTokenStore

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;
}
Also used : JsonException(uk.gov.di.authentication.shared.serialization.Json.JsonException) RefreshTokenStore(uk.gov.di.authentication.shared.entity.RefreshTokenStore) RefreshToken(com.nimbusds.oauth2.sdk.token.RefreshToken) JWTClaimsSet(com.nimbusds.jwt.JWTClaimsSet) SignedJWT(com.nimbusds.jwt.SignedJWT) HashHelper.hashSha256String(uk.gov.di.authentication.shared.helpers.HashHelper.hashSha256String) Date(java.util.Date)

Example 5 with RefreshTokenStore

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()));
}
Also used : RefreshTokenStore(uk.gov.di.authentication.shared.entity.RefreshTokenStore) KeyPair(java.security.KeyPair) RefreshToken(com.nimbusds.oauth2.sdk.token.RefreshToken) OIDCTokenResponse(com.nimbusds.openid.connect.sdk.OIDCTokenResponse) OIDCTokens(com.nimbusds.openid.connect.sdk.token.OIDCTokens) PrivateKeyJWT(com.nimbusds.oauth2.sdk.auth.PrivateKeyJWT) ClientRegistry(uk.gov.di.authentication.shared.entity.ClientRegistry) RequestObjectTestHelper.generateSignedJWT(uk.gov.di.authentication.oidc.helper.RequestObjectTestHelper.generateSignedJWT) SignedJWT(com.nimbusds.jwt.SignedJWT) ArgumentMatchers.anyString(org.mockito.ArgumentMatchers.anyString) APIGatewayProxyResponseEvent(com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent) ValueSource(org.junit.jupiter.params.provider.ValueSource) ParameterizedTest(org.junit.jupiter.params.ParameterizedTest) NullSource(org.junit.jupiter.params.provider.NullSource)

Aggregations

RefreshTokenStore (uk.gov.di.authentication.shared.entity.RefreshTokenStore)9 SignedJWT (com.nimbusds.jwt.SignedJWT)7 OIDCTokenResponse (com.nimbusds.openid.connect.sdk.OIDCTokenResponse)7 RefreshToken (com.nimbusds.oauth2.sdk.token.RefreshToken)5 Test (org.junit.jupiter.api.Test)5 ErrorObject (com.nimbusds.oauth2.sdk.ErrorObject)4 PrivateKeyJWT (com.nimbusds.oauth2.sdk.auth.PrivateKeyJWT)4 KeyPair (java.security.KeyPair)4 ParameterizedTest (org.junit.jupiter.params.ParameterizedTest)4 APIGatewayProxyResponseEvent (com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent)3 ObjectMapper (com.fasterxml.jackson.databind.ObjectMapper)3 Subject (com.nimbusds.oauth2.sdk.id.Subject)3 OIDCTokens (com.nimbusds.openid.connect.sdk.token.OIDCTokens)3 HashMap (java.util.HashMap)3 ArgumentMatchers.anyString (org.mockito.ArgumentMatchers.anyString)3 ClientRegistry (uk.gov.di.authentication.shared.entity.ClientRegistry)3 Context (com.amazonaws.services.lambda.runtime.Context)2 NoSuchElementException (java.util.NoSuchElementException)2 ClientConsent (uk.gov.di.authentication.shared.entity.ClientConsent)2 JsonException (uk.gov.di.authentication.shared.serialization.Json.JsonException)2