diff --git a/core/src/main/java/org/keycloak/AbstractOAuthClient.java b/core/src/main/java/org/keycloak/AbstractOAuthClient.java index 10b7656517..99abe30737 100755 --- a/core/src/main/java/org/keycloak/AbstractOAuthClient.java +++ b/core/src/main/java/org/keycloak/AbstractOAuthClient.java @@ -15,7 +15,6 @@ public class AbstractOAuthClient { public static final String OAUTH_TOKEN_REQUEST_STATE = "OAuth_Token_Request_State"; protected String clientId; protected Map credentials; - protected KeyStore truststore; protected String authUrl; protected String codeUrl; protected String refreshUrl; @@ -46,20 +45,10 @@ public class AbstractOAuthClient { this.credentials = credentials; } - public KeyStore getTruststore() { - return truststore; - } - - public void setTruststore(KeyStore truststore) { - this.truststore = truststore; - } - public String getAuthUrl() { return authUrl; } - - public void setAuthUrl(String authUrl) { this.authUrl = authUrl; } diff --git a/core/src/main/java/org/keycloak/KeycloakSecurityContext.java b/core/src/main/java/org/keycloak/KeycloakSecurityContext.java index 6d838cc7de..bea9d9f375 100755 --- a/core/src/main/java/org/keycloak/KeycloakSecurityContext.java +++ b/core/src/main/java/org/keycloak/KeycloakSecurityContext.java @@ -1,6 +1,5 @@ package org.keycloak; -import org.keycloak.adapters.ResourceMetadata; import org.keycloak.representations.AccessToken; import org.keycloak.representations.IDToken; @@ -15,17 +14,15 @@ public class KeycloakSecurityContext implements Serializable { protected AccessToken token; protected IDToken idToken; protected String idTokenString; - protected transient ResourceMetadata metadata; public KeycloakSecurityContext() { } - public KeycloakSecurityContext(String tokenString, AccessToken token, String idTokenString, IDToken idToken, ResourceMetadata metadata) { + public KeycloakSecurityContext(String tokenString, AccessToken token, String idTokenString, IDToken idToken) { this.tokenString = tokenString; this.token = token; this.idToken = idToken; this.idTokenString = idTokenString; - this.metadata = metadata; } public AccessToken getToken() { @@ -36,14 +33,6 @@ public class KeycloakSecurityContext implements Serializable { return tokenString; } - public ResourceMetadata getMetadata() { - return metadata; - } - - public void setMetadata(ResourceMetadata metadata) { - this.metadata = metadata; - } - public IDToken getIdToken() { return idToken; } diff --git a/core/src/main/java/org/keycloak/adapters/ResourceMetadata.java b/core/src/main/java/org/keycloak/adapters/ResourceMetadata.java deleted file mode 100755 index dd340b492c..0000000000 --- a/core/src/main/java/org/keycloak/adapters/ResourceMetadata.java +++ /dev/null @@ -1,90 +0,0 @@ -package org.keycloak.adapters; - -import java.security.KeyStore; -import java.security.PublicKey; - -/** - * @author Bill Burke - * @version $Revision: 1 $ - */ -public class ResourceMetadata { - protected String realm; - protected String resourceName; - protected KeyStore clientKeystore; - protected String clientKeyPassword; - protected KeyStore truststore; - protected PublicKey realmKey; - protected String scope; - - public String getResourceName() { - return resourceName; - } - - public String getRealm() { - return realm; - } - - /** - * keystore that contains service's private key and certificate. - * Used when making invocations on remote HTTPS endpoints that require client-cert authentication - * - * @return - */ - public KeyStore getClientKeystore() { - return clientKeystore; - } - - public String getClientKeyPassword() { - return clientKeyPassword; - } - - public void setClientKeyPassword(String clientKeyPassword) { - this.clientKeyPassword = clientKeyPassword; - } - - /** - * Truststore to use if this service makes client invocations on remote HTTPS endpoints. - * - * @return - */ - public KeyStore getTruststore() { - return truststore; - } - - /** - * Public key of the realm. Used to verify access tokens - * - * @return - */ - public PublicKey getRealmKey() { - return realmKey; - } - - public void setResourceName(String resourceName) { - this.resourceName = resourceName; - } - - public void setRealm(String realm) { - this.realm = realm; - } - - public void setClientKeystore(KeyStore clientKeystore) { - this.clientKeystore = clientKeystore; - } - - public void setTruststore(KeyStore truststore) { - this.truststore = truststore; - } - - public void setRealmKey(PublicKey realmKey) { - this.realmKey = realmKey; - } - - public String getScope() { - return scope; - } - - public void setScope(String scope) { - this.scope = scope; - } -} diff --git a/core/src/main/java/org/keycloak/util/KeystoreUtil.java b/core/src/main/java/org/keycloak/util/KeystoreUtil.java new file mode 100755 index 0000000000..d318a5fe0e --- /dev/null +++ b/core/src/main/java/org/keycloak/util/KeystoreUtil.java @@ -0,0 +1,21 @@ +package org.keycloak.util; + +import java.io.File; +import java.io.FileInputStream; +import java.security.KeyStore; + +/** + * @author Bill Burke + * @version $Revision: 1 $ + */ +public class KeystoreUtil { + public static KeyStore loadKeyStore(String filename, String password) throws Exception { + KeyStore trustStore = KeyStore.getInstance(KeyStore + .getDefaultType()); + File truststoreFile = new File(filename); + FileInputStream trustStream = new FileInputStream(truststoreFile); + trustStore.load(trustStream, password.toCharArray()); + trustStream.close(); + return trustStore; + } +} diff --git a/examples/demo-template/customer-app-cli/pom.xml b/examples/demo-template/customer-app-cli/pom.xml index 3eaf498283..0daed0f998 100755 --- a/examples/demo-template/customer-app-cli/pom.xml +++ b/examples/demo-template/customer-app-cli/pom.xml @@ -10,7 +10,7 @@ 4.0.0 org.keycloak.example.demo customer-portal-cli-example - war + jar Customer Portal CLI @@ -62,7 +62,10 @@ org.jboss.as.plugins jboss-as-maven-plugin - 7.4.Final + 7.1.1.Final + + true + org.apache.maven.plugins diff --git a/examples/demo-template/customer-app/src/main/java/org/keycloak/example/CustomerDatabaseClient.java b/examples/demo-template/customer-app/src/main/java/org/keycloak/example/CustomerDatabaseClient.java index 10d038398f..9a112dbae5 100755 --- a/examples/demo-template/customer-app/src/main/java/org/keycloak/example/CustomerDatabaseClient.java +++ b/examples/demo-template/customer-app/src/main/java/org/keycloak/example/CustomerDatabaseClient.java @@ -46,8 +46,7 @@ public class CustomerDatabaseClient { KeycloakSecurityContext session = (KeycloakSecurityContext) req.getAttribute(KeycloakSecurityContext.class.getName()); HttpClient client = new HttpClientBuilder() - .trustStore(session.getMetadata().getTruststore()) - .hostnameVerification(HttpClientBuilder.HostnameVerificationPolicy.ANY).build(); + .disableTrustManager().build(); try { HttpGet get = new HttpGet("http://localhost:8080/database/customers"); get.addHeader("Authorization", "Bearer " + session.getTokenString()); diff --git a/examples/demo-template/product-app/src/main/java/org/keycloak/example/oauth/ProductDatabaseClient.java b/examples/demo-template/product-app/src/main/java/org/keycloak/example/oauth/ProductDatabaseClient.java index 749003f8bf..6d70dcf196 100755 --- a/examples/demo-template/product-app/src/main/java/org/keycloak/example/oauth/ProductDatabaseClient.java +++ b/examples/demo-template/product-app/src/main/java/org/keycloak/example/oauth/ProductDatabaseClient.java @@ -37,8 +37,7 @@ public class ProductDatabaseClient public static List getProducts(HttpServletRequest req) throws Failure { KeycloakSecurityContext session = (KeycloakSecurityContext)req.getAttribute(KeycloakSecurityContext.class.getName()); HttpClient client = new HttpClientBuilder() - .trustStore(session.getMetadata().getTruststore()) - .hostnameVerification(HttpClientBuilder.HostnameVerificationPolicy.ANY).build(); + .disableTrustManager().build(); try { HttpGet get = new HttpGet("http://localhost:8080/database/products"); get.addHeader("Authorization", "Bearer " + session.getTokenString()); diff --git a/examples/demo-template/third-party-cdi/src/main/java/org/keycloak/example/oauth/AppContextListener.java b/examples/demo-template/third-party-cdi/src/main/java/org/keycloak/example/oauth/AppContextListener.java index f84019e530..32af874a2c 100755 --- a/examples/demo-template/third-party-cdi/src/main/java/org/keycloak/example/oauth/AppContextListener.java +++ b/examples/demo-template/third-party-cdi/src/main/java/org/keycloak/example/oauth/AppContextListener.java @@ -12,7 +12,7 @@ import javax.servlet.annotation.WebListener; import org.jboss.logging.Logger; import org.keycloak.servlet.ServletOAuthClient; -import org.keycloak.servlet.ServletOAuthClientConfigLoader; +import org.keycloak.servlet.ServletOAuthClientBuilder; /** * @author Marek Posolda @@ -40,12 +40,7 @@ public class AppContextListener implements ServletContextListener { throw new RuntimeException(e); } } - - ServletOAuthClientConfigLoader loader = new ServletOAuthClientConfigLoader(is); - loader.initOAuthClientConfiguration(true); - loader.configureServletOAuthClient(oauthClient); - - oauthClient.start(); + ServletOAuthClientBuilder.build(is, oauthClient); logger.info("OAuth client configured and started"); } diff --git a/examples/demo-template/third-party/src/main/java/org/keycloak/example/oauth/Bootstrap.java b/examples/demo-template/third-party/src/main/java/org/keycloak/example/oauth/Bootstrap.java index 7b8bec2a16..218d1cf28c 100755 --- a/examples/demo-template/third-party/src/main/java/org/keycloak/example/oauth/Bootstrap.java +++ b/examples/demo-template/third-party/src/main/java/org/keycloak/example/oauth/Bootstrap.java @@ -1,7 +1,7 @@ package org.keycloak.example.oauth; import org.keycloak.servlet.ServletOAuthClient; -import org.keycloak.servlet.ServletOAuthClientConfigLoader; +import org.keycloak.servlet.ServletOAuthClientBuilder; import javax.servlet.ServletContext; import javax.servlet.ServletContextEvent; @@ -23,16 +23,6 @@ public class Bootstrap implements ServletContextListener { private ServletOAuthClient client; - private static KeyStore loadKeyStore(String filename, String password) throws Exception { - KeyStore trustStore = KeyStore.getInstance(KeyStore - .getDefaultType()); - File truststoreFile = new File(filename); - FileInputStream trustStream = new FileInputStream(truststoreFile); - trustStore.load(trustStream, password.toCharArray()); - trustStream.close(); - return trustStore; - } - @Override public void contextInitialized(ServletContextEvent sce) { client = new ServletOAuthClient(); @@ -62,8 +52,6 @@ public class Bootstrap implements ServletContextListener { } } - ServletOAuthClientConfigLoader loader = new ServletOAuthClientConfigLoader(is); - loader.initOAuthClientConfiguration(true); - loader.configureServletOAuthClient(client); + client = ServletOAuthClientBuilder.build(is); } } diff --git a/integration/adapter-core/src/main/java/org/keycloak/adapters/HttpClientBuilder.java b/integration/adapter-core/src/main/java/org/keycloak/adapters/HttpClientBuilder.java index 3f1d473c87..1f991e2e60 100755 --- a/integration/adapter-core/src/main/java/org/keycloak/adapters/HttpClientBuilder.java +++ b/integration/adapter-core/src/main/java/org/keycloak/adapters/HttpClientBuilder.java @@ -15,6 +15,9 @@ import org.apache.http.impl.conn.SingleClientConnManager; import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager; import org.apache.http.params.BasicHttpParams; import org.apache.http.params.HttpConnectionParams; +import org.keycloak.representations.adapters.config.AdapterConfig; +import org.keycloak.util.EnvUtil; +import org.keycloak.util.KeystoreUtil; import javax.net.ssl.HostnameVerifier; import javax.net.ssl.SSLContext; @@ -271,4 +274,41 @@ public class HttpClientBuilder { } } + public HttpClient build(AdapterConfig adapterConfig) { + String truststorePath = adapterConfig.getTruststore(); + if (truststorePath != null) { + truststorePath = EnvUtil.replace(truststorePath); + String truststorePassword = adapterConfig.getTruststorePassword(); + try { + this.truststore = KeystoreUtil.loadKeyStore(truststorePath, truststorePassword); + } catch (Exception e) { + throw new RuntimeException("Failed to load truststore", e); + } + } + String clientKeystore = adapterConfig.getClientKeystore(); + if (clientKeystore != null) { + clientKeystore = EnvUtil.replace(clientKeystore); + String clientKeystorePassword = adapterConfig.getClientKeystorePassword(); + try { + KeyStore clientCertKeystore = KeystoreUtil.loadKeyStore(clientKeystore, clientKeystorePassword); + keyStore(clientCertKeystore, clientKeystorePassword); + } catch (Exception e) { + throw new RuntimeException("Failed to load keystore", e); + } + } + int size = 10; + if (adapterConfig.getConnectionPoolSize() > 0) + size = adapterConfig.getConnectionPoolSize(); + HttpClientBuilder.HostnameVerificationPolicy policy = HttpClientBuilder.HostnameVerificationPolicy.WILDCARD; + if (adapterConfig.isAllowAnyHostname()) + policy = HttpClientBuilder.HostnameVerificationPolicy.ANY; + connectionPoolSize(size); + hostnameVerification(policy); + if (adapterConfig.isDisableTrustManager()) { + disableTrustManager(); + } else { + trustStore(truststore); + } + return build(); + } } \ No newline at end of file diff --git a/integration/adapter-core/src/main/java/org/keycloak/adapters/KeycloakDeployment.java b/integration/adapter-core/src/main/java/org/keycloak/adapters/KeycloakDeployment.java new file mode 100755 index 0000000000..ba969bdf9d --- /dev/null +++ b/integration/adapter-core/src/main/java/org/keycloak/adapters/KeycloakDeployment.java @@ -0,0 +1,197 @@ +package org.keycloak.adapters; + +import org.apache.http.client.HttpClient; +import org.keycloak.util.KeycloakUriBuilder; + +import java.security.PublicKey; +import java.util.HashMap; +import java.util.Map; + +/** + * @author Bill Burke + * @version $Revision: 1 $ + */ +public class KeycloakDeployment { + protected String realm; + protected PublicKey realmKey; + protected KeycloakUriBuilder authUrl; + protected String codeUrl; + protected String refreshUrl; + + protected String resourceName; + protected boolean bearerOnly; + protected boolean publicClient; + protected Map resourceCredentials = new HashMap(); + protected HttpClient client; + + protected String scope; + protected boolean sslRequired = true; + protected String stateCookieName = "OAuth_Token_Request_State"; + protected boolean useResourceRoleMappings; + protected boolean cors; + protected int corsMaxAge = -1; + protected String corsAllowedHeaders; + protected String corsAllowedMethods; + protected boolean exposeToken; + protected volatile int notBefore; + + public String getResourceName() { + return resourceName; + } + + public String getRealm() { + return realm; + } + + public void setRealm(String realm) { + this.realm = realm; + } + + public PublicKey getRealmKey() { + return realmKey; + } + + public void setRealmKey(PublicKey realmKey) { + this.realmKey = realmKey; + } + + public KeycloakUriBuilder getAuthUrl() { + return authUrl; + } + + public void setAuthUrl(KeycloakUriBuilder authUrl) { + this.authUrl = authUrl; + } + + public String getCodeUrl() { + return codeUrl; + } + + public void setCodeUrl(String codeUrl) { + this.codeUrl = codeUrl; + } + + public String getRefreshUrl() { + return refreshUrl; + } + + public void setRefreshUrl(String refreshUrl) { + this.refreshUrl = refreshUrl; + } + + public void setResourceName(String resourceName) { + this.resourceName = resourceName; + } + + public boolean isBearerOnly() { + return bearerOnly; + } + + public void setBearerOnly(boolean bearerOnly) { + this.bearerOnly = bearerOnly; + } + + public boolean isPublicClient() { + return publicClient; + } + + public void setPublicClient(boolean publicClient) { + this.publicClient = publicClient; + } + + public Map getResourceCredentials() { + return resourceCredentials; + } + + public void setResourceCredentials(Map resourceCredentials) { + this.resourceCredentials = resourceCredentials; + } + + public HttpClient getClient() { + return client; + } + + public void setClient(HttpClient client) { + this.client = client; + } + + public String getScope() { + return scope; + } + + public void setScope(String scope) { + this.scope = scope; + } + + public boolean isSslRequired() { + return sslRequired; + } + + public void setSslRequired(boolean sslRequired) { + this.sslRequired = sslRequired; + } + + public String getStateCookieName() { + return stateCookieName; + } + + public void setStateCookieName(String stateCookieName) { + this.stateCookieName = stateCookieName; + } + + public boolean isUseResourceRoleMappings() { + return useResourceRoleMappings; + } + + public void setUseResourceRoleMappings(boolean useResourceRoleMappings) { + this.useResourceRoleMappings = useResourceRoleMappings; + } + + public boolean isCors() { + return cors; + } + + public void setCors(boolean cors) { + this.cors = cors; + } + + public int getCorsMaxAge() { + return corsMaxAge; + } + + public void setCorsMaxAge(int corsMaxAge) { + this.corsMaxAge = corsMaxAge; + } + + public String getCorsAllowedHeaders() { + return corsAllowedHeaders; + } + + public void setCorsAllowedHeaders(String corsAllowedHeaders) { + this.corsAllowedHeaders = corsAllowedHeaders; + } + + public String getCorsAllowedMethods() { + return corsAllowedMethods; + } + + public void setCorsAllowedMethods(String corsAllowedMethods) { + this.corsAllowedMethods = corsAllowedMethods; + } + + public boolean isExposeToken() { + return exposeToken; + } + + public void setExposeToken(boolean exposeToken) { + this.exposeToken = exposeToken; + } + + public int getNotBefore() { + return notBefore; + } + + public void setNotBefore(int notBefore) { + this.notBefore = notBefore; + } +} diff --git a/integration/adapter-core/src/main/java/org/keycloak/adapters/KeycloakDeploymentBuilder.java b/integration/adapter-core/src/main/java/org/keycloak/adapters/KeycloakDeploymentBuilder.java new file mode 100755 index 0000000000..5a326b8438 --- /dev/null +++ b/integration/adapter-core/src/main/java/org/keycloak/adapters/KeycloakDeploymentBuilder.java @@ -0,0 +1,95 @@ +package org.keycloak.adapters; + +import org.codehaus.jackson.map.ObjectMapper; +import org.codehaus.jackson.map.annotate.JsonSerialize; +import org.keycloak.ServiceUrlConstants; +import org.keycloak.representations.adapters.config.AdapterConfig; +import org.keycloak.util.EnvUtil; +import org.keycloak.util.KeycloakUriBuilder; +import org.keycloak.util.KeystoreUtil; +import org.keycloak.util.PemUtils; + +import java.io.IOException; +import java.io.InputStream; +import java.security.KeyStore; +import java.security.PublicKey; + +/** + * @author Bill Burke + * @version $Revision: 1 $ + */ +public class KeycloakDeploymentBuilder { + protected KeycloakDeployment deployment = new KeycloakDeployment(); + + protected KeycloakDeploymentBuilder() {} + + + + protected KeycloakDeployment internalBuild(AdapterConfig adapterConfig) { + + if (adapterConfig.getRealm() == null) throw new RuntimeException("Must set 'realm' in config"); + deployment.setRealm(adapterConfig.getRealm()); + String resource = adapterConfig.getResource(); + if (resource == null) throw new RuntimeException("Must set 'resource' in config"); + deployment.setResourceName(resource); + + String realmKeyPem = adapterConfig.getRealmKey(); + if (realmKeyPem == null) { + throw new IllegalArgumentException("You must set the realm-public-key"); + } + + PublicKey realmKey = null; + try { + realmKey = PemUtils.decodePublicKey(realmKeyPem); + } catch (Exception e) { + throw new RuntimeException(e); + } + deployment.setRealmKey(realmKey); + deployment.setSslRequired(!adapterConfig.isSslNotRequired()); + deployment.setResourceCredentials(adapterConfig.getCredentials()); + deployment.setPublicClient(adapterConfig.isPublicClient()); + + if (adapterConfig.isBearerOnly()) { + deployment.setBearerOnly(true); + return deployment; + } + + deployment.setClient(new HttpClientBuilder().build(adapterConfig)); + if (adapterConfig.getAuthServerUrl() == null) { + throw new RuntimeException("You must specify auth-url"); + } + KeycloakUriBuilder serverBuilder = KeycloakUriBuilder.fromUri(adapterConfig.getAuthServerUrl()); + String authUrl = serverBuilder.clone().path(ServiceUrlConstants.TOKEN_SERVICE_LOGIN_PATH).build(adapterConfig.getRealm()).toString(); + String tokenUrl = serverBuilder.clone().path(ServiceUrlConstants.TOKEN_SERVICE_ACCESS_CODE_PATH).build(adapterConfig.getRealm()).toString(); + String refreshUrl = serverBuilder.clone().path(ServiceUrlConstants.TOKEN_SERVICE_REFRESH_PATH).build(adapterConfig.getRealm()).toString(); + + + + deployment.setAuthUrl(KeycloakUriBuilder.fromUri(authUrl).queryParam("client_id", deployment.getResourceName())); + deployment.setCodeUrl(tokenUrl); + deployment.setRefreshUrl(refreshUrl); + + + + return deployment; + } + + public static KeycloakDeployment build(InputStream is) { + ObjectMapper mapper = new ObjectMapper(); + mapper.setSerializationInclusion(JsonSerialize.Inclusion.NON_DEFAULT); + AdapterConfig adapterConfig = null; + try { + adapterConfig = mapper.readValue(is, AdapterConfig.class); + } catch (IOException e) { + throw new RuntimeException(e); + } + return new KeycloakDeploymentBuilder().internalBuild(adapterConfig); + } + + + public static KeycloakDeployment build(AdapterConfig adapterConfig) { + return new KeycloakDeploymentBuilder().internalBuild(adapterConfig); + } + + +} diff --git a/integration/adapter-core/src/main/java/org/keycloak/adapters/RefreshableKeycloakSession.java b/integration/adapter-core/src/main/java/org/keycloak/adapters/RefreshableKeycloakSession.java index 77c6fef6b0..527fa41e98 100755 --- a/integration/adapter-core/src/main/java/org/keycloak/adapters/RefreshableKeycloakSession.java +++ b/integration/adapter-core/src/main/java/org/keycloak/adapters/RefreshableKeycloakSession.java @@ -3,7 +3,6 @@ package org.keycloak.adapters; import org.keycloak.KeycloakSecurityContext; import org.keycloak.RSATokenVerifier; import org.keycloak.VerificationException; -import org.keycloak.adapters.config.RealmConfiguration; import org.keycloak.representations.AccessToken; import org.keycloak.representations.AccessTokenResponse; import org.jboss.logging.Logger; @@ -19,15 +18,15 @@ public class RefreshableKeycloakSession extends KeycloakSecurityContext { protected static Logger log = Logger.getLogger(RefreshableKeycloakSession.class); - protected transient RealmConfiguration realmConfiguration; + protected transient KeycloakDeployment deployment; protected String refreshToken; public RefreshableKeycloakSession() { } - public RefreshableKeycloakSession(String tokenString, AccessToken token, String idTokenString, IDToken idToken, ResourceMetadata metadata, RealmConfiguration realmConfiguration, String refreshToken) { - super(tokenString, token, idTokenString, idToken, metadata); - this.realmConfiguration = realmConfiguration; + public RefreshableKeycloakSession(KeycloakDeployment deployment, String tokenString, AccessToken token, String idTokenString, IDToken idToken, String refreshToken) { + super(tokenString, token, idTokenString, idToken); + this.deployment = deployment; this.refreshToken = refreshToken; } @@ -44,22 +43,22 @@ public class RefreshableKeycloakSession extends KeycloakSecurityContext { } public boolean isActive() { - return this.token.isActive() && this.token.getIssuedAt() > realmConfiguration.getNotBefore(); + return this.token.isActive() && this.token.getIssuedAt() > deployment.getNotBefore(); } - public void setRealmConfiguration(RealmConfiguration realmConfiguration) { - this.realmConfiguration = realmConfiguration; + public void setDeployment(KeycloakDeployment deployment) { + this.deployment = deployment; } public void refreshExpiredToken() { log.info("checking whether to refresh."); if (isActive()) return; - if (this.realmConfiguration == null || refreshToken == null) return; // Might be serialized in HttpSession? + if (this.deployment == null || refreshToken == null) return; // Might be serialized in HttpSession? log.info("Doing refresh"); AccessTokenResponse response = null; try { - response = ServerRequest.invokeRefresh(realmConfiguration, refreshToken); + response = ServerRequest.invokeRefresh(deployment, refreshToken); } catch (IOException e) { log.error("Refresh token failure", e); return; @@ -71,13 +70,13 @@ public class RefreshableKeycloakSession extends KeycloakSecurityContext { String tokenString = response.getToken(); AccessToken token = null; try { - token = RSATokenVerifier.verifyToken(tokenString, realmConfiguration.getMetadata().getRealmKey(), realmConfiguration.getMetadata().getRealm()); + token = RSATokenVerifier.verifyToken(tokenString, deployment.getRealmKey(), deployment.getRealm()); log.info("Token Verification succeeded!"); } catch (VerificationException e) { log.error("failed verification of token"); } - if (response.getNotBeforePolicy() > realmConfiguration.getNotBefore()) { - realmConfiguration.setNotBefore(response.getNotBeforePolicy()); + if (response.getNotBeforePolicy() > deployment.getNotBefore()) { + deployment.setNotBefore(response.getNotBeforePolicy()); } this.token = token; diff --git a/integration/adapter-core/src/main/java/org/keycloak/adapters/ServerRequest.java b/integration/adapter-core/src/main/java/org/keycloak/adapters/ServerRequest.java index 9d10988046..8146896168 100755 --- a/integration/adapter-core/src/main/java/org/keycloak/adapters/ServerRequest.java +++ b/integration/adapter-core/src/main/java/org/keycloak/adapters/ServerRequest.java @@ -7,9 +7,7 @@ import org.apache.http.client.HttpClient; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.methods.HttpPost; import org.apache.http.message.BasicNameValuePair; -import org.keycloak.adapters.config.RealmConfiguration; import org.keycloak.representations.AccessTokenResponse; -import org.keycloak.representations.adapters.config.AdapterConfig; import org.keycloak.representations.idm.CredentialRepresentation; import org.keycloak.util.BasicAuthHelper; import org.keycloak.util.JsonSerialization; @@ -47,13 +45,13 @@ public class ServerRequest { } } - public static AccessTokenResponse invokeAccessCodeToToken(RealmConfiguration config, String code, String redirectUri) throws HttpFailure, IOException { - String codeUrl = config.getCodeUrl(); - String client_id = config.getMetadata().getResourceName(); - Map credentials = config.getResourceCredentials(); - HttpClient client = config.getClient(); + public static AccessTokenResponse invokeAccessCodeToToken(KeycloakDeployment deployment, String code, String redirectUri) throws HttpFailure, IOException { + String codeUrl = deployment.getCodeUrl(); + String client_id = deployment.getResourceName(); + Map credentials = deployment.getResourceCredentials(); + HttpClient client = deployment.getClient(); - return invokeAccessCodeToToken(client, config.isPublicClient(), code, codeUrl, redirectUri, client_id, credentials); + return invokeAccessCodeToToken(client, deployment.isPublicClient(), code, codeUrl, redirectUri, client_id, credentials); } public static AccessTokenResponse invokeAccessCodeToToken(HttpClient client, boolean publicClient, String code, String codeUrl, String redirectUri, String client_id, Map credentials) throws IOException, HttpFailure { @@ -108,12 +106,12 @@ public class ServerRequest { } } - public static AccessTokenResponse invokeRefresh(RealmConfiguration config, String refreshToken) throws IOException, HttpFailure { - String refreshUrl = config.getRefreshUrl(); - String client_id = config.getMetadata().getResourceName(); - Map credentials = config.getResourceCredentials(); - HttpClient client = config.getClient(); - return invokeRefresh(client, config.isPublicClient(), refreshToken, refreshUrl, client_id, credentials); + public static AccessTokenResponse invokeRefresh(KeycloakDeployment deployment, String refreshToken) throws IOException, HttpFailure { + String refreshUrl = deployment.getRefreshUrl(); + String client_id = deployment.getResourceName(); + Map credentials = deployment.getResourceCredentials(); + HttpClient client = deployment.getClient(); + return invokeRefresh(client, deployment.isPublicClient(), refreshToken, refreshUrl, client_id, credentials); } diff --git a/integration/adapter-core/src/main/java/org/keycloak/adapters/config/AdapterConfigLoader.java b/integration/adapter-core/src/main/java/org/keycloak/adapters/config/AdapterConfigLoader.java deleted file mode 100755 index ae1bc64d44..0000000000 --- a/integration/adapter-core/src/main/java/org/keycloak/adapters/config/AdapterConfigLoader.java +++ /dev/null @@ -1,123 +0,0 @@ -package org.keycloak.adapters.config; - -import org.codehaus.jackson.map.ObjectMapper; -import org.codehaus.jackson.map.annotate.JsonSerialize; -import org.keycloak.util.EnvUtil; -import org.keycloak.util.PemUtils; -import org.keycloak.adapters.ResourceMetadata; -import org.keycloak.representations.adapters.config.AdapterConfig; - -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.security.KeyStore; -import java.security.PublicKey; - -/** - * @author Bill Burke - * @version $Revision: 1 $ - */ -public class AdapterConfigLoader { - protected AdapterConfig adapterConfig; - protected ResourceMetadata resourceMetadata; - protected KeyStore clientCertKeystore; - protected KeyStore truststore; - - public static KeyStore loadKeyStore(String filename, String password) throws Exception { - KeyStore trustStore = KeyStore.getInstance(KeyStore - .getDefaultType()); - File truststoreFile = new File(filename); - FileInputStream trustStream = new FileInputStream(truststoreFile); - trustStore.load(trustStream, password.toCharArray()); - trustStream.close(); - return trustStore; - } - - public void init() { - initTruststore(); - initClientKeystore(); - - String realm = adapterConfig.getRealm(); - if (realm == null) throw new RuntimeException("Must set 'realm' in config"); - String resource = adapterConfig.getResource(); - if (resource == null) throw new RuntimeException("Must set 'resource' in config"); - - String realmKeyPem = adapterConfig.getRealmKey(); - if (realmKeyPem == null) { - throw new IllegalArgumentException("You must set the realm-public-key"); - } - - PublicKey realmKey = null; - try { - realmKey = PemUtils.decodePublicKey(realmKeyPem); - } catch (Exception e) { - throw new RuntimeException(e); - } - - resourceMetadata = new ResourceMetadata(); - resourceMetadata.setRealm(realm); - resourceMetadata.setResourceName(resource); - resourceMetadata.setRealmKey(realmKey); - resourceMetadata.setClientKeystore(clientCertKeystore); - String clientKeyPassword = adapterConfig.getClientKeyPassword(); - resourceMetadata.setClientKeyPassword(clientKeyPassword); - resourceMetadata.setTruststore(this.truststore); - - } - - public AdapterConfig getAdapterConfig() { - return adapterConfig; - } - - public ResourceMetadata getResourceMetadata() { - return resourceMetadata; - } - - public KeyStore getClientCertKeystore() { - return clientCertKeystore; - } - - public KeyStore getTruststore() { - return truststore; - } - - protected void loadConfig(InputStream is) { - ObjectMapper mapper = new ObjectMapper(); - mapper.setSerializationInclusion(JsonSerialize.Inclusion.NON_DEFAULT); - adapterConfig = null; - try { - adapterConfig = mapper.readValue(is, AdapterConfig.class); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - - protected void initTruststore() { - String truststorePath = adapterConfig.getTruststore(); - if (truststorePath != null) { - truststorePath = EnvUtil.replace(truststorePath); - String truststorePassword = adapterConfig.getTruststorePassword(); - try { - this.truststore = loadKeyStore(truststorePath, truststorePassword); - } catch (Exception e) { - throw new RuntimeException("Failed to load truststore", e); - } - } - } - - protected void initClientKeystore() { - String clientKeystore = adapterConfig.getClientKeystore(); - if (clientKeystore != null) { - clientKeystore = EnvUtil.replace(clientKeystore); - String clientKeystorePassword = adapterConfig.getClientKeystorePassword(); - clientCertKeystore = null; - try { - clientCertKeystore = loadKeyStore(clientKeystore, clientKeystorePassword); - } catch (Exception e) { - throw new RuntimeException("Failed to load keystore", e); - } - } - } - -} diff --git a/integration/adapter-core/src/main/java/org/keycloak/adapters/config/OAuthClientConfigLoader.java b/integration/adapter-core/src/main/java/org/keycloak/adapters/config/OAuthClientConfigLoader.java deleted file mode 100755 index 5f3add70f8..0000000000 --- a/integration/adapter-core/src/main/java/org/keycloak/adapters/config/OAuthClientConfigLoader.java +++ /dev/null @@ -1,45 +0,0 @@ -package org.keycloak.adapters.config; - -import java.io.InputStream; - -import org.keycloak.AbstractOAuthClient; -import org.keycloak.ServiceUrlConstants; -import org.keycloak.util.KeycloakUriBuilder; - -/** - * @author Marek Posolda - */ -public abstract class OAuthClientConfigLoader extends RealmConfigurationLoader { - - public OAuthClientConfigLoader() { - } - - public OAuthClientConfigLoader(InputStream is) { - super(is); - } - - /** - * For now, configure just things supported by AbstractOAuthClient - */ - public void initOAuthClientConfiguration() { - initTruststore(); - initClientKeystore(); - } - - public void configureOAuthClient(AbstractOAuthClient oauthClient) { - oauthClient.setClientId(adapterConfig.getResource()); - oauthClient.setPublicClient(adapterConfig.isPublicClient()); - oauthClient.setCredentials(adapterConfig.getCredentials()); - if (adapterConfig.getAuthServerUrl() == null) { - throw new RuntimeException("You must specify auth-url"); - } - KeycloakUriBuilder serverBuilder = KeycloakUriBuilder.fromUri(adapterConfig.getAuthServerUrl()); - String authUrl = serverBuilder.clone().path(ServiceUrlConstants.TOKEN_SERVICE_LOGIN_PATH).build(adapterConfig.getRealm()).toString(); - String tokenUrl = serverBuilder.clone().path(ServiceUrlConstants.TOKEN_SERVICE_ACCESS_CODE_PATH).build(adapterConfig.getRealm()).toString(); - String refreshUrl = serverBuilder.clone().path(ServiceUrlConstants.TOKEN_SERVICE_REFRESH_PATH).build(adapterConfig.getRealm()).toString(); - oauthClient.setAuthUrl(authUrl); - oauthClient.setCodeUrl(tokenUrl); - oauthClient.setRefreshUrl(refreshUrl); - oauthClient.setTruststore(truststore); - } -} diff --git a/integration/adapter-core/src/main/java/org/keycloak/adapters/config/RealmConfiguration.java b/integration/adapter-core/src/main/java/org/keycloak/adapters/config/RealmConfiguration.java deleted file mode 100755 index 23afde1940..0000000000 --- a/integration/adapter-core/src/main/java/org/keycloak/adapters/config/RealmConfiguration.java +++ /dev/null @@ -1,109 +0,0 @@ -package org.keycloak.adapters.config; - -import org.apache.http.client.HttpClient; -import org.keycloak.adapters.ResourceMetadata; -import org.keycloak.util.KeycloakUriBuilder; - -import java.util.HashMap; -import java.util.Map; - -/** - * @author Bill Burke - * @version $Revision: 1 $ - */ -public class RealmConfiguration { - protected ResourceMetadata metadata; - protected HttpClient client; - protected KeycloakUriBuilder authUrl; - protected String codeUrl; - protected String refreshUrl; - protected boolean publicClient; - protected Map resourceCredentials = new HashMap(); - protected boolean sslRequired = true; - protected String stateCookieName = "OAuth_Token_Request_State"; - protected volatile int notBefore; - - public RealmConfiguration() { - } - - public ResourceMetadata getMetadata() { - return metadata; - } - - public void setMetadata(ResourceMetadata metadata) { - this.metadata = metadata; - } - - - public boolean isSslRequired() { - return sslRequired; - } - - public void setSslRequired(boolean sslRequired) { - this.sslRequired = sslRequired; - } - - public String getStateCookieName() { - return stateCookieName; - } - - public void setStateCookieName(String stateCookieName) { - this.stateCookieName = stateCookieName; - } - - public HttpClient getClient() { - return client; - } - - public void setClient(HttpClient client) { - this.client = client; - } - - public KeycloakUriBuilder getAuthUrl() { - return authUrl; - } - - public void setAuthUrl(KeycloakUriBuilder authUrl) { - this.authUrl = authUrl; - } - - public String getCodeUrl() { - return codeUrl; - } - - public void setCodeUrl(String codeUrl) { - this.codeUrl = codeUrl; - } - - public String getRefreshUrl() { - return refreshUrl; - } - - public void setRefreshUrl(String refreshUrl) { - this.refreshUrl = refreshUrl; - } - - public Map getResourceCredentials() { - return resourceCredentials; - } - - public void setResourceCredentials(Map resourceCredentials) { - this.resourceCredentials = resourceCredentials; - } - - public int getNotBefore() { - return notBefore; - } - - public void setNotBefore(int notBefore) { - this.notBefore = notBefore; - } - - public boolean isPublicClient() { - return publicClient; - } - - public void setPublicClient(boolean publicClient) { - this.publicClient = publicClient; - } -} diff --git a/integration/adapter-core/src/main/java/org/keycloak/adapters/config/RealmConfigurationLoader.java b/integration/adapter-core/src/main/java/org/keycloak/adapters/config/RealmConfigurationLoader.java deleted file mode 100755 index abedb2badd..0000000000 --- a/integration/adapter-core/src/main/java/org/keycloak/adapters/config/RealmConfigurationLoader.java +++ /dev/null @@ -1,82 +0,0 @@ -package org.keycloak.adapters.config; - -import org.apache.http.client.HttpClient; -import org.keycloak.ServiceUrlConstants; -import org.keycloak.adapters.HttpClientBuilder; -import org.keycloak.util.KeycloakUriBuilder; - -import java.io.InputStream; - -/** - * @author Bill Burke - * @version $Revision: 1 $ - */ -public class RealmConfigurationLoader extends AdapterConfigLoader { - protected HttpClient client; - protected RealmConfiguration realmConfiguration; - - public RealmConfigurationLoader() { - } - - public RealmConfigurationLoader(InputStream is) { - loadConfig(is); - } - - public void init(boolean setupClient) { - init(); - initRealmConfiguration(setupClient); - } - - protected void initRealmConfiguration(boolean setupClient) { - realmConfiguration = new RealmConfiguration(); - realmConfiguration.setMetadata(resourceMetadata); - realmConfiguration.setSslRequired(!adapterConfig.isSslNotRequired()); - realmConfiguration.setResourceCredentials(adapterConfig.getCredentials()); - realmConfiguration.setPublicClient(adapterConfig.isPublicClient()); - if (!setupClient || adapterConfig.isBearerOnly()) return; - initClient(); - if (adapterConfig.getAuthServerUrl() == null) { - throw new RuntimeException("You must specify auth-url"); - } - KeycloakUriBuilder serverBuilder = KeycloakUriBuilder.fromUri(adapterConfig.getAuthServerUrl()); - String authUrl = serverBuilder.clone().path(ServiceUrlConstants.TOKEN_SERVICE_LOGIN_PATH).build(adapterConfig.getRealm()).toString(); - String tokenUrl = serverBuilder.clone().path(ServiceUrlConstants.TOKEN_SERVICE_ACCESS_CODE_PATH).build(adapterConfig.getRealm()).toString(); - String refreshUrl = serverBuilder.clone().path(ServiceUrlConstants.TOKEN_SERVICE_REFRESH_PATH).build(adapterConfig.getRealm()).toString(); - - - HttpClient client = getClient(); - - realmConfiguration.setClient(client); - realmConfiguration.setAuthUrl(KeycloakUriBuilder.fromUri(authUrl).queryParam("client_id", resourceMetadata.getResourceName())); - realmConfiguration.setCodeUrl(tokenUrl); - realmConfiguration.setRefreshUrl(refreshUrl); - } - - protected void initClient() { - int size = 10; - if (adapterConfig.getConnectionPoolSize() > 0) - size = adapterConfig.getConnectionPoolSize(); - HttpClientBuilder.HostnameVerificationPolicy policy = HttpClientBuilder.HostnameVerificationPolicy.WILDCARD; - if (adapterConfig.isAllowAnyHostname()) - policy = HttpClientBuilder.HostnameVerificationPolicy.ANY; - HttpClientBuilder builder = new HttpClientBuilder() - .connectionPoolSize(size) - .hostnameVerification(policy) - .keyStore(clientCertKeystore, adapterConfig.getClientKeyPassword()); - if (adapterConfig.isDisableTrustManager()) { - builder.disableTrustManager(); - } else { - builder.trustStore(truststore); - } - client = builder.build(); - } - - public HttpClient getClient() { - return client; - } - - public RealmConfiguration getRealmConfiguration() { - return realmConfiguration; - } - -} diff --git a/integration/as7-eap-subsystem/src/main/java/org/keycloak/subsystem/extension/SecureDeploymentDefinition.java b/integration/as7-eap-subsystem/src/main/java/org/keycloak/subsystem/extension/SecureDeploymentDefinition.java index 942ddf31c6..f00a22c714 100755 --- a/integration/as7-eap-subsystem/src/main/java/org/keycloak/subsystem/extension/SecureDeploymentDefinition.java +++ b/integration/as7-eap-subsystem/src/main/java/org/keycloak/subsystem/extension/SecureDeploymentDefinition.java @@ -68,8 +68,8 @@ public class SecureDeploymentDefinition extends SimpleResourceDefinition { .setDefaultValue(new ModelNode(false)) .build(); protected static final SimpleAttributeDefinition PUBLIC_CLIENT = - new SimpleAttributeDefinitionBuilder("bearer-only", ModelType.BOOLEAN, true) - .setXmlName("bearer-only") + new SimpleAttributeDefinitionBuilder("public-client", ModelType.BOOLEAN, true) + .setXmlName("public-client") .setAllowExpression(true) .setDefaultValue(new ModelNode(false)) .build(); diff --git a/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/AuthenticatedActionsValve.java b/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/AuthenticatedActionsValve.java index 23d5b068fc..229858cead 100755 --- a/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/AuthenticatedActionsValve.java +++ b/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/AuthenticatedActionsValve.java @@ -9,6 +9,7 @@ import org.apache.catalina.valves.ValveBase; import org.jboss.logging.Logger; import org.keycloak.KeycloakSecurityContext; import org.keycloak.adapters.AdapterConstants; +import org.keycloak.adapters.KeycloakDeployment; import org.keycloak.representations.AccessToken; import org.keycloak.representations.adapters.config.AdapterConfig; @@ -31,10 +32,10 @@ import java.util.Set; */ public class AuthenticatedActionsValve extends ValveBase { private static final Logger log = Logger.getLogger(AuthenticatedActionsValve.class); - protected AdapterConfig config; + protected KeycloakDeployment deployment; - public AuthenticatedActionsValve(AdapterConfig config, Valve next, Container container, ObjectName controller) { - this.config = config; + public AuthenticatedActionsValve(KeycloakDeployment deployment, Valve next, Container container, ObjectName controller) { + this.deployment = deployment; if (next == null) throw new RuntimeException("WTF is next null?!"); setNext(next); setContainer(container); @@ -81,11 +82,11 @@ public class AuthenticatedActionsValve extends ValveBase { response.sendError(HttpServletResponse.SC_UNAUTHORIZED); return true; } - if (!config.isExposeToken()) { + if (!deployment.isExposeToken()) { response.setStatus(HttpServletResponse.SC_OK); return true; } - if (!config.isCors() && request.getHeader("Origin") != null) { + if (!deployment.isCors() && request.getHeader("Origin") != null) { response.setStatus(HttpServletResponse.SC_OK); return true; } @@ -93,7 +94,7 @@ public class AuthenticatedActionsValve extends ValveBase { } protected boolean corsRequest(Request request, Response response, KeycloakSecurityContext session) throws IOException { - if (!config.isCors()) return false; + if (!deployment.isCors()) return false; log.debugv("CORS enabled + request.getRequestURI()"); String origin = request.getHeader("Origin"); log.debugv("Origin: {0} uri: {1}", origin, request.getRequestURI()); diff --git a/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/CatalinaBearerTokenAuthenticator.java b/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/CatalinaBearerTokenAuthenticator.java index 08f52782e9..0b38076562 100755 --- a/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/CatalinaBearerTokenAuthenticator.java +++ b/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/CatalinaBearerTokenAuthenticator.java @@ -5,7 +5,7 @@ import org.jboss.logging.Logger; import org.keycloak.KeycloakSecurityContext; import org.keycloak.KeycloakPrincipal; import org.keycloak.RSATokenVerifier; -import org.keycloak.adapters.ResourceMetadata; +import org.keycloak.adapters.KeycloakDeployment; import org.keycloak.VerificationException; import org.keycloak.representations.AccessToken; @@ -22,24 +22,16 @@ import java.util.Set; * @version $Revision: 1 $ */ public class CatalinaBearerTokenAuthenticator { - protected ResourceMetadata resourceMetadata; protected boolean challenge; protected Logger log = Logger.getLogger(CatalinaBearerTokenAuthenticator.class); protected String tokenString; protected AccessToken token; - private Principal principal; - protected boolean useResourceRoleMappings; - protected int notBefore; + protected Principal principal; + protected KeycloakDeployment deployment; - public CatalinaBearerTokenAuthenticator(ResourceMetadata resourceMetadata, int notBefore, boolean challenge, boolean useResourceRoleMappings) { - this.resourceMetadata = resourceMetadata; + public CatalinaBearerTokenAuthenticator(KeycloakDeployment deployment, boolean challenge) { + this.deployment = deployment; this.challenge = challenge; - this.useResourceRoleMappings = useResourceRoleMappings; - this.notBefore = notBefore; - } - - public ResourceMetadata getResourceMetadata() { - return resourceMetadata; } public String getTokenString() { @@ -73,23 +65,23 @@ public class CatalinaBearerTokenAuthenticator { tokenString = split[1]; try { - token = RSATokenVerifier.verifyToken(tokenString, resourceMetadata.getRealmKey(), resourceMetadata.getRealm()); + token = RSATokenVerifier.verifyToken(tokenString, deployment.getRealmKey(), deployment.getRealm()); } catch (VerificationException e) { log.error("Failed to verify token", e); challengeResponse(response, "invalid_token", e.getMessage()); } - if (token.getIssuedAt() < notBefore) { + if (token.getIssuedAt() < deployment.getNotBefore()) { log.error("Stale token"); challengeResponse(response, "invalid_token", "Stale token"); } boolean verifyCaller = false; Set roles = new HashSet(); - if (useResourceRoleMappings) { - AccessToken.Access access = token.getResourceAccess(resourceMetadata.getResourceName()); + if (deployment.isUseResourceRoleMappings()) { + AccessToken.Access access = token.getResourceAccess(deployment.getResourceName()); if (access != null) roles = access.getRoles(); - verifyCaller = token.isVerifyCaller(resourceMetadata.getResourceName()); + verifyCaller = token.isVerifyCaller(deployment.getResourceName()); } else { verifyCaller = token.isVerifyCaller(); AccessToken.Access access = token.getRealmAccess(); @@ -114,7 +106,7 @@ public class CatalinaBearerTokenAuthenticator { principal = new CatalinaSecurityContextHelper().createPrincipal(request.getContext().getRealm(), skeletonKeyPrincipal, roles); request.setUserPrincipal(principal); request.setAuthType("KEYCLOAK"); - KeycloakSecurityContext skSession = new KeycloakSecurityContext(tokenString, token, null, null, resourceMetadata); + KeycloakSecurityContext skSession = new KeycloakSecurityContext(tokenString, token, null, null); request.setAttribute(KeycloakSecurityContext.class.getName(), skSession); return true; @@ -123,7 +115,7 @@ public class CatalinaBearerTokenAuthenticator { protected void challengeResponse(HttpServletResponse response, String error, String description) throws LoginException { StringBuilder header = new StringBuilder("Bearer realm=\""); - header.append(resourceMetadata.getRealm()).append("\""); + header.append(deployment.getRealm()).append("\""); if (error != null) { header.append(", error=\"").append(error).append("\""); } diff --git a/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/CorsPreflightChecker.java b/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/CorsPreflightChecker.java index 80dfaa4615..20de1bd6e2 100755 --- a/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/CorsPreflightChecker.java +++ b/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/CorsPreflightChecker.java @@ -3,6 +3,7 @@ package org.keycloak.adapters.as7; import org.apache.catalina.connector.Request; import org.apache.catalina.connector.Response; import org.jboss.logging.Logger; +import org.keycloak.adapters.KeycloakDeployment; import org.keycloak.representations.adapters.config.AdapterConfig; import javax.servlet.http.HttpServletResponse; @@ -13,10 +14,10 @@ import javax.servlet.http.HttpServletResponse; */ public class CorsPreflightChecker { private static final Logger log = Logger.getLogger(CorsPreflightChecker.class); - protected AdapterConfig config; + protected KeycloakDeployment deployment; - public CorsPreflightChecker(AdapterConfig config) { - this.config = config; + public CorsPreflightChecker(KeycloakDeployment deployment) { + this.deployment = deployment; } public boolean checkCorsPreflight(Request request, Response response) { @@ -37,20 +38,20 @@ public class CorsPreflightChecker { response.setHeader("Access-Control-Allow-Credentials", "true"); String requestMethods = request.getHeader("Access-Control-Request-Method"); if (requestMethods != null) { - if (config.getCorsAllowedMethods() != null) { - requestMethods = config.getCorsAllowedMethods(); + if (deployment.getCorsAllowedMethods() != null) { + requestMethods = deployment.getCorsAllowedMethods(); } response.setHeader("Access-Control-Allow-Methods", requestMethods); } String allowHeaders = request.getHeader("Access-Control-Request-Headers"); if (allowHeaders != null) { - if (config.getCorsAllowedHeaders() != null) { - allowHeaders = config.getCorsAllowedHeaders(); + if (deployment.getCorsAllowedHeaders() != null) { + allowHeaders = deployment.getCorsAllowedHeaders(); } response.setHeader("Access-Control-Allow-Headers", allowHeaders); } - if (config.getCorsMaxAge() > -1) { - response.setHeader("Access-Control-Max-Age", Integer.toString(config.getCorsMaxAge())); + if (deployment.getCorsMaxAge() > -1) { + response.setHeader("Access-Control-Max-Age", Integer.toString(deployment.getCorsMaxAge())); } return true; } diff --git a/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/KeycloakAuthenticatorValve.java b/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/KeycloakAuthenticatorValve.java index 90c8d9f85f..ab380aad3f 100755 --- a/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/KeycloakAuthenticatorValve.java +++ b/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/KeycloakAuthenticatorValve.java @@ -1,5 +1,6 @@ package org.keycloak.adapters.as7; +import org.apache.catalina.Context; import org.apache.catalina.Lifecycle; import org.apache.catalina.LifecycleEvent; import org.apache.catalina.LifecycleException; @@ -16,9 +17,9 @@ import org.jboss.logging.Logger; import org.keycloak.KeycloakSecurityContext; import org.keycloak.KeycloakPrincipal; import org.keycloak.adapters.AdapterConstants; +import org.keycloak.adapters.KeycloakDeployment; +import org.keycloak.adapters.KeycloakDeploymentBuilder; import org.keycloak.adapters.RefreshableKeycloakSession; -import org.keycloak.adapters.ResourceMetadata; -import org.keycloak.adapters.as7.config.CatalinaAdapterConfigLoader; import org.keycloak.representations.AccessToken; import org.keycloak.representations.adapters.action.AdminAction; import org.keycloak.representations.adapters.action.PushNotBeforeAction; @@ -26,9 +27,6 @@ import org.keycloak.representations.adapters.action.SessionStats; import org.keycloak.representations.adapters.action.SessionStatsAction; import org.keycloak.representations.adapters.action.UserStats; import org.keycloak.representations.adapters.action.UserStatsAction; -import org.keycloak.representations.adapters.config.AdapterConfig; -import org.keycloak.adapters.config.RealmConfiguration; -import org.keycloak.adapters.config.RealmConfigurationLoader; import org.keycloak.jose.jws.JWSInput; import org.keycloak.jose.jws.crypto.RSAProvider; import org.keycloak.representations.adapters.action.LogoutAction; @@ -36,10 +34,15 @@ import org.keycloak.util.JsonSerialization; import org.keycloak.util.StreamUtil; import javax.security.auth.login.LoginException; +import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import java.io.ByteArrayInputStream; +import java.io.FileInputStream; +import java.io.FileNotFoundException; import java.io.IOException; +import java.io.InputStream; import java.util.HashMap; import java.util.HashSet; import java.util.Map; @@ -55,11 +58,9 @@ import java.util.Set; * @version $Revision: 1 $ */ public class KeycloakAuthenticatorValve extends FormAuthenticator implements LifecycleListener { - protected RealmConfiguration realmConfiguration; private static final Logger log = Logger.getLogger(KeycloakAuthenticatorValve.class); protected UserSessionManagement userSessionManagement = new UserSessionManagement(); - protected AdapterConfig adapterConfig; - protected ResourceMetadata resourceMetadata; + protected KeycloakDeployment deployment; @Override @@ -75,21 +76,44 @@ public class KeycloakAuthenticatorValve extends FormAuthenticator implements Lif if (event.getType() == Lifecycle.AFTER_START_EVENT) init(); } - protected void init() { - RealmConfigurationLoader configLoader = new CatalinaAdapterConfigLoader(context); - configLoader.init(true); - resourceMetadata = configLoader.getResourceMetadata(); - adapterConfig = configLoader.getAdapterConfig(); + private static InputStream getJSONFromServletContext(ServletContext servletContext) { + String json = servletContext.getInitParameter(AdapterConstants.AUTH_DATA_PARAM_NAME); + if (json == null) { + return null; + } + log.info("**** using " + AdapterConstants.AUTH_DATA_PARAM_NAME); + log.info(json); + return new ByteArrayInputStream(json.getBytes()); + } + private static InputStream getConfigInputStream(Context context) { + InputStream is = getJSONFromServletContext(context.getServletContext()); + if (is == null) { + String path = context.getServletContext().getInitParameter("keycloak.config.file"); + if (path == null) { + log.info("**** using /WEB-INF/keycloak.json"); + is = context.getServletContext().getResourceAsStream("/WEB-INF/keycloak.json"); + } else { + try { + is = new FileInputStream(path); + } catch (FileNotFoundException e) { + throw new RuntimeException(e); + } + } + } + return is; + } - realmConfiguration = configLoader.getRealmConfiguration(); - AuthenticatedActionsValve actions = new AuthenticatedActionsValve(adapterConfig, getNext(), getContainer(), getController()); + + protected void init() { + this.deployment = KeycloakDeploymentBuilder.build(getConfigInputStream(context)); + AuthenticatedActionsValve actions = new AuthenticatedActionsValve(deployment, getNext(), getContainer(), getController()); setNext(actions); } @Override public void invoke(Request request, Response response) throws IOException, ServletException { try { - if (adapterConfig.isCors() && new CorsPreflightChecker(adapterConfig).checkCorsPreflight(request, response)) { + if (deployment.isCors() && new CorsPreflightChecker(deployment).checkCorsPreflight(request, response)) { return; } String requestURI = request.getDecodedRequestURI(); @@ -148,7 +172,7 @@ public class KeycloakAuthenticatorValve extends FormAuthenticator implements Lif } // initiate or continue oauth2 protocol - if (!adapterConfig.isBearerOnly()) oauth(request, response); + if (!deployment.isBearerOnly()) oauth(request, response); } catch (LoginException e) { } return false; @@ -165,7 +189,7 @@ public class KeycloakAuthenticatorValve extends FormAuthenticator implements Lif JWSInput input = new JWSInput(token); boolean verified = false; try { - verified = RSAProvider.verify(input, realmConfiguration.getMetadata().getRealmKey()); + verified = RSAProvider.verify(input, deployment.getRealmKey()); } catch (Exception ignore) { } if (!verified) { @@ -188,7 +212,7 @@ public class KeycloakAuthenticatorValve extends FormAuthenticator implements Lif response.sendError(HttpServletResponse.SC_BAD_REQUEST, "Expired token"); return false; } - if (!resourceMetadata.getResourceName().equals(action.getResource())) { + if (!deployment.getResourceName().equals(action.getResource())) { log.warn("Resource name does not match"); response.sendError(HttpServletResponse.SC_BAD_REQUEST, "Resource name does not match"); return false; @@ -203,7 +227,7 @@ public class KeycloakAuthenticatorValve extends FormAuthenticator implements Lif if (!validateAction(response, action)) { return; } - realmConfiguration.setNotBefore(action.getNotBefore()); + deployment.setNotBefore(action.getNotBefore()); response.setStatus(HttpServletResponse.SC_NO_CONTENT); } @@ -280,8 +304,8 @@ public class KeycloakAuthenticatorValve extends FormAuthenticator implements Lif } protected boolean bearer(boolean challenge, Request request, HttpServletResponse response) throws LoginException, IOException { - boolean useResourceRoleMappings = adapterConfig.isUseResourceRoleMappings(); - CatalinaBearerTokenAuthenticator bearer = new CatalinaBearerTokenAuthenticator(resourceMetadata, realmConfiguration.getNotBefore(), challenge, useResourceRoleMappings); + boolean useResourceRoleMappings = deployment.isUseResourceRoleMappings(); + CatalinaBearerTokenAuthenticator bearer = new CatalinaBearerTokenAuthenticator(deployment, challenge); if (bearer.login(request, response)) { return true; } @@ -298,8 +322,7 @@ public class KeycloakAuthenticatorValve extends FormAuthenticator implements Lif RefreshableKeycloakSession session = (RefreshableKeycloakSession)request.getSessionInternal().getNote(KeycloakSecurityContext.class.getName()); if (session == null) return; // just in case session got serialized - session.setRealmConfiguration(realmConfiguration); - session.setMetadata(resourceMetadata); + session.setDeployment(deployment); if (session.isActive()) return; // FYI: A refresh requires same scope, so same roles will be set. Otherwise, refresh will fail and token will @@ -335,7 +358,7 @@ public class KeycloakAuthenticatorValve extends FormAuthenticator implements Lif * This method always set the HTTP response, so do not continue after invoking */ protected void oauth(Request request, HttpServletResponse response) throws IOException { - ServletOAuthLogin oauth = new ServletOAuthLogin(realmConfiguration, request, response, request.getConnector().getRedirectPort()); + ServletOAuthLogin oauth = new ServletOAuthLogin(deployment, request, response, request.getConnector().getRedirectPort()); String code = oauth.getCode(); if (code == null) { String error = oauth.getError(); @@ -352,8 +375,8 @@ public class KeycloakAuthenticatorValve extends FormAuthenticator implements Lif AccessToken token = oauth.getToken(); Set roles = new HashSet(); - if (adapterConfig.isUseResourceRoleMappings()) { - AccessToken.Access access = token.getResourceAccess(resourceMetadata.getResourceName()); + if (deployment.isUseResourceRoleMappings()) { + AccessToken.Access access = token.getResourceAccess(deployment.getResourceName()); if (access != null) roles.addAll(access.getRoles()); } else { AccessToken.Access access = token.getRealmAccess(); @@ -364,7 +387,7 @@ public class KeycloakAuthenticatorValve extends FormAuthenticator implements Lif Session session = request.getSessionInternal(true); session.setPrincipal(principal); session.setAuthType("OAUTH"); - KeycloakSecurityContext skSession = new RefreshableKeycloakSession(oauth.getTokenString(), oauth.getToken(), oauth.getIdTokenString(), oauth.getIdToken(), resourceMetadata, realmConfiguration, oauth.getRefreshToken()); + KeycloakSecurityContext skSession = new RefreshableKeycloakSession(deployment, oauth.getTokenString(), oauth.getToken(), oauth.getIdTokenString(), oauth.getIdToken(), oauth.getRefreshToken()); session.setNote(KeycloakSecurityContext.class.getName(), skSession); String username = token.getSubject(); diff --git a/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/ServletOAuthLogin.java b/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/ServletOAuthLogin.java index 7834b44bfa..a0df8e2d65 100755 --- a/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/ServletOAuthLogin.java +++ b/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/ServletOAuthLogin.java @@ -3,8 +3,8 @@ package org.keycloak.adapters.as7; import org.jboss.logging.Logger; import org.keycloak.RSATokenVerifier; import org.keycloak.VerificationException; +import org.keycloak.adapters.KeycloakDeployment; import org.keycloak.adapters.ServerRequest; -import org.keycloak.adapters.config.RealmConfiguration; import org.keycloak.jose.jws.JWSInput; import org.keycloak.representations.AccessToken; import org.keycloak.representations.AccessTokenResponse; @@ -27,7 +27,7 @@ public class ServletOAuthLogin { protected HttpServletRequest request; protected HttpServletResponse response; protected boolean codePresent; - protected RealmConfiguration realmInfo; + protected KeycloakDeployment deployment; protected int redirectPort; protected String tokenString; protected String idTokenString; @@ -35,10 +35,10 @@ public class ServletOAuthLogin { protected AccessToken token; protected String refreshToken; - public ServletOAuthLogin(RealmConfiguration realmInfo, HttpServletRequest request, HttpServletResponse response, int redirectPort) { + public ServletOAuthLogin(KeycloakDeployment deployment, HttpServletRequest request, HttpServletResponse response, int redirectPort) { this.request = request; this.response = response; - this.realmInfo = realmInfo; + this.deployment = deployment; this.redirectPort = redirectPort; } @@ -62,10 +62,6 @@ public class ServletOAuthLogin { return idToken; } - public RealmConfiguration getRealmInfo() { - return realmInfo; - } - protected String getDefaultCookiePath() { String path = request.getContextPath(); if ("".equals(path) || path == null) path = "/"; @@ -145,7 +141,7 @@ public class ServletOAuthLogin { protected String getRedirectUri(String state) { String url = getRequestUrl(); - if (!isRequestSecure() && realmInfo.isSslRequired()) { + if (!isRequestSecure() && deployment.isSslRequired()) { int port = redirectPort; if (port < 0) { // disabled? @@ -155,13 +151,13 @@ public class ServletOAuthLogin { if (port != 443) secureUrl.port(port); url = secureUrl.build().toString(); } - KeycloakUriBuilder uriBuilder = realmInfo.getAuthUrl().clone() - .queryParam("client_id", realmInfo.getMetadata().getResourceName()) + KeycloakUriBuilder uriBuilder = deployment.getAuthUrl().clone() + .queryParam("client_id", deployment.getResourceName()) .queryParam("redirect_uri", url) .queryParam("state", state) .queryParam("login", "true"); - if (realmInfo.getMetadata().getScope() != null) { - uriBuilder.queryParam("scope", realmInfo.getMetadata().getScope()); + if (deployment.getScope() != null) { + uriBuilder.queryParam("scope", deployment.getScope()); } return uriBuilder.build().toString(); } @@ -179,12 +175,12 @@ public class ServletOAuthLogin { sendError(HttpServletResponse.SC_FORBIDDEN); return; } - setCookie(realmInfo.getStateCookieName(), state, null, getDefaultCookiePath(), realmInfo.isSslRequired()); + setCookie(deployment.getStateCookieName(), state, null, getDefaultCookiePath(), deployment.isSslRequired()); sendRedirect(redirect); } public boolean checkStateCookie() { - Cookie stateCookie = getCookie(realmInfo.getStateCookieName()); + Cookie stateCookie = getCookie(deployment.getStateCookieName()); if (stateCookie == null) { sendError(HttpServletResponse.SC_BAD_REQUEST); @@ -193,12 +189,12 @@ public class ServletOAuthLogin { } // reset the cookie log.debug("** reseting application state cookie"); - Cookie reset = new Cookie(realmInfo.getStateCookieName(), ""); + Cookie reset = new Cookie(deployment.getStateCookieName(), ""); reset.setPath(getDefaultCookiePath()); reset.setMaxAge(0); response.addCookie(reset); - String stateCookieValue = getCookieValue(realmInfo.getStateCookieName()); + String stateCookieValue = getCookieValue(deployment.getStateCookieName()); // its ok to call request.getParameter() because this should be a redirect String state = request.getParameter("state"); if (state == null) { @@ -231,7 +227,7 @@ public class ServletOAuthLogin { */ public boolean resolveCode(String code) { // abort if not HTTPS - if (realmInfo.isSslRequired() && !isRequestSecure()) { + if (deployment.isSslRequired() && !isRequestSecure()) { log.error("SSL is required"); sendError(HttpServletResponse.SC_FORBIDDEN); return false; @@ -242,7 +238,7 @@ public class ServletOAuthLogin { String redirectUri = stripOauthParametersFromRedirect(); AccessTokenResponse tokenResponse = null; try { - tokenResponse = ServerRequest.invokeAccessCodeToToken(realmInfo, code, redirectUri); + tokenResponse = ServerRequest.invokeAccessCodeToToken(deployment, code, redirectUri); } catch (ServerRequest.HttpFailure failure) { log.error("failed to turn code into token"); log.error("status from server: " + failure.getStatus()); @@ -260,7 +256,7 @@ public class ServletOAuthLogin { tokenString = tokenResponse.getToken(); idTokenString = tokenResponse.getIdToken(); try { - token = RSATokenVerifier.verifyToken(tokenString, realmInfo.getMetadata().getRealmKey(), realmInfo.getMetadata().getRealm()); + token = RSATokenVerifier.verifyToken(tokenString, deployment.getRealmKey(), deployment.getRealm()); if (idTokenString != null) { JWSInput input = new JWSInput(idTokenString); try { @@ -275,10 +271,10 @@ public class ServletOAuthLogin { sendError(HttpServletResponse.SC_FORBIDDEN); return false; } - if (tokenResponse.getNotBeforePolicy() > realmInfo.getNotBefore()) { - realmInfo.setNotBefore(tokenResponse.getNotBeforePolicy()); + if (tokenResponse.getNotBeforePolicy() > deployment.getNotBefore()) { + deployment.setNotBefore(tokenResponse.getNotBeforePolicy()); } - if (token.getIssuedAt() < realmInfo.getNotBefore()) { + if (token.getIssuedAt() < deployment.getNotBefore()) { log.error("Stale token"); sendError(HttpServletResponse.SC_FORBIDDEN); return false; diff --git a/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/config/CatalinaAdapterConfigLoader.java b/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/config/CatalinaAdapterConfigLoader.java deleted file mode 100755 index f1abb9ca54..0000000000 --- a/integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/config/CatalinaAdapterConfigLoader.java +++ /dev/null @@ -1,47 +0,0 @@ -package org.keycloak.adapters.as7.config; - -import org.apache.catalina.Context; -import org.jboss.logging.Logger; -import org.keycloak.adapters.AdapterConstants; -import org.keycloak.adapters.config.RealmConfigurationLoader; - -import javax.servlet.ServletContext; -import java.io.ByteArrayInputStream; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.InputStream; - -public class CatalinaAdapterConfigLoader extends RealmConfigurationLoader { - private static final Logger log = Logger.getLogger(CatalinaAdapterConfigLoader.class); - - private InputStream getJSONFromServletContext(ServletContext servletContext) { - String json = servletContext.getInitParameter(AdapterConstants.AUTH_DATA_PARAM_NAME); - if (json == null) { - return null; - } - log.info("**** using " + AdapterConstants.AUTH_DATA_PARAM_NAME); - log.info(json); - return new ByteArrayInputStream(json.getBytes()); - } - - public CatalinaAdapterConfigLoader(Context context) { - log.info("******* Loading adapter config."); - InputStream is = getJSONFromServletContext(context.getServletContext()); - if (is == null) { - String path = context.getServletContext().getInitParameter("keycloak.config.file"); - if (path == null) { - log.info("**** using /WEB-INF/keycloak.json"); - is = context.getServletContext().getResourceAsStream("/WEB-INF/keycloak.json"); - } else { - try { - is = new FileInputStream(path); - } catch (FileNotFoundException e) { - throw new RuntimeException(e); - } - } - } - if (is == null) throw new RuntimeException("Could not find keycloak config."); - loadConfig(is); - } - -} \ No newline at end of file diff --git a/integration/jaxrs-oauth-client/src/main/java/org/keycloak/jaxrs/JaxrsBearerTokenFilter.java b/integration/jaxrs-oauth-client/src/main/java/org/keycloak/jaxrs/JaxrsBearerTokenFilter.java index 5a2ba59938..6335762e3b 100755 --- a/integration/jaxrs-oauth-client/src/main/java/org/keycloak/jaxrs/JaxrsBearerTokenFilter.java +++ b/integration/jaxrs-oauth-client/src/main/java/org/keycloak/jaxrs/JaxrsBearerTokenFilter.java @@ -5,7 +5,6 @@ import org.jboss.resteasy.spi.ResteasyProviderFactory; import org.keycloak.KeycloakSecurityContext; import org.keycloak.KeycloakPrincipal; import org.keycloak.RSATokenVerifier; -import org.keycloak.adapters.ResourceMetadata; import org.keycloak.VerificationException; import org.keycloak.representations.AccessToken; @@ -19,6 +18,7 @@ import javax.ws.rs.core.Response; import javax.ws.rs.core.SecurityContext; import java.io.IOException; import java.security.Principal; +import java.security.PublicKey; /** * @author Bill Burke @@ -26,16 +26,20 @@ import java.security.Principal; */ @Priority(Priorities.AUTHENTICATION) public class JaxrsBearerTokenFilter implements ContainerRequestFilter { - protected ResourceMetadata resourceMetadata; private static Logger log = Logger.getLogger(JaxrsBearerTokenFilter.class); + protected String realm; + protected PublicKey realmPublicKey; + protected String resourceName; - public JaxrsBearerTokenFilter(ResourceMetadata resourceMetadata) { - this.resourceMetadata = resourceMetadata; + public JaxrsBearerTokenFilter(String realm, PublicKey realmPublicKey, String resourceName) { + this.realm = realm; + this.realmPublicKey = realmPublicKey; + this.resourceName = resourceName; } protected void challengeResponse(ContainerRequestContext request, String error, String description) { StringBuilder header = new StringBuilder("Bearer realm=\""); - header.append(resourceMetadata.getRealm()).append("\""); + header.append(realm).append("\""); if (error != null) { header.append(", error=\"").append(error).append("\""); } @@ -66,16 +70,16 @@ public class JaxrsBearerTokenFilter implements ContainerRequestFilter { try { - AccessToken token = RSATokenVerifier.verifyToken(tokenString, resourceMetadata.getRealmKey(), resourceMetadata.getRealm()); - KeycloakSecurityContext skSession = new KeycloakSecurityContext(tokenString, token, null, null, resourceMetadata); + AccessToken token = RSATokenVerifier.verifyToken(tokenString, realmPublicKey, realm); + KeycloakSecurityContext skSession = new KeycloakSecurityContext(tokenString, token, null, null); ResteasyProviderFactory.pushContext(KeycloakSecurityContext.class, skSession); String callerPrincipal = securityContext.getUserPrincipal() != null ? securityContext.getUserPrincipal().getName() : null; final KeycloakPrincipal principal = new KeycloakPrincipal(token.getSubject(), callerPrincipal); final boolean isSecure = securityContext.isSecure(); final AccessToken.Access access; - if (resourceMetadata.getResourceName() != null) { - access = token.getResourceAccess(resourceMetadata.getResourceName()); + if (resourceName != null) { + access = token.getResourceAccess(resourceName); } else { access = token.getRealmAccess(); } diff --git a/integration/jaxrs-oauth-client/src/main/java/org/keycloak/jaxrs/JaxrsOAuthClient.java b/integration/jaxrs-oauth-client/src/main/java/org/keycloak/jaxrs/JaxrsOAuthClient.java index a090da7a74..65c56e9ac5 100755 --- a/integration/jaxrs-oauth-client/src/main/java/org/keycloak/jaxrs/JaxrsOAuthClient.java +++ b/integration/jaxrs-oauth-client/src/main/java/org/keycloak/jaxrs/JaxrsOAuthClient.java @@ -33,22 +33,10 @@ public class JaxrsOAuthClient extends AbstractOAuthClient { protected Client client; /** - * Creates a Client for obtaining access token from code - */ - public void start() { - if (client == null) { - client = new ResteasyClientBuilder().trustStore(truststore) - .hostnameVerification(ResteasyClientBuilder.HostnameVerificationPolicy.ANY) - .connectionPoolSize(10) - .build(); - } - } - - /** - * closes cllient + * closes client */ public void stop() { - client.close(); + if (client != null) client.close(); } public Client getClient() { return client; diff --git a/integration/servlet-oauth-client/pom.xml b/integration/servlet-oauth-client/pom.xml index 49009a011a..9db95f9444 100755 --- a/integration/servlet-oauth-client/pom.xml +++ b/integration/servlet-oauth-client/pom.xml @@ -36,14 +36,6 @@ ${keycloak.apache.httpcomponents.version} provided - - org.codehaus.jackson - jackson-core-asl - - - org.codehaus.jackson - jackson-mapper-asl - net.iharder base64 diff --git a/integration/servlet-oauth-client/src/main/java/org/keycloak/servlet/ServletOAuthClient.java b/integration/servlet-oauth-client/src/main/java/org/keycloak/servlet/ServletOAuthClient.java index df0d80973d..88bebd7997 100755 --- a/integration/servlet-oauth-client/src/main/java/org/keycloak/servlet/ServletOAuthClient.java +++ b/integration/servlet-oauth-client/src/main/java/org/keycloak/servlet/ServletOAuthClient.java @@ -22,20 +22,11 @@ import java.net.URI; public class ServletOAuthClient extends AbstractOAuthClient { protected HttpClient client; - /** - * Creates a Client for obtaining access token from code - */ public void start() { - if (client == null) { - client = new HttpClientBuilder().trustStore(truststore) - .hostnameVerification(HttpClientBuilder.HostnameVerificationPolicy.ANY) - .connectionPoolSize(10) - .build(); - } } /** - * closes cllient + * closes client */ public void stop() { client.getConnectionManager().shutdown(); diff --git a/integration/servlet-oauth-client/src/main/java/org/keycloak/servlet/ServletOAuthClientBuilder.java b/integration/servlet-oauth-client/src/main/java/org/keycloak/servlet/ServletOAuthClientBuilder.java new file mode 100755 index 0000000000..54095beea8 --- /dev/null +++ b/integration/servlet-oauth-client/src/main/java/org/keycloak/servlet/ServletOAuthClientBuilder.java @@ -0,0 +1,60 @@ +package org.keycloak.servlet; + +import org.apache.http.client.HttpClient; +import org.keycloak.ServiceUrlConstants; +import org.keycloak.adapters.HttpClientBuilder; +import org.keycloak.representations.adapters.config.AdapterConfig; +import org.keycloak.util.JsonSerialization; +import org.keycloak.util.KeycloakUriBuilder; + +import java.io.IOException; +import java.io.InputStream; + +/** + * @author Bill Burke + * @version $Revision: 1 $ + */ +public class ServletOAuthClientBuilder { + + public static ServletOAuthClient build(InputStream is) { + AdapterConfig adapterConfig = getAdapterConfig(is); + return build(adapterConfig); + } + + private static AdapterConfig getAdapterConfig(InputStream is) { + try { + return JsonSerialization.readValue(is, AdapterConfig.class); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + public static ServletOAuthClient build(AdapterConfig adapterConfig) { + ServletOAuthClient oauthClient = new ServletOAuthClient(); + build(adapterConfig, oauthClient); + return oauthClient; + } + + public static void build(InputStream is, ServletOAuthClient oauthClient) { + build(getAdapterConfig(is), oauthClient); + } + + + public static void build(AdapterConfig adapterConfig, ServletOAuthClient oauthClient) { + HttpClient client = new HttpClientBuilder().build(adapterConfig); + oauthClient.setClient(client); + oauthClient.setClientId(adapterConfig.getResource()); + oauthClient.setPublicClient(adapterConfig.isPublicClient()); + oauthClient.setCredentials(adapterConfig.getCredentials()); + if (adapterConfig.getAuthServerUrl() == null) { + throw new RuntimeException("You must specify auth-url"); + } + KeycloakUriBuilder serverBuilder = KeycloakUriBuilder.fromUri(adapterConfig.getAuthServerUrl()); + String authUrl = serverBuilder.clone().path(ServiceUrlConstants.TOKEN_SERVICE_LOGIN_PATH).build(adapterConfig.getRealm()).toString(); + String tokenUrl = serverBuilder.clone().path(ServiceUrlConstants.TOKEN_SERVICE_ACCESS_CODE_PATH).build(adapterConfig.getRealm()).toString(); + String refreshUrl = serverBuilder.clone().path(ServiceUrlConstants.TOKEN_SERVICE_REFRESH_PATH).build(adapterConfig.getRealm()).toString(); + oauthClient.setAuthUrl(authUrl); + oauthClient.setCodeUrl(tokenUrl); + oauthClient.setRefreshUrl(refreshUrl); + } +} diff --git a/integration/servlet-oauth-client/src/main/java/org/keycloak/servlet/ServletOAuthClientConfigLoader.java b/integration/servlet-oauth-client/src/main/java/org/keycloak/servlet/ServletOAuthClientConfigLoader.java deleted file mode 100644 index 668a50c2b4..0000000000 --- a/integration/servlet-oauth-client/src/main/java/org/keycloak/servlet/ServletOAuthClientConfigLoader.java +++ /dev/null @@ -1,36 +0,0 @@ -package org.keycloak.servlet; - -import java.io.InputStream; - -import org.keycloak.adapters.config.OAuthClientConfigLoader; - -/** - * @author Marek Posolda - */ -public class ServletOAuthClientConfigLoader extends OAuthClientConfigLoader { - - public ServletOAuthClientConfigLoader() { - } - - public ServletOAuthClientConfigLoader(InputStream is) { - super(is); - } - - /** - * For now, configure just things supported by ServletOAuthClient - * @param setupClient - */ - public void initOAuthClientConfiguration(boolean setupClient) { - initOAuthClientConfiguration(); - if (setupClient) { - initClient(); - } - } - - public void configureServletOAuthClient(ServletOAuthClient oauthClient) { - configureOAuthClient(oauthClient); - if (client != null) { - oauthClient.setClient(client); - } - } -} diff --git a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/AuthenticatedActionsHandler.java b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/AuthenticatedActionsHandler.java index ec10968972..1164db889b 100755 --- a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/AuthenticatedActionsHandler.java +++ b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/AuthenticatedActionsHandler.java @@ -7,6 +7,7 @@ import io.undertow.util.Headers; import io.undertow.util.StatusCodes; import org.jboss.logging.Logger; import org.keycloak.adapters.AdapterConstants; +import org.keycloak.adapters.KeycloakDeployment; import org.keycloak.representations.AccessToken; import org.keycloak.representations.adapters.config.AdapterConfig; @@ -27,25 +28,25 @@ import java.util.Set; */ public class AuthenticatedActionsHandler implements HttpHandler { private static final Logger log = Logger.getLogger(AuthenticatedActionsHandler.class); - protected AdapterConfig adapterConfig; + protected KeycloakDeployment deployment; protected HttpHandler next; public static class Wrapper implements HandlerWrapper { - protected AdapterConfig config; + protected KeycloakDeployment deployment; - public Wrapper(AdapterConfig config) { - this.config = config; + public Wrapper(KeycloakDeployment deployment) { + this.deployment = deployment; } @Override public HttpHandler wrap(HttpHandler handler) { - return new AuthenticatedActionsHandler(config, handler); + return new AuthenticatedActionsHandler(deployment, handler); } } - protected AuthenticatedActionsHandler(AdapterConfig config, HttpHandler next) { - this.adapterConfig = config; + protected AuthenticatedActionsHandler(KeycloakDeployment deployment, HttpHandler next) { + this.deployment = deployment; this.next = next; } @@ -82,13 +83,13 @@ public class AuthenticatedActionsHandler implements HttpHandler { exchange.endExchange(); return true; } - if (!adapterConfig.isExposeToken()) { + if (!deployment.isExposeToken()) { exchange.setResponseCode(StatusCodes.OK); exchange.endExchange(); return true; } // Don't allow a CORS request if we're not validating CORS requests. - if (!adapterConfig.isCors() && exchange.getRequestHeaders().getFirst(Headers.ORIGIN) != null) { + if (!deployment.isCors() && exchange.getRequestHeaders().getFirst(Headers.ORIGIN) != null) { exchange.setResponseCode(StatusCodes.OK); exchange.endExchange(); return true; @@ -97,7 +98,7 @@ public class AuthenticatedActionsHandler implements HttpHandler { } protected boolean corsRequest(HttpServerExchange exchange, KeycloakUndertowAccount account) throws IOException { - if (!adapterConfig.isCors()) return false; + if (!deployment.isCors()) return false; log.debugv("CORS enabled + request.getRequestURI()"); String origin = exchange.getRequestHeaders().getFirst("Origin"); log.debugv("Origin: {0} uri: {1}", origin, exchange.getRequestURI()); diff --git a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/BearerTokenAuthenticator.java b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/BearerTokenAuthenticator.java index 51aced7b17..743c3a7c86 100755 --- a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/BearerTokenAuthenticator.java +++ b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/BearerTokenAuthenticator.java @@ -5,14 +5,12 @@ import io.undertow.security.api.SecurityContext; import io.undertow.server.HttpServerExchange; import org.jboss.logging.Logger; import org.keycloak.RSATokenVerifier; -import org.keycloak.adapters.ResourceMetadata; +import org.keycloak.adapters.KeycloakDeployment; import org.keycloak.VerificationException; import org.keycloak.representations.AccessToken; import javax.security.cert.X509Certificate; -import java.util.HashSet; import java.util.List; -import java.util.Set; import static io.undertow.util.Headers.AUTHORIZATION; import static io.undertow.util.Headers.WWW_AUTHENTICATE; @@ -23,29 +21,21 @@ import static io.undertow.util.StatusCodes.UNAUTHORIZED; * @version $Revision: 1 $ */ public class BearerTokenAuthenticator { - protected ResourceMetadata resourceMetadata; protected Logger log = Logger.getLogger(BearerTokenAuthenticator.class); protected String tokenString; protected AccessToken token; - protected boolean useResourceRoleMappings; protected String surrogate; protected KeycloakChallenge challenge; - protected int notBefore; + protected KeycloakDeployment deployment; - public BearerTokenAuthenticator(ResourceMetadata resourceMetadata, int notBefore, boolean useResourceRoleMappings) { - this.resourceMetadata = resourceMetadata; - this.useResourceRoleMappings = useResourceRoleMappings; - this.notBefore = notBefore; + public BearerTokenAuthenticator(KeycloakDeployment deployment) { + this.deployment = deployment; } public KeycloakChallenge getChallenge() { return challenge; } - public ResourceMetadata getResourceMetadata() { - return resourceMetadata; - } - public String getTokenString() { return tokenString; } @@ -79,20 +69,20 @@ public class BearerTokenAuthenticator { } try { - token = RSATokenVerifier.verifyToken(tokenString, resourceMetadata.getRealmKey(), resourceMetadata.getRealm()); + token = RSATokenVerifier.verifyToken(tokenString, deployment.getRealmKey(), deployment.getRealm()); } catch (VerificationException e) { log.error("Failed to verify token", e); challenge = challengeResponse(exchange, "invalid_token", e.getMessage()); return AuthenticationMechanism.AuthenticationMechanismOutcome.NOT_AUTHENTICATED; } - if (token.getIssuedAt() < notBefore) { + if (token.getIssuedAt() < deployment.getNotBefore()) { log.error("Stale token"); challenge = challengeResponse(exchange, "invalid_token", "Stale token"); return AuthenticationMechanism.AuthenticationMechanismOutcome.NOT_AUTHENTICATED; } boolean verifyCaller = false; - if (useResourceRoleMappings) { - verifyCaller = token.isVerifyCaller(resourceMetadata.getResourceName()); + if (deployment.isUseResourceRoleMappings()) { + verifyCaller = token.isVerifyCaller(deployment.getResourceName()); } else { verifyCaller = token.isVerifyCaller(); } @@ -135,7 +125,7 @@ public class BearerTokenAuthenticator { protected KeycloakChallenge challengeResponse(HttpServerExchange exchange, String error, String description) { StringBuilder header = new StringBuilder("Bearer realm=\""); - header.append(resourceMetadata.getRealm()).append("\""); + header.append(deployment.getRealm()).append("\""); if (error != null) { header.append(", error=\"").append(error).append("\""); } diff --git a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/KeycloakAuthenticationMechanism.java b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/KeycloakAuthenticationMechanism.java index 34d4b9be25..8bf5dbe605 100755 --- a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/KeycloakAuthenticationMechanism.java +++ b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/KeycloakAuthenticationMechanism.java @@ -7,10 +7,8 @@ import io.undertow.util.AttachmentKey; import io.undertow.util.Headers; import org.jboss.logging.Logger; import org.keycloak.KeycloakPrincipal; +import org.keycloak.adapters.KeycloakDeployment; import org.keycloak.adapters.RefreshableKeycloakSession; -import org.keycloak.adapters.ResourceMetadata; -import org.keycloak.adapters.config.RealmConfiguration; -import org.keycloak.representations.adapters.config.AdapterConfig; /** * @author Bill Burke @@ -21,23 +19,17 @@ public class KeycloakAuthenticationMechanism implements AuthenticationMechanism public static final AttachmentKey KEYCLOAK_CHALLENGE_ATTACHMENT_KEY = AttachmentKey.create(KeycloakChallenge.class); - protected ResourceMetadata resourceMetadata; - protected AdapterConfig adapterConfig; - protected RealmConfiguration realmConfig; + protected KeycloakDeployment deployment; protected int sslRedirectPort; - public KeycloakAuthenticationMechanism(AdapterConfig config, RealmConfiguration realmConfig, int sslRedirectPort) { - this.resourceMetadata = realmConfig.getMetadata(); - this.adapterConfig = config; - this.realmConfig = realmConfig; + public KeycloakAuthenticationMechanism(KeycloakDeployment deployment, int sslRedirectPort) { + this.deployment = deployment; this.sslRedirectPort = sslRedirectPort; } - public KeycloakAuthenticationMechanism(AdapterConfig adapterConfig, RealmConfiguration realmConfig) { - this.resourceMetadata = realmConfig.getMetadata(); - this.adapterConfig = adapterConfig; - this.realmConfig = realmConfig; - } + public KeycloakAuthenticationMechanism(KeycloakDeployment deployment) { + this.deployment = deployment; + } @Override public AuthenticationMechanismOutcome authenticate(HttpServerExchange exchange, SecurityContext securityContext) { @@ -50,7 +42,7 @@ public class KeycloakAuthenticationMechanism implements AuthenticationMechanism } else if (outcome == AuthenticationMechanismOutcome.AUTHENTICATED) { completeAuthentication(exchange, securityContext, bearer); return AuthenticationMechanismOutcome.AUTHENTICATED; - } else if (adapterConfig.isBearerOnly()) { + } else if (deployment.isBearerOnly()) { exchange.putAttachment(KEYCLOAK_CHALLENGE_ATTACHMENT_KEY, bearer.getChallenge()); return AuthenticationMechanismOutcome.NOT_ATTEMPTED; } @@ -88,17 +80,17 @@ public class KeycloakAuthenticationMechanism implements AuthenticationMechanism } protected OAuthAuthenticator createOAuthAuthenticator(HttpServerExchange exchange) { - return new OAuthAuthenticator(exchange, realmConfig, sslRedirectPort); + return new OAuthAuthenticator(exchange, deployment, sslRedirectPort); } protected BearerTokenAuthenticator createBearerTokenAuthenticator() { - return new BearerTokenAuthenticator(resourceMetadata, realmConfig.getNotBefore(), adapterConfig.isUseResourceRoleMappings()); + return new BearerTokenAuthenticator(deployment); } protected void completeAuthentication(HttpServerExchange exchange, SecurityContext securityContext, OAuthAuthenticator oauth) { final KeycloakPrincipal principal = new KeycloakPrincipal(oauth.getToken().getSubject(), null); - RefreshableKeycloakSession session = new RefreshableKeycloakSession(oauth.getTokenString(), oauth.getToken(), oauth.getIdTokenString(), oauth.getIdToken(), resourceMetadata, realmConfig, oauth.getRefreshToken()); - KeycloakUndertowAccount account = new KeycloakUndertowAccount(principal, session, adapterConfig, resourceMetadata); + RefreshableKeycloakSession session = new RefreshableKeycloakSession(deployment, oauth.getTokenString(), oauth.getToken(), oauth.getIdTokenString(), oauth.getIdToken(), oauth.getRefreshToken()); + KeycloakUndertowAccount account = new KeycloakUndertowAccount(principal, session, deployment); // We cache account ourselves instead of using the Cache session handler of Undertow because // Undertow will return a 403 from an invalid account when calling IdentityManager.verify(Account) and @@ -118,8 +110,8 @@ public class KeycloakAuthenticationMechanism implements AuthenticationMechanism protected void completeAuthentication(HttpServerExchange exchange, SecurityContext securityContext, BearerTokenAuthenticator bearer) { final KeycloakPrincipal principal = new KeycloakPrincipal(bearer.getToken().getSubject(), bearer.getSurrogate()); - RefreshableKeycloakSession session = new RefreshableKeycloakSession(bearer.getTokenString(), bearer.getToken(), null, null, resourceMetadata, realmConfig, null); - KeycloakUndertowAccount account = new KeycloakUndertowAccount(principal, session, adapterConfig, resourceMetadata); + RefreshableKeycloakSession session = new RefreshableKeycloakSession(deployment, bearer.getTokenString(), bearer.getToken(), null, null, null); + KeycloakUndertowAccount account = new KeycloakUndertowAccount(principal, session, deployment); securityContext.authenticationComplete(account, "KEYCLOAK", false); propagateKeycloakContext(exchange, account); } diff --git a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/KeycloakIdentityManager.java b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/KeycloakIdentityManager.java deleted file mode 100755 index aaf12a49b3..0000000000 --- a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/KeycloakIdentityManager.java +++ /dev/null @@ -1,44 +0,0 @@ -package org.keycloak.adapters.undertow; - -import io.undertow.security.idm.Account; -import io.undertow.security.idm.Credential; -import io.undertow.security.idm.IdentityManager; -import org.jboss.logging.Logger; -import org.keycloak.adapters.config.RealmConfiguration; -import org.keycloak.representations.adapters.config.AdapterConfig; - -/** -* @author Bill Burke -* @version $Revision: 1 $ -*/ -class KeycloakIdentityManager implements IdentityManager { - protected static Logger log = Logger.getLogger(KeycloakIdentityManager.class); - protected AdapterConfig adapterConfig; - protected RealmConfiguration realmConfiguration; - - KeycloakIdentityManager(AdapterConfig adapterConfig, RealmConfiguration realmConfiguration) { - this.adapterConfig = adapterConfig; - this.realmConfiguration = realmConfiguration; - } - - @Override - public Account verify(Account account) { - log.info("Verifying account in IdentityManager"); - KeycloakUndertowAccount keycloakAccount = (KeycloakUndertowAccount)account; - if (!keycloakAccount.isActive(realmConfiguration, adapterConfig)) { - log.info("account.isActive() returned false, returning null"); - return null; - } - return account; - } - - @Override - public Account verify(String id, Credential credential) { - throw new IllegalStateException("Unsupported verify method"); - } - - @Override - public Account verify(Credential credential) { - throw new IllegalStateException("Unsupported verify method"); - } -} diff --git a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/KeycloakServletExtension.java b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/KeycloakServletExtension.java index d8751be216..7b630c154f 100755 --- a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/KeycloakServletExtension.java +++ b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/KeycloakServletExtension.java @@ -14,9 +14,8 @@ import io.undertow.servlet.api.ServletSessionConfig; import java.io.ByteArrayInputStream; import org.jboss.logging.Logger; import org.keycloak.adapters.AdapterConstants; -import org.keycloak.adapters.config.RealmConfiguration; -import org.keycloak.representations.adapters.config.AdapterConfig; -import org.keycloak.adapters.config.RealmConfigurationLoader; +import org.keycloak.adapters.KeycloakDeployment; +import org.keycloak.adapters.KeycloakDeploymentBuilder; import javax.servlet.ServletContext; import java.io.InputStream; @@ -63,24 +62,20 @@ public class KeycloakServletExtension implements ServletExtension { is = servletContext.getResourceAsStream("/WEB-INF/keycloak.json"); } if (is == null) throw new RuntimeException("Unable to find realm config in /WEB-INF/keycloak.json or in keycloak subsystem."); - RealmConfigurationLoader loader = new RealmConfigurationLoader(is); - loader.init(true); - AdapterConfig keycloakConfig = loader.getAdapterConfig(); - RealmConfiguration realmConfiguration = loader.getRealmConfiguration(); - PreflightCorsHandler.Wrapper preflight = new PreflightCorsHandler.Wrapper(keycloakConfig); - UserSessionManagement userSessionManagement = new UserSessionManagement(realmConfiguration); + KeycloakDeployment deployment = KeycloakDeploymentBuilder.build(is); + PreflightCorsHandler.Wrapper preflight = new PreflightCorsHandler.Wrapper(deployment); + UserSessionManagement userSessionManagement = new UserSessionManagement(deployment); ServletKeycloakAuthenticationMechanism auth = null; auth = new ServletKeycloakAuthenticationMechanism( userSessionManagement, - keycloakConfig, - realmConfiguration, + deployment, deploymentInfo.getConfidentialPortManager()); - AuthenticatedActionsHandler.Wrapper actions = new AuthenticatedActionsHandler.Wrapper(keycloakConfig); + AuthenticatedActionsHandler.Wrapper actions = new AuthenticatedActionsHandler.Wrapper(deployment); // setup handlers deploymentInfo.addInitialHandlerChainWrapper(preflight); // cors preflight - deploymentInfo.addOuterHandlerChainWrapper(new ServletAdminActionsHandler.Wrapper(realmConfiguration, loader.getResourceMetadata(), userSessionManagement)); + deploymentInfo.addOuterHandlerChainWrapper(new ServletAdminActionsHandler.Wrapper(deployment, userSessionManagement)); final ServletKeycloakAuthenticationMechanism theAuth = auth; deploymentInfo.addAuthenticationMechanism("KEYCLOAK", new AuthenticationMechanismFactory() { @Override diff --git a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/KeycloakUndertowAccount.java b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/KeycloakUndertowAccount.java index 495a468270..ab5e514ed2 100755 --- a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/KeycloakUndertowAccount.java +++ b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/KeycloakUndertowAccount.java @@ -3,11 +3,9 @@ package org.keycloak.adapters.undertow; import io.undertow.security.idm.Account; import org.jboss.logging.Logger; import org.keycloak.KeycloakPrincipal; +import org.keycloak.adapters.KeycloakDeployment; import org.keycloak.adapters.RefreshableKeycloakSession; -import org.keycloak.adapters.ResourceMetadata; -import org.keycloak.adapters.config.RealmConfiguration; import org.keycloak.representations.AccessToken; -import org.keycloak.representations.adapters.config.AdapterConfig; import java.io.Serializable; import java.security.Principal; @@ -24,16 +22,16 @@ public class KeycloakUndertowAccount implements Account, Serializable { protected KeycloakPrincipal principal; protected Set accountRoles; - public KeycloakUndertowAccount(KeycloakPrincipal principal, RefreshableKeycloakSession session, AdapterConfig config, ResourceMetadata metadata) { + public KeycloakUndertowAccount(KeycloakPrincipal principal, RefreshableKeycloakSession session, KeycloakDeployment deployment) { this.principal = principal; this.session = session; - setRoles(session.getToken(), config, metadata); + setRoles(session.getToken(), deployment); } - protected void setRoles(AccessToken accessToken, AdapterConfig adapterConfig, ResourceMetadata resourceMetadata) { + protected void setRoles(AccessToken accessToken, KeycloakDeployment deployment) { Set roles = null; - if (adapterConfig.isUseResourceRoleMappings()) { - AccessToken.Access access = accessToken.getResourceAccess(resourceMetadata.getResourceName()); + if (deployment.isUseResourceRoleMappings()) { + AccessToken.Access access = accessToken.getResourceAccess(deployment.getResourceName()); if (access != null) roles = access.getRoles(); } else { AccessToken.Access access = accessToken.getRealmAccess(); @@ -65,11 +63,10 @@ public class KeycloakUndertowAccount implements Account, Serializable { return session; } - public boolean isActive(RealmConfiguration realmConfiguration, AdapterConfig config) { + public boolean isActive(KeycloakDeployment deployment) { // this object may have been serialized, so we need to reset realm config/metadata - session.setRealmConfiguration(realmConfiguration); - session.setMetadata(realmConfiguration.getMetadata()); - log.info("realmConfig notBefore: " + realmConfiguration.getNotBefore()); + session.setDeployment(deployment); + log.info("realmConfig notBefore: " + deployment.getNotBefore()); if (session.isActive()) { log.info("session is active"); return true; @@ -84,7 +81,7 @@ public class KeycloakUndertowAccount implements Account, Serializable { } log.info("refresh succeeded"); - setRoles(session.getToken(), config, realmConfiguration.getMetadata()); + setRoles(session.getToken(), deployment); return true; } diff --git a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/OAuthAuthenticator.java b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/OAuthAuthenticator.java index 33e472b62f..751be8d2fb 100755 --- a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/OAuthAuthenticator.java +++ b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/OAuthAuthenticator.java @@ -9,8 +9,8 @@ import io.undertow.util.Headers; import io.undertow.util.StatusCodes; import org.jboss.logging.Logger; import org.keycloak.RSATokenVerifier; +import org.keycloak.adapters.KeycloakDeployment; import org.keycloak.adapters.ServerRequest; -import org.keycloak.adapters.config.RealmConfiguration; import org.keycloak.VerificationException; import org.keycloak.jose.jws.JWSInput; import org.keycloak.representations.AccessToken; @@ -30,7 +30,7 @@ import java.util.concurrent.atomic.AtomicLong; */ public class OAuthAuthenticator { private static final Logger log = Logger.getLogger(OAuthAuthenticator.class); - protected RealmConfiguration realmInfo; + protected KeycloakDeployment deployment; protected int sslRedirectPort; protected String tokenString; protected String idTokenString; @@ -41,9 +41,9 @@ public class OAuthAuthenticator { protected String refreshToken; protected String strippedOauthParametersRequestUri; - public OAuthAuthenticator(HttpServerExchange exchange, RealmConfiguration realmInfo, int sslRedirectPort) { + public OAuthAuthenticator(HttpServerExchange exchange, KeycloakDeployment deployment, int sslRedirectPort) { this.exchange = exchange; - this.realmInfo = realmInfo; + this.deployment = deployment; this.sslRedirectPort = sslRedirectPort; } @@ -129,7 +129,7 @@ public class OAuthAuthenticator { protected String getRedirectUri(String state) { String url = getRequestUrl(); log.infof("sending redirect uri: %s", url); - if (!isRequestSecure() && realmInfo.isSslRequired()) { + if (!isRequestSecure() && deployment.isSslRequired()) { int port = sslRedirectPort(); if (port < 0) { // disabled? @@ -139,8 +139,8 @@ public class OAuthAuthenticator { if (port != 443) secureUrl.port(port); url = secureUrl.build().toString(); } - return realmInfo.getAuthUrl().clone() - .queryParam("client_id", realmInfo.getMetadata().getResourceName()) + return deployment.getAuthUrl().clone() + .queryParam("client_id", deployment.getResourceName()) .queryParam("redirect_uri", url) .queryParam("state", state) .queryParam("login", "true") @@ -166,9 +166,9 @@ public class OAuthAuthenticator { if (redirect == null) { return new AuthenticationMechanism.ChallengeResult(true, StatusCodes.FORBIDDEN); } - CookieImpl cookie = new CookieImpl(realmInfo.getStateCookieName(), state); + CookieImpl cookie = new CookieImpl(deployment.getStateCookieName(), state); //cookie.setPath(getDefaultCookiePath()); todo I don't think we need to set state cookie path as it will be the same redirect - cookie.setSecure(realmInfo.isSslRequired()); + cookie.setSecure(deployment.isSslRequired()); exchange.setResponseCookie(cookie); exchange.getResponseHeaders().put(Headers.LOCATION, redirect); return new AuthenticationMechanism.ChallengeResult(true, StatusCodes.FOUND); @@ -177,7 +177,7 @@ public class OAuthAuthenticator { } protected KeycloakChallenge checkStateCookie() { - Cookie stateCookie = getCookie(realmInfo.getStateCookieName()); + Cookie stateCookie = getCookie(deployment.getStateCookieName()); if (stateCookie == null) { log.warn("No state cookie"); @@ -185,12 +185,12 @@ public class OAuthAuthenticator { } // reset the cookie log.info("** reseting application state cookie"); - Cookie reset = new CookieImpl(realmInfo.getStateCookieName(), ""); + Cookie reset = new CookieImpl(deployment.getStateCookieName(), ""); reset.setPath(stateCookie.getPath()); reset.setMaxAge(0); exchange.setResponseCookie(reset); - String stateCookieValue = getCookieValue(realmInfo.getStateCookieName()); + String stateCookieValue = getCookieValue(deployment.getStateCookieName()); String state = getQueryParamValue("state"); if (state == null) { @@ -256,7 +256,7 @@ public class OAuthAuthenticator { */ protected KeycloakChallenge resolveCode(String code) { // abort if not HTTPS - if (realmInfo.isSslRequired() && !isRequestSecure()) { + if (deployment.isSslRequired() && !isRequestSecure()) { log.error("SSL is required"); return challenge(StatusCodes.FORBIDDEN); } @@ -268,7 +268,7 @@ public class OAuthAuthenticator { AccessTokenResponse tokenResponse = null; strippedOauthParametersRequestUri = stripOauthParametersFromRedirect(); try { - tokenResponse = ServerRequest.invokeAccessCodeToToken(realmInfo, code, strippedOauthParametersRequestUri); + tokenResponse = ServerRequest.invokeAccessCodeToToken(deployment, code, strippedOauthParametersRequestUri); } catch (ServerRequest.HttpFailure failure) { log.error("failed to turn code into token"); log.error("status from server: " + failure.getStatus()); @@ -286,7 +286,7 @@ public class OAuthAuthenticator { refreshToken = tokenResponse.getRefreshToken(); idTokenString = tokenResponse.getIdToken(); try { - token = RSATokenVerifier.verifyToken(tokenString, realmInfo.getMetadata().getRealmKey(), realmInfo.getMetadata().getRealm()); + token = RSATokenVerifier.verifyToken(tokenString, deployment.getRealmKey(), deployment.getRealm()); if (idTokenString != null) { JWSInput input = new JWSInput(idTokenString); try { @@ -300,10 +300,10 @@ public class OAuthAuthenticator { log.error("failed verification of token"); return challenge(StatusCodes.FORBIDDEN); } - if (tokenResponse.getNotBeforePolicy() > realmInfo.getNotBefore()) { - realmInfo.setNotBefore(tokenResponse.getNotBeforePolicy()); + if (tokenResponse.getNotBeforePolicy() > deployment.getNotBefore()) { + deployment.setNotBefore(tokenResponse.getNotBeforePolicy()); } - if (token.getIssuedAt() < realmInfo.getNotBefore()) { + if (token.getIssuedAt() < deployment.getNotBefore()) { log.error("Stale token"); return challenge(StatusCodes.FORBIDDEN); } diff --git a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/PreflightCorsHandler.java b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/PreflightCorsHandler.java index 8757094efd..08a4295802 100755 --- a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/PreflightCorsHandler.java +++ b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/PreflightCorsHandler.java @@ -6,6 +6,7 @@ import io.undertow.server.HttpServerExchange; import io.undertow.util.HttpString; import io.undertow.util.StatusCodes; import org.jboss.logging.Logger; +import org.keycloak.adapters.KeycloakDeployment; import org.keycloak.representations.adapters.config.AdapterConfig; /** @@ -14,7 +15,7 @@ import org.keycloak.representations.adapters.config.AdapterConfig; */ public class PreflightCorsHandler implements HttpHandler { private static final Logger log = Logger.getLogger(PreflightCorsHandler.class); - protected AdapterConfig adapterConfig; + protected KeycloakDeployment deployment; protected HttpHandler next; public static final HttpString ACCESS_CONTROL_ALLOW_ORIGIN = new HttpString("Access-Control-Allow-Origin"); @@ -24,20 +25,20 @@ public class PreflightCorsHandler implements HttpHandler { public static final HttpString ACCESS_CONTROL_MAX_AGE = new HttpString("Access-Control-Max-Age"); public static class Wrapper implements HandlerWrapper { - protected AdapterConfig config; + protected KeycloakDeployment deployment; - public Wrapper(AdapterConfig config) { - this.config = config; + public Wrapper(KeycloakDeployment deployment) { + this.deployment = deployment; } @Override public HttpHandler wrap(HttpHandler handler) { - return new PreflightCorsHandler(config, handler); + return new PreflightCorsHandler(deployment, handler); } } - protected PreflightCorsHandler(AdapterConfig config, HttpHandler next) { - this.adapterConfig = config; + protected PreflightCorsHandler(KeycloakDeployment deployment, HttpHandler next) { + this.deployment = deployment; this.next = next; } @@ -61,20 +62,20 @@ public class PreflightCorsHandler implements HttpHandler { exchange.getResponseHeaders().put(ACCESS_CONTROL_ALLOW_CREDENTIALS, "true"); String requestMethods = exchange.getRequestHeaders().getFirst("Access-Control-Request-Method"); if (requestMethods != null) { - if (adapterConfig.getCorsAllowedMethods() != null) { - requestMethods = adapterConfig.getCorsAllowedMethods(); + if (deployment.getCorsAllowedMethods() != null) { + requestMethods = deployment.getCorsAllowedMethods(); } exchange.getResponseHeaders().put(ACCESS_CONTROL_ALLOW_METHODS, requestMethods); } String allowHeaders = exchange.getRequestHeaders().getFirst("Access-Control-Request-Headers"); if (allowHeaders != null) { - if (adapterConfig.getCorsAllowedHeaders() != null) { - allowHeaders = adapterConfig.getCorsAllowedHeaders(); + if (deployment.getCorsAllowedHeaders() != null) { + allowHeaders = deployment.getCorsAllowedHeaders(); } exchange.getResponseHeaders().put(ACCESS_CONTROL_ALLOW_HEADERS, allowHeaders); } - if (adapterConfig.getCorsMaxAge() > -1) { - exchange.getResponseHeaders().put(ACCESS_CONTROL_MAX_AGE, Integer.toString(adapterConfig.getCorsMaxAge())); + if (deployment.getCorsMaxAge() > -1) { + exchange.getResponseHeaders().put(ACCESS_CONTROL_MAX_AGE, Integer.toString(deployment.getCorsMaxAge())); } exchange.endExchange(); } diff --git a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/ServletAdminActionsHandler.java b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/ServletAdminActionsHandler.java index 0e329b45ac..9f60b3fb00 100755 --- a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/ServletAdminActionsHandler.java +++ b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/ServletAdminActionsHandler.java @@ -8,8 +8,7 @@ import io.undertow.servlet.handlers.ServletRequestContext; import io.undertow.util.StatusCodes; import org.jboss.logging.Logger; import org.keycloak.adapters.AdapterConstants; -import org.keycloak.adapters.ResourceMetadata; -import org.keycloak.adapters.config.RealmConfiguration; +import org.keycloak.adapters.KeycloakDeployment; import org.keycloak.jose.jws.JWSInput; import org.keycloak.jose.jws.crypto.RSAProvider; import org.keycloak.representations.adapters.action.AdminAction; @@ -25,8 +24,6 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; import java.util.Map; /** @@ -38,35 +35,30 @@ public class ServletAdminActionsHandler implements HttpHandler { private static final Logger log = Logger.getLogger(ServletAdminActionsHandler.class); protected HttpHandler next; protected UserSessionManagement userSessionManagement; - protected RealmConfiguration realmConfig; - protected ResourceMetadata resourceMetadata; + protected KeycloakDeployment deployment; public static class Wrapper implements HandlerWrapper { - protected RealmConfiguration realmConfig; - protected ResourceMetadata resourceMetadata; + protected KeycloakDeployment deployment; protected UserSessionManagement userSessionManagement; - public Wrapper(RealmConfiguration realmConfig, ResourceMetadata resourceMetadata, UserSessionManagement userSessionManagement) { - this.realmConfig = realmConfig; - this.resourceMetadata = resourceMetadata; + public Wrapper(KeycloakDeployment deployment, UserSessionManagement userSessionManagement) { + this.deployment = deployment; this.userSessionManagement = userSessionManagement; } @Override public HttpHandler wrap(HttpHandler handler) { - return new ServletAdminActionsHandler(realmConfig, resourceMetadata, userSessionManagement, handler); + return new ServletAdminActionsHandler(deployment, userSessionManagement, handler); } } - protected ServletAdminActionsHandler(RealmConfiguration realmConfig, - ResourceMetadata resourceMetadata, + protected ServletAdminActionsHandler(KeycloakDeployment deployment, UserSessionManagement userSessionManagement, HttpHandler next) { this.next = next; - this.resourceMetadata = resourceMetadata; + this.deployment = deployment; this.userSessionManagement = userSessionManagement; - this.realmConfig = realmConfig; } @@ -110,7 +102,7 @@ public class ServletAdminActionsHandler implements HttpHandler { } PushNotBeforeAction action = JsonSerialization.readValue(token.getContent(), PushNotBeforeAction.class); if (!validateAction(response, action)) return; - realmConfig.setNotBefore(action.getNotBefore()); + deployment.setNotBefore(action.getNotBefore()); return; } @@ -125,7 +117,7 @@ public class ServletAdminActionsHandler implements HttpHandler { JWSInput input = new JWSInput(token); boolean verified = false; try { - verified = RSAProvider.verify(input, realmConfig.getMetadata().getRealmKey()); + verified = RSAProvider.verify(input, deployment.getRealmKey()); } catch (Exception ignore) { } if (!verified) { @@ -148,7 +140,7 @@ public class ServletAdminActionsHandler implements HttpHandler { response.sendError(HttpServletResponse.SC_BAD_REQUEST, "Expired token"); return false; } - if (!resourceMetadata.getResourceName().equals(action.getResource())) { + if (!deployment.getResourceName().equals(action.getResource())) { log.warn("Resource name does not match"); response.sendError(HttpServletResponse.SC_BAD_REQUEST, "Resource name does not match"); return false; diff --git a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/ServletKeycloakAuthenticationMechanism.java b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/ServletKeycloakAuthenticationMechanism.java index d7da5c8ba1..481eb10267 100755 --- a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/ServletKeycloakAuthenticationMechanism.java +++ b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/ServletKeycloakAuthenticationMechanism.java @@ -4,8 +4,7 @@ import io.undertow.server.HttpServerExchange; import io.undertow.servlet.api.ConfidentialPortManager; import io.undertow.servlet.handlers.ServletRequestContext; import org.keycloak.KeycloakSecurityContext; -import org.keycloak.adapters.config.RealmConfiguration; -import org.keycloak.representations.adapters.config.AdapterConfig; +import org.keycloak.adapters.KeycloakDeployment; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; @@ -18,15 +17,15 @@ public class ServletKeycloakAuthenticationMechanism extends KeycloakAuthenticati protected ConfidentialPortManager portManager; protected UserSessionManagement userSessionManagement; - public ServletKeycloakAuthenticationMechanism(UserSessionManagement userSessionManagement, AdapterConfig config, RealmConfiguration realmConfig, ConfidentialPortManager portManager) { - super(config, realmConfig); + public ServletKeycloakAuthenticationMechanism(UserSessionManagement userSessionManagement, KeycloakDeployment deployment, ConfidentialPortManager portManager) { + super(deployment); this.portManager = portManager; this.userSessionManagement = userSessionManagement; } @Override protected OAuthAuthenticator createOAuthAuthenticator(HttpServerExchange exchange) { - return new ServletOAuthAuthenticator(exchange, realmConfig, portManager); + return new ServletOAuthAuthenticator(exchange, deployment, portManager); } @Override @@ -43,7 +42,7 @@ public class ServletKeycloakAuthenticationMechanism extends KeycloakAuthenticati log.info("Account was not in session, returning null"); return null; } - if (account.isActive(realmConfig, adapterConfig)) return account; + if (account.isActive(deployment)) return account; log.info("Account was not active, returning null"); session.setAttribute(KeycloakUndertowAccount.class.getName(), null); return null; diff --git a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/ServletOAuthAuthenticator.java b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/ServletOAuthAuthenticator.java index e891a1d024..9d680ddd37 100755 --- a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/ServletOAuthAuthenticator.java +++ b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/ServletOAuthAuthenticator.java @@ -2,7 +2,7 @@ package org.keycloak.adapters.undertow; import io.undertow.server.HttpServerExchange; import io.undertow.servlet.api.ConfidentialPortManager; -import org.keycloak.adapters.config.RealmConfiguration; +import org.keycloak.adapters.KeycloakDeployment; /** * @author Bill Burke @@ -11,8 +11,8 @@ import org.keycloak.adapters.config.RealmConfiguration; public class ServletOAuthAuthenticator extends OAuthAuthenticator { protected ConfidentialPortManager portManager; - public ServletOAuthAuthenticator(HttpServerExchange exchange, RealmConfiguration realmInfo, ConfidentialPortManager portManager) { - super(exchange, realmInfo, -1); + public ServletOAuthAuthenticator(HttpServerExchange exchange, KeycloakDeployment deployment, ConfidentialPortManager portManager) { + super(exchange, deployment, -1); this.portManager = portManager; } diff --git a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/UserSessionManagement.java b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/UserSessionManagement.java index fcf502ba69..00371a4d9c 100755 --- a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/UserSessionManagement.java +++ b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/UserSessionManagement.java @@ -8,7 +8,7 @@ import io.undertow.server.session.SessionManager; import io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler; import io.undertow.util.StatusCodes; import org.jboss.logging.Logger; -import org.keycloak.adapters.config.RealmConfiguration; +import org.keycloak.adapters.KeycloakDeployment; import org.keycloak.jose.jws.JWSInput; import org.keycloak.representations.adapters.action.LogoutAction; import org.keycloak.util.JsonSerialization; @@ -33,10 +33,10 @@ public class UserSessionManagement implements SessionListener { private static final String AUTH_SESSION_NAME = CachedAuthenticatedSessionHandler.class.getName() + ".AuthenticatedSession"; protected ConcurrentHashMap userSessionMap = new ConcurrentHashMap(); - protected RealmConfiguration realmInfo; + protected KeycloakDeployment deployment; - public UserSessionManagement(RealmConfiguration realmInfo) { - this.realmInfo = realmInfo; + public UserSessionManagement(KeycloakDeployment deployment) { + this.deployment = deployment; } public static class UserSessions { @@ -52,10 +52,6 @@ public class UserSessionManagement implements SessionListener { } } - public int getNumUserLogins() { - return userSessionMap.size(); - } - public int getActiveSessions() { int active = 0; synchronized (userSessionMap) { @@ -93,7 +89,7 @@ public class UserSessionManagement implements SessionListener { response.sendError(StatusCodes.BAD_REQUEST, "Expired token"); return; } - if (!realmInfo.getMetadata().getResourceName().equals(action.getResource())) { + if (!deployment.getResourceName().equals(action.getResource())) { log.warn("Resource name does not match"); response.sendError(StatusCodes.BAD_REQUEST, "Resource name does not match"); return;