Search in sources :

Example 86 with Subject

use of com.nimbusds.oauth2.sdk.id.Subject in project di-authentication-api by alphagov.

the class LogoutHandlerTest method shouldRedirectToDefaultLogoutUriWithErrorMessageWhenSignaturenIdTokenIsInvalid.

@Test
public void shouldRedirectToDefaultLogoutUriWithErrorMessageWhenSignaturenIdTokenIsInvalid() throws URISyntaxException, JOSEException {
    ECKey ecSigningKey = new ECKeyGenerator(Curve.P_256).algorithm(JWSAlgorithm.ES256).generate();
    SignedJWT signedJWT = TokenGeneratorHelper.generateIDToken("invalid-client-id", new Subject(), "http://localhost-rp", ecSigningKey);
    when(tokenValidationService.isTokenSignatureValid(signedJWT.serialize())).thenReturn(false);
    APIGatewayProxyRequestEvent event = generateRequestEvent(Map.of("id_token_hint", signedJWT.serialize(), "post_logout_redirect_uri", CLIENT_LOGOUT_URI.toString()));
    session.getClientSessions().add(CLIENT_SESSION_ID);
    generateSessionFromCookie(session);
    setupClientSessionToken(signedJWT);
    APIGatewayProxyResponseEvent response = handler.handleRequest(event, context);
    assertThat(response, hasStatus(302));
    ErrorObject errorObject = new ErrorObject(OAuth2Error.INVALID_REQUEST_CODE, "unable to validate id_token_hint");
    URIBuilder uriBuilder = new URIBuilder(DEFAULT_LOGOUT_URI);
    uriBuilder.addParameter("error_code", errorObject.getCode());
    uriBuilder.addParameter("error_description", errorObject.getDescription());
    URI expectedUri = uriBuilder.build();
    assertThat(response.getHeaders().get(ResponseHeaders.LOCATION), equalTo(expectedUri.toString()));
    verify(auditService).submitAuditEvent(OidcAuditableEvent.LOG_OUT_SUCCESS, "aws-session-id", SESSION_ID, AuditService.UNKNOWN, AuditService.UNKNOWN, AuditService.UNKNOWN, "123.123.123.123", AuditService.UNKNOWN, PERSISTENT_SESSION_ID);
}
Also used : APIGatewayProxyRequestEvent(com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent) ErrorObject(com.nimbusds.oauth2.sdk.ErrorObject) ECKeyGenerator(com.nimbusds.jose.jwk.gen.ECKeyGenerator) ECKey(com.nimbusds.jose.jwk.ECKey) SignedJWT(com.nimbusds.jwt.SignedJWT) APIGatewayProxyResponseEvent(com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent) URI(java.net.URI) Subject(com.nimbusds.oauth2.sdk.id.Subject) URIBuilder(org.apache.http.client.utils.URIBuilder) Test(org.junit.jupiter.api.Test)

Example 87 with Subject

use of com.nimbusds.oauth2.sdk.id.Subject in project di-authentication-api by alphagov.

the class LogoutHandlerTest method shouldRedirectToDefaultLogoutUriWithErrorMessageWhenClientIsNotFoundInClientRegistry.

