Search in sources :

Example 11 with JsonException

use of uk.gov.di.authentication.shared.serialization.Json.JsonException in project di-authentication-api by alphagov.

the class SendOtpNotificationHandler method sendOtpRequestHandler.

public APIGatewayProxyResponseEvent sendOtpRequestHandler(APIGatewayProxyRequestEvent input, Context context) {
    return isWarming(input).orElseGet(() -> {
        String sessionId = RequestHeaderHelper.getHeaderValueOrElse(input.getHeaders(), SESSION_ID_HEADER, "");
        attachSessionIdToLogs(sessionId);
        LOG.info("Request received in SendOtp Lambda");
        try {
            SendNotificationRequest sendNotificationRequest = objectMapper.readValue(input.getBody(), SendNotificationRequest.class);
            switch(sendNotificationRequest.getNotificationType()) {
                case VERIFY_EMAIL:
                    LOG.info("NotificationType is VERIFY_EMAIL");
                    Optional<ErrorResponse> emailErrorResponse = ValidationHelper.validateEmailAddress(sendNotificationRequest.getEmail());
                    if (emailErrorResponse.isPresent()) {
                        return generateApiGatewayProxyErrorResponse(400, emailErrorResponse.get());
                    }
                    if (dynamoService.userExists(sendNotificationRequest.getEmail())) {
                        return generateApiGatewayProxyErrorResponse(400, ErrorResponse.ERROR_1009);
                    }
                    return handleNotificationRequest(sendNotificationRequest.getEmail(), sendNotificationRequest, input, context);
                case VERIFY_PHONE_NUMBER:
                    LOG.info("NotificationType is VERIFY_PHONE_NUMBER");
                    Optional<ErrorResponse> phoneNumberValidationError = ValidationHelper.validatePhoneNumber(sendNotificationRequest.getPhoneNumber());
                    if (phoneNumberValidationError.isPresent()) {
                        return generateApiGatewayProxyErrorResponse(400, phoneNumberValidationError.get());
                    }
                    return handleNotificationRequest(sendNotificationRequest.getPhoneNumber(), sendNotificationRequest, input, context);
            }
            return generateApiGatewayProxyErrorResponse(400, ERROR_1002);
        } catch (SdkClientException ex) {
            LOG.error("Error sending message to queue", ex);
            return generateApiGatewayProxyResponse(500, "Error sending message to queue");
        } catch (JsonException e) {
            return generateApiGatewayProxyErrorResponse(400, ERROR_1001);
        }
    });
}
Also used : JsonException(uk.gov.di.authentication.shared.serialization.Json.JsonException) SdkClientException(software.amazon.awssdk.core.exception.SdkClientException) SendNotificationRequest(uk.gov.di.accountmanagement.entity.SendNotificationRequest) ErrorResponse(uk.gov.di.authentication.shared.entity.ErrorResponse) ApiGatewayResponseHelper.generateApiGatewayProxyErrorResponse(uk.gov.di.authentication.shared.helpers.ApiGatewayResponseHelper.generateApiGatewayProxyErrorResponse)

Example 12 with JsonException

use of uk.gov.di.authentication.shared.serialization.Json.JsonException 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 13 with JsonException

use of uk.gov.di.authentication.shared.serialization.Json.JsonException in project di-authentication-api by alphagov.

the class TokenHandler method processRefreshTokenRequest.

