use of com.nimbusds.openid.connect.sdk.OIDCClaimsRequest in project di-authentication-api by alphagov.
the class AuthorizationServiceTest method shouldReturnErrorWhenValidatingAuthRequestWhichContainsInvalidClaims.
@Test
void shouldReturnErrorWhenValidatingAuthRequestWhichContainsInvalidClaims() {
ResponseType responseType = new ResponseType(ResponseType.Value.CODE);
Scope scope = new Scope();
scope.add(OIDCScopeValue.OPENID);
when(dynamoClientService.getClient(CLIENT_ID.toString())).thenReturn(Optional.of(generateClientRegistry(REDIRECT_URI.toString(), CLIENT_ID.toString())));
var claimsSetRequest = new ClaimsSetRequest().add("nickname").add("birthdate");
var oidcClaimsRequest = new OIDCClaimsRequest().withUserInfoClaimsRequest(claimsSetRequest);
AuthenticationRequest authRequest = generateAuthRequest(REDIRECT_URI.toString(), responseType, scope, jsonArrayOf("Cl.Cm", "Cl"), Optional.of(oidcClaimsRequest));
var errorObject = authorizationService.validateAuthRequest(authRequest);
assertTrue(errorObject.isPresent());
assertThat(errorObject.get().getErrorObject(), equalTo(new ErrorObject(OAuth2Error.INVALID_REQUEST_CODE, "Request contains invalid claims")));
}
use of com.nimbusds.openid.connect.sdk.OIDCClaimsRequest in project di-authentication-api by alphagov.
the class AuthorizationServiceTest method shouldSuccessfullyValidateAuthRequestWhenValidClaimsArePresent.
@Test
void shouldSuccessfullyValidateAuthRequestWhenValidClaimsArePresent() {
var scope = new Scope(OIDCScopeValue.OPENID);
var clientRegistry = new ClientRegistry().setRedirectUrls(singletonList(REDIRECT_URI.toString())).setClientID(CLIENT_ID.toString()).setScopes(scope.toStringList()).setClaims(List.of(ValidClaims.ADDRESS.getValue(), ValidClaims.CORE_IDENTITY_JWT.getValue()));
when(dynamoClientService.getClient(CLIENT_ID.toString())).thenReturn(Optional.of(clientRegistry));
var claimsSetRequest = new ClaimsSetRequest().add(ValidClaims.ADDRESS.getValue()).add(ValidClaims.CORE_IDENTITY_JWT.getValue());
var oidcClaimsRequest = new OIDCClaimsRequest().withUserInfoClaimsRequest(claimsSetRequest);
var authRequest = generateAuthRequest(REDIRECT_URI.toString(), new ResponseType(ResponseType.Value.CODE), scope, jsonArrayOf("Cl.Cm", "Cl"), Optional.of(oidcClaimsRequest));
var errorObject = authorizationService.validateAuthRequest(authRequest);
assertTrue(errorObject.isEmpty());
}
use of com.nimbusds.openid.connect.sdk.OIDCClaimsRequest 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());
});
}
use of com.nimbusds.openid.connect.sdk.OIDCClaimsRequest in project di-authentication-api by alphagov.
the class UserInfoIntegrationTest method shouldReturn200WhenIdentityIsEnabledAndIdentityClaimsArePresent.
@Test
void shouldReturn200WhenIdentityIsEnabledAndIdentityClaimsArePresent() throws Json.JsonException, ParseException {
var configurationService = new UserInfoIntegrationTest.UserInfoConfigurationService();
handler = new UserInfoHandler(configurationService);
var claimsSetRequest = new ClaimsSetRequest().add(ValidClaims.CORE_IDENTITY_JWT.getValue()).add(ValidClaims.ADDRESS.getValue()).add(ValidClaims.PASSPORT.getValue());
var oidcValidClaimsRequest = new OIDCClaimsRequest().withUserInfoClaimsRequest(claimsSetRequest);
var claimsSet = new JWTClaimsSet.Builder().claim("scope", SCOPES).issuer("issuer-id").expirationTime(EXPIRY_DATE).issueTime(NowHelper.now()).claim("client_id", "client-id-one").subject(PUBLIC_SUBJECT.getValue()).jwtID(UUID.randomUUID().toString()).claim("claims", oidcValidClaimsRequest.getUserInfoClaimsRequest().getEntries().stream().map(ClaimsSetRequest.Entry::getClaimName).collect(Collectors.toList())).build();
var signedJWT = tokenSigner.signJwt(claimsSet);
var accessToken = new BearerAccessToken(signedJWT.serialize());
var accessTokenStore = new AccessTokenStore(accessToken.getValue(), INTERNAL_SUBJECT.getValue());
redis.addToRedis(ACCESS_TOKEN_PREFIX + CLIENT_ID + "." + PUBLIC_SUBJECT, objectMapper.writeValueAsString(accessTokenStore), 300L);
var signedCredential = SignedCredentialHelper.generateCredential();
setUpDynamo(signedCredential.serialize(), Map.of(ValidClaims.ADDRESS.getValue(), ADDRESS_CLAIM, ValidClaims.PASSPORT.getValue(), PASSPORT_CLAIM));
var response = makeRequest(Optional.empty(), Map.of("Authorization", accessToken.toAuthorizationHeader()), Map.of());
assertThat(response, hasStatus(200));
var userInfoResponse = UserInfo.parse(response.getBody());
assertThat(userInfoResponse.getEmailVerified(), equalTo(true));
assertThat(userInfoResponse.getEmailAddress(), equalTo(TEST_EMAIL_ADDRESS));
assertThat(userInfoResponse.getPhoneNumber(), equalTo(FORMATTED_PHONE_NUMBER));
assertThat(userInfoResponse.getPhoneNumberVerified(), equalTo(true));
assertThat(userInfoResponse.getSubject(), equalTo(PUBLIC_SUBJECT));
assertThat(userInfoResponse.getClaim(ValidClaims.ADDRESS.getValue()), equalTo(ADDRESS_CLAIM));
assertThat(userInfoResponse.getClaim(ValidClaims.PASSPORT.getValue()), equalTo(PASSPORT_CLAIM));
assertThat(userInfoResponse.getClaim(ValidClaims.CORE_IDENTITY_JWT.getValue()), equalTo(signedCredential.serialize()));
assertThat(userInfoResponse.toJWTClaimsSet().getClaims().size(), equalTo(8));
assertNoAuditEventsReceived(auditTopic);
}
use of com.nimbusds.openid.connect.sdk.OIDCClaimsRequest in project di-authentication-api by alphagov.
the class IdentityIntegrationTest method shouldReturn204WhenCallingIdentityLambda.
@Test
void shouldReturn204WhenCallingIdentityLambda() throws JsonProcessingException {
Subject internalSubject = new Subject();
Subject publicSubject = new Subject();
LocalDateTime localDateTime = LocalDateTime.now().plusMinutes(10);
Date expiryDate = Date.from(localDateTime.atZone(ZoneId.of("UTC")).toInstant());
List<String> scopes = new ArrayList<>();
scopes.add("email");
scopes.add("phone");
scopes.add("openid");
var claimsSetRequest = new ClaimsSetRequest().add("name").add("birthdate");
var oidcValidClaimsRequest = new OIDCClaimsRequest().withUserInfoClaimsRequest(claimsSetRequest);
JWTClaimsSet claimsSet = new JWTClaimsSet.Builder().claim("scope", scopes).issuer("issuer-id").expirationTime(expiryDate).issueTime(Date.from(LocalDateTime.now().atZone(ZoneId.of("UTC")).toInstant())).claim("client_id", "client-id-one").subject(publicSubject.getValue()).jwtID(UUID.randomUUID().toString()).claim("claims", oidcValidClaimsRequest.getUserInfoClaimsRequest().getEntries().stream().map(ClaimsSetRequest.Entry::getClaimName).collect(Collectors.toList())).build();
SignedJWT signedJWT = tokenSigner.signJwt(claimsSet);
AccessToken accessToken = new BearerAccessToken(signedJWT.serialize());
AccessTokenStore accessTokenStore = new AccessTokenStore(accessToken.getValue(), internalSubject.getValue());
String accessTokenStoreString = new ObjectMapper().writeValueAsString(accessTokenStore);
redis.addToRedis(ACCESS_TOKEN_PREFIX + CLIENT_ID + "." + publicSubject, accessTokenStoreString, 300L);
SignedJWT signedCredential = SignedCredentialHelper.generateCredential();
setUpDynamo(publicSubject.getValue(), signedCredential.serialize());
var response = makeRequest(Optional.empty(), Map.of("Authorization", accessToken.toAuthorizationHeader()), Map.of());
assertThat(response, hasStatus(200));
IdentityResponse identityResponse = new ObjectMapper().readValue(response.getBody(), IdentityResponse.class);
assertThat(identityResponse.getSub(), equalTo(publicSubject.getValue()));
assertThat(identityResponse.getIdentityCredential(), equalTo(signedCredential.serialize()));
assertThat(spotStore.getSpotCredential(publicSubject.getValue()), equalTo(Optional.empty()));
}
Aggregations