added encryption/decryption to cached JWK-URI service

pull/516/head
Justin Richer 11 years ago
parent 2b0d02dc72
commit 6605877a1b

@ -31,7 +31,7 @@ import javax.servlet.http.HttpSession;
import org.apache.http.impl.client.DefaultHttpClient;
import org.mitre.jwt.signer.service.JwtSigningAndValidationService;
import org.mitre.jwt.signer.service.impl.JWKSetSigningAndValidationServiceCacheService;
import org.mitre.jwt.signer.service.impl.JWKSetCacheService;
import org.mitre.oauth2.model.RegisteredClient;
import org.mitre.openid.connect.client.model.IssuerServiceResponse;
import org.mitre.openid.connect.client.service.AuthRequestOptionsService;
@ -85,7 +85,7 @@ public class OIDCAuthenticationFilter extends AbstractAuthenticationProcessingFi
private int timeSkewAllowance = 300;
@Autowired
private JWKSetSigningAndValidationServiceCacheService validationServices;
private JWKSetCacheService validationServices;
// modular services to build out client filter
private ServerConfigurationService servers;
@ -355,7 +355,7 @@ public class OIDCAuthenticationFilter extends AbstractAuthenticationProcessingFi
ReadOnlyJWTClaimsSet idClaims = idToken.getJWTClaimsSet();
// check the signature
JwtSigningAndValidationService jwtValidator = validationServices.get(serverConfig.getJwksUri());
JwtSigningAndValidationService jwtValidator = validationServices.getValidator(serverConfig.getJwksUri());
if (jwtValidator != null) {
if(!jwtValidator.validateSignature(idToken)) {
throw new AuthenticationServiceException("Signature validation failed");
@ -542,14 +542,14 @@ public class OIDCAuthenticationFilter extends AbstractAuthenticationProcessingFi
/**
* @return the validationServices
*/
public JWKSetSigningAndValidationServiceCacheService getValidationServices() {
public JWKSetCacheService getValidationServices() {
return validationServices;
}
/**
* @param validationServices the validationServices to set
*/
public void setValidationServices(JWKSetSigningAndValidationServiceCacheService validationServices) {
public void setValidationServices(JWKSetCacheService validationServices) {
this.validationServices = validationServices;
}

@ -25,6 +25,8 @@ import java.util.concurrent.TimeUnit;
import org.apache.http.client.HttpClient;
import org.apache.http.impl.client.DefaultHttpClient;
import org.mitre.jose.keystore.JWKSetKeyStore;
import org.mitre.jwt.encryption.service.JwtEncryptionAndDecryptionService;
import org.mitre.jwt.encryption.service.impl.DefaultJwtEncryptionAndDecryptionService;
import org.mitre.jwt.signer.service.JwtSigningAndValidationService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -39,25 +41,32 @@ import com.nimbusds.jose.jwk.JWKSet;
/**
*
* Creates a caching map of JOSE signers and validators keyed on the JWK Set URI.
* Dynamically loads JWK Sets to create the signing and validation services.
* Creates a caching map of JOSE signers/validators and encryptors/decryptors
* keyed on the JWK Set URI. Dynamically loads JWK Sets to create the services.
*
* @author jricher
*
*
*/
@Service
public class JWKSetSigningAndValidationServiceCacheService {
public class JWKSetCacheService {
private static Logger logger = LoggerFactory.getLogger(JWKSetSigningAndValidationServiceCacheService.class);
private static Logger logger = LoggerFactory.getLogger(JWKSetCacheService.class);
// map of jwk set uri -> signing/validation service built on the keys found in that jwk set
private LoadingCache<String, JwtSigningAndValidationService> cache;
private LoadingCache<String, JwtSigningAndValidationService> validators;
// map of jwk set uri -> encryption/decryption service built on the keys found in that jwk set
private LoadingCache<String, JwtEncryptionAndDecryptionService> encryptors;
public JWKSetSigningAndValidationServiceCacheService() {
this.cache = CacheBuilder.newBuilder()
public JWKSetCacheService() {
this.validators = CacheBuilder.newBuilder()
.expireAfterWrite(1, TimeUnit.HOURS) // expires 1 hour after fetch
.maximumSize(100)
.build(new JWKSetVerifierFetcher());
this.encryptors = CacheBuilder.newBuilder()
.expireAfterWrite(1, TimeUnit.HOURS) // expires 1 hour after fetch
.maximumSize(100)
.build(new JWKSetEncryptorFetcher());
}
/**
@ -66,15 +75,24 @@ public class JWKSetSigningAndValidationServiceCacheService {
* @throws ExecutionException
* @see com.google.common.cache.Cache#get(java.lang.Object)
*/
public JwtSigningAndValidationService get(String jwksUri) {
public JwtSigningAndValidationService getValidator(String jwksUri) {
try {
return cache.get(jwksUri);
return validators.get(jwksUri);
} catch (ExecutionException e) {
logger.warn("Couldn't load JWK Set from " + jwksUri, e);
return null;
}
}
public JwtEncryptionAndDecryptionService getEncrypter(String jwksUri) {
try {
return encryptors.get(jwksUri);
} catch (ExecutionException e) {
logger.warn("Couldn't load JWK Set from " + jwksUri, e);
return null;
}
}
/**
* @author jricher
*
@ -103,4 +121,28 @@ public class JWKSetSigningAndValidationServiceCacheService {
}
/**
* @author jricher
*
*/
private class JWKSetEncryptorFetcher extends CacheLoader<String, JwtEncryptionAndDecryptionService> {
private HttpClient httpClient = new DefaultHttpClient();
private HttpComponentsClientHttpRequestFactory httpFactory = new HttpComponentsClientHttpRequestFactory(httpClient);
private RestTemplate restTemplate = new RestTemplate(httpFactory);
/* (non-Javadoc)
* @see com.google.common.cache.CacheLoader#load(java.lang.Object)
*/
@Override
public JwtEncryptionAndDecryptionService load(String key) throws Exception {
String jsonString = restTemplate.getForObject(key, String.class);
JWKSet jwkSet = JWKSet.parse(jsonString);
JWKSetKeyStore keyStore = new JWKSetKeyStore(jwkSet);
JwtEncryptionAndDecryptionService service = new DefaultJwtEncryptionAndDecryptionService(keyStore);
return service;
}
}
}

@ -27,7 +27,7 @@ import java.util.Set;
import org.mitre.jwt.encryption.service.JwtEncryptionAndDecryptionService;
import org.mitre.jwt.signer.service.JwtSigningAndValidationService;
import org.mitre.jwt.signer.service.impl.DefaultJwtSigningAndValidationService;
import org.mitre.jwt.signer.service.impl.JWKSetSigningAndValidationServiceCacheService;
import org.mitre.jwt.signer.service.impl.JWKSetCacheService;
import org.mitre.oauth2.model.ClientDetailsEntity;
import org.mitre.oauth2.service.ClientDetailsEntityService;
import org.mitre.oauth2.service.SystemScopeService;
@ -67,7 +67,7 @@ public class ConnectOAuth2RequestFactory extends DefaultOAuth2RequestFactory {
private ClientDetailsEntityService clientDetailsService;
@Autowired
private JWKSetSigningAndValidationServiceCacheService validators;
private JWKSetCacheService validators;
@Autowired
private SystemScopeService systemScopes;
@ -192,7 +192,7 @@ public class ConnectOAuth2RequestFactory extends DefaultOAuth2RequestFactory {
}
// check JWT signature
JwtSigningAndValidationService validator = validators.get(client.getJwksUri());
JwtSigningAndValidationService validator = validators.getValidator(client.getJwksUri());
if (validator == null) {
throw new InvalidClientException("Unable to create signature validator for client's JWKS URI: " + client.getJwksUri());

@ -23,7 +23,7 @@ import java.text.ParseException;
import java.util.Date;
import org.mitre.jwt.signer.service.JwtSigningAndValidationService;
import org.mitre.jwt.signer.service.impl.JWKSetSigningAndValidationServiceCacheService;
import org.mitre.jwt.signer.service.impl.JWKSetCacheService;
import org.mitre.oauth2.model.ClientDetailsEntity;
import org.mitre.oauth2.service.ClientDetailsEntityService;
import org.mitre.openid.connect.config.ConfigurationPropertiesBean;
@ -51,7 +51,7 @@ public class JwtBearerAuthenticationProvider implements AuthenticationProvider {
// map of verifiers, load keys for clients
@Autowired
private JWKSetSigningAndValidationServiceCacheService validators;
private JWKSetCacheService validators;
// Allow for time sync issues by having a window of X seconds.
private int timeSkewAllowance = 300;
@ -82,7 +82,7 @@ public class JwtBearerAuthenticationProvider implements AuthenticationProvider {
// check the signature with nimbus
if (jwt instanceof SignedJWT) {
SignedJWT jws = (SignedJWT)jwt;
JwtSigningAndValidationService validator = validators.get(client.getJwksUri());
JwtSigningAndValidationService validator = validators.getValidator(client.getJwksUri());
if (validator == null || !validator.validateSignature(jws)) {
throw new AuthenticationServiceException("Invalid signature");
}

Loading…
Cancel
Save