private APIGatewayProxyResponseEvent processRefreshTokenRequest(Map<String, String> requestBody, List<String> clientScopes, RefreshToken currentRefreshToken, String clientId) {
    boolean refreshTokenSignatureValid = tokenValidationService.validateRefreshTokenSignatureAndExpiry(currentRefreshToken);
    if (!refreshTokenSignatureValid) {
        return generateApiGatewayProxyResponse(400, OAuth2Error.INVALID_GRANT.toJSONObject().toJSONString());
    }
    Subject subject;
    List<String> scopes;
    String jti;
    try {
        SignedJWT signedJwt = SignedJWT.parse(currentRefreshToken.getValue());
        subject = new Subject(signedJwt.getJWTClaimsSet().getSubject());
        scopes = (List<String>) signedJwt.getJWTClaimsSet().getClaim("scope");
        jti = signedJwt.getJWTClaimsSet().getJWTID();
    } catch (java.text.ParseException e) {
        LOG.warn("Unable to parse RefreshToken");
        return generateApiGatewayProxyResponse(400, new ErrorObject(OAuth2Error.INVALID_GRANT_CODE, "Invalid Refresh token").toJSONObject().toJSONString());
    }
    boolean areScopesValid = tokenValidationService.validateRefreshTokenScopes(clientScopes, scopes);
    if (!areScopesValid) {
        return generateApiGatewayProxyResponse(400, OAuth2Error.INVALID_SCOPE.toJSONObject().toJSONString());
    }
    String redisKey = REFRESH_TOKEN_PREFIX + jti;
    Optional<String> refreshToken = Optional.ofNullable(redisConnectionService.popValue(redisKey));
    RefreshTokenStore tokenStore;
    try {
        tokenStore = objectMapper.readValue(refreshToken.get(), RefreshTokenStore.class);
    } catch (JsonException | NoSuchElementException | IllegalArgumentException e) {
        LOG.warn("Refresh token not found with given key");
        return generateApiGatewayProxyResponse(400, new ErrorObject(OAuth2Error.INVALID_GRANT_CODE, "Invalid Refresh token").toJSONObject().toJSONString());
    }
    if (!tokenStore.getRefreshToken().equals(currentRefreshToken.getValue())) {
        LOG.warn("Refresh token store does not contain Refresh token in request");
        return generateApiGatewayProxyResponse(400, new ErrorObject(OAuth2Error.INVALID_GRANT_CODE, "Invalid Refresh token").toJSONObject().toJSONString());
    }
    OIDCTokenResponse tokenResponse = tokenService.generateRefreshTokenResponse(clientId, new Subject(tokenStore.getInternalSubjectId()), scopes, subject);
    LOG.info("Generating successful RefreshToken response");
    return generateApiGatewayProxyResponse(200, tokenResponse.toJSONObject().toJSONString());
}
Also used : JsonException(uk.gov.di.authentication.shared.serialization.Json.JsonException) RefreshTokenStore(uk.gov.di.authentication.shared.entity.RefreshTokenStore) ErrorObject(com.nimbusds.oauth2.sdk.ErrorObject) OIDCTokenResponse(com.nimbusds.openid.connect.sdk.OIDCTokenResponse) SignedJWT(com.nimbusds.jwt.SignedJWT) Subject(com.nimbusds.oauth2.sdk.id.Subject) Context(com.amazonaws.services.lambda.runtime.Context) NoSuchElementException(java.util.NoSuchElementException)

Example 14 with JsonException

use of uk.gov.di.authentication.shared.serialization.Json.JsonException in project di-authentication-api by alphagov.

the class IPVCallbackHandler method handleRequest.

