Search in sources :

Example 1 with ClientNotFoundException

use of uk.gov.di.authentication.shared.exceptions.ClientNotFoundException in project di-authentication-api by alphagov.

the class AuthCodeHandler method handleRequest.

@Override
public APIGatewayProxyResponseEvent handleRequest(APIGatewayProxyRequestEvent input, Context context) {
    return isWarming(input).orElseGet(() -> {
        Session session = sessionService.getSessionFromRequestHeaders(input.getHeaders()).orElse(null);
        if (Objects.isNull(session)) {
            return generateApiGatewayProxyErrorResponse(400, ErrorResponse.ERROR_1000);
        }
        String clientSessionId = getHeaderValueFromHeaders(input.getHeaders(), CLIENT_SESSION_ID_HEADER, configurationService.getHeadersCaseInsensitive());
        if (Objects.isNull(clientSessionId)) {
            return generateApiGatewayProxyErrorResponse(400, ErrorResponse.ERROR_1018);
        }
        attachSessionIdToLogs(session);
        attachLogFieldToLogs(CLIENT_SESSION_ID, clientSessionId);
        LOG.info("Processing request");
        AuthenticationRequest authenticationRequest;
        ClientSession clientSession;
        try {
            clientSession = clientSessionService.getClientSessionFromRequestHeaders(input.getHeaders()).orElse(null);
            if (Objects.isNull(clientSession)) {
                LOG.info("ClientSession not found");
                return generateApiGatewayProxyErrorResponse(400, ErrorResponse.ERROR_1018);
            }
            authenticationRequest = AuthenticationRequest.parse(clientSession.getAuthRequestParams());
        } catch (ParseException e) {
            if (e.getRedirectionURI() == null) {
                LOG.warn("Authentication request could not be parsed: redirect URI or Client ID is missing from auth request", e);
                throw new RuntimeException("Redirect URI or Client ID is missing from auth request", e);
            }
            AuthenticationErrorResponse errorResponse = authorizationService.generateAuthenticationErrorResponse(e.getRedirectionURI(), e.getState(), e.getResponseMode(), e.getErrorObject());
            LOG.warn("Authentication request could not be parsed", e);
            return generateResponse(new AuthCodeResponse(errorResponse.toURI().toString()));
        }
        try {
            if (!authorizationService.isClientRedirectUriValid(authenticationRequest.getClientID(), authenticationRequest.getRedirectionURI())) {
                return generateApiGatewayProxyErrorResponse(400, ErrorResponse.ERROR_1016);
            }
            VectorOfTrust requestedVectorOfTrust = clientSession.getEffectiveVectorOfTrust();
            if (isNull(session.getCurrentCredentialStrength()) || requestedVectorOfTrust.getCredentialTrustLevel().compareTo(session.getCurrentCredentialStrength()) > 0) {
                session.setCurrentCredentialStrength(requestedVectorOfTrust.getCredentialTrustLevel());
            }
            AuthorizationCode authCode = authorisationCodeService.generateAuthorisationCode(clientSessionId, session.getEmailAddress());
            AuthenticationSuccessResponse authenticationResponse = authorizationService.generateSuccessfulAuthResponse(authenticationRequest, authCode);
            LOG.info("Successfully processed request");
            cloudwatchMetricsService.incrementCounter("SignIn", Map.of("Account", session.isNewAccount().name(), "Environment", configurationService.getEnvironment(), "Client", authenticationRequest.getClientID().getValue()));
            sessionService.save(session.setAuthenticated(true).setNewAccount(EXISTING));
            auditService.submitAuditEvent(OidcAuditableEvent.AUTH_CODE_ISSUED, context.getAwsRequestId(), session.getSessionId(), authenticationRequest.getClientID().getValue(), AuditService.UNKNOWN, session.getEmailAddress(), IpAddressHelper.extractIpAddress(input), AuditService.UNKNOWN, PersistentIdHelper.extractPersistentIdFromHeaders(input.getHeaders()));
            return generateResponse(new AuthCodeResponse(authenticationResponse.toURI().toString()));
        } catch (ClientNotFoundException e) {
            AuthenticationErrorResponse errorResponse = authorizationService.generateAuthenticationErrorResponse(authenticationRequest, OAuth2Error.INVALID_CLIENT);
            return generateResponse(new AuthCodeResponse(errorResponse.toURI().toString()));
        } catch (URISyntaxException e) {
            return generateApiGatewayProxyErrorResponse(400, ErrorResponse.ERROR_1016);
        }
    });
}
Also used : AuthorizationCode(com.nimbusds.oauth2.sdk.AuthorizationCode) AuthCodeResponse(uk.gov.di.authentication.oidc.entity.AuthCodeResponse) AuthenticationErrorResponse(com.nimbusds.openid.connect.sdk.AuthenticationErrorResponse) ClientNotFoundException(uk.gov.di.authentication.shared.exceptions.ClientNotFoundException) VectorOfTrust(uk.gov.di.authentication.shared.entity.VectorOfTrust) URISyntaxException(java.net.URISyntaxException) AuthenticationSuccessResponse(com.nimbusds.openid.connect.sdk.AuthenticationSuccessResponse) ClientSession(uk.gov.di.authentication.shared.entity.ClientSession) ParseException(com.nimbusds.oauth2.sdk.ParseException) AuthenticationRequest(com.nimbusds.openid.connect.sdk.AuthenticationRequest) Session(uk.gov.di.authentication.shared.entity.Session) ClientSession(uk.gov.di.authentication.shared.entity.ClientSession)

