use of com.nimbusds.oauth2.sdk.id.Subject in project di-authentication-api by alphagov.
the class TokenHandler method handleRequest.
@Override
public APIGatewayProxyResponseEvent handleRequest(APIGatewayProxyRequestEvent input, Context context) {
return isWarming(input).orElseGet(() -> {
LOG.info("Token request received");
Optional<ErrorObject> invalidRequestParamError = tokenService.validateTokenRequestParams(input.getBody());
if (invalidRequestParamError.isPresent()) {
LOG.warn("Invalid Token Request. ErrorCode: {}. ErrorDescription: {}", invalidRequestParamError.get().getCode(), invalidRequestParamError.get().getDescription());
return generateApiGatewayProxyResponse(400, invalidRequestParamError.get().toJSONObject().toJSONString());
}
Map<String, String> requestBody = parseRequestBody(input.getBody());
String clientID = requestBody.get("client_id");
ClientRegistry client;
try {
client = clientService.getClient(clientID).orElseThrow();
} catch (NoSuchElementException e) {
LOG.warn("Client not found in Client Registry with Client ID {}", clientID);
return generateApiGatewayProxyResponse(400, OAuth2Error.INVALID_CLIENT.toJSONObject().toJSONString());
}
String baseUrl = configurationService.getBaseURL().orElseThrow(() -> {
LOG.error("Application was not configured with baseURL");
// exceptions
return new RuntimeException("Application was not configured with baseURL");
});
String tokenUrl = buildURI(baseUrl, TOKEN_PATH).toString();
Optional<ErrorObject> invalidPrivateKeyJwtError = tokenService.validatePrivateKeyJWT(input.getBody(), client.getPublicKey(), tokenUrl, clientID);
if (invalidPrivateKeyJwtError.isPresent()) {
LOG.warn("Private Key JWT is not valid for Client ID: {}", clientID);
return generateApiGatewayProxyResponse(400, invalidPrivateKeyJwtError.get().toJSONObject().toJSONString());
}
if (requestBody.get("grant_type").equals(GrantType.REFRESH_TOKEN.getValue())) {
LOG.info("Processing refresh token request");
return processRefreshTokenRequest(requestBody, client.getScopes(), new RefreshToken(requestBody.get("refresh_token")));
}
AuthCodeExchangeData authCodeExchangeData;
try {
authCodeExchangeData = authorisationCodeService.getExchangeDataForCode(requestBody.get("code")).orElseThrow();
} catch (NoSuchElementException e) {
LOG.warn("Could not retrieve client session ID from code", e);
return generateApiGatewayProxyResponse(400, OAuth2Error.INVALID_GRANT.toJSONObject().toJSONString());
}
ClientSession clientSession = clientSessionService.getClientSession(authCodeExchangeData.getClientSessionId());
AuthenticationRequest authRequest;
try {
authRequest = AuthenticationRequest.parse(clientSession.getAuthRequestParams());
} catch (ParseException e) {
LOG.warn("Could not parse authentication request from client session", e);
throw new RuntimeException(format("Unable to parse Auth Request\n Auth Request Params: %s \n Exception: %s", clientSession.getAuthRequestParams(), e));
}
if (!authRequest.getRedirectionURI().toString().equals(requestBody.get("redirect_uri"))) {
LOG.warn("Redirect URI for auth request ({}) does not match redirect URI for request body ({})", authRequest.getRedirectionURI(), requestBody.get("redirect_uri"));
return generateApiGatewayProxyResponse(400, OAuth2Error.INVALID_GRANT.toJSONObject().toJSONString());
}
UserProfile userProfile = dynamoService.getUserProfileByEmail(authCodeExchangeData.getEmail());
Subject publicSubject = ClientSubjectHelper.getSubject(userProfile, client, dynamoService);
Map<String, Object> additionalTokenClaims = new HashMap<>();
if (authRequest.getNonce() != null) {
additionalTokenClaims.put("nonce", authRequest.getNonce());
}
String vot = clientSession.getEffectiveVectorOfTrust().retrieveVectorOfTrustForToken();
OIDCClaimsRequest claimsRequest = null;
if (Objects.nonNull(clientSession.getEffectiveVectorOfTrust().getLevelOfConfidence()) && Objects.nonNull(authRequest.getOIDCClaims())) {
claimsRequest = authRequest.getOIDCClaims();
}
var tokenResponse = tokenService.generateTokenResponse(clientID, new Subject(userProfile.getSubjectID()), authRequest.getScope(), additionalTokenClaims, publicSubject, vot, userProfile.getClientConsent(), client.isConsentRequired(), claimsRequest);
clientSessionService.saveClientSession(authCodeExchangeData.getClientSessionId(), clientSession.setIdTokenHint(tokenResponse.getOIDCTokens().getIDToken().serialize()));
LOG.info("Successfully generated tokens");
return generateApiGatewayProxyResponse(200, tokenResponse.toJSONObject().toJSONString());
});
}
use of com.nimbusds.oauth2.sdk.id.Subject in project di-authentication-api by alphagov.
the class UpdatePhoneNumberHandler method handleRequest.
@Override
public APIGatewayProxyResponseEvent handleRequest(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);
}
Optional<ErrorResponse> phoneValidationErrors = validationService.validatePhoneNumber(updatePhoneNumberRequest.getPhoneNumber());
if (phoneValidationErrors.isPresent()) {
return generateApiGatewayProxyErrorResponse(400, phoneValidationErrors.get());
}
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 (JsonProcessingException | IllegalArgumentException e) {
return generateApiGatewayProxyErrorResponse(400, ErrorResponse.ERROR_1001);
}
});
}
use of com.nimbusds.oauth2.sdk.id.Subject in project di-authentication-api by alphagov.
the class UpdatePasswordHandler method handleRequest.
@Override
public APIGatewayProxyResponseEvent handleRequest(APIGatewayProxyRequestEvent input, Context context) {
return isWarming(input).orElseGet(() -> {
String sessionId = RequestHeaderHelper.getHeaderValueOrElse(input.getHeaders(), SESSION_ID_HEADER, "");
attachSessionIdToLogs(sessionId);
LOG.info("UpdatePasswordHandler received request");
context.getClientContext();
try {
UpdatePasswordRequest updatePasswordRequest = objectMapper.readValue(input.getBody(), UpdatePasswordRequest.class);
UserProfile userProfile = dynamoService.getUserProfileByEmail(updatePasswordRequest.getEmail());
Map<String, Object> authorizerParams = input.getRequestContext().getAuthorizer();
RequestBodyHelper.validatePrincipal(new Subject(userProfile.getPublicSubjectID()), authorizerParams);
String currentPassword = dynamoService.getUserCredentialsFromEmail(updatePasswordRequest.getEmail()).getPassword();
if (verifyPassword(currentPassword, updatePasswordRequest.getNewPassword())) {
return generateApiGatewayProxyErrorResponse(400, ErrorResponse.ERROR_1024);
}
dynamoService.updatePassword(updatePasswordRequest.getEmail(), updatePasswordRequest.getNewPassword());
LOG.info("User Password has successfully been updated. Adding confirmation message to SQS queue");
NotifyRequest notifyRequest = new NotifyRequest(updatePasswordRequest.getEmail(), NotificationType.PASSWORD_UPDATED);
sqsClient.send(objectMapper.writeValueAsString((notifyRequest)));
LOG.info("Message successfully added to queue. Generating successful gateway response");
auditService.submitAuditEvent(AccountManagementAuditableEvent.UPDATE_PASSWORD, context.getAwsRequestId(), sessionId, AuditService.UNKNOWN, userProfile.getSubjectID(), userProfile.getEmail(), IpAddressHelper.extractIpAddress(input), userProfile.getPhoneNumber(), PersistentIdHelper.extractPersistentIdFromHeaders(input.getHeaders()));
return generateEmptySuccessApiGatewayResponse();
} catch (JsonProcessingException | IllegalArgumentException e) {
return generateApiGatewayProxyErrorResponse(400, ErrorResponse.ERROR_1001);
}
});
}
use of com.nimbusds.oauth2.sdk.id.Subject in project di-authentication-api by alphagov.
the class RemoveAccountHandler method handleRequest.
@Override
public APIGatewayProxyResponseEvent handleRequest(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 (JsonProcessingException e) {
return generateApiGatewayProxyErrorResponse(400, ErrorResponse.ERROR_1001);
}
});
}
use of com.nimbusds.oauth2.sdk.id.Subject in project di-authentication-api by alphagov.
the class UserInfoServiceTest method createSignedAccessToken.
private AccessToken createSignedAccessToken(OIDCClaimsRequest identityClaims) throws JOSEException {
var expiryDate = NowHelper.nowPlus(3, ChronoUnit.MINUTES);
var ecSigningKey = new ECKeyGenerator(Curve.P_256).keyID(KEY_ID).algorithm(JWSAlgorithm.ES256).generate();
var signer = new ECDSASigner(ecSigningKey);
var signedJWT = TokenGeneratorHelper.generateSignedToken(CLIENT_ID, BASE_URL, SCOPES, signer, SUBJECT, ecSigningKey.getKeyID(), expiryDate, identityClaims);
return new BearerAccessToken(signedJWT.serialize());
}
Aggregations