@Test
public void shouldRedirectToDefaultLogoutUriWithErrorMessageWhenClientIsNotFoundInClientRegistry() throws JOSEException, URISyntaxException {
    ECKey ecSigningKey = new ECKeyGenerator(Curve.P_256).algorithm(JWSAlgorithm.ES256).generate();
    SignedJWT signedJWT = TokenGeneratorHelper.generateIDToken("invalid-client-id", SUBJECT, "http://localhost-rp", ecSigningKey);
    when(tokenValidationService.isTokenSignatureValid(signedJWT.serialize())).thenReturn(true);
    APIGatewayProxyRequestEvent event = generateRequestEvent(Map.of("id_token_hint", signedJWT.serialize(), "post_logout_redirect_uri", CLIENT_LOGOUT_URI.toString(), "state", STATE.toString()));
    session.getClientSessions().add(CLIENT_SESSION_ID);
    generateSessionFromCookie(session);
    setupClientSessionToken(signedJWT);
    APIGatewayProxyResponseEvent response = handler.handleRequest(event, context);
    assertThat(response, hasStatus(302));
    ErrorObject errorObject = new ErrorObject(OAuth2Error.UNAUTHORIZED_CLIENT_CODE, "client not found");
    URIBuilder uriBuilder = new URIBuilder(DEFAULT_LOGOUT_URI);
    uriBuilder.addParameter("state", STATE.getValue());
    uriBuilder.addParameter("error_code", errorObject.getCode());
    uriBuilder.addParameter("error_description", errorObject.getDescription());
    URI expectedUri = uriBuilder.build();
    assertThat(response.getHeaders().get(ResponseHeaders.LOCATION), equalTo(expectedUri.toString()));
    verify(auditService).submitAuditEvent(OidcAuditableEvent.LOG_OUT_SUCCESS, "aws-session-id", SESSION_ID, "invalid-client-id", AuditService.UNKNOWN, AuditService.UNKNOWN, "123.123.123.123", AuditService.UNKNOWN, PERSISTENT_SESSION_ID);
}
Also used : APIGatewayProxyRequestEvent(com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent) ErrorObject(com.nimbusds.oauth2.sdk.ErrorObject) ECKeyGenerator(com.nimbusds.jose.jwk.gen.ECKeyGenerator) ECKey(com.nimbusds.jose.jwk.ECKey) SignedJWT(com.nimbusds.jwt.SignedJWT) APIGatewayProxyResponseEvent(com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent) URI(java.net.URI) URIBuilder(org.apache.http.client.utils.URIBuilder) Test(org.junit.jupiter.api.Test)

Example 88 with Subject

use of com.nimbusds.oauth2.sdk.id.Subject in project di-authentication-api by alphagov.

the class UserInfoHandlerTest method shouldReturn200WithUserInfoBasedOnScopesForSuccessfulRequest.

@Test
void shouldReturn200WithUserInfoBasedOnScopesForSuccessfulRequest() throws ParseException, AccessTokenException {
    AccessToken accessToken = new BearerAccessToken();
    UserInfo userInfo = new UserInfo(SUBJECT);
    userInfo.setEmailVerified(true);
    userInfo.setPhoneNumberVerified(true);
    userInfo.setPhoneNumber(PHONE_NUMBER);
    userInfo.setEmailAddress(EMAIL_ADDRESS);
    when(accessTokenService.parse(accessToken.toAuthorizationHeader(), false)).thenReturn(accessTokenInfo);
    when(userInfoService.populateUserInfo(accessTokenInfo, false)).thenReturn(userInfo);
    APIGatewayProxyRequestEvent event = new APIGatewayProxyRequestEvent();
    event.setHeaders(Map.of("Authorization", accessToken.toAuthorizationHeader()));
    APIGatewayProxyResponseEvent result = handler.handleRequest(event, context);
    assertThat(result, hasStatus(200));
    UserInfo parsedResultBody = UserInfo.parse(result.getBody());
    assertThat(parsedResultBody.getSubject(), equalTo(SUBJECT));
    assertThat(parsedResultBody.getEmailAddress(), equalTo(EMAIL_ADDRESS));
    assertTrue(parsedResultBody.getEmailVerified());
    assertThat(parsedResultBody.getPhoneNumber(), equalTo(PHONE_NUMBER));
    assertTrue(parsedResultBody.getPhoneNumberVerified());
}
Also used : APIGatewayProxyRequestEvent(com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent) AccessToken(com.nimbusds.oauth2.sdk.token.AccessToken) BearerAccessToken(com.nimbusds.oauth2.sdk.token.BearerAccessToken) UserInfo(com.nimbusds.openid.connect.sdk.claims.UserInfo) BearerAccessToken(com.nimbusds.oauth2.sdk.token.BearerAccessToken) APIGatewayProxyResponseEvent(com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent) Test(org.junit.jupiter.api.Test)