Example 2 with ClientNotFoundException

use of uk.gov.di.authentication.shared.exceptions.ClientNotFoundException in project di-authentication-api by alphagov.

the class AuthorizationServiceTest method shouldThrowClientNotFoundExceptionWhenClientDoesNotExist.

@Test
void shouldThrowClientNotFoundExceptionWhenClientDoesNotExist() {
    when(dynamoClientService.getClient(CLIENT_ID.toString())).thenReturn(Optional.empty());
    ClientNotFoundException exception = Assertions.assertThrows(ClientNotFoundException.class, () -> authorizationService.isClientRedirectUriValid(CLIENT_ID, REDIRECT_URI), "Expected to throw exception");
    assertThat(exception.getMessage(), equalTo(format("No Client found for ClientID: %s", CLIENT_ID)));
}
Also used : ClientNotFoundException(uk.gov.di.authentication.shared.exceptions.ClientNotFoundException) Test(org.junit.jupiter.api.Test)

Example 3 with ClientNotFoundException

use of uk.gov.di.authentication.shared.exceptions.ClientNotFoundException in project di-authentication-api by alphagov.

the class SendNotificationHandler method handleRequestWithUserContext.

@Override
public APIGatewayProxyResponseEvent handleRequestWithUserContext(APIGatewayProxyRequestEvent input, Context context, SendNotificationRequest request, UserContext userContext) {
    attachSessionIdToLogs(userContext.getSession());
    attachLogFieldToLogs(PERSISTENT_SESSION_ID, extractPersistentIdFromHeaders(input.getHeaders()));
    attachLogFieldToLogs(LogFieldName.CLIENT_ID, userContext.getClient().map(ClientRegistry::getClientID).orElse("unknown"));
    try {
        if (!userContext.getSession().validateSession(request.getEmail())) {
            return generateApiGatewayProxyErrorResponse(400, ErrorResponse.ERROR_1000);
        }
        if (request.getNotificationType().equals(ACCOUNT_CREATED_CONFIRMATION)) {
            LOG.info("Placing message on queue for AccountCreatedConfirmation");
            NotifyRequest notifyRequest = new NotifyRequest(request.getEmail(), ACCOUNT_CREATED_CONFIRMATION);
            if (notTestClientWithValidTestEmail(userContext, ACCOUNT_CREATED_CONFIRMATION)) {
                sqsClient.send(objectMapper.writeValueAsString((notifyRequest)));
                LOG.info("AccountCreatedConfirmation email placed on queue");
            }
            return generateEmptySuccessApiGatewayResponse();
        }
        Optional<ErrorResponse> codeRequestValid = isCodeRequestAttemptValid(request.getEmail(), userContext.getSession(), request.getNotificationType());
        if (codeRequestValid.isPresent()) {
            return generateApiGatewayProxyErrorResponse(400, codeRequestValid.get());
        }
        switch(request.getNotificationType()) {
            case VERIFY_EMAIL:
                return handleNotificationRequest(request.getEmail(), request.getNotificationType(), userContext.getSession(), userContext);
            case VERIFY_PHONE_NUMBER:
                if (request.getPhoneNumber() == null) {
                    return generateApiGatewayProxyResponse(400, ERROR_1011);
                }
                return handleNotificationRequest(PhoneNumberHelper.removeWhitespaceFromPhoneNumber(request.getPhoneNumber()), request.getNotificationType(), userContext.getSession(), userContext);
        }
        return generateApiGatewayProxyErrorResponse(400, ERROR_1002);
    } catch (SdkClientException ex) {
        LOG.error("Error sending message to queue");
        return generateApiGatewayProxyResponse(500, "Error sending message to queue");
    } catch (JsonException e) {
        return generateApiGatewayProxyErrorResponse(400, ERROR_1001);
    } catch (ClientNotFoundException e) {
        return generateApiGatewayProxyErrorResponse(400, ErrorResponse.ERROR_1015);
    }
}
Also used : JsonException(uk.gov.di.authentication.shared.serialization.Json.JsonException) ClientNotFoundException(uk.gov.di.authentication.shared.exceptions.ClientNotFoundException) SdkClientException(software.amazon.awssdk.core.exception.SdkClientException) ClientRegistry(uk.gov.di.authentication.shared.entity.ClientRegistry) NotifyRequest(uk.gov.di.authentication.shared.entity.NotifyRequest) ErrorResponse(uk.gov.di.authentication.shared.entity.ErrorResponse) ApiGatewayResponseHelper.generateApiGatewayProxyErrorResponse(uk.gov.di.authentication.shared.helpers.ApiGatewayResponseHelper.generateApiGatewayProxyErrorResponse)

