keycloak-memoizeit
Changes
integration/adapter-core/src/main/java/org/keycloak/adapters/AdapterDeploymentContext.java 284(+284 -0)
integration/adapter-core/src/main/java/org/keycloak/adapters/KeycloakDeploymentBuilder.java 43(+14 -29)
integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/AuthenticatedActionsValve.java 11(+8 -3)
integration/as7-eap6/adapter/src/main/java/org/keycloak/adapters/as7/KeycloakAuthenticatorValve.java 46(+20 -26)
integration/undertow/src/main/java/org/keycloak/adapters/undertow/KeycloakServletExtension.java 23(+15 -8)
integration/undertow/src/main/java/org/keycloak/adapters/undertow/ServletKeycloakAuthMech.java 15(+10 -5)
integration/undertow/src/main/java/org/keycloak/adapters/undertow/ServletPreAuthActionsHandler.java 27(+16 -11)
integration/undertow/src/main/java/org/keycloak/adapters/undertow/UndertowAuthenticatedActionsHandler.java 23(+14 -9)
integration/undertow/src/main/java/org/keycloak/adapters/undertow/UndertowUserSessionManagement.java 5(+0 -5)
integration/wildfly-adapter/src/main/java/org/keycloak/adapters/wildfly/WildflyAuthenticationMechanism.java 7(+4 -3)
integration/wildfly-adapter/src/main/java/org/keycloak/adapters/wildfly/WildflyKeycloakServletExtension.java 5(+3 -2)
pom.xml 2(+1 -1)
Details
diff --git a/core/src/main/java/org/keycloak/ServiceUrlConstants.java b/core/src/main/java/org/keycloak/ServiceUrlConstants.java
index b392ca6..6538064 100755
--- a/core/src/main/java/org/keycloak/ServiceUrlConstants.java
+++ b/core/src/main/java/org/keycloak/ServiceUrlConstants.java
@@ -11,5 +11,6 @@ public interface ServiceUrlConstants {
public static final String TOKEN_SERVICE_REFRESH_PATH = "/rest/realms/{realm-name}/tokens/refresh";
public static final String TOKEN_SERVICE_LOGOUT_PATH = "/rest/realms/{realm-name}/tokens/logout";
public static final String ACCOUNT_SERVICE_PATH = "/rest/realms/{realm-name}/account";
+ public static final String REALM_INFO_PATH = "/rest/realms/{realm-name}";
}
diff --git a/integration/adapter-core/src/main/java/org/keycloak/adapters/AdapterDeploymentContext.java b/integration/adapter-core/src/main/java/org/keycloak/adapters/AdapterDeploymentContext.java
index 3dfce8e..786ea7c 100755
--- a/integration/adapter-core/src/main/java/org/keycloak/adapters/AdapterDeploymentContext.java
+++ b/integration/adapter-core/src/main/java/org/keycloak/adapters/AdapterDeploymentContext.java
@@ -1,12 +1,28 @@
package org.keycloak.adapters;
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpResponse;
+import org.apache.http.client.HttpClient;
+import org.apache.http.client.methods.HttpGet;
+import org.jboss.logging.Logger;
import org.keycloak.representations.adapters.config.AdapterConfig;
+import org.keycloak.representations.idm.PublishedRealmRepresentation;
+import org.keycloak.util.JsonSerialization;
+import org.keycloak.util.KeycloakUriBuilder;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+import java.security.PublicKey;
+import java.util.Map;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class AdapterDeploymentContext {
+ private static final Logger log = Logger.getLogger(AdapterDeploymentContext.class);
protected KeycloakDeployment deployment;
public AdapterDeploymentContext() {
@@ -20,6 +36,274 @@ public class AdapterDeploymentContext {
return deployment;
}
+ /**
+ * Resolve adapter deployment based on partial adapter configuration.
+ * This will resolve a relative auth server url based on the current request
+ * This will lazily resolve the public key of the realm if it is not set already.
+ *
+ * @return
+ */
+ public KeycloakDeployment resolveDeployment(HttpFacade facade) {
+ KeycloakDeployment deployment = this.deployment;
+ if (deployment == null) return null;
+ if (deployment.relativeUrls) {
+ deployment = new DeploymentDelegate(this.deployment);
+ deployment.setAuthServerBaseUrl(getBaseBuilder(facade, this.deployment.getAuthServerBaseUrl()).build().toString());
+ }
+ if (deployment.getRealmKey() == null) resolveRealmKey(deployment);
+ return deployment;
+ }
+
+ protected void resolveRealmKey(KeycloakDeployment deployment) {
+ if (deployment.getClient() == null) {
+ throw new RuntimeException("KeycloakDeployment was never initialized through appropriate SPIs");
+ }
+ HttpGet get = new HttpGet(deployment.getRealmInfoUrl());
+ try {
+ HttpResponse response = deployment.getClient().execute(get);
+ int status = response.getStatusLine().getStatusCode();
+ if (status != 200) {
+ close(response);
+ throw new RuntimeException("Unable to resolve realm public key remotely, status = " + status);
+ }
+ HttpEntity entity = response.getEntity();
+ if (entity == null) {
+ throw new RuntimeException("Unable to resolve realm public key remotely. There was no entity.");
+ }
+ InputStream is = entity.getContent();
+ try {
+ ByteArrayOutputStream os = new ByteArrayOutputStream();
+ int c;
+ while ((c = is.read()) != -1) {
+ os.write(c);
+ }
+ byte[] bytes = os.toByteArray();
+ String json = new String(bytes);
+ PublishedRealmRepresentation rep = JsonSerialization.readValue(json, PublishedRealmRepresentation.class);
+ deployment.setRealmKey(rep.getPublicKey());
+ } finally {
+ try {
+ is.close();
+ } catch (IOException ignored) {
+
+ }
+ }
+ } catch (IOException e) {
+ throw new RuntimeException("Unable to resolve realm public key remotely", e);
+ }
+ }
+
+ protected static class DeploymentDelegate extends KeycloakDeployment {
+ protected KeycloakDeployment delegate;
+
+ public DeploymentDelegate(KeycloakDeployment delegate) {
+ this.delegate = delegate;
+ }
+
+ @Override
+ public boolean isConfigured() {
+ return delegate.isConfigured();
+ }
+
+ @Override
+ public String getResourceName() {
+ return delegate.getResourceName();
+ }
+
+ @Override
+ public String getRealm() {
+ return delegate.getRealm();
+ }
+
+ @Override
+ public void setRealm(String realm) {
+ delegate.setRealm(realm);
+ }
+
+ @Override
+ public PublicKey getRealmKey() {
+ return delegate.getRealmKey();
+ }
+
+ @Override
+ public void setRealmKey(PublicKey realmKey) {
+ delegate.setRealmKey(realmKey);
+ }
+
+ @Override
+ public void setResourceName(String resourceName) {
+ delegate.setResourceName(resourceName);
+ }
+
+ @Override
+ public boolean isBearerOnly() {
+ return delegate.isBearerOnly();
+ }
+
+ @Override
+ public void setBearerOnly(boolean bearerOnly) {
+ delegate.setBearerOnly(bearerOnly);
+ }
+
+ @Override
+ public boolean isPublicClient() {
+ return delegate.isPublicClient();
+ }
+
+ @Override
+ public void setPublicClient(boolean publicClient) {
+ delegate.setPublicClient(publicClient);
+ }
+
+ @Override
+ public Map<String, String> getResourceCredentials() {
+ return delegate.getResourceCredentials();
+ }
+
+ @Override
+ public void setResourceCredentials(Map<String, String> resourceCredentials) {
+ delegate.setResourceCredentials(resourceCredentials);
+ }
+
+ @Override
+ public HttpClient getClient() {
+ return delegate.getClient();
+ }
+
+ @Override
+ public void setClient(HttpClient client) {
+ delegate.setClient(client);
+ }
+
+ @Override
+ public String getScope() {
+ return delegate.getScope();
+ }
+
+ @Override
+ public void setScope(String scope) {
+ delegate.setScope(scope);
+ }
+
+ @Override
+ public boolean isSslRequired() {
+ return delegate.isSslRequired();
+ }
+
+ @Override
+ public void setSslRequired(boolean sslRequired) {
+ delegate.setSslRequired(sslRequired);
+ }
+
+ @Override
+ public String getStateCookieName() {
+ return delegate.getStateCookieName();
+ }
+
+ @Override
+ public void setStateCookieName(String stateCookieName) {
+ delegate.setStateCookieName(stateCookieName);
+ }
+
+ @Override
+ public boolean isUseResourceRoleMappings() {
+ return delegate.isUseResourceRoleMappings();
+ }
+
+ @Override
+ public void setUseResourceRoleMappings(boolean useResourceRoleMappings) {
+ delegate.setUseResourceRoleMappings(useResourceRoleMappings);
+ }
+
+ @Override
+ public boolean isCors() {
+ return delegate.isCors();
+ }
+
+ @Override
+ public void setCors(boolean cors) {
+ delegate.setCors(cors);
+ }
+
+ @Override
+ public int getCorsMaxAge() {
+ return delegate.getCorsMaxAge();
+ }
+
+ @Override
+ public void setCorsMaxAge(int corsMaxAge) {
+ delegate.setCorsMaxAge(corsMaxAge);
+ }
+
+ @Override
+ public String getCorsAllowedHeaders() {
+ return delegate.getCorsAllowedHeaders();
+ }
+
+ @Override
+ public void setNotBefore(int notBefore) {
+ delegate.setNotBefore(notBefore);
+ }
+
+ @Override
+ public int getNotBefore() {
+ return delegate.getNotBefore();
+ }
+
+ @Override
+ public void setExposeToken(boolean exposeToken) {
+ delegate.setExposeToken(exposeToken);
+ }
+
+ @Override
+ public boolean isExposeToken() {
+ return delegate.isExposeToken();
+ }
+
+ @Override
+ public void setCorsAllowedMethods(String corsAllowedMethods) {
+ delegate.setCorsAllowedMethods(corsAllowedMethods);
+ }
+
+ @Override
+ public String getCorsAllowedMethods() {
+ return delegate.getCorsAllowedMethods();
+ }
+
+ @Override
+ public void setCorsAllowedHeaders(String corsAllowedHeaders) {
+ delegate.setCorsAllowedHeaders(corsAllowedHeaders);
+ }
+ }
+
+ protected KeycloakUriBuilder getBaseBuilder(HttpFacade facade, String base) {
+ KeycloakUriBuilder builder = KeycloakUriBuilder.fromUri(base);
+ URI request = URI.create(facade.getRequest().getURI());
+ String scheme = "http";
+ if (deployment.isSslRequired()) {
+ scheme = "https";
+ }
+ if (!request.getScheme().equals(scheme) && request.getPort() != -1) {
+ throw new RuntimeException("Can't resolve relative url from adapter config.");
+ }
+ builder.scheme(scheme);
+ builder.host(request.getHost());
+ builder.port(request.getPort());
+ return builder;
+ }
+
+
+
+ protected void close(HttpResponse response) {
+ if (response.getEntity() != null) {
+ try {
+ response.getEntity().getContent().close();
+ } catch (IOException e) {
+
+ }
+ }
+ }
+
public void updateDeployment(AdapterConfig config) {
deployment = KeycloakDeploymentBuilder.build(config);
}
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
index 722c40f..9e63654 100755
--- a/integration/adapter-core/src/main/java/org/keycloak/adapters/KeycloakDeployment.java
+++ b/integration/adapter-core/src/main/java/org/keycloak/adapters/KeycloakDeployment.java
@@ -1,8 +1,12 @@
package org.keycloak.adapters;
import org.apache.http.client.HttpClient;
+import org.jboss.logging.Logger;
+import org.keycloak.OAuth2Constants;
+import org.keycloak.ServiceUrlConstants;
import org.keycloak.util.KeycloakUriBuilder;
+import java.net.URI;
import java.security.PublicKey;
import java.util.HashMap;
import java.util.Map;
@@ -12,9 +16,14 @@ import java.util.Map;
* @version $Revision: 1 $
*/
public class KeycloakDeployment {
- protected boolean configured;
+ private static final Logger log = Logger.getLogger(KeycloakDeployment.class);
+
+ protected boolean relativeUrls;
protected String realm;
protected PublicKey realmKey;
+ protected KeycloakUriBuilder serverBuilder;
+ protected String authServerBaseUrl;
+ protected String realmInfoUrl;
protected KeycloakUriBuilder authUrl;
protected String codeUrl;
protected String refreshUrl;
@@ -38,12 +47,11 @@ public class KeycloakDeployment {
protected boolean exposeToken;
protected volatile int notBefore;
- public boolean isConfigured() {
- return configured;
+ public KeycloakDeployment() {
}
- public void setConfigured(boolean configured) {
- this.configured = configured;
+ public boolean isConfigured() {
+ return realm != null && realmKey != null && (bearerOnly || authServerBaseUrl != null);
}
public String getResourceName() {
@@ -66,28 +74,54 @@ public class KeycloakDeployment {
this.realmKey = realmKey;
}
- public KeycloakUriBuilder getAuthUrl() {
- return authUrl;
+ public String getAuthServerBaseUrl() {
+ return authServerBaseUrl;
}
- public void setAuthUrl(KeycloakUriBuilder authUrl) {
- this.authUrl = authUrl;
+ public void setAuthServerBaseUrl(String authServerBaseUrl) {
+ this.authServerBaseUrl = authServerBaseUrl;
+ if (authServerBaseUrl == null) return;
+
+ URI uri = URI.create(authServerBaseUrl);
+ if (uri.getHost() == null) {
+ relativeUrls = true;
+ return;
+ }
+
+ relativeUrls = false;
+
+ serverBuilder = KeycloakUriBuilder.fromUri(authServerBaseUrl);
+ String login = serverBuilder.clone().path(ServiceUrlConstants.TOKEN_SERVICE_LOGIN_PATH).build(getRealm()).toString();
+ authUrl = KeycloakUriBuilder.fromUri(login);
+ refreshUrl = serverBuilder.clone().path(ServiceUrlConstants.TOKEN_SERVICE_REFRESH_PATH).build(getRealm()).toString();
+ logoutUrl = KeycloakUriBuilder.fromUri(serverBuilder.clone().path(ServiceUrlConstants.TOKEN_SERVICE_LOGOUT_PATH).build(getRealm()).toString());
+ accountUrl = serverBuilder.clone().path(ServiceUrlConstants.ACCOUNT_SERVICE_PATH).build(getRealm()).toString();
+ realmInfoUrl = serverBuilder.clone().path(ServiceUrlConstants.REALM_INFO_PATH).build(getRealm()).toString();
+ codeUrl = serverBuilder.clone().path(ServiceUrlConstants.TOKEN_SERVICE_ACCESS_CODE_PATH).build(getRealm()).toString();
}
- public String getCodeUrl() {
- return codeUrl;
+ public String getRealmInfoUrl() {
+ return realmInfoUrl;
+ }
+
+ public KeycloakUriBuilder getAuthUrl() {
+ return authUrl;
}
- public void setCodeUrl(String codeUrl) {
- this.codeUrl = codeUrl;
+ public String getCodeUrl() {
+ return codeUrl;
}
public String getRefreshUrl() {
return refreshUrl;
}
- public void setRefreshUrl(String refreshUrl) {
- this.refreshUrl = refreshUrl;
+ public KeycloakUriBuilder getLogoutUrl() {
+ return logoutUrl;
+ }
+
+ public String getAccountUrl() {
+ return accountUrl;
}
public void setResourceName(String resourceName) {
@@ -206,19 +240,4 @@ public class KeycloakDeployment {
this.notBefore = notBefore;
}
- public KeycloakUriBuilder getLogoutUrl() {
- return logoutUrl;
- }
-
- public void setLogoutUrl(KeycloakUriBuilder logoutUrl) {
- this.logoutUrl = logoutUrl;
- }
-
- public String getAccountUrl() {
- return accountUrl;
- }
-
- public void setAccountUrl(String accountUrl) {
- this.accountUrl = accountUrl;
- }
}
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
index 04f8c15..4138e6a 100755
--- a/integration/adapter-core/src/main/java/org/keycloak/adapters/KeycloakDeploymentBuilder.java
+++ b/integration/adapter-core/src/main/java/org/keycloak/adapters/KeycloakDeploymentBuilder.java
@@ -5,14 +5,11 @@ import org.codehaus.jackson.map.annotate.JsonSerialize;
import org.keycloak.OAuth2Constants;
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;
/**
@@ -22,12 +19,11 @@ import java.security.PublicKey;
public class KeycloakDeploymentBuilder {
protected KeycloakDeployment deployment = new KeycloakDeployment();
- protected KeycloakDeploymentBuilder() {}
-
+ protected KeycloakDeploymentBuilder() {
+ }
protected KeycloakDeployment internalBuild(AdapterConfig adapterConfig) {
- deployment.setConfigured(true);
if (adapterConfig.getRealm() == null) throw new RuntimeException("Must set 'realm' in config");
deployment.setRealm(adapterConfig.getRealm());
String resource = adapterConfig.getResource();
@@ -35,17 +31,15 @@ public class KeycloakDeploymentBuilder {
deployment.setResourceName(resource);
String realmKeyPem = adapterConfig.getRealmKey();
- if (realmKeyPem == null) {
- throw new IllegalArgumentException("You must set the realm-public-key");
+ if (realmKeyPem != null) {
+ PublicKey realmKey = null;
+ try {
+ realmKey = PemUtils.decodePublicKey(realmKeyPem);
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ deployment.setRealmKey(realmKey);
}
-
- 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());
@@ -58,6 +52,9 @@ public class KeycloakDeploymentBuilder {
deployment.setCorsAllowedMethods(adapterConfig.getCorsAllowedMethods());
}
+ if (realmKeyPem == null && adapterConfig.isBearerOnly() && adapterConfig.getAuthServerUrl() == null) {
+ throw new IllegalArgumentException("For bearer auth, you must set the realm-public-key or auth-server-url");
+ }
if (adapterConfig.isBearerOnly()) {
deployment.setBearerOnly(true);
return deployment;
@@ -67,19 +64,7 @@ public class KeycloakDeploymentBuilder {
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();
- String logoutUrl = serverBuilder.clone().path(ServiceUrlConstants.TOKEN_SERVICE_LOGOUT_PATH).build(adapterConfig.getRealm()).toString();
- String accountUrl = serverBuilder.clone().path(ServiceUrlConstants.ACCOUNT_SERVICE_PATH).build(adapterConfig.getRealm()).toString();
-
- deployment.setAuthUrl(KeycloakUriBuilder.fromUri(authUrl).queryParam(OAuth2Constants.CLIENT_ID, deployment.getResourceName()));
- deployment.setCodeUrl(tokenUrl);
- deployment.setRefreshUrl(refreshUrl);
- deployment.setLogoutUrl(KeycloakUriBuilder.fromUri(logoutUrl));
- deployment.setAccountUrl(accountUrl);
-
+ deployment.setAuthServerBaseUrl(adapterConfig.getAuthServerUrl());
return deployment;
}
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 b1e6e99..c13b1de 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
@@ -169,8 +169,7 @@ public class ServerRequest {
}
}
-
- protected static void error(int status, HttpEntity entity) throws HttpFailure, IOException {
+ public static void error(int status, HttpEntity entity) throws HttpFailure, IOException {
String body = null;
if (entity != null) {
InputStream is = entity.getContent();
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 4d78076..cef3982 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
@@ -48,9 +48,14 @@ public class AuthenticatedActionsValve extends ValveBase {
@Override
public void invoke(Request request, Response response) throws IOException, ServletException {
log.debugv("AuthenticatedActionsValve.invoke {0}", request.getRequestURI());
- AuthenticatedActionsHandler handler = new AuthenticatedActionsHandler(deploymentContext.getDeployment(), new CatalinaHttpFacade(request, response));
- if (handler.handledRequest()) {
- return;
+ CatalinaHttpFacade facade = new CatalinaHttpFacade(request, response);
+ KeycloakDeployment deployment = deploymentContext.resolveDeployment(facade);
+ if (deployment != null && deployment.isConfigured()) {
+ AuthenticatedActionsHandler handler = new AuthenticatedActionsHandler(deployment, new CatalinaHttpFacade(request, response));
+ if (handler.handledRequest()) {
+ return;
+ }
+
}
getNext().invoke(request, response);
}
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 291eb5f..b3e10f2 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
@@ -16,33 +16,20 @@ import org.keycloak.adapters.AdapterConstants;
import org.keycloak.adapters.AdapterDeploymentContext;
import org.keycloak.adapters.AuthChallenge;
import org.keycloak.adapters.AuthOutcome;
+import org.keycloak.adapters.HttpFacade;
import org.keycloak.adapters.KeycloakDeployment;
import org.keycloak.adapters.KeycloakDeploymentBuilder;
import org.keycloak.adapters.PreAuthActionsHandler;
import org.keycloak.adapters.RefreshableKeycloakSecurityContext;
-import org.keycloak.representations.adapters.action.AdminAction;
-import org.keycloak.representations.adapters.action.PushNotBeforeAction;
-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.jose.jws.JWSInput;
-import org.keycloak.jose.jws.crypto.RSAProvider;
-import org.keycloak.representations.adapters.action.LogoutAction;
-import org.keycloak.util.JsonSerialization;
-import org.keycloak.util.StreamUtil;
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.Map;
/**
* Web deployment whose security is managed by a remote OAuth Skeleton Key authentication server
@@ -81,6 +68,7 @@ public class KeycloakAuthenticatorValve extends FormAuthenticator implements Lif
log.info(json);
return new ByteArrayInputStream(json.getBytes());
}
+
private static InputStream getConfigInputStream(Context context) {
InputStream is = getJSONFromServletContext(context.getServletContext());
if (is == null) {
@@ -106,8 +94,6 @@ public class KeycloakAuthenticatorValve extends FormAuthenticator implements Lif
if (configInputStream == null) {
log.warn("No adapter configuration. Keycloak is unconfigured and will deny all requests.");
kd = new KeycloakDeployment();
- kd.setConfigured(false);
-
} else {
kd = KeycloakDeploymentBuilder.build(configInputStream);
}
@@ -120,11 +106,15 @@ public class KeycloakAuthenticatorValve extends FormAuthenticator implements Lif
@Override
public void invoke(Request request, Response response) throws IOException, ServletException {
try {
- PreAuthActionsHandler handler = new PreAuthActionsHandler(userSessionManagement, deploymentContext.getDeployment(), new CatalinaHttpFacade(request, response));
- if (handler.handleRequest()) {
- return;
+ CatalinaHttpFacade facade = new CatalinaHttpFacade(request, response);
+ KeycloakDeployment deployment = deploymentContext.resolveDeployment(facade);
+ if (deployment != null && deployment.isConfigured()) {
+ PreAuthActionsHandler handler = new PreAuthActionsHandler(userSessionManagement, deployment, facade);
+ if (handler.handleRequest()) {
+ return;
+ }
}
- checkKeycloakSession(request);
+ checkKeycloakSession(request, facade);
super.invoke(request, response);
} finally {
}
@@ -132,9 +122,13 @@ public class KeycloakAuthenticatorValve extends FormAuthenticator implements Lif
@Override
public boolean authenticate(Request request, HttpServletResponse response, LoginConfig config) throws IOException {
- if (!deploymentContext.getDeployment().isConfigured()) return false;
CatalinaHttpFacade facade = new CatalinaHttpFacade(request, response);
- CatalinaRequestAuthenticator authenticator = new CatalinaRequestAuthenticator(deploymentContext.getDeployment(), this, userSessionManagement, facade, request);
+ KeycloakDeployment deployment = deploymentContext.resolveDeployment(facade);
+ if (deployment == null || !deployment.isConfigured()) {
+ return false;
+ }
+
+ CatalinaRequestAuthenticator authenticator = new CatalinaRequestAuthenticator(deployment, this, userSessionManagement, facade, request);
AuthOutcome outcome = authenticator.authenticate();
if (outcome == AuthOutcome.AUTHENTICATED) {
if (facade.isEnded()) {
@@ -147,19 +141,19 @@ public class KeycloakAuthenticatorValve extends FormAuthenticator implements Lif
challenge.challenge(facade);
}
return false;
- }
+ }
/**
* Checks that access token is still valid. Will attempt refresh of token if it is not.
*
* @param request
*/
- protected void checkKeycloakSession(Request request) {
+ protected void checkKeycloakSession(Request request, HttpFacade facade) {
if (request.getSessionInternal(false) == null || request.getSessionInternal().getPrincipal() == null) return;
- RefreshableKeycloakSecurityContext session = (RefreshableKeycloakSecurityContext)request.getSessionInternal().getNote(KeycloakSecurityContext.class.getName());
+ RefreshableKeycloakSecurityContext session = (RefreshableKeycloakSecurityContext) request.getSessionInternal().getNote(KeycloakSecurityContext.class.getName());
if (session == null) return;
// just in case session got serialized
- session.setDeployment(deploymentContext.getDeployment());
+ session.setDeployment(deploymentContext.resolveDeployment(facade));
if (session.isActive()) return;
// FYI: A refresh requires same scope, so same roles will be set. Otherwise, refresh will fail and token will
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 68f53ba..648be58 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,6 +14,7 @@ import io.undertow.servlet.api.ServletSessionConfig;
import java.io.ByteArrayInputStream;
import org.jboss.logging.Logger;
import org.keycloak.adapters.AdapterConstants;
+import org.keycloak.adapters.AdapterDeploymentContext;
import org.keycloak.adapters.AuthenticatedActionsHandler;
import org.keycloak.adapters.KeycloakDeployment;
import org.keycloak.adapters.KeycloakDeploymentBuilder;
@@ -80,16 +81,22 @@ public class KeycloakServletExtension implements ServletExtension {
}
log.info("KeycloakServletException initialization");
InputStream is = getConfigInputStream(servletContext);
- if (is == null) throw new RuntimeException("Unable to find realm config in /WEB-INF/keycloak.json or in keycloak subsystem.");
- KeycloakDeployment deployment = KeycloakDeploymentBuilder.build(is);
- UndertowUserSessionManagement userSessionManagement = new UndertowUserSessionManagement(deployment);
- final ServletKeycloakAuthMech mech = createAuthenticationMechanism(deploymentInfo, deployment, userSessionManagement);
+ KeycloakDeployment deployment = null;
+ if (is == null) {
+ throw new RuntimeException("Unable to find realm config in /WEB-INF/keycloak.json or in keycloak subsystem.");
+ } else {
+ deployment = KeycloakDeploymentBuilder.build(is);
+
+ }
+ AdapterDeploymentContext deploymentContext = new AdapterDeploymentContext(deployment);
+ UndertowUserSessionManagement userSessionManagement = new UndertowUserSessionManagement();
+ final ServletKeycloakAuthMech mech = createAuthenticationMechanism(deploymentInfo, deploymentContext, userSessionManagement);
- UndertowAuthenticatedActionsHandler.Wrapper actions = new UndertowAuthenticatedActionsHandler.Wrapper(deployment);
+ UndertowAuthenticatedActionsHandler.Wrapper actions = new UndertowAuthenticatedActionsHandler.Wrapper(deploymentContext);
// setup handlers
- deploymentInfo.addOuterHandlerChainWrapper(new ServletPreAuthActionsHandler.Wrapper(deployment, userSessionManagement));
+ deploymentInfo.addOuterHandlerChainWrapper(new ServletPreAuthActionsHandler.Wrapper(deploymentContext, userSessionManagement));
deploymentInfo.addAuthenticationMechanism("KEYCLOAK", new AuthenticationMechanismFactory() {
@Override
public AuthenticationMechanism create(String s, FormParserFactory formParserFactory, Map<String, String> stringStringMap) {
@@ -121,8 +128,8 @@ public class KeycloakServletExtension implements ServletExtension {
deploymentInfo.setServletSessionConfig(cookieConfig);
}
- protected ServletKeycloakAuthMech createAuthenticationMechanism(DeploymentInfo deploymentInfo, KeycloakDeployment deployment, UndertowUserSessionManagement userSessionManagement) {
+ protected ServletKeycloakAuthMech createAuthenticationMechanism(DeploymentInfo deploymentInfo, AdapterDeploymentContext deploymentContext, UndertowUserSessionManagement userSessionManagement) {
log.info("creating ServletKeycloakAuthMech");
- return new ServletKeycloakAuthMech(deployment, userSessionManagement, deploymentInfo.getConfidentialPortManager());
+ return new ServletKeycloakAuthMech(deploymentContext, userSessionManagement, deploymentInfo.getConfidentialPortManager());
}
}
diff --git a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/ServletKeycloakAuthMech.java b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/ServletKeycloakAuthMech.java
index d72033f..d35b752 100755
--- a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/ServletKeycloakAuthMech.java
+++ b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/ServletKeycloakAuthMech.java
@@ -5,6 +5,7 @@ import io.undertow.security.api.SecurityContext;
import io.undertow.server.HttpServerExchange;
import io.undertow.servlet.api.ConfidentialPortManager;
import io.undertow.util.AttachmentKey;
+import org.keycloak.adapters.AdapterDeploymentContext;
import org.keycloak.adapters.AuthChallenge;
import org.keycloak.adapters.AuthOutcome;
import org.keycloak.adapters.KeycloakDeployment;
@@ -16,12 +17,12 @@ import org.keycloak.adapters.KeycloakDeployment;
public class ServletKeycloakAuthMech implements AuthenticationMechanism {
public static final AttachmentKey<AuthChallenge> KEYCLOAK_CHALLENGE_ATTACHMENT_KEY = AttachmentKey.create(AuthChallenge.class);
- protected KeycloakDeployment deployment;
+ protected AdapterDeploymentContext deploymentContext;
protected UndertowUserSessionManagement userSessionManagement;
protected ConfidentialPortManager portManager;
- public ServletKeycloakAuthMech(KeycloakDeployment deployment, UndertowUserSessionManagement userSessionManagement, ConfidentialPortManager portManager) {
- this.deployment = deployment;
+ public ServletKeycloakAuthMech(AdapterDeploymentContext deploymentContext, UndertowUserSessionManagement userSessionManagement, ConfidentialPortManager portManager) {
+ this.deploymentContext = deploymentContext;
this.userSessionManagement = userSessionManagement;
this.portManager = portManager;
}
@@ -29,7 +30,11 @@ public class ServletKeycloakAuthMech implements AuthenticationMechanism {
@Override
public AuthenticationMechanismOutcome authenticate(HttpServerExchange exchange, SecurityContext securityContext) {
UndertowHttpFacade facade = new UndertowHttpFacade(exchange);
- ServletRequestAuthenticator authenticator = createRequestAuthenticator(exchange, securityContext, facade);
+ KeycloakDeployment deployment = deploymentContext.resolveDeployment(facade);
+ if (!deployment.isConfigured()) {
+ return AuthenticationMechanismOutcome.NOT_ATTEMPTED;
+ }
+ ServletRequestAuthenticator authenticator = createRequestAuthenticator(deployment, exchange, securityContext, facade);
AuthOutcome outcome = authenticator.authenticate();
if (outcome == AuthOutcome.AUTHENTICATED) {
return AuthenticationMechanismOutcome.AUTHENTICATED;
@@ -45,7 +50,7 @@ public class ServletKeycloakAuthMech implements AuthenticationMechanism {
return AuthenticationMechanismOutcome.NOT_ATTEMPTED;
}
- protected ServletRequestAuthenticator createRequestAuthenticator(HttpServerExchange exchange, SecurityContext securityContext, UndertowHttpFacade facade) {
+ protected ServletRequestAuthenticator createRequestAuthenticator(KeycloakDeployment deployment, HttpServerExchange exchange, SecurityContext securityContext, UndertowHttpFacade facade) {
int confidentialPort = 8443;
if (portManager != null) confidentialPort = portManager.getConfidentialPort(exchange);
return new ServletRequestAuthenticator(facade, deployment,
diff --git a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/ServletPreAuthActionsHandler.java b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/ServletPreAuthActionsHandler.java
index 30aa6c1..bae4217 100755
--- a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/ServletPreAuthActionsHandler.java
+++ b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/ServletPreAuthActionsHandler.java
@@ -5,6 +5,7 @@ import io.undertow.server.HttpHandler;
import io.undertow.server.HttpServerExchange;
import io.undertow.servlet.handlers.ServletRequestContext;
import org.jboss.logging.Logger;
+import org.keycloak.adapters.AdapterDeploymentContext;
import org.keycloak.adapters.PreAuthActionsHandler;
import org.keycloak.adapters.KeycloakDeployment;
@@ -17,38 +18,42 @@ public class ServletPreAuthActionsHandler implements HttpHandler {
private static final Logger log = Logger.getLogger(ServletPreAuthActionsHandler.class);
protected HttpHandler next;
protected UndertowUserSessionManagement userSessionManagement;
- protected KeycloakDeployment deployment;
+ protected AdapterDeploymentContext deploymentContext;
public static class Wrapper implements HandlerWrapper {
- protected KeycloakDeployment deployment;
+ protected AdapterDeploymentContext deploymentContext;
protected UndertowUserSessionManagement userSessionManagement;
- public Wrapper(KeycloakDeployment deployment, UndertowUserSessionManagement userSessionManagement) {
- this.deployment = deployment;
+ public Wrapper(AdapterDeploymentContext deploymentContext, UndertowUserSessionManagement userSessionManagement) {
+ this.deploymentContext = deploymentContext;
this.userSessionManagement = userSessionManagement;
}
@Override
public HttpHandler wrap(HttpHandler handler) {
- return new ServletPreAuthActionsHandler(deployment, userSessionManagement, handler);
+ return new ServletPreAuthActionsHandler(deploymentContext, userSessionManagement, handler);
}
}
- protected ServletPreAuthActionsHandler(KeycloakDeployment deployment,
+ protected ServletPreAuthActionsHandler(AdapterDeploymentContext deploymentContext,
UndertowUserSessionManagement userSessionManagement,
HttpHandler next) {
this.next = next;
- this.deployment = deployment;
+ this.deploymentContext = deploymentContext;
this.userSessionManagement = userSessionManagement;
}
@Override
public void handleRequest(HttpServerExchange exchange) throws Exception {
- final ServletRequestContext servletRequestContext = exchange.getAttachment(ServletRequestContext.ATTACHMENT_KEY);
- SessionManagementBridge bridge = new SessionManagementBridge(userSessionManagement, servletRequestContext.getDeployment().getSessionManager());
- PreAuthActionsHandler handler = new PreAuthActionsHandler(bridge, deployment, new UndertowHttpFacade(exchange));
- if (handler.handleRequest()) return;
+ UndertowHttpFacade facade = new UndertowHttpFacade(exchange);
+ KeycloakDeployment deployment = deploymentContext.resolveDeployment(facade);
+ if (deployment != null && deployment.isConfigured()) {
+ final ServletRequestContext servletRequestContext = exchange.getAttachment(ServletRequestContext.ATTACHMENT_KEY);
+ SessionManagementBridge bridge = new SessionManagementBridge(userSessionManagement, servletRequestContext.getDeployment().getSessionManager());
+ PreAuthActionsHandler handler = new PreAuthActionsHandler(bridge, deployment, facade);
+ if (handler.handleRequest()) return;
+ }
next.handleRequest(exchange);
}
}
diff --git a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/UndertowAuthenticatedActionsHandler.java b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/UndertowAuthenticatedActionsHandler.java
index 8d641c0..294daee 100755
--- a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/UndertowAuthenticatedActionsHandler.java
+++ b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/UndertowAuthenticatedActionsHandler.java
@@ -4,6 +4,7 @@ import io.undertow.server.HandlerWrapper;
import io.undertow.server.HttpHandler;
import io.undertow.server.HttpServerExchange;
import org.jboss.logging.Logger;
+import org.keycloak.adapters.AdapterDeploymentContext;
import org.keycloak.adapters.AuthenticatedActionsHandler;
import org.keycloak.adapters.KeycloakDeployment;
@@ -15,32 +16,36 @@ import org.keycloak.adapters.KeycloakDeployment;
*/
public class UndertowAuthenticatedActionsHandler implements HttpHandler {
private static final Logger log = Logger.getLogger(UndertowAuthenticatedActionsHandler.class);
- protected KeycloakDeployment deployment;
+ protected AdapterDeploymentContext deploymentContext;
protected HttpHandler next;
public static class Wrapper implements HandlerWrapper {
- protected KeycloakDeployment deployment;
+ protected AdapterDeploymentContext deploymentContext;
- public Wrapper(KeycloakDeployment deployment) {
- this.deployment = deployment;
+ public Wrapper(AdapterDeploymentContext deploymentContext) {
+ this.deploymentContext = deploymentContext;
}
@Override
public HttpHandler wrap(HttpHandler handler) {
- return new UndertowAuthenticatedActionsHandler(deployment, handler);
+ return new UndertowAuthenticatedActionsHandler(deploymentContext, handler);
}
}
- protected UndertowAuthenticatedActionsHandler(KeycloakDeployment deployment, HttpHandler next) {
- this.deployment = deployment;
+ protected UndertowAuthenticatedActionsHandler(AdapterDeploymentContext deploymentContext, HttpHandler next) {
+ this.deploymentContext = deploymentContext;
this.next = next;
}
@Override
public void handleRequest(HttpServerExchange exchange) throws Exception {
- AuthenticatedActionsHandler handler = new AuthenticatedActionsHandler(deployment, new UndertowHttpFacade(exchange));
- if (handler.handledRequest()) return;
+ UndertowHttpFacade facade = new UndertowHttpFacade(exchange);
+ KeycloakDeployment deployment = deploymentContext.resolveDeployment(facade);
+ if (deployment != null && deployment.isConfigured()) {
+ AuthenticatedActionsHandler handler = new AuthenticatedActionsHandler(deployment, facade);
+ if (handler.handledRequest()) return;
+ }
next.handleRequest(exchange);
}
}
diff --git a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/UndertowUserSessionManagement.java b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/UndertowUserSessionManagement.java
index ed7ad46..ff75800 100755
--- a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/UndertowUserSessionManagement.java
+++ b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/UndertowUserSessionManagement.java
@@ -33,11 +33,6 @@ public class UndertowUserSessionManagement implements SessionListener {
private static final String AUTH_SESSION_NAME = CachedAuthenticatedSessionHandler.class.getName() + ".AuthenticatedSession";
protected ConcurrentHashMap<String, UserSessions> userSessionMap = new ConcurrentHashMap<String, UserSessions>();
- protected KeycloakDeployment deployment;
-
- public UndertowUserSessionManagement(KeycloakDeployment deployment) {
- this.deployment = deployment;
- }
public static class UserSessions {
protected Set<String> sessionIds = new HashSet<String>();
diff --git a/integration/wildfly-adapter/src/main/java/org/keycloak/adapters/wildfly/WildflyAuthenticationMechanism.java b/integration/wildfly-adapter/src/main/java/org/keycloak/adapters/wildfly/WildflyAuthenticationMechanism.java
index 99c411c..58639df 100755
--- a/integration/wildfly-adapter/src/main/java/org/keycloak/adapters/wildfly/WildflyAuthenticationMechanism.java
+++ b/integration/wildfly-adapter/src/main/java/org/keycloak/adapters/wildfly/WildflyAuthenticationMechanism.java
@@ -3,6 +3,7 @@ package org.keycloak.adapters.wildfly;
import io.undertow.security.api.SecurityContext;
import io.undertow.server.HttpServerExchange;
import io.undertow.servlet.api.ConfidentialPortManager;
+import org.keycloak.adapters.AdapterDeploymentContext;
import org.keycloak.adapters.KeycloakDeployment;
import org.keycloak.adapters.undertow.ServletKeycloakAuthMech;
import org.keycloak.adapters.undertow.ServletRequestAuthenticator;
@@ -15,14 +16,14 @@ import org.keycloak.adapters.undertow.UndertowUserSessionManagement;
*/
public class WildflyAuthenticationMechanism extends ServletKeycloakAuthMech {
- public WildflyAuthenticationMechanism(KeycloakDeployment deployment,
+ public WildflyAuthenticationMechanism(AdapterDeploymentContext deploymentContext,
UndertowUserSessionManagement userSessionManagement,
ConfidentialPortManager portManager) {
- super(deployment, userSessionManagement, portManager);
+ super(deploymentContext, userSessionManagement, portManager);
}
@Override
- protected ServletRequestAuthenticator createRequestAuthenticator(HttpServerExchange exchange, SecurityContext securityContext, UndertowHttpFacade facade) {
+ protected ServletRequestAuthenticator createRequestAuthenticator(KeycloakDeployment deployment, HttpServerExchange exchange, SecurityContext securityContext, UndertowHttpFacade facade) {
return new WildflyRequestAuthenticator(facade, deployment,
portManager.getConfidentialPort(exchange), securityContext, exchange, userSessionManagement);
}
diff --git a/integration/wildfly-adapter/src/main/java/org/keycloak/adapters/wildfly/WildflyKeycloakServletExtension.java b/integration/wildfly-adapter/src/main/java/org/keycloak/adapters/wildfly/WildflyKeycloakServletExtension.java
index e0623ad..197f192 100755
--- a/integration/wildfly-adapter/src/main/java/org/keycloak/adapters/wildfly/WildflyKeycloakServletExtension.java
+++ b/integration/wildfly-adapter/src/main/java/org/keycloak/adapters/wildfly/WildflyKeycloakServletExtension.java
@@ -2,6 +2,7 @@ package org.keycloak.adapters.wildfly;
import io.undertow.servlet.api.DeploymentInfo;
import org.jboss.logging.Logger;
+import org.keycloak.adapters.AdapterDeploymentContext;
import org.keycloak.adapters.KeycloakDeployment;
import org.keycloak.adapters.undertow.KeycloakServletExtension;
import org.keycloak.adapters.undertow.ServletKeycloakAuthMech;
@@ -15,10 +16,10 @@ public class WildflyKeycloakServletExtension extends KeycloakServletExtension {
protected static Logger log = Logger.getLogger(WildflyKeycloakServletExtension.class);
@Override
- protected ServletKeycloakAuthMech createAuthenticationMechanism(DeploymentInfo deploymentInfo, KeycloakDeployment deployment,
+ protected ServletKeycloakAuthMech createAuthenticationMechanism(DeploymentInfo deploymentInfo, AdapterDeploymentContext deploymentContext,
UndertowUserSessionManagement userSessionManagement) {
log.info("creating WildflyAuthenticationMechanism");
- return new WildflyAuthenticationMechanism(deployment, userSessionManagement, deploymentInfo.getConfidentialPortManager());
+ return new WildflyAuthenticationMechanism(deploymentContext, userSessionManagement, deploymentInfo.getConfidentialPortManager());
}
}
pom.xml 2(+1 -1)
diff --git a/pom.xml b/pom.xml
index 1bde0c2..34ed817 100755
--- a/pom.xml
+++ b/pom.xml
@@ -102,7 +102,7 @@
<module>server</module>
<module>timer</module>
<module>bundled-war-example</module>
- <!-- <module>project-integrations</module> -->
+ <module>project-integrations</module>
</modules>
<dependencyManagement>