diff --git a/events/api/src/main/java/org/keycloak/events/Details.java b/events/api/src/main/java/org/keycloak/events/Details.java
index 50921dd892..1ca58ecce4 100755
--- a/events/api/src/main/java/org/keycloak/events/Details.java
+++ b/events/api/src/main/java/org/keycloak/events/Details.java
@@ -19,5 +19,5 @@ public interface Details {
String REFRESH_TOKEN_ID = "refresh_token_id";
String VALIDATE_ACCESS_TOKEN = "validate_access_token";
String UPDATED_REFRESH_TOKEN_ID = "updated_refresh_token_id";
-
+ String NODE_HOST = "node_host";
}
diff --git a/examples/demo-template/customer-app/src/main/webapp/customers/session.jsp b/examples/demo-template/customer-app/src/main/webapp/customers/session.jsp
index ba8583dff9..2bd9d1664a 100755
--- a/examples/demo-template/customer-app/src/main/webapp/customers/session.jsp
+++ b/examples/demo-template/customer-app/src/main/webapp/customers/session.jsp
@@ -3,13 +3,13 @@
<%@ page import="org.keycloak.ServiceUrlConstants" %>
<%@ page import="org.keycloak.example.CustomerDatabaseClient" %>
<%@ page import="org.keycloak.representations.IDToken" %>
-<%@ page import="org.keycloak.util.UriUtils" %>
+<%@ page import="org.keycloak.util.HostUtils" %>
Customer Session Page
- Your hostname: <%= UriUtils.getHostName() %>
+ Your hostname: <%= HostUtils.getHostName() %>
Your session ID: <%= request.getSession().getId() %>
You visited this page <%= CustomerDatabaseClient.increaseAndGetCounter(request) %> times.
diff --git a/examples/demo-template/testrealm.json b/examples/demo-template/testrealm.json
index a2a3a96bfe..da92138a4e 100755
--- a/examples/demo-template/testrealm.json
+++ b/examples/demo-template/testrealm.json
@@ -147,8 +147,7 @@
"enabled": true,
"adminUrl": "/database",
"baseUrl": "/database",
- "bearerOnly": true,
- "secret": "password"
+ "bearerOnly": true
}
],
"oauthClients": [
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 1095b47ce7..c2d60d10f1 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
@@ -85,12 +85,16 @@ public class KeycloakDeployment {
return authServerBaseUrl;
}
- public void setAuthServerBaseUrl(String authServerBaseUrl, AdapterConfig config) {
- this.authServerBaseUrl = authServerBaseUrl;
- if (authServerBaseUrl == null) return;
+ public void setAuthServerBaseUrl(AdapterConfig config) {
+ this.authServerBaseUrl = config.getAuthServerUrl();
+ if (authServerBaseUrl == null && config.getAuthServerUrlForBackendRequests() == null) return;
- URI uri = URI.create(authServerBaseUrl);
- if (uri.getHost() == null) {
+ URI authServerUri = null;
+ if (authServerBaseUrl != null) {
+ authServerUri = URI.create(authServerBaseUrl);
+ }
+
+ if (authServerUri == null || authServerUri.getHost() == null) {
String authServerURLForBackendReqs = config.getAuthServerUrlForBackendRequests();
if (authServerURLForBackendReqs != null) {
relativeUrls = RelativeUrlsUsed.BROWSER_ONLY;
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 cbb5fef00e..8913dd4e30 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
@@ -73,7 +73,7 @@ public class KeycloakDeploymentBuilder {
if (adapterConfig.getAuthServerUrl() == null && (!deployment.isBearerOnly() || realmKeyPem == null)) {
throw new RuntimeException("You must specify auth-url");
}
- deployment.setAuthServerBaseUrl(adapterConfig.getAuthServerUrl(), adapterConfig);
+ deployment.setAuthServerBaseUrl(adapterConfig);
log.debug("Use authServerUrl: " + deployment.getAuthServerBaseUrl() + ", codeUrl: " + deployment.getCodeUrl() + ", relativeUrls: " + deployment.getRelativeUrls());
return deployment;
diff --git a/integration/adapter-core/src/main/java/org/keycloak/adapters/NodesRegistrationLifecycle.java b/integration/adapter-core/src/main/java/org/keycloak/adapters/NodesRegistrationLifecycle.java
deleted file mode 100644
index b344702812..0000000000
--- a/integration/adapter-core/src/main/java/org/keycloak/adapters/NodesRegistrationLifecycle.java
+++ /dev/null
@@ -1,120 +0,0 @@
-package org.keycloak.adapters;
-
-import java.io.IOException;
-import java.util.Timer;
-import java.util.TimerTask;
-
-import org.jboss.logging.Logger;
-import org.keycloak.enums.RelativeUrlsUsed;
-import org.keycloak.util.HostUtils;
-
-/**
- * @author Marek Posolda
- */
-public class NodesRegistrationLifecycle {
-
- private static final Logger log = Logger.getLogger(NodesRegistrationLifecycle.class);
-
- private final KeycloakDeployment deployment;
- private final Timer timer;
-
- // True if at least one event was successfully sent
- private volatile boolean registered = false;
-
- public NodesRegistrationLifecycle(KeycloakDeployment deployment) {
- this.deployment = deployment;
- this.timer = new Timer();
- }
-
- public void start() {
- if (!deployment.isRegisterNodeAtStartup() && deployment.getRegisterNodePeriod() <= 0) {
- log.info("Skip registration of cluster nodes at startup");
- return;
- }
-
- if (deployment.getRelativeUrls() == RelativeUrlsUsed.ALL_REQUESTS) {
- log.warn("Skip registration of cluster nodes at startup as Keycloak node can't be contacted. Make sure to not use relative URI in adapters configuration!");
- return;
- }
-
- if (deployment.isRegisterNodeAtStartup()) {
- boolean success = sendRegistrationEvent();
- if (!success) {
- throw new IllegalStateException("Failed to register node to keycloak at startup");
- }
- }
-
- if (deployment.getRegisterNodePeriod() > 0) {
- addPeriodicListener();
- }
- }
-
- public void stop() {
- removePeriodicListener();
- if (registered) {
- sendUnregistrationEvent();
- }
- }
-
- protected void addPeriodicListener() {
- TimerTask task = new TimerTask() {
-
- @Override
- public void run() {
- sendRegistrationEvent();
- }
- };
-
- long interval = deployment.getRegisterNodePeriod() * 1000;
- log.info("Setup of periodic re-registration event sending each " + interval + " ms");
- timer.schedule(task, interval, interval);
- }
-
- protected void removePeriodicListener() {
- timer.cancel();
- }
-
- protected boolean sendRegistrationEvent() {
- log.info("Sending registration event right now");
-
- String host = HostUtils.getIpAddress();
- try {
- ServerRequest.invokeRegisterNode(deployment, host);
- log.infof("Node '%s' successfully registered in Keycloak", host);
- registered = true;
- return true;
- } catch (ServerRequest.HttpFailure failure) {
- log.error("failed to register node to keycloak");
- log.error("status from server: " + failure.getStatus());
- if (failure.getError() != null) {
- log.error(" " + failure.getError());
- }
- return false;
- } catch (IOException e) {
- log.error("failed to register node to keycloak", e);
- return false;
- }
- }
-
- protected boolean sendUnregistrationEvent() {
- log.info("Sending UNregistration event right now");
-
- String host = HostUtils.getIpAddress();
- try {
- ServerRequest.invokeUnregisterNode(deployment, host);
- log.infof("Node '%s' successfully unregistered from Keycloak", host);
- return true;
- } catch (ServerRequest.HttpFailure failure) {
- log.error("failed to unregister node from keycloak");
- log.error("status from server: " + failure.getStatus());
- if (failure.getError() != null) {
- log.error(" " + failure.getError());
- }
- return false;
- } catch (IOException e) {
- log.error("failed to unregister node from keycloak", e);
- return false;
- }
- }
-
-}
diff --git a/integration/adapter-core/src/main/java/org/keycloak/adapters/NodesRegistrationManagement.java b/integration/adapter-core/src/main/java/org/keycloak/adapters/NodesRegistrationManagement.java
new file mode 100644
index 0000000000..5365620d8b
--- /dev/null
+++ b/integration/adapter-core/src/main/java/org/keycloak/adapters/NodesRegistrationManagement.java
@@ -0,0 +1,117 @@
+package org.keycloak.adapters;
+
+import java.io.IOException;
+import java.util.Collection;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
+
+import org.jboss.logging.Logger;
+import org.keycloak.util.HostUtils;
+import org.keycloak.util.Time;
+
+/**
+ * @author Marek Posolda
+ */
+public class NodesRegistrationManagement {
+
+ private static final Logger log = Logger.getLogger(NodesRegistrationManagement.class);
+
+ private final Map nodeRegistrations = new ConcurrentHashMap();
+ private final Executor executor = Executors.newSingleThreadExecutor();
+
+ // Sending registration event during first request to application or if re-registration is needed
+ public void tryRegister(final KeycloakDeployment resolvedDeployment) {
+ if (resolvedDeployment.isRegisterNodeAtStartup()) {
+ final String registrationUri = resolvedDeployment.getRegisterNodeUrl();
+ if (needRefreshRegistration(registrationUri, resolvedDeployment)) {
+ Runnable runnable = new Runnable() {
+
+ @Override
+ public void run() {
+ // Need to check it again in case that executor triggered by other thread already finished computation in the meantime
+ if (needRefreshRegistration(registrationUri, resolvedDeployment)) {
+ sendRegistrationEvent(resolvedDeployment);
+ }
+ }
+ };
+ executor.execute(runnable);
+ }
+ }
+ }
+
+ private boolean needRefreshRegistration(String registrationUri, KeycloakDeployment resolvedDeployment) {
+ NodeRegistrationContext currentRegistration = nodeRegistrations.get(registrationUri);
+ /// We don't yet have any registration for this node
+ if (currentRegistration == null) {
+ return true;
+ }
+
+ return currentRegistration.lastRegistrationTime + resolvedDeployment.getRegisterNodePeriod() < Time.currentTime();
+ }
+
+ /**
+ * Called during undeployment or server stop. De-register from all previously registered deployments
+ */
+ public void stop() {
+ Collection allRegistrations = nodeRegistrations.values();
+ for (NodeRegistrationContext registration : allRegistrations) {
+ sendUnregistrationEvent(registration.resolvedDeployment);
+ }
+ }
+
+ protected void sendRegistrationEvent(KeycloakDeployment deployment) {
+ log.info("Sending registration event right now");
+
+ String host = HostUtils.getIpAddress();
+ try {
+ ServerRequest.invokeRegisterNode(deployment, host);
+ NodeRegistrationContext regContext = new NodeRegistrationContext(Time.currentTime(), deployment);
+ nodeRegistrations.put(deployment.getRegisterNodeUrl(), regContext);
+ log.infof("Node '%s' successfully registered in Keycloak", host);
+ } catch (ServerRequest.HttpFailure failure) {
+ log.error("failed to register node to keycloak");
+ log.error("status from server: " + failure.getStatus());
+ if (failure.getError() != null) {
+ log.error(" " + failure.getError());
+ }
+ } catch (IOException e) {
+ log.error("failed to register node to keycloak", e);
+ }
+ }
+
+ protected boolean sendUnregistrationEvent(KeycloakDeployment deployment) {
+ log.info("Sending Unregistration event right now");
+
+ String host = HostUtils.getIpAddress();
+ try {
+ ServerRequest.invokeUnregisterNode(deployment, host);
+ log.infof("Node '%s' successfully unregistered from Keycloak", host);
+ return true;
+ } catch (ServerRequest.HttpFailure failure) {
+ log.error("failed to unregister node from keycloak");
+ log.error("status from server: " + failure.getStatus());
+ if (failure.getError() != null) {
+ log.error(" " + failure.getError());
+ }
+ return false;
+ } catch (IOException e) {
+ log.error("failed to unregister node from keycloak", e);
+ return false;
+ }
+ }
+
+ public static class NodeRegistrationContext {
+
+ private final Integer lastRegistrationTime;
+ // deployment instance used for registration request
+ private final KeycloakDeployment resolvedDeployment;
+
+ public NodeRegistrationContext(Integer lastRegTime, KeycloakDeployment deployment) {
+ this.lastRegistrationTime = lastRegTime;
+ this.resolvedDeployment = deployment;
+ }
+ }
+
+}
diff --git a/integration/adapter-core/src/main/java/org/keycloak/adapters/PreAuthActionsHandler.java b/integration/adapter-core/src/main/java/org/keycloak/adapters/PreAuthActionsHandler.java
index a55fb97251..83cad53a19 100755
--- a/integration/adapter-core/src/main/java/org/keycloak/adapters/PreAuthActionsHandler.java
+++ b/integration/adapter-core/src/main/java/org/keycloak/adapters/PreAuthActionsHandler.java
@@ -58,6 +58,7 @@ public class PreAuthActionsHandler {
handleVersion();
return true;
} else if (requestUri.endsWith(AdapterConstants.K_TEST_AVAILABLE)) {
+ if (!resolveDeployment()) return true;
handleTestAvailable();
return true;
}
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 438ad63cfe..f4a3142854 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
@@ -231,6 +231,10 @@ public class ServerRequest {
}
public static void invokeClientManagementRequest(HttpClient client, String host, String endpointUrl, String clientId, Map credentials) throws HttpFailure, IOException {
+ if (endpointUrl == null) {
+ throw new IOException("You need to configure URI for register/unregister node for application " + clientId);
+ }
+
List formparams = new ArrayList();
formparams.add(new BasicNameValuePair(AdapterConstants.APPLICATION_CLUSTER_HOST, host));
@@ -240,6 +244,8 @@ public class ServerRequest {
if (clientSecret != null) {
String authorization = BasicAuthHelper.createHeader(clientId, clientSecret);
post.setHeader("Authorization", authorization);
+ } else {
+ throw new IOException("You need to configure clientSecret for register/unregister node for application " + clientId);
}
UrlEncodedFormEntity form = new UrlEncodedFormEntity(formparams, "UTF-8");
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 b21653eb40..8b40abb567 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
@@ -21,7 +21,7 @@ import org.keycloak.adapters.AuthOutcome;
import org.keycloak.adapters.HttpFacade;
import org.keycloak.adapters.KeycloakDeployment;
import org.keycloak.adapters.KeycloakDeploymentBuilder;
-import org.keycloak.adapters.NodesRegistrationLifecycle;
+import org.keycloak.adapters.NodesRegistrationManagement;
import org.keycloak.adapters.PreAuthActionsHandler;
import org.keycloak.adapters.RefreshableKeycloakSecurityContext;
@@ -47,7 +47,7 @@ public class KeycloakAuthenticatorValve extends FormAuthenticator implements Lif
private static final Logger log = Logger.getLogger(KeycloakAuthenticatorValve.class);
protected CatalinaUserSessionManagement userSessionManagement = new CatalinaUserSessionManagement();
protected AdapterDeploymentContext deploymentContext;
- protected NodesRegistrationLifecycle nodesRegistrationLifecycle;
+ protected NodesRegistrationManagement nodesRegistrationManagement;
@Override
@@ -127,12 +127,11 @@ public class KeycloakAuthenticatorValve extends FormAuthenticator implements Lif
AuthenticatedActionsValve actions = new AuthenticatedActionsValve(deploymentContext, getNext(), getContainer(), getController());
setNext(actions);
- nodesRegistrationLifecycle = new NodesRegistrationLifecycle(kd);
- nodesRegistrationLifecycle.start();
+ nodesRegistrationManagement = new NodesRegistrationManagement();
}
protected void beforeStop() {
- nodesRegistrationLifecycle.stop();
+ nodesRegistrationManagement.stop();
}
@Override
@@ -166,6 +165,8 @@ public class KeycloakAuthenticatorValve extends FormAuthenticator implements Lif
return false;
}
+ nodesRegistrationManagement.tryRegister(deployment);
+
CatalinaRequestAuthenticator authenticator = new CatalinaRequestAuthenticator(deployment, this, userSessionManagement, facade, request);
AuthOutcome outcome = authenticator.authenticate();
if (outcome == AuthOutcome.AUTHENTICATED) {
diff --git a/integration/tomcat7/adapter/src/main/java/org/keycloak/adapters/tomcat7/KeycloakAuthenticatorValve.java b/integration/tomcat7/adapter/src/main/java/org/keycloak/adapters/tomcat7/KeycloakAuthenticatorValve.java
index 0d45009f24..94447a1a59 100755
--- a/integration/tomcat7/adapter/src/main/java/org/keycloak/adapters/tomcat7/KeycloakAuthenticatorValve.java
+++ b/integration/tomcat7/adapter/src/main/java/org/keycloak/adapters/tomcat7/KeycloakAuthenticatorValve.java
@@ -20,7 +20,7 @@ import org.keycloak.adapters.AuthOutcome;
import org.keycloak.adapters.HttpFacade;
import org.keycloak.adapters.KeycloakDeployment;
import org.keycloak.adapters.KeycloakDeploymentBuilder;
-import org.keycloak.adapters.NodesRegistrationLifecycle;
+import org.keycloak.adapters.NodesRegistrationManagement;
import org.keycloak.adapters.PreAuthActionsHandler;
import org.keycloak.adapters.RefreshableKeycloakSecurityContext;
import org.keycloak.adapters.ServerRequest;
@@ -48,7 +48,7 @@ public class KeycloakAuthenticatorValve extends FormAuthenticator implements Lif
private final static Logger log = Logger.getLogger(""+KeycloakAuthenticatorValve.class);
protected CatalinaUserSessionManagement userSessionManagement = new CatalinaUserSessionManagement();
protected AdapterDeploymentContext deploymentContext;
- protected NodesRegistrationLifecycle nodesRegistrationLifecycle;
+ protected NodesRegistrationManagement nodesRegistrationManagement;
@Override
public void lifecycleEvent(LifecycleEvent event) {
@@ -105,12 +105,11 @@ public class KeycloakAuthenticatorValve extends FormAuthenticator implements Lif
AuthenticatedActionsValve actions = new AuthenticatedActionsValve(deploymentContext, getNext(), getContainer(), getObjectName());
setNext(actions);
- nodesRegistrationLifecycle = new NodesRegistrationLifecycle(kd);
- nodesRegistrationLifecycle.start();
+ nodesRegistrationManagement = new NodesRegistrationManagement();
}
protected void beforeStop() {
- nodesRegistrationLifecycle.stop();
+ nodesRegistrationManagement.stop();
}
private static InputStream getJSONFromServletContext(ServletContext servletContext) {
@@ -166,6 +165,8 @@ public class KeycloakAuthenticatorValve extends FormAuthenticator implements Lif
return false;
}
+ nodesRegistrationManagement.tryRegister(deployment);
+
CatalinaRequestAuthenticator authenticator = new CatalinaRequestAuthenticator(deployment, this, userSessionManagement, facade, request);
AuthOutcome outcome = authenticator.authenticate();
if (outcome == AuthOutcome.AUTHENTICATED) {
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 9919dfa834..5c7a16b4bd 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
@@ -36,7 +36,7 @@ import org.keycloak.adapters.AdapterConstants;
import org.keycloak.adapters.AdapterDeploymentContext;
import org.keycloak.adapters.KeycloakDeployment;
import org.keycloak.adapters.KeycloakDeploymentBuilder;
-import org.keycloak.adapters.NodesRegistrationLifecycle;
+import org.keycloak.adapters.NodesRegistrationManagement;
import javax.servlet.ServletContext;
import java.io.ByteArrayInputStream;
@@ -112,7 +112,8 @@ public class KeycloakServletExtension implements ServletExtension {
AdapterDeploymentContext deploymentContext = new AdapterDeploymentContext(deployment);
servletContext.setAttribute(AdapterDeploymentContext.class.getName(), deploymentContext);
UndertowUserSessionManagement userSessionManagement = new UndertowUserSessionManagement();
- final ServletKeycloakAuthMech mech = createAuthenticationMechanism(deploymentInfo, deploymentContext, userSessionManagement);
+ final NodesRegistrationManagement nodesRegistrationManagement = new NodesRegistrationManagement();
+ final ServletKeycloakAuthMech mech = createAuthenticationMechanism(deploymentInfo, deploymentContext, userSessionManagement, nodesRegistrationManagement);
UndertowAuthenticatedActionsHandler.Wrapper actions = new UndertowAuthenticatedActionsHandler.Wrapper(deploymentContext);
@@ -149,20 +150,20 @@ public class KeycloakServletExtension implements ServletExtension {
cookieConfig.setPath(deploymentInfo.getContextPath());
deploymentInfo.setServletSessionConfig(cookieConfig);
- deploymentInfo.addListener(new ListenerInfo(UndertowNodesRegistrationLifecycleWrapper.class, new InstanceFactory() {
+ deploymentInfo.addListener(new ListenerInfo(UndertowNodesRegistrationManagementWrapper.class, new InstanceFactory() {
@Override
- public InstanceHandle createInstance() throws InstantiationException {
- NodesRegistrationLifecycle nodesRegistration = new NodesRegistrationLifecycle(deployment);
- UndertowNodesRegistrationLifecycleWrapper listener = new UndertowNodesRegistrationLifecycleWrapper(nodesRegistration);
- return new ImmediateInstanceHandle(listener);
+ public InstanceHandle createInstance() throws InstantiationException {
+ UndertowNodesRegistrationManagementWrapper listener = new UndertowNodesRegistrationManagementWrapper(nodesRegistrationManagement);
+ return new ImmediateInstanceHandle(listener);
}
}));
}
- protected ServletKeycloakAuthMech createAuthenticationMechanism(DeploymentInfo deploymentInfo, AdapterDeploymentContext deploymentContext, UndertowUserSessionManagement userSessionManagement) {
+ protected ServletKeycloakAuthMech createAuthenticationMechanism(DeploymentInfo deploymentInfo, AdapterDeploymentContext deploymentContext, UndertowUserSessionManagement userSessionManagement,
+ NodesRegistrationManagement nodesRegistrationManagement) {
log.debug("creating ServletKeycloakAuthMech");
- return new ServletKeycloakAuthMech(deploymentContext, userSessionManagement, deploymentInfo.getConfidentialPortManager());
+ return new ServletKeycloakAuthMech(deploymentContext, userSessionManagement, nodesRegistrationManagement, 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 7e1ee378e5..7303bda5bb 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
@@ -26,6 +26,7 @@ import org.jboss.logging.Logger;
import org.keycloak.KeycloakSecurityContext;
import org.keycloak.adapters.AdapterDeploymentContext;
import org.keycloak.adapters.KeycloakDeployment;
+import org.keycloak.adapters.NodesRegistrationManagement;
import org.keycloak.adapters.RequestAuthenticator;
import javax.servlet.http.HttpServletRequest;
@@ -40,11 +41,13 @@ public class ServletKeycloakAuthMech extends UndertowKeycloakAuthMech {
private static final Logger log = Logger.getLogger(ServletKeycloakAuthMech.class);
protected UndertowUserSessionManagement userSessionManagement;
+ protected NodesRegistrationManagement nodesRegistrationManagement;
protected ConfidentialPortManager portManager;
- public ServletKeycloakAuthMech(AdapterDeploymentContext deploymentContext, UndertowUserSessionManagement userSessionManagement, ConfidentialPortManager portManager) {
+ public ServletKeycloakAuthMech(AdapterDeploymentContext deploymentContext, UndertowUserSessionManagement userSessionManagement, NodesRegistrationManagement nodesRegistrationManagement, ConfidentialPortManager portManager) {
super(deploymentContext);
this.userSessionManagement = userSessionManagement;
+ this.nodesRegistrationManagement = nodesRegistrationManagement;
this.portManager = portManager;
}
@@ -56,6 +59,8 @@ public class ServletKeycloakAuthMech extends UndertowKeycloakAuthMech {
return AuthenticationMechanismOutcome.NOT_ATTEMPTED;
}
+ nodesRegistrationManagement.tryRegister(deployment);
+
RequestAuthenticator authenticator = createRequestAuthenticator(deployment, exchange, securityContext, facade);
return keycloakAuthenticate(exchange, securityContext, authenticator);
diff --git a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/UndertowNodesRegistrationLifecycleWrapper.java b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/UndertowNodesRegistrationManagementWrapper.java
similarity index 57%
rename from integration/undertow/src/main/java/org/keycloak/adapters/undertow/UndertowNodesRegistrationLifecycleWrapper.java
rename to integration/undertow/src/main/java/org/keycloak/adapters/undertow/UndertowNodesRegistrationManagementWrapper.java
index 5c97f6b7ae..d6ca115880 100644
--- a/integration/undertow/src/main/java/org/keycloak/adapters/undertow/UndertowNodesRegistrationLifecycleWrapper.java
+++ b/integration/undertow/src/main/java/org/keycloak/adapters/undertow/UndertowNodesRegistrationManagementWrapper.java
@@ -3,22 +3,21 @@ package org.keycloak.adapters.undertow;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
-import org.keycloak.adapters.NodesRegistrationLifecycle;
+import org.keycloak.adapters.NodesRegistrationManagement;
/**
* @author Marek Posolda
*/
-public class UndertowNodesRegistrationLifecycleWrapper implements ServletContextListener {
+public class UndertowNodesRegistrationManagementWrapper implements ServletContextListener {
- private final NodesRegistrationLifecycle delegate;
+ private final NodesRegistrationManagement delegate;
- public UndertowNodesRegistrationLifecycleWrapper(NodesRegistrationLifecycle delegate) {
+ public UndertowNodesRegistrationManagementWrapper(NodesRegistrationManagement delegate) {
this.delegate = delegate;
}
@Override
public void contextInitialized(ServletContextEvent sce) {
- delegate.start();
}
@Override
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 4963c0a532..cdb5315b97 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
@@ -5,6 +5,7 @@ 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.NodesRegistrationManagement;
import org.keycloak.adapters.undertow.ServletKeycloakAuthMech;
import org.keycloak.adapters.undertow.ServletRequestAuthenticator;
import org.keycloak.adapters.undertow.UndertowHttpFacade;
@@ -18,8 +19,9 @@ public class WildflyAuthenticationMechanism extends ServletKeycloakAuthMech {
public WildflyAuthenticationMechanism(AdapterDeploymentContext deploymentContext,
UndertowUserSessionManagement userSessionManagement,
+ NodesRegistrationManagement nodesRegistrationManagement,
ConfidentialPortManager portManager) {
- super(deploymentContext, userSessionManagement, portManager);
+ super(deploymentContext, userSessionManagement, nodesRegistrationManagement, portManager);
}
@Override
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 60b28b926e..6130d9b136 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
@@ -3,6 +3,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.NodesRegistrationManagement;
import org.keycloak.adapters.undertow.KeycloakServletExtension;
import org.keycloak.adapters.undertow.ServletKeycloakAuthMech;
import org.keycloak.adapters.undertow.UndertowUserSessionManagement;
@@ -16,9 +17,9 @@ public class WildflyKeycloakServletExtension extends KeycloakServletExtension {
@Override
protected ServletKeycloakAuthMech createAuthenticationMechanism(DeploymentInfo deploymentInfo, AdapterDeploymentContext deploymentContext,
- UndertowUserSessionManagement userSessionManagement) {
+ UndertowUserSessionManagement userSessionManagement, NodesRegistrationManagement nodesRegistrationManagement) {
log.info("creating WildflyAuthenticationMechanism");
- return new WildflyAuthenticationMechanism(deploymentContext, userSessionManagement, deploymentInfo.getConfidentialPortManager());
+ return new WildflyAuthenticationMechanism(deploymentContext, userSessionManagement, nodesRegistrationManagement, deploymentInfo.getConfidentialPortManager());
}
}
diff --git a/model/invalidation-cache/infinispan/src/main/java/org/keycloak/models/cache/infinispan/InfinispanCacheUserProviderFactory.java b/model/invalidation-cache/infinispan/src/main/java/org/keycloak/models/cache/infinispan/InfinispanCacheUserProviderFactory.java
index efbefca0c2..8fed69e6ee 100755
--- a/model/invalidation-cache/infinispan/src/main/java/org/keycloak/models/cache/infinispan/InfinispanCacheUserProviderFactory.java
+++ b/model/invalidation-cache/infinispan/src/main/java/org/keycloak/models/cache/infinispan/InfinispanCacheUserProviderFactory.java
@@ -59,7 +59,7 @@ public class InfinispanCacheUserProviderFactory implements CacheUserProviderFact
}
@Listener
- private class CacheListener {
+ public class CacheListener {
@CacheEntryCreated
public void userCreated(CacheEntryCreatedEvent event) {
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/OpenIDConnectService.java b/services/src/main/java/org/keycloak/protocol/oidc/OpenIDConnectService.java
index ef190d980e..0ac16b9b12 100755
--- a/services/src/main/java/org/keycloak/protocol/oidc/OpenIDConnectService.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/OpenIDConnectService.java
@@ -436,6 +436,9 @@ public class OpenIDConnectService {
.build();
}
+
+ event.success();
+
return Response.ok(token, MediaType.APPLICATION_JSON_TYPE).build();
}
diff --git a/services/src/main/java/org/keycloak/services/resources/ClientsManagementService.java b/services/src/main/java/org/keycloak/services/resources/ClientsManagementService.java
index 689d892d95..80cdb25f35 100644
--- a/services/src/main/java/org/keycloak/services/resources/ClientsManagementService.java
+++ b/services/src/main/java/org/keycloak/services/resources/ClientsManagementService.java
@@ -1,5 +1,6 @@
package org.keycloak.services.resources;
+import java.util.Date;
import java.util.HashMap;
import java.util.Map;
@@ -22,6 +23,7 @@ import org.jboss.resteasy.spi.UnauthorizedException;
import org.keycloak.ClientConnection;
import org.keycloak.OAuth2Constants;
import org.keycloak.adapters.AdapterConstants;
+import org.keycloak.events.Details;
import org.keycloak.events.Errors;
import org.keycloak.events.EventBuilder;
import org.keycloak.events.EventType;
@@ -106,10 +108,13 @@ public class ClientsManagementService {
ApplicationModel application = authorizeApplication(authorizationHeader, formData);
String nodeHost = getApplicationClusterHost(formData);
+ event.client(application).detail(Details.NODE_HOST, nodeHost);
logger.infof("Registering cluster host '%s' for client '%s'", nodeHost, application.getName());
application.registerNode(nodeHost, Time.currentTime());
+ event.success();
+
return Response.noContent().build();
}
@@ -139,10 +144,13 @@ public class ClientsManagementService {
ApplicationModel application = authorizeApplication(authorizationHeader, formData);
String nodeHost = getApplicationClusterHost(formData);
+ event.client(application).detail(Details.NODE_HOST, nodeHost);
logger.infof("Unregistering cluster host '%s' for client '%s'", nodeHost, application.getName());
application.unregisterNode(nodeHost);
+ event.success();
+
return Response.noContent().build();
}
diff --git a/testsuite/docker-cluster/shared-files/deploy-examples.sh b/testsuite/docker-cluster/shared-files/deploy-examples.sh
index d2e3287965..2ddee7dbad 100644
--- a/testsuite/docker-cluster/shared-files/deploy-examples.sh
+++ b/testsuite/docker-cluster/shared-files/deploy-examples.sh
@@ -29,15 +29,19 @@ sed -i -e 's/false/true/' admin-access.war/WEB-INF/web.xml
# Configure other examples
for I in *.war/WEB-INF/keycloak.json; do
- sed -i -e 's/\"auth-server-url\".*: \"\/auth\",/&\n \"auth-server-url-for-backend-requests\": \"http:\/\/\$\{jboss.host.name\}:8080\/auth\",\
- \n \"register-node-at-startup\": false,\n \"register-node-period\": 30,/' $I;
+ sed -i -e 's/\"resource\".*: \".*\",/&\n \"auth-server-url-for-backend-requests\": \"http:\/\/\$\{jboss.host.name\}:8080\/auth\",\n \"register-node-at-startup\": true,\n \"register-node-period\": 150,/' $I;
+ sed -i -e 's/\"bearer-only\" : true,/&\n \"credentials\" : \{ \"secret\": \"password\" \},/' $I;
done;
# Enable distributable for customer-portal
sed -i -e 's/<\/module-name>/&\n /' customer-portal.war/WEB-INF/web.xml
-# Configure testrealm.json - Enable adminUrl to access adapters on local machine
-sed -i -e 's/\"adminUrl\": \"\/customer-portal/\"adminUrl\": \"http:\/\/\$\{jboss.host.name\}:8080\/customer-portal/' /keycloak-docker-cluster/examples/testrealm.json
-sed -i -e 's/\"adminUrl\": \"\/product-portal/\"adminUrl\": \"http:\/\/\$\{application.session.host\}:8080\/product-portal/' /keycloak-docker-cluster/examples/testrealm.json
+# Configure testrealm.json - Enable adminUrl to access adapters on local machine, add jboss-logging listener and add secret for database-service application
+TEST_REALM=/keycloak-docker-cluster/examples/testrealm.json
+sed -i -e 's/\"adminUrl\": \"\/customer-portal/\"adminUrl\": \"http:\/\/\$\{jboss.host.name\}:8080\/customer-portal/' $TEST_REALM
+sed -i -e 's/\"adminUrl\": \"\/product-portal/\"adminUrl\": \"http:\/\/\$\{application.session.host\}:8080\/product-portal/' $TEST_REALM
+sed -i -e 's/\"adminUrl\": \"\/database/\"adminUrl\": \"http:\/\/\$\{jboss.host.name\}:8080\/database/' $TEST_REALM
+sed -i -e 's/\"bearerOnly\": true/&,\n \"secret\": \"password\"/' $TEST_REALM
+sed -i -e 's/\"sslRequired\": \"external\",/&\n \"eventsListeners\": \[ \"jboss-logging\" \],/' $TEST_REALM