use of com.nimbusds.oauth2.sdk.id.JWTID in project di-authentication-api by alphagov.
the class TokenService method generateAndStoreAccessToken.
private AccessToken generateAndStoreAccessToken(String clientId, Subject internalSubject, List<String> scopes, Subject subject, OIDCClaimsRequest claimsRequest) {
LOG.info("Generating AccessToken");
Date expiryDate = NowHelper.nowPlus(configService.getAccessTokenExpiry(), ChronoUnit.SECONDS);
var jwtID = UUID.randomUUID().toString();
LOG.info("AccessToken being created with JWTID: {}", jwtID);
JWTClaimsSet.Builder claimSetBuilder = new JWTClaimsSet.Builder().claim("scope", scopes).issuer(configService.getOidcApiBaseURL().get()).expirationTime(expiryDate).issueTime(NowHelper.now()).claim("client_id", clientId).subject(subject.getValue()).jwtID(jwtID);
if (Objects.nonNull(claimsRequest)) {
claimSetBuilder.claim("claims", claimsRequest.getUserInfoClaimsRequest().getEntries().stream().map(ClaimsSetRequest.Entry::getClaimName).collect(Collectors.toList()));
}
SignedJWT signedJWT = generateSignedJWT(claimSetBuilder.build(), Optional.empty());
AccessToken accessToken = new BearerAccessToken(signedJWT.serialize());
try {
redisConnectionService.saveWithExpiry(ACCESS_TOKEN_PREFIX + clientId + "." + subject.getValue(), objectMapper.writeValueAsString(new AccessTokenStore(accessToken.getValue(), internalSubject.getValue())), configService.getAccessTokenExpiry());
} catch (JsonException e) {
LOG.error("Unable to save access token to Redis");
throw new RuntimeException(e);
}
return accessToken;
}
use of com.nimbusds.oauth2.sdk.id.JWTID in project di-authentication-api by alphagov.
the class AccessTokenService method parse.
public AccessTokenInfo parse(String authorizationHeader, boolean identityEnabled) throws AccessTokenException {
AccessToken accessToken;
try {
accessToken = AccessToken.parse(authorizationHeader, AccessTokenType.BEARER);
} catch (com.nimbusds.oauth2.sdk.ParseException e) {
LOG.warn("Unable to parse AccessToken");
throw new AccessTokenException("Unable to parse AccessToken", BearerTokenError.INVALID_TOKEN);
}
SignedJWT signedJWT;
try {
signedJWT = SignedJWT.parse(accessToken.getValue());
var currentDateTime = NowHelper.now();
if (DateUtils.isBefore(signedJWT.getJWTClaimsSet().getExpirationTime(), currentDateTime, 0)) {
LOG.warn("Access Token has expired. Access Token expires at: {}. CurrentDateTime is: {}", signedJWT.getJWTClaimsSet().getExpirationTime(), currentDateTime);
throw new AccessTokenException(INVALID_ACCESS_TOKEN, BearerTokenError.INVALID_TOKEN);
}
if (!tokenValidationService.validateAccessTokenSignature(accessToken)) {
LOG.warn("Unable to validate AccessToken signature");
throw new AccessTokenException("Unable to validate AccessToken signature", BearerTokenError.INVALID_TOKEN);
}
var clientID = signedJWT.getJWTClaimsSet().getStringClaim("client_id");
var client = clientService.getClient(clientID);
attachLogFieldToLogs(CLIENT_ID, clientID);
if (client.isEmpty()) {
LOG.warn("Client not found");
throw new AccessTokenException("Client not found", BearerTokenError.INVALID_TOKEN);
}
var scopes = JSONArrayUtils.parse(signedJWT.getJWTClaimsSet().getClaim("scope").toString()).stream().map(Objects::toString).collect(Collectors.toList());
if (!areScopesValid(scopes) || !client.get().getScopes().containsAll(scopes)) {
LOG.warn("Invalid Scopes: {}", scopes);
throw new AccessTokenException("Invalid Scopes", OAuth2Error.INVALID_SCOPE);
}
List<String> identityClaims = null;
if (identityEnabled) {
identityClaims = getIdentityClaims(signedJWT.getJWTClaimsSet());
}
var subject = signedJWT.getJWTClaimsSet().getSubject();
var accessTokenStore = getAccessTokenStore(clientID, subject);
if (accessTokenStore.isEmpty()) {
LOG.warn("Access Token Store is empty. Access Token expires at: {}. CurrentDateTime is: {}. JWTID in Access Token sent in request: {}", signedJWT.getJWTClaimsSet().getExpirationTime(), currentDateTime, signedJWT.getJWTClaimsSet().getJWTID());
throw new AccessTokenException(INVALID_ACCESS_TOKEN, BearerTokenError.INVALID_TOKEN);
}
if (!accessTokenStore.get().getToken().equals(accessToken.getValue())) {
LOG.warn("Access Token in Access Token Store is different to Access Token sent in request");
var storeJwtId = SignedJWT.parse(accessTokenStore.get().getToken()).getJWTClaimsSet().getJWTID();
LOG.warn("JWTID in AccessTokenStore: {} compared to JWTID in Access Token sent in request: {}", storeJwtId, signedJWT.getJWTClaimsSet().getJWTID());
throw new AccessTokenException(INVALID_ACCESS_TOKEN, BearerTokenError.INVALID_TOKEN);
}
return new AccessTokenInfo(accessTokenStore.get(), subject, scopes, identityClaims);
} catch (ParseException e) {
LOG.warn("Unable to parse AccessToken to SignedJWT");
throw new AccessTokenException("Unable to parse AccessToken to SignedJWT", BearerTokenError.INVALID_TOKEN);
} catch (com.nimbusds.oauth2.sdk.ParseException e) {
LOG.warn("Unable to parse ClaimSet in AccessToken");
throw new AccessTokenException("Unable to parse ClaimSet in AccessToken", BearerTokenError.INVALID_TOKEN);
}
}
use of com.nimbusds.oauth2.sdk.id.JWTID in project di-authentication-api by alphagov.
the class IPVTokenServiceTest method signJWTWithKMS.
private void signJWTWithKMS() throws JOSEException {
var ecSigningKey = new ECKeyGenerator(Curve.P_256).keyID(KEY_ID).algorithm(JWSAlgorithm.ES256).generate();
var claimsSet = new JWTAuthenticationClaimsSet(new ClientID(CLIENT_ID), singletonList(new Audience(buildURI(IPV_URI.toString(), "token"))), NowHelper.nowPlus(5, ChronoUnit.MINUTES), null, NowHelper.now(), new JWTID());
var ecdsaSigner = new ECDSASigner(ecSigningKey);
var jwsHeader = new JWSHeader.Builder(JWSAlgorithm.ES256).keyID(ecSigningKey.getKeyID()).build();
var signedJWT = new SignedJWT(jwsHeader, claimsSet.toJWTClaimsSet());
unchecked(signedJWT::sign).accept(ecdsaSigner);
var signResult = new SignResult();
byte[] idTokenSignatureDer = ECDSA.transcodeSignatureToDER(signedJWT.getSignature().decode());
signResult.setSignature(ByteBuffer.wrap(idTokenSignatureDer));
signResult.setKeyId(KEY_ID);
signResult.setSigningAlgorithm(JWSAlgorithm.ES256.getName());
when(kmsService.sign(any(SignRequest.class))).thenReturn(signResult);
}
Aggregations