diff --git a/adapters/oidc/adapter-core/pom.xml b/adapters/oidc/adapter-core/pom.xml index efcbf3a5d28b..6d4e8a19210e 100755 --- a/adapters/oidc/adapter-core/pom.xml +++ b/adapters/oidc/adapter-core/pom.xml @@ -21,7 +21,7 @@ keycloak-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../../../pom.xml 4.0.0 diff --git a/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/AdapterDeploymentContext.java b/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/AdapterDeploymentContext.java index 63ea79e65b25..dd0d39ba7807 100755 --- a/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/AdapterDeploymentContext.java +++ b/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/AdapterDeploymentContext.java @@ -342,6 +342,12 @@ public int getNotBefore() { return delegate.getNotBefore(); } + @Override + public void updateNotBefore(int notBefore) { + delegate.setNotBefore(notBefore); + getPublicKeyLocator().reset(this); + } + @Override public void setExposeToken(boolean exposeToken) { delegate.setExposeToken(exposeToken); @@ -446,6 +452,16 @@ public void setMinTimeBetweenJwksRequests(int minTimeBetweenJwksRequests) { public int getMinTimeBetweenJwksRequests() { return delegate.getMinTimeBetweenJwksRequests(); } + + @Override + public int getPublicKeyCacheTtl() { + return delegate.getPublicKeyCacheTtl(); + } + + @Override + public void setPublicKeyCacheTtl(int publicKeyCacheTtl) { + delegate.setPublicKeyCacheTtl(publicKeyCacheTtl); + } } protected KeycloakUriBuilder getBaseBuilder(HttpFacade facade, String base) { diff --git a/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/HttpAdapterUtils.java b/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/HttpAdapterUtils.java index 3e0f36dee729..b7877964a022 100644 --- a/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/HttpAdapterUtils.java +++ b/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/HttpAdapterUtils.java @@ -46,14 +46,7 @@ public static T sendJsonHttpRequest(KeycloakDeployment deployment, HttpReque } 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); - return JsonSerialization.readValue(json, clazz); + return JsonSerialization.readValue(is, clazz); } finally { try { is.close(); diff --git a/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/KeycloakDeployment.java b/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/KeycloakDeployment.java index 1071b710fcd8..b9ee4c6f05fb 100755 --- a/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/KeycloakDeployment.java +++ b/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/KeycloakDeployment.java @@ -81,6 +81,7 @@ public class KeycloakDeployment { protected volatile int notBefore; protected int tokenMinimumTimeToLive; protected int minTimeBetweenJwksRequests; + protected int publicKeyCacheTtl; private PolicyEnforcer policyEnforcer; public KeycloakDeployment() { @@ -328,6 +329,11 @@ public void setNotBefore(int notBefore) { this.notBefore = notBefore; } + public void updateNotBefore(int notBefore) { + this.notBefore = notBefore; + getPublicKeyLocator().reset(this); + } + public boolean isAlwaysRefreshToken() { return alwaysRefreshToken; } @@ -384,6 +390,14 @@ public void setMinTimeBetweenJwksRequests(int minTimeBetweenJwksRequests) { this.minTimeBetweenJwksRequests = minTimeBetweenJwksRequests; } + public int getPublicKeyCacheTtl() { + return publicKeyCacheTtl; + } + + public void setPublicKeyCacheTtl(int publicKeyCacheTtl) { + this.publicKeyCacheTtl = publicKeyCacheTtl; + } + public void setPolicyEnforcer(PolicyEnforcer policyEnforcer) { this.policyEnforcer = policyEnforcer; } diff --git a/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/KeycloakDeploymentBuilder.java b/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/KeycloakDeploymentBuilder.java index f6c6f5ea1239..85b19ca53891 100755 --- a/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/KeycloakDeploymentBuilder.java +++ b/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/KeycloakDeploymentBuilder.java @@ -105,6 +105,7 @@ protected KeycloakDeployment internalBuild(AdapterConfig adapterConfig) { deployment.setRegisterNodePeriod(adapterConfig.getRegisterNodePeriod()); deployment.setTokenMinimumTimeToLive(adapterConfig.getTokenMinimumTimeToLive()); deployment.setMinTimeBetweenJwksRequests(adapterConfig.getMinTimeBetweenJwksRequests()); + deployment.setPublicKeyCacheTtl(adapterConfig.getPublicKeyCacheTtl()); 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"); diff --git a/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/OAuthRequestAuthenticator.java b/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/OAuthRequestAuthenticator.java index 109361f1df2d..e8f534492a10 100755 --- a/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/OAuthRequestAuthenticator.java +++ b/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/OAuthRequestAuthenticator.java @@ -357,7 +357,7 @@ protected AuthChallenge resolveCode(String code) { return challenge(403, OIDCAuthenticationError.Reason.INVALID_TOKEN, null); } if (tokenResponse.getNotBeforePolicy() > deployment.getNotBefore()) { - deployment.setNotBefore(tokenResponse.getNotBeforePolicy()); + deployment.updateNotBefore(tokenResponse.getNotBeforePolicy()); } if (token.getIssuedAt() < deployment.getNotBefore()) { log.error("Stale token"); diff --git a/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/PreAuthActionsHandler.java b/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/PreAuthActionsHandler.java index 9a291c071be4..b4d017bc576c 100755 --- a/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/PreAuthActionsHandler.java +++ b/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/PreAuthActionsHandler.java @@ -155,7 +155,7 @@ protected void handleLogout() { } else { log.debugf("logout of all sessions for application '%s'", action.getResource()); if (action.getNotBefore() > deployment.getNotBefore()) { - deployment.setNotBefore(action.getNotBefore()); + deployment.updateNotBefore(action.getNotBefore()); } userSessionManagement.logoutAll(); } @@ -177,7 +177,7 @@ protected void handlePushNotBefore() { } PushNotBeforeAction action = JsonSerialization.readValue(token.getContent(), PushNotBeforeAction.class); if (!validateAction(action)) return; - deployment.setNotBefore(action.getNotBefore()); + deployment.updateNotBefore(action.getNotBefore()); } catch (Exception e) { throw new RuntimeException(e); } diff --git a/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/RefreshableKeycloakSecurityContext.java b/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/RefreshableKeycloakSecurityContext.java index 39a3f1e59f30..c70bce1261e3 100755 --- a/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/RefreshableKeycloakSecurityContext.java +++ b/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/RefreshableKeycloakSecurityContext.java @@ -144,7 +144,7 @@ public boolean refreshExpiredToken(boolean checkActive) { } if (response.getNotBeforePolicy() > deployment.getNotBefore()) { - deployment.setNotBefore(response.getNotBeforePolicy()); + deployment.updateNotBefore(response.getNotBeforePolicy()); } this.token = token; diff --git a/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/rotation/HardcodedPublicKeyLocator.java b/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/rotation/HardcodedPublicKeyLocator.java index 2aa51a44c30d..9e285a2c8c6c 100644 --- a/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/rotation/HardcodedPublicKeyLocator.java +++ b/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/rotation/HardcodedPublicKeyLocator.java @@ -37,4 +37,9 @@ public HardcodedPublicKeyLocator(PublicKey publicKey) { public PublicKey getPublicKey(String kid, KeycloakDeployment deployment) { return publicKey; } + + @Override + public void reset(KeycloakDeployment deployment) { + + } } diff --git a/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/rotation/JWKPublicKeyLocator.java b/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/rotation/JWKPublicKeyLocator.java index 9305f32a4901..22c6d7dc21f2 100644 --- a/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/rotation/JWKPublicKeyLocator.java +++ b/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/rotation/JWKPublicKeyLocator.java @@ -25,7 +25,6 @@ import org.keycloak.common.util.Time; import org.keycloak.jose.jwk.JSONWebKeySet; import org.keycloak.jose.jwk.JWK; -import org.keycloak.jose.jws.JWSInput; import org.keycloak.util.JWKSUtils; import java.security.PublicKey; @@ -48,30 +47,43 @@ public class JWKPublicKeyLocator implements PublicKeyLocator { @Override public PublicKey getPublicKey(String kid, KeycloakDeployment deployment) { int minTimeBetweenRequests = deployment.getMinTimeBetweenJwksRequests(); + int publicKeyCacheTtl = deployment.getPublicKeyCacheTtl(); + int currentTime = Time.currentTime(); // Check if key is in cache. - PublicKey publicKey = currentKeys.get(kid); + PublicKey publicKey = lookupCachedKey(publicKeyCacheTtl, currentTime, kid); if (publicKey != null) { return publicKey; } - int currentTime = Time.currentTime(); - // Check if we are allowed to send request - if (currentTime > lastRequestTime + minTimeBetweenRequests) { - synchronized (this) { - currentTime = Time.currentTime(); - if (currentTime > lastRequestTime + minTimeBetweenRequests) { - sendRequest(deployment); - lastRequestTime = currentTime; - } else { - log.debugf("Won't send request to realm jwks url. Last request time was %d", lastRequestTime); - } + synchronized (this) { + currentTime = Time.currentTime(); + if (currentTime > lastRequestTime + minTimeBetweenRequests) { + sendRequest(deployment); + lastRequestTime = currentTime; + } else { + log.debugf("Won't send request to realm jwks url. Last request time was %d", lastRequestTime); } + + return lookupCachedKey(publicKeyCacheTtl, currentTime, kid); } + } - return currentKeys.get(kid); + @Override + public void reset(KeycloakDeployment deployment) { + sendRequest(deployment); + lastRequestTime = Time.currentTime(); + } + + + private PublicKey lookupCachedKey(int publicKeyCacheTtl, int currentTime, String kid) { + if (lastRequestTime + publicKeyCacheTtl > currentTime) { + return currentKeys.get(kid); + } else { + return null; + } } diff --git a/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/rotation/PublicKeyLocator.java b/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/rotation/PublicKeyLocator.java index 3efd90a3b7f5..096f75f0427c 100644 --- a/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/rotation/PublicKeyLocator.java +++ b/adapters/oidc/adapter-core/src/main/java/org/keycloak/adapters/rotation/PublicKeyLocator.java @@ -34,4 +34,11 @@ public interface PublicKeyLocator { */ PublicKey getPublicKey(String kid, KeycloakDeployment deployment); + /** + * Reset the state of locator (eg. clear the cached keys) + * + * @param deployment + */ + void reset(KeycloakDeployment deployment); + } diff --git a/adapters/oidc/adapter-core/src/test/java/org/keycloak/adapters/KeycloakDeploymentBuilderTest.java b/adapters/oidc/adapter-core/src/test/java/org/keycloak/adapters/KeycloakDeploymentBuilderTest.java index 77eb475bf601..233c1ed2f0ea 100644 --- a/adapters/oidc/adapter-core/src/test/java/org/keycloak/adapters/KeycloakDeploymentBuilderTest.java +++ b/adapters/oidc/adapter-core/src/test/java/org/keycloak/adapters/KeycloakDeploymentBuilderTest.java @@ -69,6 +69,7 @@ public void load() throws Exception { assertEquals("email", deployment.getPrincipalAttribute()); assertEquals(10, deployment.getTokenMinimumTimeToLive()); assertEquals(20, deployment.getMinTimeBetweenJwksRequests()); + assertEquals(120, deployment.getPublicKeyCacheTtl()); } @Test @@ -78,6 +79,7 @@ public void loadNoClientCredentials() throws Exception { assertTrue(deployment.getPublicKeyLocator() instanceof JWKPublicKeyLocator); assertEquals(10, deployment.getMinTimeBetweenJwksRequests()); + assertEquals(86400, deployment.getPublicKeyCacheTtl()); } @Test diff --git a/adapters/oidc/adapter-core/src/test/resources/keycloak.json b/adapters/oidc/adapter-core/src/test/resources/keycloak.json index a8afd22cf2e4..9f0a204826a5 100644 --- a/adapters/oidc/adapter-core/src/test/resources/keycloak.json +++ b/adapters/oidc/adapter-core/src/test/resources/keycloak.json @@ -30,5 +30,6 @@ "token-store": "cookie", "principal-attribute": "email", "token-minimum-time-to-live": 10, - "min-time-between-jwks-requests": 20 + "min-time-between-jwks-requests": 20, + "public-key-cache-ttl": 120 } \ No newline at end of file diff --git a/adapters/oidc/as7-eap6/as7-adapter-spi/pom.xml b/adapters/oidc/as7-eap6/as7-adapter-spi/pom.xml index 1f64c36fcab8..fa0c29bf41dd 100755 --- a/adapters/oidc/as7-eap6/as7-adapter-spi/pom.xml +++ b/adapters/oidc/as7-eap6/as7-adapter-spi/pom.xml @@ -21,7 +21,7 @@ keycloak-as7-integration-pom org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../pom.xml 4.0.0 diff --git a/adapters/oidc/as7-eap6/as7-adapter/pom.xml b/adapters/oidc/as7-eap6/as7-adapter/pom.xml index 5f21d6d4275c..67ad24b51b5f 100755 --- a/adapters/oidc/as7-eap6/as7-adapter/pom.xml +++ b/adapters/oidc/as7-eap6/as7-adapter/pom.xml @@ -21,7 +21,7 @@ keycloak-as7-integration-pom org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../pom.xml 4.0.0 diff --git a/adapters/oidc/as7-eap6/as7-subsystem/pom.xml b/adapters/oidc/as7-eap6/as7-subsystem/pom.xml index 972903fcde14..4b3369d65bbf 100755 --- a/adapters/oidc/as7-eap6/as7-subsystem/pom.xml +++ b/adapters/oidc/as7-eap6/as7-subsystem/pom.xml @@ -21,7 +21,7 @@ org.keycloak keycloak-as7-integration-pom - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../pom.xml diff --git a/adapters/oidc/as7-eap6/pom.xml b/adapters/oidc/as7-eap6/pom.xml index 626c1a10f38d..e8c50f5320a9 100755 --- a/adapters/oidc/as7-eap6/pom.xml +++ b/adapters/oidc/as7-eap6/pom.xml @@ -20,7 +20,7 @@ keycloak-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../../../pom.xml Keycloak AS7 / JBoss EAP 6 Integration diff --git a/adapters/oidc/installed/pom.xml b/adapters/oidc/installed/pom.xml index 2cff21abc9a9..1e88bae93495 100755 --- a/adapters/oidc/installed/pom.xml +++ b/adapters/oidc/installed/pom.xml @@ -21,7 +21,7 @@ keycloak-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../../../pom.xml 4.0.0 diff --git a/adapters/oidc/jaxrs-oauth-client/pom.xml b/adapters/oidc/jaxrs-oauth-client/pom.xml index feca253caba4..d91119251bf1 100755 --- a/adapters/oidc/jaxrs-oauth-client/pom.xml +++ b/adapters/oidc/jaxrs-oauth-client/pom.xml @@ -21,7 +21,7 @@ keycloak-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../../../pom.xml 4.0.0 diff --git a/adapters/oidc/jetty/jetty-core/pom.xml b/adapters/oidc/jetty/jetty-core/pom.xml index d6de06173d96..0a626191a700 100755 --- a/adapters/oidc/jetty/jetty-core/pom.xml +++ b/adapters/oidc/jetty/jetty-core/pom.xml @@ -21,7 +21,7 @@ keycloak-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../../../../pom.xml 4.0.0 diff --git a/adapters/oidc/jetty/jetty8.1/pom.xml b/adapters/oidc/jetty/jetty8.1/pom.xml index 5d9bfc32c3e4..b966d60e55a3 100755 --- a/adapters/oidc/jetty/jetty8.1/pom.xml +++ b/adapters/oidc/jetty/jetty8.1/pom.xml @@ -21,7 +21,7 @@ keycloak-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../../../../pom.xml 4.0.0 diff --git a/adapters/oidc/jetty/jetty9.1/pom.xml b/adapters/oidc/jetty/jetty9.1/pom.xml index dbe08dd775d0..d017e24ddaf5 100755 --- a/adapters/oidc/jetty/jetty9.1/pom.xml +++ b/adapters/oidc/jetty/jetty9.1/pom.xml @@ -21,7 +21,7 @@ keycloak-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../../../../pom.xml 4.0.0 diff --git a/adapters/oidc/jetty/jetty9.2/pom.xml b/adapters/oidc/jetty/jetty9.2/pom.xml index 430a02d0fa21..20e7afaa48a5 100755 --- a/adapters/oidc/jetty/jetty9.2/pom.xml +++ b/adapters/oidc/jetty/jetty9.2/pom.xml @@ -21,7 +21,7 @@ keycloak-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../../../../pom.xml 4.0.0 diff --git a/adapters/oidc/jetty/jetty9.3/pom.xml b/adapters/oidc/jetty/jetty9.3/pom.xml index 9596a00bf030..b1ec1ff8043d 100644 --- a/adapters/oidc/jetty/jetty9.3/pom.xml +++ b/adapters/oidc/jetty/jetty9.3/pom.xml @@ -21,7 +21,7 @@ keycloak-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../../../../pom.xml 4.0.0 diff --git a/adapters/oidc/jetty/pom.xml b/adapters/oidc/jetty/pom.xml index 6933fe78ab36..d4b2f4bfda90 100755 --- a/adapters/oidc/jetty/pom.xml +++ b/adapters/oidc/jetty/pom.xml @@ -20,7 +20,7 @@ keycloak-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../../../pom.xml Keycloak Jetty Integration diff --git a/adapters/oidc/js/pom.xml b/adapters/oidc/js/pom.xml index 5d1f812101ee..026d8e4aa281 100755 --- a/adapters/oidc/js/pom.xml +++ b/adapters/oidc/js/pom.xml @@ -21,7 +21,7 @@ keycloak-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../../../pom.xml 4.0.0 diff --git a/adapters/oidc/js/src/main/resources/keycloak.js b/adapters/oidc/js/src/main/resources/keycloak.js index ba27ed0cfc8f..70b318ec4b34 100755 --- a/adapters/oidc/js/src/main/resources/keycloak.js +++ b/adapters/oidc/js/src/main/resources/keycloak.js @@ -846,14 +846,15 @@ kc.clearToken(); } - for (var i = loginIframe.callbackList.length - 1; i >= 0; --i) { - var promise = loginIframe.callbackList[i]; + var callbacks = loginIframe.callbackList.splice(0, loginIframe.callbackList.length); + + for (var i = callbacks.length - 1; i >= 0; --i) { + var promise = callbacks[i]; if (event.data == "unchanged") { promise.setSuccess(); } else { promise.setError(); } - loginIframe.callbackList.splice(i, 1); } }; diff --git a/adapters/oidc/js/src/main/resources/login-status-iframe.html b/adapters/oidc/js/src/main/resources/login-status-iframe.html index 6bea92ade42a..f941663e4fad 100755 --- a/adapters/oidc/js/src/main/resources/login-status-iframe.html +++ b/adapters/oidc/js/src/main/resources/login-status-iframe.html @@ -35,14 +35,14 @@ req.open('GET', url, true); req.onreadystatechange = function () { - if (req.readyState == 4) { - if (req.status == 204) { + if (req.readyState === 4) { + if (req.status === 204) { init = { clientId: clientId, origin: origin } callback('unchanged'); - } else if (req.status = 404) { + } else if (req.status === 404) { callback('changed'); } else { callback('error'); @@ -52,8 +52,8 @@ req.send(); } else { - if (clientId == init.clientId && origin == init.origin) { - if (sessionState == cookie) { + if (clientId === init.clientId && origin === init.origin) { + if (sessionState === cookie) { callback('unchanged'); } else { callback('changed'); @@ -71,7 +71,7 @@ for(var i=0; i - \ No newline at end of file + diff --git a/adapters/oidc/osgi-adapter/pom.xml b/adapters/oidc/osgi-adapter/pom.xml index bfc078b5775f..a2f33f9110e2 100755 --- a/adapters/oidc/osgi-adapter/pom.xml +++ b/adapters/oidc/osgi-adapter/pom.xml @@ -21,7 +21,7 @@ keycloak-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../../../pom.xml 4.0.0 diff --git a/adapters/oidc/pom.xml b/adapters/oidc/pom.xml index cc51e5317d4e..4c7d60e11636 100755 --- a/adapters/oidc/pom.xml +++ b/adapters/oidc/pom.xml @@ -20,7 +20,7 @@ keycloak-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../../pom.xml Keycloak OIDC Client Adapter Modules diff --git a/adapters/oidc/servlet-filter/pom.xml b/adapters/oidc/servlet-filter/pom.xml index 2371c34cccb9..5e1f89851b77 100755 --- a/adapters/oidc/servlet-filter/pom.xml +++ b/adapters/oidc/servlet-filter/pom.xml @@ -21,7 +21,7 @@ keycloak-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../../../pom.xml 4.0.0 diff --git a/adapters/oidc/servlet-oauth-client/pom.xml b/adapters/oidc/servlet-oauth-client/pom.xml index 46efa50d87e8..3928311da59b 100755 --- a/adapters/oidc/servlet-oauth-client/pom.xml +++ b/adapters/oidc/servlet-oauth-client/pom.xml @@ -21,7 +21,7 @@ keycloak-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../../../pom.xml 4.0.0 diff --git a/adapters/oidc/spring-boot/pom.xml b/adapters/oidc/spring-boot/pom.xml index 0553fb23396f..ed6e9c17c7d7 100755 --- a/adapters/oidc/spring-boot/pom.xml +++ b/adapters/oidc/spring-boot/pom.xml @@ -21,7 +21,7 @@ keycloak-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../../../pom.xml 4.0.0 diff --git a/adapters/oidc/spring-security/pom.xml b/adapters/oidc/spring-security/pom.xml index 89092e85bc2e..af2c52ec4b74 100755 --- a/adapters/oidc/spring-security/pom.xml +++ b/adapters/oidc/spring-security/pom.xml @@ -21,7 +21,7 @@ keycloak-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../../../pom.xml 4.0.0 diff --git a/adapters/oidc/spring-security/src/main/java/org/keycloak/adapters/springsecurity/filter/KeycloakAuthenticatedActionsFilter.java b/adapters/oidc/spring-security/src/main/java/org/keycloak/adapters/springsecurity/filter/KeycloakAuthenticatedActionsFilter.java new file mode 100644 index 000000000000..a30a784807eb --- /dev/null +++ b/adapters/oidc/spring-security/src/main/java/org/keycloak/adapters/springsecurity/filter/KeycloakAuthenticatedActionsFilter.java @@ -0,0 +1,90 @@ +/* + * Copyright 2016 Red Hat, Inc. and/or its affiliates + * and other contributors as indicated by the @author tags. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.keycloak.adapters.springsecurity.filter; + +import java.io.IOException; + +import javax.servlet.FilterChain; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.keycloak.adapters.AdapterDeploymentContext; +import org.keycloak.adapters.AuthenticatedActionsHandler; +import org.keycloak.adapters.NodesRegistrationManagement; +import org.keycloak.adapters.OIDCHttpFacade; +import org.keycloak.adapters.spi.HttpFacade; +import org.keycloak.adapters.springsecurity.facade.SimpleHttpFacade; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.web.filter.GenericFilterBean; + +/** + * Exposes a Keycloak adapter {@link AuthenticatedActionsHandler} as a Spring Security filter. + * + * @author Scott Rossillo + * @version $Revision: 1 $ + */ +public class KeycloakAuthenticatedActionsFilter extends GenericFilterBean implements ApplicationContextAware { + + private static final Logger log = LoggerFactory.getLogger(KeycloakAuthenticatedActionsFilter.class); + + private final NodesRegistrationManagement management = new NodesRegistrationManagement(); + private ApplicationContext applicationContext; + private AdapterDeploymentContext deploymentContext; + + + public KeycloakAuthenticatedActionsFilter() { + super(); + } + + @Override + protected void initFilterBean() throws ServletException { + deploymentContext = applicationContext.getBean(AdapterDeploymentContext.class); + } + + @Override + public void destroy() { + log.debug("Unregistering deployment"); + management.stop(); + } + + @Override + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) + throws IOException, ServletException { + + HttpFacade facade = new SimpleHttpFacade((HttpServletRequest)request, (HttpServletResponse)response); + AuthenticatedActionsHandler handler = new AuthenticatedActionsHandler(deploymentContext.resolveDeployment(facade), (OIDCHttpFacade)facade); + boolean handled = handler.handledRequest(); + if (handled) { + log.debug("Authenticated filter handled request: {}", ((HttpServletRequest) request).getRequestURI()); + } else { + chain.doFilter(request, response); + } + } + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + this.applicationContext = applicationContext; + } +} diff --git a/adapters/oidc/tomcat/pom.xml b/adapters/oidc/tomcat/pom.xml index e8495d4a78d8..99844f93ce5e 100755 --- a/adapters/oidc/tomcat/pom.xml +++ b/adapters/oidc/tomcat/pom.xml @@ -20,7 +20,7 @@ keycloak-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../../../pom.xml Keycloak Tomcat Integration diff --git a/adapters/oidc/tomcat/tomcat-core/pom.xml b/adapters/oidc/tomcat/tomcat-core/pom.xml index e048adac9065..bce1604afa30 100755 --- a/adapters/oidc/tomcat/tomcat-core/pom.xml +++ b/adapters/oidc/tomcat/tomcat-core/pom.xml @@ -21,7 +21,7 @@ keycloak-tomcat-integration-pom org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../pom.xml 4.0.0 diff --git a/adapters/oidc/tomcat/tomcat6/pom.xml b/adapters/oidc/tomcat/tomcat6/pom.xml index cd0d6d9992c7..7976af627624 100755 --- a/adapters/oidc/tomcat/tomcat6/pom.xml +++ b/adapters/oidc/tomcat/tomcat6/pom.xml @@ -21,7 +21,7 @@ keycloak-tomcat-integration-pom org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../pom.xml 4.0.0 diff --git a/adapters/oidc/tomcat/tomcat7/pom.xml b/adapters/oidc/tomcat/tomcat7/pom.xml index 8d36d61702fd..5f6435a977fb 100755 --- a/adapters/oidc/tomcat/tomcat7/pom.xml +++ b/adapters/oidc/tomcat/tomcat7/pom.xml @@ -21,7 +21,7 @@ keycloak-tomcat-integration-pom org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../pom.xml 4.0.0 diff --git a/adapters/oidc/tomcat/tomcat8/pom.xml b/adapters/oidc/tomcat/tomcat8/pom.xml index edaf4dabc041..620ca5ce9027 100755 --- a/adapters/oidc/tomcat/tomcat8/pom.xml +++ b/adapters/oidc/tomcat/tomcat8/pom.xml @@ -21,7 +21,7 @@ keycloak-tomcat-integration-pom org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../pom.xml 4.0.0 diff --git a/adapters/oidc/undertow/pom.xml b/adapters/oidc/undertow/pom.xml index be1d44e9e1ff..8c84d416f03c 100755 --- a/adapters/oidc/undertow/pom.xml +++ b/adapters/oidc/undertow/pom.xml @@ -21,7 +21,7 @@ keycloak-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../../../pom.xml 4.0.0 diff --git a/adapters/oidc/wildfly/pom.xml b/adapters/oidc/wildfly/pom.xml index 641dcc0e2180..c7625742094d 100755 --- a/adapters/oidc/wildfly/pom.xml +++ b/adapters/oidc/wildfly/pom.xml @@ -20,7 +20,7 @@ keycloak-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../../../pom.xml Keycloak WildFly Integration diff --git a/adapters/oidc/wildfly/wf8-subsystem/pom.xml b/adapters/oidc/wildfly/wf8-subsystem/pom.xml index d8058180d9be..cf5fe6886d3c 100755 --- a/adapters/oidc/wildfly/wf8-subsystem/pom.xml +++ b/adapters/oidc/wildfly/wf8-subsystem/pom.xml @@ -21,7 +21,7 @@ org.keycloak keycloak-parent - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../../../../pom.xml diff --git a/adapters/oidc/wildfly/wildfly-adapter/pom.xml b/adapters/oidc/wildfly/wildfly-adapter/pom.xml index f20335b50fe2..1db02a38129d 100755 --- a/adapters/oidc/wildfly/wildfly-adapter/pom.xml +++ b/adapters/oidc/wildfly/wildfly-adapter/pom.xml @@ -21,7 +21,7 @@ keycloak-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../../../../pom.xml 4.0.0 diff --git a/adapters/oidc/wildfly/wildfly-subsystem/pom.xml b/adapters/oidc/wildfly/wildfly-subsystem/pom.xml index 76a7ee2ee28e..16734b3f2060 100755 --- a/adapters/oidc/wildfly/wildfly-subsystem/pom.xml +++ b/adapters/oidc/wildfly/wildfly-subsystem/pom.xml @@ -21,7 +21,7 @@ org.keycloak keycloak-parent - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../../../../pom.xml diff --git a/adapters/pom.xml b/adapters/pom.xml index bb45f118090d..a9179ed3daa4 100755 --- a/adapters/pom.xml +++ b/adapters/pom.xml @@ -20,7 +20,7 @@ keycloak-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../pom.xml Keycloak Integration diff --git a/adapters/saml/as7-eap6/adapter/pom.xml b/adapters/saml/as7-eap6/adapter/pom.xml index c6098593e99b..1fdec2a81e82 100755 --- a/adapters/saml/as7-eap6/adapter/pom.xml +++ b/adapters/saml/as7-eap6/adapter/pom.xml @@ -21,7 +21,7 @@ keycloak-saml-eap-integration-pom org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../pom.xml 4.0.0 diff --git a/adapters/saml/as7-eap6/pom.xml b/adapters/saml/as7-eap6/pom.xml index f265e43714cf..f9c226cd94d9 100755 --- a/adapters/saml/as7-eap6/pom.xml +++ b/adapters/saml/as7-eap6/pom.xml @@ -20,7 +20,7 @@ keycloak-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../../../pom.xml Keycloak SAML EAP Integration diff --git a/adapters/saml/as7-eap6/subsystem/pom.xml b/adapters/saml/as7-eap6/subsystem/pom.xml index 1f97819360f9..1c0dd022b92d 100755 --- a/adapters/saml/as7-eap6/subsystem/pom.xml +++ b/adapters/saml/as7-eap6/subsystem/pom.xml @@ -21,7 +21,7 @@ org.keycloak keycloak-saml-eap-integration-pom - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../pom.xml diff --git a/adapters/saml/core-public/pom.xml b/adapters/saml/core-public/pom.xml index 00e5a3b1d7c4..821365209ad9 100755 --- a/adapters/saml/core-public/pom.xml +++ b/adapters/saml/core-public/pom.xml @@ -21,7 +21,7 @@ keycloak-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../../../pom.xml 4.0.0 diff --git a/adapters/saml/core/pom.xml b/adapters/saml/core/pom.xml index 98ad6040ac13..66fbed791096 100755 --- a/adapters/saml/core/pom.xml +++ b/adapters/saml/core/pom.xml @@ -21,7 +21,7 @@ keycloak-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../../../pom.xml 4.0.0 diff --git a/adapters/saml/jetty/jetty-core/pom.xml b/adapters/saml/jetty/jetty-core/pom.xml index d735fa5e78fb..6a97fcec6636 100755 --- a/adapters/saml/jetty/jetty-core/pom.xml +++ b/adapters/saml/jetty/jetty-core/pom.xml @@ -21,7 +21,7 @@ keycloak-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../../../../pom.xml 4.0.0 diff --git a/adapters/saml/jetty/jetty8.1/pom.xml b/adapters/saml/jetty/jetty8.1/pom.xml index adb70cc36cbe..2f58cab18929 100755 --- a/adapters/saml/jetty/jetty8.1/pom.xml +++ b/adapters/saml/jetty/jetty8.1/pom.xml @@ -21,7 +21,7 @@ keycloak-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../../../../pom.xml 4.0.0 diff --git a/adapters/saml/jetty/jetty9.1/pom.xml b/adapters/saml/jetty/jetty9.1/pom.xml index 9c8e9e3b7168..36e2c79fbbd6 100755 --- a/adapters/saml/jetty/jetty9.1/pom.xml +++ b/adapters/saml/jetty/jetty9.1/pom.xml @@ -21,7 +21,7 @@ keycloak-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../../../../pom.xml 4.0.0 diff --git a/adapters/saml/jetty/jetty9.2/pom.xml b/adapters/saml/jetty/jetty9.2/pom.xml index 43833e8aa6c4..48f8ec93d115 100755 --- a/adapters/saml/jetty/jetty9.2/pom.xml +++ b/adapters/saml/jetty/jetty9.2/pom.xml @@ -21,7 +21,7 @@ keycloak-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../../../../pom.xml 4.0.0 diff --git a/adapters/saml/jetty/jetty9.3/pom.xml b/adapters/saml/jetty/jetty9.3/pom.xml index 894f3291c41d..27e146fb94a9 100644 --- a/adapters/saml/jetty/jetty9.3/pom.xml +++ b/adapters/saml/jetty/jetty9.3/pom.xml @@ -21,7 +21,7 @@ keycloak-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../../../../pom.xml 4.0.0 diff --git a/adapters/saml/jetty/pom.xml b/adapters/saml/jetty/pom.xml index 7a06bb983285..5c195b769173 100755 --- a/adapters/saml/jetty/pom.xml +++ b/adapters/saml/jetty/pom.xml @@ -20,7 +20,7 @@ keycloak-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../../../pom.xml Keycloak SAML Jetty Integration diff --git a/adapters/saml/pom.xml b/adapters/saml/pom.xml index 6ce9bab825d6..71e4768142d1 100755 --- a/adapters/saml/pom.xml +++ b/adapters/saml/pom.xml @@ -20,7 +20,7 @@ keycloak-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../../pom.xml Keycloak SAML Client Adapter Modules diff --git a/adapters/saml/servlet-filter/pom.xml b/adapters/saml/servlet-filter/pom.xml index 0065ad0e3c34..222238c6e55a 100755 --- a/adapters/saml/servlet-filter/pom.xml +++ b/adapters/saml/servlet-filter/pom.xml @@ -21,7 +21,7 @@ keycloak-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../../../pom.xml 4.0.0 diff --git a/adapters/saml/tomcat/pom.xml b/adapters/saml/tomcat/pom.xml index 7d699d5f3ed8..d244ce42474e 100755 --- a/adapters/saml/tomcat/pom.xml +++ b/adapters/saml/tomcat/pom.xml @@ -20,7 +20,7 @@ keycloak-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../../../pom.xml Keycloak SAML Tomcat Integration diff --git a/adapters/saml/tomcat/tomcat-core/pom.xml b/adapters/saml/tomcat/tomcat-core/pom.xml index 4654bdfe8318..a195726bbc19 100755 --- a/adapters/saml/tomcat/tomcat-core/pom.xml +++ b/adapters/saml/tomcat/tomcat-core/pom.xml @@ -21,7 +21,7 @@ keycloak-saml-tomcat-integration-pom org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../pom.xml 4.0.0 diff --git a/adapters/saml/tomcat/tomcat6/pom.xml b/adapters/saml/tomcat/tomcat6/pom.xml index 218151daf7cf..1a75eb9327d5 100755 --- a/adapters/saml/tomcat/tomcat6/pom.xml +++ b/adapters/saml/tomcat/tomcat6/pom.xml @@ -21,7 +21,7 @@ keycloak-saml-tomcat-integration-pom org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../pom.xml 4.0.0 diff --git a/adapters/saml/tomcat/tomcat7/pom.xml b/adapters/saml/tomcat/tomcat7/pom.xml index c2c0006937d1..f2e25862a95c 100755 --- a/adapters/saml/tomcat/tomcat7/pom.xml +++ b/adapters/saml/tomcat/tomcat7/pom.xml @@ -21,7 +21,7 @@ keycloak-saml-tomcat-integration-pom org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../pom.xml 4.0.0 diff --git a/adapters/saml/tomcat/tomcat8/pom.xml b/adapters/saml/tomcat/tomcat8/pom.xml index e292c36d4b9e..5d4e8b883ecf 100755 --- a/adapters/saml/tomcat/tomcat8/pom.xml +++ b/adapters/saml/tomcat/tomcat8/pom.xml @@ -21,7 +21,7 @@ keycloak-saml-tomcat-integration-pom org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../pom.xml 4.0.0 diff --git a/adapters/saml/undertow/pom.xml b/adapters/saml/undertow/pom.xml index e81f6677e72f..5c51f9f534f9 100755 --- a/adapters/saml/undertow/pom.xml +++ b/adapters/saml/undertow/pom.xml @@ -21,7 +21,7 @@ keycloak-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../../../pom.xml 4.0.0 diff --git a/adapters/saml/wildfly/pom.xml b/adapters/saml/wildfly/pom.xml index 441d734b54fc..65e9ecb16cf2 100755 --- a/adapters/saml/wildfly/pom.xml +++ b/adapters/saml/wildfly/pom.xml @@ -20,7 +20,7 @@ keycloak-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../../../pom.xml Keycloak SAML Wildfly Integration diff --git a/adapters/saml/wildfly/wildfly-adapter/pom.xml b/adapters/saml/wildfly/wildfly-adapter/pom.xml index e849beedaa66..d18013a5dff3 100755 --- a/adapters/saml/wildfly/wildfly-adapter/pom.xml +++ b/adapters/saml/wildfly/wildfly-adapter/pom.xml @@ -21,7 +21,7 @@ keycloak-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../../../../pom.xml 4.0.0 diff --git a/adapters/saml/wildfly/wildfly-subsystem/pom.xml b/adapters/saml/wildfly/wildfly-subsystem/pom.xml index 8c628c8f6ee5..d297bd06dbe8 100755 --- a/adapters/saml/wildfly/wildfly-subsystem/pom.xml +++ b/adapters/saml/wildfly/wildfly-subsystem/pom.xml @@ -21,7 +21,7 @@ org.keycloak keycloak-parent - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../../../../pom.xml diff --git a/adapters/spi/adapter-spi/pom.xml b/adapters/spi/adapter-spi/pom.xml index c4ceb9fd0cb5..216fc6bf529a 100755 --- a/adapters/spi/adapter-spi/pom.xml +++ b/adapters/spi/adapter-spi/pom.xml @@ -21,7 +21,7 @@ keycloak-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../../../pom.xml 4.0.0 diff --git a/adapters/spi/jboss-adapter-core/pom.xml b/adapters/spi/jboss-adapter-core/pom.xml index 11b61c3e3f83..7a4623cec476 100755 --- a/adapters/spi/jboss-adapter-core/pom.xml +++ b/adapters/spi/jboss-adapter-core/pom.xml @@ -21,7 +21,7 @@ keycloak-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../../../pom.xml 4.0.0 diff --git a/adapters/spi/jetty-adapter-spi/pom.xml b/adapters/spi/jetty-adapter-spi/pom.xml index e2134163ecc7..edf189c24d6a 100755 --- a/adapters/spi/jetty-adapter-spi/pom.xml +++ b/adapters/spi/jetty-adapter-spi/pom.xml @@ -21,7 +21,7 @@ keycloak-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../../../pom.xml 4.0.0 diff --git a/adapters/spi/pom.xml b/adapters/spi/pom.xml index d662207ed499..f14009fab409 100755 --- a/adapters/spi/pom.xml +++ b/adapters/spi/pom.xml @@ -20,7 +20,7 @@ keycloak-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../../pom.xml Keycloak Client Adapter SPI Modules diff --git a/adapters/spi/servlet-adapter-spi/pom.xml b/adapters/spi/servlet-adapter-spi/pom.xml index ecae51f155a7..7a61a0bc60ea 100755 --- a/adapters/spi/servlet-adapter-spi/pom.xml +++ b/adapters/spi/servlet-adapter-spi/pom.xml @@ -21,7 +21,7 @@ keycloak-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../../../pom.xml 4.0.0 diff --git a/adapters/spi/tomcat-adapter-spi/pom.xml b/adapters/spi/tomcat-adapter-spi/pom.xml index 23378d7c583c..3ee0fda74460 100755 --- a/adapters/spi/tomcat-adapter-spi/pom.xml +++ b/adapters/spi/tomcat-adapter-spi/pom.xml @@ -21,7 +21,7 @@ keycloak-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../../../pom.xml 4.0.0 diff --git a/adapters/spi/undertow-adapter-spi/pom.xml b/adapters/spi/undertow-adapter-spi/pom.xml index 9ebbed5ce248..d3b0e7fc0d44 100755 --- a/adapters/spi/undertow-adapter-spi/pom.xml +++ b/adapters/spi/undertow-adapter-spi/pom.xml @@ -21,7 +21,7 @@ keycloak-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../../../pom.xml 4.0.0 diff --git a/authz/client/pom.xml b/authz/client/pom.xml index 3dbf10c18316..fda32679559c 100644 --- a/authz/client/pom.xml +++ b/authz/client/pom.xml @@ -7,7 +7,7 @@ org.keycloak keycloak-authz-parent - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../pom.xml diff --git a/authz/policy/common/pom.xml b/authz/policy/common/pom.xml index a27dba1a98df..6cf86b6a3611 100644 --- a/authz/policy/common/pom.xml +++ b/authz/policy/common/pom.xml @@ -25,7 +25,7 @@ org.keycloak keycloak-authz-provider-parent - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../pom.xml diff --git a/authz/policy/drools/pom.xml b/authz/policy/drools/pom.xml index dd4adff2a3ef..0dcd10713c95 100644 --- a/authz/policy/drools/pom.xml +++ b/authz/policy/drools/pom.xml @@ -7,7 +7,7 @@ org.keycloak keycloak-authz-provider-parent - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../pom.xml diff --git a/authz/policy/pom.xml b/authz/policy/pom.xml index 6a8816d51f0d..3f24bf51db55 100644 --- a/authz/policy/pom.xml +++ b/authz/policy/pom.xml @@ -7,7 +7,7 @@ org.keycloak keycloak-authz-parent - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../pom.xml diff --git a/authz/pom.xml b/authz/pom.xml index 9e9898bcb0ea..7be9e346445f 100644 --- a/authz/pom.xml +++ b/authz/pom.xml @@ -7,7 +7,7 @@ org.keycloak keycloak-parent - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../pom.xml diff --git a/common/pom.xml b/common/pom.xml index e741c092b6ff..f94aa831ed53 100755 --- a/common/pom.xml +++ b/common/pom.xml @@ -21,7 +21,7 @@ keycloak-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../pom.xml 4.0.0 diff --git a/core/pom.xml b/core/pom.xml index 3e69bdc1c7cf..ab080f8f44ce 100755 --- a/core/pom.xml +++ b/core/pom.xml @@ -21,7 +21,7 @@ keycloak-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../pom.xml 4.0.0 diff --git a/core/src/main/java/org/keycloak/representations/adapters/config/AdapterConfig.java b/core/src/main/java/org/keycloak/representations/adapters/config/AdapterConfig.java index 0ba327d7331e..e4065bcd05e9 100755 --- a/core/src/main/java/org/keycloak/representations/adapters/config/AdapterConfig.java +++ b/core/src/main/java/org/keycloak/representations/adapters/config/AdapterConfig.java @@ -36,7 +36,8 @@ "client-keystore", "client-keystore-password", "client-key-password", "always-refresh-token", "register-node-at-startup", "register-node-period", "token-store", "principal-attribute", - "proxy-url", "turn-off-change-session-id-on-login", "token-minimum-time-to-live", "min-time-between-jwks-requests", + "proxy-url", "turn-off-change-session-id-on-login", "token-minimum-time-to-live", + "min-time-between-jwks-requests", "public-key-cache-ttl", "policy-enforcer" }) public class AdapterConfig extends BaseAdapterConfig implements AdapterHttpClientConfig { @@ -73,6 +74,8 @@ public class AdapterConfig extends BaseAdapterConfig implements AdapterHttpClien protected int tokenMinimumTimeToLive = 0; @JsonProperty("min-time-between-jwks-requests") protected int minTimeBetweenJwksRequests = 10; + @JsonProperty("public-key-cache-ttl") + protected int publicKeyCacheTtl = 86400; // 1 day @JsonProperty("policy-enforcer") protected PolicyEnforcerConfig policyEnforcerConfig; @@ -233,4 +236,12 @@ public int getMinTimeBetweenJwksRequests() { public void setMinTimeBetweenJwksRequests(int minTimeBetweenJwksRequests) { this.minTimeBetweenJwksRequests = minTimeBetweenJwksRequests; } + + public int getPublicKeyCacheTtl() { + return publicKeyCacheTtl; + } + + public void setPublicKeyCacheTtl(int publicKeyCacheTtl) { + this.publicKeyCacheTtl = publicKeyCacheTtl; + } } diff --git a/dependencies/pom.xml b/dependencies/pom.xml index 17883aba05ee..6d727403614d 100755 --- a/dependencies/pom.xml +++ b/dependencies/pom.xml @@ -21,7 +21,7 @@ keycloak-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT 4.0.0 diff --git a/dependencies/server-all/pom.xml b/dependencies/server-all/pom.xml index 4d66d38139a1..f4489d4a45c0 100755 --- a/dependencies/server-all/pom.xml +++ b/dependencies/server-all/pom.xml @@ -21,7 +21,7 @@ keycloak-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../../pom.xml 4.0.0 diff --git a/dependencies/server-min/pom.xml b/dependencies/server-min/pom.xml index 6cbf21b22b52..1da3a70014b8 100755 --- a/dependencies/server-min/pom.xml +++ b/dependencies/server-min/pom.xml @@ -21,7 +21,7 @@ keycloak-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../../pom.xml 4.0.0 diff --git a/distribution/adapters/as7-eap6-adapter/as7-adapter-zip/pom.xml b/distribution/adapters/as7-eap6-adapter/as7-adapter-zip/pom.xml index 4315912996f3..589927f9e4d0 100755 --- a/distribution/adapters/as7-eap6-adapter/as7-adapter-zip/pom.xml +++ b/distribution/adapters/as7-eap6-adapter/as7-adapter-zip/pom.xml @@ -21,7 +21,7 @@ keycloak-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../../../../pom.xml diff --git a/distribution/adapters/as7-eap6-adapter/as7-modules/pom.xml b/distribution/adapters/as7-eap6-adapter/as7-modules/pom.xml index ec486aa30ee1..ca587580d554 100755 --- a/distribution/adapters/as7-eap6-adapter/as7-modules/pom.xml +++ b/distribution/adapters/as7-eap6-adapter/as7-modules/pom.xml @@ -25,7 +25,7 @@ keycloak-as7-eap6-adapter-dist-pom org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../pom.xml diff --git a/distribution/adapters/as7-eap6-adapter/eap6-adapter-zip/pom.xml b/distribution/adapters/as7-eap6-adapter/eap6-adapter-zip/pom.xml index 2a9767de3de8..991ac2d5ed59 100755 --- a/distribution/adapters/as7-eap6-adapter/eap6-adapter-zip/pom.xml +++ b/distribution/adapters/as7-eap6-adapter/eap6-adapter-zip/pom.xml @@ -21,7 +21,7 @@ keycloak-as7-eap6-adapter-dist-pom org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../pom.xml diff --git a/distribution/adapters/as7-eap6-adapter/pom.xml b/distribution/adapters/as7-eap6-adapter/pom.xml index a00b0500649a..fe2df2ecdea1 100644 --- a/distribution/adapters/as7-eap6-adapter/pom.xml +++ b/distribution/adapters/as7-eap6-adapter/pom.xml @@ -20,7 +20,7 @@ keycloak-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../../../pom.xml Keycloak AS7 / JBoss EAP 6 Adapter Distros diff --git a/distribution/adapters/fuse-adapter-zip/pom.xml b/distribution/adapters/fuse-adapter-zip/pom.xml index 7c036d9407a2..abda11dc963f 100644 --- a/distribution/adapters/fuse-adapter-zip/pom.xml +++ b/distribution/adapters/fuse-adapter-zip/pom.xml @@ -21,7 +21,7 @@ keycloak-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../../../pom.xml diff --git a/distribution/adapters/jetty81-adapter-zip/pom.xml b/distribution/adapters/jetty81-adapter-zip/pom.xml index 074315f9c1fb..72fa56733d14 100755 --- a/distribution/adapters/jetty81-adapter-zip/pom.xml +++ b/distribution/adapters/jetty81-adapter-zip/pom.xml @@ -21,7 +21,7 @@ keycloak-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../../../pom.xml diff --git a/distribution/adapters/jetty91-adapter-zip/pom.xml b/distribution/adapters/jetty91-adapter-zip/pom.xml index 6ad37cdf188d..09ee966fa2ee 100755 --- a/distribution/adapters/jetty91-adapter-zip/pom.xml +++ b/distribution/adapters/jetty91-adapter-zip/pom.xml @@ -21,7 +21,7 @@ keycloak-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../../../pom.xml diff --git a/distribution/adapters/jetty92-adapter-zip/pom.xml b/distribution/adapters/jetty92-adapter-zip/pom.xml index e1acb949898c..10dfe4e3e1b9 100755 --- a/distribution/adapters/jetty92-adapter-zip/pom.xml +++ b/distribution/adapters/jetty92-adapter-zip/pom.xml @@ -21,7 +21,7 @@ keycloak-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../../../pom.xml diff --git a/distribution/adapters/jetty93-adapter-zip/pom.xml b/distribution/adapters/jetty93-adapter-zip/pom.xml index a65b62de5766..ddb743f72950 100644 --- a/distribution/adapters/jetty93-adapter-zip/pom.xml +++ b/distribution/adapters/jetty93-adapter-zip/pom.xml @@ -21,7 +21,7 @@ keycloak-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../../../pom.xml diff --git a/distribution/adapters/js-adapter-zip/pom.xml b/distribution/adapters/js-adapter-zip/pom.xml index 1e3074bed16e..57dcae40382d 100755 --- a/distribution/adapters/js-adapter-zip/pom.xml +++ b/distribution/adapters/js-adapter-zip/pom.xml @@ -21,7 +21,7 @@ keycloak-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../../../pom.xml diff --git a/distribution/adapters/osgi/features/pom.xml b/distribution/adapters/osgi/features/pom.xml index 56a1253f732f..7448ff600079 100755 --- a/distribution/adapters/osgi/features/pom.xml +++ b/distribution/adapters/osgi/features/pom.xml @@ -21,7 +21,7 @@ keycloak-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../../../../pom.xml Keycloak OSGI Features diff --git a/distribution/adapters/osgi/jaas/pom.xml b/distribution/adapters/osgi/jaas/pom.xml index b9868930df08..fcd302962dec 100755 --- a/distribution/adapters/osgi/jaas/pom.xml +++ b/distribution/adapters/osgi/jaas/pom.xml @@ -21,7 +21,7 @@ keycloak-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../../../../pom.xml Keycloak OSGI JAAS Realm Configuration diff --git a/distribution/adapters/osgi/pom.xml b/distribution/adapters/osgi/pom.xml index 8a4f6037fa93..093e2ece6e29 100755 --- a/distribution/adapters/osgi/pom.xml +++ b/distribution/adapters/osgi/pom.xml @@ -21,7 +21,7 @@ keycloak-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../../../pom.xml Keycloak OSGI Integration diff --git a/distribution/adapters/osgi/thirdparty/pom.xml b/distribution/adapters/osgi/thirdparty/pom.xml index 470469addbde..1974d0f03806 100755 --- a/distribution/adapters/osgi/thirdparty/pom.xml +++ b/distribution/adapters/osgi/thirdparty/pom.xml @@ -21,7 +21,7 @@ keycloak-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../../../../pom.xml diff --git a/distribution/adapters/pom.xml b/distribution/adapters/pom.xml index 5c9bcc8480a4..b8ca39ae6d91 100755 --- a/distribution/adapters/pom.xml +++ b/distribution/adapters/pom.xml @@ -20,7 +20,7 @@ keycloak-distribution-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT Adapters Distribution Parent diff --git a/distribution/adapters/tomcat6-adapter-zip/pom.xml b/distribution/adapters/tomcat6-adapter-zip/pom.xml index bc650acb01bc..67de7c35656e 100755 --- a/distribution/adapters/tomcat6-adapter-zip/pom.xml +++ b/distribution/adapters/tomcat6-adapter-zip/pom.xml @@ -21,7 +21,7 @@ keycloak-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../../../pom.xml diff --git a/distribution/adapters/tomcat7-adapter-zip/pom.xml b/distribution/adapters/tomcat7-adapter-zip/pom.xml index b524945ca0eb..6d2d8875cd90 100755 --- a/distribution/adapters/tomcat7-adapter-zip/pom.xml +++ b/distribution/adapters/tomcat7-adapter-zip/pom.xml @@ -21,7 +21,7 @@ keycloak-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../../../pom.xml diff --git a/distribution/adapters/tomcat8-adapter-zip/pom.xml b/distribution/adapters/tomcat8-adapter-zip/pom.xml index d1dac8d30635..ba29d3332222 100755 --- a/distribution/adapters/tomcat8-adapter-zip/pom.xml +++ b/distribution/adapters/tomcat8-adapter-zip/pom.xml @@ -21,7 +21,7 @@ keycloak-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../../../pom.xml diff --git a/distribution/adapters/wf8-adapter/pom.xml b/distribution/adapters/wf8-adapter/pom.xml index 922e754fefc2..7bd34a0b965c 100644 --- a/distribution/adapters/wf8-adapter/pom.xml +++ b/distribution/adapters/wf8-adapter/pom.xml @@ -20,7 +20,7 @@ keycloak-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../../../pom.xml Keycloak Wildfly 8 Adapter diff --git a/distribution/adapters/wf8-adapter/wf8-adapter-zip/pom.xml b/distribution/adapters/wf8-adapter/wf8-adapter-zip/pom.xml index 4d0a06ba6e12..9bb314b2c008 100755 --- a/distribution/adapters/wf8-adapter/wf8-adapter-zip/pom.xml +++ b/distribution/adapters/wf8-adapter/wf8-adapter-zip/pom.xml @@ -21,7 +21,7 @@ keycloak-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../../../../pom.xml diff --git a/distribution/adapters/wf8-adapter/wf8-modules/pom.xml b/distribution/adapters/wf8-adapter/wf8-modules/pom.xml index ef7c3310be41..2e151c724fda 100755 --- a/distribution/adapters/wf8-adapter/wf8-modules/pom.xml +++ b/distribution/adapters/wf8-adapter/wf8-modules/pom.xml @@ -25,7 +25,7 @@ keycloak-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../../../../pom.xml diff --git a/distribution/adapters/wildfly-adapter/pom.xml b/distribution/adapters/wildfly-adapter/pom.xml index 0f814d47e794..af991b81698b 100644 --- a/distribution/adapters/wildfly-adapter/pom.xml +++ b/distribution/adapters/wildfly-adapter/pom.xml @@ -20,7 +20,7 @@ keycloak-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../../../pom.xml Keycloak Wildfly Adapter diff --git a/distribution/adapters/wildfly-adapter/wildfly-adapter-zip/pom.xml b/distribution/adapters/wildfly-adapter/wildfly-adapter-zip/pom.xml index 42518765894a..f691030ed364 100755 --- a/distribution/adapters/wildfly-adapter/wildfly-adapter-zip/pom.xml +++ b/distribution/adapters/wildfly-adapter/wildfly-adapter-zip/pom.xml @@ -21,7 +21,7 @@ keycloak-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../../../../pom.xml diff --git a/distribution/adapters/wildfly-adapter/wildfly-modules/pom.xml b/distribution/adapters/wildfly-adapter/wildfly-modules/pom.xml index bf500db1ba9e..b528fefce32d 100755 --- a/distribution/adapters/wildfly-adapter/wildfly-modules/pom.xml +++ b/distribution/adapters/wildfly-adapter/wildfly-modules/pom.xml @@ -25,7 +25,7 @@ keycloak-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../../../../pom.xml diff --git a/distribution/api-docs-dist/pom.xml b/distribution/api-docs-dist/pom.xml index 22675780905a..8536bb96f81f 100755 --- a/distribution/api-docs-dist/pom.xml +++ b/distribution/api-docs-dist/pom.xml @@ -21,7 +21,7 @@ keycloak-distribution-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT keycloak-api-docs-dist diff --git a/distribution/demo-dist/pom.xml b/distribution/demo-dist/pom.xml index 2d0130ff32ec..ddb6e0483853 100755 --- a/distribution/demo-dist/pom.xml +++ b/distribution/demo-dist/pom.xml @@ -21,7 +21,7 @@ keycloak-distribution-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT keycloak-demo-dist diff --git a/distribution/downloads/pom.xml b/distribution/downloads/pom.xml index 1fc22ff938e0..bba0b912a4b3 100755 --- a/distribution/downloads/pom.xml +++ b/distribution/downloads/pom.xml @@ -21,7 +21,7 @@ keycloak-distribution-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT keycloak-dist-downloads diff --git a/distribution/examples-dist/pom.xml b/distribution/examples-dist/pom.xml index cb25859405fe..c7eea912cbf2 100755 --- a/distribution/examples-dist/pom.xml +++ b/distribution/examples-dist/pom.xml @@ -21,7 +21,7 @@ keycloak-distribution-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT keycloak-examples-dist diff --git a/distribution/feature-packs/adapter-feature-pack/pom.xml b/distribution/feature-packs/adapter-feature-pack/pom.xml index ca868b3e94e1..9dbfe27990c1 100755 --- a/distribution/feature-packs/adapter-feature-pack/pom.xml +++ b/distribution/feature-packs/adapter-feature-pack/pom.xml @@ -19,7 +19,7 @@ org.keycloak feature-packs-parent - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT 4.0.0 diff --git a/distribution/feature-packs/pom.xml b/distribution/feature-packs/pom.xml index 4198508487a9..e767d8cd3fb5 100644 --- a/distribution/feature-packs/pom.xml +++ b/distribution/feature-packs/pom.xml @@ -20,7 +20,7 @@ keycloak-distribution-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT Feature Pack Builds diff --git a/distribution/feature-packs/server-feature-pack/pom.xml b/distribution/feature-packs/server-feature-pack/pom.xml index f001634bb938..2a5ee4c903d5 100644 --- a/distribution/feature-packs/server-feature-pack/pom.xml +++ b/distribution/feature-packs/server-feature-pack/pom.xml @@ -19,7 +19,7 @@ org.keycloak feature-packs-parent - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../pom.xml 4.0.0 diff --git a/distribution/pom.xml b/distribution/pom.xml index 6004cc0ca78d..dfb8e7c0da4f 100755 --- a/distribution/pom.xml +++ b/distribution/pom.xml @@ -20,7 +20,7 @@ keycloak-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../pom.xml diff --git a/distribution/proxy-dist/pom.xml b/distribution/proxy-dist/pom.xml index 279314d46a11..40e5d265acd8 100755 --- a/distribution/proxy-dist/pom.xml +++ b/distribution/proxy-dist/pom.xml @@ -21,7 +21,7 @@ keycloak-distribution-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT keycloak-proxy-dist diff --git a/distribution/saml-adapters/as7-eap6-adapter/as7-adapter-zip/pom.xml b/distribution/saml-adapters/as7-eap6-adapter/as7-adapter-zip/pom.xml index bc99ccb2332a..d3ad498eb034 100755 --- a/distribution/saml-adapters/as7-eap6-adapter/as7-adapter-zip/pom.xml +++ b/distribution/saml-adapters/as7-eap6-adapter/as7-adapter-zip/pom.xml @@ -21,7 +21,7 @@ keycloak-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../../../../pom.xml diff --git a/distribution/saml-adapters/as7-eap6-adapter/as7-modules/pom.xml b/distribution/saml-adapters/as7-eap6-adapter/as7-modules/pom.xml index bef3baf6475c..545e0337f48c 100755 --- a/distribution/saml-adapters/as7-eap6-adapter/as7-modules/pom.xml +++ b/distribution/saml-adapters/as7-eap6-adapter/as7-modules/pom.xml @@ -25,7 +25,7 @@ keycloak-saml-as7-eap6-adapter-dist-pom org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../pom.xml diff --git a/distribution/saml-adapters/as7-eap6-adapter/eap6-adapter-zip/pom.xml b/distribution/saml-adapters/as7-eap6-adapter/eap6-adapter-zip/pom.xml index cc487792eb3b..d6433a4aa668 100755 --- a/distribution/saml-adapters/as7-eap6-adapter/eap6-adapter-zip/pom.xml +++ b/distribution/saml-adapters/as7-eap6-adapter/eap6-adapter-zip/pom.xml @@ -21,7 +21,7 @@ keycloak-saml-as7-eap6-adapter-dist-pom org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../pom.xml diff --git a/distribution/saml-adapters/as7-eap6-adapter/pom.xml b/distribution/saml-adapters/as7-eap6-adapter/pom.xml index 0ceef5a14ae0..1a705c1a5fda 100755 --- a/distribution/saml-adapters/as7-eap6-adapter/pom.xml +++ b/distribution/saml-adapters/as7-eap6-adapter/pom.xml @@ -20,7 +20,7 @@ keycloak-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../../../pom.xml Keycloak SAML AS7 / JBoss EAP 6 Adapter Distros diff --git a/distribution/saml-adapters/jetty81-adapter-zip/pom.xml b/distribution/saml-adapters/jetty81-adapter-zip/pom.xml index 1d8ddd34b7d9..aeb4407092e5 100755 --- a/distribution/saml-adapters/jetty81-adapter-zip/pom.xml +++ b/distribution/saml-adapters/jetty81-adapter-zip/pom.xml @@ -21,7 +21,7 @@ keycloak-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../../../pom.xml diff --git a/distribution/saml-adapters/jetty92-adapter-zip/pom.xml b/distribution/saml-adapters/jetty92-adapter-zip/pom.xml index 589fdde4ba30..9ba4478bdd3f 100755 --- a/distribution/saml-adapters/jetty92-adapter-zip/pom.xml +++ b/distribution/saml-adapters/jetty92-adapter-zip/pom.xml @@ -21,7 +21,7 @@ keycloak-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../../../pom.xml diff --git a/distribution/saml-adapters/jetty93-adapter-zip/pom.xml b/distribution/saml-adapters/jetty93-adapter-zip/pom.xml index 9f06f28bc504..42e4d7517885 100644 --- a/distribution/saml-adapters/jetty93-adapter-zip/pom.xml +++ b/distribution/saml-adapters/jetty93-adapter-zip/pom.xml @@ -21,7 +21,7 @@ keycloak-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../../../pom.xml diff --git a/distribution/saml-adapters/pom.xml b/distribution/saml-adapters/pom.xml index e27379346391..e45813038e71 100755 --- a/distribution/saml-adapters/pom.xml +++ b/distribution/saml-adapters/pom.xml @@ -20,7 +20,7 @@ keycloak-distribution-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT SAML Adapters Distribution Parent diff --git a/distribution/saml-adapters/tomcat6-adapter-zip/pom.xml b/distribution/saml-adapters/tomcat6-adapter-zip/pom.xml index 828270131919..bee45754e369 100755 --- a/distribution/saml-adapters/tomcat6-adapter-zip/pom.xml +++ b/distribution/saml-adapters/tomcat6-adapter-zip/pom.xml @@ -21,7 +21,7 @@ keycloak-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../../../pom.xml diff --git a/distribution/saml-adapters/tomcat7-adapter-zip/pom.xml b/distribution/saml-adapters/tomcat7-adapter-zip/pom.xml index 59112359d615..14b987528a1c 100755 --- a/distribution/saml-adapters/tomcat7-adapter-zip/pom.xml +++ b/distribution/saml-adapters/tomcat7-adapter-zip/pom.xml @@ -21,7 +21,7 @@ keycloak-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../../../pom.xml diff --git a/distribution/saml-adapters/tomcat8-adapter-zip/pom.xml b/distribution/saml-adapters/tomcat8-adapter-zip/pom.xml index e0036d68f353..339b05459c95 100755 --- a/distribution/saml-adapters/tomcat8-adapter-zip/pom.xml +++ b/distribution/saml-adapters/tomcat8-adapter-zip/pom.xml @@ -21,7 +21,7 @@ keycloak-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../../../pom.xml diff --git a/distribution/saml-adapters/wildfly-adapter/pom.xml b/distribution/saml-adapters/wildfly-adapter/pom.xml index 91f640208055..da5d1f12bd64 100755 --- a/distribution/saml-adapters/wildfly-adapter/pom.xml +++ b/distribution/saml-adapters/wildfly-adapter/pom.xml @@ -20,7 +20,7 @@ keycloak-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../../../pom.xml Keycloak Wildfly SAML Adapter diff --git a/distribution/saml-adapters/wildfly-adapter/wildfly-adapter-zip/pom.xml b/distribution/saml-adapters/wildfly-adapter/wildfly-adapter-zip/pom.xml index 655a99f274fa..34823e976766 100755 --- a/distribution/saml-adapters/wildfly-adapter/wildfly-adapter-zip/pom.xml +++ b/distribution/saml-adapters/wildfly-adapter/wildfly-adapter-zip/pom.xml @@ -21,7 +21,7 @@ keycloak-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../../../../pom.xml diff --git a/distribution/saml-adapters/wildfly-adapter/wildfly-modules/pom.xml b/distribution/saml-adapters/wildfly-adapter/wildfly-modules/pom.xml index 6e8a4c3dbbe9..9fe62c9dd503 100755 --- a/distribution/saml-adapters/wildfly-adapter/wildfly-modules/pom.xml +++ b/distribution/saml-adapters/wildfly-adapter/wildfly-modules/pom.xml @@ -25,7 +25,7 @@ keycloak-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../../../../pom.xml diff --git a/distribution/server-dist/pom.xml b/distribution/server-dist/pom.xml index 6ce5eaad729d..85bd5520233f 100755 --- a/distribution/server-dist/pom.xml +++ b/distribution/server-dist/pom.xml @@ -21,7 +21,7 @@ keycloak-distribution-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT keycloak-server-dist diff --git a/distribution/server-overlay/pom.xml b/distribution/server-overlay/pom.xml index 485dd4693c3b..ddf8cb56e7dc 100755 --- a/distribution/server-overlay/pom.xml +++ b/distribution/server-overlay/pom.xml @@ -21,7 +21,7 @@ keycloak-distribution-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT keycloak-server-overlay diff --git a/examples/admin-client/pom.xml b/examples/admin-client/pom.xml index 70b4e062a170..a37811e3959c 100755 --- a/examples/admin-client/pom.xml +++ b/examples/admin-client/pom.xml @@ -22,7 +22,7 @@ keycloak-examples-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT Keycloak Examples - Admin Client diff --git a/examples/authz/hello-world-authz-service/pom.xml b/examples/authz/hello-world-authz-service/pom.xml index 11ec9504802e..d68e59912f0f 100755 --- a/examples/authz/hello-world-authz-service/pom.xml +++ b/examples/authz/hello-world-authz-service/pom.xml @@ -24,7 +24,7 @@ org.keycloak keycloak-authz-example-parent - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../pom.xml diff --git a/examples/authz/hello-world/pom.xml b/examples/authz/hello-world/pom.xml index 7863206386a0..c48651c49e5b 100755 --- a/examples/authz/hello-world/pom.xml +++ b/examples/authz/hello-world/pom.xml @@ -24,7 +24,7 @@ org.keycloak keycloak-authz-example-parent - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../pom.xml diff --git a/examples/authz/photoz/photoz-authz-policy/pom.xml b/examples/authz/photoz/photoz-authz-policy/pom.xml index 5f594cc3280c..36415dcb5d58 100755 --- a/examples/authz/photoz/photoz-authz-policy/pom.xml +++ b/examples/authz/photoz/photoz-authz-policy/pom.xml @@ -6,7 +6,7 @@ org.keycloak keycloak-authz-photoz-parent - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../pom.xml diff --git a/examples/authz/photoz/photoz-html5-client/pom.xml b/examples/authz/photoz/photoz-html5-client/pom.xml index 94a586d8c413..337a8a9a6444 100755 --- a/examples/authz/photoz/photoz-html5-client/pom.xml +++ b/examples/authz/photoz/photoz-html5-client/pom.xml @@ -5,7 +5,7 @@ org.keycloak keycloak-authz-photoz-parent - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../pom.xml diff --git a/examples/authz/photoz/photoz-restful-api/pom.xml b/examples/authz/photoz/photoz-restful-api/pom.xml index 46dd910ffb1d..c4016f09e6ae 100755 --- a/examples/authz/photoz/photoz-restful-api/pom.xml +++ b/examples/authz/photoz/photoz-restful-api/pom.xml @@ -6,7 +6,7 @@ org.keycloak keycloak-authz-photoz-parent - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../pom.xml diff --git a/examples/authz/photoz/pom.xml b/examples/authz/photoz/pom.xml index 35222d844c88..813c680bebc9 100755 --- a/examples/authz/photoz/pom.xml +++ b/examples/authz/photoz/pom.xml @@ -6,7 +6,7 @@ org.keycloak keycloak-authz-example-parent - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../pom.xml diff --git a/examples/authz/pom.xml b/examples/authz/pom.xml index c15d7baf04c5..a05ae7ab3b65 100755 --- a/examples/authz/pom.xml +++ b/examples/authz/pom.xml @@ -6,7 +6,7 @@ keycloak-examples-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../pom.xml diff --git a/examples/authz/servlet-authz/pom.xml b/examples/authz/servlet-authz/pom.xml index 0ad402227a67..502c20a90f40 100755 --- a/examples/authz/servlet-authz/pom.xml +++ b/examples/authz/servlet-authz/pom.xml @@ -6,7 +6,7 @@ org.keycloak keycloak-authz-example-parent - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../pom.xml diff --git a/examples/basic-auth/pom.xml b/examples/basic-auth/pom.xml index dbe695e541db..26f5d89587c1 100755 --- a/examples/basic-auth/pom.xml +++ b/examples/basic-auth/pom.xml @@ -23,7 +23,7 @@ keycloak-examples-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT Keycloak Examples - Basic Auth diff --git a/examples/broker/facebook-authentication/pom.xml b/examples/broker/facebook-authentication/pom.xml index ac389599d80b..c385021b5a5b 100755 --- a/examples/broker/facebook-authentication/pom.xml +++ b/examples/broker/facebook-authentication/pom.xml @@ -23,7 +23,7 @@ keycloak-examples-broker-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT Keycloak Broker Examples - Facebook Authentication diff --git a/examples/broker/google-authentication/pom.xml b/examples/broker/google-authentication/pom.xml index 6daddda5f90a..2915b37d7274 100755 --- a/examples/broker/google-authentication/pom.xml +++ b/examples/broker/google-authentication/pom.xml @@ -23,7 +23,7 @@ keycloak-examples-broker-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT Keycloak Broker Examples - Google Authentication diff --git a/examples/broker/pom.xml b/examples/broker/pom.xml index 7574ff6d96ab..ea4e4b9b107b 100755 --- a/examples/broker/pom.xml +++ b/examples/broker/pom.xml @@ -20,7 +20,7 @@ keycloak-examples-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT Broker Examples diff --git a/examples/broker/saml-broker-authentication/pom.xml b/examples/broker/saml-broker-authentication/pom.xml index a926b417129d..44ee35cf450e 100755 --- a/examples/broker/saml-broker-authentication/pom.xml +++ b/examples/broker/saml-broker-authentication/pom.xml @@ -23,7 +23,7 @@ keycloak-examples-broker-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT Keycloak Broker Examples - SAML Identity Provider Brokering diff --git a/examples/broker/twitter-authentication/pom.xml b/examples/broker/twitter-authentication/pom.xml index 5d7faccaab0f..af32c5e7a6c4 100755 --- a/examples/broker/twitter-authentication/pom.xml +++ b/examples/broker/twitter-authentication/pom.xml @@ -23,7 +23,7 @@ keycloak-examples-broker-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT Keycloak Broker Examples - Twitter Authentication diff --git a/examples/cors/angular-product-app/pom.xml b/examples/cors/angular-product-app/pom.xml index 3412f64834d3..ec4f7696a556 100755 --- a/examples/cors/angular-product-app/pom.xml +++ b/examples/cors/angular-product-app/pom.xml @@ -21,7 +21,7 @@ keycloak-examples-cors-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT 4.0.0 diff --git a/examples/cors/database-service/pom.xml b/examples/cors/database-service/pom.xml index 14f71ecfc062..e59fca3b59b8 100755 --- a/examples/cors/database-service/pom.xml +++ b/examples/cors/database-service/pom.xml @@ -21,7 +21,7 @@ keycloak-examples-cors-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT 4.0.0 diff --git a/examples/cors/pom.xml b/examples/cors/pom.xml index 69aa10f71f5b..a38f8d8d57fc 100755 --- a/examples/cors/pom.xml +++ b/examples/cors/pom.xml @@ -21,7 +21,7 @@ keycloak-examples-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT Keycloak Examples - CORS diff --git a/examples/demo-template/admin-access-app/pom.xml b/examples/demo-template/admin-access-app/pom.xml index 2d93fb4968c6..49ba4f8c0464 100755 --- a/examples/demo-template/admin-access-app/pom.xml +++ b/examples/demo-template/admin-access-app/pom.xml @@ -21,7 +21,7 @@ keycloak-examples-demo-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT 4.0.0 diff --git a/examples/demo-template/angular-product-app/pom.xml b/examples/demo-template/angular-product-app/pom.xml index 9d81a988183c..c540f364e80f 100755 --- a/examples/demo-template/angular-product-app/pom.xml +++ b/examples/demo-template/angular-product-app/pom.xml @@ -21,7 +21,7 @@ keycloak-examples-demo-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT 4.0.0 diff --git a/examples/demo-template/angular2-product-app/pom.xml b/examples/demo-template/angular2-product-app/pom.xml index ee63fd6eb9c9..3ac174ab2162 100644 --- a/examples/demo-template/angular2-product-app/pom.xml +++ b/examples/demo-template/angular2-product-app/pom.xml @@ -21,7 +21,7 @@ keycloak-examples-demo-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT 4.0.0 diff --git a/examples/demo-template/customer-app-cli/pom.xml b/examples/demo-template/customer-app-cli/pom.xml index 0f8a08f46c5d..c4aef580f0fc 100755 --- a/examples/demo-template/customer-app-cli/pom.xml +++ b/examples/demo-template/customer-app-cli/pom.xml @@ -21,7 +21,7 @@ keycloak-examples-demo-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT 4.0.0 diff --git a/examples/demo-template/customer-app-filter/pom.xml b/examples/demo-template/customer-app-filter/pom.xml index 7d3bd7614c54..5e49975687d3 100755 --- a/examples/demo-template/customer-app-filter/pom.xml +++ b/examples/demo-template/customer-app-filter/pom.xml @@ -21,7 +21,7 @@ keycloak-examples-demo-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT 4.0.0 diff --git a/examples/demo-template/customer-app-js/pom.xml b/examples/demo-template/customer-app-js/pom.xml index a0f6317ef4f3..efd296182d98 100755 --- a/examples/demo-template/customer-app-js/pom.xml +++ b/examples/demo-template/customer-app-js/pom.xml @@ -21,7 +21,7 @@ keycloak-examples-demo-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT 4.0.0 diff --git a/examples/demo-template/customer-app/pom.xml b/examples/demo-template/customer-app/pom.xml index 1adc37f1d94e..96697dbe5b23 100755 --- a/examples/demo-template/customer-app/pom.xml +++ b/examples/demo-template/customer-app/pom.xml @@ -21,7 +21,7 @@ keycloak-examples-demo-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT 4.0.0 diff --git a/examples/demo-template/database-service/pom.xml b/examples/demo-template/database-service/pom.xml index e46ebf4f3ba4..1fbdec472b8f 100755 --- a/examples/demo-template/database-service/pom.xml +++ b/examples/demo-template/database-service/pom.xml @@ -21,7 +21,7 @@ keycloak-examples-demo-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT 4.0.0 diff --git a/examples/demo-template/example-ear/pom.xml b/examples/demo-template/example-ear/pom.xml index a81d5e993066..57fb93b5c226 100755 --- a/examples/demo-template/example-ear/pom.xml +++ b/examples/demo-template/example-ear/pom.xml @@ -21,7 +21,7 @@ keycloak-examples-demo-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT 4.0.0 diff --git a/examples/demo-template/offline-access-app/pom.xml b/examples/demo-template/offline-access-app/pom.xml index d5dc95daf209..103f13de3691 100755 --- a/examples/demo-template/offline-access-app/pom.xml +++ b/examples/demo-template/offline-access-app/pom.xml @@ -21,7 +21,7 @@ keycloak-examples-demo-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT 4.0.0 diff --git a/examples/demo-template/pom.xml b/examples/demo-template/pom.xml index f2d38ad12b8e..d08aedbc1d99 100755 --- a/examples/demo-template/pom.xml +++ b/examples/demo-template/pom.xml @@ -20,7 +20,7 @@ keycloak-examples-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT Examples diff --git a/examples/demo-template/product-app/pom.xml b/examples/demo-template/product-app/pom.xml index 8b123e8499dc..71ae41f22b45 100755 --- a/examples/demo-template/product-app/pom.xml +++ b/examples/demo-template/product-app/pom.xml @@ -21,7 +21,7 @@ keycloak-examples-demo-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT 4.0.0 diff --git a/examples/demo-template/service-account/pom.xml b/examples/demo-template/service-account/pom.xml index 517cd394871f..2d5c45da7028 100755 --- a/examples/demo-template/service-account/pom.xml +++ b/examples/demo-template/service-account/pom.xml @@ -21,7 +21,7 @@ keycloak-examples-demo-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT 4.0.0 diff --git a/examples/demo-template/third-party-cdi/pom.xml b/examples/demo-template/third-party-cdi/pom.xml index 8ceaf946a145..b0b0212ee63b 100755 --- a/examples/demo-template/third-party-cdi/pom.xml +++ b/examples/demo-template/third-party-cdi/pom.xml @@ -21,7 +21,7 @@ keycloak-examples-demo-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT 4.0.0 diff --git a/examples/demo-template/third-party/pom.xml b/examples/demo-template/third-party/pom.xml index 664b2e68855a..fcd67c5159ed 100755 --- a/examples/demo-template/third-party/pom.xml +++ b/examples/demo-template/third-party/pom.xml @@ -21,7 +21,7 @@ keycloak-examples-demo-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT 4.0.0 diff --git a/examples/fuse/camel/pom.xml b/examples/fuse/camel/pom.xml index 984e98785c33..be15f3d740e7 100755 --- a/examples/fuse/camel/pom.xml +++ b/examples/fuse/camel/pom.xml @@ -21,7 +21,7 @@ keycloak-examples-fuse-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT 4.0.0 diff --git a/examples/fuse/customer-app-fuse/pom.xml b/examples/fuse/customer-app-fuse/pom.xml index 603a2cc47fda..7d9f990f5dd1 100755 --- a/examples/fuse/customer-app-fuse/pom.xml +++ b/examples/fuse/customer-app-fuse/pom.xml @@ -21,7 +21,7 @@ keycloak-examples-fuse-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT 4.0.0 diff --git a/examples/fuse/cxf-jaxrs/pom.xml b/examples/fuse/cxf-jaxrs/pom.xml index ac4832ec9699..60238fb627f1 100755 --- a/examples/fuse/cxf-jaxrs/pom.xml +++ b/examples/fuse/cxf-jaxrs/pom.xml @@ -21,7 +21,7 @@ keycloak-examples-fuse-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT 4.0.0 diff --git a/examples/fuse/cxf-jaxws/pom.xml b/examples/fuse/cxf-jaxws/pom.xml index 2a37cfbc3ff9..b3705c7ab233 100755 --- a/examples/fuse/cxf-jaxws/pom.xml +++ b/examples/fuse/cxf-jaxws/pom.xml @@ -21,7 +21,7 @@ keycloak-examples-fuse-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT 4.0.0 diff --git a/examples/fuse/external-config/pom.xml b/examples/fuse/external-config/pom.xml index 178904bcb1d4..daadfefca643 100755 --- a/examples/fuse/external-config/pom.xml +++ b/examples/fuse/external-config/pom.xml @@ -21,7 +21,7 @@ keycloak-examples-fuse-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT Keycloak Examples - External Config diff --git a/examples/fuse/features/pom.xml b/examples/fuse/features/pom.xml index 58183e61748b..7d59641074f2 100755 --- a/examples/fuse/features/pom.xml +++ b/examples/fuse/features/pom.xml @@ -21,7 +21,7 @@ keycloak-examples-fuse-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT 4.0.0 diff --git a/examples/fuse/pom.xml b/examples/fuse/pom.xml index d589b8d1c647..cc09f877a8fb 100755 --- a/examples/fuse/pom.xml +++ b/examples/fuse/pom.xml @@ -20,7 +20,7 @@ keycloak-examples-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT Fuse examples diff --git a/examples/fuse/product-app-fuse/pom.xml b/examples/fuse/product-app-fuse/pom.xml index 1b5dc91d2de7..418f327ccee3 100755 --- a/examples/fuse/product-app-fuse/pom.xml +++ b/examples/fuse/product-app-fuse/pom.xml @@ -21,7 +21,7 @@ keycloak-examples-fuse-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT 4.0.0 diff --git a/examples/js-console/pom.xml b/examples/js-console/pom.xml index 3d5f651357d7..eade8ca31e84 100755 --- a/examples/js-console/pom.xml +++ b/examples/js-console/pom.xml @@ -21,7 +21,7 @@ keycloak-examples-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT 4.0.0 diff --git a/examples/kerberos/pom.xml b/examples/kerberos/pom.xml index 129575ba304e..8e2bcca436a4 100755 --- a/examples/kerberos/pom.xml +++ b/examples/kerberos/pom.xml @@ -22,7 +22,7 @@ keycloak-examples-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT Keycloak Examples - Kerberos Credential Delegation diff --git a/examples/ldap/pom.xml b/examples/ldap/pom.xml index 4b65b78173f2..d70425b6cb56 100644 --- a/examples/ldap/pom.xml +++ b/examples/ldap/pom.xml @@ -22,7 +22,7 @@ keycloak-examples-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT 4.0.0 diff --git a/examples/multi-tenant/pom.xml b/examples/multi-tenant/pom.xml index ac303311ab5d..e0c276c9a8ab 100755 --- a/examples/multi-tenant/pom.xml +++ b/examples/multi-tenant/pom.xml @@ -21,7 +21,7 @@ keycloak-examples-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT Keycloak Examples - Multi Tenant diff --git a/examples/pom.xml b/examples/pom.xml index 1a985e2ad54d..f2507b1696e5 100755 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -20,7 +20,7 @@ keycloak-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT Examples diff --git a/examples/providers/authenticator/pom.xml b/examples/providers/authenticator/pom.xml index 100b03a41bbc..5b70723eb3b4 100755 --- a/examples/providers/authenticator/pom.xml +++ b/examples/providers/authenticator/pom.xml @@ -20,7 +20,7 @@ keycloak-examples-providers-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT Authenticator Example diff --git a/examples/providers/domain-extension/pom.xml b/examples/providers/domain-extension/pom.xml index e0d75ca6e47a..7cae0351bc2e 100755 --- a/examples/providers/domain-extension/pom.xml +++ b/examples/providers/domain-extension/pom.xml @@ -20,7 +20,7 @@ keycloak-examples-providers-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT Domain Extension Example diff --git a/examples/providers/event-listener-sysout/pom.xml b/examples/providers/event-listener-sysout/pom.xml index e5dcf77bc6d9..d17e48ae9547 100755 --- a/examples/providers/event-listener-sysout/pom.xml +++ b/examples/providers/event-listener-sysout/pom.xml @@ -20,7 +20,7 @@ keycloak-examples-providers-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT Event Listener System.out Example diff --git a/examples/providers/event-store-mem/pom.xml b/examples/providers/event-store-mem/pom.xml index d1e068c0f6ed..88ac583cd266 100755 --- a/examples/providers/event-store-mem/pom.xml +++ b/examples/providers/event-store-mem/pom.xml @@ -20,7 +20,7 @@ keycloak-examples-providers-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT Event Store In-Mem Example diff --git a/examples/providers/pom.xml b/examples/providers/pom.xml index c9be81d3bb98..dd59811509bc 100755 --- a/examples/providers/pom.xml +++ b/examples/providers/pom.xml @@ -20,7 +20,7 @@ keycloak-examples-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT Provider Examples diff --git a/examples/providers/rest/pom.xml b/examples/providers/rest/pom.xml index b17a42e9d3eb..1f785500d5ff 100755 --- a/examples/providers/rest/pom.xml +++ b/examples/providers/rest/pom.xml @@ -20,7 +20,7 @@ keycloak-examples-providers-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT Authenticator Example diff --git a/examples/providers/user-storage-jpa/pom.xml b/examples/providers/user-storage-jpa/pom.xml index d22ecc8015df..0eb846feb994 100755 --- a/examples/providers/user-storage-jpa/pom.xml +++ b/examples/providers/user-storage-jpa/pom.xml @@ -20,7 +20,7 @@ keycloak-examples-providers-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT User Storage JPA Provider Exapmle diff --git a/examples/providers/user-storage-simple/pom.xml b/examples/providers/user-storage-simple/pom.xml index 099510323dc9..03faeec62a38 100755 --- a/examples/providers/user-storage-simple/pom.xml +++ b/examples/providers/user-storage-simple/pom.xml @@ -20,7 +20,7 @@ keycloak-examples-providers-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT UserStorageProvider Simple Example diff --git a/examples/saml/pom.xml b/examples/saml/pom.xml index 429fe35dc17b..c5ffee9cf4f7 100755 --- a/examples/saml/pom.xml +++ b/examples/saml/pom.xml @@ -20,7 +20,7 @@ keycloak-examples-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT Provider Examples diff --git a/examples/saml/post-with-encryption/pom.xml b/examples/saml/post-with-encryption/pom.xml index 41cde50ce2b0..40c690ae89f7 100755 --- a/examples/saml/post-with-encryption/pom.xml +++ b/examples/saml/post-with-encryption/pom.xml @@ -22,7 +22,7 @@ keycloak-examples-saml-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT saml-post-encryption diff --git a/examples/saml/post-with-signature/pom.xml b/examples/saml/post-with-signature/pom.xml index 06d1a8710f19..fc74042de409 100755 --- a/examples/saml/post-with-signature/pom.xml +++ b/examples/saml/post-with-signature/pom.xml @@ -22,7 +22,7 @@ keycloak-examples-saml-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT sales-post-sig diff --git a/examples/saml/redirect-with-signature/pom.xml b/examples/saml/redirect-with-signature/pom.xml index c86a0f6ae5d4..0a8a6d93f776 100755 --- a/examples/saml/redirect-with-signature/pom.xml +++ b/examples/saml/redirect-with-signature/pom.xml @@ -22,7 +22,7 @@ keycloak-examples-saml-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT saml-redirect-signatures diff --git a/examples/saml/servlet-filter/pom.xml b/examples/saml/servlet-filter/pom.xml index fb01fa874885..3b1f94b12b44 100755 --- a/examples/saml/servlet-filter/pom.xml +++ b/examples/saml/servlet-filter/pom.xml @@ -22,7 +22,7 @@ keycloak-examples-saml-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT saml-servlet-filter diff --git a/examples/themes/pom.xml b/examples/themes/pom.xml index ab4c7b618a04..ff5fc6a2f9da 100755 --- a/examples/themes/pom.xml +++ b/examples/themes/pom.xml @@ -20,7 +20,7 @@ keycloak-examples-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT Themes Examples diff --git a/federation/kerberos/pom.xml b/federation/kerberos/pom.xml index a169fe2c5c8a..e8eddb18aaf0 100755 --- a/federation/kerberos/pom.xml +++ b/federation/kerberos/pom.xml @@ -20,7 +20,7 @@ keycloak-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../../pom.xml 4.0.0 diff --git a/federation/ldap/pom.xml b/federation/ldap/pom.xml index 8e554a5846b7..932381410762 100755 --- a/federation/ldap/pom.xml +++ b/federation/ldap/pom.xml @@ -20,7 +20,7 @@ keycloak-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../../pom.xml 4.0.0 diff --git a/federation/ldap/src/main/java/org/keycloak/storage/ldap/LDAPConfig.java b/federation/ldap/src/main/java/org/keycloak/storage/ldap/LDAPConfig.java index ec2e32c403a9..930837d0370a 100644 --- a/federation/ldap/src/main/java/org/keycloak/storage/ldap/LDAPConfig.java +++ b/federation/ldap/src/main/java/org/keycloak/storage/ldap/LDAPConfig.java @@ -127,6 +127,10 @@ public String getUuidLDAPAttributeName() { return uuidAttrName; } + + public boolean isObjectGUID() { + return getUuidLDAPAttributeName().equalsIgnoreCase(LDAPConstants.OBJECT_GUID); + } public boolean isPagination() { String pagination = config.getFirst(LDAPConstants.PAGINATION); diff --git a/federation/ldap/src/main/java/org/keycloak/storage/ldap/idm/store/ldap/LDAPOperationManager.java b/federation/ldap/src/main/java/org/keycloak/storage/ldap/idm/store/ldap/LDAPOperationManager.java index 4fe40020e357..cb58a1e1748f 100644 --- a/federation/ldap/src/main/java/org/keycloak/storage/ldap/idm/store/ldap/LDAPOperationManager.java +++ b/federation/ldap/src/main/java/org/keycloak/storage/ldap/idm/store/ldap/LDAPOperationManager.java @@ -242,7 +242,7 @@ private SearchControls getSearchControls(Collection returningAttributes, public String getFilterById(String id) { String filter = null; - if (this.config.isActiveDirectory()) { + if (this.config.isObjectGUID()) { final String strObjectGUID = ""; try { @@ -458,8 +458,7 @@ public Attributes getAttributes(final String entryUUID, final String baseDN, Set public String decodeEntryUUID(final Object entryUUID) { String id; - - if (this.config.isActiveDirectory() && entryUUID instanceof byte[]) { + if (this.config.isObjectGUID() && entryUUID instanceof byte[]) { id = LDAPUtil.decodeObjectGUID((byte[]) entryUUID); } else { id = entryUUID.toString(); @@ -516,7 +515,7 @@ private Map createConnectionProperties() { } } - if (config.isActiveDirectory()) { + if (this.config.isObjectGUID()) { env.put("java.naming.ldap.attributes.binary", LDAPConstants.OBJECT_GUID); } diff --git a/federation/ldap/src/main/java/org/keycloak/storage/ldap/mappers/msadlds/MSADLDSUserAccountControlStorageMapper.java b/federation/ldap/src/main/java/org/keycloak/storage/ldap/mappers/msadlds/MSADLDSUserAccountControlStorageMapper.java new file mode 100644 index 000000000000..be07781321e4 --- /dev/null +++ b/federation/ldap/src/main/java/org/keycloak/storage/ldap/mappers/msadlds/MSADLDSUserAccountControlStorageMapper.java @@ -0,0 +1,267 @@ +/* + * Copyright 2016 Red Hat, Inc. and/or its affiliates + * and other contributors as indicated by the @author tags. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.keycloak.storage.ldap.mappers.msadlds; + +import org.jboss.logging.Logger; +import org.keycloak.component.ComponentModel; +import org.keycloak.credential.CredentialInput; +import org.keycloak.models.LDAPConstants; +import org.keycloak.models.ModelException; +import org.keycloak.models.RealmModel; +import org.keycloak.models.UserModel; +import org.keycloak.models.utils.UserModelDelegate; +import org.keycloak.storage.UserStorageProvider; +import org.keycloak.storage.ldap.LDAPStorageProvider; +import org.keycloak.storage.ldap.idm.model.LDAPObject; +import org.keycloak.storage.ldap.idm.query.internal.LDAPQuery; +import org.keycloak.storage.ldap.mappers.AbstractLDAPStorageMapper; +import org.keycloak.storage.ldap.mappers.PasswordUpdated; + +import javax.naming.AuthenticationException; +import java.util.HashSet; +import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * Mapper specific to MSAD LDS. It's able to read the msDS-UserAccountDisabled, msDS-UserPasswordExpired and pwdLastSet attributes and set actions in Keycloak based on that. + * It's also able to handle exception code from LDAP user authentication (See http://www-01.ibm.com/support/docview.wss?uid=swg21290631 ) + * + * @author Marek Posolda + * @author Slawomir Dabek + */ +public class MSADLDSUserAccountControlStorageMapper extends AbstractLDAPStorageMapper implements PasswordUpdated { + + private static final Logger logger = Logger.getLogger(MSADLDSUserAccountControlStorageMapper.class); + + private static final Pattern AUTH_EXCEPTION_REGEX = Pattern.compile(".*AcceptSecurityContext error, data ([0-9a-f]*), v.*"); + private static final Pattern AUTH_INVALID_NEW_PASSWORD = Pattern.compile("(?s).*problem 1005 \\(CONSTRAINT_ATT_TYPE\\), data [0-9a-f]*, Att 23 \\(userPassword\\).*"); + + public MSADLDSUserAccountControlStorageMapper(ComponentModel mapperModel, LDAPStorageProvider ldapProvider, RealmModel realm) { + super(mapperModel, ldapProvider, realm); + ldapProvider.setUpdater(this); + } + + @Override + public void beforeLDAPQuery(LDAPQuery query) { + query.addReturningLdapAttribute(LDAPConstants.PWD_LAST_SET); + query.addReturningLdapAttribute(LDAPConstants.MSDS_USER_ACCOUNT_DISABLED); + + // This needs to be read-only and can be set to writable just on demand + query.addReturningReadOnlyLdapAttribute(LDAPConstants.PWD_LAST_SET); + + if (ldapProvider.getEditMode() != UserStorageProvider.EditMode.WRITABLE) { + query.addReturningReadOnlyLdapAttribute(LDAPConstants.MSDS_USER_ACCOUNT_DISABLED); + } + } + + @Override + public void passwordUpdated(UserModel user, LDAPObject ldapUser, CredentialInput input) { + logger.debugf("Going to update pwdLastSet for ldap user '%s' after successful password update", ldapUser.getDn().toString()); + + // Normally it's read-only + ldapUser.removeReadOnlyAttributeName(LDAPConstants.PWD_LAST_SET); + + ldapUser.setSingleAttribute(LDAPConstants.PWD_LAST_SET, "-1"); + + if (user.isEnabled()) { + // TODO: Use removeAttribute once available + ldapUser.setSingleAttribute(LDAPConstants.MSDS_USER_ACCOUNT_DISABLED, "FALSE"); + logger.debugf("Removing msDS-UserPasswordExpired of user '%s'", ldapUser.getDn().toString()); + } + + ldapProvider.getLdapIdentityStore().update(ldapUser); + } + + @Override + public UserModel proxy(LDAPObject ldapUser, UserModel delegate) { + return new MSADUserModelDelegate(delegate, ldapUser); + } + + @Override + public void onRegisterUserToLDAP(LDAPObject ldapUser, UserModel localUser) { + + } + + @Override + public void onImportUserFromLDAP(LDAPObject ldapUser, UserModel user, boolean isCreate) { + + } + + @Override + public boolean onAuthenticationFailure(LDAPObject ldapUser, UserModel user, AuthenticationException ldapException) { + String exceptionMessage = ldapException.getMessage(); + Matcher m = AUTH_EXCEPTION_REGEX.matcher(exceptionMessage); + if (m.matches()) { + String errorCode = m.group(1); + return processAuthErrorCode(errorCode, user); + } else { + return false; + } + } + + protected boolean processAuthErrorCode(String errorCode, UserModel user) { + logger.debugf("MSAD LDS Error code is '%s' after failed LDAP login of user '%s'", errorCode, user.getUsername()); + + if (ldapProvider.getEditMode() == UserStorageProvider.EditMode.WRITABLE) { + if (errorCode.equals("532") || errorCode.equals("773")) { + // User needs to change his MSAD password. Allow him to login, but add UPDATE_PASSWORD required action + user.addRequiredAction(UserModel.RequiredAction.UPDATE_PASSWORD); + return true; + } else if (errorCode.equals("533")) { + // User is disabled in MSAD LDS. Set him to disabled in KC as well + user.setEnabled(false); + return true; + } else if (errorCode.equals("775")) { + logger.warnf("Locked user '%s' attempt to login", user.getUsername()); + } + } + + return false; + } + + + protected ModelException processFailedPasswordUpdateException(ModelException e) { + if (e.getCause() == null || e.getCause().getMessage() == null) { + return e; + } + + String exceptionMessage = e.getCause().getMessage(); + Matcher m = AUTH_INVALID_NEW_PASSWORD.matcher(exceptionMessage); + if (m.matches()) { + ModelException me = new ModelException("invalidPasswordRegexPatternMessage", e); + me.setParameters(new Object[]{"passwordConstraintViolation"}); + return me; + } + + return e; + } + + public class MSADUserModelDelegate extends UserModelDelegate { + + private final LDAPObject ldapUser; + + public MSADUserModelDelegate(UserModel delegate, LDAPObject ldapUser) { + super(delegate); + this.ldapUser = ldapUser; + } + + @Override + public boolean isEnabled() { + boolean kcEnabled = super.isEnabled(); + + if (getPwdLastSet() > 0) { + // Merge KC and MSAD LDS + return kcEnabled && !Boolean.parseBoolean(ldapUser.getAttributeAsString(LDAPConstants.MSDS_USER_ACCOUNT_DISABLED)); + } else { + // If new MSAD LDS user is created and pwdLastSet is still 0, MSAD account is in disabled state. So read just from Keycloak DB. User is not able to login via MSAD anyway + return kcEnabled; + } + } + + @Override + public void setEnabled(boolean enabled) { + // Always update DB + super.setEnabled(enabled); + + if (ldapProvider.getEditMode() == UserStorageProvider.EditMode.WRITABLE && getPwdLastSet() > 0) { + if (enabled) { + logger.debugf("Removing msDS-UserAccountDisabled of user '%s'", ldapUser.getDn().toString()); + // TODO: Use removeAttribute once available + ldapUser.setSingleAttribute(LDAPConstants.MSDS_USER_ACCOUNT_DISABLED, "FALSE"); + } else { + logger.debugf("Setting msDS-UserAccountDisabled of user '%s' to value 'TRUE'", ldapUser.getDn().toString()); + ldapUser.setSingleAttribute(LDAPConstants.MSDS_USER_ACCOUNT_DISABLED, "TRUE"); + } + + ldapProvider.getLdapIdentityStore().update(ldapUser); + } + } + + @Override + public void addRequiredAction(RequiredAction action) { + String actionName = action.name(); + addRequiredAction(actionName); + } + + @Override + public void addRequiredAction(String action) { + // Always update DB + super.addRequiredAction(action); + + if (ldapProvider.getEditMode() == UserStorageProvider.EditMode.WRITABLE && RequiredAction.UPDATE_PASSWORD.toString().equals(action)) { + logger.debugf("Going to propagate required action UPDATE_PASSWORD to MSAD for ldap user '%s' ", ldapUser.getDn().toString()); + + // Normally it's read-only + ldapUser.removeReadOnlyAttributeName(LDAPConstants.PWD_LAST_SET); + + ldapUser.setSingleAttribute(LDAPConstants.PWD_LAST_SET, "0"); + ldapProvider.getLdapIdentityStore().update(ldapUser); + } + } + + @Override + public void removeRequiredAction(RequiredAction action) { + String actionName = action.name(); + removeRequiredAction(actionName); + } + + @Override + public void removeRequiredAction(String action) { + // Always update DB + super.removeRequiredAction(action); + + if (ldapProvider.getEditMode() == UserStorageProvider.EditMode.WRITABLE && RequiredAction.UPDATE_PASSWORD.toString().equals(action)) { + + // Don't set pwdLastSet in MSAD LDS when it is new user + if (!Boolean.parseBoolean(ldapUser.getAttributeAsString(LDAPConstants.MSDS_USER_PASSWORD_NOTREQD))) { + logger.debugf("Going to remove required action UPDATE_PASSWORD from MSAD LDS for ldap user '%s' ", ldapUser.getDn().toString()); + + // Normally it's read-only + ldapUser.removeReadOnlyAttributeName(LDAPConstants.PWD_LAST_SET); + + ldapUser.setSingleAttribute(LDAPConstants.PWD_LAST_SET, "-1"); + ldapProvider.getLdapIdentityStore().update(ldapUser); + } + } + } + + @Override + public Set getRequiredActions() { + Set requiredActions = super.getRequiredActions(); + + if (ldapProvider.getEditMode() == UserStorageProvider.EditMode.WRITABLE) { + if (getPwdLastSet() == 0 || Boolean.parseBoolean(ldapUser.getAttributeAsString(LDAPConstants.MSDS_USER_PASSWORD_EXPIRED))) { + requiredActions = new HashSet<>(requiredActions); + requiredActions.add(RequiredAction.UPDATE_PASSWORD.toString()); + return requiredActions; + } + } + + return requiredActions; + } + + protected long getPwdLastSet() { + String pwdLastSet = ldapUser.getAttributeAsString(LDAPConstants.PWD_LAST_SET); + return pwdLastSet == null ? 0 : Long.parseLong(pwdLastSet); + } + + + } + +} diff --git a/federation/ldap/src/main/java/org/keycloak/storage/ldap/mappers/msadlds/MSADLDSUserAccountControlStorageMapperFactory.java b/federation/ldap/src/main/java/org/keycloak/storage/ldap/mappers/msadlds/MSADLDSUserAccountControlStorageMapperFactory.java new file mode 100644 index 000000000000..fc456cdddf27 --- /dev/null +++ b/federation/ldap/src/main/java/org/keycloak/storage/ldap/mappers/msadlds/MSADLDSUserAccountControlStorageMapperFactory.java @@ -0,0 +1,63 @@ +/* + * Copyright 2016 Red Hat, Inc. and/or its affiliates + * and other contributors as indicated by the @author tags. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.keycloak.storage.ldap.mappers.msadlds; + +import org.keycloak.component.ComponentModel; +import org.keycloak.models.LDAPConstants; +import org.keycloak.models.RealmModel; +import org.keycloak.provider.ProviderConfigProperty; +import org.keycloak.storage.ldap.LDAPStorageProvider; +import org.keycloak.storage.ldap.mappers.AbstractLDAPStorageMapper; +import org.keycloak.storage.ldap.mappers.AbstractLDAPStorageMapperFactory; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author Marek Posolda + * @author Slawomir Dabek + */ +public class MSADLDSUserAccountControlStorageMapperFactory extends AbstractLDAPStorageMapperFactory { + + public static final String PROVIDER_ID = LDAPConstants.MSADLDS_USER_ACCOUNT_CONTROL_MAPPER; + protected static final List configProperties = new ArrayList<>(); + + static { + } + + @Override + public String getHelpText() { + return "Mapper specific to MSAD LDS. It's able to integrate the MSAD LDS user account state into Keycloak account state (account enabled, password is expired etc). It's using msDS-UserAccountDisabled and pwdLastSet MSAD attributes for that. " + + "For example if pwdLastSet is 0, the Keycloak user is required to update password, if msDS-UserAccountDisabled is 'TRUE' the Keycloak user is disabled as well etc. Mapper is also able to handle exception code from LDAP user authentication."; + } + + @Override + public List getConfigProperties() { + return configProperties; + } + + @Override + public String getId() { + return PROVIDER_ID; + } + + @Override + protected AbstractLDAPStorageMapper createMapper(ComponentModel mapperModel, LDAPStorageProvider federationProvider, RealmModel realm) { + return new MSADLDSUserAccountControlStorageMapper(mapperModel, federationProvider, realm); + } +} diff --git a/federation/ldap/src/main/resources/META-INF/services/org.keycloak.storage.ldap.mappers.LDAPStorageMapperFactory b/federation/ldap/src/main/resources/META-INF/services/org.keycloak.storage.ldap.mappers.LDAPStorageMapperFactory index 6f3f5ae3b069..3781e87bf351 100644 --- a/federation/ldap/src/main/resources/META-INF/services/org.keycloak.storage.ldap.mappers.LDAPStorageMapperFactory +++ b/federation/ldap/src/main/resources/META-INF/services/org.keycloak.storage.ldap.mappers.LDAPStorageMapperFactory @@ -20,4 +20,5 @@ org.keycloak.storage.ldap.mappers.HardcodedLDAPRoleStorageMapperFactory org.keycloak.storage.ldap.mappers.membership.group.GroupLDAPStorageMapperFactory org.keycloak.storage.ldap.mappers.membership.role.RoleLDAPStorageMapperFactory org.keycloak.storage.ldap.mappers.msad.MSADUserAccountControlStorageMapperFactory +org.keycloak.storage.ldap.mappers.msadlds.MSADLDSUserAccountControlStorageMapperFactory org.keycloak.storage.ldap.mappers.UserAttributeLDAPStorageMapperFactory diff --git a/federation/pom.xml b/federation/pom.xml index 0d592a3b9fd8..b7766646fd3b 100755 --- a/federation/pom.xml +++ b/federation/pom.xml @@ -22,7 +22,7 @@ keycloak-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../pom.xml 4.0.0 diff --git a/federation/sssd/pom.xml b/federation/sssd/pom.xml index 789bbe2c2d0c..9e4d2c33d7a8 100644 --- a/federation/sssd/pom.xml +++ b/federation/sssd/pom.xml @@ -4,7 +4,7 @@ keycloak-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../../pom.xml 4.0.0 diff --git a/integration/admin-client/pom.xml b/integration/admin-client/pom.xml index 3c3924656b68..507619bc57e6 100755 --- a/integration/admin-client/pom.xml +++ b/integration/admin-client/pom.xml @@ -22,7 +22,7 @@ keycloak-integration-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT 4.0.0 diff --git a/integration/client-cli/client-cli-dist/pom.xml b/integration/client-cli/client-cli-dist/pom.xml index b6fdbf39af15..1b567cb52979 100755 --- a/integration/client-cli/client-cli-dist/pom.xml +++ b/integration/client-cli/client-cli-dist/pom.xml @@ -21,7 +21,7 @@ keycloak-client-cli-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT keycloak-client-cli-dist diff --git a/integration/client-cli/client-registration-cli/pom.xml b/integration/client-cli/client-registration-cli/pom.xml index f1f95d0944f7..dc5c21023748 100755 --- a/integration/client-cli/client-registration-cli/pom.xml +++ b/integration/client-cli/client-registration-cli/pom.xml @@ -21,7 +21,7 @@ keycloak-client-cli-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT 4.0.0 diff --git a/integration/client-cli/pom.xml b/integration/client-cli/pom.xml index 64a78e43050b..4759514b25dc 100644 --- a/integration/client-cli/pom.xml +++ b/integration/client-cli/pom.xml @@ -20,7 +20,7 @@ keycloak-integration-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT Keycloak Client CLI diff --git a/integration/client-registration/pom.xml b/integration/client-registration/pom.xml index 7e101921aea5..45e4690331d6 100755 --- a/integration/client-registration/pom.xml +++ b/integration/client-registration/pom.xml @@ -21,7 +21,7 @@ keycloak-integration-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT 4.0.0 diff --git a/integration/pom.xml b/integration/pom.xml index 44422df0a9c9..863eadea56e5 100755 --- a/integration/pom.xml +++ b/integration/pom.xml @@ -20,7 +20,7 @@ keycloak-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../pom.xml Keycloak Integration diff --git a/model/infinispan/pom.xml b/model/infinispan/pom.xml index 287dd99a3701..ef3ceceae709 100755 --- a/model/infinispan/pom.xml +++ b/model/infinispan/pom.xml @@ -21,7 +21,7 @@ keycloak-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../../pom.xml 4.0.0 diff --git a/model/infinispan/src/main/java/org/keycloak/keys/infinispan/InfinispanPublicKeyStorageProvider.java b/model/infinispan/src/main/java/org/keycloak/keys/infinispan/InfinispanPublicKeyStorageProvider.java index edfd392c6ce2..b5f48cd5bb13 100644 --- a/model/infinispan/src/main/java/org/keycloak/keys/infinispan/InfinispanPublicKeyStorageProvider.java +++ b/model/infinispan/src/main/java/org/keycloak/keys/infinispan/InfinispanPublicKeyStorageProvider.java @@ -55,12 +55,13 @@ public class InfinispanPublicKeyStorageProvider implements PublicKeyStorageProvi private Set invalidations = new HashSet<>(); + private boolean transactionEnlisted = false; + public InfinispanPublicKeyStorageProvider(KeycloakSession session, Cache keys, Map> tasksInProgress, int minTimeBetweenRequests) { this.session = session; this.keys = keys; this.tasksInProgress = tasksInProgress; this.minTimeBetweenRequests = minTimeBetweenRequests; - session.getTransactionManager().enlistAfterCompletion(getAfterTransaction()); } @@ -73,6 +74,11 @@ public void clearCache() { void addInvalidation(String cacheKey) { + if (!transactionEnlisted) { + session.getTransactionManager().enlistAfterCompletion(getAfterTransaction()); + transactionEnlisted = true; + } + this.invalidations.add(cacheKey); } diff --git a/model/infinispan/src/test/java/org/keycloak/keys/infinispan/InfinispanKeyStorageProviderTest.java b/model/infinispan/src/test/java/org/keycloak/keys/infinispan/InfinispanKeyStorageProviderTest.java index ffd355c8a8a5..77dd98952fdc 100644 --- a/model/infinispan/src/test/java/org/keycloak/keys/infinispan/InfinispanKeyStorageProviderTest.java +++ b/model/infinispan/src/test/java/org/keycloak/keys/infinispan/InfinispanKeyStorageProviderTest.java @@ -45,7 +45,6 @@ /** * @author Marek Posolda */ -@Ignore public class InfinispanKeyStorageProviderTest { private Map counters = new ConcurrentHashMap<>(); diff --git a/model/jpa/pom.xml b/model/jpa/pom.xml index 8bca064c4b41..ea50a668b9dc 100755 --- a/model/jpa/pom.xml +++ b/model/jpa/pom.xml @@ -21,7 +21,7 @@ keycloak-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../../pom.xml 4.0.0 diff --git a/model/mongo/pom.xml b/model/mongo/pom.xml index 4f3a1c11ea49..6bfb882bda21 100755 --- a/model/mongo/pom.xml +++ b/model/mongo/pom.xml @@ -22,7 +22,7 @@ keycloak-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../../pom.xml 4.0.0 diff --git a/model/pom.xml b/model/pom.xml index 7bbd07e1e609..a89dcb72d941 100755 --- a/model/pom.xml +++ b/model/pom.xml @@ -20,7 +20,7 @@ keycloak-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../pom.xml Keycloak Model Parent diff --git a/pom.xml b/pom.xml index 277f016c6087..55bb4f842e69 100755 --- a/pom.xml +++ b/pom.xml @@ -32,7 +32,7 @@ org.keycloak keycloak-parent - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT pom diff --git a/proxy/launcher/pom.xml b/proxy/launcher/pom.xml index 5821286acb6c..7b33d0993a36 100755 --- a/proxy/launcher/pom.xml +++ b/proxy/launcher/pom.xml @@ -21,7 +21,7 @@ keycloak-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../../pom.xml 4.0.0 diff --git a/proxy/pom.xml b/proxy/pom.xml index b21e506d1e87..2009021fd93c 100755 --- a/proxy/pom.xml +++ b/proxy/pom.xml @@ -20,7 +20,7 @@ keycloak-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../pom.xml Model Parent diff --git a/proxy/proxy-server/pom.xml b/proxy/proxy-server/pom.xml index 37d91bd85c5a..9d19ccd51855 100755 --- a/proxy/proxy-server/pom.xml +++ b/proxy/proxy-server/pom.xml @@ -21,7 +21,7 @@ keycloak-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../../pom.xml 4.0.0 diff --git a/saml-core-api/pom.xml b/saml-core-api/pom.xml index 914e893f3fcf..7bdc5688a2d8 100755 --- a/saml-core-api/pom.xml +++ b/saml-core-api/pom.xml @@ -21,7 +21,7 @@ keycloak-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../pom.xml 4.0.0 diff --git a/saml-core/pom.xml b/saml-core/pom.xml index 7cb185199a1e..a93790a926c4 100755 --- a/saml-core/pom.xml +++ b/saml-core/pom.xml @@ -21,7 +21,7 @@ keycloak-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../pom.xml 4.0.0 diff --git a/server-spi-private/pom.xml b/server-spi-private/pom.xml index 60c73a3e5683..5551600c9a9a 100755 --- a/server-spi-private/pom.xml +++ b/server-spi-private/pom.xml @@ -21,7 +21,7 @@ keycloak-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../pom.xml 4.0.0 diff --git a/server-spi-private/src/main/java/org/keycloak/broker/provider/BrokeredIdentityContext.java b/server-spi-private/src/main/java/org/keycloak/broker/provider/BrokeredIdentityContext.java index f7a26e9899c8..f2c8a7aad79b 100755 --- a/server-spi-private/src/main/java/org/keycloak/broker/provider/BrokeredIdentityContext.java +++ b/server-spi-private/src/main/java/org/keycloak/broker/provider/BrokeredIdentityContext.java @@ -161,6 +161,10 @@ public void setUserAttribute(String attributeName, String attributeValue) { getContextData().put(Constants.USER_ATTRIBUTES_PREFIX + attributeName, list); } + public void setUserAttribute(String attributeName, List attributeValues) { + getContextData().put(Constants.USER_ATTRIBUTES_PREFIX + attributeName, attributeValues); + } + public String getUserAttribute(String attributeName) { List userAttribute = (List) getContextData().get(Constants.USER_ATTRIBUTES_PREFIX + attributeName); if (userAttribute == null || userAttribute.isEmpty()) { diff --git a/server-spi-private/src/main/java/org/keycloak/models/LDAPConstants.java b/server-spi-private/src/main/java/org/keycloak/models/LDAPConstants.java index b560e1844ef8..08be1c1bd238 100644 --- a/server-spi-private/src/main/java/org/keycloak/models/LDAPConstants.java +++ b/server-spi-private/src/main/java/org/keycloak/models/LDAPConstants.java @@ -26,6 +26,7 @@ public class LDAPConstants { public static final String LDAP_PROVIDER = "ldap"; public static final String MSAD_USER_ACCOUNT_CONTROL_MAPPER = "msad-user-account-control-mapper"; + public static final String MSADLDS_USER_ACCOUNT_CONTROL_MAPPER = "msad-lds-user-account-control-mapper"; public static final String VENDOR = "vendor"; public static final String VENDOR_RHDS = "rhds"; @@ -93,6 +94,9 @@ public class LDAPConstants { public static final String GROUP_OF_UNIQUE_NAMES = "groupOfUniqueNames"; public static final String USER_ACCOUNT_CONTROL = "userAccountControl"; public static final String PWD_LAST_SET = "pwdLastSet"; + public static final String MSDS_USER_ACCOUNT_DISABLED = "msDS-UserAccountDisabled"; + public static final String MSDS_USER_PASSWORD_NOTREQD = "msDS-UserPasswordNotRequired"; + public static final String MSDS_USER_PASSWORD_EXPIRED = "msDS-UserPasswordExpired"; // read-only public static final String COMMA = ","; public static final String EQUAL = "="; diff --git a/server-spi-private/src/main/java/org/keycloak/services/managers/ClientSessionCode.java b/server-spi-private/src/main/java/org/keycloak/services/managers/ClientSessionCode.java index 27101740884c..1369e2701430 100755 --- a/server-spi-private/src/main/java/org/keycloak/services/managers/ClientSessionCode.java +++ b/server-spi-private/src/main/java/org/keycloak/services/managers/ClientSessionCode.java @@ -18,22 +18,16 @@ package org.keycloak.services.managers; import org.jboss.logging.Logger; -import org.keycloak.common.util.Base64Url; import org.keycloak.common.util.Time; -import org.keycloak.jose.jws.Algorithm; -import org.keycloak.jose.jws.crypto.RSAProvider; import org.keycloak.models.ClientModel; import org.keycloak.models.ClientSessionModel; import org.keycloak.models.ClientTemplateModel; -import org.keycloak.models.KeyManager; import org.keycloak.models.KeycloakSession; import org.keycloak.models.ProtocolMapperModel; import org.keycloak.models.RealmModel; import org.keycloak.models.RoleModel; import org.keycloak.models.utils.KeycloakModelUtils; -import java.security.PublicKey; -import java.security.Signature; import java.util.HashSet; import java.util.Set; @@ -43,6 +37,8 @@ */ public class ClientSessionCode { + private static final String ACTIVE_CODE = "active_code"; + private static final Logger logger = Logger.getLogger(ClientSessionCode.class); private static final String NEXT_CODE = ClientSessionCode.class.getName() + ".nextCode"; @@ -99,7 +95,7 @@ public static ParseResult parseResult(String code, KeycloakSession session, Real return result; } - if (!verifyCode(code, session, realm, result.clientSession)) { + if (!verifyCode(code, result.clientSession)) { result.illegalHash = true; return result; } @@ -119,7 +115,7 @@ public static ClientSessionCode parse(String code, KeycloakSession session, Real return null; } - if (!verifyCode(code, session, realm, clientSession)) { + if (!verifyCode(code, clientSession)) { return null; } @@ -215,7 +211,7 @@ public void setAction(String action) { public String getCode() { String nextCode = (String) session.getAttribute(NEXT_CODE + "." + clientSession.getId()); if (nextCode == null) { - nextCode = generateCode(session, realm, clientSession); + nextCode = generateCode(clientSession); session.setAttribute(NEXT_CODE + "." + clientSession.getId(), nextCode); } else { logger.debug("Code already generated for session, using code from session attributes"); @@ -223,30 +219,18 @@ public String getCode() { return nextCode; } - private static String generateCode(KeycloakSession session, RealmModel realm, ClientSessionModel clientSession) { + private static String generateCode(ClientSessionModel clientSession) { try { - KeyManager.ActiveKey keys = session.keys().getActiveKey(realm); - - String secret = KeycloakModelUtils.generateSecret(); + String actionId = KeycloakModelUtils.generateSecret(); StringBuilder sb = new StringBuilder(); - sb.append(secret); + sb.append(actionId); sb.append('.'); sb.append(clientSession.getId()); String code = sb.toString(); - Signature signature = RSAProvider.getSignature(Algorithm.RS256); - signature.initSign(keys.getPrivateKey()); - signature.update(code.getBytes("utf-8")); - - sb = new StringBuilder(); - - sb.append(Base64Url.encode(signature.sign())); - sb.append('.'); - sb.append(keys.getKid()); - - clientSession.setNote(ClientSessionModel.ACTION_SIGNATURE, sb.toString()); + clientSession.setNote(ACTIVE_CODE, code); return code; } catch (Exception e) { @@ -254,24 +238,17 @@ private static String generateCode(KeycloakSession session, RealmModel realm, Cl } } - private static boolean verifyCode(String code, KeycloakSession session, RealmModel realm, ClientSessionModel clientSession) { + private static boolean verifyCode(String code, ClientSessionModel clientSession) { try { - String note = clientSession.getNote(ClientSessionModel.ACTION_SIGNATURE); - if (note == null) { - logger.debug("Action signature not found in client session"); + String activeCode = clientSession.getNote(ACTIVE_CODE); + if (activeCode == null) { + logger.debug("Active code not found in client session"); return false; } - clientSession.removeNote(ClientSessionModel.ACTION_SIGNATURE); - - String[] signed = note.split("\\."); - - PublicKey publicKey = session.keys().getPublicKey(realm, signed[1]); + clientSession.removeNote(ACTIVE_CODE); - Signature verifier = RSAProvider.getSignature(Algorithm.RS256); - verifier.initVerify(publicKey); - verifier.update(code.getBytes("utf-8")); - return verifier.verify(Base64Url.decode(signed[0])); + return code.equals(activeCode); } catch (Exception e) { throw new RuntimeException(e); } diff --git a/server-spi/pom.xml b/server-spi/pom.xml index 41a118272ae5..0e8c9400fa39 100755 --- a/server-spi/pom.xml +++ b/server-spi/pom.xml @@ -21,7 +21,7 @@ keycloak-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../pom.xml 4.0.0 diff --git a/server-spi/src/main/java/org/keycloak/models/ClientSessionModel.java b/server-spi/src/main/java/org/keycloak/models/ClientSessionModel.java index 6b7e9d57159a..84fa64e1c16c 100755 --- a/server-spi/src/main/java/org/keycloak/models/ClientSessionModel.java +++ b/server-spi/src/main/java/org/keycloak/models/ClientSessionModel.java @@ -24,7 +24,6 @@ * @author Stian Thorgersen */ public interface ClientSessionModel { - public static final String ACTION_SIGNATURE = "action_signature"; public String getId(); public RealmModel getRealm(); diff --git a/services/pom.xml b/services/pom.xml index 5f89ececcc3f..ad25f69f010c 100755 --- a/services/pom.xml +++ b/services/pom.xml @@ -21,7 +21,7 @@ keycloak-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../pom.xml 4.0.0 diff --git a/services/src/main/java/org/keycloak/authentication/AuthenticationProcessor.java b/services/src/main/java/org/keycloak/authentication/AuthenticationProcessor.java index 3b409a04c578..2f23cb82a474 100755 --- a/services/src/main/java/org/keycloak/authentication/AuthenticationProcessor.java +++ b/services/src/main/java/org/keycloak/authentication/AuthenticationProcessor.java @@ -802,7 +802,7 @@ public Response authenticateOnly() throws AuthenticationFlowException { * */ public void setActionSuccessful() { - oneActionWasSuccessful = true; +// oneActionWasSuccessful = true; } public Response checkWasSuccessfulBrowserAction() { diff --git a/services/src/main/java/org/keycloak/broker/oidc/mappers/AbstractClaimMapper.java b/services/src/main/java/org/keycloak/broker/oidc/mappers/AbstractClaimMapper.java index feb51b67c9a8..f2b52882fe9f 100755 --- a/services/src/main/java/org/keycloak/broker/oidc/mappers/AbstractClaimMapper.java +++ b/services/src/main/java/org/keycloak/broker/oidc/mappers/AbstractClaimMapper.java @@ -76,7 +76,7 @@ public static Object getClaimValue(BrokeredIdentityContext context, String claim { // Search the OIDC UserInfo claim set (if any) JsonNode profileJsonNode = (JsonNode) context.getContextData().get(OIDCIdentityProvider.USER_INFO); - String value = AbstractJsonUserAttributeMapper.getJsonValue(profileJsonNode, claim); + Object value = AbstractJsonUserAttributeMapper.getJsonValue(profileJsonNode, claim); if (value != null) return value; } return null; diff --git a/services/src/main/java/org/keycloak/broker/oidc/mappers/AbstractJsonUserAttributeMapper.java b/services/src/main/java/org/keycloak/broker/oidc/mappers/AbstractJsonUserAttributeMapper.java index e718a0d7f7f3..49e145cf0bf0 100755 --- a/services/src/main/java/org/keycloak/broker/oidc/mappers/AbstractJsonUserAttributeMapper.java +++ b/services/src/main/java/org/keycloak/broker/oidc/mappers/AbstractJsonUserAttributeMapper.java @@ -35,7 +35,7 @@ * Abstract class for Social Provider mappers which allow mapping of JSON user profile field into Keycloak user * attribute. Concrete mapper classes with own ID and provider mapping must be implemented for each social provider who * uses {@link JsonNode} user profile. - * + * * @author Vlastimil Elias (velias at redhat dot com) */ public abstract class AbstractJsonUserAttributeMapper extends AbstractIdentityProviderMapper { @@ -81,8 +81,8 @@ public abstract class AbstractJsonUserAttributeMapper extends AbstractIdentityPr } /** - * Store used profile JsonNode into user context for later use by this mapper. Profile data are dumped into special logger if enabled also to allow investigation of the structure. - * + * Store used profile JsonNode into user context for later use by this mapper. Profile data are dumped into special logger if enabled also to allow investigation of the structure. + * * @param user context to store profile data into * @param profile to store into context * @param provider identification of social provider to be used in log dump @@ -125,9 +125,13 @@ public void preprocessFederatedIdentity(KeycloakSession session, RealmModel real } attribute = attribute.trim(); - String value = getJsonValue(mapperModel, context); + Object value = getJsonValue(mapperModel, context); if (value != null) { - context.setUserAttribute(attribute, value); + if (value instanceof List) { + context.setUserAttribute(attribute, (List) value); + } else { + context.setUserAttribute(attribute, value.toString()); + } } } @@ -136,7 +140,7 @@ public void updateBrokeredUser(KeycloakSession session, RealmModel realm, UserMo // we do not update user profile from social provider } - protected static String getJsonValue(IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) { + protected static Object getJsonValue(IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) { String jsonField = mapperModel.getConfig().get(CONF_JSON_FIELD); if (jsonField == null || jsonField.trim().isEmpty()) { @@ -152,7 +156,7 @@ protected static String getJsonValue(IdentityProviderMapperModel mapperModel, Br JsonNode profileJsonNode = (JsonNode) context.getContextData().get(CONTEXT_JSON_NODE); - String value = getJsonValue(profileJsonNode, jsonField); + Object value = getJsonValue(profileJsonNode, jsonField); if (value == null) { logger.debugf("User profile JSON value '%s' is not available.", jsonField); @@ -161,7 +165,7 @@ protected static String getJsonValue(IdentityProviderMapperModel mapperModel, Br return value; } - public static String getJsonValue(JsonNode baseNode, String fieldPath) { + public static Object getJsonValue(JsonNode baseNode, String fieldPath) { logger.debug("Going to process JsonNode path " + fieldPath + " on data " + baseNode); if (baseNode != null) { @@ -206,6 +210,20 @@ public static String getJsonValue(JsonNode baseNode, String fieldPath) { } if (idx < 0) { + if (currentNode.isArray()) { + List values = new ArrayList<>(); + for (JsonNode childNode : currentNode) { + if (childNode.isTextual()) { + values.add(childNode.textValue()); + } else { + logger.warn("JsonNode in array is not text value " + childNode); + } + } + if (values.isEmpty()) { + return null; + } + return arrayIndex == idx? values : null; + } if (!currentNode.isValueNode()) { logger.debug("JsonNode is not value node for name " + currentFieldName); return null; diff --git a/services/src/main/java/org/keycloak/broker/oidc/mappers/UserAttributeMapper.java b/services/src/main/java/org/keycloak/broker/oidc/mappers/UserAttributeMapper.java index 52ad5de33fb9..2e2abcae2929 100755 --- a/services/src/main/java/org/keycloak/broker/oidc/mappers/UserAttributeMapper.java +++ b/services/src/main/java/org/keycloak/broker/oidc/mappers/UserAttributeMapper.java @@ -20,14 +20,20 @@ import org.keycloak.broker.oidc.KeycloakOIDCIdentityProviderFactory; import org.keycloak.broker.oidc.OIDCIdentityProviderFactory; import org.keycloak.broker.provider.BrokeredIdentityContext; +import org.keycloak.common.util.CollectionUtil; import org.keycloak.models.IdentityProviderMapperModel; import org.keycloak.models.KeycloakSession; import org.keycloak.models.RealmModel; import org.keycloak.models.UserModel; import org.keycloak.provider.ProviderConfigProperty; +import org.keycloak.saml.common.util.StringUtil; import java.util.ArrayList; +import java.util.Collections; import java.util.List; +import java.util.Objects; +import java.util.function.Consumer; +import java.util.stream.Collectors; /** * @author Bill Burke @@ -37,9 +43,12 @@ public class UserAttributeMapper extends AbstractClaimMapper { public static final String[] COMPATIBLE_PROVIDERS = {KeycloakOIDCIdentityProviderFactory.PROVIDER_ID, OIDCIdentityProviderFactory.PROVIDER_ID}; - private static final List configProperties = new ArrayList(); + private static final List configProperties = new ArrayList<>(); public static final String USER_ATTRIBUTE = "user.attribute"; + public static final String EMAIL = "email"; + public static final String FIRST_NAME = "firstName"; + public static final String LAST_NAME = "lastName"; static { ProviderConfigProperty property; @@ -88,37 +97,63 @@ public String getDisplayType() { @Override public void preprocessFederatedIdentity(KeycloakSession session, RealmModel realm, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) { String attribute = mapperModel.getConfig().get(USER_ATTRIBUTE); + if(StringUtil.isNullOrEmpty(attribute)){ + return; + } Object value = getClaimValue(mapperModel, context); - if (value != null) { - if (attribute.equalsIgnoreCase("email")) { - context.setEmail(value.toString()); - } else if (attribute.equalsIgnoreCase("firstName")) { - context.setFirstName(value.toString()); - } else if (attribute.equalsIgnoreCase("lastName")) { - context.setLastName(value.toString()); - } else { - context.setUserAttribute(attribute, value.toString()); - } + List values = toList(value); + + if (EMAIL.equalsIgnoreCase(attribute)) { + setIfNotEmpty(context::setEmail, values); + } else if (FIRST_NAME.equalsIgnoreCase(attribute)) { + setIfNotEmpty(context::setFirstName, values); + } else if (LAST_NAME.equalsIgnoreCase(attribute)) { + setIfNotEmpty(context::setLastName, values); + } else { + List valuesToString = values.stream() + .filter(Objects::nonNull) + .map(Object::toString) + .collect(Collectors.toList()); + + context.setUserAttribute(attribute, valuesToString); + } + } + + private void setIfNotEmpty(Consumer consumer, List values) { + if (values != null && !values.isEmpty()) { + consumer.accept(values.get(0)); } } + private List toList(Object value) { + List values = (value instanceof List) + ? (List) value + : Collections.singletonList(value); + return values.stream() + .filter(Objects::nonNull) + .map(Object::toString) + .collect(Collectors.toList()); + } + @Override public void updateBrokeredUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) { String attribute = mapperModel.getConfig().get(USER_ATTRIBUTE); + if(StringUtil.isNullOrEmpty(attribute)){ + return; + } Object value = getClaimValue(mapperModel, context); - String stringValue = null; - if (value != null) stringValue = value.toString(); - if (attribute.equalsIgnoreCase("email")) { - user.setEmail(stringValue); - } else if (attribute.equalsIgnoreCase("firstName")) { - user.setFirstName(stringValue); - } else if (attribute.equalsIgnoreCase("lastName")) { - user.setLastName(stringValue); + List values = toList(value); + if (EMAIL.equalsIgnoreCase(attribute)) { + setIfNotEmpty(user::setEmail, values); + } else if (FIRST_NAME.equalsIgnoreCase(attribute)) { + setIfNotEmpty(user::setFirstName, values); + } else if (LAST_NAME.equalsIgnoreCase(attribute)) { + setIfNotEmpty(user::setLastName, values); } else { - String current = user.getFirstAttribute(attribute); - if (stringValue != null && !stringValue.equals(current)) { - user.setSingleAttribute(attribute, stringValue); - } else if (value == null) { + List current = user.getAttribute(attribute); + if (!CollectionUtil.collectionEquals(values, current)) { + user.setAttribute(attribute, values); + } else if (values.isEmpty()) { user.removeAttribute(attribute); } } diff --git a/services/src/main/java/org/keycloak/broker/saml/mappers/UserAttributeMapper.java b/services/src/main/java/org/keycloak/broker/saml/mappers/UserAttributeMapper.java index 70cae078e536..8a71493fe579 100755 --- a/services/src/main/java/org/keycloak/broker/saml/mappers/UserAttributeMapper.java +++ b/services/src/main/java/org/keycloak/broker/saml/mappers/UserAttributeMapper.java @@ -21,17 +21,18 @@ import org.keycloak.broker.provider.BrokeredIdentityContext; import org.keycloak.broker.saml.SAMLEndpoint; import org.keycloak.broker.saml.SAMLIdentityProviderFactory; +import org.keycloak.common.util.CollectionUtil; import org.keycloak.dom.saml.v2.assertion.AssertionType; import org.keycloak.dom.saml.v2.assertion.AttributeStatementType; import org.keycloak.dom.saml.v2.assertion.AttributeType; -import org.keycloak.models.IdentityProviderMapperModel; -import org.keycloak.models.KeycloakSession; -import org.keycloak.models.RealmModel; -import org.keycloak.models.UserModel; +import org.keycloak.models.*; import org.keycloak.provider.ProviderConfigProperty; +import org.keycloak.saml.common.util.StringUtil; -import java.util.ArrayList; -import java.util.List; +import java.util.*; +import java.util.function.Consumer; +import java.util.function.Predicate; +import java.util.stream.Collectors; /** * @author Bill Burke @@ -41,11 +42,14 @@ public class UserAttributeMapper extends AbstractIdentityProviderMapper { public static final String[] COMPATIBLE_PROVIDERS = {SAMLIdentityProviderFactory.PROVIDER_ID}; - private static final List configProperties = new ArrayList(); + private static final List configProperties = new ArrayList<>(); public static final String ATTRIBUTE_NAME = "attribute.name"; public static final String ATTRIBUTE_FRIENDLY_NAME = "attribute.friendly.name"; public static final String USER_ATTRIBUTE = "user.attribute"; + private static final String EMAIL = "email"; + private static final String FIRST_NAME = "firstName"; + private static final String LAST_NAME = "lastName"; static { ProviderConfigProperty property; @@ -99,61 +103,84 @@ public String getDisplayType() { @Override public void preprocessFederatedIdentity(KeycloakSession session, RealmModel realm, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) { String attribute = mapperModel.getConfig().get(USER_ATTRIBUTE); - String value = getAttribute(mapperModel, context); - if (value != null) { - if (attribute.equalsIgnoreCase("email")) { - context.setEmail(value); - } else if (attribute.equalsIgnoreCase("firstName")) { - context.setFirstName(value); - } else if (attribute.equalsIgnoreCase("lastName")) { - context.setLastName(value); + if (StringUtil.isNullOrEmpty(attribute)) { + return; + } + String attributeName = getAttributeNameFromMapperModel(mapperModel); + + List attributeValuesInContext = findAttributeValuesInContext(attributeName, context); + if (!attributeValuesInContext.isEmpty()) { + if (attribute.equalsIgnoreCase(EMAIL)) { + setIfNotEmpty(context::setEmail, attributeValuesInContext); + } else if (attribute.equalsIgnoreCase(FIRST_NAME)) { + setIfNotEmpty(context::setFirstName, attributeValuesInContext); + } else if (attribute.equalsIgnoreCase(LAST_NAME)) { + setIfNotEmpty(context::setLastName, attributeValuesInContext); } else { - context.setUserAttribute(attribute, value); + context.setUserAttribute(attribute, attributeValuesInContext); } } } - protected String getAttribute(IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) { - String name = mapperModel.getConfig().get(ATTRIBUTE_NAME); - if (name != null && name.trim().equals("")) name = null; - String friendly = mapperModel.getConfig().get(ATTRIBUTE_FRIENDLY_NAME); - if (friendly != null && friendly.trim().equals("")) friendly = null; - AssertionType assertion = (AssertionType)context.getContextData().get(SAMLEndpoint.SAML_ASSERTION); - for (AttributeStatementType statement : assertion.getAttributeStatements()) { - for (AttributeStatementType.ASTChoiceType choice : statement.getAttributes()) { - AttributeType attr = choice.getAttribute(); - if (name != null && !name.equals(attr.getName())) continue; - if (friendly != null && !friendly.equals(attr.getFriendlyName())) continue; - - List attributeValue = attr.getAttributeValue(); - if (attributeValue == null || attributeValue.isEmpty()) return null; - return attributeValue.get(0).toString(); - } + private String getAttributeNameFromMapperModel(IdentityProviderMapperModel mapperModel) { + String attributeName = mapperModel.getConfig().get(ATTRIBUTE_NAME); + if (attributeName == null) { + attributeName = mapperModel.getConfig().get(ATTRIBUTE_FRIENDLY_NAME); + } + return attributeName; + } + + private void setIfNotEmpty(Consumer consumer, List values) { + if (values != null && !values.isEmpty()) { + consumer.accept(values.get(0)); } - return null; + } + + private Predicate elementWith(String attributeName) { + return attributeType -> { + AttributeType attribute = attributeType.getAttribute(); + return Objects.equals(attribute.getName(), attributeName) + || Objects.equals(attribute.getFriendlyName(), attributeName); + }; + } + + + private List findAttributeValuesInContext(String attributeName, BrokeredIdentityContext context) { + AssertionType assertion = (AssertionType) context.getContextData().get(SAMLEndpoint.SAML_ASSERTION); + + return assertion.getAttributeStatements().stream() + .flatMap(statement -> statement.getAttributes().stream()) + .filter(elementWith(attributeName)) + .flatMap(attributeType -> attributeType.getAttribute().getAttributeValue().stream()) + .filter(Objects::nonNull) + .map(Object::toString) + .collect(Collectors.toList()); } @Override public void updateBrokeredUser(KeycloakSession session, RealmModel realm, UserModel user, IdentityProviderMapperModel mapperModel, BrokeredIdentityContext context) { String attribute = mapperModel.getConfig().get(USER_ATTRIBUTE); - String value = getAttribute(mapperModel, context); - if (attribute.equalsIgnoreCase("email")) { - user.setEmail(value); - } else if (attribute.equalsIgnoreCase("firstName")) { - user.setFirstName(value); - } else if (attribute.equalsIgnoreCase("lastName")) { - user.setLastName(value); + if (StringUtil.isNullOrEmpty(attribute)) { + return; + } + String attributeName = getAttributeNameFromMapperModel(mapperModel); + List attributeValuesInContext = findAttributeValuesInContext(attributeName, context); + if (attribute.equalsIgnoreCase(EMAIL)) { + setIfNotEmpty(user::setEmail, attributeValuesInContext); + } else if (attribute.equalsIgnoreCase(FIRST_NAME)) { + setIfNotEmpty(user::setFirstName, attributeValuesInContext); + } else if (attribute.equalsIgnoreCase(LAST_NAME)) { + setIfNotEmpty(user::setLastName, attributeValuesInContext); } else { - String current = user.getFirstAttribute(attribute); - if (value != null && !value.equals(current)) { - user.setSingleAttribute(attribute, value.toString()); - } else if (value == null) { + List currentAttributeValues = user.getAttributes().get(attribute); + if (attributeValuesInContext != null + && currentAttributeValues != null + && !CollectionUtil.collectionEquals(attributeValuesInContext, currentAttributeValues)) { + user.setAttribute(attribute, attributeValuesInContext); + } else if (attributeValuesInContext == null) { user.removeAttribute(attribute); } } - - - } @Override diff --git a/services/src/main/java/org/keycloak/partialimport/ClientRolesPartialImport.java b/services/src/main/java/org/keycloak/partialimport/ClientRolesPartialImport.java index 008917da7c82..95fa4a664551 100644 --- a/services/src/main/java/org/keycloak/partialimport/ClientRolesPartialImport.java +++ b/services/src/main/java/org/keycloak/partialimport/ClientRolesPartialImport.java @@ -103,6 +103,11 @@ public void deleteRole(RealmModel realm, String clientId, RoleRepresentation rol return; } RoleModel role = client.getRole(getName(roleRep)); + if (role == null) { + // role might not exist if client was just created as part of the + // partial import + return; + } client.removeRole(role); } diff --git a/services/src/main/java/org/keycloak/protocol/oidc/TokenManager.java b/services/src/main/java/org/keycloak/protocol/oidc/TokenManager.java index c67160794bd3..5e48c7bc7d9c 100755 --- a/services/src/main/java/org/keycloak/protocol/oidc/TokenManager.java +++ b/services/src/main/java/org/keycloak/protocol/oidc/TokenManager.java @@ -38,6 +38,7 @@ import org.keycloak.models.KeyManager; import org.keycloak.models.KeycloakSession; import org.keycloak.models.KeycloakSessionFactory; +import org.keycloak.models.ModelException; import org.keycloak.models.ProtocolMapperModel; import org.keycloak.models.RealmModel; import org.keycloak.models.RoleModel; @@ -130,15 +131,24 @@ public TokenValidation validateToken(KeycloakSession session, UriInfo uriInfo, C if (TokenUtil.TOKEN_TYPE_OFFLINE.equals(oldToken.getType())) { UserSessionManager sessionManager = new UserSessionManager(session); - clientSession = sessionManager.findOfflineClientSession(realm, oldToken.getClientSession(), oldToken.getSessionState()); + clientSession = sessionManager.findOfflineClientSession(realm, oldToken.getClientSession()); if (clientSession != null) { userSession = clientSession.getUserSession(); + if (userSession == null) { + throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Offline user session not found", "Offline user session not found"); + } + + String userSessionId = oldToken.getSessionState(); + if (!userSessionId.equals(userSession.getId())) { + throw new ModelException("User session don't match. Offline client session " + clientSession.getId() + ", It's user session " + userSession.getId() + + " Wanted user session: " + userSessionId); + } + // Revoke timeouted offline userSession if (userSession.getLastSessionRefresh() < Time.currentTime() - realm.getOfflineSessionIdleTimeout()) { sessionManager.revokeOfflineUserSession(userSession); - userSession = null; - clientSession = null; + throw new OAuthErrorException(OAuthErrorException.INVALID_GRANT, "Offline user session not active", "Offline user session session not active"); } } } else { diff --git a/services/src/main/java/org/keycloak/protocol/oidc/mappers/AddressMapper.java b/services/src/main/java/org/keycloak/protocol/oidc/mappers/AddressMapper.java index 674c9ff10c86..2f40c218298d 100755 --- a/services/src/main/java/org/keycloak/protocol/oidc/mappers/AddressMapper.java +++ b/services/src/main/java/org/keycloak/protocol/oidc/mappers/AddressMapper.java @@ -17,14 +17,11 @@ package org.keycloak.protocol.oidc.mappers; -import org.keycloak.models.ClientSessionModel; -import org.keycloak.models.KeycloakSession; import org.keycloak.models.ProtocolMapperModel; import org.keycloak.models.UserModel; import org.keycloak.models.UserSessionModel; import org.keycloak.protocol.oidc.OIDCLoginProtocol; import org.keycloak.provider.ProviderConfigProperty; -import org.keycloak.representations.AccessToken; import org.keycloak.representations.AddressClaimSet; import org.keycloak.representations.IDToken; @@ -34,7 +31,6 @@ import java.util.Map; /** - * Set the 'name' claim to be first + last name. * * @author Bill Burke * @version $Revision: 1 $ @@ -43,26 +39,39 @@ public class AddressMapper extends AbstractOIDCProtocolMapper implements OIDCAcc private static final List configProperties = new ArrayList(); + public static final String STREET = "street"; + static { OIDCAttributeMapperHelper.addIncludeInTokensConfig(configProperties, AddressMapper.class); + + configProperties.add(createConfigProperty(STREET)); + configProperties.add(createConfigProperty(AddressClaimSet.LOCALITY)); + configProperties.add(createConfigProperty(AddressClaimSet.REGION)); + configProperties.add(createConfigProperty(AddressClaimSet.POSTAL_CODE)); + configProperties.add(createConfigProperty(AddressClaimSet.COUNTRY)); + configProperties.add(createConfigProperty(AddressClaimSet.FORMATTED)); + } + + protected static ProviderConfigProperty createConfigProperty(String claimName) { + ProviderConfigProperty property = new ProviderConfigProperty(); + property.setName(getModelPropertyName(claimName)); + property.setLabel("addressClaim." + claimName + ".label"); + property.setHelpText("addressClaim." + claimName + ".tooltip"); + property.setType(ProviderConfigProperty.STRING_TYPE); + property.setDefaultValue(claimName); + return property; + } + + public static String getModelPropertyName(String claimName) { + return "user.attribute." + claimName; } public static final String PROVIDER_ID = "oidc-address-mapper"; public static ProtocolMapperModel createAddressMapper() { - Map config; - ProtocolMapperModel address = new ProtocolMapperModel(); - address.setName("address"); - address.setProtocolMapper(PROVIDER_ID); - address.setProtocol(OIDCLoginProtocol.LOGIN_PROTOCOL); - address.setConsentRequired(true); - address.setConsentText("${address}"); - config = new HashMap(); - config.put(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN, "true"); - config.put(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN, "true"); - address.setConfig(config); - return address; + return createAddressMapper(true, true); } + public static ProtocolMapperModel createAddressMapper(boolean idToken, boolean accessToken) { Map config; ProtocolMapperModel address = new ProtocolMapperModel(); @@ -74,6 +83,14 @@ public static ProtocolMapperModel createAddressMapper(boolean idToken, boolean a config = new HashMap(); config.put(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN, Boolean.toString(idToken)); config.put(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN, Boolean.toString(accessToken)); + + config.put(getModelPropertyName(STREET), STREET); + config.put(getModelPropertyName(AddressClaimSet.LOCALITY), AddressClaimSet.LOCALITY); + config.put(getModelPropertyName(AddressClaimSet.REGION), AddressClaimSet.REGION); + config.put(getModelPropertyName(AddressClaimSet.POSTAL_CODE), AddressClaimSet.POSTAL_CODE); + config.put(getModelPropertyName(AddressClaimSet.COUNTRY), AddressClaimSet.COUNTRY); + config.put(getModelPropertyName(AddressClaimSet.FORMATTED), AddressClaimSet.FORMATTED); + address.setConfig(config); return address; } @@ -107,12 +124,24 @@ public String getHelpText() { protected void setClaim(IDToken token, ProtocolMapperModel mappingModel, UserSessionModel userSession) { UserModel user = userSession.getUser(); AddressClaimSet addressSet = new AddressClaimSet(); - addressSet.setStreetAddress(user.getFirstAttribute("street")); - addressSet.setLocality(user.getFirstAttribute("locality")); - addressSet.setRegion(user.getFirstAttribute("region")); - addressSet.setPostalCode(user.getFirstAttribute("postal_code")); - addressSet.setCountry(user.getFirstAttribute("country")); + addressSet.setStreetAddress(getUserModelAttributeValue(user, mappingModel, STREET)); + addressSet.setLocality(getUserModelAttributeValue(user, mappingModel, AddressClaimSet.LOCALITY)); + addressSet.setRegion(getUserModelAttributeValue(user, mappingModel, AddressClaimSet.REGION)); + addressSet.setPostalCode(getUserModelAttributeValue(user, mappingModel, AddressClaimSet.POSTAL_CODE)); + addressSet.setCountry(getUserModelAttributeValue(user, mappingModel, AddressClaimSet.COUNTRY)); + addressSet.setFormattedAddress(getUserModelAttributeValue(user, mappingModel, AddressClaimSet.FORMATTED)); token.getOtherClaims().put("address", addressSet); } + private String getUserModelAttributeValue(UserModel user, ProtocolMapperModel mappingModel, String claim) { + String modelPropertyName = getModelPropertyName(claim); + String userAttrName = mappingModel.getConfig().get(modelPropertyName); + + if (userAttrName == null) { + userAttrName = claim; + } + + return user.getFirstAttribute(userAttrName); + } + } diff --git a/services/src/main/java/org/keycloak/protocol/oidc/mappers/OIDCAttributeMapperHelper.java b/services/src/main/java/org/keycloak/protocol/oidc/mappers/OIDCAttributeMapperHelper.java index 8b64aef891ca..7b8ba36716a5 100755 --- a/services/src/main/java/org/keycloak/protocol/oidc/mappers/OIDCAttributeMapperHelper.java +++ b/services/src/main/java/org/keycloak/protocol/oidc/mappers/OIDCAttributeMapperHelper.java @@ -25,10 +25,9 @@ import org.keycloak.representations.IDToken; import org.keycloak.services.ServicesLogger; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; +import java.util.function.Function; +import java.util.stream.Collectors; /** * @author Bill Burke @@ -70,29 +69,78 @@ public static Object mapAttributeValue(ProtocolMapperModel mappingModel, Object ServicesLogger.LOGGER.multipleValuesForMapper(attributeValue.toString(), mappingModel.getName()); } - attributeValue = valueAsList.get(0); + attributeValue = valueAsList; } } String type = mappingModel.getConfig().get(JSON_TYPE); + Object converted = convertToType(type, attributeValue); + return converted != null ? converted : attributeValue; + } + + private static List transform(List attributeValue, Function mapper) { + return attributeValue.stream() + .filter(Objects::nonNull) + .map(mapper) + .collect(Collectors.toList()); + } + + private static Object convertToType(String type, Object attributeValue) { if (type == null) return attributeValue; - if (type.equals("boolean")) { - if (attributeValue instanceof Boolean) return attributeValue; - if (attributeValue instanceof String) return Boolean.valueOf((String)attributeValue); - throw new RuntimeException("cannot map type for token claim"); - } else if (type.equals("String")) { - if (attributeValue instanceof String) return attributeValue; - return attributeValue.toString(); - } else if (type.equals("long")) { - if (attributeValue instanceof Long) return attributeValue; - if (attributeValue instanceof String) return Long.valueOf((String)attributeValue); - throw new RuntimeException("cannot map type for token claim"); - } else if (type.equals("int")) { - if (attributeValue instanceof Integer) return attributeValue; - if (attributeValue instanceof String) return Integer.valueOf((String)attributeValue); - throw new RuntimeException("cannot map type for token claim"); + switch (type) { + case "boolean": + Boolean booleanObject = getBoolean(attributeValue); + if (booleanObject != null) return booleanObject; + if (attributeValue instanceof List) { + return transform((List) attributeValue, OIDCAttributeMapperHelper::getBoolean); + } + throw new RuntimeException("cannot map type for token claim"); + case "String": + if (attributeValue instanceof String) return attributeValue; + if (attributeValue instanceof List) { + return transform((List) attributeValue, OIDCAttributeMapperHelper::getString); + } + return attributeValue.toString(); + case "long": + Long longObject = getLong(attributeValue); + if (longObject != null) return longObject; + if (attributeValue instanceof List) { + return transform((List) attributeValue, OIDCAttributeMapperHelper::getLong); + } + throw new RuntimeException("cannot map type for token claim"); + case "int": + Integer intObject = getInteger(attributeValue); + if (intObject != null) return intObject; + if (attributeValue instanceof List) { + return transform((List) attributeValue, OIDCAttributeMapperHelper::getInteger); + } + throw new RuntimeException("cannot map type for token claim"); + default: + return null; } - return attributeValue; + } + + private static String getString(Object attributeValue) { + return attributeValue.toString(); + } + + + private static Long getLong(Object attributeValue) { + if (attributeValue instanceof Long) return (Long) attributeValue; + if (attributeValue instanceof String) return Long.valueOf((String) attributeValue); + return null; + } + + private static Integer getInteger(Object attributeValue) { + if (attributeValue instanceof Integer) return (Integer) attributeValue; + if (attributeValue instanceof String) return Integer.valueOf((String) attributeValue); + return null; + } + + private static Boolean getBoolean(Object attributeValue) { + if (attributeValue instanceof Boolean) return (Boolean) attributeValue; + if (attributeValue instanceof String) return Boolean.valueOf((String) attributeValue); + return null; } public static void mapClaim(IDToken token, ProtocolMapperModel mappingModel, Object attributeValue) { diff --git a/services/src/main/java/org/keycloak/protocol/saml/mappers/AttributeStatementHelper.java b/services/src/main/java/org/keycloak/protocol/saml/mappers/AttributeStatementHelper.java index c1cf9c4b733d..423cab9b944d 100755 --- a/services/src/main/java/org/keycloak/protocol/saml/mappers/AttributeStatementHelper.java +++ b/services/src/main/java/org/keycloak/protocol/saml/mappers/AttributeStatementHelper.java @@ -52,6 +52,15 @@ public static void addAttribute(AttributeStatementType attributeStatement, Proto attributeStatement.addAttribute(new AttributeStatementType.ASTChoiceType(attribute)); } + public static void addAttributes(AttributeStatementType attributeStatement, ProtocolMapperModel mappingModel, + List attributeValues) { + + AttributeType attribute = createAttributeType(mappingModel); + attributeValues.forEach(attribute::addAttributeValue); + + attributeStatement.addAttribute(new AttributeStatementType.ASTChoiceType(attribute)); + } + public static AttributeType createAttributeType(ProtocolMapperModel mappingModel) { String attributeName = mappingModel.getConfig().get(SAML_ATTRIBUTE_NAME); AttributeType attribute = new AttributeType(attributeName); diff --git a/services/src/main/java/org/keycloak/protocol/saml/mappers/UserAttributeStatementMapper.java b/services/src/main/java/org/keycloak/protocol/saml/mappers/UserAttributeStatementMapper.java index 2340191c5154..f29d97223487 100755 --- a/services/src/main/java/org/keycloak/protocol/saml/mappers/UserAttributeStatementMapper.java +++ b/services/src/main/java/org/keycloak/protocol/saml/mappers/UserAttributeStatementMapper.java @@ -80,10 +80,9 @@ public String getHelpText() { public void transformAttributeStatement(AttributeStatementType attributeStatement, ProtocolMapperModel mappingModel, KeycloakSession session, UserSessionModel userSession, ClientSessionModel clientSession) { UserModel user = userSession.getUser(); String attributeName = mappingModel.getConfig().get(ProtocolMapperUtils.USER_ATTRIBUTE); - String attributeValue = KeycloakModelUtils.resolveFirstAttribute(user, attributeName); - if (attributeValue == null) return; - AttributeStatementHelper.addAttribute(attributeStatement, mappingModel, attributeValue); - + List attributeValues = KeycloakModelUtils.resolveAttribute(user, attributeName); + if (attributeValues.isEmpty()) return; + AttributeStatementHelper.addAttributes(attributeStatement, mappingModel, attributeValues); } public static ProtocolMapperModel createAttributeMapper(String name, String userAttribute, diff --git a/services/src/main/java/org/keycloak/services/managers/ClientManager.java b/services/src/main/java/org/keycloak/services/managers/ClientManager.java index 1aa9b7f0f30c..fec49c92c564 100644 --- a/services/src/main/java/org/keycloak/services/managers/ClientManager.java +++ b/services/src/main/java/org/keycloak/services/managers/ClientManager.java @@ -195,6 +195,17 @@ public void enableServiceAccount(ClientModel client) { } } + public void clientIdChanged(ClientModel client, String newClientId) { + logger.debugf("Updating clientId from '%s' to '%s'", client.getClientId(), newClientId); + + UserModel serviceAccountUser = realmManager.getSession().users().getServiceAccount(client); + if (serviceAccountUser != null) { + String username = ServiceAccountConstants.SERVICE_ACCOUNT_USER_PREFIX + newClientId; + serviceAccountUser.setUsername(username); + serviceAccountUser.setEmail(username + "@placeholder.org"); + } + } + @JsonPropertyOrder({"realm", "realm-public-key", "bearer-only", "auth-server-url", "ssl-required", "resource", "public-client", "credentials", "use-resource-role-mappings"}) diff --git a/services/src/main/java/org/keycloak/services/managers/UserSessionManager.java b/services/src/main/java/org/keycloak/services/managers/UserSessionManager.java index e3ee409e496c..4c8c2fe89e73 100644 --- a/services/src/main/java/org/keycloak/services/managers/UserSessionManager.java +++ b/services/src/main/java/org/keycloak/services/managers/UserSessionManager.java @@ -72,18 +72,8 @@ public void createOrUpdateOfflineSession(ClientSessionModel clientSession, UserS } // userSessionId is provided from offline token. It's used just to verify if it match the ID from clientSession representation - public ClientSessionModel findOfflineClientSession(RealmModel realm, String clientSessionId, String userSessionId) { - ClientSessionModel clientSession = kcSession.sessions().getOfflineClientSession(realm, clientSessionId); - if (clientSession == null) { - return null; - } - - if (!userSessionId.equals(clientSession.getUserSession().getId())) { - throw new ModelException("User session don't match. Offline client session " + clientSession.getId() + ", It's user session " + clientSession.getUserSession().getId() + - " Wanted user session: " + userSessionId); - } - - return clientSession; + public ClientSessionModel findOfflineClientSession(RealmModel realm, String clientSessionId) { + return kcSession.sessions().getOfflineClientSession(realm, clientSessionId); } public Set findClientsWithOfflineToken(RealmModel realm, UserModel user) { diff --git a/services/src/main/java/org/keycloak/services/resources/LoginActionsService.java b/services/src/main/java/org/keycloak/services/resources/LoginActionsService.java index 7e0e11274b01..2bdb1297da24 100755 --- a/services/src/main/java/org/keycloak/services/resources/LoginActionsService.java +++ b/services/src/main/java/org/keycloak/services/resources/LoginActionsService.java @@ -96,6 +96,7 @@ public class LoginActionsService { public static final String REQUIRED_ACTION = "required-action"; public static final String FIRST_BROKER_LOGIN_PATH = "first-broker-login"; public static final String POST_BROKER_LOGIN_PATH = "post-broker-login"; + public static final String LAST_PROCESSED_CODE = "last_processed_code"; private RealmModel realm; @@ -323,14 +324,22 @@ public boolean verifyRequiredAction(String code, String executedAction) { public Response authenticate(@QueryParam("code") String code, @QueryParam("execution") String execution) { event.event(EventType.LOGIN); - Checks checks = new Checks(); - if (!checks.verifyCode(code, ClientSessionModel.Action.AUTHENTICATE.name(), ClientSessionCode.ActionType.LOGIN)) { - return checks.response; + + ClientSessionModel clientSession = ClientSessionCode.getClientSession(code, session, realm); + if (clientSession != null && code.equals(clientSession.getNote(LAST_PROCESSED_CODE))) { + // Allow refresh of previous page + } else { + Checks checks = new Checks(); + if (!checks.verifyCode(code, ClientSessionModel.Action.AUTHENTICATE.name(), ClientSessionCode.ActionType.LOGIN)) { + return checks.response; + } + + ClientSessionCode clientSessionCode = checks.clientCode; + clientSession = clientSessionCode.getClientSession(); } - event.detail(Details.CODE_ID, code); - ClientSessionCode clientSessionCode = checks.clientCode; - ClientSessionModel clientSession = clientSessionCode.getClientSession(); + event.detail(Details.CODE_ID, code); + clientSession.setNote(LAST_PROCESSED_CODE, code); return processAuthentication(execution, clientSession, null); } @@ -373,12 +382,21 @@ protected Response processFlow(String execution, ClientSessionModel clientSessio public Response authenticateForm(@QueryParam("code") String code, @QueryParam("execution") String execution) { event.event(EventType.LOGIN); + + ClientSessionModel clientSession = ClientSessionCode.getClientSession(code, session, realm); + if (clientSession != null && code.equals(clientSession.getNote(LAST_PROCESSED_CODE))) { + // Post already processed (refresh) - ignore form post and return next form + request.getFormParameters().clear(); + return authenticate(code, null); + } + Checks checks = new Checks(); if (!checks.verifyCode(code, ClientSessionModel.Action.AUTHENTICATE.name(), ClientSessionCode.ActionType.LOGIN)) { return checks.response; } final ClientSessionCode clientCode = checks.clientCode; - final ClientSessionModel clientSession = clientCode.getClientSession(); + clientSession = clientCode.getClientSession(); + clientSession.setNote(LAST_PROCESSED_CODE, code); return processAuthentication(execution, clientSession, null); } diff --git a/services/src/main/java/org/keycloak/services/resources/admin/ClientResource.java b/services/src/main/java/org/keycloak/services/resources/admin/ClientResource.java index 8928568ac61b..12750226462f 100755 --- a/services/src/main/java/org/keycloak/services/resources/admin/ClientResource.java +++ b/services/src/main/java/org/keycloak/services/resources/admin/ClientResource.java @@ -158,6 +158,10 @@ public void updateClientFromRep(ClientRepresentation rep, ClientModel client, Ke new ClientManager(new RealmManager(session)).enableServiceAccount(client); } + if (!rep.getClientId().equals(client.getClientId())) { + new ClientManager(new RealmManager(session)).clientIdChanged(client, rep.getClientId()); + } + RepresentationToModel.updateClient(rep, client); if (Profile.isPreviewEnabled()) { diff --git a/services/src/main/java/org/keycloak/services/resources/admin/info/ServerInfoAdminResource.java b/services/src/main/java/org/keycloak/services/resources/admin/info/ServerInfoAdminResource.java index 8017b04a082e..6c1779471ae2 100755 --- a/services/src/main/java/org/keycloak/services/resources/admin/info/ServerInfoAdminResource.java +++ b/services/src/main/java/org/keycloak/services/resources/admin/info/ServerInfoAdminResource.java @@ -56,8 +56,10 @@ import org.keycloak.theme.ThemeProvider; import javax.ws.rs.GET; +import javax.ws.rs.Produces; import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; import java.io.IOException; import java.util.Collections; import java.util.Comparator; @@ -83,6 +85,7 @@ public class ServerInfoAdminResource { * @return */ @GET + @Produces(MediaType.APPLICATION_JSON) public ServerInfoRepresentation getInfo() { ServerInfoRepresentation info = new ServerInfoRepresentation(); info.setSystemInfo(SystemInfoRepresentation.create(session.getKeycloakSessionFactory().getServerStartupTimestamp())); diff --git a/services/src/test/java/org/keycloak/test/broker/oidc/mappers/AbstractJsonUserAttributeMapperTest.java b/services/src/test/java/org/keycloak/test/broker/oidc/mappers/AbstractJsonUserAttributeMapperTest.java index 24c4cebcd61e..786a528c43e0 100755 --- a/services/src/test/java/org/keycloak/test/broker/oidc/mappers/AbstractJsonUserAttributeMapperTest.java +++ b/services/src/test/java/org/keycloak/test/broker/oidc/mappers/AbstractJsonUserAttributeMapperTest.java @@ -24,10 +24,11 @@ import org.keycloak.broker.oidc.mappers.AbstractJsonUserAttributeMapper; import java.io.IOException; +import java.util.Arrays; /** * Unit test for {@link org.keycloak.broker.oidc.mappers.AbstractJsonUserAttributeMapper} - * + * * @author Vlastimil Elias (velias at redhat dot com) */ public class AbstractJsonUserAttributeMapperTest { @@ -58,7 +59,7 @@ public void getJsonValue_simpleValues() throws JsonProcessingException, IOExcept //unknown field returns null Assert.assertEquals(null, AbstractJsonUserAttributeMapper.getJsonValue(getJsonNode(), "value_unknown")); - + // we check value is trimmed also! Assert.assertEquals("v1", AbstractJsonUserAttributeMapper.getJsonValue(getJsonNode(), "value1")); Assert.assertEquals(null, AbstractJsonUserAttributeMapper.getJsonValue(getJsonNode(), "value_empty")); @@ -95,14 +96,14 @@ public void getJsonValue_nestedSimpleValues() throws JsonProcessingException, IO public void getJsonValue_simpleArray() throws JsonProcessingException, IOException { // array field itself returns null if no index is provided - Assert.assertEquals(null, AbstractJsonUserAttributeMapper.getJsonValue(getJsonNode(), "value_array")); + Assert.assertEquals(Arrays.asList("a1", "a2"), AbstractJsonUserAttributeMapper.getJsonValue(getJsonNode(), "value_array")); // outside index returns null Assert.assertEquals(null, AbstractJsonUserAttributeMapper.getJsonValue(getJsonNode(), "value_array[2]")); //corect index Assert.assertEquals("a1", AbstractJsonUserAttributeMapper.getJsonValue(getJsonNode(), "value_array[0]")); Assert.assertEquals("a2", AbstractJsonUserAttributeMapper.getJsonValue(getJsonNode(), "value_array[1]")); - + //incorrect array constructs Assert.assertNull(AbstractJsonUserAttributeMapper.getJsonValue(getJsonNode(), "value_array[]")); Assert.assertNull(AbstractJsonUserAttributeMapper.getJsonValue(getJsonNode(), "value_array]")); @@ -125,7 +126,7 @@ public void getJsonValue_nestedArrayWithObjects() throws JsonProcessingException Assert.assertEquals(null, AbstractJsonUserAttributeMapper.getJsonValue(getJsonNode(), "nesta.a.av1")); Assert.assertEquals(null, AbstractJsonUserAttributeMapper.getJsonValue(getJsonNode(), "nesta.a].av1")); Assert.assertEquals(null, AbstractJsonUserAttributeMapper.getJsonValue(getJsonNode(), "nesta.a[.av1")); - + } } diff --git a/testsuite/integration-arquillian/pom.xml b/testsuite/integration-arquillian/pom.xml index ccd3e12d02b6..5f7fe929aff8 100644 --- a/testsuite/integration-arquillian/pom.xml +++ b/testsuite/integration-arquillian/pom.xml @@ -24,7 +24,7 @@ org.keycloak keycloak-testsuite-pom - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../pom.xml diff --git a/testsuite/integration-arquillian/servers/app-server/jboss/as7/pom.xml b/testsuite/integration-arquillian/servers/app-server/jboss/as7/pom.xml index 94af0b3ea490..39d567b5524e 100644 --- a/testsuite/integration-arquillian/servers/app-server/jboss/as7/pom.xml +++ b/testsuite/integration-arquillian/servers/app-server/jboss/as7/pom.xml @@ -21,7 +21,7 @@ org.keycloak.testsuite integration-arquillian-servers-app-server-jboss - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT 4.0.0 diff --git a/testsuite/integration-arquillian/servers/app-server/jboss/eap/pom.xml b/testsuite/integration-arquillian/servers/app-server/jboss/eap/pom.xml index 7eff562af927..61a085a4312e 100644 --- a/testsuite/integration-arquillian/servers/app-server/jboss/eap/pom.xml +++ b/testsuite/integration-arquillian/servers/app-server/jboss/eap/pom.xml @@ -21,7 +21,7 @@ org.keycloak.testsuite integration-arquillian-servers-app-server-jboss - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT 4.0.0 diff --git a/testsuite/integration-arquillian/servers/app-server/jboss/eap6-fuse/pom.xml b/testsuite/integration-arquillian/servers/app-server/jboss/eap6-fuse/pom.xml index e60fbc162759..60fc6a223f83 100644 --- a/testsuite/integration-arquillian/servers/app-server/jboss/eap6-fuse/pom.xml +++ b/testsuite/integration-arquillian/servers/app-server/jboss/eap6-fuse/pom.xml @@ -5,7 +5,7 @@ integration-arquillian-servers-app-server-jboss org.keycloak.testsuite - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT 4.0.0 diff --git a/testsuite/integration-arquillian/servers/app-server/jboss/eap6/pom.xml b/testsuite/integration-arquillian/servers/app-server/jboss/eap6/pom.xml index 853845c47122..2a47b31d24d6 100644 --- a/testsuite/integration-arquillian/servers/app-server/jboss/eap6/pom.xml +++ b/testsuite/integration-arquillian/servers/app-server/jboss/eap6/pom.xml @@ -21,7 +21,7 @@ org.keycloak.testsuite integration-arquillian-servers-app-server-jboss - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT 4.0.0 diff --git a/testsuite/integration-arquillian/servers/app-server/jboss/pom.xml b/testsuite/integration-arquillian/servers/app-server/jboss/pom.xml index 49f01629660b..a2c6b4a39754 100644 --- a/testsuite/integration-arquillian/servers/app-server/jboss/pom.xml +++ b/testsuite/integration-arquillian/servers/app-server/jboss/pom.xml @@ -21,7 +21,7 @@ org.keycloak.testsuite integration-arquillian-servers-app-server - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT 4.0.0 diff --git a/testsuite/integration-arquillian/servers/app-server/jboss/relative/eap/pom.xml b/testsuite/integration-arquillian/servers/app-server/jboss/relative/eap/pom.xml index b0a62e0db693..360b73f41e7b 100644 --- a/testsuite/integration-arquillian/servers/app-server/jboss/relative/eap/pom.xml +++ b/testsuite/integration-arquillian/servers/app-server/jboss/relative/eap/pom.xml @@ -21,7 +21,7 @@ org.keycloak.testsuite integration-arquillian-servers-app-server-jboss-relative - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT 4.0.0 diff --git a/testsuite/integration-arquillian/servers/app-server/jboss/relative/pom.xml b/testsuite/integration-arquillian/servers/app-server/jboss/relative/pom.xml index 767b21b29dbb..131fb8d3ab5a 100644 --- a/testsuite/integration-arquillian/servers/app-server/jboss/relative/pom.xml +++ b/testsuite/integration-arquillian/servers/app-server/jboss/relative/pom.xml @@ -21,7 +21,7 @@ org.keycloak.testsuite integration-arquillian-servers-app-server-jboss - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT 4.0.0 diff --git a/testsuite/integration-arquillian/servers/app-server/jboss/relative/wildfly/pom.xml b/testsuite/integration-arquillian/servers/app-server/jboss/relative/wildfly/pom.xml index 2fe4ad2a24cd..04b75f954c0f 100644 --- a/testsuite/integration-arquillian/servers/app-server/jboss/relative/wildfly/pom.xml +++ b/testsuite/integration-arquillian/servers/app-server/jboss/relative/wildfly/pom.xml @@ -21,7 +21,7 @@ org.keycloak.testsuite integration-arquillian-servers-app-server-jboss-relative - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT 4.0.0 diff --git a/testsuite/integration-arquillian/servers/app-server/jboss/wildfly/pom.xml b/testsuite/integration-arquillian/servers/app-server/jboss/wildfly/pom.xml index 9f2b285fdc76..7c59b1025b1d 100644 --- a/testsuite/integration-arquillian/servers/app-server/jboss/wildfly/pom.xml +++ b/testsuite/integration-arquillian/servers/app-server/jboss/wildfly/pom.xml @@ -21,7 +21,7 @@ org.keycloak.testsuite integration-arquillian-servers-app-server-jboss - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT 4.0.0 diff --git a/testsuite/integration-arquillian/servers/app-server/jboss/wildfly8/pom.xml b/testsuite/integration-arquillian/servers/app-server/jboss/wildfly8/pom.xml index d59b46536449..5ea9125112fc 100644 --- a/testsuite/integration-arquillian/servers/app-server/jboss/wildfly8/pom.xml +++ b/testsuite/integration-arquillian/servers/app-server/jboss/wildfly8/pom.xml @@ -21,7 +21,7 @@ org.keycloak.testsuite integration-arquillian-servers-app-server-jboss - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT 4.0.0 diff --git a/testsuite/integration-arquillian/servers/app-server/jboss/wildfly9/pom.xml b/testsuite/integration-arquillian/servers/app-server/jboss/wildfly9/pom.xml index e6612faa1a01..d1b80e92d982 100644 --- a/testsuite/integration-arquillian/servers/app-server/jboss/wildfly9/pom.xml +++ b/testsuite/integration-arquillian/servers/app-server/jboss/wildfly9/pom.xml @@ -21,7 +21,7 @@ org.keycloak.testsuite integration-arquillian-servers-app-server-jboss - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT 4.0.0 diff --git a/testsuite/integration-arquillian/servers/app-server/karaf/fuse61/pom.xml b/testsuite/integration-arquillian/servers/app-server/karaf/fuse61/pom.xml index 52b44ec6aaf2..e6fb8dd09094 100644 --- a/testsuite/integration-arquillian/servers/app-server/karaf/fuse61/pom.xml +++ b/testsuite/integration-arquillian/servers/app-server/karaf/fuse61/pom.xml @@ -21,7 +21,7 @@ org.keycloak.testsuite integration-arquillian-servers-app-server-karaf - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT 4.0.0 diff --git a/testsuite/integration-arquillian/servers/app-server/karaf/fuse62/pom.xml b/testsuite/integration-arquillian/servers/app-server/karaf/fuse62/pom.xml index 6379104a9a02..126f03efb100 100644 --- a/testsuite/integration-arquillian/servers/app-server/karaf/fuse62/pom.xml +++ b/testsuite/integration-arquillian/servers/app-server/karaf/fuse62/pom.xml @@ -21,7 +21,7 @@ org.keycloak.testsuite integration-arquillian-servers-app-server-karaf - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT 4.0.0 diff --git a/testsuite/integration-arquillian/servers/app-server/karaf/fuse63/pom.xml b/testsuite/integration-arquillian/servers/app-server/karaf/fuse63/pom.xml index 22a48d17334f..ea1eadf8d11b 100644 --- a/testsuite/integration-arquillian/servers/app-server/karaf/fuse63/pom.xml +++ b/testsuite/integration-arquillian/servers/app-server/karaf/fuse63/pom.xml @@ -21,7 +21,7 @@ org.keycloak.testsuite integration-arquillian-servers-app-server-karaf - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT 4.0.0 diff --git a/testsuite/integration-arquillian/servers/app-server/karaf/karaf3/pom.xml b/testsuite/integration-arquillian/servers/app-server/karaf/karaf3/pom.xml index aed028f3782d..c5a56a94f9b5 100644 --- a/testsuite/integration-arquillian/servers/app-server/karaf/karaf3/pom.xml +++ b/testsuite/integration-arquillian/servers/app-server/karaf/karaf3/pom.xml @@ -21,7 +21,7 @@ org.keycloak.testsuite integration-arquillian-servers-app-server-karaf - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT 4.0.0 diff --git a/testsuite/integration-arquillian/servers/app-server/karaf/pom.xml b/testsuite/integration-arquillian/servers/app-server/karaf/pom.xml index b9eb252ed730..e57d3c78408d 100644 --- a/testsuite/integration-arquillian/servers/app-server/karaf/pom.xml +++ b/testsuite/integration-arquillian/servers/app-server/karaf/pom.xml @@ -21,7 +21,7 @@ org.keycloak.testsuite integration-arquillian-servers-app-server - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT 4.0.0 diff --git a/testsuite/integration-arquillian/servers/app-server/pom.xml b/testsuite/integration-arquillian/servers/app-server/pom.xml index 12b674bb777f..b2c217bc439e 100644 --- a/testsuite/integration-arquillian/servers/app-server/pom.xml +++ b/testsuite/integration-arquillian/servers/app-server/pom.xml @@ -21,7 +21,7 @@ org.keycloak.testsuite integration-arquillian-servers - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT 4.0.0 diff --git a/testsuite/integration-arquillian/servers/app-server/tomcat/pom.xml b/testsuite/integration-arquillian/servers/app-server/tomcat/pom.xml index 21d4477f9d0e..2e90fa67d2ff 100644 --- a/testsuite/integration-arquillian/servers/app-server/tomcat/pom.xml +++ b/testsuite/integration-arquillian/servers/app-server/tomcat/pom.xml @@ -21,7 +21,7 @@ org.keycloak.testsuite integration-arquillian-servers-app-server - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT 4.0.0 diff --git a/testsuite/integration-arquillian/servers/app-server/tomcat/tomcat7/pom.xml b/testsuite/integration-arquillian/servers/app-server/tomcat/tomcat7/pom.xml index 62cdea96c7b1..71982b6666b5 100644 --- a/testsuite/integration-arquillian/servers/app-server/tomcat/tomcat7/pom.xml +++ b/testsuite/integration-arquillian/servers/app-server/tomcat/tomcat7/pom.xml @@ -21,7 +21,7 @@ org.keycloak.testsuite integration-arquillian-servers-app-server-tomcat - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT 4.0.0 diff --git a/testsuite/integration-arquillian/servers/app-server/tomcat/tomcat8/pom.xml b/testsuite/integration-arquillian/servers/app-server/tomcat/tomcat8/pom.xml index 126041c9ae37..79b6090ccee1 100644 --- a/testsuite/integration-arquillian/servers/app-server/tomcat/tomcat8/pom.xml +++ b/testsuite/integration-arquillian/servers/app-server/tomcat/tomcat8/pom.xml @@ -21,7 +21,7 @@ org.keycloak.testsuite integration-arquillian-servers-app-server-tomcat - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT 4.0.0 diff --git a/testsuite/integration-arquillian/servers/app-server/tomcat/tomcat9/pom.xml b/testsuite/integration-arquillian/servers/app-server/tomcat/tomcat9/pom.xml index e461d629e0fa..47ff0c931579 100644 --- a/testsuite/integration-arquillian/servers/app-server/tomcat/tomcat9/pom.xml +++ b/testsuite/integration-arquillian/servers/app-server/tomcat/tomcat9/pom.xml @@ -21,7 +21,7 @@ org.keycloak.testsuite integration-arquillian-servers-app-server-tomcat - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT 4.0.0 diff --git a/testsuite/integration-arquillian/servers/auth-server/jboss/eap/pom.xml b/testsuite/integration-arquillian/servers/auth-server/jboss/eap/pom.xml index 2601da635885..b5bc27acabbb 100644 --- a/testsuite/integration-arquillian/servers/auth-server/jboss/eap/pom.xml +++ b/testsuite/integration-arquillian/servers/auth-server/jboss/eap/pom.xml @@ -21,7 +21,7 @@ org.keycloak.testsuite integration-arquillian-servers-auth-server-jboss - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT 4.0.0 diff --git a/testsuite/integration-arquillian/servers/auth-server/jboss/pom.xml b/testsuite/integration-arquillian/servers/auth-server/jboss/pom.xml index 926338956f4e..7e54e46d2192 100644 --- a/testsuite/integration-arquillian/servers/auth-server/jboss/pom.xml +++ b/testsuite/integration-arquillian/servers/auth-server/jboss/pom.xml @@ -21,7 +21,7 @@ org.keycloak.testsuite integration-arquillian-servers-auth-server - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT 4.0.0 diff --git a/testsuite/integration-arquillian/servers/auth-server/jboss/wildfly/pom.xml b/testsuite/integration-arquillian/servers/auth-server/jboss/wildfly/pom.xml index 3ecf670fdd2e..e2958f6f25ab 100644 --- a/testsuite/integration-arquillian/servers/auth-server/jboss/wildfly/pom.xml +++ b/testsuite/integration-arquillian/servers/auth-server/jboss/wildfly/pom.xml @@ -21,7 +21,7 @@ org.keycloak.testsuite integration-arquillian-servers-auth-server-jboss - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT 4.0.0 diff --git a/testsuite/integration-arquillian/servers/auth-server/pom.xml b/testsuite/integration-arquillian/servers/auth-server/pom.xml index 232d6a6d27d2..56e9a0f37ca5 100644 --- a/testsuite/integration-arquillian/servers/auth-server/pom.xml +++ b/testsuite/integration-arquillian/servers/auth-server/pom.xml @@ -21,7 +21,7 @@ org.keycloak.testsuite integration-arquillian-servers - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT 4.0.0 diff --git a/testsuite/integration-arquillian/servers/auth-server/services/pom.xml b/testsuite/integration-arquillian/servers/auth-server/services/pom.xml index 12fc60879db9..afc70810431b 100644 --- a/testsuite/integration-arquillian/servers/auth-server/services/pom.xml +++ b/testsuite/integration-arquillian/servers/auth-server/services/pom.xml @@ -21,7 +21,7 @@ org.keycloak.testsuite integration-arquillian-servers-auth-server - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT 4.0.0 diff --git a/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/pom.xml b/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/pom.xml index 97933583f3ea..e40a806b29dc 100644 --- a/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/pom.xml +++ b/testsuite/integration-arquillian/servers/auth-server/services/testsuite-providers/pom.xml @@ -24,7 +24,7 @@ org.keycloak.testsuite integration-arquillian-servers-auth-server-services - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT integration-arquillian-testsuite-providers diff --git a/testsuite/integration-arquillian/servers/auth-server/undertow/pom.xml b/testsuite/integration-arquillian/servers/auth-server/undertow/pom.xml index ff476ed3bc84..2793df4e4d72 100644 --- a/testsuite/integration-arquillian/servers/auth-server/undertow/pom.xml +++ b/testsuite/integration-arquillian/servers/auth-server/undertow/pom.xml @@ -21,7 +21,7 @@ org.keycloak.testsuite integration-arquillian-servers-auth-server - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT 4.0.0 diff --git a/testsuite/integration-arquillian/servers/auth-server/undertow/src/main/java/org/keycloak/testsuite/arquillian/undertow/KeycloakOnUndertow.java b/testsuite/integration-arquillian/servers/auth-server/undertow/src/main/java/org/keycloak/testsuite/arquillian/undertow/KeycloakOnUndertow.java index 9d299734b0f7..bdbd4d92cecc 100644 --- a/testsuite/integration-arquillian/servers/auth-server/undertow/src/main/java/org/keycloak/testsuite/arquillian/undertow/KeycloakOnUndertow.java +++ b/testsuite/integration-arquillian/servers/auth-server/undertow/src/main/java/org/keycloak/testsuite/arquillian/undertow/KeycloakOnUndertow.java @@ -50,8 +50,8 @@ import java.lang.reflect.Field; import java.util.Collection; -import java.util.HashMap; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; public class KeycloakOnUndertow implements DeployableContainer { @@ -61,7 +61,7 @@ public class KeycloakOnUndertow implements DeployableContainer deployedArchivesToContextPath = new HashMap<>(); + Map deployedArchivesToContextPath = new ConcurrentHashMap<>(); private DeploymentInfo createAuthServerDeploymentInfo() { ResteasyDeployment deployment = new ResteasyDeployment(); diff --git a/testsuite/integration-arquillian/servers/migration/pom.xml b/testsuite/integration-arquillian/servers/migration/pom.xml index 13fb3b486e11..6b76f9450492 100644 --- a/testsuite/integration-arquillian/servers/migration/pom.xml +++ b/testsuite/integration-arquillian/servers/migration/pom.xml @@ -21,7 +21,7 @@ org.keycloak.testsuite integration-arquillian-servers - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT 4.0.0 diff --git a/testsuite/integration-arquillian/servers/pom.xml b/testsuite/integration-arquillian/servers/pom.xml index 2bea37c1002c..7117c159f5cb 100644 --- a/testsuite/integration-arquillian/servers/pom.xml +++ b/testsuite/integration-arquillian/servers/pom.xml @@ -21,7 +21,7 @@ org.keycloak.testsuite integration-arquillian - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT 4.0.0 diff --git a/testsuite/integration-arquillian/servers/wildfly-balancer/pom.xml b/testsuite/integration-arquillian/servers/wildfly-balancer/pom.xml index f14cd0975183..f3270e081d1c 100644 --- a/testsuite/integration-arquillian/servers/wildfly-balancer/pom.xml +++ b/testsuite/integration-arquillian/servers/wildfly-balancer/pom.xml @@ -21,7 +21,7 @@ org.keycloak.testsuite integration-arquillian-servers - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT 4.0.0 diff --git a/testsuite/integration-arquillian/test-apps/app-profile-jee/pom.xml b/testsuite/integration-arquillian/test-apps/app-profile-jee/pom.xml index d9d031a0f831..e8ff1c40a942 100644 --- a/testsuite/integration-arquillian/test-apps/app-profile-jee/pom.xml +++ b/testsuite/integration-arquillian/test-apps/app-profile-jee/pom.xml @@ -5,7 +5,7 @@ org.keycloak.testsuite integration-arquillian-test-apps - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT keycloak-test-app-profile-jee diff --git a/testsuite/integration-arquillian/test-apps/hello-world-authz-service/pom.xml b/testsuite/integration-arquillian/test-apps/hello-world-authz-service/pom.xml index 1d41d2efed88..5d575d9dc4ad 100755 --- a/testsuite/integration-arquillian/test-apps/hello-world-authz-service/pom.xml +++ b/testsuite/integration-arquillian/test-apps/hello-world-authz-service/pom.xml @@ -24,7 +24,7 @@ org.keycloak.testsuite integration-arquillian-test-apps - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT hello-world-authz-service diff --git a/testsuite/integration-arquillian/test-apps/js-console/pom.xml b/testsuite/integration-arquillian/test-apps/js-console/pom.xml index 6ba97ca49cd9..73093aa39821 100755 --- a/testsuite/integration-arquillian/test-apps/js-console/pom.xml +++ b/testsuite/integration-arquillian/test-apps/js-console/pom.xml @@ -21,7 +21,7 @@ org.keycloak.testsuite integration-arquillian-test-apps - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT 4.0.0 diff --git a/testsuite/integration-arquillian/test-apps/js-database/pom.xml b/testsuite/integration-arquillian/test-apps/js-database/pom.xml index 513c057b59eb..3d746e472e12 100644 --- a/testsuite/integration-arquillian/test-apps/js-database/pom.xml +++ b/testsuite/integration-arquillian/test-apps/js-database/pom.xml @@ -5,7 +5,7 @@ integration-arquillian-test-apps org.keycloak.testsuite - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT 4.0.0 diff --git a/testsuite/integration-arquillian/test-apps/photoz/photoz-authz-policy/pom.xml b/testsuite/integration-arquillian/test-apps/photoz/photoz-authz-policy/pom.xml index 8439fc00e263..abdb7d699bfd 100755 --- a/testsuite/integration-arquillian/test-apps/photoz/photoz-authz-policy/pom.xml +++ b/testsuite/integration-arquillian/test-apps/photoz/photoz-authz-policy/pom.xml @@ -6,7 +6,7 @@ org.keycloak.testsuite integration-arquillian-test-apps-photoz-parent - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../pom.xml diff --git a/testsuite/integration-arquillian/test-apps/photoz/photoz-html5-client/pom.xml b/testsuite/integration-arquillian/test-apps/photoz/photoz-html5-client/pom.xml index 82fd69fb5fe0..e17a37b98f1d 100755 --- a/testsuite/integration-arquillian/test-apps/photoz/photoz-html5-client/pom.xml +++ b/testsuite/integration-arquillian/test-apps/photoz/photoz-html5-client/pom.xml @@ -5,7 +5,7 @@ org.keycloak.testsuite integration-arquillian-test-apps-photoz-parent - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../pom.xml diff --git a/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/pom.xml b/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/pom.xml index 1351553b5d2a..bd272b5d6c96 100755 --- a/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/pom.xml +++ b/testsuite/integration-arquillian/test-apps/photoz/photoz-restful-api/pom.xml @@ -6,7 +6,7 @@ org.keycloak.testsuite integration-arquillian-test-apps-photoz-parent - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../pom.xml diff --git a/testsuite/integration-arquillian/test-apps/photoz/pom.xml b/testsuite/integration-arquillian/test-apps/photoz/pom.xml index 71db385d3ef9..4a880b24e698 100755 --- a/testsuite/integration-arquillian/test-apps/photoz/pom.xml +++ b/testsuite/integration-arquillian/test-apps/photoz/pom.xml @@ -6,7 +6,7 @@ org.keycloak.testsuite integration-arquillian-test-apps - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT integration-arquillian-test-apps-photoz-parent diff --git a/testsuite/integration-arquillian/test-apps/pom.xml b/testsuite/integration-arquillian/test-apps/pom.xml index 4d743892654b..cacb0ac9a5c2 100644 --- a/testsuite/integration-arquillian/test-apps/pom.xml +++ b/testsuite/integration-arquillian/test-apps/pom.xml @@ -5,7 +5,7 @@ integration-arquillian org.keycloak.testsuite - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT 4.0.0 diff --git a/testsuite/integration-arquillian/test-apps/servlet-authz/pom.xml b/testsuite/integration-arquillian/test-apps/servlet-authz/pom.xml index 249d47e3bd8f..724df70fbf82 100755 --- a/testsuite/integration-arquillian/test-apps/servlet-authz/pom.xml +++ b/testsuite/integration-arquillian/test-apps/servlet-authz/pom.xml @@ -6,7 +6,7 @@ org.keycloak.testsuite integration-arquillian-test-apps - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT servlet-authz-app diff --git a/testsuite/integration-arquillian/test-apps/servlets/pom.xml b/testsuite/integration-arquillian/test-apps/servlets/pom.xml index cab0c285bf30..9159c739597a 100644 --- a/testsuite/integration-arquillian/test-apps/servlets/pom.xml +++ b/testsuite/integration-arquillian/test-apps/servlets/pom.xml @@ -5,7 +5,7 @@ integration-arquillian-test-apps org.keycloak.testsuite - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT 4.0.0 diff --git a/testsuite/integration-arquillian/test-apps/servlets/src/main/java/org/keycloak/testsuite/adapter/filter/AdapterActionsFilter.java b/testsuite/integration-arquillian/test-apps/servlets/src/main/java/org/keycloak/testsuite/adapter/filter/AdapterActionsFilter.java index 1bfbb3e0cea4..3b3cc4997fa5 100644 --- a/testsuite/integration-arquillian/test-apps/servlets/src/main/java/org/keycloak/testsuite/adapter/filter/AdapterActionsFilter.java +++ b/testsuite/integration-arquillian/test-apps/servlets/src/main/java/org/keycloak/testsuite/adapter/filter/AdapterActionsFilter.java @@ -23,12 +23,14 @@ import org.keycloak.adapters.KeycloakDeployment; import org.keycloak.adapters.rotation.JWKPublicKeyLocator; import org.keycloak.common.util.Time; +import org.keycloak.common.util.reflections.Reflections; import javax.servlet.*; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; +import java.lang.reflect.Field; /** * Filter to handle "special" requests to perform actions on adapter side (for example setting time offset ) @@ -38,7 +40,7 @@ public class AdapterActionsFilter implements Filter { public static final String TIME_OFFSET_PARAM = "timeOffset"; - public static final String RESET_PUBLIC_KEY_PARAM = "resetPublicKey"; + public static final String RESET_DEPLOYMENT_PARAM = "resetDeployment"; private static final Logger log = Logger.getLogger(AdapterActionsFilter.class); @@ -54,19 +56,28 @@ public void doFilter(ServletRequest request, ServletResponse response, FilterCha //Accept timeOffset as argument to enforce timeouts String timeOffsetParam = request.getParameter(TIME_OFFSET_PARAM); - String resetPublicKey = request.getParameter(RESET_PUBLIC_KEY_PARAM); + String resetDeploymentParam = request.getParameter(RESET_DEPLOYMENT_PARAM); if (timeOffsetParam != null && !timeOffsetParam.isEmpty()) { int timeOffset = Integer.parseInt(timeOffsetParam); log.infof("Time offset updated to %d for application %s", timeOffset, servletReq.getRequestURI()); Time.setOffset(timeOffset); writeResponse(servletResp, "Offset set successfully"); - } else if (resetPublicKey != null && !resetPublicKey.isEmpty()) { + } else if (resetDeploymentParam != null && !resetDeploymentParam.isEmpty()) { AdapterDeploymentContext deploymentContext = (AdapterDeploymentContext) request.getServletContext().getAttribute(AdapterDeploymentContext.class.getName()); - KeycloakDeployment deployment = deploymentContext.resolveDeployment(null); - deployment.setPublicKeyLocator(new JWKPublicKeyLocator()); - log.infof("Restarted publicKey locator for application %s", servletReq.getRequestURI()); - writeResponse(servletResp, "PublicKeyLocator restarted successfully"); + + Field field = Reflections.findDeclaredField(AdapterDeploymentContext.class, "deployment"); + Reflections.setAccessible(field); + KeycloakDeployment deployment = (KeycloakDeployment) Reflections.getFieldValue(field, deploymentContext); + + Time.setOffset(0); + deployment.setNotBefore(0); + if (deployment.getPublicKeyLocator() instanceof JWKPublicKeyLocator) { + deployment.setPublicKeyLocator(new JWKPublicKeyLocator()); + } + + log.infof("Restarted PublicKeyLocator, notBefore and timeOffset for application %s", servletReq.getRequestURI()); + writeResponse(servletResp, "Restarted PublicKeyLocator, notBefore and timeOffset successfully"); } else { // Continue request chain.doFilter(request, response); diff --git a/testsuite/integration-arquillian/test-apps/servlets/src/main/java/org/keycloak/testsuite/adapter/servlet/AbstractShowTokensServlet.java b/testsuite/integration-arquillian/test-apps/servlets/src/main/java/org/keycloak/testsuite/adapter/servlet/AbstractShowTokensServlet.java index 370717210ca8..6db5922cc1f4 100644 --- a/testsuite/integration-arquillian/test-apps/servlets/src/main/java/org/keycloak/testsuite/adapter/servlet/AbstractShowTokensServlet.java +++ b/testsuite/integration-arquillian/test-apps/servlets/src/main/java/org/keycloak/testsuite/adapter/servlet/AbstractShowTokensServlet.java @@ -49,6 +49,7 @@ protected String renderTokens(HttpServletRequest req) throws ServletException, return new StringBuilder("" + accessTokenPretty + "") .append("" + refreshTokenPretty + "") + .append("" + ctx.getTokenString() + "") .toString(); } diff --git a/testsuite/integration-arquillian/test-apps/test-apps-dist/pom.xml b/testsuite/integration-arquillian/test-apps/test-apps-dist/pom.xml index f4790c1f610d..0ce34513305e 100644 --- a/testsuite/integration-arquillian/test-apps/test-apps-dist/pom.xml +++ b/testsuite/integration-arquillian/test-apps/test-apps-dist/pom.xml @@ -5,7 +5,7 @@ integration-arquillian-test-apps org.keycloak.testsuite - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT 4.0.0 diff --git a/testsuite/integration-arquillian/test-utils/pom.xml b/testsuite/integration-arquillian/test-utils/pom.xml index 5fb36070f1c4..5e179e18e549 100644 --- a/testsuite/integration-arquillian/test-utils/pom.xml +++ b/testsuite/integration-arquillian/test-utils/pom.xml @@ -5,7 +5,7 @@ integration-arquillian org.keycloak.testsuite - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT 4.0.0 diff --git a/testsuite/integration-arquillian/tests/base/pom.xml b/testsuite/integration-arquillian/tests/base/pom.xml index a0eb15cba515..a945047e9ba1 100644 --- a/testsuite/integration-arquillian/tests/base/pom.xml +++ b/testsuite/integration-arquillian/tests/base/pom.xml @@ -21,7 +21,7 @@ org.keycloak.testsuite integration-arquillian-tests - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT 4.0.0 diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/adapter/page/AbstractShowTokensPage.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/adapter/page/AbstractShowTokensPage.java index ea7ef6fe4865..64d0de2eb79b 100644 --- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/adapter/page/AbstractShowTokensPage.java +++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/adapter/page/AbstractShowTokensPage.java @@ -38,6 +38,9 @@ public abstract class AbstractShowTokensPage extends AbstractPageWithInjectedUrl @FindBy(id = "refreshToken") private WebElement refreshToken; + @FindBy(id = "accessTokenString") + private WebElement accessTokenString; + public AccessToken getAccessToken() { try { @@ -51,13 +54,25 @@ public AccessToken getAccessToken() { return null; } + public RefreshToken getRefreshToken() { try { return JsonSerialization.readValue(refreshToken.getText(), RefreshToken.class); } catch (IOException e) { e.printStackTrace(); } catch (NoSuchElementException nsee) { - log.warn("No idToken element found on the page"); + log.warn("No refreshToken element found on the page"); + } + + return null; + } + + + public String getAccessTokenString() { + try { + return accessTokenString.getText(); + } catch (NoSuchElementException nsee) { + log.warn("No accessTokenString element found on the page"); } return null; diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/AbstractServletsAdapterTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/AbstractServletsAdapterTest.java index a40275f72762..cc018d22671c 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/AbstractServletsAdapterTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/AbstractServletsAdapterTest.java @@ -111,14 +111,17 @@ public void setDefaultPageUriParameters() { testRealmPage.setAuthRealm(DEMO); } - protected void setAdapterAndServerTimeOffset(int timeOffset, String servletUri) { + protected void setAdapterAndServerTimeOffset(int timeOffset, String... servletUris) { setTimeOffset(timeOffset); - String timeOffsetUri = UriBuilder.fromUri(servletUri) - .queryParam(AdapterActionsFilter.TIME_OFFSET_PARAM, timeOffset) - .build().toString(); - driver.navigate().to(timeOffsetUri); - WaitUtils.waitUntilElement(By.tagName("body")).is().visible(); + for (String servletUri : servletUris) { + String timeOffsetUri = UriBuilder.fromUri(servletUri) + .queryParam(AdapterActionsFilter.TIME_OFFSET_PARAM, timeOffset) + .build().toString(); + + driver.navigate().to(timeOffsetUri); + WaitUtils.waitUntilElement(By.tagName("body")).is().visible(); + } } } diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/servlet/AbstractDemoFilterServletAdapterTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/servlet/AbstractDemoFilterServletAdapterTest.java index 0ad81d501b9e..a9ce39a16de1 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/servlet/AbstractDemoFilterServletAdapterTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/servlet/AbstractDemoFilterServletAdapterTest.java @@ -27,10 +27,4 @@ public void testOIDCParamsForwarding() { } - @Test - @Override - @Ignore - public void testClientWithJwksUri() { - - } } diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/servlet/AbstractDemoServletsAdapterTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/servlet/AbstractDemoServletsAdapterTest.java index f57b858bdf3d..fde26a1514db 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/servlet/AbstractDemoServletsAdapterTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/servlet/AbstractDemoServletsAdapterTest.java @@ -27,17 +27,13 @@ import org.keycloak.OAuth2Constants; import org.keycloak.admin.client.resource.ClientResource; import org.keycloak.common.Version; -import org.keycloak.common.util.MultivaluedHashMap; import org.keycloak.common.util.Time; import org.keycloak.constants.AdapterConstants; -import org.keycloak.keys.KeyProvider; -import org.keycloak.protocol.oidc.OIDCAdvancedConfigWrapper; import org.keycloak.protocol.oidc.OIDCLoginProtocol; import org.keycloak.protocol.oidc.OIDCLoginProtocolService; import org.keycloak.representations.AccessToken; import org.keycloak.representations.VersionRepresentation; import org.keycloak.representations.idm.ClientRepresentation; -import org.keycloak.representations.idm.ComponentRepresentation; import org.keycloak.representations.idm.RealmRepresentation; import org.keycloak.representations.idm.UserRepresentation; import org.keycloak.testsuite.adapter.AbstractServletsAdapterTest; @@ -67,7 +63,6 @@ import javax.ws.rs.core.Form; import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.Response; -import javax.ws.rs.core.UriBuilder; import java.io.File; import java.io.IOException; import java.net.URI; @@ -86,7 +81,6 @@ import org.keycloak.testsuite.adapter.page.CustomerPortalNoConf; import static org.keycloak.testsuite.auth.page.AuthRealm.DEMO; import static org.keycloak.testsuite.util.URLAssert.assertCurrentUrlEquals; -import static org.keycloak.testsuite.util.URLAssert.assertCurrentUrlStartsWith; import static org.keycloak.testsuite.util.URLAssert.assertCurrentUrlStartsWithLoginUrlOf; import static org.keycloak.testsuite.util.WaitUtils.pause; import static org.keycloak.testsuite.util.WaitUtils.waitUntilElement; @@ -141,7 +135,7 @@ protected static WebArchive securePortal() { @Deployment(name = CustomerDb.DEPLOYMENT_NAME) protected static WebArchive customerDb() { - return servletDeployment(CustomerDb.DEPLOYMENT_NAME, CustomerDatabaseServlet.class); + return servletDeployment(CustomerDb.DEPLOYMENT_NAME, AdapterActionsFilter.class, CustomerDatabaseServlet.class); } @Deployment(name = CustomerDbErrorPage.DEPLOYMENT_NAME) @@ -217,97 +211,6 @@ public void testSavedPostRequest() throws InterruptedException { client.close(); } - @Test - public void testRealmKeyRotationWithNewKeyDownload() throws Exception { - // Login success first - tokenMinTTLPage.navigateTo(); - testRealmLoginPage.form().waitForUsernameInputPresent(); - assertCurrentUrlStartsWithLoginUrlOf(testRealmPage); - testRealmLoginPage.form().login("bburke@redhat.com", "password"); - assertCurrentUrlEquals(tokenMinTTLPage); - - AccessToken token = tokenMinTTLPage.getAccessToken(); - Assert.assertEquals("bburke@redhat.com", token.getPreferredUsername()); - - // Logout - String logoutUri = OIDCLoginProtocolService.logoutUrl(authServerPage.createUriBuilder()) - .queryParam(OAuth2Constants.REDIRECT_URI, tokenMinTTLPage.toString()) - .build("demo").toString(); - driver.navigate().to(logoutUri); - - // Generate new realm key - String realmId = adminClient.realm(DEMO).toRepresentation().getId(); - ComponentRepresentation keys = new ComponentRepresentation(); - keys.setName("generated"); - keys.setProviderType(KeyProvider.class.getName()); - keys.setProviderId("rsa-generated"); - keys.setParentId(realmId); - keys.setConfig(new MultivaluedHashMap<>()); - keys.getConfig().putSingle("priority", "100"); - Response response = adminClient.realm(DEMO).components().add(keys); - assertEquals(201, response.getStatus()); - response.close(); - - String adapterActionsUrl = tokenMinTTLPage.toString() + "/unsecured/foo"; - setAdapterAndServerTimeOffset(300, adapterActionsUrl); - - // Try to login. Should work now due to realm key change - tokenMinTTLPage.navigateTo(); - testRealmLoginPage.form().waitForUsernameInputPresent(); - assertCurrentUrlStartsWithLoginUrlOf(testRealmPage); - testRealmLoginPage.form().login("bburke@redhat.com", "password"); - assertCurrentUrlEquals(tokenMinTTLPage); - token = tokenMinTTLPage.getAccessToken(); - Assert.assertEquals("bburke@redhat.com", token.getPreferredUsername()); - driver.navigate().to(logoutUri); - - // Revert public keys change - String timeOffsetUri = UriBuilder.fromUri(adapterActionsUrl) - .queryParam(AdapterActionsFilter.RESET_PUBLIC_KEY_PARAM, "true") - .build().toString(); - driver.navigate().to(timeOffsetUri); - waitUntilElement(By.tagName("body")).is().visible(); - - setAdapterAndServerTimeOffset(0, adapterActionsUrl); - } - - @Test - public void testClientWithJwksUri() throws Exception { - // Set client to bad JWKS URI - ClientResource clientResource = ApiUtil.findClientResourceByClientId(testRealmResource(), "secure-portal"); - ClientRepresentation client = clientResource.toRepresentation(); - OIDCAdvancedConfigWrapper wrapper = OIDCAdvancedConfigWrapper.fromClientRepresentation(client); - wrapper.setUseJwksUrl(true); - wrapper.setJwksUrl(securePortal + "/bad-jwks-url"); - clientResource.update(client); - - // Login should fail at the code-to-token - securePortal.navigateTo(); - assertCurrentUrlStartsWithLoginUrlOf(testRealmPage); - testRealmLoginPage.form().login("bburke@redhat.com", "password"); - String pageSource = driver.getPageSource(); - assertCurrentUrlStartsWith(securePortal); - assertFalse(pageSource.contains("Bill Burke") && pageSource.contains("Stian Thorgersen")); - - // Set client to correct JWKS URI - client = clientResource.toRepresentation(); - wrapper = OIDCAdvancedConfigWrapper.fromClientRepresentation(client); - wrapper.setUseJwksUrl(true); - wrapper.setJwksUrl(securePortal + "/" + AdapterConstants.K_JWKS); - clientResource.update(client); - - // Login to secure-portal should be fine now. Client keys downloaded from JWKS URI - securePortal.navigateTo(); - assertCurrentUrlEquals(securePortal); - pageSource = driver.getPageSource(); - assertTrue(pageSource.contains("Bill Burke") && pageSource.contains("Stian Thorgersen")); - - // Logout - String logoutUri = OIDCLoginProtocolService.logoutUrl(authServerPage.createUriBuilder()) - .queryParam(OAuth2Constants.REDIRECT_URI, securePortal.toString()).build("demo").toString(); - driver.navigate().to(logoutUri); - } - @Test public void testLoginSSOAndLogout() { // test login to customer-portal which does a bearer request to customer-db diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/servlet/AbstractOIDCPublicKeyRotationAdapterTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/servlet/AbstractOIDCPublicKeyRotationAdapterTest.java new file mode 100644 index 000000000000..8c42b997aaa3 --- /dev/null +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/servlet/AbstractOIDCPublicKeyRotationAdapterTest.java @@ -0,0 +1,346 @@ +/* + * Copyright 2016 Red Hat, Inc. and/or its affiliates + * and other contributors as indicated by the @author tags. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.keycloak.testsuite.adapter.servlet; + +import java.io.IOException; +import java.io.InputStream; +import java.util.concurrent.TimeUnit; + +import javax.ws.rs.core.Response; +import javax.ws.rs.core.UriBuilder; + +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.apache.http.impl.client.DefaultHttpClient; +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.arquillian.graphene.page.Page; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.keycloak.OAuth2Constants; +import org.keycloak.admin.client.resource.ClientResource; +import org.keycloak.common.util.MultivaluedHashMap; +import org.keycloak.common.util.StreamUtil; +import org.keycloak.common.util.Time; +import org.keycloak.constants.AdapterConstants; +import org.keycloak.keys.KeyProvider; +import org.keycloak.protocol.oidc.OIDCAdvancedConfigWrapper; +import org.keycloak.protocol.oidc.OIDCLoginProtocolService; +import org.keycloak.representations.AccessToken; +import org.keycloak.representations.adapters.action.GlobalRequestResult; +import org.keycloak.representations.idm.ClientRepresentation; +import org.keycloak.representations.idm.ComponentRepresentation; +import org.keycloak.representations.idm.RealmRepresentation; +import org.keycloak.testsuite.adapter.AbstractServletsAdapterTest; +import org.keycloak.testsuite.adapter.filter.AdapterActionsFilter; +import org.keycloak.testsuite.adapter.page.CustomerDb; +import org.keycloak.testsuite.adapter.page.SecurePortal; +import org.keycloak.testsuite.adapter.page.TokenMinTTLPage; +import org.keycloak.testsuite.admin.ApiUtil; +import org.keycloak.testsuite.util.URLAssert; +import org.openqa.selenium.By; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.keycloak.testsuite.auth.page.AuthRealm.DEMO; +import static org.keycloak.testsuite.util.URLAssert.assertCurrentUrlEquals; +import static org.keycloak.testsuite.util.URLAssert.assertCurrentUrlStartsWith; +import static org.keycloak.testsuite.util.URLAssert.assertCurrentUrlStartsWithLoginUrlOf; +import static org.keycloak.testsuite.util.WaitUtils.waitUntilElement; + +/** + * Tests related to public key rotation for OIDC adapter + * + * @author Marek Posolda + */ +public class AbstractOIDCPublicKeyRotationAdapterTest extends AbstractServletsAdapterTest { + + @Page + private SecurePortal securePortal; + + @Page + private TokenMinTTLPage tokenMinTTLPage; + + @Page + private CustomerDb customerDb; + + @Deployment(name = SecurePortal.DEPLOYMENT_NAME) + protected static WebArchive securePortal() { + return servletDeployment(SecurePortal.DEPLOYMENT_NAME, CallAuthenticatedServlet.class); + } + + @Deployment(name = TokenMinTTLPage.DEPLOYMENT_NAME) + protected static WebArchive tokenMinTTLPage() { + return servletDeployment(TokenMinTTLPage.DEPLOYMENT_NAME, AdapterActionsFilter.class, AbstractShowTokensServlet.class, TokenMinTTLServlet.class, ErrorServlet.class); + } + + @Deployment(name = CustomerDb.DEPLOYMENT_NAME) + protected static WebArchive customerDb() { + return servletDeployment(CustomerDb.DEPLOYMENT_NAME, AdapterActionsFilter.class, CustomerDatabaseServlet.class); + } + + + + + @Before + public void beforeRotationAdapterTest() { + // Delete all cookies from token-min-ttl page to be sure we are logged out + tokenMinTTLPage.navigateTo(); + driver.manage().deleteAllCookies(); + } + + + @Test + public void testRealmKeyRotationWithNewKeyDownload() throws Exception { + // Login success first + loginToTokenMinTtlApp(); + + // Logout + String logoutUri = OIDCLoginProtocolService.logoutUrl(authServerPage.createUriBuilder()) + .queryParam(OAuth2Constants.REDIRECT_URI, tokenMinTTLPage.toString()) + .build("demo").toString(); + driver.navigate().to(logoutUri); + assertCurrentUrlStartsWithLoginUrlOf(testRealmPage); + + // Generate new realm key + generateNewRealmKey(); + + // Try to login again. It should fail now because not yet allowed to download new keys + tokenMinTTLPage.navigateTo(); + testRealmLoginPage.form().waitForUsernameInputPresent(); + assertCurrentUrlStartsWithLoginUrlOf(testRealmPage); + testRealmLoginPage.form().login("bburke@redhat.com", "password"); + URLAssert.assertCurrentUrlStartsWith(driver, tokenMinTTLPage.getInjectedUrl().toString()); + Assert.assertNull(tokenMinTTLPage.getAccessToken()); + + driver.navigate().to(logoutUri); + assertCurrentUrlStartsWithLoginUrlOf(testRealmPage); + + setAdapterAndServerTimeOffset(300, tokenMinTTLPage.toString() + "/unsecured/foo"); + + // Try to login. Should work now due to realm key change + loginToTokenMinTtlApp(); + driver.navigate().to(logoutUri); + + // Revert public keys change + resetKeycloakDeploymentForAdapter(tokenMinTTLPage.toString() + "/unsecured/foo"); + } + + + @Test + public void testClientWithJwksUri() throws Exception { + // Set client to bad JWKS URI + ClientResource clientResource = ApiUtil.findClientResourceByClientId(testRealmResource(), "secure-portal"); + ClientRepresentation client = clientResource.toRepresentation(); + OIDCAdvancedConfigWrapper wrapper = OIDCAdvancedConfigWrapper.fromClientRepresentation(client); + wrapper.setUseJwksUrl(true); + wrapper.setJwksUrl(securePortal + "/bad-jwks-url"); + clientResource.update(client); + + // Login should fail at the code-to-token + securePortal.navigateTo(); + assertCurrentUrlStartsWithLoginUrlOf(testRealmPage); + testRealmLoginPage.form().login("bburke@redhat.com", "password"); + String pageSource = driver.getPageSource(); + assertCurrentUrlStartsWith(securePortal); + assertFalse(pageSource.contains("Bill Burke") && pageSource.contains("Stian Thorgersen")); + + // Set client to correct JWKS URI + client = clientResource.toRepresentation(); + wrapper = OIDCAdvancedConfigWrapper.fromClientRepresentation(client); + wrapper.setUseJwksUrl(true); + wrapper.setJwksUrl(securePortal + "/" + AdapterConstants.K_JWKS); + clientResource.update(client); + + // Login to secure-portal should be fine now. Client keys downloaded from JWKS URI + securePortal.navigateTo(); + assertCurrentUrlEquals(securePortal); + pageSource = driver.getPageSource(); + assertTrue(pageSource.contains("Bill Burke") && pageSource.contains("Stian Thorgersen")); + + // Logout + String logoutUri = OIDCLoginProtocolService.logoutUrl(authServerPage.createUriBuilder()) + .queryParam(OAuth2Constants.REDIRECT_URI, securePortal.toString()).build("demo").toString(); + driver.navigate().to(logoutUri); + } + + + // KEYCLOAK-3824: Test for public-key-cache-ttl + @Test + public void testPublicKeyCacheTtl() { + // increase accessTokenLifespan to 1200 + RealmRepresentation demoRealm = adminClient.realm(DEMO).toRepresentation(); + demoRealm.setAccessTokenLifespan(1200); + adminClient.realm(DEMO).update(demoRealm); + + // authenticate in tokenMinTTL app + loginToTokenMinTtlApp(); + String accessTokenString = tokenMinTTLPage.getAccessTokenString(); + + // Send REST request to customer-db app. I should be successfully authenticated + int status = invokeRESTEndpoint(accessTokenString); + Assert.assertEquals(200, status); + + // Re-generate realm public key and remove the old key + String oldKeyId = getActiveKeyId(); + generateNewRealmKey(); + adminClient.realm(DEMO).components().component(oldKeyId).remove(); + + // Send REST request to the customer-db app. Should be still succcessfully authenticated as the JWKPublicKeyLocator cache is still valid + status = invokeRESTEndpoint(accessTokenString); + Assert.assertEquals(200, status); + + // TimeOffset to 900 on the REST app side. Token is still valid (1200) but JWKPublicKeyLocator should try to download new key (public-key-cache-ttl=600) + setAdapterAndServerTimeOffset(900, customerDb.toString() + "/unsecured/foo"); + + // Send REST request. New request to the publicKey cache should be sent, and key is no longer returned as token contains the old kid + status = invokeRESTEndpoint(accessTokenString); + Assert.assertEquals(401, status); + + // Revert public keys change and time offset + resetKeycloakDeploymentForAdapter(customerDb.toString() + "/unsecured/foo"); + resetKeycloakDeploymentForAdapter(tokenMinTTLPage.toString() + "/unsecured/foo"); + } + + + // KEYCLOAK-3823: Test that sending notBefore policy invalidates JWKPublicKeyLocator cache + @Test + public void testPublicKeyCacheInvalidatedWhenPushedNotBefore() { + driver.manage().timeouts().pageLoadTimeout(1000, TimeUnit.SECONDS); + + // increase accessTokenLifespan to 1200 + RealmRepresentation demoRealm = adminClient.realm(DEMO).toRepresentation(); + demoRealm.setAccessTokenLifespan(1200); + adminClient.realm(DEMO).update(demoRealm); + + // authenticate in tokenMinTTL app + loginToTokenMinTtlApp(); + String accessTokenString = tokenMinTTLPage.getAccessTokenString(); + + // Generate new realm public key + String oldKeyId = getActiveKeyId(); + generateNewRealmKey(); + + // Send REST request to customer-db app. It should be successfully authenticated even that token is signed by the old key + int status = invokeRESTEndpoint(accessTokenString); + Assert.assertEquals(200, status); + + // Remove the old realm key now + adminClient.realm(DEMO).components().component(oldKeyId).remove(); + + // Set some offset to ensure pushing notBefore will pass + setAdapterAndServerTimeOffset(130, customerDb.toString() + "/unsecured/foo", tokenMinTTLPage.toString() + "/unsecured/foo"); + + // Send notBefore policy from the realm + demoRealm.setNotBefore(Time.currentTime() - 1); + adminClient.realm(DEMO).update(demoRealm); + GlobalRequestResult result = adminClient.realm(DEMO).pushRevocation(); + Assert.assertTrue(result.getSuccessRequests().contains(customerDb.toString())); + + // Send REST request. New request to the publicKey cache should be sent, and key is no longer returned as token contains the old kid + status = invokeRESTEndpoint(accessTokenString); + Assert.assertEquals(401, status); + + // Revert public keys change and time offset + resetKeycloakDeploymentForAdapter(customerDb.toString() + "/unsecured/foo"); + resetKeycloakDeploymentForAdapter(tokenMinTTLPage.toString() + "/unsecured/foo"); + } + + + // HELPER METHODS + + private void loginToTokenMinTtlApp() { + tokenMinTTLPage.navigateTo(); + testRealmLoginPage.form().waitForUsernameInputPresent(); + assertCurrentUrlStartsWithLoginUrlOf(testRealmPage); + testRealmLoginPage.form().login("bburke@redhat.com", "password"); + assertCurrentUrlEquals(tokenMinTTLPage); + + AccessToken token = tokenMinTTLPage.getAccessToken(); + Assert.assertEquals("bburke@redhat.com", token.getPreferredUsername()); + } + + + private void generateNewRealmKey() { + String realmId = adminClient.realm(DEMO).toRepresentation().getId(); + + ComponentRepresentation keys = new ComponentRepresentation(); + keys.setName("generated"); + keys.setProviderType(KeyProvider.class.getName()); + keys.setProviderId("rsa-generated"); + keys.setParentId(realmId); + keys.setConfig(new MultivaluedHashMap<>()); + keys.getConfig().putSingle("priority", "150"); + Response response = adminClient.realm(DEMO).components().add(keys); + assertEquals(201, response.getStatus()); + response.close(); + } + + private String getActiveKeyId() { + String realmId = adminClient.realm(DEMO).toRepresentation().getId(); + return adminClient.realm(DEMO).components().query(realmId, KeyProvider.class.getName()) + .get(0).getId(); + } + + + private int invokeRESTEndpoint(String accessTokenString) { + + HttpClient client = new DefaultHttpClient(); + try { + String restUrl = customerDb.toString(); + HttpGet get = new HttpGet(restUrl); + get.addHeader("Authorization", "Bearer " + accessTokenString); + try { + HttpResponse response = client.execute(get); + int status = response.getStatusLine().getStatusCode(); + if (status != 200) { + return status; + } + + HttpEntity entity = response.getEntity(); + InputStream is = entity.getContent(); + try { + String body = StreamUtil.readString(is); + Assert.assertTrue(body.contains("Stian Thorgersen") && body.contains("Bill Burke")); + return status; + } finally { + is.close(); + } + } catch (IOException e) { + throw new RuntimeException(e); + } + } finally { + client.getConnectionManager().shutdown(); + } + } + + + private void resetKeycloakDeploymentForAdapter(String adapterActionsUrl) { + String timeOffsetUri = UriBuilder.fromUri(adapterActionsUrl) + .queryParam(AdapterActionsFilter.RESET_DEPLOYMENT_PARAM, "true") + .build().toString(); + driver.navigate().to(timeOffsetUri); + waitUntilElement(By.tagName("body")).is().visible(); + } + + +} diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/undertow/servlet/UndertowOIDCPublicKeyRotationAdapterTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/undertow/servlet/UndertowOIDCPublicKeyRotationAdapterTest.java new file mode 100644 index 000000000000..0dfd99c996dc --- /dev/null +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/adapter/undertow/servlet/UndertowOIDCPublicKeyRotationAdapterTest.java @@ -0,0 +1,28 @@ +/* + * Copyright 2016 Red Hat, Inc. and/or its affiliates + * and other contributors as indicated by the @author tags. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.keycloak.testsuite.adapter.undertow.servlet; + +import org.keycloak.testsuite.adapter.servlet.AbstractOIDCPublicKeyRotationAdapterTest; +import org.keycloak.testsuite.arquillian.annotation.AppServerContainer; + +/** + * @author Marek Posolda + */ +@AppServerContainer("auth-server-undertow") +public class UndertowOIDCPublicKeyRotationAdapterTest extends AbstractOIDCPublicKeyRotationAdapterTest { +} diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/UserTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/UserTest.java index 545fbff0f10f..5b4777b9cc26 100755 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/UserTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/UserTest.java @@ -28,6 +28,7 @@ import org.keycloak.admin.client.resource.RealmResource; import org.keycloak.admin.client.resource.RoleMappingResource; import org.keycloak.admin.client.resource.UserResource; +import org.keycloak.admin.client.resource.UsersResource; import org.keycloak.events.admin.OperationType; import org.keycloak.events.admin.ResourceType; import org.keycloak.models.Constants; @@ -847,6 +848,19 @@ public void roleMappings() { assertNames(roles.clientLevel(clientUuid).listAll(), "client-composite"); } + @Test + public void defaultMaxResults() { + UsersResource users = adminClient.realms().realm("test").users(); + + for (int i = 0; i < 110; i++) { + users.create(UserBuilder.create().username("test-" + i).build()).close(); + } + + assertEquals(100, users.search("test", null, null).size()); + assertEquals(105, users.search("test", 0, 105).size()); + assertEquals(111, users.search("test", 0, 1000).size()); + } + private void switchEditUsernameAllowedOn() { RealmRepresentation rep = realm.toRepresentation(); rep.setEditUsernameAllowed(true); diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/event/AdminEventTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/event/AdminEventTest.java index 2d48ccc3c810..3d33fdc43613 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/event/AdminEventTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/event/AdminEventTest.java @@ -19,11 +19,17 @@ import org.junit.Before; import org.junit.Test; +import org.keycloak.admin.client.resource.RealmResource; +import org.keycloak.admin.client.resource.UsersResource; +import org.keycloak.events.EventType; +import org.keycloak.events.admin.OperationType; import org.keycloak.representations.idm.AdminEventRepresentation; import org.keycloak.representations.idm.AuthDetailsRepresentation; +import org.keycloak.representations.idm.EventRepresentation; import org.keycloak.representations.idm.RealmRepresentation; import org.keycloak.representations.idm.UserRepresentation; import org.keycloak.testsuite.admin.ApiUtil; +import org.keycloak.testsuite.util.UserBuilder; import java.util.Arrays; import java.util.Collections; @@ -127,4 +133,22 @@ public void testFilterAdminEvents() { List events = testRealmResource().getAdminEvents(Arrays.asList("CREATE"), realmName(), null, null, null, null, null, null, null, null); assertEquals(2, events.size()); } + + @Test + public void defaultMaxResults() { + RealmResource realm = adminClient.realms().realm("test"); + AdminEventRepresentation event = new AdminEventRepresentation(); + event.setOperationType(OperationType.CREATE.toString()); + event.setAuthDetails(new AuthDetailsRepresentation()); + event.setRealmId(realm.toRepresentation().getId()); + + for (int i = 0; i < 110; i++) { + testingClient.testing("test").onAdminEvent(event, false); + } + + assertEquals(100, realm.getAdminEvents(null, null, null, null, null, null, null, null, null, null).size()); + assertEquals(105, realm.getAdminEvents(null, null, null, null, null, null, null, null, 0, 105).size()); + assertTrue(realm.getAdminEvents(null, null, null, null, null, null, null, null, 0, 1000).size() >= 110); + } + } diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/event/LoginEventsTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/event/LoginEventsTest.java index a4fa8be87e8e..dc0d787cd416 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/event/LoginEventsTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/event/LoginEventsTest.java @@ -20,8 +20,13 @@ import org.jboss.arquillian.graphene.page.Page; import org.junit.Before; import org.junit.Test; +import org.keycloak.admin.client.resource.RealmResource; +import org.keycloak.admin.client.resource.UsersResource; +import org.keycloak.events.EventBuilder; +import org.keycloak.events.EventType; import org.keycloak.representations.idm.EventRepresentation; import org.keycloak.testsuite.console.page.events.LoginEvents; +import org.keycloak.testsuite.util.UserBuilder; import java.util.Arrays; import java.util.List; @@ -128,6 +133,22 @@ public void filterTest() { assertEquals(2, filteredEvents.size()); } + @Test + public void defaultMaxResults() { + RealmResource realm = adminClient.realms().realm("test"); + EventRepresentation event = new EventRepresentation(); + event.setRealmId(realm.toRepresentation().getId()); + event.setType(EventType.LOGIN.toString()); + + for (int i = 0; i < 110; i++) { + testingClient.testing("test").onEvent(event); + } + + assertEquals(100, realm.getEvents(null, null, null, null, null, null, null, null).size()); + assertEquals(105, realm.getEvents(null, null, null, null, null, null, 0, 105).size()); + assertTrue(realm.getEvents(null, null, null, null, null, null, 0, 1000).size() >= 110); + } + /* Removed this test because it takes too long. The default interval for event cleanup is 15 minutes (900 seconds). I don't have time to figure out diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/group/GroupMappersTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/group/GroupMappersTest.java index d61a517ce6c8..a1e6b0ad3655 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/group/GroupMappersTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/group/GroupMappersTest.java @@ -32,10 +32,10 @@ import org.keycloak.representations.idm.RealmRepresentation; import org.keycloak.representations.idm.UserRepresentation; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; +import java.util.*; + +import static org.hamcrest.CoreMatchers.hasItems; +import static org.hamcrest.MatcherAssert.assertThat; /** * @author Marko Strukelj @@ -119,7 +119,7 @@ public void testGroupMappers() throws Exception { Assert.assertNotNull(groups); Assert.assertTrue(groups.size() == 1); Assert.assertEquals("topGroup", groups.get(0)); - Assert.assertEquals("true", token.getOtherClaims().get("topAttribute")); + Assert.assertEquals(Collections.singletonList("true"), token.getOtherClaims().get("topAttribute")); } { UserRepresentation user = realm.users().search("level2GroupUser", -1, -1).get(0); @@ -132,8 +132,8 @@ public void testGroupMappers() throws Exception { Assert.assertNotNull(groups); Assert.assertTrue(groups.size() == 1); Assert.assertEquals("level2group", groups.get(0)); - Assert.assertEquals("true", token.getOtherClaims().get("topAttribute")); - Assert.assertEquals("true", token.getOtherClaims().get("level2Attribute")); + Assert.assertEquals(Collections.singletonList("true"), token.getOtherClaims().get("topAttribute")); + Assert.assertEquals(Collections.singletonList("true"), token.getOtherClaims().get("level2Attribute")); } } } diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/group/GroupTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/group/GroupTest.java index 1f0274e9cba0..d16626f86aec 100755 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/group/GroupTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/admin/group/GroupTest.java @@ -19,8 +19,11 @@ import org.junit.Assert; import org.junit.Test; +import org.keycloak.admin.client.resource.GroupResource; +import org.keycloak.admin.client.resource.GroupsResource; import org.keycloak.admin.client.resource.RealmResource; import org.keycloak.admin.client.resource.RoleMappingResource; +import org.keycloak.admin.client.resource.UsersResource; import org.keycloak.events.admin.OperationType; import org.keycloak.events.admin.ResourceType; import org.keycloak.models.Constants; @@ -578,4 +581,28 @@ public void adminEndpointAccessibleWhenAdminRoleAssignedToGroupAfterUserJoinedIt assertThat(userClient.realms().findAll(), // Any admin operation will do not(empty())); } + + @Test + public void defaultMaxResults() { + GroupsResource groups = adminClient.realms().realm("test").groups(); + Response response = groups.add(GroupBuilder.create().name("test").build()); + String groupId = ApiUtil.getCreatedId(response); + response.close(); + + GroupResource group = groups.group(groupId); + + UsersResource users = adminClient.realms().realm("test").users(); + + for (int i = 0; i < 110; i++) { + Response r = users.create(UserBuilder.create().username("test-" + i).build()); + String userId = ApiUtil.getCreatedId(r); + r.close(); + + users.get(userId).joinGroup(groupId); + } + + assertEquals(100, group.members(null, null).size()); + assertEquals(105, group.members(0, 105).size()); + assertEquals(110, group.members(0, 1000).size()); + } } diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/broker/AbstractUserAttributeMapperTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/broker/AbstractUserAttributeMapperTest.java index 2e5c4c6789ff..f5e9d2e73202 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/broker/AbstractUserAttributeMapperTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/broker/AbstractUserAttributeMapperTest.java @@ -238,7 +238,6 @@ public void testBasicMappingRemoveValue() { } @Test - @Ignore("Unignore to test KEYCLOAK-3648") public void testBasicMappingMultipleValues() { testValueMapping(ImmutableMap.>builder() .put(ATTRIBUTE_TO_MAP_NAME, ImmutableList.builder().add("value 1").add("value 2").build()) diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/LoginTotpTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/LoginTotpTest.java index 06ebacd8839e..15a8b6b9b4f3 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/LoginTotpTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/forms/LoginTotpTest.java @@ -127,6 +127,26 @@ public void loginWithTotpSuccess() throws Exception { events.expectLogin().assertEvent(); } + // KEYCLOAK-3835 + @Test + public void loginWithTotpRefreshTotpPage() throws Exception { + loginPage.open(); + loginPage.login("test-user@localhost", "password"); + + Assert.assertTrue(loginTotpPage.isCurrent()); + + // Refresh TOTP page + driver.navigate().refresh(); + + System.out.println(driver.getPageSource()); + + loginTotpPage.login(totp.generateTOTP("totpSecret")); + + Assert.assertEquals(RequestType.AUTH_RESPONSE, appPage.getRequestType()); + + events.expectLogin().assertEvent(); + } + @Test public void loginWithTotpCancel() throws Exception { loginPage.open(); diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oauth/OIDCProtocolMappersTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oauth/OIDCProtocolMappersTest.java index ac86d2023a0f..b89658885289 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oauth/OIDCProtocolMappersTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oauth/OIDCProtocolMappersTest.java @@ -29,7 +29,9 @@ import org.keycloak.admin.client.resource.ProtocolMappersResource; import org.keycloak.admin.client.resource.UserResource; import org.keycloak.protocol.oidc.OIDCLoginProtocol; +import org.keycloak.protocol.oidc.mappers.AddressMapper; import org.keycloak.representations.AccessToken; +import org.keycloak.representations.AddressClaimSet; import org.keycloak.representations.IDToken; import org.keycloak.representations.idm.ClientRepresentation; import org.keycloak.representations.idm.ProtocolMapperRepresentation; @@ -96,11 +98,13 @@ public void testTokenMapping() throws Exception { user.singleAttribute("street", "5 Yawkey Way"); user.singleAttribute("locality", "Boston"); - user.singleAttribute("region", "MA"); + user.singleAttribute("region_some", "MA"); // Custom name for userAttribute name, which will be mapped to region user.singleAttribute("postal_code", "02115"); user.singleAttribute("country", "USA"); + user.singleAttribute("formatted", "6 Foo Street"); user.singleAttribute("phone", "617-777-6666"); + List departments = Arrays.asList("finance", "development"); user.getAttributes().put("departments", departments); userResource.update(user); @@ -108,6 +112,9 @@ public void testTokenMapping() throws Exception { ClientResource app = findClientResourceByClientId(adminClient.realm("test"), "test-app"); ProtocolMapperRepresentation mapper = createAddressMapper(true, true); + mapper.getConfig().put(AddressMapper.getModelPropertyName(AddressClaimSet.REGION), "region_some"); + mapper.getConfig().put(AddressMapper.getModelPropertyName(AddressClaimSet.COUNTRY), "country_some"); + mapper.getConfig().remove(AddressMapper.getModelPropertyName(AddressClaimSet.POSTAL_CODE)); // Even if we remove protocolMapper config property, it should still default to postal_code app.getProtocolMappers().createMapper(mapper); ProtocolMapperRepresentation hard = createHardcodedClaim("hard", "hard", "coded", "String", false, null, true, true); @@ -131,14 +138,15 @@ public void testTokenMapping() throws Exception { assertEquals(idToken.getAddress().getLocality(), "Boston"); assertEquals(idToken.getAddress().getRegion(), "MA"); assertEquals(idToken.getAddress().getPostalCode(), "02115"); - assertEquals(idToken.getAddress().getCountry(), "USA"); + assertNull(idToken.getAddress().getCountry()); // Null because we changed userAttribute name to "country_some", but user contains "country" + assertEquals(idToken.getAddress().getFormattedAddress(), "6 Foo Street"); assertNotNull(idToken.getOtherClaims().get("home_phone")); - assertEquals("617-777-6666", idToken.getOtherClaims().get("home_phone")); + assertThat((List) idToken.getOtherClaims().get("home_phone"), hasItems("617-777-6666")); assertEquals("coded", idToken.getOtherClaims().get("hard")); Map nested = (Map) idToken.getOtherClaims().get("nested"); assertEquals("coded-nested", nested.get("hard")); nested = (Map) idToken.getOtherClaims().get("home"); - assertEquals("617-777-6666", nested.get("phone")); + assertThat((List) nested.get("phone"), hasItems("617-777-6666")); List departments = (List) idToken.getOtherClaims().get("department"); assertEquals(2, departments.size()); assertTrue(departments.contains("finance") && departments.contains("development")); @@ -150,14 +158,15 @@ public void testTokenMapping() throws Exception { assertEquals(accessToken.getAddress().getLocality(), "Boston"); assertEquals(accessToken.getAddress().getRegion(), "MA"); assertEquals(accessToken.getAddress().getPostalCode(), "02115"); - assertEquals(accessToken.getAddress().getCountry(), "USA"); + assertNull(idToken.getAddress().getCountry()); // Null because we changed userAttribute name to "country_some", but user contains "country" + assertEquals(idToken.getAddress().getFormattedAddress(), "6 Foo Street"); assertNotNull(accessToken.getOtherClaims().get("home_phone")); - assertEquals("617-777-6666", accessToken.getOtherClaims().get("home_phone")); + assertThat((List) accessToken.getOtherClaims().get("home_phone"), hasItems("617-777-6666")); assertEquals("coded", accessToken.getOtherClaims().get("hard")); nested = (Map) accessToken.getOtherClaims().get("nested"); assertEquals("coded-nested", nested.get("hard")); nested = (Map) accessToken.getOtherClaims().get("home"); - assertEquals("617-777-6666", nested.get("phone")); + assertThat((List) nested.get("phone"), hasItems("617-777-6666")); departments = (List) idToken.getOtherClaims().get("department"); assertEquals(2, departments.size()); assertTrue(departments.contains("finance") && departments.contains("development")); diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oauth/OfflineTokenTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oauth/OfflineTokenTest.java index 36cab0bd1a69..223a3f65ef9a 100755 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oauth/OfflineTokenTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oauth/OfflineTokenTest.java @@ -285,7 +285,7 @@ public void offlineTokenDirectGrantFlow() throws Exception { oauth.scope(OAuth2Constants.OFFLINE_ACCESS); oauth.clientId("offline-client"); OAuthClient.AccessTokenResponse tokenResponse = oauth.doGrantAccessTokenRequest("secret1", "test-user@localhost", "password"); - tokenResponse.getErrorDescription(); + Assert.assertNull(tokenResponse.getErrorDescription()); AccessToken token = oauth.verifyToken(tokenResponse.getAccessToken()); String offlineTokenString = tokenResponse.getRefreshToken(); RefreshToken offlineToken = oauth.verifyRefreshToken(offlineTokenString); diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oauth/ServiceAccountTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oauth/ServiceAccountTest.java index c3b05cbbc29c..cfd790727c0e 100755 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oauth/ServiceAccountTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/oauth/ServiceAccountTest.java @@ -232,14 +232,14 @@ public void changeClientIdTest() throws Exception { RefreshToken refreshToken = oauth.verifyRefreshToken(response.getRefreshToken()); Assert.assertEquals("updated-client", accessToken.getOtherClaims().get(ServiceAccountConstants.CLIENT_ID)); - // Username still same. Client ID changed + // Username updated after client ID changed events.expectClientLogin() .client("updated-client") .user(userId) .session(accessToken.getSessionState()) .detail(Details.TOKEN_ID, accessToken.getId()) .detail(Details.REFRESH_TOKEN_ID, refreshToken.getId()) - .detail(Details.USERNAME, ServiceAccountConstants.SERVICE_ACCOUNT_USER_PREFIX + "service-account-cl") + .detail(Details.USERNAME, ServiceAccountConstants.SERVICE_ACCOUNT_USER_PREFIX + "updated-client") .assertEvent(); diff --git a/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/customer-db/WEB-INF/keycloak.json b/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/customer-db/WEB-INF/keycloak.json index 362017077b48..400fac38715c 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/customer-db/WEB-INF/keycloak.json +++ b/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/customer-db/WEB-INF/keycloak.json @@ -1,10 +1,10 @@ { "realm" : "demo", "resource" : "customer-db", - "realm-public-key" : "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB", "auth-server-url": "http://localhost:8180/auth", "ssl-required" : "external", "bearer-only" : true, - "enable-cors" : true + "enable-cors" : true, + "public-key-cache-ttl": 600 } diff --git a/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/customer-db/WEB-INF/web.xml b/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/customer-db/WEB-INF/web.xml index cebfe6f5e565..56ed0e725adf 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/customer-db/WEB-INF/web.xml +++ b/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/customer-db/WEB-INF/web.xml @@ -23,11 +23,22 @@ customer-db + + + AdapterActionsFilter + org.keycloak.testsuite.adapter.filter.AdapterActionsFilter + + Servlet org.keycloak.testsuite.adapter.servlet.CustomerDatabaseServlet + + AdapterActionsFilter + /* + + Servlet /* @@ -42,6 +53,12 @@ user + + + Unsecured + /unsecured/* + + KEYCLOAK diff --git a/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/demorealm.json b/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/demorealm.json index d65fa9484731..b1f70e273808 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/demorealm.json +++ b/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/demorealm.json @@ -117,6 +117,13 @@ ], "clients": [ + { + "clientId": "customer-db", + "enabled": true, + "adminUrl": "/customer-db", + "baseUrl": "/customer-db", + "bearerOnly": true + }, { "clientId": "customer-portal", "enabled": true, diff --git a/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/secure-portal/WEB-INF/keycloak.json b/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/secure-portal/WEB-INF/keycloak.json index de290de301be..f3fa1a59f045 100644 --- a/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/secure-portal/WEB-INF/keycloak.json +++ b/testsuite/integration-arquillian/tests/base/src/test/resources/adapter-test/secure-portal/WEB-INF/keycloak.json @@ -1,6 +1,5 @@ { "realm": "demo", - "realm-public-key": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB", "auth-server-url": "http://localhost:8180/auth", "ssl-required": "external", "resource": "secure-portal", diff --git a/testsuite/integration-arquillian/tests/other/adapters/jboss/as7/pom.xml b/testsuite/integration-arquillian/tests/other/adapters/jboss/as7/pom.xml index 832de00bc16a..807e22fbaec3 100644 --- a/testsuite/integration-arquillian/tests/other/adapters/jboss/as7/pom.xml +++ b/testsuite/integration-arquillian/tests/other/adapters/jboss/as7/pom.xml @@ -24,7 +24,7 @@ org.keycloak.testsuite integration-arquillian-tests-adapters-jboss - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT integration-arquillian-tests-adapters-as7 diff --git a/testsuite/integration-arquillian/tests/other/adapters/jboss/as7/src/test/java/org/keycloak/testsuite/adapter/AS7OIDCPublicKeyRotationAdapterTest.java b/testsuite/integration-arquillian/tests/other/adapters/jboss/as7/src/test/java/org/keycloak/testsuite/adapter/AS7OIDCPublicKeyRotationAdapterTest.java new file mode 100644 index 000000000000..50cc0e904625 --- /dev/null +++ b/testsuite/integration-arquillian/tests/other/adapters/jboss/as7/src/test/java/org/keycloak/testsuite/adapter/AS7OIDCPublicKeyRotationAdapterTest.java @@ -0,0 +1,28 @@ +/* + * Copyright 2016 Red Hat, Inc. and/or its affiliates + * and other contributors as indicated by the @author tags. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.keycloak.testsuite.adapter; + +import org.keycloak.testsuite.adapter.servlet.AbstractOIDCPublicKeyRotationAdapterTest; +import org.keycloak.testsuite.arquillian.annotation.AppServerContainer; + +/** + * @author Marek Posolda + */ +@AppServerContainer("app-server-as7") +public class AS7OIDCPublicKeyRotationAdapterTest extends AbstractOIDCPublicKeyRotationAdapterTest { +} diff --git a/testsuite/integration-arquillian/tests/other/adapters/jboss/eap/pom.xml b/testsuite/integration-arquillian/tests/other/adapters/jboss/eap/pom.xml index 54e808438875..7f828eb67d5c 100644 --- a/testsuite/integration-arquillian/tests/other/adapters/jboss/eap/pom.xml +++ b/testsuite/integration-arquillian/tests/other/adapters/jboss/eap/pom.xml @@ -24,7 +24,7 @@ org.keycloak.testsuite integration-arquillian-tests-adapters-jboss - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT integration-arquillian-tests-adapters-eap diff --git a/testsuite/integration-arquillian/tests/other/adapters/jboss/eap/src/test/java/org/keycloak/testsuite/adapter/EAPOIDCPublicKeyRotationAdapterTest.java b/testsuite/integration-arquillian/tests/other/adapters/jboss/eap/src/test/java/org/keycloak/testsuite/adapter/EAPOIDCPublicKeyRotationAdapterTest.java new file mode 100644 index 000000000000..df936d8ccee2 --- /dev/null +++ b/testsuite/integration-arquillian/tests/other/adapters/jboss/eap/src/test/java/org/keycloak/testsuite/adapter/EAPOIDCPublicKeyRotationAdapterTest.java @@ -0,0 +1,28 @@ +/* + * Copyright 2016 Red Hat, Inc. and/or its affiliates + * and other contributors as indicated by the @author tags. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.keycloak.testsuite.adapter; + +import org.keycloak.testsuite.adapter.servlet.AbstractOIDCPublicKeyRotationAdapterTest; +import org.keycloak.testsuite.arquillian.annotation.AppServerContainer; + +/** + * @author Marek Posolda + */ +@AppServerContainer("app-server-eap") +public class EAPOIDCPublicKeyRotationAdapterTest extends AbstractOIDCPublicKeyRotationAdapterTest { +} diff --git a/testsuite/integration-arquillian/tests/other/adapters/jboss/eap6-fuse/pom.xml b/testsuite/integration-arquillian/tests/other/adapters/jboss/eap6-fuse/pom.xml index d59e6b0ce094..9e3588e4fc2c 100644 --- a/testsuite/integration-arquillian/tests/other/adapters/jboss/eap6-fuse/pom.xml +++ b/testsuite/integration-arquillian/tests/other/adapters/jboss/eap6-fuse/pom.xml @@ -24,7 +24,7 @@ org.keycloak.testsuite integration-arquillian-tests-adapters-jboss - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT integration-arquillian-tests-adapters-eap6-fuse diff --git a/testsuite/integration-arquillian/tests/other/adapters/jboss/eap6/pom.xml b/testsuite/integration-arquillian/tests/other/adapters/jboss/eap6/pom.xml index c8b9bd5a500a..0cc9426f338f 100644 --- a/testsuite/integration-arquillian/tests/other/adapters/jboss/eap6/pom.xml +++ b/testsuite/integration-arquillian/tests/other/adapters/jboss/eap6/pom.xml @@ -24,7 +24,7 @@ org.keycloak.testsuite integration-arquillian-tests-adapters-jboss - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT integration-arquillian-tests-adapters-eap6 diff --git a/testsuite/integration-arquillian/tests/other/adapters/jboss/eap6/src/test/java/org/keycloak/testsuite/adapter/EAP6OIDCPublicKeyRotationAdapterTest.java b/testsuite/integration-arquillian/tests/other/adapters/jboss/eap6/src/test/java/org/keycloak/testsuite/adapter/EAP6OIDCPublicKeyRotationAdapterTest.java new file mode 100644 index 000000000000..607ead848a46 --- /dev/null +++ b/testsuite/integration-arquillian/tests/other/adapters/jboss/eap6/src/test/java/org/keycloak/testsuite/adapter/EAP6OIDCPublicKeyRotationAdapterTest.java @@ -0,0 +1,28 @@ +/* + * Copyright 2016 Red Hat, Inc. and/or its affiliates + * and other contributors as indicated by the @author tags. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.keycloak.testsuite.adapter; + +import org.keycloak.testsuite.adapter.servlet.AbstractOIDCPublicKeyRotationAdapterTest; +import org.keycloak.testsuite.arquillian.annotation.AppServerContainer; + +/** + * @author Marek Posolda + */ +@AppServerContainer("app-server-eap6") +public class EAP6OIDCPublicKeyRotationAdapterTest extends AbstractOIDCPublicKeyRotationAdapterTest { +} diff --git a/testsuite/integration-arquillian/tests/other/adapters/jboss/pom.xml b/testsuite/integration-arquillian/tests/other/adapters/jboss/pom.xml index 17a362f4dc4e..1c6e70e9e3af 100644 --- a/testsuite/integration-arquillian/tests/other/adapters/jboss/pom.xml +++ b/testsuite/integration-arquillian/tests/other/adapters/jboss/pom.xml @@ -24,7 +24,7 @@ org.keycloak.testsuite integration-arquillian-tests-adapters - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT integration-arquillian-tests-adapters-jboss diff --git a/testsuite/integration-arquillian/tests/other/adapters/jboss/relative/eap/pom.xml b/testsuite/integration-arquillian/tests/other/adapters/jboss/relative/eap/pom.xml index 358118625f0e..038c40ebcf6e 100644 --- a/testsuite/integration-arquillian/tests/other/adapters/jboss/relative/eap/pom.xml +++ b/testsuite/integration-arquillian/tests/other/adapters/jboss/relative/eap/pom.xml @@ -24,7 +24,7 @@ org.keycloak.testsuite integration-arquillian-tests-adapters-jboss-relative - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT integration-arquillian-tests-adapters-relative-eap diff --git a/testsuite/integration-arquillian/tests/other/adapters/jboss/relative/pom.xml b/testsuite/integration-arquillian/tests/other/adapters/jboss/relative/pom.xml index 16b40b54e64f..9fd88589ad7d 100644 --- a/testsuite/integration-arquillian/tests/other/adapters/jboss/relative/pom.xml +++ b/testsuite/integration-arquillian/tests/other/adapters/jboss/relative/pom.xml @@ -24,7 +24,7 @@ org.keycloak.testsuite integration-arquillian-tests-adapters-jboss - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT pom diff --git a/testsuite/integration-arquillian/tests/other/adapters/jboss/relative/wildfly/pom.xml b/testsuite/integration-arquillian/tests/other/adapters/jboss/relative/wildfly/pom.xml index 8899d0aa98e0..34d2d6122820 100644 --- a/testsuite/integration-arquillian/tests/other/adapters/jboss/relative/wildfly/pom.xml +++ b/testsuite/integration-arquillian/tests/other/adapters/jboss/relative/wildfly/pom.xml @@ -24,7 +24,7 @@ org.keycloak.testsuite integration-arquillian-tests-adapters-jboss-relative - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT integration-arquillian-tests-adapters-relative-wildfly diff --git a/testsuite/integration-arquillian/tests/other/adapters/jboss/wildfly/pom.xml b/testsuite/integration-arquillian/tests/other/adapters/jboss/wildfly/pom.xml index fb4621702da0..6d6f0f97ceb7 100644 --- a/testsuite/integration-arquillian/tests/other/adapters/jboss/wildfly/pom.xml +++ b/testsuite/integration-arquillian/tests/other/adapters/jboss/wildfly/pom.xml @@ -24,7 +24,7 @@ org.keycloak.testsuite integration-arquillian-tests-adapters-jboss - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT integration-arquillian-tests-adapters-wildfly diff --git a/testsuite/integration-arquillian/tests/other/adapters/jboss/wildfly/src/test/java/org/keycloak/testsuite/adapter/WildflyOIDCPublicKeyRotationAdapterTest.java b/testsuite/integration-arquillian/tests/other/adapters/jboss/wildfly/src/test/java/org/keycloak/testsuite/adapter/WildflyOIDCPublicKeyRotationAdapterTest.java new file mode 100644 index 000000000000..d54889be0728 --- /dev/null +++ b/testsuite/integration-arquillian/tests/other/adapters/jboss/wildfly/src/test/java/org/keycloak/testsuite/adapter/WildflyOIDCPublicKeyRotationAdapterTest.java @@ -0,0 +1,28 @@ +/* + * Copyright 2016 Red Hat, Inc. and/or its affiliates + * and other contributors as indicated by the @author tags. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.keycloak.testsuite.adapter; + +import org.keycloak.testsuite.adapter.servlet.AbstractOIDCPublicKeyRotationAdapterTest; +import org.keycloak.testsuite.arquillian.annotation.AppServerContainer; + +/** + * @author Marek Posolda + */ +@AppServerContainer("app-server-wildfly") +public class WildflyOIDCPublicKeyRotationAdapterTest extends AbstractOIDCPublicKeyRotationAdapterTest { +} diff --git a/testsuite/integration-arquillian/tests/other/adapters/jboss/wildfly8/pom.xml b/testsuite/integration-arquillian/tests/other/adapters/jboss/wildfly8/pom.xml index f08f7b91b6d4..c0901a51e7b5 100644 --- a/testsuite/integration-arquillian/tests/other/adapters/jboss/wildfly8/pom.xml +++ b/testsuite/integration-arquillian/tests/other/adapters/jboss/wildfly8/pom.xml @@ -24,7 +24,7 @@ org.keycloak.testsuite integration-arquillian-tests-adapters-jboss - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT integration-arquillian-tests-adapters-wildfly8 diff --git a/testsuite/integration-arquillian/tests/other/adapters/jboss/wildfly8/src/test/java/org/keycloak/testsuite/adapter/Wildfly8OIDCPublicKeyRotationAdapterTest.java b/testsuite/integration-arquillian/tests/other/adapters/jboss/wildfly8/src/test/java/org/keycloak/testsuite/adapter/Wildfly8OIDCPublicKeyRotationAdapterTest.java new file mode 100644 index 000000000000..0cad5fcfda97 --- /dev/null +++ b/testsuite/integration-arquillian/tests/other/adapters/jboss/wildfly8/src/test/java/org/keycloak/testsuite/adapter/Wildfly8OIDCPublicKeyRotationAdapterTest.java @@ -0,0 +1,28 @@ +/* + * Copyright 2016 Red Hat, Inc. and/or its affiliates + * and other contributors as indicated by the @author tags. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.keycloak.testsuite.adapter; + +import org.keycloak.testsuite.adapter.servlet.AbstractOIDCPublicKeyRotationAdapterTest; +import org.keycloak.testsuite.arquillian.annotation.AppServerContainer; + +/** + * @author Marek Posolda + */ +@AppServerContainer("app-server-wildfly8") +public class Wildfly8OIDCPublicKeyRotationAdapterTest extends AbstractOIDCPublicKeyRotationAdapterTest { +} diff --git a/testsuite/integration-arquillian/tests/other/adapters/jboss/wildfly9/pom.xml b/testsuite/integration-arquillian/tests/other/adapters/jboss/wildfly9/pom.xml index 73aba180e1be..afd4c65b11e1 100644 --- a/testsuite/integration-arquillian/tests/other/adapters/jboss/wildfly9/pom.xml +++ b/testsuite/integration-arquillian/tests/other/adapters/jboss/wildfly9/pom.xml @@ -24,7 +24,7 @@ org.keycloak.testsuite integration-arquillian-tests-adapters-jboss - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT integration-arquillian-tests-adapters-wildfly9 diff --git a/testsuite/integration-arquillian/tests/other/adapters/jboss/wildfly9/src/test/java/org/keycloak/testsuite/adapter/Wildfly9OIDCPublicKeyRotationAdapterTest.java b/testsuite/integration-arquillian/tests/other/adapters/jboss/wildfly9/src/test/java/org/keycloak/testsuite/adapter/Wildfly9OIDCPublicKeyRotationAdapterTest.java new file mode 100644 index 000000000000..a1b8118ef59f --- /dev/null +++ b/testsuite/integration-arquillian/tests/other/adapters/jboss/wildfly9/src/test/java/org/keycloak/testsuite/adapter/Wildfly9OIDCPublicKeyRotationAdapterTest.java @@ -0,0 +1,28 @@ +/* + * Copyright 2016 Red Hat, Inc. and/or its affiliates + * and other contributors as indicated by the @author tags. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.keycloak.testsuite.adapter; + +import org.keycloak.testsuite.adapter.servlet.AbstractOIDCPublicKeyRotationAdapterTest; +import org.keycloak.testsuite.arquillian.annotation.AppServerContainer; + +/** + * @author Marek Posolda + */ +@AppServerContainer("app-server-wildfly9") +public class Wildfly9OIDCPublicKeyRotationAdapterTest extends AbstractOIDCPublicKeyRotationAdapterTest { +} diff --git a/testsuite/integration-arquillian/tests/other/adapters/karaf/fuse61/pom.xml b/testsuite/integration-arquillian/tests/other/adapters/karaf/fuse61/pom.xml index 56e177c37b3f..f6b75cacb8a8 100644 --- a/testsuite/integration-arquillian/tests/other/adapters/karaf/fuse61/pom.xml +++ b/testsuite/integration-arquillian/tests/other/adapters/karaf/fuse61/pom.xml @@ -24,7 +24,7 @@ org.keycloak.testsuite integration-arquillian-tests-adapters-karaf - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT integration-arquillian-tests-adapters-fuse61 diff --git a/testsuite/integration-arquillian/tests/other/adapters/karaf/fuse62/pom.xml b/testsuite/integration-arquillian/tests/other/adapters/karaf/fuse62/pom.xml index c5a7eb88da8f..d7a36368efae 100644 --- a/testsuite/integration-arquillian/tests/other/adapters/karaf/fuse62/pom.xml +++ b/testsuite/integration-arquillian/tests/other/adapters/karaf/fuse62/pom.xml @@ -24,7 +24,7 @@ org.keycloak.testsuite integration-arquillian-tests-adapters-karaf - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT integration-arquillian-tests-adapters-fuse62 diff --git a/testsuite/integration-arquillian/tests/other/adapters/karaf/fuse63/pom.xml b/testsuite/integration-arquillian/tests/other/adapters/karaf/fuse63/pom.xml index ec311a6f06d8..2265346c1612 100644 --- a/testsuite/integration-arquillian/tests/other/adapters/karaf/fuse63/pom.xml +++ b/testsuite/integration-arquillian/tests/other/adapters/karaf/fuse63/pom.xml @@ -24,7 +24,7 @@ org.keycloak.testsuite integration-arquillian-tests-adapters-karaf - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT integration-arquillian-tests-adapters-fuse63 diff --git a/testsuite/integration-arquillian/tests/other/adapters/karaf/karaf3/pom.xml b/testsuite/integration-arquillian/tests/other/adapters/karaf/karaf3/pom.xml index 91a4b545bbf9..0e6eb3949377 100644 --- a/testsuite/integration-arquillian/tests/other/adapters/karaf/karaf3/pom.xml +++ b/testsuite/integration-arquillian/tests/other/adapters/karaf/karaf3/pom.xml @@ -24,7 +24,7 @@ org.keycloak.testsuite integration-arquillian-tests-adapters-karaf - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT integration-arquillian-tests-adapters-karaf3 diff --git a/testsuite/integration-arquillian/tests/other/adapters/karaf/pom.xml b/testsuite/integration-arquillian/tests/other/adapters/karaf/pom.xml index 6393b232665f..02ba17621698 100644 --- a/testsuite/integration-arquillian/tests/other/adapters/karaf/pom.xml +++ b/testsuite/integration-arquillian/tests/other/adapters/karaf/pom.xml @@ -24,7 +24,7 @@ org.keycloak.testsuite integration-arquillian-tests-adapters - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT integration-arquillian-tests-adapters-karaf diff --git a/testsuite/integration-arquillian/tests/other/adapters/pom.xml b/testsuite/integration-arquillian/tests/other/adapters/pom.xml index 646a919fb80a..2f722f785ef9 100644 --- a/testsuite/integration-arquillian/tests/other/adapters/pom.xml +++ b/testsuite/integration-arquillian/tests/other/adapters/pom.xml @@ -24,7 +24,7 @@ org.keycloak.testsuite integration-arquillian-tests-other - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT integration-arquillian-tests-adapters diff --git a/testsuite/integration-arquillian/tests/other/adapters/tomcat/pom.xml b/testsuite/integration-arquillian/tests/other/adapters/tomcat/pom.xml index c0e89f13225c..64fe6bf6b5de 100644 --- a/testsuite/integration-arquillian/tests/other/adapters/tomcat/pom.xml +++ b/testsuite/integration-arquillian/tests/other/adapters/tomcat/pom.xml @@ -24,7 +24,7 @@ org.keycloak.testsuite integration-arquillian-tests-adapters - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT integration-arquillian-tests-adapters-tomcat diff --git a/testsuite/integration-arquillian/tests/other/adapters/tomcat/tomcat7/pom.xml b/testsuite/integration-arquillian/tests/other/adapters/tomcat/tomcat7/pom.xml index f56584371107..b67fb8f0da79 100644 --- a/testsuite/integration-arquillian/tests/other/adapters/tomcat/tomcat7/pom.xml +++ b/testsuite/integration-arquillian/tests/other/adapters/tomcat/tomcat7/pom.xml @@ -24,7 +24,7 @@ org.keycloak.testsuite integration-arquillian-tests-adapters-tomcat - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT integration-arquillian-tests-adapters-tomcat7 diff --git a/testsuite/integration-arquillian/tests/other/adapters/tomcat/tomcat8/pom.xml b/testsuite/integration-arquillian/tests/other/adapters/tomcat/tomcat8/pom.xml index 1f32e6d02653..67ce9fc8343f 100644 --- a/testsuite/integration-arquillian/tests/other/adapters/tomcat/tomcat8/pom.xml +++ b/testsuite/integration-arquillian/tests/other/adapters/tomcat/tomcat8/pom.xml @@ -24,7 +24,7 @@ org.keycloak.testsuite integration-arquillian-tests-adapters-tomcat - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT integration-arquillian-tests-adapters-tomcat8 diff --git a/testsuite/integration-arquillian/tests/other/adapters/tomcat/tomcat9/pom.xml b/testsuite/integration-arquillian/tests/other/adapters/tomcat/tomcat9/pom.xml index 90ceb8e07fe4..96876e6e4b65 100644 --- a/testsuite/integration-arquillian/tests/other/adapters/tomcat/tomcat9/pom.xml +++ b/testsuite/integration-arquillian/tests/other/adapters/tomcat/tomcat9/pom.xml @@ -24,7 +24,7 @@ org.keycloak.testsuite integration-arquillian-tests-adapters-tomcat - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT integration-arquillian-tests-adapters-tomcat9 diff --git a/testsuite/integration-arquillian/tests/other/clean-start/pom.xml b/testsuite/integration-arquillian/tests/other/clean-start/pom.xml index d164e6a22e7e..6c975c914d67 100644 --- a/testsuite/integration-arquillian/tests/other/clean-start/pom.xml +++ b/testsuite/integration-arquillian/tests/other/clean-start/pom.xml @@ -23,7 +23,7 @@ org.keycloak.testsuite integration-arquillian-tests-other - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT integration-arquillian-tests-smoke-clean-start diff --git a/testsuite/integration-arquillian/tests/other/console/pom.xml b/testsuite/integration-arquillian/tests/other/console/pom.xml index 77d18aac11c4..5390cf0cc75c 100644 --- a/testsuite/integration-arquillian/tests/other/console/pom.xml +++ b/testsuite/integration-arquillian/tests/other/console/pom.xml @@ -24,7 +24,7 @@ org.keycloak.testsuite integration-arquillian-tests-other - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT integration-arquillian-tests-console diff --git a/testsuite/integration-arquillian/tests/other/console_no_users/pom.xml b/testsuite/integration-arquillian/tests/other/console_no_users/pom.xml index cf29acdda9fe..a48b81d7c3f9 100644 --- a/testsuite/integration-arquillian/tests/other/console_no_users/pom.xml +++ b/testsuite/integration-arquillian/tests/other/console_no_users/pom.xml @@ -24,7 +24,7 @@ org.keycloak.testsuite integration-arquillian-tests-other - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT integration-arquillian-tests-console-no-users diff --git a/testsuite/integration-arquillian/tests/other/jpa-performance/pom.xml b/testsuite/integration-arquillian/tests/other/jpa-performance/pom.xml index 171cc643e73f..a72798bc0eca 100644 --- a/testsuite/integration-arquillian/tests/other/jpa-performance/pom.xml +++ b/testsuite/integration-arquillian/tests/other/jpa-performance/pom.xml @@ -24,7 +24,7 @@ org.keycloak.testsuite integration-arquillian-tests-other - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT integration-arquillian-tests-jpa-performance diff --git a/testsuite/integration-arquillian/tests/other/mod_auth_mellon/pom.xml b/testsuite/integration-arquillian/tests/other/mod_auth_mellon/pom.xml index b2bd6301cabf..77272e25b3d3 100644 --- a/testsuite/integration-arquillian/tests/other/mod_auth_mellon/pom.xml +++ b/testsuite/integration-arquillian/tests/other/mod_auth_mellon/pom.xml @@ -24,7 +24,7 @@ org.keycloak.testsuite integration-arquillian-tests-other - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT integration-arquillian-tests-other-mod_auth_mellon diff --git a/testsuite/integration-arquillian/tests/other/nodejs_adapter/pom.xml b/testsuite/integration-arquillian/tests/other/nodejs_adapter/pom.xml index 2e3d915bca0b..b7f068901656 100644 --- a/testsuite/integration-arquillian/tests/other/nodejs_adapter/pom.xml +++ b/testsuite/integration-arquillian/tests/other/nodejs_adapter/pom.xml @@ -24,7 +24,7 @@ org.keycloak.testsuite integration-arquillian-tests-other - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT integration-arquillian-tests-nodejs-adapter diff --git a/testsuite/integration-arquillian/tests/other/pom.xml b/testsuite/integration-arquillian/tests/other/pom.xml index ae956fa9bf51..4838f7e130bd 100644 --- a/testsuite/integration-arquillian/tests/other/pom.xml +++ b/testsuite/integration-arquillian/tests/other/pom.xml @@ -24,7 +24,7 @@ org.keycloak.testsuite integration-arquillian-tests - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT integration-arquillian-tests-other diff --git a/testsuite/integration-arquillian/tests/other/sssd/pom.xml b/testsuite/integration-arquillian/tests/other/sssd/pom.xml index 8269427025fa..5c0abdb02766 100644 --- a/testsuite/integration-arquillian/tests/other/sssd/pom.xml +++ b/testsuite/integration-arquillian/tests/other/sssd/pom.xml @@ -5,7 +5,7 @@ integration-arquillian-tests-other org.keycloak.testsuite - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT 4.0.0 diff --git a/testsuite/integration-arquillian/tests/pom.xml b/testsuite/integration-arquillian/tests/pom.xml index bb9e838f6d22..ce348e9cc0fb 100755 --- a/testsuite/integration-arquillian/tests/pom.xml +++ b/testsuite/integration-arquillian/tests/pom.xml @@ -24,7 +24,7 @@ org.keycloak.testsuite integration-arquillian - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT pom diff --git a/testsuite/integration/pom.xml b/testsuite/integration/pom.xml index 94283a90b892..131b7cc337dd 100755 --- a/testsuite/integration/pom.xml +++ b/testsuite/integration/pom.xml @@ -21,7 +21,7 @@ keycloak-testsuite-pom org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT 4.0.0 diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/UserSessionProviderOfflineTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/UserSessionProviderOfflineTest.java index b9f4f2aedafd..fb4b3af81bc7 100644 --- a/testsuite/integration/src/test/java/org/keycloak/testsuite/model/UserSessionProviderOfflineTest.java +++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/model/UserSessionProviderOfflineTest.java @@ -107,7 +107,7 @@ public void testOfflineSessionsCrud() { // Assert all previously saved offline sessions found for (Map.Entry entry : offlineSessions.entrySet()) { - Assert.assertTrue(sessionManager.findOfflineClientSession(realm, entry.getKey(), entry.getValue()) != null); + Assert.assertTrue(sessionManager.findOfflineClientSession(realm, entry.getKey()) != null); UserSessionModel offlineSession = session.sessions().getUserSession(realm, entry.getValue()); boolean found = false; @@ -187,7 +187,7 @@ public void testOnRealmRemoved() { resetSession(); - ClientSessionModel offlineClientSession = sessionManager.findOfflineClientSession(fooRealm, clientSession.getId(), userSession.getId()); + ClientSessionModel offlineClientSession = sessionManager.findOfflineClientSession(fooRealm, clientSession.getId()); Assert.assertEquals("foo-app", offlineClientSession.getClient().getClientId()); Assert.assertEquals("user3", offlineClientSession.getUserSession().getUser().getUsername()); Assert.assertEquals(offlineClientSession.getId(), offlineClientSession.getUserSession().getClientSessions().get(0).getId()); @@ -206,7 +206,7 @@ public void testOnRealmRemoved() { // Assert nothing loaded fooRealm = session.realms().getRealm("foo"); - Assert.assertNull(sessionManager.findOfflineClientSession(fooRealm, clientSession.getId(), userSession.getId())); + Assert.assertNull(sessionManager.findOfflineClientSession(fooRealm, clientSession.getId())); Assert.assertEquals(0, session.sessions().getOfflineSessionsCount(fooRealm, fooRealm.getClientByClientId("foo-app"))); // Cleanup @@ -338,7 +338,7 @@ public void testExpired() { // Assert all previously saved offline sessions found for (Map.Entry entry : offlineSessions.entrySet()) { - Assert.assertTrue(sessionManager.findOfflineClientSession(realm, entry.getKey(), entry.getValue()) != null); + Assert.assertTrue(sessionManager.findOfflineClientSession(realm, entry.getKey()) != null); } UserSessionModel session0 = session.sessions().getOfflineUserSession(realm, origSessions[0].getId()); @@ -379,9 +379,9 @@ public void testExpired() { for (Map.Entry entry : offlineSessions.entrySet()) { String userSessionId = entry.getValue(); if (userSessionId.equals(session1.getId())) { - Assert.assertFalse(sessionManager.findOfflineClientSession(realm, entry.getKey(), userSessionId) != null); + Assert.assertFalse(sessionManager.findOfflineClientSession(realm, entry.getKey()) != null); } else { - Assert.assertTrue(sessionManager.findOfflineClientSession(realm, entry.getKey(), userSessionId) != null); + Assert.assertTrue(sessionManager.findOfflineClientSession(realm, entry.getKey()) != null); } } Assert.assertEquals(1, persister.getUserSessionsCount(true)); @@ -394,7 +394,7 @@ public void testExpired() { resetSession(); for (Map.Entry entry : offlineSessions.entrySet()) { - Assert.assertTrue(sessionManager.findOfflineClientSession(realm, entry.getKey(), entry.getValue()) == null); + Assert.assertTrue(sessionManager.findOfflineClientSession(realm, entry.getKey()) == null); } Assert.assertEquals(0, persister.getUserSessionsCount(true)); diff --git a/testsuite/jetty/jetty81/pom.xml b/testsuite/jetty/jetty81/pom.xml index 9fcabbfd38c5..4fa3829392ec 100755 --- a/testsuite/jetty/jetty81/pom.xml +++ b/testsuite/jetty/jetty81/pom.xml @@ -21,7 +21,7 @@ keycloak-testsuite-pom org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../../pom.xml 4.0.0 diff --git a/testsuite/jetty/jetty91/pom.xml b/testsuite/jetty/jetty91/pom.xml index da1d2b8ca65a..b24c1e698a53 100755 --- a/testsuite/jetty/jetty91/pom.xml +++ b/testsuite/jetty/jetty91/pom.xml @@ -21,7 +21,7 @@ keycloak-testsuite-pom org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../../pom.xml 4.0.0 diff --git a/testsuite/jetty/jetty92/pom.xml b/testsuite/jetty/jetty92/pom.xml index d55eee77a251..a3df7a669834 100755 --- a/testsuite/jetty/jetty92/pom.xml +++ b/testsuite/jetty/jetty92/pom.xml @@ -21,7 +21,7 @@ keycloak-testsuite-pom org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../../pom.xml 4.0.0 diff --git a/testsuite/jetty/jetty93/pom.xml b/testsuite/jetty/jetty93/pom.xml index eb2ba4f9e7d9..b686d2e1a7bb 100644 --- a/testsuite/jetty/jetty93/pom.xml +++ b/testsuite/jetty/jetty93/pom.xml @@ -21,7 +21,7 @@ keycloak-testsuite-pom org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../../pom.xml 4.0.0 diff --git a/testsuite/jetty/pom.xml b/testsuite/jetty/pom.xml index 2c59a7d18c47..d51e88088019 100755 --- a/testsuite/jetty/pom.xml +++ b/testsuite/jetty/pom.xml @@ -20,7 +20,7 @@ keycloak-testsuite-pom org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../pom.xml Keycloak SAML Jetty Testsuite Integration diff --git a/testsuite/pom.xml b/testsuite/pom.xml index fb0c228619d7..eb7da68594e6 100755 --- a/testsuite/pom.xml +++ b/testsuite/pom.xml @@ -21,7 +21,7 @@ keycloak-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../pom.xml 4.0.0 diff --git a/testsuite/proxy/pom.xml b/testsuite/proxy/pom.xml index 7530893fb097..603cc2ebd7c5 100755 --- a/testsuite/proxy/pom.xml +++ b/testsuite/proxy/pom.xml @@ -21,7 +21,7 @@ keycloak-testsuite-pom org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../pom.xml 4.0.0 diff --git a/testsuite/tomcat6/pom.xml b/testsuite/tomcat6/pom.xml index 5e3b7a050554..b00837305dc0 100755 --- a/testsuite/tomcat6/pom.xml +++ b/testsuite/tomcat6/pom.xml @@ -21,7 +21,7 @@ keycloak-testsuite-pom org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../pom.xml 4.0.0 diff --git a/testsuite/tomcat7/pom.xml b/testsuite/tomcat7/pom.xml index eb0d3f0cad08..a5f9b350d069 100755 --- a/testsuite/tomcat7/pom.xml +++ b/testsuite/tomcat7/pom.xml @@ -21,7 +21,7 @@ keycloak-testsuite-pom org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../pom.xml 4.0.0 diff --git a/testsuite/tomcat8/pom.xml b/testsuite/tomcat8/pom.xml index d0c206bc13ee..21395da3c452 100755 --- a/testsuite/tomcat8/pom.xml +++ b/testsuite/tomcat8/pom.xml @@ -21,7 +21,7 @@ keycloak-testsuite-pom org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT ../pom.xml 4.0.0 diff --git a/themes/pom.xml b/themes/pom.xml index fa98402a7011..0e1ecd6f4bf0 100755 --- a/themes/pom.xml +++ b/themes/pom.xml @@ -4,7 +4,7 @@ keycloak-parent org.keycloak - 2.4.1.Final-SNAPSHOT + 2.5.0.Final-SNAPSHOT 4.0.0 diff --git a/themes/src/main/resources/theme/base/admin/messages/admin-messages_en.properties b/themes/src/main/resources/theme/base/admin/messages/admin-messages_en.properties index 29f1465944ee..8cf09f3b7ae5 100644 --- a/themes/src/main/resources/theme/base/admin/messages/admin-messages_en.properties +++ b/themes/src/main/resources/theme/base/admin/messages/admin-messages_en.properties @@ -170,8 +170,18 @@ sectorIdentifierUri.label=Sector Identifier URI sectorIdentifierUri.tooltip=Providers that use pairwise sub values and support Dynamic Client Registration SHOULD use the sector_identifier_uri parameter. It provides a way for a group of websites under common administrative control to have consistent pairwise sub values independent of the individual domain names. It also provides a way for Clients to change redirect_uri domains without having to reregister all of their users. pairwiseSubAlgorithmSalt.label=Salt pairwiseSubAlgorithmSalt.tooltip=Salt used when calculating the pairwise subject identifier. If left blank, a salt will be generated. - - +addressClaim.street.label=User Attribute Name for Street +addressClaim.street.tooltip=Name of User Attribute, which will be used to map to 'street_address' subclaim inside 'address' token claim. Defaults to 'street' . +addressClaim.locality.label=User Attribute Name for Locality +addressClaim.locality.tooltip=Name of User Attribute, which will be used to map to 'locality' subclaim inside 'address' token claim. Defaults to 'locality' . +addressClaim.region.label=User Attribute Name for Region +addressClaim.region.tooltip=Name of User Attribute, which will be used to map to 'region' subclaim inside 'address' token claim. Defaults to 'region' . +addressClaim.postal_code.label=User Attribute Name for Postal Code +addressClaim.postal_code.tooltip=Name of User Attribute, which will be used to map to 'postal_code' subclaim inside 'address' token claim. Defaults to 'postal_code' . +addressClaim.country.label=User Attribute Name for Country +addressClaim.country.tooltip=Name of User Attribute, which will be used to map to 'country' subclaim inside 'address' token claim. Defaults to 'country' . +addressClaim.formatted.label=User Attribute Name for Formatted Address +addressClaim.formatted.tooltip=Name of User Attribute, which will be used to map to 'formatted' subclaim inside 'address' token claim. Defaults to 'formatted' . # client details clients.tooltip=Clients are trusted browser apps and web services in a realm. These clients can request a login. You can also define client specific roles. diff --git a/themes/src/main/resources/theme/base/admin/resources/js/controllers/realm.js b/themes/src/main/resources/theme/base/admin/resources/js/controllers/realm.js index 5e6bdbaace98..e45133901539 100644 --- a/themes/src/main/resources/theme/base/admin/resources/js/controllers/realm.js +++ b/themes/src/main/resources/theme/base/admin/resources/js/controllers/realm.js @@ -2638,13 +2638,21 @@ module.controller('RealmImportCtrl', function($scope, realm, $route, $scope.itemCount = function(section) { if (!$scope.importing) return 0; if ($scope.hasRealmRoles() && (section === 'roles.realm')) return $scope.fileContent.roles.realm.length; - if ($scope.hasClientRoles() && (section === 'roles.client')) return Object.keys($scope.fileContent.roles.client).length; + if ($scope.hasClientRoles() && (section === 'roles.client')) return clientRolesCount($scope.fileContent.roles.client); if (!$scope.fileContent.hasOwnProperty(section)) return 0; return $scope.fileContent[section].length; } + clientRolesCount = function(clientRoles) { + var total = 0; + for (var clientName in clientRoles) { + total += clientRoles[clientName].length; + } + return total; + } + $scope.hasResources = function() { return ($scope.importUsers && $scope.hasArray('users')) || ($scope.importGroups && $scope.hasArray('groups')) || diff --git a/themes/src/main/resources/theme/base/admin/resources/js/services.js b/themes/src/main/resources/theme/base/admin/resources/js/services.js index d70ade2d2c51..b8cb2a3f8fd0 100755 --- a/themes/src/main/resources/theme/base/admin/resources/js/services.js +++ b/themes/src/main/resources/theme/base/admin/resources/js/services.js @@ -197,6 +197,9 @@ module.factory('ComponentUtils', function() { var utils = {}; utils.addLastEmptyValueToMultivaluedLists = function(properties, config) { + if (!properties) { + return; + } for (var i=0 ; i