Search in sources :

Example 1 with OIDCClaimsRequest

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")));
}
Also used : ClaimsSetRequest(com.nimbusds.openid.connect.sdk.claims.ClaimsSetRequest) OIDCClaimsRequest(com.nimbusds.openid.connect.sdk.OIDCClaimsRequest) Scope(com.nimbusds.oauth2.sdk.Scope) ErrorObject(com.nimbusds.oauth2.sdk.ErrorObject) AuthenticationRequest(com.nimbusds.openid.connect.sdk.AuthenticationRequest) ResponseType(com.nimbusds.oauth2.sdk.ResponseType) Test(org.junit.jupiter.api.Test)

Example 2 with OIDCClaimsRequest

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());
}
Also used : ClaimsSetRequest(com.nimbusds.openid.connect.sdk.claims.ClaimsSetRequest) OIDCClaimsRequest(com.nimbusds.openid.connect.sdk.OIDCClaimsRequest) Scope(com.nimbusds.oauth2.sdk.Scope) ClientRegistry(uk.gov.di.authentication.shared.entity.ClientRegistry) ResponseType(com.nimbusds.oauth2.sdk.ResponseType) Test(org.junit.jupiter.api.Test)

Example 3 with OIDCClaimsRequest

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());
    });
}
Also used : UserProfile(uk.gov.di.authentication.shared.entity.UserProfile) HashMap(java.util.HashMap) ErrorObject(com.nimbusds.oauth2.sdk.ErrorObject) OIDCTokenResponse(com.nimbusds.openid.connect.sdk.OIDCTokenResponse) Subject(com.nimbusds.oauth2.sdk.id.Subject) AuthCodeExchangeData(uk.gov.di.authentication.shared.entity.AuthCodeExchangeData) OIDCClaimsRequest(com.nimbusds.openid.connect.sdk.OIDCClaimsRequest) RefreshToken(com.nimbusds.oauth2.sdk.token.RefreshToken) Scope(com.nimbusds.oauth2.sdk.Scope) ClientSession(uk.gov.di.authentication.shared.entity.ClientSession) ClientRegistry(uk.gov.di.authentication.shared.entity.ClientRegistry) ErrorObject(com.nimbusds.oauth2.sdk.ErrorObject) ParseException(com.nimbusds.oauth2.sdk.ParseException) AuthenticationRequest(com.nimbusds.openid.connect.sdk.AuthenticationRequest) NoSuchElementException(java.util.NoSuchElementException)

Example 4 with OIDCClaimsRequest

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);
}
Also used : ClaimsSetRequest(com.nimbusds.openid.connect.sdk.claims.ClaimsSetRequest) OIDCClaimsRequest(com.nimbusds.openid.connect.sdk.OIDCClaimsRequest) AccessTokenStore(uk.gov.di.authentication.shared.entity.AccessTokenStore) JWTClaimsSet(com.nimbusds.jwt.JWTClaimsSet) UserInfoHandler(uk.gov.di.authentication.oidc.lambda.UserInfoHandler) BearerAccessToken(com.nimbusds.oauth2.sdk.token.BearerAccessToken) Test(org.junit.jupiter.api.Test) ApiGatewayHandlerIntegrationTest(uk.gov.di.authentication.sharedtest.basetest.ApiGatewayHandlerIntegrationTest)

Example 5 with OIDCClaimsRequest

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()));
}
Also used : LocalDateTime(java.time.LocalDateTime) ClaimsSetRequest(com.nimbusds.openid.connect.sdk.claims.ClaimsSetRequest) IdentityResponse(uk.gov.di.authentication.oidc.entity.IdentityResponse) ArrayList(java.util.ArrayList) SignedJWT(com.nimbusds.jwt.SignedJWT) Subject(com.nimbusds.oauth2.sdk.id.Subject) Date(java.util.Date) OIDCClaimsRequest(com.nimbusds.openid.connect.sdk.OIDCClaimsRequest) AccessTokenStore(uk.gov.di.authentication.shared.entity.AccessTokenStore) JWTClaimsSet(com.nimbusds.jwt.JWTClaimsSet) AccessToken(com.nimbusds.oauth2.sdk.token.AccessToken) BearerAccessToken(com.nimbusds.oauth2.sdk.token.BearerAccessToken) BearerAccessToken(com.nimbusds.oauth2.sdk.token.BearerAccessToken) ObjectMapper(com.fasterxml.jackson.databind.ObjectMapper) Test(org.junit.jupiter.api.Test) ApiGatewayHandlerIntegrationTest(uk.gov.di.authentication.sharedtest.basetest.ApiGatewayHandlerIntegrationTest)

Aggregations

OIDCClaimsRequest (com.nimbusds.openid.connect.sdk.OIDCClaimsRequest)13 ClaimsSetRequest (com.nimbusds.openid.connect.sdk.claims.ClaimsSetRequest)9 Test (org.junit.jupiter.api.Test)9 Scope (com.nimbusds.oauth2.sdk.Scope)8 ErrorObject (com.nimbusds.oauth2.sdk.ErrorObject)6 ResponseType (com.nimbusds.oauth2.sdk.ResponseType)6 AuthenticationRequest (com.nimbusds.openid.connect.sdk.AuthenticationRequest)5 Subject (com.nimbusds.oauth2.sdk.id.Subject)4 BearerAccessToken (com.nimbusds.oauth2.sdk.token.BearerAccessToken)3 HashMap (java.util.HashMap)3 AccessTokenStore (uk.gov.di.authentication.shared.entity.AccessTokenStore)3 ClientRegistry (uk.gov.di.authentication.shared.entity.ClientRegistry)3 ApiGatewayHandlerIntegrationTest (uk.gov.di.authentication.sharedtest.basetest.ApiGatewayHandlerIntegrationTest)3 JWTClaimsSet (com.nimbusds.jwt.JWTClaimsSet)2 ParseException (com.nimbusds.oauth2.sdk.ParseException)2 ClientID (com.nimbusds.oauth2.sdk.id.ClientID)2 State (com.nimbusds.oauth2.sdk.id.State)2 RefreshToken (com.nimbusds.oauth2.sdk.token.RefreshToken)2 Nonce (com.nimbusds.openid.connect.sdk.Nonce)2 OIDCTokenResponse (com.nimbusds.openid.connect.sdk.OIDCTokenResponse)2