Example 4 with ClientNotFoundException

use of uk.gov.di.authentication.shared.exceptions.ClientNotFoundException in project di-authentication-api by alphagov.

the class VerifyCodeHandler method getOtpCodeForTestClient.

private Optional<String> getOtpCodeForTestClient(UserContext userContext, NotificationType notificationType) throws ClientNotFoundException {
    LOG.warn("TestClients are ENABLED");
    final String emailAddress = userContext.getSession().getEmailAddress();
    final Optional<String> generatedOTPCode = codeStorageService.getOtpCode(emailAddress, notificationType);
    return userContext.getClient().map(clientRegistry -> {
        if (clientRegistry.isTestClient() && clientRegistry.getTestClientEmailAllowlist().contains(emailAddress)) {
            LOG.info("Using TestClient with NotificationType {}", notificationType);
            switch(notificationType) {
                case VERIFY_EMAIL:
                    return configurationService.getTestClientVerifyEmailOTP();
                case VERIFY_PHONE_NUMBER:
                    return configurationService.getTestClientVerifyPhoneNumberOTP();
                case MFA_SMS:
                    return configurationService.getTestClientVerifyPhoneNumberOTP();
                default:
                    LOG.info("Returning the generated OTP for NotificationType {}", notificationType);
                    return generatedOTPCode;
            }
        } else {
            return generatedOTPCode;
        }
    }).orElseThrow(() -> new ClientNotFoundException(userContext.getSession()));
}
Also used : ClientRegistry(uk.gov.di.authentication.shared.entity.ClientRegistry) CodeStorageService(uk.gov.di.authentication.shared.services.CodeStorageService) SessionService(uk.gov.di.authentication.shared.services.SessionService) Context(com.amazonaws.services.lambda.runtime.Context) ConfigurationService(uk.gov.di.authentication.shared.services.ConfigurationService) MFA_SMS(uk.gov.di.authentication.shared.entity.NotificationType.MFA_SMS) RequestHeaderHelper.getHeaderValueFromHeaders(uk.gov.di.authentication.shared.helpers.RequestHeaderHelper.getHeaderValueFromHeaders) RequestHandler(com.amazonaws.services.lambda.runtime.RequestHandler) AuthenticationService(uk.gov.di.authentication.shared.services.AuthenticationService) APIGatewayProxyRequestEvent(com.amazonaws.services.lambda.runtime.events.APIGatewayProxyRequestEvent) Session(uk.gov.di.authentication.shared.entity.Session) ClientService(uk.gov.di.authentication.shared.services.ClientService) ApiGatewayResponseHelper.generateEmptySuccessApiGatewayResponse(uk.gov.di.authentication.shared.helpers.ApiGatewayResponseHelper.generateEmptySuccessApiGatewayResponse) VERIFY_EMAIL(uk.gov.di.authentication.shared.entity.NotificationType.VERIFY_EMAIL) PersistentIdHelper.extractPersistentIdFromHeaders(uk.gov.di.authentication.shared.helpers.PersistentIdHelper.extractPersistentIdFromHeaders) CODE_BLOCKED_KEY_PREFIX(uk.gov.di.authentication.shared.services.CodeStorageService.CODE_BLOCKED_KEY_PREFIX) PERSISTENT_SESSION_ID(uk.gov.di.authentication.shared.helpers.LogLineHelper.LogFieldName.PERSISTENT_SESSION_ID) Map(java.util.Map) UserProfile(uk.gov.di.authentication.shared.entity.UserProfile) Map.entry(java.util.Map.entry) CLIENT_ID(uk.gov.di.authentication.shared.helpers.LogLineHelper.LogFieldName.CLIENT_ID) MetadataPair.pair(uk.gov.di.authentication.shared.services.AuditService.MetadataPair.pair) FrontendAuditableEvent(uk.gov.di.authentication.frontendapi.domain.FrontendAuditableEvent) AuditableEvent(uk.gov.di.authentication.shared.domain.AuditableEvent) VERIFY_PHONE_NUMBER(uk.gov.di.authentication.shared.entity.NotificationType.VERIFY_PHONE_NUMBER) IpAddressHelper(uk.gov.di.authentication.shared.helpers.IpAddressHelper) APIGatewayProxyResponseEvent(com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent) AuditService(uk.gov.di.authentication.shared.services.AuditService) LogLineHelper.attachLogFieldToLogs(uk.gov.di.authentication.shared.helpers.LogLineHelper.attachLogFieldToLogs) CredentialTrustLevel(uk.gov.di.authentication.shared.entity.CredentialTrustLevel) ClientNotFoundException(uk.gov.di.authentication.shared.exceptions.ClientNotFoundException) VerifyCodeRequest(uk.gov.di.authentication.frontendapi.entity.VerifyCodeRequest) VectorOfTrust(uk.gov.di.authentication.shared.entity.VectorOfTrust) ErrorResponse(uk.gov.di.authentication.shared.entity.ErrorResponse) ValidationHelper(uk.gov.di.authentication.shared.helpers.ValidationHelper) BaseFrontendHandler(uk.gov.di.authentication.shared.lambda.BaseFrontendHandler) ClientSessionService(uk.gov.di.authentication.shared.services.ClientSessionService) List(java.util.List) Logger(org.apache.logging.log4j.Logger) RequestHeaders(uk.gov.di.authentication.shared.domain.RequestHeaders) RedisConnectionService(uk.gov.di.authentication.shared.services.RedisConnectionService) LogLineHelper.attachSessionIdToLogs(uk.gov.di.authentication.shared.helpers.LogLineHelper.attachSessionIdToLogs) ApiGatewayResponseHelper.generateApiGatewayProxyErrorResponse(uk.gov.di.authentication.shared.helpers.ApiGatewayResponseHelper.generateApiGatewayProxyErrorResponse) CloudwatchMetricsService(uk.gov.di.authentication.shared.services.CloudwatchMetricsService) Optional(java.util.Optional) LogManager(org.apache.logging.log4j.LogManager) UserContext(uk.gov.di.authentication.shared.state.UserContext) NotificationType(uk.gov.di.authentication.shared.entity.NotificationType) ClientNotFoundException(uk.gov.di.authentication.shared.exceptions.ClientNotFoundException)

