*/
private void processRequestObject(String jwtString, AuthorizationRequest request) {
// parse the request object
try {
JWT jwt = JWTParser.parse(jwtString);
// TODO: move keys to constants
if (jwt instanceof SignedJWT) {
// it's a signed JWT, check the signature
SignedJWT signedJwt = (SignedJWT)jwt;
// need to check clientId first so that we can load the client to check other fields
if (request.getClientId() == null) {
request.setClientId(signedJwt.getJWTClaimsSet().getStringClaim("client_id"));
}
ClientDetailsEntity client = clientDetailsService.loadClientByClientId(request.getClientId());
if (client == null) {
throw new InvalidClientException("Client not found: " + request.getClientId());
}
JWSAlgorithm alg = signedJwt.getHeader().getAlgorithm();
if (client.getRequestObjectSigningAlg() == null ||
!client.getRequestObjectSigningAlg().equals(alg)) {
throw new InvalidClientException("Client's registered request object signing algorithm (" + client.getRequestObjectSigningAlg() + ") does not match request object's actual algorithm (" + alg.getName() + ")");
}
if (alg.equals(JWSAlgorithm.RS256)
|| alg.equals(JWSAlgorithm.RS384)
|| alg.equals(JWSAlgorithm.RS512)) {
// it's RSA, need to find the JWK URI and fetch the key
if (client.getJwksUri() == null) {
throw new InvalidClientException("Client must have a JWKS URI registered to use signed request objects.");
}
// check JWT signature
JwtSigningAndValidationService validator = validators.getValidator(client.getJwksUri());
if (validator == null) {
throw new InvalidClientException("Unable to create signature validator for client's JWKS URI: " + client.getJwksUri());
}
if (!validator.validateSignature(signedJwt)) {
throw new InvalidClientException("Signature did not validate for presented JWT request object.");
}
} else if (alg.equals(JWSAlgorithm.HS256)
|| alg.equals(JWSAlgorithm.HS384)
|| alg.equals(JWSAlgorithm.HS512)) {
// it's HMAC, we need to make a validator based on the client secret
JwtSigningAndValidationService validator = symmetricCacheService.getSymmetricValidtor(client);
if (validator == null) {
throw new InvalidClientException("Unable to create signature validator for client's secret: " + client.getClientSecret());
}
if (!validator.validateSignature(signedJwt)) {
throw new InvalidClientException("Signature did not validate for presented JWT request object.");
}
}
} else if (jwt instanceof PlainJWT) {
PlainJWT plainJwt = (PlainJWT)jwt;
// need to check clientId first so that we can load the client to check other fields
if (request.getClientId() == null) {
request.setClientId(plainJwt.getJWTClaimsSet().getStringClaim("client_id"));
}
ClientDetailsEntity client = clientDetailsService.loadClientByClientId(request.getClientId());
if (client == null) {
throw new InvalidClientException("Client not found: " + request.getClientId());
}
if (client.getRequestObjectSigningAlg() == null) {
throw new InvalidClientException("Client is not registered for unsigned request objects (no request_object_signing_alg registered)");
} else if (!client.getRequestObjectSigningAlg().equals(Algorithm.NONE)) {
throw new InvalidClientException("Client is not registered for unsigned request objects (request_object_signing_alg is " + client.getRequestObjectSigningAlg() +")");
}
// if we got here, we're OK, keep processing
} else if (jwt instanceof EncryptedJWT) {
EncryptedJWT encryptedJWT = (EncryptedJWT)jwt;
// decrypt the jwt if we can
encryptionService.decryptJwt(encryptedJWT);
// TODO: what if the content is a signed JWT? (#525)
if (!encryptedJWT.getState().equals(State.DECRYPTED)) {
throw new InvalidClientException("Unable to decrypt the request object");
}
// need to check clientId first so that we can load the client to check other fields
if (request.getClientId() == null) {
request.setClientId(encryptedJWT.getJWTClaimsSet().getStringClaim("client_id"));
}
ClientDetailsEntity client = clientDetailsService.loadClientByClientId(request.getClientId());
if (client == null) {
throw new InvalidClientException("Client not found: " + request.getClientId());
}
}
/*
* NOTE: Claims inside the request object always take precedence over those in the parameter map.
*/
// now that we've got the JWT, and it's been parsed, validated, and/or decrypted, we can process the claims
ReadOnlyJWTClaimsSet claims = jwt.getJWTClaimsSet();
Set<String> responseTypes = OAuth2Utils.parseParameterList(claims.getStringClaim("response_type"));
if (responseTypes != null && !responseTypes.isEmpty()) {
if (!responseTypes.equals(request.getResponseTypes())) {
logger.info("Mismatch between request object and regular parameter for response_type, using request object");