Example 89 with Subject

use of com.nimbusds.oauth2.sdk.id.Subject in project di-authentication-api by alphagov.

the class AccessTokenServiceTest method createSignedAccessToken.

private AccessToken createSignedAccessToken(OIDCClaimsRequest identityClaims, boolean expired) {
    try {
        var expiryDate = expired ? NowHelper.nowMinus(2, ChronoUnit.MINUTES) : NowHelper.nowPlus(3, ChronoUnit.MINUTES);
        var ecSigningKey = new ECKeyGenerator(Curve.P_256).keyID(KEY_ID).algorithm(JWSAlgorithm.ES256).generate();
        var signedJWT = TokenGeneratorHelper.generateSignedToken(CLIENT_ID, BASE_URL, SCOPES, new ECDSASigner(ecSigningKey), SUBJECT, ecSigningKey.getKeyID(), expiryDate, identityClaims);
        return new BearerAccessToken(signedJWT.serialize());
    } catch (JOSEException e) {
        throw new RuntimeException(e);
    }
}
Also used : ECDSASigner(com.nimbusds.jose.crypto.ECDSASigner) ECKeyGenerator(com.nimbusds.jose.jwk.gen.ECKeyGenerator) BearerAccessToken(com.nimbusds.oauth2.sdk.token.BearerAccessToken) JOSEException(com.nimbusds.jose.JOSEException)

Example 90 with Subject

use of com.nimbusds.oauth2.sdk.id.Subject in project di-authentication-api by alphagov.

the class AccessTokenService method parse.