Example 5 with ClientNotFoundException

use of uk.gov.di.authentication.shared.exceptions.ClientNotFoundException in project di-authentication-api by alphagov.

the class MfaHandler method handleRequestWithUserContext.

@Override
public APIGatewayProxyResponseEvent handleRequestWithUserContext(APIGatewayProxyRequestEvent input, Context context, MfaRequest request, UserContext userContext) {
    try {
        String persistentSessionId = PersistentIdHelper.extractPersistentIdFromHeaders(input.getHeaders());
        attachSessionIdToLogs(userContext.getSession().getSessionId());
        attachLogFieldToLogs(PERSISTENT_SESSION_ID, persistentSessionId);
        attachLogFieldToLogs(CLIENT_ID, userContext.getClient().map(ClientRegistry::getClientID).orElse("unknown"));
        LOG.info("MfaHandler received request");
        String email = request.getEmail().toLowerCase(Locale.ROOT);
        Optional<ErrorResponse> codeRequestValid = validateCodeRequestAttempts(email, userContext);
        if (codeRequestValid.isPresent()) {
            auditService.submitAuditEvent(FrontendAuditableEvent.MFA_INVALID_CODE_REQUEST, context.getAwsRequestId(), userContext.getSession().getSessionId(), userContext.getClient().map(ClientRegistry::getClientID).orElse(AuditService.UNKNOWN), AuditService.UNKNOWN, email, IpAddressHelper.extractIpAddress(input), AuditService.UNKNOWN, persistentSessionId);
            return generateApiGatewayProxyErrorResponse(400, codeRequestValid.get());
        }
        if (!userContext.getSession().validateSession(email)) {
            LOG.warn("Email does not match Email in Request");
            auditService.submitAuditEvent(FrontendAuditableEvent.MFA_MISMATCHED_EMAIL, context.getAwsRequestId(), userContext.getSession().getSessionId(), userContext.getClient().map(ClientRegistry::getClientID).orElse(AuditService.UNKNOWN), AuditService.UNKNOWN, email, IpAddressHelper.extractIpAddress(input), AuditService.UNKNOWN, persistentSessionId);
            return generateApiGatewayProxyErrorResponse(400, ERROR_1000);
        }
        String phoneNumber = authenticationService.getPhoneNumber(email).orElse(null);
        if (phoneNumber == null) {
            auditService.submitAuditEvent(FrontendAuditableEvent.MFA_MISSING_PHONE_NUMBER, context.getAwsRequestId(), userContext.getSession().getSessionId(), userContext.getClient().map(ClientRegistry::getClientID).orElse(AuditService.UNKNOWN), AuditService.UNKNOWN, email, IpAddressHelper.extractIpAddress(input), AuditService.UNKNOWN, persistentSessionId);
            return generateApiGatewayProxyErrorResponse(400, ERROR_1014);
        }
        String code = codeGeneratorService.sixDigitCode();
        codeStorageService.saveOtpCode(email, code, configurationService.getCodeExpiry(), MFA_SMS);
        sessionService.save(userContext.getSession().incrementCodeRequestCount());
        NotifyRequest notifyRequest = new NotifyRequest(phoneNumber, MFA_SMS, code);
        AuditableEvent auditableEvent;
        if (!isTestClientAndAllowedEmail(userContext, MFA_SMS)) {
            sqsClient.send(objectMapper.writeValueAsString(notifyRequest));
            auditableEvent = FrontendAuditableEvent.MFA_CODE_SENT;
        } else {
            auditableEvent = FrontendAuditableEvent.MFA_CODE_SENT_FOR_TEST_CLIENT;
        }
        auditService.submitAuditEvent(auditableEvent, context.getAwsRequestId(), userContext.getSession().getSessionId(), userContext.getClient().map(ClientRegistry::getClientID).orElse(AuditService.UNKNOWN), AuditService.UNKNOWN, email, IpAddressHelper.extractIpAddress(input), phoneNumber, persistentSessionId);
        LOG.info("Successfully processed request");
        return generateEmptySuccessApiGatewayResponse();
    } catch (JsonException e) {
        return generateApiGatewayProxyErrorResponse(400, ERROR_1001);
    } catch (ClientNotFoundException e) {
        LOG.warn("Client not found");
        return generateApiGatewayProxyErrorResponse(400, ErrorResponse.ERROR_1015);
    }
}
Also used : JsonException(uk.gov.di.authentication.shared.serialization.Json.JsonException) ClientNotFoundException(uk.gov.di.authentication.shared.exceptions.ClientNotFoundException) ClientRegistry(uk.gov.di.authentication.shared.entity.ClientRegistry) NotifyRequest(uk.gov.di.authentication.shared.entity.NotifyRequest) ErrorResponse(uk.gov.di.authentication.shared.entity.ErrorResponse) ApiGatewayResponseHelper.generateApiGatewayProxyErrorResponse(uk.gov.di.authentication.shared.helpers.ApiGatewayResponseHelper.generateApiGatewayProxyErrorResponse) FrontendAuditableEvent(uk.gov.di.authentication.frontendapi.domain.FrontendAuditableEvent) AuditableEvent(uk.gov.di.authentication.shared.domain.AuditableEvent)

