added support for unsigned ID tokens in client, use client configuration to turn this on, closes #633
parent
5c2cb75407
commit
c7a6c4fafe
|
@ -67,10 +67,14 @@ import com.google.common.collect.Lists;
|
||||||
import com.google.gson.JsonElement;
|
import com.google.gson.JsonElement;
|
||||||
import com.google.gson.JsonObject;
|
import com.google.gson.JsonObject;
|
||||||
import com.google.gson.JsonParser;
|
import com.google.gson.JsonParser;
|
||||||
|
import com.nimbusds.jose.Algorithm;
|
||||||
import com.nimbusds.jose.JWSAlgorithm;
|
import com.nimbusds.jose.JWSAlgorithm;
|
||||||
import com.nimbusds.jose.JWSHeader;
|
import com.nimbusds.jose.JWSHeader;
|
||||||
import com.nimbusds.jose.util.Base64;
|
import com.nimbusds.jose.util.Base64;
|
||||||
|
import com.nimbusds.jwt.JWT;
|
||||||
import com.nimbusds.jwt.JWTClaimsSet;
|
import com.nimbusds.jwt.JWTClaimsSet;
|
||||||
|
import com.nimbusds.jwt.JWTParser;
|
||||||
|
import com.nimbusds.jwt.PlainJWT;
|
||||||
import com.nimbusds.jwt.ReadOnlyJWTClaimsSet;
|
import com.nimbusds.jwt.ReadOnlyJWTClaimsSet;
|
||||||
import com.nimbusds.jwt.SignedJWT;
|
import com.nimbusds.jwt.SignedJWT;
|
||||||
|
|
||||||
|
@ -437,7 +441,7 @@ public class OIDCAuthenticationFilter extends AbstractAuthenticationProcessingFi
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
SignedJWT idToken = SignedJWT.parse(idTokenValue);
|
JWT idToken = JWTParser.parse(idTokenValue);
|
||||||
|
|
||||||
// validate our ID Token over a number of tests
|
// validate our ID Token over a number of tests
|
||||||
ReadOnlyJWTClaimsSet idClaims = idToken.getJWTClaimsSet();
|
ReadOnlyJWTClaimsSet idClaims = idToken.getJWTClaimsSet();
|
||||||
|
@ -445,27 +449,50 @@ public class OIDCAuthenticationFilter extends AbstractAuthenticationProcessingFi
|
||||||
// check the signature
|
// check the signature
|
||||||
JwtSigningAndValidationService jwtValidator = null;
|
JwtSigningAndValidationService jwtValidator = null;
|
||||||
|
|
||||||
JWSAlgorithm alg = idToken.getHeader().getAlgorithm();
|
Algorithm tokenAlg = idToken.getHeader().getAlgorithm();
|
||||||
if (alg.equals(JWSAlgorithm.HS256)
|
|
||||||
|| alg.equals(JWSAlgorithm.HS384)
|
|
||||||
|| alg.equals(JWSAlgorithm.HS512)) {
|
|
||||||
|
|
||||||
// generate one based on client secret
|
Algorithm clientAlg = clientConfig.getIdTokenSignedResponseAlg();
|
||||||
jwtValidator = symmetricCacheService.getSymmetricValidtor(clientConfig.getClient());
|
|
||||||
} else {
|
|
||||||
// otherwise load from the server's public key
|
|
||||||
jwtValidator = validationServices.getValidator(serverConfig.getJwksUri());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (jwtValidator != null) {
|
if (clientAlg != null) {
|
||||||
if(!jwtValidator.validateSignature(idToken)) {
|
if (!clientAlg.equals(tokenAlg)) {
|
||||||
throw new AuthenticationServiceException("Signature validation failed");
|
throw new AuthenticationServiceException("Token algorithm " + tokenAlg + " does not match expected algorithm " + clientAlg);
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
logger.error("No validation service found. Skipping signature validation");
|
|
||||||
throw new AuthenticationServiceException("Unable to find an appropriate signature validator for ID Token.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
// check the issuer
|
||||||
if (idClaims.getIssuer() == null) {
|
if (idClaims.getIssuer() == null) {
|
||||||
throw new AuthenticationServiceException("Id Token Issuer is null");
|
throw new AuthenticationServiceException("Id Token Issuer is null");
|
||||||
|
|
Loading…
Reference in New Issue