Search in sources :

Example 31 with Subject

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

the class LoginHandlerTest method shouldReturn401IfMigratedUserHasInvalidCredentials.

@Test
void shouldReturn401IfMigratedUserHasInvalidCredentials() {
    String legacySubjectId = new Subject().getValue();
    UserProfile userProfile = generateUserProfile(legacySubjectId);
    when(authenticationService.getUserProfileByEmailMaybe(EMAIL)).thenReturn(Optional.of(userProfile));
    when(userMigrationService.processMigratedUser(userCredentials, PASSWORD)).thenReturn(false);
    APIGatewayProxyRequestEvent event = new APIGatewayProxyRequestEvent();
    event.setHeaders(Map.of("Session-Id", session.getSessionId()));
    event.setBody(format("{ \"password\": \"%s\", \"email\": \"%s\" }", PASSWORD, EMAIL));
    usingValidSession();
    APIGatewayProxyResponseEvent result = handler.handleRequest(event, context);
    assertThat(result, hasStatus(401));
    assertThat(result, hasJsonBody(ErrorResponse.ERROR_1008));
}
Also used : UserProfile(uk.gov.di.authentication.shared.entity.UserProfile) APIGatewayProxyRequestEvent(com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent) APIGatewayProxyResponseEvent(com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent) Subject(com.nimbusds.oauth2.sdk.id.Subject) Test(org.junit.jupiter.api.Test)

Example 32 with Subject

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

the class AuthoriseAccessTokenHandler method authoriseAccessTokenHandler.

public AuthPolicy authoriseAccessTokenHandler(TokenAuthorizerContext input, Context context) {
    if (input.getType().equals(WARMUP_HEADER)) {
        LOG.info("Warmup Request Received");
        try {
            sleep(configurationService.getWarmupDelayMillis());
        } catch (InterruptedException e) {
            LOG.error("Sleep was interrupted", e);
            throw new RuntimeException("Sleep was interrupted", e);
        }
        LOG.info("Instance warmed for request");
        throw new RuntimeException("Unauthorized");
    } else {
        LOG.info("Request received in AuthoriseAccessTokenHandler");
        try {
            String token = input.getAuthorizationToken();
            AccessToken accessToken = AccessToken.parse(token, AccessTokenType.BEARER);
            SignedJWT signedAccessToken = SignedJWT.parse(accessToken.getValue());
            JWTClaimsSet claimsSet = signedAccessToken.getJWTClaimsSet();
            Date currentDateTime = NowHelper.now();
            if (DateUtils.isBefore(claimsSet.getExpirationTime(), currentDateTime, 0)) {
                LOG.warn("Access Token expires at: {}. CurrentDateTime is: {}", claimsSet.getExpirationTime(), currentDateTime);
                throw new RuntimeException("Unauthorized");
            }
            boolean isAccessTokenSignatureValid = tokenValidationService.validateAccessTokenSignature(accessToken);
            if (!isAccessTokenSignatureValid) {
                LOG.warn("Access Token signature is not valid");
                throw new RuntimeException("Unauthorized");
            }
            LOG.info("Successfully validated Access Token signature");
            List<String> scopeList = claimsSet.getStringListClaim("scope");
            if (scopeList == null || !scopeList.contains(CustomScopeValue.ACCOUNT_MANAGEMENT.getValue())) {
                LOG.warn("Access Token scope is not valid or missing");
                throw new RuntimeException("Unauthorized");
            }
            LOG.info("Successfully validated Access Token scope");
            String clientId = claimsSet.getStringClaim("client_id");
            if (clientId == null) {
                LOG.warn("Access Token client_id is missing");
                throw new RuntimeException("Unauthorized");
            }
            if (!clientService.isValidClient(clientId)) {
                LOG.warn("Access Token client_id does not exist in Dynamo. ClientId {}", clientId);
                throw new RuntimeException("Unauthorized");
            }
            String subject = claimsSet.getSubject();
            if (subject == null) {
                LOG.warn("Access Token subject is missing");
                throw new RuntimeException("Unauthorized");
            }
            try {
                dynamoService.getUserProfileFromPublicSubject(subject);
            } catch (Exception e) {
                LOG.error("Unable to retrieve UserProfile from Dynamo with given SubjectID");
                throw new RuntimeException("Unauthorized");
            }
            LOG.info("User found in Dynamo with given SubjectID");
            String methodArn = input.getMethodArn();
            String[] arnPartials = methodArn.split(":");
            String region = arnPartials[3];
            String awsAccountId = arnPartials[4];
            String[] apiGatewayArnPartials = arnPartials[5].split("/");
            String restApiId = apiGatewayArnPartials[0];
            String stage = apiGatewayArnPartials[1];
            LOG.info("Generating AuthPolicy");
            return new AuthPolicy(subject, AuthPolicy.PolicyDocument.getAllowAllPolicy(region, awsAccountId, restApiId, stage));
        } catch (ParseException | java.text.ParseException e) {
            LOG.warn("Unable to parse Access Token");
            throw new RuntimeException("Unauthorized");
        }
    }
}
Also used : SignedJWT(com.nimbusds.jwt.SignedJWT) Date(java.util.Date) ParseException(com.nimbusds.oauth2.sdk.ParseException) AuthPolicy(uk.gov.di.accountmanagement.entity.AuthPolicy) AccessToken(com.nimbusds.oauth2.sdk.token.AccessToken) JWTClaimsSet(com.nimbusds.jwt.JWTClaimsSet) ParseException(com.nimbusds.oauth2.sdk.ParseException)

