use of uk.gov.di.authentication.shared.entity.AuthCodeExchangeData in project di-authentication-api by alphagov.
the class TokenHandlerTest method shouldReturn200ForSuccessfulTokenRequest.
@ParameterizedTest
@MethodSource("validVectorValues")
public void shouldReturn200ForSuccessfulTokenRequest(String vectorValue) throws JOSEException {
KeyPair keyPair = generateRsaKeyPair();
UserProfile userProfile = generateUserProfile();
SignedJWT signedJWT = generateIDToken(CLIENT_ID, PUBLIC_SUBJECT, "issuer-url", new ECKeyGenerator(Curve.P_256).algorithm(JWSAlgorithm.ES256).generate());
OIDCTokenResponse tokenResponse = new OIDCTokenResponse(new OIDCTokens(signedJWT, 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());
String authCode = new AuthorizationCode().toString();
when(authorisationCodeService.getExchangeDataForCode(authCode)).thenReturn(Optional.of(new AuthCodeExchangeData().setEmail(TEST_EMAIL).setClientSessionId(CLIENT_SESSION_ID)));
AuthenticationRequest authenticationRequest = generateAuthRequest(JsonArrayHelper.jsonArrayOf(vectorValue));
VectorOfTrust vtr = VectorOfTrust.parseFromAuthRequestAttribute(authenticationRequest.getCustomParameter("vtr"));
when(clientSessionService.getClientSession(CLIENT_SESSION_ID)).thenReturn(new ClientSession(authenticationRequest.toParameters(), LocalDateTime.now(), vtr));
when(dynamoService.getUserProfileByEmail(eq(TEST_EMAIL))).thenReturn(userProfile);
when(tokenService.generateTokenResponse(CLIENT_ID, INTERNAL_SUBJECT, SCOPES, Map.of("nonce", NONCE), PUBLIC_SUBJECT, vtr.retrieveVectorOfTrustForToken(), userProfile.getClientConsent(), clientRegistry.isConsentRequired(), null)).thenReturn(tokenResponse);
APIGatewayProxyResponseEvent result = generateApiGatewayRequest(privateKeyJWT, authCode);
assertThat(result, hasStatus(200));
assertTrue(result.getBody().contains(refreshToken.getValue()));
assertTrue(result.getBody().contains(accessToken.getValue()));
}
use of uk.gov.di.authentication.shared.entity.AuthCodeExchangeData in project di-authentication-api by alphagov.
the class TokenHandlerTest method shouldReturn200ForSuccessfulTokenRequest.
@ParameterizedTest
@MethodSource("validVectorValues")
public void shouldReturn200ForSuccessfulTokenRequest(String vectorValue, boolean clientRegistryConsent, boolean expectedConsentRequired, boolean clientIdInHeader) throws JOSEException {
KeyPair keyPair = generateRsaKeyPair();
UserProfile userProfile = generateUserProfile();
SignedJWT signedJWT = generateIDToken(CLIENT_ID, PUBLIC_SUBJECT, "issuer-url", new ECKeyGenerator(Curve.P_256).algorithm(JWSAlgorithm.ES256).generate());
OIDCTokenResponse tokenResponse = new OIDCTokenResponse(new OIDCTokens(signedJWT, accessToken, refreshToken));
PrivateKeyJWT privateKeyJWT = generatePrivateKeyJWT(keyPair.getPrivate());
ClientRegistry clientRegistry = generateClientRegistry(keyPair, clientRegistryConsent);
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());
String authCode = new AuthorizationCode().toString();
AuthenticationRequest authenticationRequest = generateAuthRequest(JsonArrayHelper.jsonArrayOf(vectorValue));
VectorOfTrust vtr = VectorOfTrust.parseFromAuthRequestAttribute(authenticationRequest.getCustomParameter("vtr"));
when(authorisationCodeService.getExchangeDataForCode(authCode)).thenReturn(Optional.of(new AuthCodeExchangeData().setEmail(TEST_EMAIL).setClientSessionId(CLIENT_SESSION_ID).setClientSession(new ClientSession(authenticationRequest.toParameters(), LocalDateTime.now(), vtr))));
when(dynamoService.getUserProfileByEmail(eq(TEST_EMAIL))).thenReturn(userProfile);
when(tokenService.generateTokenResponse(CLIENT_ID, INTERNAL_SUBJECT, SCOPES, Map.of("nonce", NONCE), PUBLIC_SUBJECT, vtr.retrieveVectorOfTrustForToken(), userProfile.getClientConsent(), expectedConsentRequired, null, false)).thenReturn(tokenResponse);
APIGatewayProxyResponseEvent result = generateApiGatewayRequest(privateKeyJWT, authCode, CLIENT_ID, clientIdInHeader);
assertThat(result, hasStatus(200));
assertTrue(result.getBody().contains(refreshToken.getValue()));
assertTrue(result.getBody().contains(accessToken.getValue()));
}
use of uk.gov.di.authentication.shared.entity.AuthCodeExchangeData in project di-authentication-api by alphagov.
the class TokenHandlerTest method shouldReturn400IfRedirectUriDoesNotMatchRedirectUriFromAuthRequest.
@Test
public void shouldReturn400IfRedirectUriDoesNotMatchRedirectUriFromAuthRequest() throws JOSEException {
KeyPair keyPair = generateRsaKeyPair();
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());
String authCode = new AuthorizationCode().toString();
when(authorisationCodeService.getExchangeDataForCode(authCode)).thenReturn(Optional.of(new AuthCodeExchangeData().setEmail(TEST_EMAIL).setClientSessionId(CLIENT_SESSION_ID).setClientSession(new ClientSession(generateAuthRequest().toParameters(), LocalDateTime.now(), mock(VectorOfTrust.class)))));
APIGatewayProxyResponseEvent result = generateApiGatewayRequest(privateKeyJWT, authCode, "http://invalid-redirect-uri", CLIENT_ID, true);
assertThat(result, hasStatus(400));
assertThat(result, hasBody(OAuth2Error.INVALID_GRANT.toJSONObject().toJSONString()));
}
use of uk.gov.di.authentication.shared.entity.AuthCodeExchangeData in project di-authentication-api by alphagov.
the class TokenHandlerTest method shouldReturn200ForSuccessfulDocAppJourneyTokenRequest.
@Test
void shouldReturn200ForSuccessfulDocAppJourneyTokenRequest() throws JOSEException {
KeyPair keyPair = generateRsaKeyPair();
UserProfile userProfile = generateUserProfile();
SignedJWT signedJWT = generateIDToken(DOC_APP_CLIENT_ID.getValue(), PUBLIC_SUBJECT, "issuer-url", new ECKeyGenerator(Curve.P_256).algorithm(JWSAlgorithm.ES256).generate());
OIDCTokenResponse tokenResponse = new OIDCTokenResponse(new OIDCTokens(signedJWT, accessToken, refreshToken));
PrivateKeyJWT privateKeyJWT = generatePrivateKeyJWT(keyPair.getPrivate());
ClientRegistry clientRegistry = generateClientRegistry(keyPair, false);
when(tokenService.validateTokenRequestParams(anyString())).thenReturn(Optional.empty());
when(clientService.getClient(DOC_APP_CLIENT_ID.getValue())).thenReturn(Optional.of(clientRegistry));
when(tokenService.getClientIDFromPrivateKeyJWT(anyString())).thenReturn(Optional.of(DOC_APP_CLIENT_ID.getValue()));
when(tokenService.validatePrivateKeyJWT(anyString(), eq(clientRegistry.getPublicKey()), eq(BASE_URI), eq(DOC_APP_CLIENT_ID.getValue()))).thenReturn(Optional.empty());
String authCode = new AuthorizationCode().toString();
AuthorizationRequest authenticationRequest = generateRequestObjectAuthRequest();
VectorOfTrust vtr = VectorOfTrust.parseFromAuthRequestAttribute(authenticationRequest.getCustomParameter("vtr"));
ClientSession clientSession = new ClientSession(authenticationRequest.toParameters(), LocalDateTime.now(), vtr);
clientSession.setDocAppSubjectId(DOC_APP_USER_PUBLIC_SUBJECT);
when(authorisationCodeService.getExchangeDataForCode(authCode)).thenReturn(Optional.of(new AuthCodeExchangeData().setEmail(TEST_EMAIL).setClientSessionId(CLIENT_SESSION_ID).setClientSession(clientSession)));
when(dynamoService.getUserProfileByEmail(TEST_EMAIL)).thenReturn(userProfile);
when(tokenService.generateTokenResponse(DOC_APP_CLIENT_ID.getValue(), DOC_APP_USER_PUBLIC_SUBJECT, new Scope(OIDCScopeValue.OPENID, DOC_CHECKING_APP), Map.of(), DOC_APP_USER_PUBLIC_SUBJECT, vtr.retrieveVectorOfTrustForToken(), null, false, null, true)).thenReturn(tokenResponse);
APIGatewayProxyResponseEvent result = generateApiGatewayRequest(privateKeyJWT, authCode, DOC_APP_CLIENT_ID.getValue(), true);
assertThat(result, hasStatus(200));
assertTrue(result.getBody().contains(refreshToken.getValue()));
assertTrue(result.getBody().contains(accessToken.getValue()));
}
use of uk.gov.di.authentication.shared.entity.AuthCodeExchangeData in project di-authentication-api by alphagov.
the class TokenHandler method tokenRequestHandler.
public APIGatewayProxyResponseEvent tokenRequestHandler(APIGatewayProxyRequestEvent input, Context context) {
return isWarming(input).orElseGet(() -> {
LOG.info("Token request received");
Optional<ErrorObject> invalidRequestParamError = tokenService.validateTokenRequestParams(input.getBody());
if (invalidRequestParamError.isPresent()) {
LOG.warn("Invalid Token Request. ErrorCode: {}. ErrorDescription: {}", invalidRequestParamError.get().getCode(), invalidRequestParamError.get().getDescription());
return generateApiGatewayProxyResponse(400, invalidRequestParamError.get().toJSONObject().toJSONString());
}
Map<String, String> requestBody = parseRequestBody(input.getBody());
addAnnotation("grant_type", requestBody.get("grant_type"));
String clientID;
ClientRegistry client;
try {
clientID = tokenService.getClientIDFromPrivateKeyJWT(input.getBody()).orElseThrow();
attachLogFieldToLogs(CLIENT_ID, clientID);
addAnnotation("client_id", clientID);
client = clientService.getClient(clientID).orElseThrow();
} catch (NoSuchElementException e) {
LOG.warn("Invalid client or client not found in Client Registry");
return generateApiGatewayProxyResponse(400, OAuth2Error.INVALID_CLIENT.toJSONObject().toJSONString());
}
String baseUrl = configurationService.getOidcApiBaseURL().orElseThrow(() -> {
LOG.error("Application was not configured with baseURL");
return new RuntimeException("Application was not configured with baseURL");
});
String tokenUrl = buildURI(baseUrl, TOKEN_PATH).toString();
Optional<ErrorObject> invalidPrivateKeyJwtError = segmentedFunctionCall("validatePrivateKeyJWT", () -> tokenService.validatePrivateKeyJWT(input.getBody(), client.getPublicKey(), tokenUrl, clientID));
if (invalidPrivateKeyJwtError.isPresent()) {
LOG.warn("Private Key JWT is not valid for Client ID: {}", clientID);
return generateApiGatewayProxyResponse(400, invalidPrivateKeyJwtError.get().toJSONObject().toJSONString());
}
if (requestBody.get("grant_type").equals(GrantType.REFRESH_TOKEN.getValue())) {
LOG.info("Processing refresh token request");
return segmentedFunctionCall("processRefreshTokenRequest", () -> processRefreshTokenRequest(requestBody, client.getScopes(), new RefreshToken(requestBody.get("refresh_token")), clientID));
}
AuthCodeExchangeData authCodeExchangeData;
try {
authCodeExchangeData = segmentedFunctionCall("authorisationCodeService", () -> authorisationCodeService.getExchangeDataForCode(requestBody.get("code")).orElseThrow());
} catch (NoSuchElementException e) {
LOG.warn("Could not retrieve client session ID from code", e);
return generateApiGatewayProxyResponse(400, OAuth2Error.INVALID_GRANT.toJSONObject().toJSONString());
}
updateAttachedLogFieldToLogs(CLIENT_SESSION_ID, authCodeExchangeData.getClientSessionId());
ClientSession clientSession = authCodeExchangeData.getClientSession();
AuthenticationRequest authRequest;
try {
authRequest = AuthenticationRequest.parse(clientSession.getAuthRequestParams());
} catch (ParseException e) {
LOG.warn("Could not parse authentication request from client session", e);
throw new RuntimeException(format("Unable to parse Auth Request\n Auth Request Params: %s \n Exception: %s", clientSession.getAuthRequestParams(), e));
}
var authRequestRedirectURI = isDocCheckingAppUserWithSubjectId(clientSession) ? getRequestObjectClaim(authRequest, "redirect_uri", String.class) : authRequest.getRedirectionURI().toString();
if (!authRequestRedirectURI.equals(requestBody.get("redirect_uri"))) {
LOG.warn("Redirect URI for auth request ({}) does not match redirect URI for request body ({})", authRequestRedirectURI, requestBody.get("redirect_uri"));
return generateApiGatewayProxyResponse(400, OAuth2Error.INVALID_GRANT.toJSONObject().toJSONString());
}
Map<String, Object> additionalTokenClaims = new HashMap<>();
if (authRequest.getNonce() != null) {
additionalTokenClaims.put("nonce", authRequest.getNonce());
}
String vot = clientSession.getEffectiveVectorOfTrust().retrieveVectorOfTrustForToken();
OIDCClaimsRequest claimsRequest = null;
if (Objects.nonNull(clientSession.getEffectiveVectorOfTrust().getLevelOfConfidence()) && Objects.nonNull(authRequest.getOIDCClaims())) {
claimsRequest = authRequest.getOIDCClaims();
}
var isConsentRequired = client.isConsentRequired() && !clientSession.getEffectiveVectorOfTrust().containsLevelOfConfidence();
final OIDCClaimsRequest finalClaimsRequest = claimsRequest;
OIDCTokenResponse tokenResponse;
if (isDocCheckingAppUserWithSubjectId(clientSession)) {
LOG.info("Doc Checking App User with SubjectId: true");
Scope scope = new Scope(getRequestObjectScopeClaim(authRequest));
tokenResponse = segmentedFunctionCall("generateTokenResponse", () -> tokenService.generateTokenResponse(clientID, clientSession.getDocAppSubjectId(), scope, additionalTokenClaims, clientSession.getDocAppSubjectId(), vot, null, false, finalClaimsRequest, true));
} else {
UserProfile userProfile = dynamoService.getUserProfileByEmail(authCodeExchangeData.getEmail());
Subject subject = ClientSubjectHelper.getSubject(userProfile, client, dynamoService);
tokenResponse = segmentedFunctionCall("generateTokenResponse", () -> tokenService.generateTokenResponse(clientID, new Subject(userProfile.getSubjectID()), authRequest.getScope(), additionalTokenClaims, subject, vot, userProfile.getClientConsent(), isConsentRequired, finalClaimsRequest, false));
}
clientSessionService.saveClientSession(authCodeExchangeData.getClientSessionId(), clientSession.setIdTokenHint(tokenResponse.getOIDCTokens().getIDToken().serialize()));
LOG.info("Successfully generated tokens");
return generateApiGatewayProxyResponse(200, tokenResponse.toJSONObject().toJSONString());
});
}
Aggregations