Compare commits
470
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9481a351ed | ||
|
|
f98dcf2d7e | ||
|
|
27807c9bff | ||
|
|
22b56679e3 | ||
|
|
3ba8989681 | ||
|
|
bdd20b9699 | ||
|
|
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 | ||
|
|
88a37067ad | ||
|
|
c6dab26769 | ||
|
|
9bceec9ef5 | ||
|
|
d1e491d57d | ||
|
|
7cfa1cc368 | ||
|
|
b79ee3c7f3 | ||
|
|
6085b21c36 | ||
|
|
b24d2e064a | ||
|
|
4fcb22c540 | ||
|
|
07689c9537 | ||
|
|
e329c7801d | ||
|
|
2de2df3a41 | ||
|
|
194a63cc71 | ||
|
|
6392405413 | ||
|
|
a18a4477e0 | ||
|
|
94ffeda62a | ||
|
|
264e81efb2 | ||
|
|
cea52a6db9 | ||
|
|
b8c7fcf587 | ||
|
|
04228791f3 | ||
|
|
04c4110f76 | ||
|
|
13e92cdb35 | ||
|
|
bd271b2367 | ||
|
|
9fea9f6fe0 | ||
|
|
8717cd0090 | ||
|
|
e487db349c | ||
|
|
29c0fe564c | ||
|
|
b2d1a1a17f | ||
|
|
4868918f94 | ||
|
|
15d0a116ac | ||
|
|
b5212d58ec | ||
|
|
cf1c577840 | ||
|
|
57127f39d0 | ||
|
|
052534de82 | ||
|
|
99e1eac094 | ||
|
|
7410bdb31c | ||
|
|
cc9c8d8ca1 | ||
|
|
5bacd2919d | ||
|
|
f55d18189c | ||
|
|
6097a0c9e1 | ||
|
|
39f8311484 | ||
|
|
fe8e437e74 | ||
|
|
1373708dea | ||
|
|
34605ee3c6 | ||
|
|
3444fb62f1 | ||
|
|
cc788cf44e | ||
|
|
13e4f607ad | ||
|
|
5da491c270 | ||
|
|
99fcc51019 | ||
|
|
350b9550c3 | ||
|
|
f289b281a0 | ||
|
|
9cd860d698 | ||
|
|
536b88790e | ||
|
|
73d3e8afd9 | ||
|
|
aef6bb9789 | ||
|
|
b4f56e92f3 | ||
|
|
8daa2c3703 | ||
|
|
c7f2a0ffdd | ||
|
|
c19360c6f2 | ||
|
|
71da6ab4e9 | ||
|
|
9f33685785 | ||
|
|
df4f1e7129 | ||
|
|
212182ee34 | ||
|
|
86988833e9 | ||
|
|
5a0504b5d9 | ||
|
|
e364680792 | ||
|
|
ef46070410 | ||
|
|
843b4b470b | ||
|
|
dcf6da2a51 | ||
|
|
9bb65ba9b7 | ||
|
|
3d29816ea3 | ||
|
|
2eeb2f52c5 | ||
|
|
32827be8b1 | ||
|
|
23c1f513e7 | ||
|
|
ae40bfb96e | ||
|
|
547f5ecfa6 | ||
|
|
1913f801b9 | ||
|
|
5842f7c837 | ||
|
|
1ef2eb6110 | ||
|
|
178625d3f2 | ||
|
|
9fb46a7b1c | ||
|
|
bea8de8a1a | ||
|
|
d68f6bbc42 | ||
|
|
7de999a7f9 | ||
|
|
ffb688b393 | ||
|
|
6aee6b0c46 | ||
|
|
aa78c9eaf5 | ||
|
|
02eda8943c | ||
|
|
2f7143e72f | ||
|
|
9ad14d991c | ||
|
|
59a6c9f13f | ||
|
|
ae838c12db | ||
|
|
ac9268bd48 | ||
|
|
0b58bebc90 | ||
|
|
93157e49d5 | ||
|
|
3d9f11168e | ||
|
|
c4cce147e2 | ||
|
|
3a2927e12e | ||
|
|
901ff9c3d5 | ||
|
|
8de3b26126 | ||
|
|
1e51ade620 | ||
|
|
89e6f93fa4 | ||
|
|
41630d6962 | ||
|
|
efcd0346fc | ||
|
|
f13deab812 | ||
|
|
f28b3c1269 | ||
|
|
5e1ec459e5 | ||
|
|
9a6f202c46 | ||
|
|
e11957ecf3 | ||
|
|
23c8809598 | ||
|
|
7098daaf72 | ||
|
|
ba73ab1c2a | ||
|
|
45f5fa6a74 | ||
|
|
50b7dbe7b2 | ||
|
|
811d532b48 | ||
|
|
7ceef826ac | ||
|
|
fe294dcb58 | ||
|
|
8441bda3da | ||
|
|
227900f288 | ||
|
|
345e0da76d | ||
|
|
139e12fa5f | ||
|
|
4df70c517d | ||
|
|
cbd6f7e1d0 | ||
|
|
426e55664f | ||
|
|
ab0a669662 | ||
|
|
5c03b20bd1 | ||
|
|
7eeebff874 | ||
|
|
a0a7372160 | ||
|
|
9e697d033f | ||
|
|
2ec3eaf68a | ||
|
|
e047872c25 | ||
|
|
f1173f8022 | ||
|
|
420286c103 | ||
|
|
1495f4881e | ||
|
|
452611242c | ||
|
|
d075172fd2 | ||
|
|
c32620b718 | ||
|
|
37b8d1ad10 | ||
|
|
be4f2aff63 | ||
|
|
14669dfbc5 | ||
|
|
5cec0d4bef | ||
|
|
dd74b57d13 | ||
|
|
a09bc6520f | ||
|
|
8a02ef1859 | ||
|
|
9ccd05ff54 | ||
|
|
42a8a0eb15 | ||
|
|
fb374ad99d | ||
|
|
a4f46d3310 | ||
|
|
5bc134ea7b | ||
|
|
28c289cfb8 | ||
|
|
0b5b27ea3a | ||
|
|
f1dbe3c9e2 | ||
|
|
9fb3201c8b | ||
|
|
96f8f99313 | ||
|
|
86c49f5e89 | ||
|
|
017dbb1d9f | ||
|
|
60eda52aba | ||
|
|
377fbced4a | ||
|
|
fb6a8da863 | ||
|
|
0cb5ba0f6e | ||
|
|
eb1b011989 | ||
|
|
72691b2e74 | ||
|
|
f9eeecf836 | ||
|
|
61e7936d79 | ||
|
|
4934fe5a8e | ||
|
|
2035398ef4 | ||
|
|
56160ef12b | ||
|
|
b0644ce18c | ||
|
|
cf5c3aa53b | ||
|
|
f9e87516ae | ||
|
|
ed1a30f67b | ||
|
|
77293b85e0 | ||
|
|
ad9210a7a7 | ||
|
|
15af61a7cc | ||
|
|
2d1417d72b | ||
|
|
41404424ac | ||
|
|
a2a531a747 | ||
|
|
a76c52ef84 | ||
|
|
ed75ef900a | ||
|
|
862502f3ed | ||
|
|
2b57b8371b | ||
|
|
4044b39ab7 | ||
|
|
e0bc56960b | ||
|
|
180352aa09 | ||
|
|
09a61f4706 | ||
|
|
5150251141 | ||
|
|
732d56b0c0 | ||
|
|
08aeb13804 | ||
|
|
1f0469894a | ||
|
|
8a0859fcba | ||
|
|
5212f57b5b | ||
|
|
6ac1301dc2 | ||
|
|
1eb0cde74f | ||
|
|
32f8fd4b9f | ||
|
|
90a5272860 | ||
|
|
40a8f0a243 | ||
|
|
f2ee9df600 | ||
|
|
9ab44b79ce | ||
|
|
50c11e105b | ||
|
|
b7c98ed433 | ||
|
|
d217b23719 | ||
|
|
171c6ab88f | ||
|
|
45411b1199 | ||
|
|
e0bfb13ed9 | ||
|
|
902332c5ae | ||
|
|
08d7211a93 | ||
|
|
1c0e204f50 | ||
|
|
d6e620a266 | ||
|
|
54b3d3abec | ||
|
|
31ed69a970 | ||
|
|
b1d9fd670a | ||
|
|
bf58511d81 | ||
|
|
b5317f3485 | ||
|
|
e805ffd945 | ||
|
|
40b5731198 | ||
|
|
bb00524f94 | ||
|
|
172007f59c | ||
|
|
3e3216fb23 | ||
|
|
34f82fa1b1 | ||
|
|
74fd904bc4 | ||
|
|
4910b35d69 |
No files matched your search
@@ -14,6 +14,7 @@
|
||||
nbactions.xml
|
||||
nb-configuration.xml
|
||||
catalog.xml
|
||||
nbproject
|
||||
|
||||
# Compiled source #
|
||||
###################
|
||||
|
||||
+2
-3
@@ -12,12 +12,11 @@ env:
|
||||
- MAVEN_SKIP_RC=true
|
||||
- MAVEN_OPTS="-Xms512m -Xmx2048m"
|
||||
matrix:
|
||||
- TESTS=old
|
||||
- TESTS=group1
|
||||
- TESTS=group2
|
||||
- TESTS=group3
|
||||
- TESTS=group4
|
||||
- TESTS=adapter
|
||||
- TESTS=old
|
||||
|
||||
jdk:
|
||||
- oraclejdk8
|
||||
@@ -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.0.Final</version>
|
||||
<version>3.0.0.Final</version>
|
||||
<relativePath>../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
+1
-3
@@ -196,10 +196,8 @@ public class OAuthRequestAuthenticator {
|
||||
return sslRedirectPort;
|
||||
}
|
||||
|
||||
protected static final AtomicLong counter = new AtomicLong();
|
||||
|
||||
protected String getStateCode() {
|
||||
return counter.getAndIncrement() + "/" + AdapterUtils.generateId();
|
||||
return AdapterUtils.generateId();
|
||||
}
|
||||
|
||||
protected AuthChallenge loginRedirect() {
|
||||
|
||||
+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;
|
||||
|
||||
+1
-2
@@ -253,8 +253,7 @@ public abstract class AbstractPolicyEnforcer {
|
||||
}
|
||||
|
||||
private String getPath(Request request) {
|
||||
String pathInfo = URI.create(request.getURI()).getPath().substring(1);
|
||||
return pathInfo.substring(pathInfo.indexOf('/'), pathInfo.length());
|
||||
return request.getRelativePath();
|
||||
}
|
||||
|
||||
private Set<String> getRequiredScopes(PathConfig pathConfig, Request request) {
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-as7-integration-pom</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>2.5.0.Final</version>
|
||||
<version>3.0.0.Final</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.0.Final</version>
|
||||
<version>3.0.0.Final</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.0.Final</version>
|
||||
<version>3.0.0.Final</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>2.5.0.Final</version>
|
||||
<version>3.0.0.Final</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.0.Final</version>
|
||||
<version>3.0.0.Final</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.0.Final</version>
|
||||
<version>3.0.0.Final</version>
|
||||
<relativePath>../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@@ -66,6 +66,11 @@ public class JaxrsHttpFacade implements OIDCHttpFacade {
|
||||
return requestContext.getUriInfo().getRequestUri().toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRelativePath() {
|
||||
return requestContext.getUriInfo().getPath();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSecure() {
|
||||
return securityContext.isSecure();
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>2.5.0.Final</version>
|
||||
<version>3.0.0.Final</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.0.Final</version>
|
||||
<version>3.0.0.Final</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 Jetty81SessionManager implements JettySessionManager {
|
||||
protected SessionManager sessionManager;
|
||||
|
||||
public Jetty81SessionManager(SessionManager sessionManager) {
|
||||
this.sessionManager = sessionManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
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.0.Final</version>
|
||||
<version>3.0.0.Final</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.0.Final</version>
|
||||
<version>3.0.0.Final</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.0.Final</version>
|
||||
<version>3.0.0.Final</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.Final</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.0.Final</version>
|
||||
<version>3.0.0.Final</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.0.Final</version>
|
||||
<version>3.0.0.Final</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) {
|
||||
@@ -153,7 +157,7 @@
|
||||
processCallback(callback, initPromise);
|
||||
return;
|
||||
} else if (initOptions) {
|
||||
if (initOptions.token || initOptions.refreshToken) {
|
||||
if (initOptions.refreshToken) {
|
||||
setToken(initOptions.token, initOptions.refreshToken, initOptions.idToken);
|
||||
|
||||
if (loginIframe.enable) {
|
||||
@@ -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;
|
||||
@@ -379,7 +384,7 @@
|
||||
kc.updateToken = function(minValidity) {
|
||||
var promise = createPromise();
|
||||
|
||||
if (!kc.tokenParsed || !kc.refreshToken) {
|
||||
if (!kc.refreshToken) {
|
||||
promise.setError();
|
||||
return promise.promise;
|
||||
}
|
||||
@@ -388,14 +393,10 @@
|
||||
|
||||
var exec = function() {
|
||||
var refreshToken = false;
|
||||
if (kc.timeSkew == -1) {
|
||||
console.info('Skew ' + kc.timeSkew);
|
||||
refreshToken = true;
|
||||
console.info('[KEYCLOAK] Refreshing token: time skew not set');
|
||||
} else if (minValidity == -1) {
|
||||
if (minValidity == -1) {
|
||||
refreshToken = true;
|
||||
console.info('[KEYCLOAK] Refreshing token: forced refresh');
|
||||
} else if (kc.isTokenExpired(minValidity)) {
|
||||
} else if (!kc.tokenParsed || kc.isTokenExpired(minValidity)) {
|
||||
refreshToken = true;
|
||||
console.info('[KEYCLOAK] Refreshing token: token expired');
|
||||
}
|
||||
@@ -638,49 +639,6 @@
|
||||
kc.tokenTimeoutHandle = null;
|
||||
}
|
||||
|
||||
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.authenticated = true;
|
||||
kc.subject = kc.tokenParsed.sub;
|
||||
kc.realmAccess = kc.tokenParsed.realm_access;
|
||||
kc.resourceAccess = kc.tokenParsed.resource_access;
|
||||
|
||||
if (timeLocal) {
|
||||
kc.timeSkew = Math.floor(timeLocal / 1000) - kc.tokenParsed.iat;
|
||||
console.info('[KEYCLOAK] Estimated time difference between browser and server is ' + kc.timeSkew + ' seconds');
|
||||
} else {
|
||||
kc.timeSkew = -1;
|
||||
}
|
||||
|
||||
if (kc.onTokenExpired) {
|
||||
if (kc.timeSkew == -1) {
|
||||
kc.onTokenExpired();
|
||||
} else {
|
||||
var expiresIn = (kc.tokenParsed['exp'] - (new Date().getTime() / 1000) + kc.timeSkew) * 1000;
|
||||
if (expiresIn <= 0) {
|
||||
kc.onTokenExpired();
|
||||
} else {
|
||||
kc.tokenTimeoutHandle = setTimeout(kc.onTokenExpired, expiresIn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
delete kc.token;
|
||||
delete kc.tokenParsed;
|
||||
delete kc.subject;
|
||||
delete kc.realmAccess;
|
||||
delete kc.resourceAccess;
|
||||
|
||||
kc.authenticated = false;
|
||||
}
|
||||
|
||||
if (refreshToken) {
|
||||
kc.refreshToken = refreshToken;
|
||||
kc.refreshTokenParsed = decodeToken(refreshToken);
|
||||
@@ -696,6 +654,42 @@
|
||||
delete kc.idToken;
|
||||
delete kc.idTokenParsed;
|
||||
}
|
||||
|
||||
if (token) {
|
||||
kc.token = token;
|
||||
kc.tokenParsed = decodeToken(token);
|
||||
kc.sessionId = kc.tokenParsed.session_state;
|
||||
kc.authenticated = true;
|
||||
kc.subject = kc.tokenParsed.sub;
|
||||
kc.realmAccess = kc.tokenParsed.realm_access;
|
||||
kc.resourceAccess = kc.tokenParsed.resource_access;
|
||||
|
||||
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) {
|
||||
var expiresIn = (kc.tokenParsed['exp'] - (new Date().getTime() / 1000) + kc.timeSkew) * 1000;
|
||||
console.info('[KEYCLOAK] Token expires in ' + Math.round(expiresIn / 1000) + ' s');
|
||||
if (expiresIn <= 0) {
|
||||
kc.onTokenExpired();
|
||||
} else {
|
||||
kc.tokenTimeoutHandle = setTimeout(kc.onTokenExpired, expiresIn);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
delete kc.token;
|
||||
delete kc.tokenParsed;
|
||||
delete kc.subject;
|
||||
delete kc.realmAccess;
|
||||
delete kc.resourceAccess;
|
||||
|
||||
kc.authenticated = false;
|
||||
}
|
||||
}
|
||||
|
||||
function decodeToken(str) {
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
<!--
|
||||
~ 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.
|
||||
-->
|
||||
|
||||
<script>
|
||||
function getCookie(cname)
|
||||
{
|
||||
var name = cname + "=";
|
||||
var ca = document.cookie.split(';');
|
||||
for(var i=0; i<ca.length; i++)
|
||||
{
|
||||
var c = ca[i].trim();
|
||||
if (c.indexOf(name)==0) return c.substring(name.length,c.length);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
function receiveMessage(event)
|
||||
{
|
||||
if (event.origin !== "ORIGIN") {
|
||||
console.log(event.origin + " does not match built origin");
|
||||
return;
|
||||
|
||||
}
|
||||
var data = JSON.parse(event.data);
|
||||
data.loggedIn = false;
|
||||
var cookie = getCookie('KEYCLOAK_SESSION');
|
||||
if (cookie) {
|
||||
data.loggedIn = true;
|
||||
data.session = cookie;
|
||||
}
|
||||
|
||||
event.source.postMessage(JSON.stringify(data),
|
||||
event.origin);
|
||||
}
|
||||
window.addEventListener("message", receiveMessage, false);
|
||||
</script>
|
||||
@@ -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.0.Final</version>
|
||||
<version>3.0.0.Final</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.0.Final</version>
|
||||
<version>3.0.0.Final</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.0.Final</version>
|
||||
<version>3.0.0.Final</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.0.Final</version>
|
||||
<version>3.0.0.Final</version>
|
||||
<relativePath>../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
+5
@@ -218,6 +218,11 @@ public class ServletOAuthClient extends KeycloakDeploymentDelegateOAuthClient {
|
||||
return servletRequest.getRequestURL().toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRelativePath() {
|
||||
return servletRequest.getServletPath();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSecure() {
|
||||
return servletRequest.isSecure();
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>2.5.0.Final</version>
|
||||
<version>3.0.0.Final</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.0.Final</version>
|
||||
<version>3.0.0.Final</version>
|
||||
<relativePath>../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
+5
@@ -70,6 +70,11 @@ class WrappedHttpServletRequest implements Request {
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRelativePath() {
|
||||
return request.getServletPath();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSecure() {
|
||||
return request.isSecure();
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>2.5.0.Final</version>
|
||||
<version>3.0.0.Final</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.0.Final</version>
|
||||
<version>3.0.0.Final</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.0.Final</version>
|
||||
<version>3.0.0.Final</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.0.Final</version>
|
||||
<version>3.0.0.Final</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.0.Final</version>
|
||||
<version>3.0.0.Final</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.0.Final</version>
|
||||
<version>3.0.0.Final</version>
|
||||
<relativePath>../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
+9
-4
@@ -173,10 +173,15 @@ public class KeycloakServletExtension implements ServletExtension {
|
||||
}
|
||||
});
|
||||
|
||||
log.debug("Setting jsession cookie path to: " + deploymentInfo.getContextPath());
|
||||
ServletSessionConfig cookieConfig = new ServletSessionConfig();
|
||||
cookieConfig.setPath(deploymentInfo.getContextPath());
|
||||
deploymentInfo.setServletSessionConfig(cookieConfig);
|
||||
ServletSessionConfig cookieConfig = deploymentInfo.getServletSessionConfig();
|
||||
if (cookieConfig == null) {
|
||||
cookieConfig = new ServletSessionConfig();
|
||||
}
|
||||
if (cookieConfig.getPath() == null) {
|
||||
log.debug("Setting jsession cookie path to: " + deploymentInfo.getContextPath());
|
||||
cookieConfig.setPath(deploymentInfo.getContextPath());
|
||||
deploymentInfo.setServletSessionConfig(cookieConfig);
|
||||
}
|
||||
ChangeSessionId.turnOffChangeSessionIdOnLogin(deploymentInfo);
|
||||
deploymentInfo.addListener(new ListenerInfo(UndertowNodesRegistrationManagementWrapper.class, new InstanceFactory<UndertowNodesRegistrationManagementWrapper>() {
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>2.5.0.Final</version>
|
||||
<version>3.0.0.Final</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.0.Final</version>
|
||||
<version>3.0.0.Final</version>
|
||||
<relativePath>../../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>2.5.0.Final</version>
|
||||
<version>3.0.0.Final</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.0.Final</version>
|
||||
<version>3.0.0.Final</version>
|
||||
<relativePath>../../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
||||
+1
-1
@@ -20,7 +20,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>2.5.0.Final</version>
|
||||
<version>3.0.0.Final</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.0.Final</version>
|
||||
<version>3.0.0.Final</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.0.Final</version>
|
||||
<version>3.0.0.Final</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.0.Final</version>
|
||||
<version>3.0.0.Final</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>2.5.0.Final</version>
|
||||
<version>3.0.0.Final</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.0.Final</version>
|
||||
<version>3.0.0.Final</version>
|
||||
<relativePath>../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
+31
-7
@@ -60,6 +60,7 @@ import org.keycloak.saml.processing.core.saml.v2.common.SAMLDocumentHolder;
|
||||
import org.keycloak.saml.processing.core.saml.v2.util.AssertionUtil;
|
||||
import org.keycloak.saml.processing.web.util.PostBindingUtil;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Node;
|
||||
|
||||
import java.io.IOException;
|
||||
@@ -70,14 +71,11 @@ import java.security.KeyManagementException;
|
||||
import java.security.PublicKey;
|
||||
import java.security.Signature;
|
||||
import java.security.SignatureException;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
import org.keycloak.dom.saml.v2.SAML2Object;
|
||||
import org.keycloak.dom.saml.v2.protocol.ExtensionsType;
|
||||
import org.keycloak.rotation.KeyLocator;
|
||||
import org.keycloak.saml.processing.core.util.KeycloakKeySamlExtensionGenerator;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -196,7 +194,7 @@ public abstract class AbstractSamlAuthenticationHandler implements SamlAuthentic
|
||||
challenge = new AuthChallenge() {
|
||||
@Override
|
||||
public boolean challenge(HttpFacade exchange) {
|
||||
SamlAuthenticationError error = new SamlAuthenticationError(SamlAuthenticationError.Reason.INVALID_SIGNATURE);
|
||||
SamlAuthenticationError error = new SamlAuthenticationError(SamlAuthenticationError.Reason.INVALID_SIGNATURE, statusResponse);
|
||||
exchange.getRequest().setError(error);
|
||||
exchange.getResponse().sendError(403);
|
||||
return true;
|
||||
@@ -312,8 +310,25 @@ public abstract class AbstractSamlAuthenticationHandler implements SamlAuthentic
|
||||
return false;
|
||||
}
|
||||
|
||||
protected AuthOutcome handleLoginResponse(ResponseType responseType, boolean postBinding, OnSessionCreated onCreateSession) {
|
||||
protected AuthOutcome handleLoginResponse(final ResponseType responseType, boolean postBinding, OnSessionCreated onCreateSession) {
|
||||
AssertionType assertion = null;
|
||||
if (! isSuccessfulSamlResponse(responseType) || responseType.getAssertions() == null || responseType.getAssertions().isEmpty()) {
|
||||
challenge = new AuthChallenge() {
|
||||
@Override
|
||||
public boolean challenge(HttpFacade exchange) {
|
||||
SamlAuthenticationError error = new SamlAuthenticationError(SamlAuthenticationError.Reason.ERROR_STATUS, responseType);
|
||||
exchange.getRequest().setError(error);
|
||||
exchange.getResponse().sendError(403);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getResponseCode() {
|
||||
return 403;
|
||||
}
|
||||
};
|
||||
return AuthOutcome.FAILED;
|
||||
}
|
||||
try {
|
||||
assertion = AssertionUtil.getAssertion(responseType, deployment.getDecryptionKey());
|
||||
if (AssertionUtil.hasExpired(assertion)) {
|
||||
@@ -335,6 +350,7 @@ public abstract class AbstractSamlAuthenticationHandler implements SamlAuthentic
|
||||
return 403;
|
||||
}
|
||||
};
|
||||
return AuthOutcome.FAILED;
|
||||
}
|
||||
|
||||
if (deployment.getIDP().getSingleSignOnService().validateAssertionSignature()) {
|
||||
@@ -346,7 +362,7 @@ public abstract class AbstractSamlAuthenticationHandler implements SamlAuthentic
|
||||
challenge = new AuthChallenge() {
|
||||
@Override
|
||||
public boolean challenge(HttpFacade exchange) {
|
||||
SamlAuthenticationError error = new SamlAuthenticationError(SamlAuthenticationError.Reason.INVALID_SIGNATURE);
|
||||
SamlAuthenticationError error = new SamlAuthenticationError(SamlAuthenticationError.Reason.INVALID_SIGNATURE, responseType);
|
||||
exchange.getRequest().setError(error);
|
||||
exchange.getResponse().sendError(403);
|
||||
return true;
|
||||
@@ -449,6 +465,14 @@ public abstract class AbstractSamlAuthenticationHandler implements SamlAuthentic
|
||||
return AuthOutcome.AUTHENTICATED;
|
||||
}
|
||||
|
||||
private boolean isSuccessfulSamlResponse(ResponseType responseType) {
|
||||
return responseType != null
|
||||
&& responseType.getStatus() != null
|
||||
&& responseType.getStatus().getStatusCode() != null
|
||||
&& responseType.getStatus().getStatusCode().getValue() != null
|
||||
&& Objects.equals(responseType.getStatus().getStatusCode().getValue().toString(), JBossSAMLURIConstants.STATUS_SUCCESS.get());
|
||||
}
|
||||
|
||||
private String getAttributeValue(Object attrValue) {
|
||||
String value = null;
|
||||
if (attrValue instanceof String) {
|
||||
|
||||
@@ -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.0.Final</version>
|
||||
<version>3.0.0.Final</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.0.Final</version>
|
||||
<version>3.0.0.Final</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 Jetty8SessionManager implements JettySessionManager {
|
||||
protected SessionManager sessionManager;
|
||||
|
||||
public Jetty8SessionManager(SessionManager sessionManager) {
|
||||
this.sessionManager = sessionManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
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.0.Final</version>
|
||||
<version>3.0.0.Final</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.0.Final</version>
|
||||
<version>3.0.0.Final</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.0.Final</version>
|
||||
<version>3.0.0.Final</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.Final</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.0.Final</version>
|
||||
<version>3.0.0.Final</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.0.Final</version>
|
||||
<version>3.0.0.Final</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.0.Final</version>
|
||||
<version>3.0.0.Final</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.0.Final</version>
|
||||
<version>3.0.0.Final</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.0.Final</version>
|
||||
<version>3.0.0.Final</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.0.Final</version>
|
||||
<version>3.0.0.Final</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
Loaded 100 of 1413 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user