@Override
public APIGatewayProxyResponseEvent handleRequest(APIGatewayProxyRequestEvent input, Context context) {
    return isWarming(input).orElseGet(() -> {
        LOG.info("Request received to IPVCallbackHandler");
        if (!configurationService.isIdentityEnabled()) {
            LOG.error("Identity is not enabled");
            throw new RuntimeException("Identity is not enabled");
        }
        try {
            var sessionCookiesIds = CookieHelper.parseSessionCookie(input.getHeaders()).orElseThrow();
            var session = sessionService.readSessionFromRedis(sessionCookiesIds.getSessionId()).orElseThrow();
            attachSessionIdToLogs(session);
            var persistentId = PersistentIdHelper.extractPersistentIdFromCookieHeader(input.getHeaders());
            attachLogFieldToLogs(PERSISTENT_SESSION_ID, persistentId);
            var clientSession = clientSessionService.getClientSession(sessionCookiesIds.getClientSessionId()).orElse(null);
            if (Objects.isNull(clientSession)) {
                LOG.error("ClientSession not found");
                throw new RuntimeException();
            }
            attachLogFieldToLogs(CLIENT_SESSION_ID, sessionCookiesIds.getClientSessionId());
            var authRequest = AuthenticationRequest.parse(clientSession.getAuthRequestParams());
            var clientId = authRequest.getClientID().getValue();
            var clientRegistry = dynamoClientService.getClient(clientId).orElse(null);
            if (Objects.isNull(clientRegistry)) {
                LOG.error("Client registry not found with given clientId");
                throw new RuntimeException("Client registry not found with given clientId");
            }
            var errorObject = ipvAuthorisationService.validateResponse(input.getQueryStringParameters(), session.getSessionId());
            if (errorObject.isPresent()) {
                LOG.error("Error in IPV AuthorisationResponse. ErrorCode: {}. ErrorDescription: {}", errorObject.get().getCode(), errorObject.get().getDescription());
                var errorResponse = new AuthenticationErrorResponse(authRequest.getRedirectionURI(), new ErrorObject(ACCESS_DENIED_CODE, errorObject.get().getDescription()), authRequest.getState(), authRequest.getResponseMode());
                return new APIGatewayProxyResponseEvent().withStatusCode(302).withHeaders(Map.of(ResponseHeaders.LOCATION, errorResponse.toURI().toString()));
            }
            var userProfile = dynamoService.getUserProfileFromEmail(session.getEmailAddress()).orElse(null);
            if (Objects.isNull(userProfile)) {
                LOG.error("Email from session does not have a user profile");
                throw new RuntimeException("Email from session does not have a user profile");
            }
            auditService.submitAuditEvent(IPVAuditableEvent.IPV_AUTHORISATION_RESPONSE_RECEIVED, context.getAwsRequestId(), session.getSessionId(), clientId, userProfile.getSubjectID(), userProfile.getEmail(), AuditService.UNKNOWN, userProfile.getPhoneNumber(), persistentId);
            var tokenRequest = ipvTokenService.constructTokenRequest(input.getQueryStringParameters().get("code"));
            var tokenResponse = ipvTokenService.sendTokenRequest(tokenRequest);
            if (tokenResponse.indicatesSuccess()) {
                auditService.submitAuditEvent(IPVAuditableEvent.IPV_SUCCESSFUL_TOKEN_RESPONSE_RECEIVED, context.getAwsRequestId(), session.getSessionId(), clientId, userProfile.getSubjectID(), userProfile.getEmail(), AuditService.UNKNOWN, userProfile.getPhoneNumber(), persistentId);
            } else {
                LOG.error("IPV TokenResponse was not successful: {}", tokenResponse.toErrorResponse().toJSONObject());
                auditService.submitAuditEvent(IPVAuditableEvent.IPV_UNSUCCESSFUL_TOKEN_RESPONSE_RECEIVED, context.getAwsRequestId(), session.getSessionId(), clientId, userProfile.getSubjectID(), userProfile.getEmail(), AuditService.UNKNOWN, userProfile.getPhoneNumber(), persistentId);
                throw new RuntimeException("IPV TokenResponse was not successful");
            }
            var pairwiseSubject = ClientSubjectHelper.getSubject(userProfile, clientRegistry, dynamoService);
            var userIdentityUserInfo = ipvTokenService.sendIpvUserIdentityRequest(new UserInfoRequest(ConstructUriHelper.buildURI(configurationService.getIPVBackendURI().toString(), "user-identity"), tokenResponse.toSuccessResponse().getTokens().getBearerAccessToken()));
            if (Objects.isNull(userIdentityUserInfo)) {
                LOG.error("IPV UserIdentityRequest failed.");
                throw new RuntimeException("IPV UserIdentityRequest failed.");
            } else {
                LOG.info("IPV UserIdentityRequest succeeded: {}", userIdentityUserInfo.toJSONObject().toJSONString());
            }
            auditService.submitAuditEvent(IPVAuditableEvent.IPV_SUCCESSFUL_IDENTITY_RESPONSE_RECEIVED, context.getAwsRequestId(), session.getSessionId(), clientId, userProfile.getSubjectID(), userProfile.getEmail(), AuditService.UNKNOWN, userProfile.getPhoneNumber(), persistentId);
            if (configurationService.isSpotEnabled()) {
                Optional<ErrorObject> userIdentityError = validateUserIdentityResponse(userIdentityUserInfo);
                if (userIdentityError.isEmpty()) {
                    LOG.info("SPOT will be invoked.");
                    var logIds = new LogIds(session.getSessionId(), persistentId, context.getAwsRequestId(), clientId);
                    queueSPOTRequest(logIds, getSectorIdentifierForClient(clientRegistry), userProfile, pairwiseSubject, userIdentityUserInfo);
                    auditService.submitAuditEvent(IPVAuditableEvent.IPV_SPOT_REQUESTED, context.getAwsRequestId(), session.getSessionId(), clientId, userProfile.getSubjectID(), userProfile.getEmail(), AuditService.UNKNOWN, userProfile.getPhoneNumber(), persistentId);
                } else {
                    LOG.warn("SPOT will not be invoked. Returning Error to RP");
                    var errorResponse = new AuthenticationErrorResponse(authRequest.getRedirectionURI(), userIdentityError.get(), authRequest.getState(), authRequest.getResponseMode());
                    return new APIGatewayProxyResponseEvent().withStatusCode(302).withHeaders(Map.of(ResponseHeaders.LOCATION, errorResponse.toURI().toString()));
                }
            }
            saveAdditionalClaimsToDynamo(pairwiseSubject, userIdentityUserInfo);
            var redirectURI = ConstructUriHelper.buildURI(configurationService.getLoginURI().toString(), REDIRECT_PATH);
            return new APIGatewayProxyResponseEvent().withStatusCode(302).withHeaders(Map.of(ResponseHeaders.LOCATION, redirectURI.toString()));
        } catch (NoSuchElementException e) {
            LOG.error("Session not found", e);
            throw new RuntimeException("Session not found", e);
        } catch (ParseException e) {
            LOG.info("Cannot retrieve auth request params from client session id");
            throw new RuntimeException();
        } catch (JsonException e) {
            LOG.error("Unable to serialize SPOTRequest when placing on queue");
            throw new RuntimeException(e);
        }
    });
}
Also used : JsonException(uk.gov.di.authentication.shared.serialization.Json.JsonException) AuthenticationErrorResponse(com.nimbusds.openid.connect.sdk.AuthenticationErrorResponse) ErrorObject(com.nimbusds.oauth2.sdk.ErrorObject) LogIds(uk.gov.di.authentication.ipv.entity.LogIds) UserInfoRequest(com.nimbusds.openid.connect.sdk.UserInfoRequest) ParseException(com.nimbusds.oauth2.sdk.ParseException) APIGatewayProxyResponseEvent(com.amazonaws.services.lambda.runtime.events.APIGatewayProxyResponseEvent) NoSuchElementException(java.util.NoSuchElementException)