Aggregations

ClientNotFoundException (uk.gov.di.authentication.shared.exceptions.ClientNotFoundException)8 ClientRegistry (uk.gov.di.authentication.shared.entity.ClientRegistry)4 ErrorResponse (uk.gov.di.authentication.shared.entity.ErrorResponse)4 ApiGatewayResponseHelper.generateApiGatewayProxyErrorResponse (uk.gov.di.authentication.shared.helpers.ApiGatewayResponseHelper.generateApiGatewayProxyErrorResponse)4 Session (uk.gov.di.authentication.shared.entity.Session)3 VectorOfTrust (uk.gov.di.authentication.shared.entity.VectorOfTrust)3 AuthorizationCode (com.nimbusds.oauth2.sdk.AuthorizationCode)2 ParseException (com.nimbusds.oauth2.sdk.ParseException)2 AuthenticationErrorResponse (com.nimbusds.openid.connect.sdk.AuthenticationErrorResponse)2 AuthenticationRequest (com.nimbusds.openid.connect.sdk.AuthenticationRequest)2 AuthenticationSuccessResponse (com.nimbusds.openid.connect.sdk.AuthenticationSuccessResponse)2 Test (org.junit.jupiter.api.Test)2 FrontendAuditableEvent (uk.gov.di.authentication.frontendapi.domain.FrontendAuditableEvent)2 AuthCodeResponse (uk.gov.di.authentication.oidc.entity.AuthCodeResponse)2 AuditableEvent (uk.gov.di.authentication.shared.domain.AuditableEvent)2 ClientSession (uk.gov.di.authentication.shared.entity.ClientSession)2 NotifyRequest (uk.gov.di.authentication.shared.entity.NotifyRequest)2 JsonException (uk.gov.di.authentication.shared.serialization.Json.JsonException)2 Context (com.amazonaws.services.lambda.runtime.Context)1 RequestHandler (com.amazonaws.services.lambda.runtime.RequestHandler)1