JwksStoreService.java
/*
* The contents of this file are subject to the terms of the Common Development and
* Distribution License (the License). You may not use this file except in compliance with the
* License.
*
* You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
* specific language governing permission and limitations under the License.
*
* When distributing Covered Software, include this CDDL Header Notice in each file and include
* the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
* Header, with the fields enclosed by brackets [] replaced by your own identifying
* information: "Portions copyright [year] [name of copyright owner]".
*
* Copyright 2017 ForgeRock AS.
*/
package org.forgerock.json.jose.jwk.store;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import org.forgerock.json.jose.exceptions.FailedToLoadJWKException;
import org.forgerock.util.SimpleHTTPClient;
import org.forgerock.util.time.Duration;
/**
* Manage the jwks store, to avoid having more than one jwks store for the same JWKs_URI unnecessary.
*/
public class JwksStoreService {
/** The default cache timeout in ms. */
public final static Duration JWKS_STORE_DEFAULT_CACHE_TIMEOUT_MS = Duration.duration(1L, TimeUnit.HOURS);
/** The default cache time before reload the cache in case of cache miss ms. */
public final static Duration JWKS_STORE_DEFAULT_CACHE_MISS_CACHE_TIME_MS = Duration.duration(1L, TimeUnit.MINUTES);
private final SimpleHTTPClient simpleHTTPClient;
private final Map<String, JwksStore> jwksStoreByUID = new HashMap<>();
/** Default constructor. */
public JwksStoreService() {
this(new SimpleHTTPClient());
}
/**
* Constructor with read and connection timeout. It's used for the connection to the JWKs_URI.
*
* @param readTimeout the read timeout
* @param connTimeout the connection timeout
*/
public JwksStoreService(int readTimeout, int connTimeout) {
this(new SimpleHTTPClient(readTimeout, connTimeout));
}
/**
* Constructor with a HTTP client, that will be used to connect to the JWKS_URI.
*
* @param simpleHTTPClient the HTTP client
*/
public JwksStoreService(SimpleHTTPClient simpleHTTPClient) {
this.simpleHTTPClient = simpleHTTPClient;
}
/**
* Returns the appropriate JWKs store.
*
* @param uid Reference to the jwks store. Note that the uid check is case insensitive
* @return a JWKs Store for the corresponding UID. If doesn't exist, returns null
*/
public synchronized JwksStore getJwksStore(String uid) {
return jwksStoreByUID.get(uid.toLowerCase());
}
/**
* Configure a JWKs store.
*
* @param uid the unique identifier for this store
* @param cacheTimeout a cache timeout to avoid reloading the cache all the time when doing encryption
* @param cacheMissCacheTime the cache time before reload the cache in case of cache miss.
* @param jwkUrl the jwk url hosted by the client application
* @return the JWKs store corresponding
* @throws FailedToLoadJWKException if the jwks can't be reloaded.
*/
public synchronized JwksStore configureJwksStore(String uid, final Duration cacheTimeout,
final Duration cacheMissCacheTime, final URL jwkUrl) throws FailedToLoadJWKException {
uid = uid.toLowerCase();
JwksStore jwksStore = getJwksStore(uid);
if (jwksStore != null) {
jwksStore.setCacheTimeout(cacheTimeout);
jwksStore.setCacheMissCacheTime(cacheMissCacheTime);
jwksStore.setJwkUrl(jwkUrl);
return jwksStore;
} else {
jwksStore = new JwksStore(uid, cacheTimeout, cacheMissCacheTime, jwkUrl, simpleHTTPClient);
jwksStoreByUID.put(uid, jwksStore);
return jwksStore;
}
}
/**
* Remove the corresponding jwks store if exist.
*
* @param uid the uid. Note that the uid check isn't case sensitive
*/
public synchronized void removeJwksStore(String uid) {
jwksStoreByUID.remove(uid.toLowerCase());
}
}