KEYCLOAK-3493 KEYCLOAK-3532 Renamed KeyStorageProvider to PublicKeyStorageProvider
This commit is contained in:
parent
d12f157299
commit
0f9798a10d
18 changed files with 77 additions and 79 deletions
|
@ -40,7 +40,7 @@ public interface InfinispanConnectionProvider extends Provider {
|
||||||
String AUTHORIZATION_CACHE_NAME = "authorization";
|
String AUTHORIZATION_CACHE_NAME = "authorization";
|
||||||
|
|
||||||
String KEYS_CACHE_NAME = "keys";
|
String KEYS_CACHE_NAME = "keys";
|
||||||
int KEYS_CACHE_DEFAULT_MAX = 500;
|
int KEYS_CACHE_DEFAULT_MAX = 1000;
|
||||||
int KEYS_CACHE_MAX_IDLE_SECONDS = 3600;
|
int KEYS_CACHE_MAX_IDLE_SECONDS = 3600;
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -28,16 +28,16 @@ import java.util.concurrent.FutureTask;
|
||||||
import org.infinispan.Cache;
|
import org.infinispan.Cache;
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
import org.keycloak.common.util.Time;
|
import org.keycloak.common.util.Time;
|
||||||
import org.keycloak.keys.KeyLoader;
|
import org.keycloak.keys.PublicKeyLoader;
|
||||||
import org.keycloak.keys.KeyStorageProvider;
|
import org.keycloak.keys.PublicKeyStorageProvider;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
* @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;
|
private final Cache<String, PublicKeysEntry> keys;
|
||||||
|
|
||||||
|
@ -45,7 +45,7 @@ public class InfinispanKeyStorageProvider implements KeyStorageProvider {
|
||||||
|
|
||||||
private final int minTimeBetweenRequests ;
|
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.keys = keys;
|
||||||
this.tasksInProgress = tasksInProgress;
|
this.tasksInProgress = tasksInProgress;
|
||||||
this.minTimeBetweenRequests = minTimeBetweenRequests;
|
this.minTimeBetweenRequests = minTimeBetweenRequests;
|
||||||
|
@ -53,7 +53,7 @@ public class InfinispanKeyStorageProvider implements KeyStorageProvider {
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@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
|
// Check if key is in cache
|
||||||
PublicKeysEntry entry = keys.get(modelKey);
|
PublicKeysEntry entry = keys.get(modelKey);
|
||||||
if (entry != null) {
|
if (entry != null) {
|
||||||
|
@ -127,9 +127,9 @@ public class InfinispanKeyStorageProvider implements KeyStorageProvider {
|
||||||
private class WrapperCallable implements Callable<PublicKeysEntry> {
|
private class WrapperCallable implements Callable<PublicKeysEntry> {
|
||||||
|
|
||||||
private final String modelKey;
|
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.modelKey = modelKey;
|
||||||
this.delegate = delegate;
|
this.delegate = delegate;
|
||||||
}
|
}
|
|
@ -25,17 +25,18 @@ import org.infinispan.Cache;
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
import org.keycloak.Config;
|
import org.keycloak.Config;
|
||||||
import org.keycloak.connections.infinispan.InfinispanConnectionProvider;
|
import org.keycloak.connections.infinispan.InfinispanConnectionProvider;
|
||||||
import org.keycloak.keys.KeyStorageProvider;
|
import org.keycloak.keys.PublicKeyStorageProvider;
|
||||||
import org.keycloak.keys.KeyStorageProviderFactory;
|
import org.keycloak.keys.PublicKeyStorageSpi;
|
||||||
|
import org.keycloak.keys.PublicKeyStorageProviderFactory;
|
||||||
import org.keycloak.models.KeycloakSession;
|
import org.keycloak.models.KeycloakSession;
|
||||||
import org.keycloak.models.KeycloakSessionFactory;
|
import org.keycloak.models.KeycloakSessionFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
* @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";
|
public static final String PROVIDER_ID = "infinispan";
|
||||||
|
|
||||||
|
@ -46,9 +47,9 @@ public class InfinispanKeyStorageProviderFactory implements KeyStorageProviderFa
|
||||||
private int minTimeBetweenRequests;
|
private int minTimeBetweenRequests;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public KeyStorageProvider create(KeycloakSession session) {
|
public PublicKeyStorageProvider create(KeycloakSession session) {
|
||||||
lazyInit(session);
|
lazyInit(session);
|
||||||
return new InfinispanKeyStorageProvider(keysCache, tasksInProgress, minTimeBetweenRequests);
|
return new InfinispanPublicKeyStorageProvider(keysCache, tasksInProgress, minTimeBetweenRequests);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void lazyInit(KeycloakSession session) {
|
private void lazyInit(KeycloakSession session) {
|
|
@ -15,4 +15,4 @@
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
#
|
#
|
||||||
|
|
||||||
org.keycloak.keys.infinispan.InfinispanKeyStorageProviderFactory
|
org.keycloak.keys.infinispan.InfinispanPublicKeyStorageProviderFactory
|
|
@ -39,8 +39,8 @@ import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.keycloak.common.util.Time;
|
import org.keycloak.common.util.Time;
|
||||||
import org.keycloak.connections.infinispan.InfinispanConnectionProvider;
|
import org.keycloak.connections.infinispan.InfinispanConnectionProvider;
|
||||||
import org.keycloak.keys.KeyLoader;
|
import org.keycloak.keys.PublicKeyLoader;
|
||||||
import org.keycloak.keys.infinispan.InfinispanKeyStorageProvider;
|
import org.keycloak.keys.infinispan.InfinispanPublicKeyStorageProvider;
|
||||||
import org.keycloak.keys.infinispan.PublicKeysEntry;
|
import org.keycloak.keys.infinispan.PublicKeysEntry;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -130,14 +130,14 @@ public class InfinispanKeyStorageProviderTest {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
InfinispanKeyStorageProvider provider = new InfinispanKeyStorageProvider(keys, tasksInProgress, minTimeBetweenRequests);
|
InfinispanPublicKeyStorageProvider provider = new InfinispanPublicKeyStorageProvider(keys, tasksInProgress, minTimeBetweenRequests);
|
||||||
provider.getPublicKey(modelKey, "kid1", new SampleLoader(modelKey));
|
provider.getPublicKey(modelKey, "kid1", new SampleLoader(modelKey));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private class SampleLoader implements KeyLoader {
|
private class SampleLoader implements PublicKeyLoader {
|
||||||
|
|
||||||
private final String modelKey;
|
private final String modelKey;
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,7 @@ import java.util.Map;
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||||
*/
|
*/
|
||||||
public interface KeyLoader {
|
public interface PublicKeyLoader {
|
||||||
|
|
||||||
Map<String, PublicKey> loadKeys() throws Exception;
|
Map<String, PublicKey> loadKeys() throws Exception;
|
||||||
|
|
|
@ -24,7 +24,7 @@ import org.keycloak.provider.Provider;
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
* @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
|
* @param loader
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
PublicKey getPublicKey(String modelKey, String kid, KeyLoader loader);
|
PublicKey getPublicKey(String modelKey, String kid, PublicKeyLoader loader);
|
||||||
|
|
||||||
}
|
}
|
|
@ -22,5 +22,5 @@ import org.keycloak.provider.ProviderFactory;
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||||
*/
|
*/
|
||||||
public interface KeyStorageProviderFactory extends ProviderFactory<KeyStorageProvider> {
|
public interface PublicKeyStorageProviderFactory extends ProviderFactory<PublicKeyStorageProvider> {
|
||||||
}
|
}
|
|
@ -24,7 +24,7 @@ import org.keycloak.provider.Spi;
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||||
*/
|
*/
|
||||||
public class KeyStorageSpi implements Spi {
|
public class PublicKeyStorageSpi implements Spi {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isInternal() {
|
public boolean isInternal() {
|
||||||
|
@ -33,16 +33,16 @@ public class KeyStorageSpi implements Spi {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return "keyStorage";
|
return "publicKeyStorage";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Class<? extends Provider> getProviderClass() {
|
public Class<? extends Provider> getProviderClass() {
|
||||||
return KeyStorageProvider.class;
|
return PublicKeyStorageProvider.class;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Class<? extends ProviderFactory> getProviderFactoryClass() {
|
public Class<? extends ProviderFactory> getProviderFactoryClass() {
|
||||||
return KeyStorageProviderFactory.class;
|
return PublicKeyStorageProviderFactory.class;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -65,4 +65,4 @@ org.keycloak.policy.PasswordPolicyManagerSpi
|
||||||
org.keycloak.transaction.TransactionManagerLookupSpi
|
org.keycloak.transaction.TransactionManagerLookupSpi
|
||||||
org.keycloak.credential.hash.PasswordHashSpi
|
org.keycloak.credential.hash.PasswordHashSpi
|
||||||
org.keycloak.credential.CredentialSpi
|
org.keycloak.credential.CredentialSpi
|
||||||
org.keycloak.keys.KeyStorageSpi
|
org.keycloak.keys.PublicKeyStorageSpi
|
||||||
|
|
|
@ -17,27 +17,7 @@
|
||||||
|
|
||||||
package org.keycloak.authentication.authenticators.client;
|
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.security.PublicKey;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
@ -48,6 +28,26 @@ import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
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 .
|
* Client authentication based on JWT signed by client private key .
|
||||||
* See <a href="https://tools.ietf.org/html/rfc7519">specs</a> for more details.
|
* 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) {
|
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) {
|
if (publicKey == null) {
|
||||||
Response challengeResponse = ClientAuthUtil.errorResponse(Response.Status.BAD_REQUEST.getStatusCode(), "unauthorized_client", "Unable to load public key");
|
Response challengeResponse = ClientAuthUtil.errorResponse(Response.Status.BAD_REQUEST.getStatusCode(), "unauthorized_client", "Unable to load public key");
|
||||||
context.failure(AuthenticationFlowError.CLIENT_CREDENTIALS_SETUP_REQUIRED, challengeResponse);
|
context.failure(AuthenticationFlowError.CLIENT_CREDENTIALS_SETUP_REQUIRED, challengeResponse);
|
||||||
|
|
|
@ -32,7 +32,7 @@ import org.keycloak.events.EventType;
|
||||||
import org.keycloak.jose.jws.JWSInput;
|
import org.keycloak.jose.jws.JWSInput;
|
||||||
import org.keycloak.jose.jws.JWSInputException;
|
import org.keycloak.jose.jws.JWSInputException;
|
||||||
import org.keycloak.jose.jws.crypto.RSAProvider;
|
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.ClientSessionModel;
|
||||||
import org.keycloak.models.KeycloakSession;
|
import org.keycloak.models.KeycloakSession;
|
||||||
import org.keycloak.models.RealmModel;
|
import org.keycloak.models.RealmModel;
|
||||||
|
@ -299,7 +299,7 @@ public class OIDCIdentityProvider extends AbstractOAuth2IdentityProvider<OIDCIde
|
||||||
protected boolean verify(JWSInput jws) {
|
protected boolean verify(JWSInput jws) {
|
||||||
if (!getConfig().isValidateSignature()) return true;
|
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);
|
return publicKey != null && RSAProvider.verify(jws, publicKey);
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,7 @@ import org.keycloak.authentication.authenticators.client.JWTClientAuthenticator;
|
||||||
import org.keycloak.jose.jwk.JSONWebKeySet;
|
import org.keycloak.jose.jwk.JSONWebKeySet;
|
||||||
import org.keycloak.jose.jwk.JWK;
|
import org.keycloak.jose.jwk.JWK;
|
||||||
import org.keycloak.jose.jwk.JWKBuilder;
|
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.ClientModel;
|
||||||
import org.keycloak.models.KeycloakSession;
|
import org.keycloak.models.KeycloakSession;
|
||||||
import org.keycloak.models.ModelException;
|
import org.keycloak.models.ModelException;
|
||||||
|
@ -41,7 +41,7 @@ import org.keycloak.util.JWKSUtils;
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
* @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;
|
protected static ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,7 @@ import org.keycloak.common.util.PemUtils;
|
||||||
import org.keycloak.jose.jwk.JSONWebKeySet;
|
import org.keycloak.jose.jwk.JSONWebKeySet;
|
||||||
import org.keycloak.jose.jwk.JWK;
|
import org.keycloak.jose.jwk.JWK;
|
||||||
import org.keycloak.jose.jwk.JWKBuilder;
|
import org.keycloak.jose.jwk.JWKBuilder;
|
||||||
import org.keycloak.keys.KeyLoader;
|
import org.keycloak.keys.PublicKeyLoader;
|
||||||
import org.keycloak.models.KeycloakSession;
|
import org.keycloak.models.KeycloakSession;
|
||||||
import org.keycloak.protocol.oidc.utils.JWKSHttpUtils;
|
import org.keycloak.protocol.oidc.utils.JWKSHttpUtils;
|
||||||
import org.keycloak.services.ServicesLogger;
|
import org.keycloak.services.ServicesLogger;
|
||||||
|
@ -35,14 +35,14 @@ import org.keycloak.util.JWKSUtils;
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
* @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;
|
protected static ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
|
||||||
|
|
||||||
private final KeycloakSession session;
|
private final KeycloakSession session;
|
||||||
private final OIDCIdentityProviderConfig config;
|
private final OIDCIdentityProviderConfig config;
|
||||||
|
|
||||||
public OIDCIdentityProviderLoader(KeycloakSession session, OIDCIdentityProviderConfig config) {
|
public OIDCIdentityProviderPublicKeyLoader(KeycloakSession session, OIDCIdentityProviderConfig config) {
|
||||||
this.session = session;
|
this.session = session;
|
||||||
this.config = config;
|
this.config = config;
|
||||||
}
|
}
|
|
@ -21,7 +21,7 @@ import java.security.PublicKey;
|
||||||
|
|
||||||
import org.keycloak.broker.oidc.OIDCIdentityProviderConfig;
|
import org.keycloak.broker.oidc.OIDCIdentityProviderConfig;
|
||||||
import org.keycloak.jose.jws.JWSInput;
|
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.ClientModel;
|
||||||
import org.keycloak.models.KeycloakSession;
|
import org.keycloak.models.KeycloakSession;
|
||||||
import org.keycloak.models.RealmModel;
|
import org.keycloak.models.RealmModel;
|
||||||
|
@ -29,12 +29,12 @@ import org.keycloak.models.RealmModel;
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
* @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) {
|
public static PublicKey getClientPublicKey(KeycloakSession session, ClientModel client, JWSInput input) {
|
||||||
String kid = input.getHeader().getKeyId();
|
String kid = input.getHeader().getKeyId();
|
||||||
|
|
||||||
KeyStorageProvider keyStorage = session.getProvider(KeyStorageProvider.class);
|
PublicKeyStorageProvider keyStorage = session.getProvider(PublicKeyStorageProvider.class);
|
||||||
|
|
||||||
String modelKey = getModelKey(client);
|
String modelKey = getModelKey(client);
|
||||||
ClientPublicKeyLoader loader = new ClientPublicKeyLoader(session, 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) {
|
public static PublicKey getIdentityProviderPublicKey(KeycloakSession session, RealmModel realm, OIDCIdentityProviderConfig idpConfig, JWSInput input) {
|
||||||
String kid = input.getHeader().getKeyId();
|
String kid = input.getHeader().getKeyId();
|
||||||
|
|
||||||
KeyStorageProvider keyStorage = session.getProvider(KeyStorageProvider.class);
|
PublicKeyStorageProvider keyStorage = session.getProvider(PublicKeyStorageProvider.class);
|
||||||
|
|
||||||
String modelKey = getModelKey(realm, idpConfig);
|
String modelKey = getModelKey(realm, idpConfig);
|
||||||
OIDCIdentityProviderLoader loader = new OIDCIdentityProviderLoader(session, idpConfig);
|
OIDCIdentityProviderPublicKeyLoader loader = new OIDCIdentityProviderPublicKeyLoader(session, idpConfig);
|
||||||
return keyStorage.getPublicKey(modelKey, kid, loader);
|
return keyStorage.getPublicKey(modelKey, kid, loader);
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,24 +17,21 @@
|
||||||
|
|
||||||
package org.keycloak.protocol.oidc.endpoints.request;
|
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.security.PublicKey;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
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
|
* Parse the parameters from OIDC "request" object
|
||||||
*
|
*
|
||||||
|
@ -57,7 +54,7 @@ class AuthzEndpointRequestObjectParser extends AuthzEndpointRequestParser {
|
||||||
if (header.getAlgorithm() == Algorithm.none) {
|
if (header.getAlgorithm() == Algorithm.none) {
|
||||||
this.requestParams = JsonSerialization.readValue(input.getContent(), TypedHashMap.class);
|
this.requestParams = JsonSerialization.readValue(input.getContent(), TypedHashMap.class);
|
||||||
} else if (header.getAlgorithm() == Algorithm.RS256) {
|
} else if (header.getAlgorithm() == Algorithm.RS256) {
|
||||||
PublicKey clientPublicKey = KeyStorageManager.getClientPublicKey(session, client, input);
|
PublicKey clientPublicKey = PublicKeyStorageManager.getClientPublicKey(session, client, input);
|
||||||
if (clientPublicKey == null) {
|
if (clientPublicKey == null) {
|
||||||
throw new RuntimeException("Client public key not found");
|
throw new RuntimeException("Client public key not found");
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,7 +73,7 @@ keycloak.server.subsys.default.config=\
|
||||||
<default-provider>${keycloak.jta.lookup.provider:jboss}</default-provider>\
|
<default-provider>${keycloak.jta.lookup.provider:jboss}</default-provider>\
|
||||||
<provider name="jboss" enabled="true"/>\
|
<provider name="jboss" enabled="true"/>\
|
||||||
</spi>\
|
</spi>\
|
||||||
<spi name="keyStorage">\
|
<spi name="publicKeyStorage">\
|
||||||
<provider name="infinispan" enabled="true">\
|
<provider name="infinispan" enabled="true">\
|
||||||
<properties>\
|
<properties>\
|
||||||
<property name="minTimeBetweenRequests" value="10"/>\
|
<property name="minTimeBetweenRequests" value="10"/>\
|
||||||
|
|
|
@ -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=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/:add(default-provider=${keycloak.jta.lookup.provider:jboss})
|
||||||
/subsystem=keycloak-server/spi=jta-lookup/provider=jboss/:add(enabled=true)
|
/subsystem=keycloak-server/spi=jta-lookup/provider=jboss/:add(enabled=true)
|
||||||
/subsystem=keycloak-server/spi=keyStorage/:add
|
/subsystem=keycloak-server/spi=publicKeyStorage/:add
|
||||||
/subsystem=keycloak-server/spi=keyStorage/provider=infinispan/:add(properties={minTimeBetweenRequests => "10"},enabled=true)
|
/subsystem=keycloak-server/spi=publicKeyStorage/provider=infinispan/:add(properties={minTimeBetweenRequests => "10"},enabled=true)
|
Loading…
Reference in a new issue