KEYCLOAK-3493 KEYCLOAK-3532 Renamed KeyStorageProvider to PublicKeyStorageProvider

This commit is contained in:
mposolda 2016-10-03 14:23:46 +02:00
parent d12f157299
commit 0f9798a10d
18 changed files with 77 additions and 79 deletions

View file

@ -40,7 +40,7 @@ public interface InfinispanConnectionProvider extends Provider {
String AUTHORIZATION_CACHE_NAME = "authorization";
String KEYS_CACHE_NAME = "keys";
int KEYS_CACHE_DEFAULT_MAX = 500;
int KEYS_CACHE_DEFAULT_MAX = 1000;
int KEYS_CACHE_MAX_IDLE_SECONDS = 3600;

View file

@ -28,16 +28,16 @@ import java.util.concurrent.FutureTask;
import org.infinispan.Cache;
import org.jboss.logging.Logger;
import org.keycloak.common.util.Time;
import org.keycloak.keys.KeyLoader;
import org.keycloak.keys.KeyStorageProvider;
import org.keycloak.keys.PublicKeyLoader;
import org.keycloak.keys.PublicKeyStorageProvider;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class InfinispanKeyStorageProvider implements KeyStorageProvider {
public class InfinispanPublicKeyStorageProvider implements PublicKeyStorageProvider {
private static final Logger log = Logger.getLogger(InfinispanKeyStorageProvider.class);
private static final Logger log = Logger.getLogger(InfinispanPublicKeyStorageProvider.class);
private final Cache<String, PublicKeysEntry> keys;
@ -45,7 +45,7 @@ public class InfinispanKeyStorageProvider implements KeyStorageProvider {
private final int minTimeBetweenRequests ;
public InfinispanKeyStorageProvider(Cache<String, PublicKeysEntry> keys, Map<String, FutureTask<PublicKeysEntry>> tasksInProgress, int minTimeBetweenRequests) {
public InfinispanPublicKeyStorageProvider(Cache<String, PublicKeysEntry> keys, Map<String, FutureTask<PublicKeysEntry>> tasksInProgress, int minTimeBetweenRequests) {
this.keys = keys;
this.tasksInProgress = tasksInProgress;
this.minTimeBetweenRequests = minTimeBetweenRequests;
@ -53,7 +53,7 @@ public class InfinispanKeyStorageProvider implements KeyStorageProvider {
@Override
public PublicKey getPublicKey(String modelKey, String kid, KeyLoader loader) {
public PublicKey getPublicKey(String modelKey, String kid, PublicKeyLoader loader) {
// Check if key is in cache
PublicKeysEntry entry = keys.get(modelKey);
if (entry != null) {
@ -127,9 +127,9 @@ public class InfinispanKeyStorageProvider implements KeyStorageProvider {
private class WrapperCallable implements Callable<PublicKeysEntry> {
private final String modelKey;
private final KeyLoader delegate;
private final PublicKeyLoader delegate;
public WrapperCallable(String modelKey, KeyLoader delegate) {
public WrapperCallable(String modelKey, PublicKeyLoader delegate) {
this.modelKey = modelKey;
this.delegate = delegate;
}

View file

@ -25,17 +25,18 @@ import org.infinispan.Cache;
import org.jboss.logging.Logger;
import org.keycloak.Config;
import org.keycloak.connections.infinispan.InfinispanConnectionProvider;
import org.keycloak.keys.KeyStorageProvider;
import org.keycloak.keys.KeyStorageProviderFactory;
import org.keycloak.keys.PublicKeyStorageProvider;
import org.keycloak.keys.PublicKeyStorageSpi;
import org.keycloak.keys.PublicKeyStorageProviderFactory;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakSessionFactory;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class InfinispanKeyStorageProviderFactory implements KeyStorageProviderFactory {
public class InfinispanPublicKeyStorageProviderFactory implements PublicKeyStorageProviderFactory {
private static final Logger log = Logger.getLogger(InfinispanKeyStorageProviderFactory.class);
private static final Logger log = Logger.getLogger(InfinispanPublicKeyStorageProviderFactory.class);
public static final String PROVIDER_ID = "infinispan";
@ -46,9 +47,9 @@ public class InfinispanKeyStorageProviderFactory implements KeyStorageProviderFa
private int minTimeBetweenRequests;
@Override
public KeyStorageProvider create(KeycloakSession session) {
public PublicKeyStorageProvider create(KeycloakSession session) {
lazyInit(session);
return new InfinispanKeyStorageProvider(keysCache, tasksInProgress, minTimeBetweenRequests);
return new InfinispanPublicKeyStorageProvider(keysCache, tasksInProgress, minTimeBetweenRequests);
}
private void lazyInit(KeycloakSession session) {

View file

@ -15,4 +15,4 @@
# limitations under the License.
#
org.keycloak.keys.infinispan.InfinispanKeyStorageProviderFactory
org.keycloak.keys.infinispan.InfinispanPublicKeyStorageProviderFactory

View file

@ -39,8 +39,8 @@ import org.junit.Before;
import org.junit.Test;
import org.keycloak.common.util.Time;
import org.keycloak.connections.infinispan.InfinispanConnectionProvider;
import org.keycloak.keys.KeyLoader;
import org.keycloak.keys.infinispan.InfinispanKeyStorageProvider;
import org.keycloak.keys.PublicKeyLoader;
import org.keycloak.keys.infinispan.InfinispanPublicKeyStorageProvider;
import org.keycloak.keys.infinispan.PublicKeysEntry;
/**
@ -130,14 +130,14 @@ public class InfinispanKeyStorageProviderTest {
@Override
public void run() {
InfinispanKeyStorageProvider provider = new InfinispanKeyStorageProvider(keys, tasksInProgress, minTimeBetweenRequests);
InfinispanPublicKeyStorageProvider provider = new InfinispanPublicKeyStorageProvider(keys, tasksInProgress, minTimeBetweenRequests);
provider.getPublicKey(modelKey, "kid1", new SampleLoader(modelKey));
}
}
private class SampleLoader implements KeyLoader {
private class SampleLoader implements PublicKeyLoader {
private final String modelKey;

View file

@ -23,7 +23,7 @@ import java.util.Map;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public interface KeyLoader {
public interface PublicKeyLoader {
Map<String, PublicKey> loadKeys() throws Exception;

View file

@ -24,7 +24,7 @@ import org.keycloak.provider.Provider;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public interface KeyStorageProvider extends Provider {
public interface PublicKeyStorageProvider extends Provider {
/**
@ -35,6 +35,6 @@ public interface KeyStorageProvider extends Provider {
* @param loader
* @return
*/
PublicKey getPublicKey(String modelKey, String kid, KeyLoader loader);
PublicKey getPublicKey(String modelKey, String kid, PublicKeyLoader loader);
}

View file

@ -22,5 +22,5 @@ import org.keycloak.provider.ProviderFactory;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public interface KeyStorageProviderFactory extends ProviderFactory<KeyStorageProvider> {
public interface PublicKeyStorageProviderFactory extends ProviderFactory<PublicKeyStorageProvider> {
}

View file

@ -24,7 +24,7 @@ import org.keycloak.provider.Spi;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class KeyStorageSpi implements Spi {
public class PublicKeyStorageSpi implements Spi {
@Override
public boolean isInternal() {
@ -33,16 +33,16 @@ public class KeyStorageSpi implements Spi {
@Override
public String getName() {
return "keyStorage";
return "publicKeyStorage";
}
@Override
public Class<? extends Provider> getProviderClass() {
return KeyStorageProvider.class;
return PublicKeyStorageProvider.class;
}
@Override
public Class<? extends ProviderFactory> getProviderFactoryClass() {
return KeyStorageProviderFactory.class;
return PublicKeyStorageProviderFactory.class;
}
}

View file

@ -65,4 +65,4 @@ org.keycloak.policy.PasswordPolicyManagerSpi
org.keycloak.transaction.TransactionManagerLookupSpi
org.keycloak.credential.hash.PasswordHashSpi
org.keycloak.credential.CredentialSpi
org.keycloak.keys.KeyStorageSpi
org.keycloak.keys.PublicKeyStorageSpi

View file

@ -17,27 +17,7 @@
package org.keycloak.authentication.authenticators.client;
import org.keycloak.OAuth2Constants;
import org.keycloak.authentication.AuthenticationFlowError;
import org.keycloak.authentication.ClientAuthenticationFlowContext;
import org.keycloak.common.util.Time;
import org.keycloak.jose.jws.JWSInput;
import org.keycloak.jose.jws.crypto.RSAProvider;
import org.keycloak.keys.loader.KeyStorageManager;
import org.keycloak.models.AuthenticationExecutionModel;
import org.keycloak.models.ClientModel;
import org.keycloak.models.ModelException;
import org.keycloak.models.RealmModel;
import org.keycloak.protocol.oidc.OIDCLoginProtocol;
import org.keycloak.protocol.oidc.OIDCLoginProtocolService;
import org.keycloak.provider.ProviderConfigProperty;
import org.keycloak.representations.JsonWebToken;
import org.keycloak.services.ServicesLogger;
import org.keycloak.services.Urls;
import org.keycloak.services.util.CertificateInfoHelper;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;
import java.security.PublicKey;
import java.util.Arrays;
import java.util.Collections;
@ -48,6 +28,26 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.core.Response;
import org.keycloak.OAuth2Constants;
import org.keycloak.authentication.AuthenticationFlowError;
import org.keycloak.authentication.ClientAuthenticationFlowContext;
import org.keycloak.common.util.Time;
import org.keycloak.jose.jws.JWSInput;
import org.keycloak.jose.jws.crypto.RSAProvider;
import org.keycloak.keys.loader.PublicKeyStorageManager;
import org.keycloak.models.AuthenticationExecutionModel;
import org.keycloak.models.ClientModel;
import org.keycloak.models.RealmModel;
import org.keycloak.protocol.oidc.OIDCLoginProtocol;
import org.keycloak.protocol.oidc.OIDCLoginProtocolService;
import org.keycloak.provider.ProviderConfigProperty;
import org.keycloak.representations.JsonWebToken;
import org.keycloak.services.ServicesLogger;
import org.keycloak.services.Urls;
/**
* Client authentication based on JWT signed by client private key .
* See <a href="https://tools.ietf.org/html/rfc7519">specs</a> for more details.
@ -163,7 +163,7 @@ public class JWTClientAuthenticator extends AbstractClientAuthenticator {
}
protected PublicKey getSignatureValidationKey(ClientModel client, ClientAuthenticationFlowContext context, JWSInput jws) {
PublicKey publicKey = KeyStorageManager.getClientPublicKey(context.getSession(), client, jws);
PublicKey publicKey = PublicKeyStorageManager.getClientPublicKey(context.getSession(), client, jws);
if (publicKey == null) {
Response challengeResponse = ClientAuthUtil.errorResponse(Response.Status.BAD_REQUEST.getStatusCode(), "unauthorized_client", "Unable to load public key");
context.failure(AuthenticationFlowError.CLIENT_CREDENTIALS_SETUP_REQUIRED, challengeResponse);

View file

@ -32,7 +32,7 @@ import org.keycloak.events.EventType;
import org.keycloak.jose.jws.JWSInput;
import org.keycloak.jose.jws.JWSInputException;
import org.keycloak.jose.jws.crypto.RSAProvider;
import org.keycloak.keys.loader.KeyStorageManager;
import org.keycloak.keys.loader.PublicKeyStorageManager;
import org.keycloak.models.ClientSessionModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
@ -299,7 +299,7 @@ public class OIDCIdentityProvider extends AbstractOAuth2IdentityProvider<OIDCIde
protected boolean verify(JWSInput jws) {
if (!getConfig().isValidateSignature()) return true;
PublicKey publicKey = KeyStorageManager.getIdentityProviderPublicKey(session, session.getContext().getRealm(), getConfig(), jws);
PublicKey publicKey = PublicKeyStorageManager.getIdentityProviderPublicKey(session, session.getContext().getRealm(), getConfig(), jws);
return publicKey != null && RSAProvider.verify(jws, publicKey);
}

View file

@ -26,7 +26,7 @@ import org.keycloak.authentication.authenticators.client.JWTClientAuthenticator;
import org.keycloak.jose.jwk.JSONWebKeySet;
import org.keycloak.jose.jwk.JWK;
import org.keycloak.jose.jwk.JWKBuilder;
import org.keycloak.keys.KeyLoader;
import org.keycloak.keys.PublicKeyLoader;
import org.keycloak.models.ClientModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.ModelException;
@ -41,7 +41,7 @@ import org.keycloak.util.JWKSUtils;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class ClientPublicKeyLoader implements KeyLoader {
public class ClientPublicKeyLoader implements PublicKeyLoader {
protected static ServicesLogger logger = ServicesLogger.ROOT_LOGGER;

View file

@ -26,7 +26,7 @@ import org.keycloak.common.util.PemUtils;
import org.keycloak.jose.jwk.JSONWebKeySet;
import org.keycloak.jose.jwk.JWK;
import org.keycloak.jose.jwk.JWKBuilder;
import org.keycloak.keys.KeyLoader;
import org.keycloak.keys.PublicKeyLoader;
import org.keycloak.models.KeycloakSession;
import org.keycloak.protocol.oidc.utils.JWKSHttpUtils;
import org.keycloak.services.ServicesLogger;
@ -35,14 +35,14 @@ import org.keycloak.util.JWKSUtils;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class OIDCIdentityProviderLoader implements KeyLoader {
public class OIDCIdentityProviderPublicKeyLoader implements PublicKeyLoader {
protected static ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
private final KeycloakSession session;
private final OIDCIdentityProviderConfig config;
public OIDCIdentityProviderLoader(KeycloakSession session, OIDCIdentityProviderConfig config) {
public OIDCIdentityProviderPublicKeyLoader(KeycloakSession session, OIDCIdentityProviderConfig config) {
this.session = session;
this.config = config;
}

View file

@ -21,7 +21,7 @@ import java.security.PublicKey;
import org.keycloak.broker.oidc.OIDCIdentityProviderConfig;
import org.keycloak.jose.jws.JWSInput;
import org.keycloak.keys.KeyStorageProvider;
import org.keycloak.keys.PublicKeyStorageProvider;
import org.keycloak.models.ClientModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel;
@ -29,12 +29,12 @@ import org.keycloak.models.RealmModel;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class KeyStorageManager {
public class PublicKeyStorageManager {
public static PublicKey getClientPublicKey(KeycloakSession session, ClientModel client, JWSInput input) {
String kid = input.getHeader().getKeyId();
KeyStorageProvider keyStorage = session.getProvider(KeyStorageProvider.class);
PublicKeyStorageProvider keyStorage = session.getProvider(PublicKeyStorageProvider.class);
String modelKey = getModelKey(client);
ClientPublicKeyLoader loader = new ClientPublicKeyLoader(session, client);
@ -49,10 +49,10 @@ public class KeyStorageManager {
public static PublicKey getIdentityProviderPublicKey(KeycloakSession session, RealmModel realm, OIDCIdentityProviderConfig idpConfig, JWSInput input) {
String kid = input.getHeader().getKeyId();
KeyStorageProvider keyStorage = session.getProvider(KeyStorageProvider.class);
PublicKeyStorageProvider keyStorage = session.getProvider(PublicKeyStorageProvider.class);
String modelKey = getModelKey(realm, idpConfig);
OIDCIdentityProviderLoader loader = new OIDCIdentityProviderLoader(session, idpConfig);
OIDCIdentityProviderPublicKeyLoader loader = new OIDCIdentityProviderPublicKeyLoader(session, idpConfig);
return keyStorage.getPublicKey(modelKey, kid, loader);
}

View file

@ -17,24 +17,21 @@
package org.keycloak.protocol.oidc.endpoints.request;
import org.keycloak.authentication.authenticators.client.JWTClientAuthenticator;
import org.keycloak.jose.jws.Algorithm;
import org.keycloak.jose.jws.JWSHeader;
import org.keycloak.jose.jws.JWSInput;
import org.keycloak.jose.jws.crypto.RSAProvider;
import org.keycloak.keys.KeyStorageProvider;
import org.keycloak.keys.loader.KeyStorageManager;
import org.keycloak.models.ClientModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.protocol.oidc.OIDCAdvancedConfigWrapper;
import org.keycloak.services.util.CertificateInfoHelper;
import org.keycloak.util.JsonSerialization;
import java.security.PublicKey;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import org.keycloak.jose.jws.Algorithm;
import org.keycloak.jose.jws.JWSHeader;
import org.keycloak.jose.jws.JWSInput;
import org.keycloak.jose.jws.crypto.RSAProvider;
import org.keycloak.keys.loader.PublicKeyStorageManager;
import org.keycloak.models.ClientModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.protocol.oidc.OIDCAdvancedConfigWrapper;
import org.keycloak.util.JsonSerialization;
/**
* Parse the parameters from OIDC "request" object
*
@ -57,7 +54,7 @@ class AuthzEndpointRequestObjectParser extends AuthzEndpointRequestParser {
if (header.getAlgorithm() == Algorithm.none) {
this.requestParams = JsonSerialization.readValue(input.getContent(), TypedHashMap.class);
} else if (header.getAlgorithm() == Algorithm.RS256) {
PublicKey clientPublicKey = KeyStorageManager.getClientPublicKey(session, client, input);
PublicKey clientPublicKey = PublicKeyStorageManager.getClientPublicKey(session, client, input);
if (clientPublicKey == null) {
throw new RuntimeException("Client public key not found");
}

View file

@ -73,7 +73,7 @@ keycloak.server.subsys.default.config=\
<default-provider>${keycloak.jta.lookup.provider:jboss}</default-provider>\
<provider name="jboss" enabled="true"/>\
</spi>\
<spi name="keyStorage">\
<spi name="publicKeyStorage">\
<provider name="infinispan" enabled="true">\
<properties>\
<property name="minTimeBetweenRequests" value="10"/>\

View file

@ -19,5 +19,5 @@
/subsystem=keycloak-server/spi=connectionsInfinispan/provider=default/:add(properties={cacheContainer => "java:comp/env/infinispan/Keycloak"},enabled=true)
/subsystem=keycloak-server/spi=jta-lookup/:add(default-provider=${keycloak.jta.lookup.provider:jboss})
/subsystem=keycloak-server/spi=jta-lookup/provider=jboss/:add(enabled=true)
/subsystem=keycloak-server/spi=keyStorage/:add
/subsystem=keycloak-server/spi=keyStorage/provider=infinispan/:add(properties={minTimeBetweenRequests => "10"},enabled=true)
/subsystem=keycloak-server/spi=publicKeyStorage/:add
/subsystem=keycloak-server/spi=publicKeyStorage/provider=infinispan/:add(properties={minTimeBetweenRequests => "10"},enabled=true)