Compare commits
249
Commits
2.5.5.Final
...
3.0.0.CR1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1cdecab650 | ||
|
|
de1650ccc4 | ||
|
|
c30cdb5411 | ||
|
|
b2d677256d | ||
|
|
f44405207b | ||
|
|
feeac69197 | ||
|
|
2aa93d7d55 | ||
|
|
80c9e23282 | ||
|
|
366dee6575 | ||
|
|
44907503a4 | ||
|
|
1974b34c29 | ||
|
|
6d51862057 | ||
|
|
d723c608d6 | ||
|
|
9a0de676c4 | ||
|
|
a555f99b1a | ||
|
|
32d3f760ec | ||
|
|
99581748e0 | ||
|
|
f0ae34d1ad | ||
|
|
4f39cf8abd | ||
|
|
e6df617cfc | ||
|
|
9d1d22565c | ||
|
|
e7e6314146 | ||
|
|
649ca36ece | ||
|
|
253c8a342b | ||
|
|
71a9d51c56 | ||
|
|
ef164f5e69 | ||
|
|
b0484409d4 | ||
|
|
aa84709087 | ||
|
|
adf3eaf8fe | ||
|
|
4dcb8d2c2a | ||
|
|
2cf4518ffd | ||
|
|
3f29c68e92 | ||
|
|
a56dd1651b | ||
|
|
f32fc99e80 | ||
|
|
b5433720c1 | ||
|
|
613f4bb4c6 | ||
|
|
063f5303dd | ||
|
|
45caea4dbd | ||
|
|
68da8c23ad | ||
|
|
282896b653 | ||
|
|
3884dd974a | ||
|
|
64f20b580a | ||
|
|
e7cd8d41c6 | ||
|
|
f3e842fdd9 | ||
|
|
42954e84d9 | ||
|
|
0ff4223184 | ||
|
|
b618dbd97f | ||
|
|
213cffa9c5 | ||
|
|
dc2d2cdbde | ||
|
|
8b888fdf0c | ||
|
|
46c6db1739 | ||
|
|
11d93994c2 | ||
|
|
c78c0b73d3 | ||
|
|
2175f66a30 | ||
|
|
7029ef80f8 | ||
|
|
16d5ca3378 | ||
|
|
5b4e3434bb | ||
|
|
1dea38bdbb | ||
|
|
0fc4cd134f | ||
|
|
efffcc5f41 | ||
|
|
6f2ace538f | ||
|
|
50af3212f1 | ||
|
|
e2e91ef098 | ||
|
|
0c4a1b1489 | ||
|
|
61c3d6eb74 | ||
|
|
62876b9694 | ||
|
|
739dae0846 | ||
|
|
7ab67d205b | ||
|
|
224c9c5395 | ||
|
|
7904ce5a37 | ||
|
|
e770a05db0 | ||
|
|
89c89b4867 | ||
|
|
213ed6fa4b | ||
|
|
280689055f | ||
|
|
1d11cb468c | ||
|
|
05e080624b | ||
|
|
c6dc59f63e | ||
|
|
a0a85f62c6 | ||
|
|
3bb29e033b | ||
|
|
87c9c99259 | ||
|
|
b0b0bfdf76 | ||
|
|
b8767d13d5 | ||
|
|
686f82342b | ||
|
|
cfb8d25ff2 | ||
|
|
a24070c2b0 | ||
|
|
69e61398a6 | ||
|
|
89768ef003 | ||
|
|
794defe6fc | ||
|
|
27ba4eb978 | ||
|
|
3a0c2be885 | ||
|
|
04da679628 | ||
|
|
43be3fc409 | ||
|
|
567393a102 | ||
|
|
75851ee0b3 | ||
|
|
b54d7c37b6 | ||
|
|
69cf7b4d0d | ||
|
|
4f4ae44a16 | ||
|
|
31191bdfc8 | ||
|
|
091b376624 | ||
|
|
52fbe00c04 | ||
|
|
c94b7922aa | ||
|
|
8d82390843 | ||
|
|
0765b01189 | ||
|
|
b4f625e1ce | ||
|
|
b5b0f433ac | ||
|
|
bcbde3fdf0 | ||
|
|
1970e03361 | ||
|
|
07f99a946d | ||
|
|
6ea9581c6c | ||
|
|
18a8ed3e95 | ||
|
|
e2b1c97e26 | ||
|
|
6a809a2009 | ||
|
|
6b808d78e6 | ||
|
|
26edcdf6bc | ||
|
|
f77670c4dd | ||
|
|
5a64d67404 | ||
|
|
ceb5a3a04b | ||
|
|
999a3f62ac | ||
|
|
ca64b90cbf | ||
|
|
2a7f595d1c | ||
|
|
089bde3571 | ||
|
|
2f45183ee5 | ||
|
|
a5677e87db | ||
|
|
0d7b4bab11 | ||
|
|
2cf25b6c57 | ||
|
|
4fbb8ed994 | ||
|
|
4f78312a98 | ||
|
|
48832f8ff4 | ||
|
|
098d8e915d | ||
|
|
49e8918462 | ||
|
|
0f1e73facc | ||
|
|
f6bc0806d5 | ||
|
|
3bf9428cc0 | ||
|
|
ec32acec27 | ||
|
|
152b4f13e7 | ||
|
|
284ef5992d | ||
|
|
faf0e98665 | ||
|
|
4d614ed635 | ||
|
|
3653d7ed9a | ||
|
|
eb5e30579d | ||
|
|
1625e6c977 | ||
|
|
6af06348bd | ||
|
|
e960e45671 | ||
|
|
5bce87d6e7 | ||
|
|
7db6d51a39 | ||
|
|
b1510c43ff | ||
|
|
44c81910bf | ||
|
|
27e390965e | ||
|
|
119435ac76 | ||
|
|
b31c38a158 | ||
|
|
49ac3587b6 | ||
|
|
06da1d164d | ||
|
|
f2a4fd029d | ||
|
|
aa59c2f95f | ||
|
|
8d5a8085a4 | ||
|
|
083f27f19d | ||
|
|
fe0b9e9893 | ||
|
|
91bcc24977 | ||
|
|
d72b67c460 | ||
|
|
68b5afed06 | ||
|
|
c3e72b11db | ||
|
|
224f93f25d | ||
|
|
3af9f2f989 | ||
|
|
8668eff1b6 | ||
|
|
3cec57da6a | ||
|
|
6602123b55 | ||
|
|
767b4a2e2a | ||
|
|
beb96b7f01 | ||
|
|
4ede1174b7 | ||
|
|
e3a8bed5b2 | ||
|
|
4f214921e3 | ||
|
|
00932f4eb3 | ||
|
|
dbe87d6592 | ||
|
|
9416ee7224 | ||
|
|
75909a0add | ||
|
|
d9633dc20c | ||
|
|
75bee51ac1 | ||
|
|
7d203ed448 | ||
|
|
bb9da83e52 | ||
|
|
8e16e5d953 | ||
|
|
44180a68e6 | ||
|
|
cf5e2a1d20 | ||
|
|
ceece3dce4 | ||
|
|
520839a29b | ||
|
|
a6b1e4f5f7 | ||
|
|
c4df0d2690 | ||
|
|
3de77b7be9 | ||
|
|
f3a552ac9d | ||
|
|
27c0f783bc | ||
|
|
72a5d03f34 | ||
|
|
5b5dc3e442 | ||
|
|
1c7de24084 | ||
|
|
f157e2e637 | ||
|
|
f128be9b31 | ||
|
|
8a16ab52a9 | ||
|
|
b693a3ee47 | ||
|
|
f73aaef67a | ||
|
|
652152f167 | ||
|
|
d60c3b7c0c | ||
|
|
73cad40fb7 | ||
|
|
cde3e87ad9 | ||
|
|
68a171f36c | ||
|
|
be2378a424 | ||
|
|
9aa2dacec9 | ||
|
|
ddf9301ceb | ||
|
|
7abe140621 | ||
|
|
ee62c52543 | ||
|
|
b4e4cbcbaa | ||
|
|
a7c3d1b8df | ||
|
|
79dede8e78 | ||
|
|
1d04d56bdb | ||
|
|
0d308e2b69 | ||
|
|
0c16a15b7d | ||
|
|
beebeaa265 | ||
|
|
c705a8ffc8 | ||
|
|
57c74e3f39 | ||
|
|
f92dd6bd16 | ||
|
|
99e1482e06 | ||
|
|
aec59a7e91 | ||
|
|
9a16805f17 | ||
|
|
2fd0c38ad1 | ||
|
|
2990703aeb | ||
|
|
acf2e30c2f | ||
|
|
5c5b7a33d3 | ||
|
|
e28ca0ae61 | ||
|
|
ad0630d04f | ||
|
|
4d362fe9ca | ||
|
|
bb77ab4a81 | ||
|
|
b42af99866 | ||
|
|
1a073629ec | ||
|
|
265522a2e3 | ||
|
|
c10be4b1cf | ||
|
|
065c931a83 | ||
|
|
7210ea36d2 | ||
|
|
5fd3eb2990 | ||
|
|
3a366dd0a6 | ||
|
|
1674bf1643 | ||
|
|
3e13ffda65 | ||
|
|
42ad8aec64 | ||
|
|
835d4c0aad | ||
|
|
ef9006e1a3 | ||
|
|
a8e2c8ef31 | ||
|
|
6f22f88d85 | ||
|
|
5bacd2919d | ||
|
|
9bb65ba9b7 | ||
|
|
ba73ab1c2a | ||
|
|
45f5fa6a74 | ||
|
|
50b7dbe7b2 | ||
|
|
4910b35d69 |
No files matched your search
+1
-2
@@ -16,7 +16,6 @@ env:
|
||||
- TESTS=group2
|
||||
- TESTS=group3
|
||||
- TESTS=group4
|
||||
- TESTS=adapter
|
||||
- TESTS=old
|
||||
|
||||
jdk:
|
||||
@@ -26,7 +25,7 @@ before_script:
|
||||
- export MAVEN_SKIP_RC=true
|
||||
|
||||
install:
|
||||
- travis_wait 60 mvn install -Pdistribution -DskipTests=true -B -V -q
|
||||
- travis_wait 60 mvn install --no-snapshot-updates -Pdistribution -DskipTests=true -B -V -q
|
||||
|
||||
script:
|
||||
- ./travis-run-tests.sh $TESTS
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>2.5.1.Final-SNAPSHOT</version>
|
||||
<version>3.0.0.CR1</version>
|
||||
<relativePath>../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
+3
-1
@@ -24,6 +24,7 @@ import org.keycloak.KeycloakPrincipal;
|
||||
import org.keycloak.adapters.spi.AuthChallenge;
|
||||
import org.keycloak.adapters.spi.AuthOutcome;
|
||||
import org.keycloak.adapters.spi.HttpFacade;
|
||||
import org.keycloak.common.enums.SslRequired;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
@@ -160,7 +161,8 @@ public abstract class RequestAuthenticator {
|
||||
|
||||
protected boolean verifySSL() {
|
||||
if (!facade.getRequest().isSecure() && deployment.getSslRequired().isRequired(facade.getRequest().getRemoteAddr())) {
|
||||
log.warn("SSL is required to authenticate");
|
||||
log.warnf("SSL is required to authenticate. Remote address %s is secure: %s, SSL required for: %s .",
|
||||
facade.getRequest().getRemoteAddr(), facade.getRequest().isSecure(), deployment.getSslRequired().name());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-as7-integration-pom</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>2.5.1.Final-SNAPSHOT</version>
|
||||
<version>3.0.0.CR1</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-as7-integration-pom</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>2.5.1.Final-SNAPSHOT</version>
|
||||
<version>3.0.0.CR1</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<parent>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-as7-integration-pom</artifactId>
|
||||
<version>2.5.1.Final-SNAPSHOT</version>
|
||||
<version>3.0.0.CR1</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>2.5.1.Final-SNAPSHOT</version>
|
||||
<version>3.0.0.CR1</version>
|
||||
<relativePath>../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<name>Keycloak AS7 / JBoss EAP 6 Integration</name>
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>2.5.1.Final-SNAPSHOT</version>
|
||||
<version>3.0.0.CR1</version>
|
||||
<relativePath>../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>2.5.1.Final-SNAPSHOT</version>
|
||||
<version>3.0.0.CR1</version>
|
||||
<relativePath>../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>2.5.1.Final-SNAPSHOT</version>
|
||||
<version>3.0.0.CR1</version>
|
||||
<relativePath>../../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
+3
-1
@@ -106,6 +106,8 @@ public abstract class AbstractKeycloakJettyAuthenticator extends LoginAuthentica
|
||||
|
||||
public abstract AdapterTokenStore createSessionTokenStore(Request request, KeycloakDeployment resolvedDeployment);
|
||||
|
||||
public abstract JettyUserSessionManagement createSessionManagement(Request request);
|
||||
|
||||
public void logoutCurrent(Request request) {
|
||||
AdapterDeploymentContext deploymentContext = (AdapterDeploymentContext) request.getAttribute(AdapterDeploymentContext.class.getName());
|
||||
KeycloakSecurityContext ksc = (KeycloakSecurityContext) request.getAttribute(KeycloakSecurityContext.class.getName());
|
||||
@@ -287,7 +289,7 @@ public abstract class AbstractKeycloakJettyAuthenticator extends LoginAuthentica
|
||||
log.debug("*** deployment isn't configured return false");
|
||||
return Authentication.UNAUTHENTICATED;
|
||||
}
|
||||
PreAuthActionsHandler handler = new PreAuthActionsHandler(new JettyUserSessionManagement(request.getSessionManager()), deploymentContext, facade);
|
||||
PreAuthActionsHandler handler = new PreAuthActionsHandler(createSessionManagement(request), deploymentContext, facade);
|
||||
if (handler.handleRequest()) {
|
||||
return Authentication.SEND_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>2.5.1.Final-SNAPSHOT</version>
|
||||
<version>3.0.0.CR1</version>
|
||||
<relativePath>../../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
+15
-8
@@ -15,19 +15,26 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.models.mongo.keycloak.entities;
|
||||
package org.keycloak.adapters.jetty;
|
||||
|
||||
import org.keycloak.connections.mongo.api.MongoCollection;
|
||||
import org.keycloak.connections.mongo.api.MongoIdentifiableEntity;
|
||||
import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext;
|
||||
import org.eclipse.jetty.server.SessionManager;
|
||||
import org.keycloak.adapters.jetty.spi.JettySessionManager;
|
||||
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
@MongoCollection(collectionName = "userConsents")
|
||||
public class MongoUserConsentEntity extends UserConsentEntity implements MongoIdentifiableEntity {
|
||||
public class Jetty81SessionManager implements JettySessionManager {
|
||||
protected SessionManager sessionManager;
|
||||
|
||||
public Jetty81SessionManager(SessionManager sessionManager) {
|
||||
this.sessionManager = sessionManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterRemove(MongoStoreInvocationContext invocationContext) {
|
||||
public HttpSession getHttpSession(String id) {
|
||||
return sessionManager.getHttpSession(id);
|
||||
}
|
||||
}
|
||||
+6
@@ -25,6 +25,7 @@ import org.keycloak.adapters.AdapterTokenStore;
|
||||
import org.keycloak.adapters.KeycloakDeployment;
|
||||
import org.keycloak.adapters.jetty.core.AbstractKeycloakJettyAuthenticator;
|
||||
import org.keycloak.adapters.jetty.core.JettySessionTokenStore;
|
||||
import org.keycloak.adapters.jetty.spi.JettyUserSessionManagement;
|
||||
|
||||
import javax.servlet.ServletRequest;
|
||||
|
||||
@@ -44,6 +45,11 @@ public class KeycloakJettyAuthenticator extends AbstractKeycloakJettyAuthenticat
|
||||
return new JettySessionTokenStore(request, resolvedDeployment, new JettyAdapterSessionStore(request));
|
||||
}
|
||||
|
||||
@Override
|
||||
public JettyUserSessionManagement createSessionManagement(Request request) {
|
||||
return new JettyUserSessionManagement(new Jetty81SessionManager(request.getSessionManager()));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Request resolveRequest(ServletRequest req) {
|
||||
return (req instanceof Request)?(Request)req: AbstractHttpConnection.getCurrentConnection().getRequest();
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>2.5.1.Final-SNAPSHOT</version>
|
||||
<version>3.0.0.CR1</version>
|
||||
<relativePath>../../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
Executable
+40
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* 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.jetty;
|
||||
|
||||
import org.eclipse.jetty.server.SessionManager;
|
||||
import org.keycloak.adapters.jetty.spi.JettySessionManager;
|
||||
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class Jetty91SessionManager implements JettySessionManager {
|
||||
protected SessionManager sessionManager;
|
||||
|
||||
public Jetty91SessionManager(SessionManager sessionManager) {
|
||||
this.sessionManager = sessionManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpSession getHttpSession(String id) {
|
||||
return sessionManager.getHttpSession(id);
|
||||
}
|
||||
}
|
||||
+6
@@ -27,6 +27,7 @@ import org.keycloak.adapters.jetty.core.AbstractKeycloakJettyAuthenticator;
|
||||
import org.keycloak.adapters.jetty.core.JettyRequestAuthenticator;
|
||||
import org.keycloak.adapters.jetty.core.JettySessionTokenStore;
|
||||
import org.keycloak.adapters.jetty.spi.JettyHttpFacade;
|
||||
import org.keycloak.adapters.jetty.spi.JettyUserSessionManagement;
|
||||
|
||||
import javax.servlet.ServletRequest;
|
||||
|
||||
@@ -46,6 +47,11 @@ public class KeycloakJettyAuthenticator extends AbstractKeycloakJettyAuthenticat
|
||||
return new JettySessionTokenStore(request, resolvedDeployment, new JettyAdapterSessionStore(request));
|
||||
}
|
||||
|
||||
@Override
|
||||
public JettyUserSessionManagement createSessionManagement(Request request) {
|
||||
return new JettyUserSessionManagement(new Jetty91SessionManager(request.getSessionManager()));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Request resolveRequest(ServletRequest req) {
|
||||
return (req instanceof Request) ? (Request)req : HttpChannel.getCurrentHttpChannel().getRequest();
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>2.5.1.Final-SNAPSHOT</version>
|
||||
<version>3.0.0.CR1</version>
|
||||
<relativePath>../../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
Executable
+40
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* 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.jetty;
|
||||
|
||||
import org.eclipse.jetty.server.SessionManager;
|
||||
import org.keycloak.adapters.jetty.spi.JettySessionManager;
|
||||
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class Jetty92SessionManager implements JettySessionManager {
|
||||
protected SessionManager sessionManager;
|
||||
|
||||
public Jetty92SessionManager(SessionManager sessionManager) {
|
||||
this.sessionManager = sessionManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpSession getHttpSession(String id) {
|
||||
return sessionManager.getHttpSession(id);
|
||||
}
|
||||
}
|
||||
+6
@@ -27,6 +27,7 @@ import org.keycloak.adapters.jetty.core.AbstractKeycloakJettyAuthenticator;
|
||||
import org.keycloak.adapters.jetty.core.JettyRequestAuthenticator;
|
||||
import org.keycloak.adapters.jetty.core.JettySessionTokenStore;
|
||||
import org.keycloak.adapters.jetty.spi.JettyHttpFacade;
|
||||
import org.keycloak.adapters.jetty.spi.JettyUserSessionManagement;
|
||||
|
||||
import javax.servlet.ServletRequest;
|
||||
|
||||
@@ -61,6 +62,11 @@ public class KeycloakJettyAuthenticator extends AbstractKeycloakJettyAuthenticat
|
||||
return new JettySessionTokenStore(request, resolvedDeployment, new JettyAdapterSessionStore(request));
|
||||
}
|
||||
|
||||
@Override
|
||||
public JettyUserSessionManagement createSessionManagement(Request request) {
|
||||
return new JettyUserSessionManagement(new Jetty92SessionManager(request.getSessionManager()));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected JettyRequestAuthenticator createRequestAuthenticator(Request request, JettyHttpFacade facade,
|
||||
KeycloakDeployment deployment, AdapterTokenStore tokenStore) {
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>2.5.1.Final-SNAPSHOT</version>
|
||||
<version>3.0.0.CR1</version>
|
||||
<relativePath>../../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
Executable
+40
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* 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.jetty;
|
||||
|
||||
import org.eclipse.jetty.server.SessionManager;
|
||||
import org.keycloak.adapters.jetty.spi.JettySessionManager;
|
||||
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class Jetty93SessionManager implements JettySessionManager {
|
||||
protected SessionManager sessionManager;
|
||||
|
||||
public Jetty93SessionManager(SessionManager sessionManager) {
|
||||
this.sessionManager = sessionManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpSession getHttpSession(String id) {
|
||||
return sessionManager.getHttpSession(id);
|
||||
}
|
||||
}
|
||||
+6
@@ -26,6 +26,7 @@ import org.keycloak.adapters.jetty.core.AbstractKeycloakJettyAuthenticator;
|
||||
import org.keycloak.adapters.jetty.core.JettyRequestAuthenticator;
|
||||
import org.keycloak.adapters.jetty.core.JettySessionTokenStore;
|
||||
import org.keycloak.adapters.jetty.spi.JettyHttpFacade;
|
||||
import org.keycloak.adapters.jetty.spi.JettyUserSessionManagement;
|
||||
|
||||
import javax.servlet.ServletRequest;
|
||||
|
||||
@@ -60,6 +61,11 @@ public class KeycloakJettyAuthenticator extends AbstractKeycloakJettyAuthenticat
|
||||
return new JettySessionTokenStore(request, resolvedDeployment, new JettyAdapterSessionStore(request));
|
||||
}
|
||||
|
||||
@Override
|
||||
public JettyUserSessionManagement createSessionManagement(Request request) {
|
||||
return new JettyUserSessionManagement(new Jetty93SessionManager(request.getSessionManager()));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected JettyRequestAuthenticator createRequestAuthenticator(Request request, JettyHttpFacade facade,
|
||||
KeycloakDeployment deployment, AdapterTokenStore tokenStore) {
|
||||
|
||||
@@ -0,0 +1,156 @@
|
||||
<?xml version="1.0"?>
|
||||
<!--
|
||||
~ 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.
|
||||
-->
|
||||
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>3.0.0.CR1</version>
|
||||
<relativePath>../../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>keycloak-jetty94-adapter</artifactId>
|
||||
<name>Keycloak Jetty 9.4.x Integration</name>
|
||||
<properties>
|
||||
<jetty9.version>9.4.2.v20170220</jetty9.version>
|
||||
<keycloak.osgi.export>
|
||||
org.keycloak.adapters.jetty.*
|
||||
</keycloak.osgi.export>
|
||||
<keycloak.osgi.import>
|
||||
org.eclipse.jetty.*;resolution:=optional,
|
||||
javax.servlet.*;version="[3.0,4)";resolution:=optional,
|
||||
org.keycloak.*;version="${project.version}",
|
||||
*;resolution:=optional
|
||||
</keycloak.osgi.import>
|
||||
</properties>
|
||||
<description />
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.jboss.logging</groupId>
|
||||
<artifactId>jboss-logging</artifactId>
|
||||
<version>${jboss.logging.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-adapter-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-jetty-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
<artifactId>httpclient</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.bouncycastle</groupId>
|
||||
<artifactId>bcprov-jdk15on</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-annotations</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-server</artifactId>
|
||||
<version>${jetty9.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-util</artifactId>
|
||||
<version>${jetty9.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-security</artifactId>
|
||||
<version>${jetty9.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<source>1.6</source>
|
||||
<target>1.6</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<!-- Adding OSGI metadata to the JAR without changing the packaging type. -->
|
||||
<plugin>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<configuration>
|
||||
<archive>
|
||||
<manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile>
|
||||
</archive>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.felix</groupId>
|
||||
<artifactId>maven-bundle-plugin</artifactId>
|
||||
<extensions>true</extensions>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>bundle-manifest</id>
|
||||
<phase>process-classes</phase>
|
||||
<goals>
|
||||
<goal>manifest</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<instructions>
|
||||
<Bundle-ClassPath>.</Bundle-ClassPath>
|
||||
<Bundle-Name>${project.name}</Bundle-Name>
|
||||
<Bundle-SymbolicName>${project.groupId}.${project.artifactId}</Bundle-SymbolicName>
|
||||
<Import-Package>${keycloak.osgi.import}</Import-Package>
|
||||
<Export-Package>${keycloak.osgi.export}</Export-Package>
|
||||
</instructions>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* 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.jetty;
|
||||
|
||||
import org.eclipse.jetty.server.Request;
|
||||
import org.keycloak.adapters.AdapterTokenStore;
|
||||
import org.keycloak.adapters.KeycloakDeployment;
|
||||
import org.keycloak.adapters.jetty.core.JettyRequestAuthenticator;
|
||||
import org.keycloak.adapters.spi.HttpFacade;
|
||||
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class Jetty94RequestAuthenticator extends JettyRequestAuthenticator {
|
||||
public Jetty94RequestAuthenticator(HttpFacade facade, KeycloakDeployment deployment, AdapterTokenStore tokenStore, int sslRedirectPort, Request request) {
|
||||
super(facade, deployment, tokenStore, sslRedirectPort, request);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String changeHttpSessionId(boolean create) {
|
||||
Request request = this.request;
|
||||
HttpSession session = request.getSession(false);
|
||||
if (session == null) {
|
||||
return request.getSession(true).getId();
|
||||
}
|
||||
if (!deployment.isTurnOffChangeSessionIdOnLogin()) return request.changeSessionId();
|
||||
else return session.getId();
|
||||
}
|
||||
}
|
||||
Executable
+40
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* 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.jetty;
|
||||
|
||||
import org.eclipse.jetty.server.session.SessionHandler;
|
||||
import org.keycloak.adapters.jetty.spi.JettySessionManager;
|
||||
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class Jetty94SessionManager implements JettySessionManager {
|
||||
protected SessionHandler sessionHandler;
|
||||
|
||||
public Jetty94SessionManager(SessionHandler sessionHandler) {
|
||||
this.sessionHandler = sessionHandler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpSession getHttpSession(String id) {
|
||||
return sessionHandler.getHttpSession(id);
|
||||
}
|
||||
}
|
||||
+111
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* 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.jetty;
|
||||
|
||||
import org.eclipse.jetty.security.authentication.FormAuthenticator;
|
||||
import org.eclipse.jetty.server.Request;
|
||||
import org.eclipse.jetty.util.MultiMap;
|
||||
import org.keycloak.adapters.jetty.spi.JettyHttpFacade;
|
||||
import org.keycloak.adapters.spi.AdapterSessionStore;
|
||||
import org.keycloak.common.util.MultivaluedHashMap;
|
||||
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class JettyAdapterSessionStore implements AdapterSessionStore {
|
||||
public static final String CACHED_FORM_PARAMETERS = "__CACHED_FORM_PARAMETERS";
|
||||
protected Request myRequest;
|
||||
|
||||
public JettyAdapterSessionStore(Request request) {
|
||||
this.myRequest = request; // for IDE/compilation purposes
|
||||
}
|
||||
|
||||
protected MultiMap<String> extractFormParameters(Request base_request) {
|
||||
MultiMap<String> formParameters = new MultiMap<String>();
|
||||
base_request.extractFormParameters(formParameters);
|
||||
return formParameters;
|
||||
}
|
||||
protected void restoreFormParameters(MultiMap<String> j_post, Request base_request) {
|
||||
base_request.setContentParameters(j_post);
|
||||
}
|
||||
|
||||
public boolean restoreRequest() {
|
||||
HttpSession session = myRequest.getSession(false);
|
||||
if (session == null) return false;
|
||||
synchronized (session) {
|
||||
String j_uri = (String) session.getAttribute(FormAuthenticator.__J_URI);
|
||||
if (j_uri != null) {
|
||||
// check if the request is for the same url as the original and restore
|
||||
// params if it was a post
|
||||
StringBuffer buf = myRequest.getRequestURL();
|
||||
if (myRequest.getQueryString() != null)
|
||||
buf.append("?").append(myRequest.getQueryString());
|
||||
if (j_uri.equals(buf.toString())) {
|
||||
String method = (String)session.getAttribute(JettyHttpFacade.__J_METHOD);
|
||||
myRequest.setMethod(method);
|
||||
MultivaluedHashMap<String, String> j_post = (MultivaluedHashMap<String, String>) session.getAttribute(CACHED_FORM_PARAMETERS);
|
||||
if (j_post != null) {
|
||||
myRequest.setContentType("application/x-www-form-urlencoded");
|
||||
MultiMap<String> map = new MultiMap<String>();
|
||||
for (String key : j_post.keySet()) {
|
||||
for (String val : j_post.getList(key)) {
|
||||
map.add(key, val);
|
||||
}
|
||||
}
|
||||
restoreFormParameters(map, myRequest);
|
||||
}
|
||||
session.removeAttribute(FormAuthenticator.__J_URI);
|
||||
session.removeAttribute(JettyHttpFacade.__J_METHOD);
|
||||
session.removeAttribute(FormAuthenticator.__J_POST);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void saveRequest() {
|
||||
// remember the current URI
|
||||
HttpSession session = myRequest.getSession();
|
||||
synchronized (session) {
|
||||
// But only if it is not set already, or we save every uri that leads to a login form redirect
|
||||
if (session.getAttribute(FormAuthenticator.__J_URI) == null) {
|
||||
StringBuffer buf = myRequest.getRequestURL();
|
||||
if (myRequest.getQueryString() != null)
|
||||
buf.append("?").append(myRequest.getQueryString());
|
||||
session.setAttribute(FormAuthenticator.__J_URI, buf.toString());
|
||||
session.setAttribute(JettyHttpFacade.__J_METHOD, myRequest.getMethod());
|
||||
|
||||
if ("application/x-www-form-urlencoded".equals(myRequest.getContentType()) && "POST".equalsIgnoreCase(myRequest.getMethod())) {
|
||||
MultiMap<String> formParameters = extractFormParameters(myRequest);
|
||||
MultivaluedHashMap<String, String> map = new MultivaluedHashMap<String, String>();
|
||||
for (String key : formParameters.keySet()) {
|
||||
for (Object value : formParameters.getValues(key)) {
|
||||
map.add(key, (String) value);
|
||||
}
|
||||
}
|
||||
session.setAttribute(CACHED_FORM_PARAMETERS, map);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+75
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* 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.jetty;
|
||||
|
||||
import org.eclipse.jetty.server.Authentication;
|
||||
import org.eclipse.jetty.server.Request;
|
||||
import org.eclipse.jetty.server.UserIdentity;
|
||||
import org.keycloak.adapters.AdapterTokenStore;
|
||||
import org.keycloak.adapters.KeycloakDeployment;
|
||||
import org.keycloak.adapters.jetty.core.AbstractKeycloakJettyAuthenticator;
|
||||
import org.keycloak.adapters.jetty.core.JettyRequestAuthenticator;
|
||||
import org.keycloak.adapters.jetty.core.JettySessionTokenStore;
|
||||
import org.keycloak.adapters.jetty.spi.JettyHttpFacade;
|
||||
import org.keycloak.adapters.jetty.spi.JettyUserSessionManagement;
|
||||
|
||||
import javax.servlet.ServletRequest;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class KeycloakJettyAuthenticator extends AbstractKeycloakJettyAuthenticator {
|
||||
|
||||
public KeycloakJettyAuthenticator() {
|
||||
super();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected Request resolveRequest(ServletRequest req) {
|
||||
return Request.getBaseRequest(req);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Authentication createAuthentication(UserIdentity userIdentity, final Request request) {
|
||||
return new KeycloakAuthentication(getAuthMethod(), userIdentity) {
|
||||
@Override
|
||||
public void logout() {
|
||||
logoutCurrent(request);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public AdapterTokenStore createSessionTokenStore(Request request, KeycloakDeployment resolvedDeployment) {
|
||||
return new JettySessionTokenStore(request, resolvedDeployment, new JettyAdapterSessionStore(request));
|
||||
}
|
||||
|
||||
@Override
|
||||
public JettyUserSessionManagement createSessionManagement(Request request) {
|
||||
return new JettyUserSessionManagement(new Jetty94SessionManager(request.getSessionHandler()));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected JettyRequestAuthenticator createRequestAuthenticator(Request request, JettyHttpFacade facade,
|
||||
KeycloakDeployment deployment, AdapterTokenStore tokenStore) {
|
||||
return new Jetty94RequestAuthenticator(facade, deployment, tokenStore, -1, request);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -20,7 +20,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>2.5.1.Final-SNAPSHOT</version>
|
||||
<version>3.0.0.CR1</version>
|
||||
<relativePath>../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<name>Keycloak Jetty Integration</name>
|
||||
@@ -36,5 +36,6 @@
|
||||
<module>jetty9.1</module>
|
||||
<module>jetty9.2</module>
|
||||
<module>jetty9.3</module>
|
||||
<module>jetty9.4</module>
|
||||
</modules>
|
||||
</project>
|
||||
@@ -21,7 +21,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>2.5.1.Final-SNAPSHOT</version>
|
||||
<version>3.0.0.CR1</version>
|
||||
<relativePath>../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@@ -87,6 +87,10 @@
|
||||
}
|
||||
kc.flow = initOptions.flow;
|
||||
}
|
||||
|
||||
if (initOptions.timeSkew != null) {
|
||||
kc.timeSkew = initOptions.timeSkew;
|
||||
}
|
||||
}
|
||||
|
||||
if (!kc.responseMode) {
|
||||
@@ -162,12 +166,8 @@
|
||||
kc.onAuthSuccess && kc.onAuthSuccess();
|
||||
initPromise.setSuccess();
|
||||
}).error(function () {
|
||||
kc.onAuthError && kc.onAuthError();
|
||||
if (initOptions.onLoad) {
|
||||
onLoad();
|
||||
} else {
|
||||
initPromise.setError();
|
||||
}
|
||||
setToken(null, null, null);
|
||||
initPromise.setSuccess();
|
||||
});
|
||||
});
|
||||
} else {
|
||||
@@ -369,6 +369,11 @@
|
||||
throw 'Not authenticated';
|
||||
}
|
||||
|
||||
if (kc.timeSkew == null) {
|
||||
console.info('[KEYCLOAK] Unable to determine if token is expired as timeskew is not set');
|
||||
return true;
|
||||
}
|
||||
|
||||
var expiresIn = kc.tokenParsed['exp'] - Math.ceil(new Date().getTime() / 1000) + kc.timeSkew;
|
||||
if (minValidity) {
|
||||
expiresIn -= minValidity;
|
||||
@@ -653,12 +658,7 @@
|
||||
if (token) {
|
||||
kc.token = token;
|
||||
kc.tokenParsed = decodeToken(token);
|
||||
|
||||
var sessionId = kc.realm + '/' + kc.tokenParsed.sub;
|
||||
if (kc.tokenParsed.session_state) {
|
||||
sessionId = sessionId + '/' + kc.tokenParsed.session_state;
|
||||
}
|
||||
kc.sessionId = sessionId;
|
||||
kc.sessionId = kc.tokenParsed.session_state;
|
||||
kc.authenticated = true;
|
||||
kc.subject = kc.tokenParsed.sub;
|
||||
kc.realmAccess = kc.tokenParsed.realm_access;
|
||||
@@ -666,6 +666,9 @@
|
||||
|
||||
if (timeLocal) {
|
||||
kc.timeSkew = Math.floor(timeLocal / 1000) - kc.tokenParsed.iat;
|
||||
}
|
||||
|
||||
if (kc.timeSkew != null) {
|
||||
console.info('[KEYCLOAK] Estimated time difference between browser and server is ' + kc.timeSkew + ' seconds');
|
||||
|
||||
if (kc.onTokenExpired) {
|
||||
@@ -677,11 +680,7 @@
|
||||
kc.tokenTimeoutHandle = setTimeout(kc.onTokenExpired, expiresIn);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
kc.updateToken(-1);
|
||||
}
|
||||
} else if (refreshToken) {
|
||||
kc.updateToken(-1);
|
||||
} else {
|
||||
delete kc.token;
|
||||
delete kc.tokenParsed;
|
||||
|
||||
@@ -53,7 +53,8 @@
|
||||
req.send();
|
||||
} else {
|
||||
if (clientId === init.clientId && origin === init.origin) {
|
||||
if (sessionState === cookie) {
|
||||
var c = cookie.split('/');
|
||||
if (sessionState === c[2]) {
|
||||
callback('unchanged');
|
||||
} else {
|
||||
callback('changed');
|
||||
@@ -81,7 +82,7 @@
|
||||
var origin = event.origin;
|
||||
var data = event.data.split(' ');
|
||||
if (data.length != 2) {
|
||||
event.source.postMessage('error', origin);
|
||||
return;
|
||||
}
|
||||
|
||||
var clientId = data[0];
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>2.5.1.Final-SNAPSHOT</version>
|
||||
<version>3.0.0.CR1</version>
|
||||
<relativePath>../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
+83
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* 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.osgi;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
|
||||
import org.keycloak.adapters.KeycloakConfigResolver;
|
||||
import org.keycloak.adapters.KeycloakDeployment;
|
||||
import org.keycloak.adapters.KeycloakDeploymentBuilder;
|
||||
import org.keycloak.adapters.spi.HttpFacade;
|
||||
import org.osgi.framework.BundleContext;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||
*/
|
||||
public class BundleBasedKeycloakConfigResolver implements KeycloakConfigResolver {
|
||||
|
||||
private volatile KeycloakDeployment cachedDeployment;
|
||||
|
||||
private BundleContext bundleContext;
|
||||
private String configLocation = "WEB-INF/keycloak.json";
|
||||
|
||||
public BundleContext getBundleContext() {
|
||||
return bundleContext;
|
||||
}
|
||||
|
||||
public void setBundleContext(BundleContext bundleContext) {
|
||||
this.bundleContext = bundleContext;
|
||||
}
|
||||
|
||||
public String getConfigLocation() {
|
||||
return configLocation;
|
||||
}
|
||||
|
||||
public void setConfigLocation(String configLocation) {
|
||||
this.configLocation = configLocation;
|
||||
}
|
||||
|
||||
@Override
|
||||
public KeycloakDeployment resolve(HttpFacade.Request request) {
|
||||
if (cachedDeployment != null) {
|
||||
return cachedDeployment;
|
||||
} else {
|
||||
cachedDeployment = findDeployment(request);
|
||||
return cachedDeployment;
|
||||
}
|
||||
}
|
||||
|
||||
protected KeycloakDeployment findDeployment(HttpFacade.Request request) {
|
||||
if (bundleContext == null) {
|
||||
throw new IllegalStateException("bundleContext must be set for BundleBasedKeycloakConfigResolver!");
|
||||
}
|
||||
|
||||
URL url = bundleContext.getBundle().getResource(configLocation);
|
||||
if (url == null) {
|
||||
throw new IllegalStateException("Failed to find the file " + configLocation + " on classpath.");
|
||||
}
|
||||
|
||||
try {
|
||||
InputStream is = url.openStream();
|
||||
return KeycloakDeploymentBuilder.build(is);
|
||||
} catch (IOException ioe) {
|
||||
throw new IllegalStateException("Error reading file' " + configLocation + "' from bundle classpath.", ioe);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -20,7 +20,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>2.5.1.Final-SNAPSHOT</version>
|
||||
<version>3.0.0.CR1</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<name>Keycloak OIDC Client Adapter Modules</name>
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>2.5.1.Final-SNAPSHOT</version>
|
||||
<version>3.0.0.CR1</version>
|
||||
<relativePath>../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
+4
-1
@@ -53,6 +53,9 @@ import java.util.regex.Pattern;
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class KeycloakOIDCFilter implements Filter {
|
||||
|
||||
public static final String SKIP_PATTERN_PARAM = "keycloak.config.skipPattern";
|
||||
|
||||
protected AdapterDeploymentContext deploymentContext;
|
||||
protected SessionIdMapper idMapper = new InMemorySessionIdMapper();
|
||||
protected NodesRegistrationManagement nodesRegistrationManagement;
|
||||
@@ -63,7 +66,7 @@ public class KeycloakOIDCFilter implements Filter {
|
||||
@Override
|
||||
public void init(final FilterConfig filterConfig) throws ServletException {
|
||||
|
||||
String skipPatternDefinition = filterConfig.getInitParameter("keycloak.config.skipPattern");
|
||||
String skipPatternDefinition = filterConfig.getInitParameter(SKIP_PATTERN_PARAM);
|
||||
if (skipPatternDefinition != null) {
|
||||
skipPattern = Pattern.compile(skipPatternDefinition, Pattern.DOTALL);
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>2.5.1.Final-SNAPSHOT</version>
|
||||
<version>3.0.0.CR1</version>
|
||||
<relativePath>../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>2.5.1.Final-SNAPSHOT</version>
|
||||
<version>3.0.0.CR1</version>
|
||||
<relativePath>../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
@@ -31,7 +31,7 @@
|
||||
<description/>
|
||||
|
||||
<properties>
|
||||
<spring-boot.version>1.2.1.RELEASE</spring-boot.version>
|
||||
<spring-boot.version>1.3.0.RELEASE</spring-boot.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
@@ -111,6 +111,13 @@
|
||||
<artifactId>junit</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-configuration-processor</artifactId>
|
||||
<optional>true</optional>
|
||||
<version>${spring-boot.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
|
||||
+26
-1
@@ -38,9 +38,16 @@ public class KeycloakSpringBootProperties extends AdapterConfig {
|
||||
return config;
|
||||
}
|
||||
|
||||
/**
|
||||
* To provide Java EE security constraints
|
||||
*/
|
||||
private List<SecurityConstraint> securityConstraints = new ArrayList<SecurityConstraint>();
|
||||
|
||||
@ConfigurationProperties()
|
||||
public static class SecurityConstraint {
|
||||
/**
|
||||
* A list of security collections
|
||||
*/
|
||||
private List<SecurityCollection> securityCollections = new ArrayList<SecurityCollection>();
|
||||
|
||||
public List<SecurityCollection> getSecurityCollections() {
|
||||
@@ -51,13 +58,31 @@ public class KeycloakSpringBootProperties extends AdapterConfig {
|
||||
this.securityCollections = securityCollections;
|
||||
}
|
||||
}
|
||||
|
||||
@ConfigurationProperties()
|
||||
public static class SecurityCollection {
|
||||
/**
|
||||
* The name of your security constraint
|
||||
*/
|
||||
private String name;
|
||||
/**
|
||||
* The description of your security collection
|
||||
*/
|
||||
private String description;
|
||||
/**
|
||||
* A list of roles that applies for this security collection
|
||||
*/
|
||||
private List<String> authRoles = new ArrayList<String>();
|
||||
/**
|
||||
* A list of URL patterns that should match to apply the security collection
|
||||
*/
|
||||
private List<String> patterns = new ArrayList<String>();
|
||||
/**
|
||||
* A list of HTTP methods that applies for this security collection
|
||||
*/
|
||||
private List<String> methods = new ArrayList<String>();
|
||||
/**
|
||||
* A list of HTTP methods that will be omitted for this security collection
|
||||
*/
|
||||
private List<String> omittedMethods = new ArrayList<String>();
|
||||
|
||||
public List<String> getAuthRoles() {
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>2.5.1.Final-SNAPSHOT</version>
|
||||
<version>3.0.0.CR1</version>
|
||||
<relativePath>../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>2.5.1.Final-SNAPSHOT</version>
|
||||
<version>3.0.0.CR1</version>
|
||||
<relativePath>../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<name>Keycloak Tomcat Integration</name>
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-tomcat-integration-pom</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>2.5.1.Final-SNAPSHOT</version>
|
||||
<version>3.0.0.CR1</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
+9
-11
@@ -25,6 +25,7 @@ import org.apache.catalina.Manager;
|
||||
import org.apache.catalina.authenticator.FormAuthenticator;
|
||||
import org.apache.catalina.connector.Request;
|
||||
import org.apache.catalina.connector.Response;
|
||||
import org.jboss.logging.Logger;
|
||||
import org.keycloak.KeycloakSecurityContext;
|
||||
import org.keycloak.adapters.AdapterDeploymentContext;
|
||||
import org.keycloak.adapters.AdapterTokenStore;
|
||||
@@ -48,8 +49,6 @@ import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* Keycloak authentication valve
|
||||
@@ -62,7 +61,7 @@ public abstract class AbstractKeycloakAuthenticatorValve extends FormAuthenticat
|
||||
|
||||
public static final String TOKEN_STORE_NOTE = "TOKEN_STORE_NOTE";
|
||||
|
||||
private final static Logger log = Logger.getLogger(""+AbstractKeycloakAuthenticatorValve.class);
|
||||
private final static Logger log = Logger.getLogger(AbstractKeycloakAuthenticatorValve.class);
|
||||
protected CatalinaUserSessionManagement userSessionManagement = new CatalinaUserSessionManagement();
|
||||
protected AdapterDeploymentContext deploymentContext;
|
||||
protected NodesRegistrationManagement nodesRegistrationManagement;
|
||||
@@ -118,22 +117,22 @@ public abstract class AbstractKeycloakAuthenticatorValve extends FormAuthenticat
|
||||
try {
|
||||
KeycloakConfigResolver configResolver = (KeycloakConfigResolver) context.getLoader().getClassLoader().loadClass(configResolverClass).newInstance();
|
||||
deploymentContext = new AdapterDeploymentContext(configResolver);
|
||||
log.log(Level.INFO, "Using {0} to resolve Keycloak configuration on a per-request basis.", configResolverClass);
|
||||
log.debugv("Using {0} to resolve Keycloak configuration on a per-request basis.", configResolverClass);
|
||||
} catch (Exception ex) {
|
||||
log.log(Level.FINE, "The specified resolver {0} could NOT be loaded. Keycloak is unconfigured and will deny all requests. Reason: {1}", new Object[]{configResolverClass, ex.getMessage()});
|
||||
log.errorv("The specified resolver {0} could NOT be loaded. Keycloak is unconfigured and will deny all requests. Reason: {1}", configResolverClass, ex.getMessage());
|
||||
deploymentContext = new AdapterDeploymentContext(new KeycloakDeployment());
|
||||
}
|
||||
} else {
|
||||
InputStream configInputStream = getConfigInputStream(context);
|
||||
KeycloakDeployment kd;
|
||||
if (configInputStream == null) {
|
||||
log.warning("No adapter configuration. Keycloak is unconfigured and will deny all requests.");
|
||||
log.warn("No adapter configuration. Keycloak is unconfigured and will deny all requests.");
|
||||
kd = new KeycloakDeployment();
|
||||
} else {
|
||||
kd = KeycloakDeploymentBuilder.build(configInputStream);
|
||||
}
|
||||
deploymentContext = new AdapterDeploymentContext(kd);
|
||||
log.fine("Keycloak is using a per-deployment configuration.");
|
||||
log.debug("Keycloak is using a per-deployment configuration.");
|
||||
}
|
||||
|
||||
context.getServletContext().setAttribute(AdapterDeploymentContext.class.getName(), deploymentContext);
|
||||
@@ -149,8 +148,7 @@ public abstract class AbstractKeycloakAuthenticatorValve extends FormAuthenticat
|
||||
if (json == null) {
|
||||
return null;
|
||||
}
|
||||
log.finest("**** using " + AdapterConstants.AUTH_DATA_PARAM_NAME);
|
||||
log.finest(json);
|
||||
log.trace("**** using " + AdapterConstants.AUTH_DATA_PARAM_NAME);
|
||||
return new ByteArrayInputStream(json.getBytes());
|
||||
}
|
||||
|
||||
@@ -159,13 +157,13 @@ public abstract class AbstractKeycloakAuthenticatorValve extends FormAuthenticat
|
||||
if (is == null) {
|
||||
String path = context.getServletContext().getInitParameter("keycloak.config.file");
|
||||
if (path == null) {
|
||||
log.finest("**** using /WEB-INF/keycloak.json");
|
||||
log.trace("**** using /WEB-INF/keycloak.json");
|
||||
is = context.getServletContext().getResourceAsStream("/WEB-INF/keycloak.json");
|
||||
} else {
|
||||
try {
|
||||
is = new FileInputStream(path);
|
||||
} catch (FileNotFoundException e) {
|
||||
log.log(Level.SEVERE, "NOT FOUND {0}", path);
|
||||
log.errorv("NOT FOUND {0}", path);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-tomcat-integration-pom</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>2.5.1.Final-SNAPSHOT</version>
|
||||
<version>3.0.0.CR1</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-tomcat-integration-pom</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>2.5.1.Final-SNAPSHOT</version>
|
||||
<version>3.0.0.CR1</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-tomcat-integration-pom</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>2.5.1.Final-SNAPSHOT</version>
|
||||
<version>3.0.0.CR1</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>2.5.1.Final-SNAPSHOT</version>
|
||||
<version>3.0.0.CR1</version>
|
||||
<relativePath>../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>2.5.1.Final-SNAPSHOT</version>
|
||||
<version>3.0.0.CR1</version>
|
||||
<relativePath>../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<name>Keycloak WildFly Integration</name>
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<parent>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<version>2.5.1.Final-SNAPSHOT</version>
|
||||
<version>3.0.0.CR1</version>
|
||||
<relativePath>../../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>2.5.1.Final-SNAPSHOT</version>
|
||||
<version>3.0.0.CR1</version>
|
||||
<relativePath>../../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<parent>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<version>2.5.1.Final-SNAPSHOT</version>
|
||||
<version>3.0.0.CR1</version>
|
||||
<relativePath>../../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
||||
+1
-1
@@ -20,7 +20,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>2.5.1.Final-SNAPSHOT</version>
|
||||
<version>3.0.0.CR1</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<name>Keycloak Adapters</name>
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-saml-eap-integration-pom</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>2.5.1.Final-SNAPSHOT</version>
|
||||
<version>3.0.0.CR1</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
+10
-2
@@ -22,9 +22,10 @@ import org.apache.catalina.connector.Request;
|
||||
import org.apache.catalina.connector.Response;
|
||||
import org.apache.catalina.core.StandardContext;
|
||||
import org.apache.catalina.deploy.LoginConfig;
|
||||
|
||||
import org.keycloak.adapters.jbossweb.JBossWebPrincipalFactory;
|
||||
import org.keycloak.adapters.saml.AbstractSamlAuthenticatorValve;
|
||||
import org.keycloak.adapters.saml.SamlDeployment;
|
||||
import org.keycloak.adapters.saml.*;
|
||||
import org.keycloak.adapters.spi.SessionIdMapperUpdater;
|
||||
import org.keycloak.adapters.tomcat.GenericPrincipalFactory;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
@@ -71,4 +72,11 @@ public class SamlAuthenticatorValve extends AbstractSamlAuthenticatorValve {
|
||||
protected GenericPrincipalFactory createPrincipalFactory() {
|
||||
return new JBossWebPrincipalFactory();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addTokenStoreUpdaters() {
|
||||
context.addApplicationListenerInstance(new IdMapperUpdaterSessionListener(mapper));
|
||||
setIdMapperUpdater(SessionIdMapperUpdater.EXTERNAL);
|
||||
super.addTokenStoreUpdaters();
|
||||
}
|
||||
}
|
||||
+111
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* Copyright 2017 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.saml.jbossweb.infinispan;
|
||||
|
||||
import org.keycloak.adapters.spi.SessionIdMapper;
|
||||
import org.keycloak.adapters.spi.SessionIdMapperUpdater;
|
||||
|
||||
import javax.naming.InitialContext;
|
||||
import javax.naming.NamingException;
|
||||
import javax.servlet.ServletContext;
|
||||
import org.apache.catalina.Context;
|
||||
import org.infinispan.Cache;
|
||||
import org.infinispan.configuration.cache.CacheMode;
|
||||
import org.infinispan.configuration.cache.Configuration;
|
||||
import org.infinispan.manager.EmbeddedCacheManager;
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author hmlnarik
|
||||
*/
|
||||
public class InfinispanSessionCacheIdMapperUpdater {
|
||||
|
||||
private static final Logger LOG = Logger.getLogger(InfinispanSessionCacheIdMapperUpdater.class);
|
||||
|
||||
public static final String DEFAULT_CACHE_CONTAINER_JNDI_NAME = "java:jboss/infinispan/container/web";
|
||||
|
||||
private static final String DEPLOYMENT_CACHE_CONTAINER_JNDI_NAME_PARAM_NAME = "keycloak.sessionIdMapperUpdater.infinispan.cacheContainerJndi";
|
||||
private static final String DEPLOYMENT_CACHE_NAME_PARAM_NAME = "keycloak.sessionIdMapperUpdater.infinispan.deploymentCacheName";
|
||||
private static final String SSO_CACHE_NAME_PARAM_NAME = "keycloak.sessionIdMapperUpdater.infinispan.cacheName";
|
||||
|
||||
public static SessionIdMapperUpdater addTokenStoreUpdaters(Context context, SessionIdMapper mapper, SessionIdMapperUpdater previousIdMapperUpdater) {
|
||||
boolean distributable = context.getDistributable();
|
||||
|
||||
if (! distributable) {
|
||||
LOG.warnv("Deployment {0} does not use supported distributed session cache mechanism", context.getName());
|
||||
return previousIdMapperUpdater;
|
||||
}
|
||||
|
||||
ServletContext servletContext = context.getServletContext();
|
||||
String cacheContainerLookup = (servletContext != null && servletContext.getInitParameter(DEPLOYMENT_CACHE_CONTAINER_JNDI_NAME_PARAM_NAME) != null)
|
||||
? servletContext.getInitParameter(DEPLOYMENT_CACHE_CONTAINER_JNDI_NAME_PARAM_NAME)
|
||||
: DEFAULT_CACHE_CONTAINER_JNDI_NAME;
|
||||
|
||||
// the following is based on https://github.com/jbossas/jboss-as/blob/7.2.0.Final/clustering/web-infinispan/src/main/java/org/jboss/as/clustering/web/infinispan/DistributedCacheManagerFactory.java#L116-L122
|
||||
String host = context.getParent() == null ? "" : context.getParent().getName();
|
||||
String contextPath = context.getPath();
|
||||
if ("/".equals(contextPath)) {
|
||||
contextPath = "/ROOT";
|
||||
}
|
||||
|
||||
boolean deploymentSessionCacheNamePreset = servletContext != null && servletContext.getInitParameter(DEPLOYMENT_CACHE_NAME_PARAM_NAME) != null;
|
||||
String deploymentSessionCacheName = deploymentSessionCacheNamePreset
|
||||
? servletContext.getInitParameter(DEPLOYMENT_CACHE_NAME_PARAM_NAME)
|
||||
: host + contextPath;
|
||||
boolean ssoCacheNamePreset = servletContext != null && servletContext.getInitParameter(SSO_CACHE_NAME_PARAM_NAME) != null;
|
||||
String ssoCacheName = ssoCacheNamePreset
|
||||
? servletContext.getInitParameter(SSO_CACHE_NAME_PARAM_NAME)
|
||||
: deploymentSessionCacheName + ".ssoCache";
|
||||
|
||||
try {
|
||||
EmbeddedCacheManager cacheManager = (EmbeddedCacheManager) new InitialContext().lookup(cacheContainerLookup);
|
||||
|
||||
Configuration ssoCacheConfiguration = cacheManager.getCacheConfiguration(ssoCacheName);
|
||||
if (ssoCacheConfiguration == null) {
|
||||
Configuration cacheConfiguration = cacheManager.getCacheConfiguration(deploymentSessionCacheName);
|
||||
if (cacheConfiguration == null) {
|
||||
LOG.debugv("Using default cache container configuration for SSO cache. lookup={0}, looked up configuration of cache={1}", cacheContainerLookup, deploymentSessionCacheName);
|
||||
ssoCacheConfiguration = cacheManager.getDefaultCacheConfiguration();
|
||||
} else {
|
||||
LOG.debugv("Using distributed HTTP session cache configuration for SSO cache. lookup={0}, configuration taken from cache={1}", cacheContainerLookup, deploymentSessionCacheName);
|
||||
ssoCacheConfiguration = cacheConfiguration;
|
||||
cacheManager.defineConfiguration(ssoCacheName, ssoCacheConfiguration);
|
||||
}
|
||||
} else {
|
||||
LOG.debugv("Using custom configuration for SSO cache. lookup={0}, cache name={1}", cacheContainerLookup, ssoCacheName);
|
||||
}
|
||||
|
||||
CacheMode ssoCacheMode = ssoCacheConfiguration.clustering().cacheMode();
|
||||
if (ssoCacheMode != CacheMode.REPL_ASYNC && ssoCacheMode != CacheMode.REPL_SYNC) {
|
||||
LOG.warnv("SSO cache mode is {0}, it is recommended to use replicated mode instead", ssoCacheConfiguration.clustering().cacheModeString());
|
||||
}
|
||||
|
||||
Cache<String, String[]> ssoCache = cacheManager.getCache(ssoCacheName, true);
|
||||
ssoCache.addListener(new SsoSessionCacheListener(mapper));
|
||||
|
||||
LOG.debugv("Added distributed SSO session cache, lookup={0}, cache name={1}", cacheContainerLookup, deploymentSessionCacheName);
|
||||
|
||||
SsoCacheSessionIdMapperUpdater updater = new SsoCacheSessionIdMapperUpdater(ssoCache, previousIdMapperUpdater);
|
||||
|
||||
return updater;
|
||||
} catch (NamingException ex) {
|
||||
LOG.warnv("Failed to obtain distributed session cache container, lookup={0}", cacheContainerLookup);
|
||||
return previousIdMapperUpdater;
|
||||
}
|
||||
}
|
||||
}
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright 2017 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.saml.jbossweb.infinispan;
|
||||
|
||||
import org.keycloak.adapters.spi.SessionIdMapper;
|
||||
import org.keycloak.adapters.spi.SessionIdMapperUpdater;
|
||||
|
||||
import org.infinispan.Cache;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author hmlnarik
|
||||
*/
|
||||
public class SsoCacheSessionIdMapperUpdater implements SessionIdMapperUpdater {
|
||||
|
||||
private final SessionIdMapperUpdater delegate;
|
||||
/**
|
||||
* Cache where key is a HTTP session ID, and value is a pair (user session ID, principal name) of Strings.
|
||||
*/
|
||||
private final Cache<String, String[]> httpSessionToSsoCache;
|
||||
|
||||
public SsoCacheSessionIdMapperUpdater(Cache<String, String[]> httpSessionToSsoCache, SessionIdMapperUpdater previousIdMapperUpdater) {
|
||||
this.delegate = previousIdMapperUpdater;
|
||||
this.httpSessionToSsoCache = httpSessionToSsoCache;
|
||||
}
|
||||
|
||||
// SessionIdMapperUpdater methods
|
||||
|
||||
@Override
|
||||
public void clear(SessionIdMapper idMapper) {
|
||||
httpSessionToSsoCache.clear();
|
||||
this.delegate.clear(idMapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void map(SessionIdMapper idMapper, String sso, String principal, String httpSessionId) {
|
||||
httpSessionToSsoCache.put(httpSessionId, new String[] {sso, principal});
|
||||
this.delegate.map(idMapper, sso, principal, httpSessionId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeSession(SessionIdMapper idMapper, String httpSessionId) {
|
||||
httpSessionToSsoCache.remove(httpSessionId);
|
||||
this.delegate.removeSession(idMapper, httpSessionId);
|
||||
}
|
||||
}
|
||||
+156
@@ -0,0 +1,156 @@
|
||||
/*
|
||||
* Copyright 2017 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.saml.jbossweb.infinispan;
|
||||
|
||||
import org.keycloak.adapters.spi.SessionIdMapper;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.*;
|
||||
import org.infinispan.notifications.Listener;
|
||||
import org.infinispan.notifications.cachelistener.annotation.*;
|
||||
import org.infinispan.notifications.cachelistener.event.*;
|
||||
import org.infinispan.notifications.cachemanagerlistener.annotation.CacheStarted;
|
||||
import org.infinispan.notifications.cachemanagerlistener.annotation.CacheStopped;
|
||||
import org.infinispan.notifications.cachemanagerlistener.event.CacheStartedEvent;
|
||||
import org.infinispan.notifications.cachemanagerlistener.event.CacheStoppedEvent;
|
||||
import org.infinispan.transaction.xa.GlobalTransaction;
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author hmlnarik
|
||||
*/
|
||||
@Listener
|
||||
public class SsoSessionCacheListener {
|
||||
|
||||
private static final Logger LOG = Logger.getLogger(SsoSessionCacheListener.class);
|
||||
|
||||
private final ConcurrentMap<GlobalTransaction, Queue<Event>> map = new ConcurrentHashMap<>();
|
||||
|
||||
private final SessionIdMapper idMapper;
|
||||
|
||||
private ExecutorService executor = Executors.newSingleThreadExecutor();
|
||||
|
||||
public SsoSessionCacheListener(SessionIdMapper idMapper) {
|
||||
this.idMapper = idMapper;
|
||||
}
|
||||
|
||||
@TransactionRegistered
|
||||
public void startTransaction(TransactionRegisteredEvent event) {
|
||||
map.put(event.getGlobalTransaction(), new ConcurrentLinkedQueue<Event>());
|
||||
}
|
||||
|
||||
@CacheStarted
|
||||
public void cacheStarted(CacheStartedEvent event) {
|
||||
this.executor = Executors.newSingleThreadExecutor();
|
||||
}
|
||||
|
||||
@CacheStopped
|
||||
public void cacheStopped(CacheStoppedEvent event) {
|
||||
this.executor.shutdownNow();
|
||||
}
|
||||
|
||||
@CacheEntryCreated
|
||||
@CacheEntryRemoved
|
||||
@CacheEntryModified
|
||||
public void addEvent(TransactionalEvent event) {
|
||||
if (event.isPre() == false) {
|
||||
map.get(event.getGlobalTransaction()).add(event);
|
||||
}
|
||||
}
|
||||
|
||||
@TransactionCompleted
|
||||
public void endTransaction(TransactionCompletedEvent event) {
|
||||
Queue<Event> events = map.remove(event.getGlobalTransaction());
|
||||
|
||||
if (events == null || ! event.isTransactionSuccessful()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (event.isOriginLocal()) {
|
||||
// Local events are processed by local HTTP session listener
|
||||
return;
|
||||
}
|
||||
|
||||
for (final Event e : events) {
|
||||
switch (e.getType()) {
|
||||
case CACHE_ENTRY_CREATED:
|
||||
this.executor.submit(new Runnable() {
|
||||
@Override public void run() {
|
||||
cacheEntryCreated((CacheEntryCreatedEvent) e);
|
||||
}
|
||||
});
|
||||
break;
|
||||
|
||||
case CACHE_ENTRY_MODIFIED:
|
||||
this.executor.submit(new Runnable() {
|
||||
@Override public void run() {
|
||||
cacheEntryModified((CacheEntryModifiedEvent) e);
|
||||
}
|
||||
});
|
||||
break;
|
||||
|
||||
case CACHE_ENTRY_REMOVED:
|
||||
this.executor.submit(new Runnable() {
|
||||
@Override public void run() {
|
||||
cacheEntryRemoved((CacheEntryRemovedEvent) e);
|
||||
}
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void cacheEntryCreated(CacheEntryCreatedEvent event) {
|
||||
if (! (event.getKey() instanceof String) || ! (event.getValue() instanceof String[])) {
|
||||
return;
|
||||
}
|
||||
String httpSessionId = (String) event.getKey();
|
||||
String[] value = (String[]) event.getValue();
|
||||
String ssoId = value[0];
|
||||
String principal = value[1];
|
||||
|
||||
LOG.tracev("cacheEntryCreated {0}:{1}", httpSessionId, ssoId);
|
||||
|
||||
this.idMapper.map(ssoId, principal, httpSessionId);
|
||||
}
|
||||
|
||||
private void cacheEntryModified(CacheEntryModifiedEvent event) {
|
||||
if (! (event.getKey() instanceof String) || ! (event.getValue() instanceof String[])) {
|
||||
return;
|
||||
}
|
||||
String httpSessionId = (String) event.getKey();
|
||||
String[] value = (String[]) event.getValue();
|
||||
String ssoId = value[0];
|
||||
String principal = value[1];
|
||||
|
||||
LOG.tracev("cacheEntryModified {0}:{1}", httpSessionId, ssoId);
|
||||
|
||||
this.idMapper.removeSession(httpSessionId);
|
||||
this.idMapper.map(ssoId, principal, httpSessionId);
|
||||
}
|
||||
|
||||
private void cacheEntryRemoved(CacheEntryRemovedEvent event) {
|
||||
if (! (event.getKey() instanceof String)) {
|
||||
return;
|
||||
}
|
||||
|
||||
LOG.tracev("cacheEntryRemoved {0}", event.getKey());
|
||||
|
||||
this.idMapper.removeSession((String) event.getKey());
|
||||
}
|
||||
}
|
||||
@@ -20,7 +20,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>2.5.1.Final-SNAPSHOT</version>
|
||||
<version>3.0.0.CR1</version>
|
||||
<relativePath>../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<name>Keycloak SAML EAP Integration</name>
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<parent>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-saml-eap-integration-pom</artifactId>
|
||||
<version>2.5.1.Final-SNAPSHOT</version>
|
||||
<version>3.0.0.CR1</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>2.5.1.Final-SNAPSHOT</version>
|
||||
<version>3.0.0.CR1</version>
|
||||
<relativePath>../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>2.5.1.Final-SNAPSHOT</version>
|
||||
<version>3.0.0.CR1</version>
|
||||
<relativePath>../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@@ -308,7 +308,7 @@
|
||||
</xs:attribute>
|
||||
<xs:attribute name="signatureCanonicalizationMethod" type="xs:string" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation>This is the signature canonicalization method that the IDP expects signed documents to use. The default value is http://www.w3.org/2001/10/xml-exc-c14n# and should be good for most IDPs.</xs:documentation>
|
||||
<xs:documentation>This is the signature canonicalization method that the IDP expects signed documents to use. The default value is https://www.w3.org/2001/10/xml-exc-c14n# and should be good for most IDPs.</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="encryption" type="xs:boolean" use="optional">
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>2.5.1.Final-SNAPSHOT</version>
|
||||
<version>3.0.0.CR1</version>
|
||||
<relativePath>../../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
+3
-1
@@ -104,12 +104,14 @@ public abstract class AbstractSamlAuthenticator extends LoginAuthenticator {
|
||||
|
||||
protected JettySamlSessionStore createJettySamlSessionStore(Request request, HttpFacade facade, SamlDeployment resolvedDeployment) {
|
||||
JettySamlSessionStore store;
|
||||
store = new JettySamlSessionStore(request, createSessionTokenStore(request, resolvedDeployment), facade, idMapper, new JettyUserSessionManagement(request.getSessionManager()), resolvedDeployment);
|
||||
store = new JettySamlSessionStore(request, createSessionTokenStore(request, resolvedDeployment), facade, idMapper, createSessionManagement(request), resolvedDeployment);
|
||||
return store;
|
||||
}
|
||||
|
||||
public abstract AdapterSessionStore createSessionTokenStore(Request request, SamlDeployment resolvedDeployment);
|
||||
|
||||
public abstract JettyUserSessionManagement createSessionManagement(Request request);
|
||||
|
||||
public void logoutCurrent(Request request) {
|
||||
JettyHttpFacade facade = new JettyHttpFacade(request, null);
|
||||
SamlDeployment deployment = deploymentContext.resolveDeployment(facade);
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>2.5.1.Final-SNAPSHOT</version>
|
||||
<version>3.0.0.CR1</version>
|
||||
<relativePath>../../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
+15
-9
@@ -15,20 +15,26 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.models.mongo.keycloak.entities;
|
||||
package org.keycloak.adapters.saml.jetty;
|
||||
|
||||
import org.keycloak.connections.mongo.api.MongoCollection;
|
||||
import org.keycloak.connections.mongo.api.MongoIdentifiableEntity;
|
||||
import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext;
|
||||
import org.eclipse.jetty.server.SessionManager;
|
||||
import org.keycloak.adapters.jetty.spi.JettySessionManager;
|
||||
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bburke@redhat.com">Bill Burke</a>
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
@MongoCollection(collectionName = "clientTemplates")
|
||||
public class MongoClientTemplateEntity extends ClientTemplateEntity implements MongoIdentifiableEntity {
|
||||
public class Jetty8SessionManager implements JettySessionManager {
|
||||
protected SessionManager sessionManager;
|
||||
|
||||
public Jetty8SessionManager(SessionManager sessionManager) {
|
||||
this.sessionManager = sessionManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterRemove(MongoStoreInvocationContext context) {
|
||||
|
||||
public HttpSession getHttpSession(String id) {
|
||||
return sessionManager.getHttpSession(id);
|
||||
}
|
||||
}
|
||||
+6
@@ -21,6 +21,7 @@ import org.eclipse.jetty.server.AbstractHttpConnection;
|
||||
import org.eclipse.jetty.server.Authentication;
|
||||
import org.eclipse.jetty.server.Request;
|
||||
import org.eclipse.jetty.server.UserIdentity;
|
||||
import org.keycloak.adapters.jetty.spi.JettyUserSessionManagement;
|
||||
import org.keycloak.adapters.saml.SamlDeployment;
|
||||
import org.keycloak.adapters.spi.AdapterSessionStore;
|
||||
|
||||
@@ -42,6 +43,11 @@ public class KeycloakSamlAuthenticator extends AbstractSamlAuthenticator {
|
||||
return new JettyAdapterSessionStore(request);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JettyUserSessionManagement createSessionManagement(Request request) {
|
||||
return new JettyUserSessionManagement(new Jetty8SessionManager(request.getSessionManager()));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Request resolveRequest(ServletRequest req) {
|
||||
return (req instanceof Request)?(Request)req: AbstractHttpConnection.getCurrentConnection().getRequest();
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>2.5.1.Final-SNAPSHOT</version>
|
||||
<version>3.0.0.CR1</version>
|
||||
<relativePath>../../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* 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.saml.jetty;
|
||||
|
||||
import org.eclipse.jetty.server.SessionManager;
|
||||
import org.keycloak.adapters.jetty.spi.JettySessionManager;
|
||||
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class Jetty9SessionManager implements JettySessionManager {
|
||||
protected SessionManager sessionManager;
|
||||
|
||||
public Jetty9SessionManager(SessionManager sessionManager) {
|
||||
this.sessionManager = sessionManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpSession getHttpSession(String id) {
|
||||
return sessionManager.getHttpSession(id);
|
||||
}
|
||||
}
|
||||
+6
-1
@@ -44,6 +44,11 @@ public class KeycloakSamlAuthenticator extends AbstractSamlAuthenticator {
|
||||
return new JettyAdapterSessionStore(request);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JettyUserSessionManagement createSessionManagement(Request request) {
|
||||
return new JettyUserSessionManagement(new Jetty9SessionManager(request.getSessionManager()));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Request resolveRequest(ServletRequest req) {
|
||||
return (req instanceof Request) ? (Request)req : HttpChannel.getCurrentHttpChannel().getRequest();
|
||||
@@ -62,7 +67,7 @@ public class KeycloakSamlAuthenticator extends AbstractSamlAuthenticator {
|
||||
@Override
|
||||
protected JettySamlSessionStore createJettySamlSessionStore(Request request, HttpFacade facade, SamlDeployment resolvedDeployment) {
|
||||
JettySamlSessionStore store;
|
||||
store = new Jetty9SamlSessionStore(request, createSessionTokenStore(request, resolvedDeployment), facade, idMapper, new JettyUserSessionManagement(request.getSessionManager()), resolvedDeployment);
|
||||
store = new Jetty9SamlSessionStore(request, createSessionTokenStore(request, resolvedDeployment), facade, idMapper, createSessionManagement(request), resolvedDeployment);
|
||||
return store;
|
||||
}
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>2.5.1.Final-SNAPSHOT</version>
|
||||
<version>3.0.0.CR1</version>
|
||||
<relativePath>../../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* 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.saml.jetty;
|
||||
|
||||
import org.eclipse.jetty.server.SessionManager;
|
||||
import org.keycloak.adapters.jetty.spi.JettySessionManager;
|
||||
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class Jetty9SessionManager implements JettySessionManager {
|
||||
protected SessionManager sessionManager;
|
||||
|
||||
public Jetty9SessionManager(SessionManager sessionManager) {
|
||||
this.sessionManager = sessionManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpSession getHttpSession(String id) {
|
||||
return sessionManager.getHttpSession(id);
|
||||
}
|
||||
}
|
||||
+6
-1
@@ -59,10 +59,15 @@ public class KeycloakSamlAuthenticator extends AbstractSamlAuthenticator {
|
||||
return new JettyAdapterSessionStore(request);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JettyUserSessionManagement createSessionManagement(Request request) {
|
||||
return new JettyUserSessionManagement(new Jetty9SessionManager(request.getSessionManager()));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected JettySamlSessionStore createJettySamlSessionStore(Request request, HttpFacade facade, SamlDeployment resolvedDeployment) {
|
||||
JettySamlSessionStore store;
|
||||
store = new Jetty9SamlSessionStore(request, createSessionTokenStore(request, resolvedDeployment), facade, idMapper, new JettyUserSessionManagement(request.getSessionManager()), resolvedDeployment);
|
||||
store = new Jetty9SamlSessionStore(request, createSessionTokenStore(request, resolvedDeployment), facade, idMapper, createSessionManagement(request), resolvedDeployment);
|
||||
return store;
|
||||
}
|
||||
}
|
||||
@@ -21,7 +21,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>2.5.1.Final-SNAPSHOT</version>
|
||||
<version>3.0.0.CR1</version>
|
||||
<relativePath>../../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* 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.saml.jetty;
|
||||
|
||||
import org.eclipse.jetty.server.SessionManager;
|
||||
import org.keycloak.adapters.jetty.spi.JettySessionManager;
|
||||
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class Jetty9SessionManager implements JettySessionManager {
|
||||
protected SessionManager sessionManager;
|
||||
|
||||
public Jetty9SessionManager(SessionManager sessionManager) {
|
||||
this.sessionManager = sessionManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpSession getHttpSession(String id) {
|
||||
return sessionManager.getHttpSession(id);
|
||||
}
|
||||
}
|
||||
+6
-1
@@ -58,10 +58,15 @@ public class KeycloakSamlAuthenticator extends AbstractSamlAuthenticator {
|
||||
return new JettyAdapterSessionStore(request);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JettyUserSessionManagement createSessionManagement(Request request) {
|
||||
return new JettyUserSessionManagement(new Jetty9SessionManager(request.getSessionManager()));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected JettySamlSessionStore createJettySamlSessionStore(Request request, HttpFacade facade, SamlDeployment resolvedDeployment) {
|
||||
JettySamlSessionStore store;
|
||||
store = new Jetty9SamlSessionStore(request, createSessionTokenStore(request, resolvedDeployment), facade, idMapper, new JettyUserSessionManagement(request.getSessionManager()), resolvedDeployment);
|
||||
store = new Jetty9SamlSessionStore(request, createSessionTokenStore(request, resolvedDeployment), facade, idMapper, createSessionManagement(request), resolvedDeployment);
|
||||
return store;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,162 @@
|
||||
<?xml version="1.0"?>
|
||||
<!--
|
||||
~ 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.
|
||||
-->
|
||||
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>3.0.0.CR1</version>
|
||||
<relativePath>../../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>keycloak-saml-jetty94-adapter</artifactId>
|
||||
<name>Keycloak Jetty 9.4.x SAML Integration</name>
|
||||
<properties>
|
||||
<jetty9.version>9.4.2.v20170220</jetty9.version>
|
||||
<keycloak.osgi.export>
|
||||
org.keycloak.adapters.jetty.*
|
||||
</keycloak.osgi.export>
|
||||
<keycloak.osgi.import>
|
||||
org.eclipse.jetty.*;resolution:=optional,
|
||||
javax.servlet.*;version="[3.0,4)";resolution:=optional,
|
||||
org.keycloak.*;version="${project.version}",
|
||||
*;resolution:=optional
|
||||
</keycloak.osgi.import>
|
||||
</properties>
|
||||
<description />
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.jboss.logging</groupId>
|
||||
<artifactId>jboss-logging</artifactId>
|
||||
<version>${jboss.logging.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-common</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.bouncycastle</groupId>
|
||||
<artifactId>bcprov-jdk15on</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-saml-adapter-api-public</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-saml-adapter-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-adapter-spi</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-saml-jetty-adapter-core</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-server</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-util</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-security</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-server</artifactId>
|
||||
<version>${jetty9.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-util</artifactId>
|
||||
<version>${jetty9.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-security</artifactId>
|
||||
<version>${jetty9.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<source>1.6</source>
|
||||
<target>1.6</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<!-- Adding OSGI metadata to the JAR without changing the packaging type. -->
|
||||
<plugin>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<configuration>
|
||||
<archive>
|
||||
<manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile>
|
||||
</archive>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.felix</groupId>
|
||||
<artifactId>maven-bundle-plugin</artifactId>
|
||||
<extensions>true</extensions>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>bundle-manifest</id>
|
||||
<phase>process-classes</phase>
|
||||
<goals>
|
||||
<goal>manifest</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<instructions>
|
||||
<Bundle-ClassPath>.</Bundle-ClassPath>
|
||||
<Bundle-Name>${project.name}</Bundle-Name>
|
||||
<Bundle-SymbolicName>${project.groupId}.${project.artifactId}</Bundle-SymbolicName>
|
||||
<Import-Package>${keycloak.osgi.import}</Import-Package>
|
||||
<Export-Package>${keycloak.osgi.export}</Export-Package>
|
||||
</instructions>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* 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.saml.jetty;
|
||||
|
||||
import org.eclipse.jetty.server.Request;
|
||||
import org.keycloak.adapters.jetty.spi.JettyUserSessionManagement;
|
||||
import org.keycloak.adapters.saml.SamlDeployment;
|
||||
import org.keycloak.adapters.spi.AdapterSessionStore;
|
||||
import org.keycloak.adapters.spi.HttpFacade;
|
||||
import org.keycloak.adapters.spi.SessionIdMapper;
|
||||
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class Jetty9SamlSessionStore extends JettySamlSessionStore {
|
||||
public Jetty9SamlSessionStore(Request request, AdapterSessionStore sessionStore, HttpFacade facade, SessionIdMapper idMapper, JettyUserSessionManagement sessionManagement, SamlDeployment deployment) {
|
||||
super(request, sessionStore, facade, idMapper, sessionManagement, deployment);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String changeSessionId(HttpSession session) {
|
||||
Request request = this.request;
|
||||
if (!deployment.turnOffChangeSessionIdOnLogin()) return request.changeSessionId();
|
||||
else return session.getId();
|
||||
}
|
||||
}
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* 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.saml.jetty;
|
||||
|
||||
import org.eclipse.jetty.server.session.SessionHandler;
|
||||
import org.keycloak.adapters.jetty.spi.JettySessionManager;
|
||||
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class Jetty9SessionManager implements JettySessionManager {
|
||||
protected SessionHandler sessionHandler;
|
||||
|
||||
public Jetty9SessionManager(SessionHandler sessionHandler) {
|
||||
this.sessionHandler = sessionHandler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HttpSession getHttpSession(String id) {
|
||||
return sessionHandler.getHttpSession(id);
|
||||
}
|
||||
}
|
||||
+111
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* 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.saml.jetty;
|
||||
|
||||
import org.eclipse.jetty.security.authentication.FormAuthenticator;
|
||||
import org.eclipse.jetty.server.Request;
|
||||
import org.eclipse.jetty.util.MultiMap;
|
||||
import org.keycloak.adapters.jetty.spi.JettyHttpFacade;
|
||||
import org.keycloak.adapters.spi.AdapterSessionStore;
|
||||
import org.keycloak.common.util.MultivaluedHashMap;
|
||||
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class JettyAdapterSessionStore implements AdapterSessionStore {
|
||||
public static final String CACHED_FORM_PARAMETERS = "__CACHED_FORM_PARAMETERS";
|
||||
protected Request myRequest;
|
||||
|
||||
public JettyAdapterSessionStore(Request request) {
|
||||
this.myRequest = request; // for IDE/compilation purposes
|
||||
}
|
||||
|
||||
protected MultiMap<String> extractFormParameters(Request base_request) {
|
||||
MultiMap<String> formParameters = new MultiMap<String>();
|
||||
base_request.extractFormParameters(formParameters);
|
||||
return formParameters;
|
||||
}
|
||||
protected void restoreFormParameters(MultiMap<String> j_post, Request base_request) {
|
||||
base_request.setContentParameters(j_post);
|
||||
}
|
||||
|
||||
public boolean restoreRequest() {
|
||||
HttpSession session = myRequest.getSession(false);
|
||||
if (session == null) return false;
|
||||
synchronized (session) {
|
||||
String j_uri = (String) session.getAttribute(FormAuthenticator.__J_URI);
|
||||
if (j_uri != null) {
|
||||
// check if the request is for the same url as the original and restore
|
||||
// params if it was a post
|
||||
StringBuffer buf = myRequest.getRequestURL();
|
||||
if (myRequest.getQueryString() != null)
|
||||
buf.append("?").append(myRequest.getQueryString());
|
||||
if (j_uri.equals(buf.toString())) {
|
||||
String method = (String)session.getAttribute(JettyHttpFacade.__J_METHOD);
|
||||
myRequest.setMethod(method);
|
||||
MultivaluedHashMap<String, String> j_post = (MultivaluedHashMap<String, String>) session.getAttribute(CACHED_FORM_PARAMETERS);
|
||||
if (j_post != null) {
|
||||
myRequest.setContentType("application/x-www-form-urlencoded");
|
||||
MultiMap<String> map = new MultiMap<String>();
|
||||
for (String key : j_post.keySet()) {
|
||||
for (String val : j_post.getList(key)) {
|
||||
map.add(key, val);
|
||||
}
|
||||
}
|
||||
restoreFormParameters(map, myRequest);
|
||||
}
|
||||
session.removeAttribute(FormAuthenticator.__J_URI);
|
||||
session.removeAttribute(JettyHttpFacade.__J_METHOD);
|
||||
session.removeAttribute(FormAuthenticator.__J_POST);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void saveRequest() {
|
||||
// remember the current URI
|
||||
HttpSession session = myRequest.getSession();
|
||||
synchronized (session) {
|
||||
// But only if it is not set already, or we save every uri that leads to a login form redirect
|
||||
if (session.getAttribute(FormAuthenticator.__J_URI) == null) {
|
||||
StringBuffer buf = myRequest.getRequestURL();
|
||||
if (myRequest.getQueryString() != null)
|
||||
buf.append("?").append(myRequest.getQueryString());
|
||||
session.setAttribute(FormAuthenticator.__J_URI, buf.toString());
|
||||
session.setAttribute(JettyHttpFacade.__J_METHOD, myRequest.getMethod());
|
||||
|
||||
if ("application/x-www-form-urlencoded".equals(myRequest.getContentType()) && "POST".equalsIgnoreCase(myRequest.getMethod())) {
|
||||
MultiMap<String> formParameters = extractFormParameters(myRequest);
|
||||
MultivaluedHashMap<String, String> map = new MultivaluedHashMap<String, String>();
|
||||
for (String key : formParameters.keySet()) {
|
||||
for (Object value : formParameters.getValues(key)) {
|
||||
map.add(key, (String) value);
|
||||
}
|
||||
}
|
||||
session.setAttribute(CACHED_FORM_PARAMETERS, map);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+72
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* 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.saml.jetty;
|
||||
|
||||
import org.eclipse.jetty.server.Authentication;
|
||||
import org.eclipse.jetty.server.Request;
|
||||
import org.eclipse.jetty.server.UserIdentity;
|
||||
import org.keycloak.adapters.jetty.spi.JettyUserSessionManagement;
|
||||
import org.keycloak.adapters.saml.SamlDeployment;
|
||||
import org.keycloak.adapters.spi.AdapterSessionStore;
|
||||
import org.keycloak.adapters.spi.HttpFacade;
|
||||
|
||||
import javax.servlet.ServletRequest;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class KeycloakSamlAuthenticator extends AbstractSamlAuthenticator {
|
||||
|
||||
public KeycloakSamlAuthenticator() {
|
||||
super();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected Request resolveRequest(ServletRequest req) {
|
||||
return Request.getBaseRequest(req);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Authentication createAuthentication(UserIdentity userIdentity, final Request request) {
|
||||
return new KeycloakAuthentication(getAuthMethod(), userIdentity) {
|
||||
@Override
|
||||
public void logout() {
|
||||
logoutCurrent(request);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public AdapterSessionStore createSessionTokenStore(Request request, SamlDeployment resolvedDeployment) {
|
||||
return new JettyAdapterSessionStore(request);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JettyUserSessionManagement createSessionManagement(Request request) {
|
||||
return new JettyUserSessionManagement(new Jetty9SessionManager(request.getSessionHandler()));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected JettySamlSessionStore createJettySamlSessionStore(Request request, HttpFacade facade, SamlDeployment resolvedDeployment) {
|
||||
JettySamlSessionStore store;
|
||||
store = new Jetty9SamlSessionStore(request, createSessionTokenStore(request, resolvedDeployment), facade, idMapper, createSessionManagement(request), resolvedDeployment);
|
||||
return store;
|
||||
}
|
||||
}
|
||||
@@ -20,7 +20,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>2.5.1.Final-SNAPSHOT</version>
|
||||
<version>3.0.0.CR1</version>
|
||||
<relativePath>../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<name>Keycloak SAML Jetty Integration</name>
|
||||
@@ -36,5 +36,6 @@
|
||||
<module>jetty9.1</module>
|
||||
<module>jetty9.2</module>
|
||||
<module>jetty9.3</module>
|
||||
<module>jetty9.4</module>
|
||||
</modules>
|
||||
</project>
|
||||
@@ -20,7 +20,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>2.5.1.Final-SNAPSHOT</version>
|
||||
<version>3.0.0.CR1</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<name>Keycloak SAML Client Adapter Modules</name>
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>2.5.1.Final-SNAPSHOT</version>
|
||||
<version>3.0.0.CR1</version>
|
||||
<relativePath>../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>2.5.1.Final-SNAPSHOT</version>
|
||||
<version>3.0.0.CR1</version>
|
||||
<relativePath>../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<name>Keycloak SAML Tomcat Integration</name>
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-saml-tomcat-integration-pom</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>2.5.1.Final-SNAPSHOT</version>
|
||||
<version>3.0.0.CR1</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
+83
-23
@@ -24,13 +24,11 @@ import org.apache.catalina.LifecycleListener;
|
||||
import org.apache.catalina.authenticator.FormAuthenticator;
|
||||
import org.apache.catalina.connector.Request;
|
||||
import org.apache.catalina.connector.Response;
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import org.keycloak.adapters.saml.config.parsers.DeploymentBuilder;
|
||||
import org.keycloak.adapters.saml.config.parsers.ResourceLoader;
|
||||
import org.keycloak.adapters.spi.AuthChallenge;
|
||||
import org.keycloak.adapters.spi.AuthOutcome;
|
||||
import org.keycloak.adapters.spi.HttpFacade;
|
||||
import org.keycloak.adapters.spi.InMemorySessionIdMapper;
|
||||
import org.keycloak.adapters.spi.SessionIdMapper;
|
||||
import org.keycloak.adapters.spi.*;
|
||||
import org.keycloak.adapters.tomcat.CatalinaHttpFacade;
|
||||
import org.keycloak.adapters.tomcat.CatalinaUserSessionManagement;
|
||||
import org.keycloak.adapters.tomcat.GenericPrincipalFactory;
|
||||
@@ -45,8 +43,8 @@ import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import java.lang.reflect.*;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Keycloak authentication valve
|
||||
@@ -59,10 +57,11 @@ public abstract class AbstractSamlAuthenticatorValve extends FormAuthenticator i
|
||||
|
||||
public static final String TOKEN_STORE_NOTE = "TOKEN_STORE_NOTE";
|
||||
|
||||
private final static Logger log = Logger.getLogger(""+AbstractSamlAuthenticatorValve.class);
|
||||
private final static Logger log = Logger.getLogger(AbstractSamlAuthenticatorValve.class);
|
||||
protected CatalinaUserSessionManagement userSessionManagement = new CatalinaUserSessionManagement();
|
||||
protected SamlDeploymentContext deploymentContext;
|
||||
protected SessionIdMapper mapper = new InMemorySessionIdMapper();
|
||||
protected SessionIdMapperUpdater idMapperUpdater = SessionIdMapperUpdater.DIRECT;
|
||||
|
||||
@Override
|
||||
public void lifecycleEvent(LifecycleEvent event) {
|
||||
@@ -70,7 +69,7 @@ public abstract class AbstractSamlAuthenticatorValve extends FormAuthenticator i
|
||||
cache = false;
|
||||
} else if (Lifecycle.AFTER_START_EVENT.equals(event.getType())) {
|
||||
keycloakInit();
|
||||
} else if (event.getType() == Lifecycle.BEFORE_STOP_EVENT) {
|
||||
} else if (Lifecycle.BEFORE_STOP_EVENT.equals(event.getType())) {
|
||||
beforeStop();
|
||||
}
|
||||
}
|
||||
@@ -103,14 +102,14 @@ public abstract class AbstractSamlAuthenticatorValve extends FormAuthenticator i
|
||||
//deploymentContext = new SamlDeploymentContext(configResolver);
|
||||
//log.log(Level.INFO, "Using {0} to resolve Keycloak configuration on a per-request basis.", configResolverClass);
|
||||
} catch (Exception ex) {
|
||||
log.log(Level.FINE, "The specified resolver {0} could NOT be loaded. Keycloak is unconfigured and will deny all requests. Reason: {1}", new Object[]{configResolverClass, ex.getMessage()});
|
||||
log.errorv("The specified resolver {0} could NOT be loaded. Keycloak is unconfigured and will deny all requests. Reason: {1}", configResolverClass, ex.getMessage());
|
||||
//deploymentContext = new AdapterDeploymentContext(new KeycloakDeployment());
|
||||
}
|
||||
} else {
|
||||
InputStream is = getConfigInputStream(context);
|
||||
final SamlDeployment deployment;
|
||||
if (is == null) {
|
||||
log.info("No adapter configuration. Keycloak is unconfigured and will deny all requests.");
|
||||
log.error("No adapter configuration. Keycloak is unconfigured and will deny all requests.");
|
||||
deployment = new DefaultSamlDeployment();
|
||||
} else {
|
||||
try {
|
||||
@@ -126,10 +125,12 @@ public abstract class AbstractSamlAuthenticatorValve extends FormAuthenticator i
|
||||
}
|
||||
}
|
||||
deploymentContext = new SamlDeploymentContext(deployment);
|
||||
log.fine("Keycloak is using a per-deployment configuration.");
|
||||
log.debug("Keycloak is using a per-deployment configuration.");
|
||||
}
|
||||
|
||||
context.getServletContext().setAttribute(SamlDeploymentContext.class.getName(), deploymentContext);
|
||||
|
||||
addTokenStoreUpdaters();
|
||||
}
|
||||
|
||||
protected void beforeStop() {
|
||||
@@ -140,8 +141,7 @@ public abstract class AbstractSamlAuthenticatorValve extends FormAuthenticator i
|
||||
if (xml == null) {
|
||||
return null;
|
||||
}
|
||||
log.finest("**** using " + AdapterConstants.AUTH_DATA_PARAM_NAME);
|
||||
log.finest(xml);
|
||||
log.trace("**** using " + AdapterConstants.AUTH_DATA_PARAM_NAME);
|
||||
return new ByteArrayInputStream(xml.getBytes());
|
||||
}
|
||||
|
||||
@@ -150,13 +150,13 @@ public abstract class AbstractSamlAuthenticatorValve extends FormAuthenticator i
|
||||
if (is == null) {
|
||||
String path = context.getServletContext().getInitParameter("keycloak.config.file");
|
||||
if (path == null) {
|
||||
log.fine("**** using /WEB-INF/keycloak-saml.xml");
|
||||
log.trace("**** using /WEB-INF/keycloak-saml.xml");
|
||||
is = context.getServletContext().getResourceAsStream("/WEB-INF/keycloak-saml.xml");
|
||||
} else {
|
||||
try {
|
||||
is = new FileInputStream(path);
|
||||
} catch (FileNotFoundException e) {
|
||||
log.log(Level.SEVERE, "NOT FOUND {0}", path);
|
||||
log.errorv("NOT FOUND {0}", path);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
@@ -166,7 +166,7 @@ public abstract class AbstractSamlAuthenticatorValve extends FormAuthenticator i
|
||||
|
||||
@Override
|
||||
public void invoke(Request request, Response response) throws IOException, ServletException {
|
||||
log.fine("*********************** SAML ************");
|
||||
log.trace("*********************** SAML ************");
|
||||
CatalinaHttpFacade facade = new CatalinaHttpFacade(response, request);
|
||||
SamlDeployment deployment = deploymentContext.resolveDeployment(facade);
|
||||
if (request.getRequestURI().substring(request.getContextPath().length()).endsWith("/saml")) {
|
||||
@@ -208,11 +208,11 @@ public abstract class AbstractSamlAuthenticatorValve extends FormAuthenticator i
|
||||
}
|
||||
|
||||
protected boolean authenticateInternal(Request request, HttpServletResponse response, Object loginConfig) throws IOException {
|
||||
log.fine("authenticateInternal");
|
||||
log.trace("authenticateInternal");
|
||||
CatalinaHttpFacade facade = new CatalinaHttpFacade(response, request);
|
||||
SamlDeployment deployment = deploymentContext.resolveDeployment(facade);
|
||||
if (deployment == null || !deployment.isConfigured()) {
|
||||
log.fine("deployment not configured");
|
||||
log.trace("deployment not configured");
|
||||
return false;
|
||||
}
|
||||
SamlSessionStore tokenStore = getSessionStore(request, facade, deployment);
|
||||
@@ -225,7 +225,7 @@ public abstract class AbstractSamlAuthenticatorValve extends FormAuthenticator i
|
||||
protected boolean executeAuthenticator(Request request, HttpServletResponse response, CatalinaHttpFacade facade, SamlDeployment deployment, SamlAuthenticator authenticator) {
|
||||
AuthOutcome outcome = authenticator.authenticate();
|
||||
if (outcome == AuthOutcome.AUTHENTICATED) {
|
||||
log.fine("AUTHENTICATED");
|
||||
log.trace("AUTHENTICATED");
|
||||
if (facade.isEnded()) {
|
||||
return false;
|
||||
}
|
||||
@@ -237,13 +237,13 @@ public abstract class AbstractSamlAuthenticatorValve extends FormAuthenticator i
|
||||
forwardToLogoutPage(request, response, deployment);
|
||||
|
||||
}
|
||||
log.fine("Logging OUT");
|
||||
log.trace("Logging OUT");
|
||||
return false;
|
||||
}
|
||||
|
||||
AuthChallenge challenge = authenticator.getChallenge();
|
||||
if (challenge != null) {
|
||||
log.fine("challenge");
|
||||
log.trace("challenge");
|
||||
challenge.challenge(facade);
|
||||
}
|
||||
return false;
|
||||
@@ -275,8 +275,68 @@ public abstract class AbstractSamlAuthenticatorValve extends FormAuthenticator i
|
||||
|
||||
protected SamlSessionStore createSessionStore(Request request, HttpFacade facade, SamlDeployment resolvedDeployment) {
|
||||
SamlSessionStore store;
|
||||
store = new CatalinaSamlSessionStore(userSessionManagement, createPrincipalFactory(), mapper, request, this, facade, resolvedDeployment);
|
||||
store = new CatalinaSamlSessionStore(userSessionManagement, createPrincipalFactory(), mapper, idMapperUpdater, request, this, facade, resolvedDeployment);
|
||||
return store;
|
||||
}
|
||||
|
||||
protected void addTokenStoreUpdaters() {
|
||||
SessionIdMapperUpdater updater = getIdMapperUpdater();
|
||||
|
||||
try {
|
||||
String idMapperSessionUpdaterClasses = context.getServletContext().getInitParameter("keycloak.sessionIdMapperUpdater.classes");
|
||||
if (idMapperSessionUpdaterClasses == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (String clazz : idMapperSessionUpdaterClasses.split("\\s*,\\s*")) {
|
||||
if (! clazz.isEmpty()) {
|
||||
updater = invokeAddTokenStoreUpdaterMethod(clazz, updater);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
setIdMapperUpdater(updater);
|
||||
}
|
||||
}
|
||||
|
||||
private SessionIdMapperUpdater invokeAddTokenStoreUpdaterMethod(String idMapperSessionUpdaterClass, SessionIdMapperUpdater previousIdMapperUpdater) {
|
||||
try {
|
||||
Class<?> clazz = context.getLoader().getClassLoader().loadClass(idMapperSessionUpdaterClass);
|
||||
Method addTokenStoreUpdatersMethod = clazz.getMethod("addTokenStoreUpdaters", Context.class, SessionIdMapper.class, SessionIdMapperUpdater.class);
|
||||
if (! Modifier.isStatic(addTokenStoreUpdatersMethod.getModifiers())
|
||||
|| ! Modifier.isPublic(addTokenStoreUpdatersMethod.getModifiers())
|
||||
|| ! SessionIdMapperUpdater.class.isAssignableFrom(addTokenStoreUpdatersMethod.getReturnType())) {
|
||||
log.errorv("addTokenStoreUpdaters method in class {0} has to be public static. Ignoring class.", idMapperSessionUpdaterClass);
|
||||
return previousIdMapperUpdater;
|
||||
}
|
||||
|
||||
log.debugv("Initializing sessionIdMapperUpdater class {0}", idMapperSessionUpdaterClass);
|
||||
return (SessionIdMapperUpdater) addTokenStoreUpdatersMethod.invoke(null, context, mapper, previousIdMapperUpdater);
|
||||
} catch (ClassNotFoundException ex) {
|
||||
log.warnv(ex, "Cannot use sessionIdMapperUpdater class {0}", idMapperSessionUpdaterClass);
|
||||
return previousIdMapperUpdater;
|
||||
} catch (NoSuchMethodException ex) {
|
||||
log.warnv(ex, "Cannot use sessionIdMapperUpdater class {0}", idMapperSessionUpdaterClass);
|
||||
return previousIdMapperUpdater;
|
||||
} catch (SecurityException ex) {
|
||||
log.warnv(ex, "Cannot use sessionIdMapperUpdater class {0}", idMapperSessionUpdaterClass);
|
||||
return previousIdMapperUpdater;
|
||||
} catch (IllegalAccessException ex) {
|
||||
log.warnv(ex, "Cannot use {0}.addTokenStoreUpdaters(DeploymentInfo, SessionIdMapper) method", idMapperSessionUpdaterClass);
|
||||
return previousIdMapperUpdater;
|
||||
} catch (IllegalArgumentException ex) {
|
||||
log.warnv(ex, "Cannot use {0}.addTokenStoreUpdaters(DeploymentInfo, SessionIdMapper) method", idMapperSessionUpdaterClass);
|
||||
return previousIdMapperUpdater;
|
||||
} catch (InvocationTargetException ex) {
|
||||
log.warnv(ex, "Cannot use {0}.addTokenStoreUpdaters(DeploymentInfo, SessionIdMapper) method", idMapperSessionUpdaterClass);
|
||||
return previousIdMapperUpdater;
|
||||
}
|
||||
}
|
||||
|
||||
public SessionIdMapperUpdater getIdMapperUpdater() {
|
||||
return idMapperUpdater;
|
||||
}
|
||||
|
||||
public void setIdMapperUpdater(SessionIdMapperUpdater idMapperUpdater) {
|
||||
this.idMapperUpdater = idMapperUpdater;
|
||||
}
|
||||
}
|
||||
+12
-6
@@ -24,6 +24,7 @@ import org.apache.catalina.realm.GenericPrincipal;
|
||||
import org.jboss.logging.Logger;
|
||||
import org.keycloak.adapters.spi.HttpFacade;
|
||||
import org.keycloak.adapters.spi.SessionIdMapper;
|
||||
import org.keycloak.adapters.spi.SessionIdMapperUpdater;
|
||||
import org.keycloak.adapters.tomcat.CatalinaUserSessionManagement;
|
||||
import org.keycloak.adapters.tomcat.GenericPrincipalFactory;
|
||||
import org.keycloak.common.util.KeycloakUriBuilder;
|
||||
@@ -45,17 +46,20 @@ public class CatalinaSamlSessionStore implements SamlSessionStore {
|
||||
private final CatalinaUserSessionManagement sessionManagement;
|
||||
protected final GenericPrincipalFactory principalFactory;
|
||||
private final SessionIdMapper idMapper;
|
||||
private final SessionIdMapperUpdater idMapperUpdater;
|
||||
protected final Request request;
|
||||
protected final AbstractSamlAuthenticatorValve valve;
|
||||
protected final HttpFacade facade;
|
||||
protected final SamlDeployment deployment;
|
||||
|
||||
public CatalinaSamlSessionStore(CatalinaUserSessionManagement sessionManagement, GenericPrincipalFactory principalFactory,
|
||||
SessionIdMapper idMapper, Request request, AbstractSamlAuthenticatorValve valve, HttpFacade facade,
|
||||
SessionIdMapper idMapper, SessionIdMapperUpdater idMapperUpdater,
|
||||
Request request, AbstractSamlAuthenticatorValve valve, HttpFacade facade,
|
||||
SamlDeployment deployment) {
|
||||
this.sessionManagement = sessionManagement;
|
||||
this.principalFactory = principalFactory;
|
||||
this.idMapper = idMapper;
|
||||
this.idMapperUpdater = idMapperUpdater;
|
||||
this.request = request;
|
||||
this.valve = valve;
|
||||
this.facade = facade;
|
||||
@@ -89,11 +93,13 @@ public class CatalinaSamlSessionStore implements SamlSessionStore {
|
||||
Session sessionInternal = request.getSessionInternal(false);
|
||||
if (sessionInternal == null) return;
|
||||
HttpSession session = sessionInternal.getSession();
|
||||
List<String> ids = new LinkedList<String>();
|
||||
if (session != null) {
|
||||
SamlSession samlSession = (SamlSession)session.getAttribute(SamlSession.class.getName());
|
||||
if (samlSession != null) {
|
||||
if (samlSession.getSessionIndex() != null) {
|
||||
idMapper.removeSession(session.getId());
|
||||
ids.add(session.getId());
|
||||
idMapperUpdater.removeSession(idMapper, session.getId());
|
||||
}
|
||||
session.removeAttribute(SamlSession.class.getName());
|
||||
}
|
||||
@@ -101,6 +107,7 @@ public class CatalinaSamlSessionStore implements SamlSessionStore {
|
||||
}
|
||||
sessionInternal.setPrincipal(null);
|
||||
sessionInternal.setAuthType(null);
|
||||
logoutSessionIds(ids);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -111,7 +118,7 @@ public class CatalinaSamlSessionStore implements SamlSessionStore {
|
||||
ids.addAll(sessions);
|
||||
logoutSessionIds(ids);
|
||||
for (String id : ids) {
|
||||
idMapper.removeSession(id);
|
||||
idMapperUpdater.removeSession(idMapper, id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -125,7 +132,7 @@ public class CatalinaSamlSessionStore implements SamlSessionStore {
|
||||
String sessionId = idMapper.getSessionFromSSO(id);
|
||||
if (sessionId != null) {
|
||||
sessionIds.add(sessionId);
|
||||
idMapper.removeSession(sessionId);
|
||||
idMapperUpdater.removeSession(idMapper, sessionId);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -141,7 +148,6 @@ public class CatalinaSamlSessionStore implements SamlSessionStore {
|
||||
@Override
|
||||
public boolean isLoggedIn() {
|
||||
Session session = request.getSessionInternal(false);
|
||||
if (session == null) return false;
|
||||
if (session == null) {
|
||||
log.debug("session was null, returning null");
|
||||
return false;
|
||||
@@ -193,7 +199,7 @@ public class CatalinaSamlSessionStore implements SamlSessionStore {
|
||||
request.setUserPrincipal(principal);
|
||||
request.setAuthType("KEYCLOAK-SAML");
|
||||
String newId = changeSessionId(session);
|
||||
idMapper.map(account.getSessionIndex(), account.getPrincipal().getSamlSubject(), newId);
|
||||
idMapperUpdater.map(idMapper, account.getSessionIndex(), account.getPrincipal().getSamlSubject(), newId);
|
||||
|
||||
}
|
||||
|
||||
|
||||
+93
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Copyright 2017 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.saml;
|
||||
|
||||
import org.keycloak.adapters.spi.SessionIdMapper;
|
||||
|
||||
import java.util.Objects;
|
||||
import javax.servlet.http.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author hmlnarik
|
||||
*/
|
||||
public class IdMapperUpdaterSessionListener implements HttpSessionListener, HttpSessionAttributeListener {
|
||||
|
||||
private final SessionIdMapper idMapper;
|
||||
|
||||
public IdMapperUpdaterSessionListener(SessionIdMapper idMapper) {
|
||||
this.idMapper = idMapper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sessionCreated(HttpSessionEvent hse) {
|
||||
HttpSession session = hse.getSession();
|
||||
Object value = session.getAttribute(SamlSession.class.getName());
|
||||
map(session.getId(), value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sessionDestroyed(HttpSessionEvent hse) {
|
||||
HttpSession session = hse.getSession();
|
||||
unmap(session.getId(), session.getAttribute(SamlSession.class.getName()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void attributeAdded(HttpSessionBindingEvent hsbe) {
|
||||
HttpSession session = hsbe.getSession();
|
||||
if (Objects.equals(hsbe.getName(), SamlSession.class.getName())) {
|
||||
map(session.getId(), hsbe.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void attributeRemoved(HttpSessionBindingEvent hsbe) {
|
||||
HttpSession session = hsbe.getSession();
|
||||
if (Objects.equals(hsbe.getName(), SamlSession.class.getName())) {
|
||||
unmap(session.getId(), hsbe.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void attributeReplaced(HttpSessionBindingEvent hsbe) {
|
||||
HttpSession session = hsbe.getSession();
|
||||
if (Objects.equals(hsbe.getName(), SamlSession.class.getName())) {
|
||||
unmap(session.getId(), hsbe.getValue());
|
||||
map(session.getId(), session.getAttribute(SamlSession.class.getName()));
|
||||
}
|
||||
}
|
||||
|
||||
private void map(String sessionId, Object value) {
|
||||
if (! (value instanceof SamlSession) || sessionId == null) {
|
||||
return;
|
||||
}
|
||||
SamlSession account = (SamlSession) value;
|
||||
|
||||
idMapper.map(account.getSessionIndex(), account.getPrincipal().getSamlSubject(), sessionId);
|
||||
}
|
||||
|
||||
private void unmap(String sessionId, Object value) {
|
||||
if (! (value instanceof SamlSession) || sessionId == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
SamlSession samlSession = (SamlSession) value;
|
||||
if (samlSession.getSessionIndex() != null) {
|
||||
idMapper.removeSession(sessionId);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -21,7 +21,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-saml-tomcat-integration-pom</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>2.5.1.Final-SNAPSHOT</version>
|
||||
<version>3.0.0.CR1</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-saml-tomcat-integration-pom</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>2.5.1.Final-SNAPSHOT</version>
|
||||
<version>3.0.0.CR1</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-saml-tomcat-integration-pom</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>2.5.1.Final-SNAPSHOT</version>
|
||||
<version>3.0.0.CR1</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
+2
-1
@@ -24,6 +24,7 @@ import org.keycloak.adapters.saml.CatalinaSamlSessionStore;
|
||||
import org.keycloak.adapters.saml.SamlDeployment;
|
||||
import org.keycloak.adapters.spi.HttpFacade;
|
||||
import org.keycloak.adapters.spi.SessionIdMapper;
|
||||
import org.keycloak.adapters.spi.SessionIdMapperUpdater;
|
||||
import org.keycloak.adapters.tomcat.CatalinaUserSessionManagement;
|
||||
import org.keycloak.adapters.tomcat.GenericPrincipalFactory;
|
||||
|
||||
@@ -33,7 +34,7 @@ import org.keycloak.adapters.tomcat.GenericPrincipalFactory;
|
||||
*/
|
||||
public class Tomcat8SamlSessionStore extends CatalinaSamlSessionStore {
|
||||
public Tomcat8SamlSessionStore(CatalinaUserSessionManagement sessionManagement, GenericPrincipalFactory principalFactory, SessionIdMapper idMapper, Request request, AbstractSamlAuthenticatorValve valve, HttpFacade facade, SamlDeployment deployment) {
|
||||
super(sessionManagement, principalFactory, idMapper, request, valve, facade, deployment);
|
||||
super(sessionManagement, principalFactory, idMapper, SessionIdMapperUpdater.DIRECT, request, valve, facade, deployment);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>2.5.1.Final-SNAPSHOT</version>
|
||||
<version>3.0.0.CR1</version>
|
||||
<relativePath>../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
+103
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Copyright 2017 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.saml.undertow;
|
||||
|
||||
import org.keycloak.adapters.saml.SamlSession;
|
||||
import org.keycloak.adapters.spi.SessionIdMapper;
|
||||
|
||||
import io.undertow.server.HttpServerExchange;
|
||||
import io.undertow.server.session.Session;
|
||||
import io.undertow.server.session.SessionListener;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author hmlnarik
|
||||
*/
|
||||
public class IdMapperUpdaterSessionListener implements SessionListener {
|
||||
|
||||
private final SessionIdMapper idMapper;
|
||||
|
||||
public IdMapperUpdaterSessionListener(SessionIdMapper idMapper) {
|
||||
this.idMapper = idMapper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sessionCreated(Session session, HttpServerExchange exchange) {
|
||||
Object value = session.getAttribute(SamlSession.class.getName());
|
||||
map(session.getId(), value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sessionDestroyed(Session session, HttpServerExchange exchange, SessionDestroyedReason reason) {
|
||||
if (reason != SessionDestroyedReason.UNDEPLOY) {
|
||||
unmap(session.getId(), session.getAttribute(SamlSession.class.getName()));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void attributeAdded(Session session, String name, Object value) {
|
||||
if (Objects.equals(name, SamlSession.class.getName())) {
|
||||
map(session.getId(), value);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void attributeUpdated(Session session, String name, Object newValue, Object oldValue) {
|
||||
if (Objects.equals(name, SamlSession.class.getName())) {
|
||||
unmap(session.getId(), oldValue);
|
||||
map(session.getId(), newValue);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void attributeRemoved(Session session, String name, Object oldValue) {
|
||||
if (Objects.equals(name, SamlSession.class.getName())) {
|
||||
unmap(session.getId(), oldValue);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sessionIdChanged(Session session, String oldSessionId) {
|
||||
Object value = session.getAttribute(SamlSession.class.getName());
|
||||
if (value != null) {
|
||||
unmap(oldSessionId, value);
|
||||
map(session.getId(), value);
|
||||
}
|
||||
}
|
||||
|
||||
private void map(String sessionId, Object value) {
|
||||
if (! (value instanceof SamlSession) || sessionId == null) {
|
||||
return;
|
||||
}
|
||||
SamlSession account = (SamlSession) value;
|
||||
|
||||
idMapper.map(account.getSessionIndex(), account.getPrincipal().getSamlSubject(), sessionId);
|
||||
}
|
||||
|
||||
private void unmap(String sessionId, Object value) {
|
||||
if (! (value instanceof SamlSession) || sessionId == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
SamlSession samlSession = (SamlSession) value;
|
||||
if (samlSession.getSessionIndex() != null) {
|
||||
idMapper.removeSession(sessionId);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+1
-1
@@ -154,7 +154,7 @@ public class SamlServletExtension implements ServletExtension {
|
||||
servletContext.setAttribute(SamlDeploymentContext.class.getName(), deploymentContext);
|
||||
UndertowUserSessionManagement userSessionManagement = new UndertowUserSessionManagement();
|
||||
final ServletSamlAuthMech mech = createAuthMech(deploymentInfo, deploymentContext, userSessionManagement);
|
||||
|
||||
mech.addTokenStoreUpdaters(deploymentInfo);
|
||||
|
||||
// setup handlers
|
||||
|
||||
|
||||
+64
-4
@@ -21,35 +21,89 @@ import io.undertow.security.api.SecurityContext;
|
||||
import io.undertow.server.HttpServerExchange;
|
||||
import io.undertow.servlet.handlers.ServletRequestContext;
|
||||
import io.undertow.util.Headers;
|
||||
|
||||
import org.keycloak.adapters.saml.SamlDeployment;
|
||||
import org.keycloak.adapters.saml.SamlDeploymentContext;
|
||||
import org.keycloak.adapters.saml.SamlSessionStore;
|
||||
import org.keycloak.adapters.spi.HttpFacade;
|
||||
import org.keycloak.adapters.spi.InMemorySessionIdMapper;
|
||||
import org.keycloak.adapters.spi.SessionIdMapper;
|
||||
import org.keycloak.adapters.spi.*;
|
||||
import org.keycloak.adapters.undertow.ServletHttpFacade;
|
||||
import org.keycloak.adapters.undertow.UndertowHttpFacade;
|
||||
import org.keycloak.adapters.undertow.UndertowUserSessionManagement;
|
||||
|
||||
import io.undertow.servlet.api.DeploymentInfo;
|
||||
import javax.servlet.RequestDispatcher;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.*;
|
||||
import java.util.Map;
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class ServletSamlAuthMech extends AbstractSamlAuthMech {
|
||||
|
||||
private static final Logger LOG = Logger.getLogger(ServletSamlAuthMech.class);
|
||||
|
||||
protected SessionIdMapper idMapper = new InMemorySessionIdMapper();
|
||||
protected SessionIdMapperUpdater idMapperUpdater = SessionIdMapperUpdater.DIRECT;
|
||||
|
||||
public ServletSamlAuthMech(SamlDeploymentContext deploymentContext, UndertowUserSessionManagement sessionManagement, String errorPage) {
|
||||
super(deploymentContext, sessionManagement, errorPage);
|
||||
}
|
||||
|
||||
public void addTokenStoreUpdaters(DeploymentInfo deploymentInfo) {
|
||||
deploymentInfo.addSessionListener(new IdMapperUpdaterSessionListener(idMapper)); // This takes care of HTTP sessions manipulated locally
|
||||
SessionIdMapperUpdater updater = SessionIdMapperUpdater.EXTERNAL;
|
||||
|
||||
try {
|
||||
Map<String, String> initParameters = deploymentInfo.getInitParameters();
|
||||
String idMapperSessionUpdaterClasses = initParameters == null
|
||||
? null
|
||||
: initParameters.get("keycloak.sessionIdMapperUpdater.classes");
|
||||
if (idMapperSessionUpdaterClasses == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (String clazz : idMapperSessionUpdaterClasses.split("\\s*,\\s*")) {
|
||||
if (! clazz.isEmpty()) {
|
||||
updater = invokeAddTokenStoreUpdaterMethod(clazz, deploymentInfo, updater);
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
setIdMapperUpdater(updater);
|
||||
}
|
||||
}
|
||||
|
||||
private SessionIdMapperUpdater invokeAddTokenStoreUpdaterMethod(String idMapperSessionUpdaterClass, DeploymentInfo deploymentInfo,
|
||||
SessionIdMapperUpdater previousIdMapperUpdater) {
|
||||
try {
|
||||
Class<?> clazz = deploymentInfo.getClassLoader().loadClass(idMapperSessionUpdaterClass);
|
||||
Method addTokenStoreUpdatersMethod = clazz.getMethod("addTokenStoreUpdaters", DeploymentInfo.class, SessionIdMapper.class, SessionIdMapperUpdater.class);
|
||||
if (! Modifier.isStatic(addTokenStoreUpdatersMethod.getModifiers())
|
||||
|| ! Modifier.isPublic(addTokenStoreUpdatersMethod.getModifiers())
|
||||
|| ! SessionIdMapperUpdater.class.isAssignableFrom(addTokenStoreUpdatersMethod.getReturnType())) {
|
||||
LOG.errorv("addTokenStoreUpdaters method in class {0} has to be public static. Ignoring class.", idMapperSessionUpdaterClass);
|
||||
return previousIdMapperUpdater;
|
||||
}
|
||||
|
||||
LOG.debugv("Initializing sessionIdMapperUpdater class {0}", idMapperSessionUpdaterClass);
|
||||
return (SessionIdMapperUpdater) addTokenStoreUpdatersMethod.invoke(null, deploymentInfo, idMapper, previousIdMapperUpdater);
|
||||
} catch (ClassNotFoundException | NoSuchMethodException | SecurityException ex) {
|
||||
LOG.warnv(ex, "Cannot use sessionIdMapperUpdater class {0}", idMapperSessionUpdaterClass);
|
||||
return previousIdMapperUpdater;
|
||||
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
|
||||
LOG.warnv(ex, "Cannot use {0}.addTokenStoreUpdaters(DeploymentInfo, SessionIdMapper) method", idMapperSessionUpdaterClass);
|
||||
return previousIdMapperUpdater;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SamlSessionStore getTokenStore(HttpServerExchange exchange, HttpFacade facade, SamlDeployment deployment, SecurityContext securityContext) {
|
||||
return new ServletSamlSessionStore(exchange, sessionManagement, securityContext, idMapper, deployment);
|
||||
return new ServletSamlSessionStore(exchange, sessionManagement, securityContext, idMapper, idMapperUpdater, deployment);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -84,5 +138,11 @@ public class ServletSamlAuthMech extends AbstractSamlAuthMech {
|
||||
return null;
|
||||
}
|
||||
|
||||
public SessionIdMapperUpdater getIdMapperUpdater() {
|
||||
return idMapperUpdater;
|
||||
}
|
||||
|
||||
protected void setIdMapperUpdater(SessionIdMapperUpdater idMapperUpdater) {
|
||||
this.idMapperUpdater = idMapperUpdater;
|
||||
}
|
||||
}
|
||||
+12
-5
@@ -24,11 +24,13 @@ import io.undertow.server.session.SessionManager;
|
||||
import io.undertow.servlet.handlers.ServletRequestContext;
|
||||
import io.undertow.servlet.spec.HttpSessionImpl;
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import org.keycloak.adapters.saml.SamlDeployment;
|
||||
import org.keycloak.adapters.saml.SamlSession;
|
||||
import org.keycloak.adapters.saml.SamlSessionStore;
|
||||
import org.keycloak.adapters.saml.SamlUtil;
|
||||
import org.keycloak.adapters.spi.SessionIdMapper;
|
||||
import org.keycloak.adapters.spi.SessionIdMapperUpdater;
|
||||
import org.keycloak.adapters.undertow.ChangeSessionId;
|
||||
import org.keycloak.adapters.undertow.SavedRequest;
|
||||
import org.keycloak.adapters.undertow.ServletHttpFacade;
|
||||
@@ -44,6 +46,8 @@ import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Session store manipulation methods per single HTTP exchange.
|
||||
*
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
@@ -55,17 +59,20 @@ public class ServletSamlSessionStore implements SamlSessionStore {
|
||||
private final UndertowUserSessionManagement sessionManagement;
|
||||
private final SecurityContext securityContext;
|
||||
private final SessionIdMapper idMapper;
|
||||
private final SessionIdMapperUpdater idMapperUpdater;
|
||||
protected final SamlDeployment deployment;
|
||||
|
||||
|
||||
public ServletSamlSessionStore(HttpServerExchange exchange, UndertowUserSessionManagement sessionManagement,
|
||||
SecurityContext securityContext,
|
||||
SessionIdMapper idMapper, SamlDeployment deployment) {
|
||||
SessionIdMapper idMapper, SessionIdMapperUpdater idMapperUpdater,
|
||||
SamlDeployment deployment) {
|
||||
this.exchange = exchange;
|
||||
this.sessionManagement = sessionManagement;
|
||||
this.securityContext = securityContext;
|
||||
this.idMapper = idMapper;
|
||||
this.deployment = deployment;
|
||||
this.idMapperUpdater = idMapperUpdater;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -97,7 +104,7 @@ public class ServletSamlSessionStore implements SamlSessionStore {
|
||||
SamlSession samlSession = (SamlSession)session.getAttribute(SamlSession.class.getName());
|
||||
if (samlSession != null) {
|
||||
if (samlSession.getSessionIndex() != null) {
|
||||
idMapper.removeSession(session.getId());
|
||||
idMapperUpdater.removeSession(idMapper, session.getId());
|
||||
}
|
||||
session.removeAttribute(SamlSession.class.getName());
|
||||
}
|
||||
@@ -113,7 +120,7 @@ public class ServletSamlSessionStore implements SamlSessionStore {
|
||||
ids.addAll(sessions);
|
||||
logoutSessionIds(ids);
|
||||
for (String id : ids) {
|
||||
idMapper.removeSession(id);
|
||||
idMapperUpdater.removeSession(idMapper, id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -127,7 +134,7 @@ public class ServletSamlSessionStore implements SamlSessionStore {
|
||||
String sessionId = idMapper.getSessionFromSSO(id);
|
||||
if (sessionId != null) {
|
||||
sessionIds.add(sessionId);
|
||||
idMapper.removeSession(sessionId);
|
||||
idMapperUpdater.removeSession(idMapper, sessionId);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -177,7 +184,7 @@ public class ServletSamlSessionStore implements SamlSessionStore {
|
||||
session.setAttribute(SamlSession.class.getName(), account);
|
||||
sessionManagement.login(servletRequestContext.getDeployment().getSessionManager());
|
||||
String sessionId = changeSessionId(session);
|
||||
idMapper.map(account.getSessionIndex(), account.getPrincipal().getSamlSubject(), sessionId);
|
||||
idMapperUpdater.map(idMapper, account.getSessionIndex(), account.getPrincipal().getSamlSubject(), sessionId);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>2.5.1.Final-SNAPSHOT</version>
|
||||
<version>3.0.0.CR1</version>
|
||||
<relativePath>../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<name>Keycloak SAML Wildfly Integration</name>
|
||||
|
||||
Loaded 100 of 1086 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user