public AccessTokenInfo parse(String authorizationHeader, boolean identityEnabled) throws AccessTokenException {
    AccessToken accessToken;
    try {
        accessToken = AccessToken.parse(authorizationHeader, AccessTokenType.BEARER);
    } catch (com.nimbusds.oauth2.sdk.ParseException e) {
        LOG.warn("Unable to parse AccessToken");
        throw new AccessTokenException("Unable to parse AccessToken", BearerTokenError.INVALID_TOKEN);
    }
    SignedJWT signedJWT;
    try {
        signedJWT = SignedJWT.parse(accessToken.getValue());
        var currentDateTime = NowHelper.now();
        if (DateUtils.isBefore(signedJWT.getJWTClaimsSet().getExpirationTime(), currentDateTime, 0)) {
            LOG.warn("Access Token has expired. Access Token expires at: {}. CurrentDateTime is: {}", signedJWT.getJWTClaimsSet().getExpirationTime(), currentDateTime);
            throw new AccessTokenException(INVALID_ACCESS_TOKEN, BearerTokenError.INVALID_TOKEN);
        }
        if (!tokenValidationService.validateAccessTokenSignature(accessToken)) {
            LOG.warn("Unable to validate AccessToken signature");
            throw new AccessTokenException("Unable to validate AccessToken signature", BearerTokenError.INVALID_TOKEN);
        }
        var clientID = signedJWT.getJWTClaimsSet().getStringClaim("client_id");
        var client = clientService.getClient(clientID);
        attachLogFieldToLogs(CLIENT_ID, clientID);
        if (client.isEmpty()) {
            LOG.warn("Client not found");
            throw new AccessTokenException("Client not found", BearerTokenError.INVALID_TOKEN);
        }
        var scopes = JSONArrayUtils.parse(signedJWT.getJWTClaimsSet().getClaim("scope").toString()).stream().map(Objects::toString).collect(Collectors.toList());
        if (!areScopesValid(scopes) || !client.get().getScopes().containsAll(scopes)) {
            LOG.warn("Invalid Scopes: {}", scopes);
            throw new AccessTokenException("Invalid Scopes", OAuth2Error.INVALID_SCOPE);
        }
        List<String> identityClaims = null;
        if (identityEnabled) {
            identityClaims = getIdentityClaims(signedJWT.getJWTClaimsSet());
        }
        var subject = signedJWT.getJWTClaimsSet().getSubject();
        var accessTokenStore = getAccessTokenStore(clientID, subject);
        if (accessTokenStore.isEmpty()) {
            LOG.warn("Access Token Store is empty. Access Token expires at: {}. CurrentDateTime is: {}. JWTID in Access Token sent in request: {}", signedJWT.getJWTClaimsSet().getExpirationTime(), currentDateTime, signedJWT.getJWTClaimsSet().getJWTID());
            throw new AccessTokenException(INVALID_ACCESS_TOKEN, BearerTokenError.INVALID_TOKEN);
        }
        if (!accessTokenStore.get().getToken().equals(accessToken.getValue())) {
            LOG.warn("Access Token in Access Token Store is different to Access Token sent in request");
            var storeJwtId = SignedJWT.parse(accessTokenStore.get().getToken()).getJWTClaimsSet().getJWTID();
            LOG.warn("JWTID in AccessTokenStore: {} compared to JWTID in Access Token sent in request: {}", storeJwtId, signedJWT.getJWTClaimsSet().getJWTID());
            throw new AccessTokenException(INVALID_ACCESS_TOKEN, BearerTokenError.INVALID_TOKEN);
        }
        return new AccessTokenInfo(accessTokenStore.get(), subject, scopes, identityClaims);
    } catch (ParseException e) {
        LOG.warn("Unable to parse AccessToken to SignedJWT");
        throw new AccessTokenException("Unable to parse AccessToken to SignedJWT", BearerTokenError.INVALID_TOKEN);
    } catch (com.nimbusds.oauth2.sdk.ParseException e) {
        LOG.warn("Unable to parse ClaimSet in AccessToken");
        throw new AccessTokenException("Unable to parse ClaimSet in AccessToken", BearerTokenError.INVALID_TOKEN);
    }
}
Also used : AccessTokenInfo(uk.gov.di.authentication.oidc.entity.AccessTokenInfo) AccessToken(com.nimbusds.oauth2.sdk.token.AccessToken) AccessTokenException(uk.gov.di.authentication.shared.exceptions.AccessTokenException) SignedJWT(com.nimbusds.jwt.SignedJWT) ParseException(java.text.ParseException)

Aggregations

Subject (com.nimbusds.oauth2.sdk.id.Subject)59 Test (org.junit.jupiter.api.Test)36 SignedJWT (com.nimbusds.jwt.SignedJWT)22 Date (java.util.Date)22 ApiGatewayHandlerIntegrationTest (uk.gov.di.authentication.sharedtest.basetest.ApiGatewayHandlerIntegrationTest)19 UserProfile (uk.gov.di.authentication.shared.entity.UserProfile)18 KeyPair (java.security.KeyPair)16 BearerAccessToken (com.nimbusds.oauth2.sdk.token.BearerAccessToken)15 JWTClaimsSet (com.nimbusds.jwt.JWTClaimsSet)13 ParseException (com.nimbusds.oauth2.sdk.ParseException)12 Scope (com.nimbusds.oauth2.sdk.Scope)12 APIGatewayProxyRequestEvent (com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent)11 APIGatewayProxyResponseEvent (com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent)11 AccessToken (com.nimbusds.oauth2.sdk.token.AccessToken)10 ECKeyGenerator (com.nimbusds.jose.jwk.gen.ECKeyGenerator)9 ParameterizedTest (org.junit.jupiter.params.ParameterizedTest)9 ECDSASigner (com.nimbusds.jose.crypto.ECDSASigner)8 Issuer (com.nimbusds.oauth2.sdk.id.Issuer)8 IDTokenClaimsSet (com.nimbusds.openid.connect.sdk.claims.IDTokenClaimsSet)8 LocalDateTime (java.time.LocalDateTime)8