try {
JWT idToken = JWTParser.parse(idTokenValue);
// validate our ID Token over a number of tests
ReadOnlyJWTClaimsSet idClaims = idToken.getJWTClaimsSet();
// check the signature
JwtSigningAndValidationService jwtValidator = null;
Algorithm tokenAlg = idToken.getHeader().getAlgorithm();
Algorithm clientAlg = clientConfig.getIdTokenSignedResponseAlg();
if (clientAlg != null) {
if (!clientAlg.equals(tokenAlg)) {
throw new AuthenticationServiceException("Token algorithm " + tokenAlg + " does not match expected algorithm " + clientAlg);
}
}
if (idToken instanceof PlainJWT) {
if (clientAlg == null) {
throw new AuthenticationServiceException("Unsigned ID tokens can only be used if explicitly configured in client.");
}
if (tokenAlg != null && !tokenAlg.equals(JWSAlgorithm.NONE)) {
throw new AuthenticationServiceException("Unsigned token received, expected signature with " + tokenAlg);
}
} else if (idToken instanceof SignedJWT) {
SignedJWT signedIdToken = (SignedJWT)idToken;
if (tokenAlg.equals(JWSAlgorithm.HS256)
|| tokenAlg.equals(JWSAlgorithm.HS384)
|| tokenAlg.equals(JWSAlgorithm.HS512)) {
// generate one based on client secret
jwtValidator = symmetricCacheService.getSymmetricValidtor(clientConfig.getClient());
} else {
// otherwise load from the server's public key
jwtValidator = validationServices.getValidator(serverConfig.getJwksUri());
}
if (jwtValidator != null) {
if(!jwtValidator.validateSignature(signedIdToken)) {
throw new AuthenticationServiceException("Signature validation failed");
}
} else {
logger.error("No validation service found. Skipping signature validation");
throw new AuthenticationServiceException("Unable to find an appropriate signature validator for ID Token.");
}
} // TODO: encrypted id tokens
// check the issuer
if (idClaims.getIssuer() == null) {
throw new AuthenticationServiceException("Id Token Issuer is null");
} else if (!idClaims.getIssuer().equals(serverConfig.getIssuer())){
throw new AuthenticationServiceException("Issuers do not match, expected " + serverConfig.getIssuer() + " got " + idClaims.getIssuer());
}
// check expiration
if (idClaims.getExpirationTime() == null) {
throw new AuthenticationServiceException("Id Token does not have required expiration claim");
} else {
// it's not null, see if it's expired
Date now = new Date(System.currentTimeMillis() - (timeSkewAllowance * 1000));
if (now.after(idClaims.getExpirationTime())) {
throw new AuthenticationServiceException("Id Token is expired: " + idClaims.getExpirationTime());
}
}
// check not before
if (idClaims.getNotBeforeTime() != null) {
Date now = new Date(System.currentTimeMillis() + (timeSkewAllowance * 1000));
if (now.before(idClaims.getNotBeforeTime())){
throw new AuthenticationServiceException("Id Token not valid untill: " + idClaims.getNotBeforeTime());
}
}
// check issued at
if (idClaims.getIssueTime() == null) {
throw new AuthenticationServiceException("Id Token does not have required issued-at claim");
} else {
// since it's not null, see if it was issued in the future
Date now = new Date(System.currentTimeMillis() + (timeSkewAllowance * 1000));
if (now.before(idClaims.getIssueTime())) {
throw new AuthenticationServiceException("Id Token was issued in the future: " + idClaims.getIssueTime());
}
}
// check audience
if (idClaims.getAudience() == null) {
throw new AuthenticationServiceException("Id token audience is null");
} else if (!idClaims.getAudience().contains(clientConfig.getClientId())) {
throw new AuthenticationServiceException("Audience does not match, expected " + clientConfig.getClientId() + " got " + idClaims.getAudience());
}
// compare the nonce to our stored claim
String nonce = idClaims.getStringClaim("nonce");
if (Strings.isNullOrEmpty(nonce)) {
logger.error("ID token did not contain a nonce claim.");
throw new AuthenticationServiceException("ID token did not contain a nonce claim.");
}
String storedNonce = getStoredNonce(session);
if (!nonce.equals(storedNonce)) {
logger.error("Possible replay attack detected! The comparison of the nonce in the returned "
+ "ID Token to the session " + NONCE_SESSION_VARIABLE + " failed. Expected " + storedNonce + " got " + nonce + ".");
throw new AuthenticationServiceException(
"Possible replay attack detected! The comparison of the nonce in the returned "
+ "ID Token to the session " + NONCE_SESSION_VARIABLE + " failed. Expected " + storedNonce + " got " + nonce + ".");
}
// pull the subject (user id) out as a claim on the id_token
String userId = idClaims.getSubject();
// construct an OIDCAuthenticationToken and return a Authentication object w/the userId and the idToken
OIDCAuthenticationToken token = new OIDCAuthenticationToken(userId, idClaims.getIssuer(), serverConfig, idTokenValue, accessTokenValue, refreshTokenValue);
Authentication authentication = this.getAuthenticationManager().authenticate(token);
return authentication;
} catch (ParseException e) {