Example 15 with JsonException

use of uk.gov.di.authentication.shared.serialization.Json.JsonException in project di-authentication-api by alphagov.

the class SPOTResponseHandler method handleRequest.

@Override
public Object handleRequest(SQSEvent event, Context context) {
    auditService.submitAuditEvent(IPVAuditableEvent.SPOT_RESPONSE_RECEIVED, context.getAwsRequestId(), AuditService.UNKNOWN, AuditService.UNKNOWN, AuditService.UNKNOWN, AuditService.UNKNOWN, AuditService.UNKNOWN, AuditService.UNKNOWN, AuditService.UNKNOWN);
    for (SQSMessage msg : event.getRecords()) {
        try {
            var spotResponse = objectMapper.readValue(msg.getBody(), SPOTResponse.class);
            if (spotResponse.getStatus() != SPOTStatus.ACCEPTED) {
                LOG.warn("SPOTResponse Status is not Accepted. Deleting Identity Credential. Actual Status: {}", spotResponse.getStatus());
                dynamoIdentityService.deleteIdentityCredentials(spotResponse.getSub());
                return null;
            }
            LOG.info("SPOTResponse Status is Accepted. Adding CoreIdentityJWT to Dynamo");
            dynamoIdentityService.addCoreIdentityJWT(spotResponse.getSub(), spotResponse.getClaims().values().stream().map(Object::toString).findFirst().orElseThrow());
        } catch (JsonException e) {
            LOG.error("Unable to deserialize SPOT response from SQS queue");
            return null;
        } catch (NoSuchElementException e) {
            LOG.error("Status is OK but no credential is present in SPOTResponse");
            return null;
        }
    }
    return null;
}
Also used : JsonException(uk.gov.di.authentication.shared.serialization.Json.JsonException) SQSMessage(com.amazonaws.services.lambda.runtime.events.SQSEvent.SQSMessage) NoSuchElementException(java.util.NoSuchElementException)

Aggregations

JsonException (uk.gov.di.authentication.shared.serialization.Json.JsonException)25 ClientRegistry (uk.gov.di.authentication.shared.entity.ClientRegistry)7 ErrorResponse (uk.gov.di.authentication.shared.entity.ErrorResponse)7 ApiGatewayResponseHelper.generateApiGatewayProxyErrorResponse (uk.gov.di.authentication.shared.helpers.ApiGatewayResponseHelper.generateApiGatewayProxyErrorResponse)7 Subject (com.nimbusds.oauth2.sdk.id.Subject)6 NotifyRequest (uk.gov.di.accountmanagement.entity.NotifyRequest)5 UserProfile (uk.gov.di.authentication.shared.entity.UserProfile)5 State (com.nimbusds.oauth2.sdk.id.State)4 NotifyRequest (uk.gov.di.authentication.shared.entity.NotifyRequest)4 SQSMessage (com.amazonaws.services.lambda.runtime.events.SQSEvent.SQSMessage)3 SignedJWT (com.nimbusds.jwt.SignedJWT)3 ErrorObject (com.nimbusds.oauth2.sdk.ErrorObject)3 NoSuchElementException (java.util.NoSuchElementException)3 JWTClaimsSet (com.nimbusds.jwt.JWTClaimsSet)2 ParseException (com.nimbusds.oauth2.sdk.ParseException)2 ResponseType (com.nimbusds.oauth2.sdk.ResponseType)2 ClientID (com.nimbusds.oauth2.sdk.id.ClientID)2 Date (java.util.Date)2 HashMap (java.util.HashMap)2 SdkClientException (software.amazon.awssdk.core.exception.SdkClientException)2