Example 33 with Subject

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

the class RemoveAccountHandler method removeAccountRequestHandler.

public APIGatewayProxyResponseEvent removeAccountRequestHandler(APIGatewayProxyRequestEvent input, Context context) {
    return isWarming(input).orElseGet(() -> {
        try {
            String sessionId = RequestHeaderHelper.getHeaderValueOrElse(input.getHeaders(), SESSION_ID_HEADER, "");
            attachSessionIdToLogs(sessionId);
            LOG.info("RemoveAccountHandler received request");
            RemoveAccountRequest removeAccountRequest = objectMapper.readValue(input.getBody(), RemoveAccountRequest.class);
            String email = removeAccountRequest.getEmail();
            UserProfile userProfile = authenticationService.getUserProfileByEmailMaybe(email).orElseThrow(() -> new RuntimeException("User not found"));
            Map<String, Object> authorizerParams = input.getRequestContext().getAuthorizer();
            RequestBodyHelper.validatePrincipal(new Subject(userProfile.getPublicSubjectID()), authorizerParams);
            authenticationService.removeAccount(email);
            LOG.info("User account removed. Adding message to SQS queue");
            NotifyRequest notifyRequest = new NotifyRequest(email, NotificationType.DELETE_ACCOUNT);
            sqsClient.send(objectMapper.writeValueAsString((notifyRequest)));
            LOG.info("Remove account message successfully added to queue. Generating successful gateway response");
            auditService.submitAuditEvent(AccountManagementAuditableEvent.DELETE_ACCOUNT, context.getAwsRequestId(), sessionId, AuditService.UNKNOWN, userProfile.getSubjectID(), userProfile.getEmail(), IpAddressHelper.extractIpAddress(input), userProfile.getPhoneNumber(), PersistentIdHelper.extractPersistentIdFromHeaders(input.getHeaders()));
            return generateEmptySuccessApiGatewayResponse();
        } catch (JsonException e) {
            return generateApiGatewayProxyErrorResponse(400, ErrorResponse.ERROR_1001);
        }
    });
}
Also used : JsonException(uk.gov.di.authentication.shared.serialization.Json.JsonException) UserProfile(uk.gov.di.authentication.shared.entity.UserProfile) RemoveAccountRequest(uk.gov.di.accountmanagement.entity.RemoveAccountRequest) NotifyRequest(uk.gov.di.accountmanagement.entity.NotifyRequest) Subject(com.nimbusds.oauth2.sdk.id.Subject)

Example 34 with Subject

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

