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);
}
});
}
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);
}
});
}
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());
}
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);
}
});
}
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;
}
Aggregations