use of com.nimbusds.oauth2.sdk.id.Subject in project di-authentication-api by alphagov.
the class UserInfoIntegrationTest method shouldCallUserInfoWithAccessTokenAndReturn200.
@Test
public void shouldCallUserInfoWithAccessTokenAndReturn200() throws JsonProcessingException {
Subject internalSubject = new Subject();
Subject publicSubject = new Subject();
LocalDateTime localDateTime = LocalDateTime.now().plusMinutes(10);
Date expiryDate = Date.from(localDateTime.atZone(ZoneId.of("UTC")).toInstant());
List<String> scopes = new ArrayList<>();
scopes.add("email");
scopes.add("phone");
scopes.add("openid");
JWTClaimsSet claimsSet = new JWTClaimsSet.Builder().claim("scope", scopes).issuer("issuer-id").expirationTime(expiryDate).issueTime(Date.from(LocalDateTime.now().atZone(ZoneId.of("UTC")).toInstant())).claim("client_id", "client-id-one").subject(publicSubject.getValue()).jwtID(UUID.randomUUID().toString()).build();
SignedJWT signedJWT = tokenSigner.signJwt(claimsSet);
AccessToken accessToken = new BearerAccessToken(signedJWT.serialize());
AccessTokenStore accessTokenStore = new AccessTokenStore(accessToken.getValue(), internalSubject.getValue());
String accessTokenStoreString = new ObjectMapper().writeValueAsString(accessTokenStore);
redis.addToRedis(ACCESS_TOKEN_PREFIX + CLIENT_ID + "." + publicSubject, accessTokenStoreString, 300L);
setUpDynamo(internalSubject);
var response = makeRequest(Optional.empty(), Map.of("Authorization", accessToken.toAuthorizationHeader()), Map.of());
assertThat(response, hasStatus(200));
UserInfo expectedUserInfoResponse = new UserInfo(publicSubject);
expectedUserInfoResponse.setEmailAddress(TEST_EMAIL_ADDRESS);
expectedUserInfoResponse.setEmailVerified(true);
expectedUserInfoResponse.setPhoneNumber(FORMATTED_PHONE_NUMBER);
expectedUserInfoResponse.setPhoneNumberVerified(true);
assertThat(response.getBody(), equalTo(expectedUserInfoResponse.toJSONString()));
assertNoAuditEventsReceived(auditTopic);
}
use of com.nimbusds.oauth2.sdk.id.Subject in project di-authentication-api by alphagov.
the class ResetPasswordRequestHandlerTest method shouldReturn200AndPutMessageOnQueueForAValidRequest.
@Test
void shouldReturn200AndPutMessageOnQueueForAValidRequest() throws JsonProcessingException {
String persistentId = "some-persistent-id-value";
Map<String, String> headers = new HashMap<>();
headers.put(PersistentIdHelper.PERSISTENT_ID_HEADER_NAME, persistentId);
headers.put("Session-Id", session.getSessionId());
Subject subject = new Subject("subject_1");
when(validationService.validateEmailAddress(eq(TEST_EMAIL_ADDRESS))).thenReturn(Optional.empty());
when(authenticationService.getSubjectFromEmail(TEST_EMAIL_ADDRESS)).thenReturn(subject);
when(resetPasswordService.buildResetPasswordLink(TEST_SIX_DIGIT_CODE, session.getSessionId(), persistentId)).thenReturn(TEST_RESET_PASSWORD_LINK);
NotifyRequest notifyRequest = new NotifyRequest(TEST_EMAIL_ADDRESS, RESET_PASSWORD, TEST_RESET_PASSWORD_LINK);
ObjectMapper objectMapper = new ObjectMapper();
String serialisedRequest = objectMapper.writeValueAsString(notifyRequest);
usingValidSession();
APIGatewayProxyRequestEvent event = new APIGatewayProxyRequestEvent();
event.setRequestContext(contextWithSourceIp("123.123.123.123"));
event.setHeaders(headers);
event.setBody(format("{ \"email\": \"%s\" }", TEST_EMAIL_ADDRESS));
APIGatewayProxyResponseEvent result = handler.handleRequest(event, context);
assertEquals(204, result.getStatusCode());
verify(awsSqsClient).send(serialisedRequest);
verify(codeStorageService).savePasswordResetCode(subject.getValue(), TEST_SIX_DIGIT_CODE, CODE_EXPIRY_TIME, RESET_PASSWORD);
verify(sessionService).save(argThat(this::isSessionWithEmailSent));
verify(auditService).submitAuditEvent(FrontendAuditableEvent.PASSWORD_RESET_REQUESTED, context.getAwsRequestId(), session.getSessionId(), AuditService.UNKNOWN, AuditService.UNKNOWN, TEST_EMAIL_ADDRESS, "123.123.123.123", AuditService.UNKNOWN, persistentId);
}
use of com.nimbusds.oauth2.sdk.id.Subject in project di-authentication-api by alphagov.
the class TokenService method generateIDToken.
private SignedJWT generateIDToken(String clientId, Subject publicSubject, Map<String, Object> additionalTokenClaims, AccessTokenHash accessTokenHash, String vot) {
attachLogFieldToLogs(CLIENT_ID, clientId);
LOG.info("Generating IdToken");
URI trustMarkUri = buildURI(configService.getBaseURL().get(), "/trustmark");
LocalDateTime localDateTime = LocalDateTime.now().plusSeconds(configService.getIDTokenExpiry());
Date expiryDate = Date.from(localDateTime.atZone(ZoneId.of("UTC")).toInstant());
IDTokenClaimsSet idTokenClaims = new IDTokenClaimsSet(new Issuer(configService.getBaseURL().get()), publicSubject, List.of(new Audience(clientId)), expiryDate, new Date());
idTokenClaims.setAccessTokenHash(accessTokenHash);
idTokenClaims.putAll(additionalTokenClaims);
idTokenClaims.setClaim("vot", vot);
idTokenClaims.setClaim("vtm", trustMarkUri.toString());
try {
return generateSignedJWT(idTokenClaims.toJWTClaimsSet());
} catch (com.nimbusds.oauth2.sdk.ParseException e) {
LOG.error("Error when trying to parse IDTokenClaims to JWTClaimSet", e);
throw new RuntimeException(e);
}
}
use of com.nimbusds.oauth2.sdk.id.Subject in project di-authentication-api by alphagov.
the class UpdateEmailHandler 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("UpdateEmailHandler received request");
try {
UpdateEmailRequest updateInfoRequest = objectMapper.readValue(input.getBody(), UpdateEmailRequest.class);
boolean isValidOtpCode = codeStorageService.isValidOtpCode(updateInfoRequest.getReplacementEmailAddress(), updateInfoRequest.getOtp(), NotificationType.VERIFY_EMAIL);
if (!isValidOtpCode) {
return generateApiGatewayProxyErrorResponse(400, ErrorResponse.ERROR_1020);
}
Optional<ErrorResponse> emailValidationErrors = validationService.validateEmailAddressUpdate(updateInfoRequest.getExistingEmailAddress(), updateInfoRequest.getReplacementEmailAddress());
if (emailValidationErrors.isPresent()) {
return generateApiGatewayProxyErrorResponse(400, emailValidationErrors.get());
}
if (dynamoService.userExists(updateInfoRequest.getReplacementEmailAddress())) {
return generateApiGatewayProxyErrorResponse(400, ErrorResponse.ERROR_1009);
}
UserProfile userProfile = dynamoService.getUserProfileByEmail(updateInfoRequest.getExistingEmailAddress());
Map<String, Object> authorizerParams = input.getRequestContext().getAuthorizer();
RequestBodyHelper.validatePrincipal(new Subject(userProfile.getPublicSubjectID()), authorizerParams);
dynamoService.updateEmail(updateInfoRequest.getExistingEmailAddress(), updateInfoRequest.getReplacementEmailAddress());
LOG.info("Email has successfully been updated. Adding message to SQS queue");
NotifyRequest notifyRequest = new NotifyRequest(updateInfoRequest.getReplacementEmailAddress(), NotificationType.EMAIL_UPDATED);
sqsClient.send(objectMapper.writeValueAsString((notifyRequest)));
auditService.submitAuditEvent(AccountManagementAuditableEvent.UPDATE_EMAIL, context.getAwsRequestId(), sessionId, AuditService.UNKNOWN, userProfile.getSubjectID(), updateInfoRequest.getReplacementEmailAddress(), IpAddressHelper.extractIpAddress(input), userProfile.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 AuthoriseAccessTokenHandler method handleRequest.
@Override
public AuthPolicy handleRequest(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();
LocalDateTime localDateTime = LocalDateTime.now();
Date currentDateTime = Date.from(localDateTime.atZone(ZoneId.of("UTC")).toInstant());
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");
}
}
}
Aggregations