the class UpdatePhoneNumberHandler method updatePhoneNumberRequestHandler.

public APIGatewayProxyResponseEvent updatePhoneNumberRequestHandler(APIGatewayProxyRequestEvent input, Context context) {
    return isWarming(input).orElseGet(() -> {
        String sessionId = RequestHeaderHelper.getHeaderValueOrElse(input.getHeaders(), SESSION_ID_HEADER, "");
        attachSessionIdToLogs(sessionId);
        LOG.info("UpdatePhoneNumberHandler received request");
        try {
            UpdatePhoneNumberRequest updatePhoneNumberRequest = objectMapper.readValue(input.getBody(), UpdatePhoneNumberRequest.class);
            boolean isValidOtpCode = codeStorageService.isValidOtpCode(updatePhoneNumberRequest.getEmail(), updatePhoneNumberRequest.getOtp(), NotificationType.VERIFY_PHONE_NUMBER);
            if (!isValidOtpCode) {
                return generateApiGatewayProxyErrorResponse(400, ErrorResponse.ERROR_1020);
            }
            UserProfile userProfile = dynamoService.getUserProfileByEmail(updatePhoneNumberRequest.getEmail());
            Map<String, Object> authorizerParams = input.getRequestContext().getAuthorizer();
            RequestBodyHelper.validatePrincipal(new Subject(userProfile.getPublicSubjectID()), authorizerParams);
            dynamoService.updatePhoneNumber(updatePhoneNumberRequest.getEmail(), updatePhoneNumberRequest.getPhoneNumber());
            LOG.info("Phone Number has successfully been updated. Adding message to SQS queue");
            NotifyRequest notifyRequest = new NotifyRequest(updatePhoneNumberRequest.getEmail(), NotificationType.PHONE_NUMBER_UPDATED);
            sqsClient.send(objectMapper.writeValueAsString((notifyRequest)));
            auditService.submitAuditEvent(AccountManagementAuditableEvent.UPDATE_PHONE_NUMBER, context.getAwsRequestId(), sessionId, AuditService.UNKNOWN, userProfile.getSubjectID(), userProfile.getEmail(), IpAddressHelper.extractIpAddress(input), updatePhoneNumberRequest.getPhoneNumber(), PersistentIdHelper.extractPersistentIdFromHeaders(input.getHeaders()));
            LOG.info("Message successfully added to queue. Generating successful gateway response");
            return generateEmptySuccessApiGatewayResponse();
        } catch (JsonException | IllegalArgumentException e) {
            return generateApiGatewayProxyErrorResponse(400, ErrorResponse.ERROR_1001);
        }
    });
}
Also used : JsonException(uk.gov.di.authentication.shared.serialization.Json.JsonException) UserProfile(uk.gov.di.authentication.shared.entity.UserProfile) NotifyRequest(uk.gov.di.accountmanagement.entity.NotifyRequest) Subject(com.nimbusds.oauth2.sdk.id.Subject) UpdatePhoneNumberRequest(uk.gov.di.accountmanagement.entity.UpdatePhoneNumberRequest)

Example 35 with Subject

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

the class AuthoriseAccessTokenIntegrationTest method shouldThrowExceptionWhenAccessTokenHasUnknownSubject.

@Test
void shouldThrowExceptionWhenAccessTokenHasUnknownSubject() {
    var publicSubject = new Subject().getValue();
    var scopes = asList(OIDCScopeValue.OPENID.getValue(), CustomScopeValue.ACCOUNT_MANAGEMENT.getValue());
    var accessToken = generateSignedAccessToken(scopes, CLIENT_ID.getValue(), publicSubject, validDate);
    setUpClient(scopes);
    setUpClient(scopes);
    expectException(() -> makeRequest(accessToken.toAuthorizationHeader()));
}
Also used : Subject(com.nimbusds.oauth2.sdk.id.Subject) HandlerIntegrationTest(uk.gov.di.authentication.sharedtest.basetest.HandlerIntegrationTest) Test(org.junit.jupiter.api.Test)

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