Compare commits
510
Commits
3.3.0.CR1
...
3.4.1.Final
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e220ae80cc | ||
|
|
a79114f0f5 | ||
|
|
a3675c5d77 | ||
|
|
53ec81f03e | ||
|
|
b069ba27f0 | ||
|
|
4daf6aaec5 | ||
|
|
6bb04617a6 | ||
|
|
7b03eed9c8 | ||
|
|
b466f4d0b6 | ||
|
|
b8e5fd2b99 | ||
|
|
b72b01bb9d | ||
|
|
603052c594 | ||
|
|
106599b52c | ||
|
|
17748d5ba8 | ||
|
|
4caa40fd0a | ||
|
|
674fb31a2c | ||
|
|
c5d9301951 | ||
|
|
5f43a6a342 | ||
|
|
6587cfa084 | ||
|
|
6a528a3ee6 | ||
|
|
2be78a0239 | ||
|
|
4408cdb5c7 | ||
|
|
a3288d5f8e | ||
|
|
9cae8b79e4 | ||
|
|
0bd2e63162 | ||
|
|
9ffc11d04f | ||
|
|
af66c5dbd2 | ||
|
|
83136c1bd8 | ||
|
|
d22c58ee30 | ||
|
|
de6301e65a | ||
|
|
c02c07d78e | ||
|
|
f48509c32c | ||
|
|
c5b06f23e9 | ||
|
|
fc8a8b1dd8 | ||
|
|
bf73375a5c | ||
|
|
4240295af9 | ||
|
|
3afb635110 | ||
|
|
c36b3cd296 | ||
|
|
683fe6fa03 | ||
|
|
0a8995efc7 | ||
|
|
c398f6619f | ||
|
|
33c38ceb8b | ||
|
|
b0b28e6282 | ||
|
|
792ffdf39b | ||
|
|
36314c51d6 | ||
|
|
24b7e318ca | ||
|
|
cf485c3fc9 | ||
|
|
5666bfe88b | ||
|
|
27268044ae | ||
|
|
c860ca61c3 | ||
|
|
1782d220c7 | ||
|
|
c35c6e6ab7 | ||
|
|
0e2332196d | ||
|
|
a8bcdfb401 | ||
|
|
96e481fe45 | ||
|
|
87b17a6e6c | ||
|
|
6035e5c831 | ||
|
|
9d35891e7d | ||
|
|
00677a6b92 | ||
|
|
697caaa805 | ||
|
|
fda491a966 | ||
|
|
92504e8ba3 | ||
|
|
bb900f9db8 | ||
|
|
819a60932e | ||
|
|
e4a6ee19d1 | ||
|
|
aef682cd5b | ||
|
|
dd6502013e | ||
|
|
ecbf6e5386 | ||
|
|
2721e6a5e4 | ||
|
|
e3c9fa25a3 | ||
|
|
6d91ab674b | ||
|
|
6f4ab8870e | ||
|
|
0b3ae30473 | ||
|
|
94ba85c210 | ||
|
|
2117db5e6d | ||
|
|
116bfb05c2 | ||
|
|
aee6d16f58 | ||
|
|
ae29e36e1f | ||
|
|
02220558e6 | ||
|
|
12bdf48ecc | ||
|
|
bd1072d2eb | ||
|
|
61c5a332b4 | ||
|
|
75d517a1e8 | ||
|
|
8993ca08ad | ||
|
|
afd906b9a9 | ||
|
|
c083c1c4cf | ||
|
|
d78bc37253 | ||
|
|
d0ee1e6ee5 | ||
|
|
c16c02b0cf | ||
|
|
7fd237b40b | ||
|
|
a993f6fb75 | ||
|
|
5f20df00d0 | ||
|
|
186b10ab53 | ||
|
|
06762ba13d | ||
|
|
08ca03051c | ||
|
|
8f82440103 | ||
|
|
9485a63157 | ||
|
|
37b625fd99 | ||
|
|
8e53ccf5ab | ||
|
|
7c0c48da01 | ||
|
|
ff5010cdd0 | ||
|
|
0940c922ef | ||
|
|
83ff0eab10 | ||
|
|
c66ff60c58 | ||
|
|
feaf834184 | ||
|
|
805e9288fa | ||
|
|
641069d4fd | ||
|
|
a06fd31412 | ||
|
|
07aa718cb9 | ||
|
|
f186ea12c6 | ||
|
|
dc05134e41 | ||
|
|
f96c3312e2 | ||
|
|
d1579f62a3 | ||
|
|
86fb18395e | ||
|
|
bc28223a77 | ||
|
|
f923211e9f | ||
|
|
6f2ba821a6 | ||
|
|
8839278da7 | ||
|
|
485ba4a3e4 | ||
|
|
bd25040e22 | ||
|
|
c4a1764801 | ||
|
|
3c48ee39d9 | ||
|
|
a787cfa33a | ||
|
|
1bd2f0e98f | ||
|
|
393fae74b3 | ||
|
|
a2f6c16764 | ||
|
|
a70461b726 | ||
|
|
6b8ead6c4b | ||
|
|
8b023f57f9 | ||
|
|
eebf0b0499 | ||
|
|
63a01b1e1f | ||
|
|
913c94dbd1 | ||
|
|
0c414eee80 | ||
|
|
b0ccce397a | ||
|
|
6731c55429 | ||
|
|
fdb618219f | ||
|
|
89f4b87038 | ||
|
|
ea869a3008 | ||
|
|
1412fed265 | ||
|
|
de72542151 | ||
|
|
03d0488335 | ||
|
|
925d5e1dea | ||
|
|
d8b3654011 | ||
|
|
51c7917853 | ||
|
|
d30bf938ee | ||
|
|
5d8f449ea0 | ||
|
|
290f6ed2ad | ||
|
|
98a46c4497 | ||
|
|
d02ffd33b3 | ||
|
|
a5b73a365d | ||
|
|
71df504834 | ||
|
|
8cfbb8d0b3 | ||
|
|
0f4b8be2b0 | ||
|
|
af97a84108 | ||
|
|
e28f402b6b | ||
|
|
0dfbe01c73 | ||
|
|
90900b1a1f | ||
|
|
4295f4ec31 | ||
|
|
c530a061cc | ||
|
|
04ad634986 | ||
|
|
d4b9c3c014 | ||
|
|
bc3515fd1b | ||
|
|
b033ce0669 | ||
|
|
7035a4647d | ||
|
|
39345b0b61 | ||
|
|
8b8e694c60 | ||
|
|
a98f085be6 | ||
|
|
128ff12f8f | ||
|
|
e28652489e | ||
|
|
dae0fafc8a | ||
|
|
19eed51582 | ||
|
|
9ff22f596d | ||
|
|
e1af9f133f | ||
|
|
26e253f4a5 | ||
|
|
2854a2006e | ||
|
|
518824e41b | ||
|
|
3bf1904269 | ||
|
|
2c2a332f80 | ||
|
|
8759b42e6b | ||
|
|
bf937452c6 | ||
|
|
9243430b75 | ||
|
|
b21d5bbf04 | ||
|
|
5119dc3ad5 | ||
|
|
476dd1cef5 | ||
|
|
a8ba3eb7f9 | ||
|
|
d3b270d025 | ||
|
|
b8f3c8a445 | ||
|
|
eb46f403d6 | ||
|
|
9c0ec8cb10 | ||
|
|
d268412738 | ||
|
|
e360aadcd4 | ||
|
|
f88b3cddb6 | ||
|
|
56548fcaf0 | ||
|
|
fce9cc205c | ||
|
|
701b7acd80 | ||
|
|
819181007c | ||
|
|
7cf52044b2 | ||
|
|
d1468eaa45 | ||
|
|
afb4a59b19 | ||
|
|
b1a05dfce2 | ||
|
|
62a1c187a2 | ||
|
|
1db3134df8 | ||
|
|
ffc0d7fc7c | ||
|
|
fe2f65daac | ||
|
|
ef8adc15f4 | ||
|
|
1ac9bd510b | ||
|
|
4d0d28c222 | ||
|
|
6b0c58bab3 | ||
|
|
3716fa44ac | ||
|
|
d3dee07956 | ||
|
|
986540ab34 | ||
|
|
c9aa5e638e | ||
|
|
8d879867b5 | ||
|
|
92027e4c57 | ||
|
|
081ad09ed8 | ||
|
|
b0d88be420 | ||
|
|
57d3c44bb7 | ||
|
|
a70cab502c | ||
|
|
12b2e72162 | ||
|
|
a45a2acc4c | ||
|
|
8cbdbb2fed | ||
|
|
9e2ab2750a | ||
|
|
aabd47ecdf | ||
|
|
248da4687a | ||
|
|
2b44cb70af | ||
|
|
906538e6aa | ||
|
|
75c354fd94 | ||
|
|
9bd5d31c1f | ||
|
|
903a4dd849 | ||
|
|
de6eab6d5d | ||
|
|
8c1a3253fb | ||
|
|
375e01a074 | ||
|
|
74f5c1c160 | ||
|
|
5f889dd3c6 | ||
|
|
50ccb5e5f6 | ||
|
|
9793e6aa25 | ||
|
|
2dd6a2e655 | ||
|
|
1840cc54e4 | ||
|
|
7190820fc4 | ||
|
|
80e9b08bb6 | ||
|
|
4d762159ef | ||
|
|
a7bc294a08 | ||
|
|
8e0cc2a5ea | ||
|
|
bc12193c3c | ||
|
|
7dd7b6b984 | ||
|
|
711aa83d31 | ||
|
|
a6e1413d58 | ||
|
|
a4ec32ba66 | ||
|
|
9a19e95b60 | ||
|
|
f0bbcbf0fd | ||
|
|
223713bc53 | ||
|
|
330f2acc29 | ||
|
|
4010e5e247 | ||
|
|
574fd42534 | ||
|
|
9083e5fe5c | ||
|
|
1eb2d894e5 | ||
|
|
9b75b603e3 | ||
|
|
20d0fa1b4e | ||
|
|
faf830dc77 | ||
|
|
a3a1761eb7 | ||
|
|
6dd8592434 | ||
|
|
aaf25ad4f0 | ||
|
|
73ba06b26b | ||
|
|
92245e3fc8 | ||
|
|
1dd2a90e20 | ||
|
|
25d785df02 | ||
|
|
60d8236f05 | ||
|
|
54ebc21880 | ||
|
|
bd706418c9 | ||
|
|
0371a562d9 | ||
|
|
3248557897 | ||
|
|
00ea849cb9 | ||
|
|
0fbbe52ea7 | ||
|
|
5421c862e0 | ||
|
|
d9ffc4fa21 | ||
|
|
fea4c54adc | ||
|
|
8e5a6f9bf2 | ||
|
|
988d660083 | ||
|
|
4071dd7734 | ||
|
|
8faa6f1f4d | ||
|
|
19f54111ec | ||
|
|
cedc095a9c | ||
|
|
4c2ddfdf54 | ||
|
|
0fb99a0098 | ||
|
|
6d18ba4b32 | ||
|
|
649bca7618 | ||
|
|
d01be82b35 | ||
|
|
3103e0fd0a | ||
|
|
fe76b2428b | ||
|
|
2a818947c2 | ||
|
|
83b4279ce1 | ||
|
|
9c16a58d52 | ||
|
|
cb2bd0fe1a | ||
|
|
a42e0d6a31 | ||
|
|
056ba75a72 | ||
|
|
b6ab2852c2 | ||
|
|
9cbc335b68 | ||
|
|
e2f5ac60cf | ||
|
|
cb43e3d763 | ||
|
|
31dccc9a5e | ||
|
|
c66ce3a209 | ||
|
|
7c99a8b641 | ||
|
|
46d3ed7832 | ||
|
|
d9af93850c | ||
|
|
656fc5d7c0 | ||
|
|
1e57f277b8 | ||
|
|
4700b69158 | ||
|
|
1874820008 | ||
|
|
5b92b2bfb6 | ||
|
|
26f11078dc | ||
|
|
f5ff24ccdb | ||
|
|
a5c1bf1abf | ||
|
|
1ec2647b25 | ||
|
|
06ad4caa1b | ||
|
|
b0464f1751 | ||
|
|
5bd4ea30ad | ||
|
|
d336667972 | ||
|
|
50dd07217d | ||
|
|
ab8f4720d6 | ||
|
|
fe972ce12b | ||
|
|
c6483f8b1e | ||
|
|
12ab553d76 | ||
|
|
c8516c2349 | ||
|
|
6082e49252 | ||
|
|
7774d5c6b8 | ||
|
|
6cbfbeca0b | ||
|
|
00ddf03ad3 | ||
|
|
940715a975 | ||
|
|
a6e852495d | ||
|
|
34451d159b | ||
|
|
089a9e3321 | ||
|
|
c9da02912e | ||
|
|
25dbf1cfac | ||
|
|
945404be24 | ||
|
|
698483ee17 | ||
|
|
a877759d13 | ||
|
|
c4adf6805a | ||
|
|
730a2f7946 | ||
|
|
5cde17b38f | ||
|
|
9131e7e73c | ||
|
|
92941d0838 | ||
|
|
eab047c130 | ||
|
|
bca4c35708 | ||
|
|
9aa4c3cf22 | ||
|
|
b0a1550df5 | ||
|
|
89fade7ae4 | ||
|
|
8c7313f290 | ||
|
|
8e5db87b50 | ||
|
|
98c63bc195 | ||
|
|
6f6a467c7b | ||
|
|
f0f7321c38 | ||
|
|
da146f13c1 | ||
|
|
684c8dd0ce | ||
|
|
c2ffaa0777 | ||
|
|
632414cc92 | ||
|
|
f1593d3fb8 | ||
|
|
f806d4a5d6 | ||
|
|
da72968085 | ||
|
|
faa5ec5125 | ||
|
|
00fb767ad1 | ||
|
|
ef60512e09 | ||
|
|
ca6b82856e | ||
|
|
817d6cc8c7 | ||
|
|
c4cc752e18 | ||
|
|
4a7013d550 | ||
|
|
bb0bccc3c0 | ||
|
|
b17cbadaf3 | ||
|
|
7d641baf4e | ||
|
|
13fe9e7cf8 | ||
|
|
7fc94b8cad | ||
|
|
3b6e1f4e93 | ||
|
|
63673c4328 | ||
|
|
134daeac7f | ||
|
|
4c71e2ec17 | ||
|
|
d3c30c30d4 | ||
|
|
efb43682a9 | ||
|
|
d478cdfda4 | ||
|
|
d6f202e292 | ||
|
|
01187901ea | ||
|
|
f0ce4d4236 | ||
|
|
fd025ae76b | ||
|
|
9034708c99 | ||
|
|
9db6a5e0df | ||
|
|
f4b4c75d15 | ||
|
|
57c633967a | ||
|
|
1599e6db6e | ||
|
|
537081ec9d | ||
|
|
3020a04a8b | ||
|
|
7067ad1b07 | ||
|
|
790e2dc69f | ||
|
|
236b2b9273 | ||
|
|
9d452b4bc3 | ||
|
|
eb4f7f3b21 | ||
|
|
a551195ddf | ||
|
|
e78bf5f876 | ||
|
|
15ddb2009d | ||
|
|
8667f5ec02 | ||
|
|
05b0189773 | ||
|
|
8ace0e68c3 | ||
|
|
79c51a6a80 | ||
|
|
ab58052a4c | ||
|
|
7124d93a24 | ||
|
|
c67a1d0469 | ||
|
|
9d66d55ac1 | ||
|
|
657c68475d | ||
|
|
ad6e45bf22 | ||
|
|
c8a4fc2c57 | ||
|
|
87cad0d84b | ||
|
|
18031e2ed3 | ||
|
|
ca92bcbf7f | ||
|
|
fa35249afd | ||
|
|
e8ef050093 | ||
|
|
6b687c4318 | ||
|
|
b4aae198fc | ||
|
|
2276279434 | ||
|
|
5a22b360f1 | ||
|
|
f927ee7b4e | ||
|
|
21238ec35c | ||
|
|
42bb09fa31 | ||
|
|
34b8c58c0f | ||
|
|
3e6adbc904 | ||
|
|
a4315f4076 | ||
|
|
6ec5264f20 | ||
|
|
a6b9e5604c | ||
|
|
c999a0d8f9 | ||
|
|
affeadf4f3 | ||
|
|
c597123d1a | ||
|
|
ee35673615 | ||
|
|
9098105a64 | ||
|
|
685acb786a | ||
|
|
d18aa44fb4 | ||
|
|
e907da77d7 | ||
|
|
56e0a52197 | ||
|
|
8b2d47dd71 | ||
|
|
503ce3a47f | ||
|
|
867bb20339 | ||
|
|
b7af96aa4d | ||
|
|
550e5f752a | ||
|
|
cdb3c159c5 | ||
|
|
90db6654d3 | ||
|
|
c8c88dd58c | ||
|
|
5b1a761b0f | ||
|
|
7f8b5e032a | ||
|
|
db56d82dbd | ||
|
|
a485d7be53 | ||
|
|
2a1f40d487 | ||
|
|
d636bc2616 | ||
|
|
9673ce5541 | ||
|
|
cea88bd67f | ||
|
|
2cadf0a260 | ||
|
|
9c48da2a78 | ||
|
|
1a74288413 | ||
|
|
feeac52621 | ||
|
|
2637a9ccd4 | ||
|
|
e907a9aa6d | ||
|
|
24e9cbb292 | ||
|
|
458c2f2682 | ||
|
|
bf184e8599 | ||
|
|
cf47d49fc6 | ||
|
|
15949fcb02 | ||
|
|
9032889c15 | ||
|
|
a33007afb6 | ||
|
|
1ed5730769 | ||
|
|
9f660b48c4 | ||
|
|
473aefacec | ||
|
|
330cb022eb | ||
|
|
2c24b39268 | ||
|
|
352bc6b94b | ||
|
|
998262177f | ||
|
|
0a5de1239f | ||
|
|
f10891b662 | ||
|
|
c1664478d9 | ||
|
|
1fb8846a7a | ||
|
|
c8eeeffdeb | ||
|
|
9ed5fc5595 | ||
|
|
aaac85e541 | ||
|
|
37479a9afe | ||
|
|
ff354f6edc | ||
|
|
fe43c26829 | ||
|
|
30d8a7503b | ||
|
|
bb9a1335ec | ||
|
|
fa6d5f0ee2 | ||
|
|
d62164f6f0 | ||
|
|
f1628ab903 | ||
|
|
d2d5329f15 | ||
|
|
8c69306f2b | ||
|
|
e055589448 | ||
|
|
924b4f651a | ||
|
|
e36b94d905 | ||
|
|
7191048f91 | ||
|
|
b6ba6efe48 | ||
|
|
0570e6e218 | ||
|
|
8bfab22417 | ||
|
|
d3dc26181e | ||
|
|
433a8dd2e3 | ||
|
|
801205a5bc | ||
|
|
dcfa4aca8c | ||
|
|
a1247f8f92 | ||
|
|
944332a84a | ||
|
|
463661b051 | ||
|
|
e38dfff213 | ||
|
|
0a82a6b434 | ||
|
|
6a28971218 | ||
|
|
c8aa708cff | ||
|
|
1a50e77a4d | ||
|
|
41d8d17062 | ||
|
|
124bf43a27 | ||
|
|
6929dddacf | ||
|
|
f377a45c4e | ||
|
|
c4da7637d6 |
No files matched your search
+3
-1
@@ -52,4 +52,6 @@ target
|
|||||||
|
|
||||||
# nodejs #
|
# nodejs #
|
||||||
##########
|
##########
|
||||||
node_modules
|
# KEYCLOAK-5391: We will re-exclude node_modules when node_modules handling is worked out.
|
||||||
|
# For now, we keep our js libraries checked into GitHub, so we don't ignore.
|
||||||
|
#node_modules
|
||||||
@@ -15,6 +15,7 @@ env:
|
|||||||
- TESTS=server-group3
|
- TESTS=server-group3
|
||||||
- TESTS=server-group4
|
- TESTS=server-group4
|
||||||
- TESTS=old
|
- TESTS=old
|
||||||
|
- TESTS=crossdc
|
||||||
|
|
||||||
jdk:
|
jdk:
|
||||||
- oraclejdk8
|
- oraclejdk8
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ Starting Keycloak
|
|||||||
|
|
||||||
To start Keycloak during development first build as specified above, then run:
|
To start Keycloak during development first build as specified above, then run:
|
||||||
|
|
||||||
mvn -f testsuite/integration/pom.xml exec:java -Pkeycloak-server
|
mvn -f testsuite/utils/pom.xml exec:java -Pkeycloak-server
|
||||||
|
|
||||||
|
|
||||||
To start Keycloak from the server distribution first build the distribution it as specified above, then run:
|
To start Keycloak from the server distribution first build the distribution it as specified above, then run:
|
||||||
@@ -49,6 +49,10 @@ To start Keycloak from the server distribution first build the distribution it a
|
|||||||
|
|
||||||
To stop the server press `Ctrl + C`.
|
To stop the server press `Ctrl + C`.
|
||||||
|
|
||||||
|
Reporting security vulnerabilities
|
||||||
|
----------------------------------
|
||||||
|
|
||||||
|
If you've found a security vulnerability, please look at the [instructions on how to properly report it](http://www.keycloak.org/security.html)
|
||||||
|
|
||||||
Help and Documentation
|
Help and Documentation
|
||||||
----------------------
|
----------------------
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>3.3.0.CR1-SNAPSHOT</version>
|
<version>3.4.1.Final</version>
|
||||||
<relativePath>../../../pom.xml</relativePath>
|
<relativePath>../../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|||||||
+10
@@ -277,6 +277,16 @@ public class AdapterDeploymentContext {
|
|||||||
delegate.setSslRequired(sslRequired);
|
delegate.setSslRequired(sslRequired);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getConfidentialPort() {
|
||||||
|
return delegate.getConfidentialPort();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setConfidentialPort(int confidentialPort) {
|
||||||
|
delegate.setConfidentialPort(confidentialPort);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TokenStore getTokenStore() {
|
public TokenStore getTokenStore() {
|
||||||
return delegate.getTokenStore();
|
return delegate.getTokenStore();
|
||||||
|
|||||||
+6
-5
@@ -71,9 +71,10 @@ public class BasicAuthRequestAuthenticator extends BearerTokenRequestAuthenticat
|
|||||||
AccessTokenResponse atr=null;
|
AccessTokenResponse atr=null;
|
||||||
try {
|
try {
|
||||||
String userpw=new String(Base64.decode(tokenString));
|
String userpw=new String(Base64.decode(tokenString));
|
||||||
String[] parts=userpw.split(":");
|
int seperatorIndex = userpw.indexOf(":");
|
||||||
|
String user = userpw.substring(0, seperatorIndex);
|
||||||
atr = getToken(parts[0], parts[1]);
|
String pw = userpw.substring(seperatorIndex + 1);
|
||||||
|
atr = getToken(user, pw);
|
||||||
tokenString = atr.getToken();
|
tokenString = atr.getToken();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.debug("Failed to obtain token", e);
|
log.debug("Failed to obtain token", e);
|
||||||
@@ -82,8 +83,8 @@ public class BasicAuthRequestAuthenticator extends BearerTokenRequestAuthenticat
|
|||||||
}
|
}
|
||||||
|
|
||||||
return authenticateToken(exchange, atr.getToken());
|
return authenticateToken(exchange, atr.getToken());
|
||||||
}
|
}
|
||||||
|
|
||||||
private AccessTokenResponse getToken(String username, String password) throws Exception {
|
private AccessTokenResponse getToken(String username, String password) throws Exception {
|
||||||
AccessTokenResponse tokenResponse=null;
|
AccessTokenResponse tokenResponse=null;
|
||||||
HttpClient client = deployment.getClient();
|
HttpClient client = deployment.getClient();
|
||||||
|
|||||||
+19
-1
@@ -23,6 +23,8 @@ import org.keycloak.adapters.spi.AuthChallenge;
|
|||||||
import org.keycloak.adapters.spi.AuthOutcome;
|
import org.keycloak.adapters.spi.AuthOutcome;
|
||||||
import org.keycloak.adapters.spi.HttpFacade;
|
import org.keycloak.adapters.spi.HttpFacade;
|
||||||
import org.keycloak.common.VerificationException;
|
import org.keycloak.common.VerificationException;
|
||||||
|
import org.keycloak.jose.jws.JWSInput;
|
||||||
|
import org.keycloak.jose.jws.JWSInputException;
|
||||||
import org.keycloak.representations.AccessToken;
|
import org.keycloak.representations.AccessToken;
|
||||||
|
|
||||||
import javax.security.cert.X509Certificate;
|
import javax.security.cert.X509Certificate;
|
||||||
@@ -83,6 +85,16 @@ public class BearerTokenRequestAuthenticator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected AuthOutcome authenticateToken(HttpFacade exchange, String tokenString) {
|
protected AuthOutcome authenticateToken(HttpFacade exchange, String tokenString) {
|
||||||
|
log.debug("Verifying access_token");
|
||||||
|
if (log.isTraceEnabled()) {
|
||||||
|
try {
|
||||||
|
JWSInput jwsInput = new JWSInput(tokenString);
|
||||||
|
String wireString = jwsInput.getWireString();
|
||||||
|
log.tracef("\taccess_token: %s", wireString.substring(0, wireString.lastIndexOf(".")) + ".signature");
|
||||||
|
} catch (JWSInputException e) {
|
||||||
|
log.errorf(e, "Failed to parse access_token: %s", tokenString);
|
||||||
|
}
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
token = AdapterRSATokenVerifier.verifyToken(tokenString, deployment);
|
token = AdapterRSATokenVerifier.verifyToken(tokenString, deployment);
|
||||||
} catch (VerificationException e) {
|
} catch (VerificationException e) {
|
||||||
@@ -124,6 +136,7 @@ public class BearerTokenRequestAuthenticator {
|
|||||||
}
|
}
|
||||||
surrogate = chain[0].getSubjectDN().getName();
|
surrogate = chain[0].getSubjectDN().getName();
|
||||||
}
|
}
|
||||||
|
log.debug("successful authorized");
|
||||||
return AuthOutcome.AUTHENTICATED;
|
return AuthOutcome.AUTHENTICATED;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -164,7 +177,12 @@ public class BearerTokenRequestAuthenticator {
|
|||||||
OIDCAuthenticationError error = new OIDCAuthenticationError(reason, description);
|
OIDCAuthenticationError error = new OIDCAuthenticationError(reason, description);
|
||||||
facade.getRequest().setError(error);
|
facade.getRequest().setError(error);
|
||||||
facade.getResponse().addHeader("WWW-Authenticate", challenge);
|
facade.getResponse().addHeader("WWW-Authenticate", challenge);
|
||||||
facade.getResponse().sendError(401);
|
if(deployment.isDelegateBearerErrorResponseSending()){
|
||||||
|
facade.getResponse().setStatus(401);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
facade.getResponse().sendError(401);
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
+19
-2
@@ -68,6 +68,7 @@ public class KeycloakDeployment {
|
|||||||
|
|
||||||
protected String scope;
|
protected String scope;
|
||||||
protected SslRequired sslRequired = SslRequired.ALL;
|
protected SslRequired sslRequired = SslRequired.ALL;
|
||||||
|
protected int confidentialPort = -1;
|
||||||
protected TokenStore tokenStore = TokenStore.SESSION;
|
protected TokenStore tokenStore = TokenStore.SESSION;
|
||||||
protected String stateCookieName = "OAuth_Token_Request_State";
|
protected String stateCookieName = "OAuth_Token_Request_State";
|
||||||
protected boolean useResourceRoleMappings;
|
protected boolean useResourceRoleMappings;
|
||||||
@@ -94,6 +95,8 @@ public class KeycloakDeployment {
|
|||||||
|
|
||||||
protected Map<String, String> redirectRewriteRules;
|
protected Map<String, String> redirectRewriteRules;
|
||||||
|
|
||||||
|
protected boolean delegateBearerErrorResponseSending = false;
|
||||||
|
|
||||||
public KeycloakDeployment() {
|
public KeycloakDeployment() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -275,6 +278,14 @@ public class KeycloakDeployment {
|
|||||||
this.sslRequired = sslRequired;
|
this.sslRequired = sslRequired;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getConfidentialPort() {
|
||||||
|
return confidentialPort;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setConfidentialPort(int confidentialPort) {
|
||||||
|
this.confidentialPort = confidentialPort;
|
||||||
|
}
|
||||||
|
|
||||||
public TokenStore getTokenStore() {
|
public TokenStore getTokenStore() {
|
||||||
return tokenStore;
|
return tokenStore;
|
||||||
}
|
}
|
||||||
@@ -456,6 +467,12 @@ public class KeycloakDeployment {
|
|||||||
public void setRewriteRedirectRules(Map<String, String> redirectRewriteRules) {
|
public void setRewriteRedirectRules(Map<String, String> redirectRewriteRules) {
|
||||||
this.redirectRewriteRules = redirectRewriteRules;
|
this.redirectRewriteRules = redirectRewriteRules;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isDelegateBearerErrorResponseSending() {
|
||||||
|
return delegateBearerErrorResponseSending;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDelegateBearerErrorResponseSending(boolean delegateBearerErrorResponseSending) {
|
||||||
|
this.delegateBearerErrorResponseSending = delegateBearerErrorResponseSending;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+5
@@ -78,6 +78,11 @@ public class KeycloakDeploymentBuilder {
|
|||||||
} else {
|
} else {
|
||||||
deployment.setSslRequired(SslRequired.EXTERNAL);
|
deployment.setSslRequired(SslRequired.EXTERNAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (adapterConfig.getConfidentialPort() != -1) {
|
||||||
|
deployment.setConfidentialPort(adapterConfig.getConfidentialPort());
|
||||||
|
}
|
||||||
|
|
||||||
if (adapterConfig.getTokenStore() != null) {
|
if (adapterConfig.getTokenStore() != null) {
|
||||||
deployment.setTokenStore(TokenStore.valueOf(adapterConfig.getTokenStore().toUpperCase()));
|
deployment.setTokenStore(TokenStore.valueOf(adapterConfig.getTokenStore().toUpperCase()));
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
+25
-2
@@ -66,7 +66,7 @@ public class OAuthRequestAuthenticator {
|
|||||||
this.reqAuthenticator = requestAuthenticator;
|
this.reqAuthenticator = requestAuthenticator;
|
||||||
this.facade = facade;
|
this.facade = facade;
|
||||||
this.deployment = deployment;
|
this.deployment = deployment;
|
||||||
this.sslRedirectPort = sslRedirectPort;
|
this.sslRedirectPort = deployment.getConfidentialPort() != -1 ? deployment.getConfidentialPort() : sslRedirectPort;
|
||||||
this.tokenStore = tokenStore;
|
this.tokenStore = tokenStore;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -170,6 +170,9 @@ public class OAuthRequestAuthenticator {
|
|||||||
String maxAge = getQueryParamValue(OAuth2Constants.MAX_AGE);
|
String maxAge = getQueryParamValue(OAuth2Constants.MAX_AGE);
|
||||||
url = UriUtils.stripQueryParam(url, OAuth2Constants.MAX_AGE);
|
url = UriUtils.stripQueryParam(url, OAuth2Constants.MAX_AGE);
|
||||||
|
|
||||||
|
String uiLocales = getQueryParamValue(OAuth2Constants.UI_LOCALES_PARAM);
|
||||||
|
url = UriUtils.stripQueryParam(url, OAuth2Constants.UI_LOCALES_PARAM);
|
||||||
|
|
||||||
KeycloakUriBuilder redirectUriBuilder = deployment.getAuthUrl().clone()
|
KeycloakUriBuilder redirectUriBuilder = deployment.getAuthUrl().clone()
|
||||||
.queryParam(OAuth2Constants.RESPONSE_TYPE, OAuth2Constants.CODE)
|
.queryParam(OAuth2Constants.RESPONSE_TYPE, OAuth2Constants.CODE)
|
||||||
.queryParam(OAuth2Constants.CLIENT_ID, deployment.getResourceName())
|
.queryParam(OAuth2Constants.CLIENT_ID, deployment.getResourceName())
|
||||||
@@ -188,6 +191,9 @@ public class OAuthRequestAuthenticator {
|
|||||||
if (maxAge != null && maxAge.length() > 0) {
|
if (maxAge != null && maxAge.length() > 0) {
|
||||||
redirectUriBuilder.queryParam(OAuth2Constants.MAX_AGE, maxAge);
|
redirectUriBuilder.queryParam(OAuth2Constants.MAX_AGE, maxAge);
|
||||||
}
|
}
|
||||||
|
if (uiLocales != null && uiLocales.length() > 0) {
|
||||||
|
redirectUriBuilder.queryParam(OAuth2Constants.UI_LOCALES_PARAM, uiLocales);
|
||||||
|
}
|
||||||
|
|
||||||
scope = TokenUtil.attachOIDCScope(scope);
|
scope = TokenUtil.attachOIDCScope(scope);
|
||||||
redirectUriBuilder.queryParam(OAuth2Constants.SCOPE, scope);
|
redirectUriBuilder.queryParam(OAuth2Constants.SCOPE, scope);
|
||||||
@@ -331,7 +337,7 @@ public class OAuthRequestAuthenticator {
|
|||||||
} catch (ServerRequest.HttpFailure failure) {
|
} catch (ServerRequest.HttpFailure failure) {
|
||||||
log.error("failed to turn code into token");
|
log.error("failed to turn code into token");
|
||||||
log.error("status from server: " + failure.getStatus());
|
log.error("status from server: " + failure.getStatus());
|
||||||
if (failure.getStatus() == 400 && failure.getError() != null) {
|
if (failure.getError() != null) {
|
||||||
log.error(" " + failure.getError());
|
log.error(" " + failure.getError());
|
||||||
}
|
}
|
||||||
return challenge(403, OIDCAuthenticationError.Reason.CODE_TO_TOKEN_FAILURE, null);
|
return challenge(403, OIDCAuthenticationError.Reason.CODE_TO_TOKEN_FAILURE, null);
|
||||||
@@ -344,6 +350,14 @@ public class OAuthRequestAuthenticator {
|
|||||||
tokenString = tokenResponse.getToken();
|
tokenString = tokenResponse.getToken();
|
||||||
refreshToken = tokenResponse.getRefreshToken();
|
refreshToken = tokenResponse.getRefreshToken();
|
||||||
idTokenString = tokenResponse.getIdToken();
|
idTokenString = tokenResponse.getIdToken();
|
||||||
|
|
||||||
|
log.debug("Verifying tokens");
|
||||||
|
if (log.isTraceEnabled()) {
|
||||||
|
logToken("\taccess_token", tokenString);
|
||||||
|
logToken("\tid_token", idTokenString);
|
||||||
|
logToken("\trefresh_token", refreshToken);
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
token = AdapterRSATokenVerifier.verifyToken(tokenString, deployment);
|
token = AdapterRSATokenVerifier.verifyToken(tokenString, deployment);
|
||||||
if (idTokenString != null) {
|
if (idTokenString != null) {
|
||||||
@@ -398,4 +412,13 @@ public class OAuthRequestAuthenticator {
|
|||||||
return originalUri;
|
return originalUri;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void logToken(String name, String token) {
|
||||||
|
try {
|
||||||
|
JWSInput jwsInput = new JWSInput(token);
|
||||||
|
String wireString = jwsInput.getWireString();
|
||||||
|
log.tracef("\t%s: %s", name, wireString.substring(0, wireString.lastIndexOf(".")) + ".signature");
|
||||||
|
} catch (JWSInputException e) {
|
||||||
|
log.errorf(e, "Failed to parse %s: %s", name, token);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+1
-1
@@ -32,7 +32,7 @@ import java.util.Map;
|
|||||||
*/
|
*/
|
||||||
public class ClientIdAndSecretCredentialsProvider implements ClientCredentialsProvider {
|
public class ClientIdAndSecretCredentialsProvider implements ClientCredentialsProvider {
|
||||||
|
|
||||||
private static Logger logger = Logger.getLogger(ClientCredentialsProviderUtils.class);
|
private static Logger logger = Logger.getLogger(ClientIdAndSecretCredentialsProvider.class);
|
||||||
|
|
||||||
public static final String PROVIDER_ID = CredentialRepresentation.SECRET;
|
public static final String PROVIDER_ID = CredentialRepresentation.SECRET;
|
||||||
|
|
||||||
|
|||||||
+41
-18
@@ -33,6 +33,7 @@ import org.keycloak.authorization.client.ClientAuthorizationContext;
|
|||||||
import org.keycloak.representations.AccessToken;
|
import org.keycloak.representations.AccessToken;
|
||||||
import org.keycloak.representations.adapters.config.PolicyEnforcerConfig;
|
import org.keycloak.representations.adapters.config.PolicyEnforcerConfig;
|
||||||
import org.keycloak.representations.adapters.config.PolicyEnforcerConfig.EnforcementMode;
|
import org.keycloak.representations.adapters.config.PolicyEnforcerConfig.EnforcementMode;
|
||||||
|
import org.keycloak.representations.adapters.config.PolicyEnforcerConfig.MethodConfig;
|
||||||
import org.keycloak.representations.adapters.config.PolicyEnforcerConfig.PathConfig;
|
import org.keycloak.representations.adapters.config.PolicyEnforcerConfig.PathConfig;
|
||||||
import org.keycloak.representations.idm.authorization.Permission;
|
import org.keycloak.representations.idm.authorization.Permission;
|
||||||
|
|
||||||
@@ -96,9 +97,9 @@ public abstract class AbstractPolicyEnforcer {
|
|||||||
return createEmptyAuthorizationContext(true);
|
return createEmptyAuthorizationContext(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
Set<String> requiredScopes = getRequiredScopes(pathConfig, request);
|
MethodConfig methodConfig = getRequiredScopes(pathConfig, request);
|
||||||
|
|
||||||
if (isAuthorized(pathConfig, requiredScopes, accessToken, httpFacade)) {
|
if (isAuthorized(pathConfig, methodConfig, accessToken, httpFacade)) {
|
||||||
try {
|
try {
|
||||||
return createAuthorizationContext(accessToken, pathConfig);
|
return createAuthorizationContext(accessToken, pathConfig);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
@@ -108,7 +109,7 @@ public abstract class AbstractPolicyEnforcer {
|
|||||||
|
|
||||||
LOGGER.debugf("Sending challenge to the client. Path [%s]", pathConfig);
|
LOGGER.debugf("Sending challenge to the client. Path [%s]", pathConfig);
|
||||||
|
|
||||||
if (!challenge(pathConfig, requiredScopes, httpFacade)) {
|
if (!challenge(pathConfig, methodConfig, httpFacade)) {
|
||||||
LOGGER.debugf("Challenge not sent, sending default forbidden response. Path [%s]", pathConfig);
|
LOGGER.debugf("Challenge not sent, sending default forbidden response. Path [%s]", pathConfig);
|
||||||
handleAccessDenied(httpFacade);
|
handleAccessDenied(httpFacade);
|
||||||
}
|
}
|
||||||
@@ -118,9 +119,9 @@ public abstract class AbstractPolicyEnforcer {
|
|||||||
return createEmptyAuthorizationContext(false);
|
return createEmptyAuthorizationContext(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract boolean challenge(PathConfig pathConfig, Set<String> requiredScopes, OIDCHttpFacade facade);
|
protected abstract boolean challenge(PathConfig pathConfig, MethodConfig methodConfig, OIDCHttpFacade facade);
|
||||||
|
|
||||||
protected boolean isAuthorized(PathConfig actualPathConfig, Set<String> requiredScopes, AccessToken accessToken, OIDCHttpFacade httpFacade) {
|
protected boolean isAuthorized(PathConfig actualPathConfig, MethodConfig methodConfig, AccessToken accessToken, OIDCHttpFacade httpFacade) {
|
||||||
Request request = httpFacade.getRequest();
|
Request request = httpFacade.getRequest();
|
||||||
PolicyEnforcerConfig enforcerConfig = getEnforcerConfig();
|
PolicyEnforcerConfig enforcerConfig = getEnforcerConfig();
|
||||||
|
|
||||||
@@ -146,7 +147,7 @@ public abstract class AbstractPolicyEnforcer {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasResourceScopePermission(requiredScopes, permission, actualPathConfig)) {
|
if (hasResourceScopePermission(methodConfig, permission)) {
|
||||||
LOGGER.debugf("Authorization GRANTED for path [%s]. Permissions [%s].", actualPathConfig, permissions);
|
LOGGER.debugf("Authorization GRANTED for path [%s]. Permissions [%s].", actualPathConfig, permissions);
|
||||||
if (request.getMethod().equalsIgnoreCase("DELETE") && actualPathConfig.isInstance()) {
|
if (request.getMethod().equalsIgnoreCase("DELETE") && actualPathConfig.isInstance()) {
|
||||||
this.paths.remove(actualPathConfig);
|
this.paths.remove(actualPathConfig);
|
||||||
@@ -155,7 +156,7 @@ public abstract class AbstractPolicyEnforcer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (hasResourceScopePermission(requiredScopes, permission, actualPathConfig)) {
|
if (hasResourceScopePermission(methodConfig, permission)) {
|
||||||
hasPermission = true;
|
hasPermission = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -166,7 +167,7 @@ public abstract class AbstractPolicyEnforcer {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOGGER.debugf("Authorization FAILED for path [%s]. No enough permissions [%s].", actualPathConfig, permissions);
|
LOGGER.debugf("Authorization FAILED for path [%s]. Not enough permissions [%s].", actualPathConfig, permissions);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -186,9 +187,29 @@ public abstract class AbstractPolicyEnforcer {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean hasResourceScopePermission(Set<String> requiredScopes, Permission permission, PathConfig actualPathConfig) {
|
private boolean hasResourceScopePermission(MethodConfig methodConfig, Permission permission) {
|
||||||
|
List<String> requiredScopes = methodConfig.getScopes();
|
||||||
Set<String> allowedScopes = permission.getScopes();
|
Set<String> allowedScopes = permission.getScopes();
|
||||||
return (allowedScopes.containsAll(requiredScopes) || allowedScopes.isEmpty());
|
|
||||||
|
if (allowedScopes.isEmpty()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
PolicyEnforcerConfig.ScopeEnforcementMode enforcementMode = methodConfig.getScopesEnforcementMode();
|
||||||
|
|
||||||
|
if (PolicyEnforcerConfig.ScopeEnforcementMode.ALL.equals(enforcementMode)) {
|
||||||
|
return allowedScopes.containsAll(requiredScopes);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (PolicyEnforcerConfig.ScopeEnforcementMode.ANY.equals(enforcementMode)) {
|
||||||
|
for (String requiredScope : requiredScopes) {
|
||||||
|
if (allowedScopes.contains(requiredScope)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return requiredScopes.isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected AuthzClient getAuthzClient() {
|
protected AuthzClient getAuthzClient() {
|
||||||
@@ -236,20 +257,22 @@ public abstract class AbstractPolicyEnforcer {
|
|||||||
return request.getRelativePath();
|
return request.getRelativePath();
|
||||||
}
|
}
|
||||||
|
|
||||||
private Set<String> getRequiredScopes(PathConfig pathConfig, Request request) {
|
private MethodConfig getRequiredScopes(PathConfig pathConfig, Request request) {
|
||||||
Set<String> requiredScopes = new HashSet<>();
|
|
||||||
|
|
||||||
requiredScopes.addAll(pathConfig.getScopes());
|
|
||||||
|
|
||||||
String method = request.getMethod();
|
String method = request.getMethod();
|
||||||
|
|
||||||
for (PolicyEnforcerConfig.MethodConfig methodConfig : pathConfig.getMethods()) {
|
for (MethodConfig methodConfig : pathConfig.getMethods()) {
|
||||||
if (methodConfig.getMethod().equals(method)) {
|
if (methodConfig.getMethod().equals(method)) {
|
||||||
requiredScopes.addAll(methodConfig.getScopes());
|
return methodConfig;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return requiredScopes;
|
MethodConfig methodConfig = new MethodConfig();
|
||||||
|
|
||||||
|
methodConfig.setMethod(request.getMethod());
|
||||||
|
methodConfig.setScopes(pathConfig.getScopes());
|
||||||
|
methodConfig.setScopesEnforcementMode(PolicyEnforcerConfig.ScopeEnforcementMode.ANY);
|
||||||
|
|
||||||
|
return methodConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
private AuthorizationContext createAuthorizationContext(AccessToken accessToken, PathConfig pathConfig) {
|
private AuthorizationContext createAuthorizationContext(AccessToken accessToken, PathConfig pathConfig) {
|
||||||
|
|||||||
+8
-7
@@ -17,7 +17,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.keycloak.adapters.authorization;
|
package org.keycloak.adapters.authorization;
|
||||||
|
|
||||||
import java.util.Set;
|
import java.util.HashSet;
|
||||||
|
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
import org.keycloak.adapters.OIDCHttpFacade;
|
import org.keycloak.adapters.OIDCHttpFacade;
|
||||||
@@ -26,6 +26,7 @@ import org.keycloak.authorization.client.AuthzClient;
|
|||||||
import org.keycloak.authorization.client.representation.PermissionRequest;
|
import org.keycloak.authorization.client.representation.PermissionRequest;
|
||||||
import org.keycloak.authorization.client.resource.PermissionResource;
|
import org.keycloak.authorization.client.resource.PermissionResource;
|
||||||
import org.keycloak.authorization.client.resource.ProtectionResource;
|
import org.keycloak.authorization.client.resource.ProtectionResource;
|
||||||
|
import org.keycloak.representations.adapters.config.PolicyEnforcerConfig;
|
||||||
import org.keycloak.representations.adapters.config.PolicyEnforcerConfig.PathConfig;
|
import org.keycloak.representations.adapters.config.PolicyEnforcerConfig.PathConfig;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -40,9 +41,9 @@ public class BearerTokenPolicyEnforcer extends AbstractPolicyEnforcer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean challenge(PathConfig pathConfig, Set<String> requiredScopes, OIDCHttpFacade facade) {
|
protected boolean challenge(PathConfig pathConfig, PolicyEnforcerConfig.MethodConfig methodConfig, OIDCHttpFacade facade) {
|
||||||
if (getEnforcerConfig().getUserManagedAccess() != null) {
|
if (getEnforcerConfig().getUserManagedAccess() != null) {
|
||||||
challengeUmaAuthentication(pathConfig, requiredScopes, facade);
|
challengeUmaAuthentication(pathConfig, methodConfig, facade);
|
||||||
} else {
|
} else {
|
||||||
challengeEntitlementAuthentication(facade);
|
challengeEntitlementAuthentication(facade);
|
||||||
}
|
}
|
||||||
@@ -61,10 +62,10 @@ public class BearerTokenPolicyEnforcer extends AbstractPolicyEnforcer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void challengeUmaAuthentication(PathConfig pathConfig, Set<String> requiredScopes, OIDCHttpFacade facade) {
|
private void challengeUmaAuthentication(PathConfig pathConfig, PolicyEnforcerConfig.MethodConfig methodConfig, OIDCHttpFacade facade) {
|
||||||
HttpFacade.Response response = facade.getResponse();
|
HttpFacade.Response response = facade.getResponse();
|
||||||
AuthzClient authzClient = getAuthzClient();
|
AuthzClient authzClient = getAuthzClient();
|
||||||
String ticket = getPermissionTicket(pathConfig, requiredScopes, authzClient);
|
String ticket = getPermissionTicket(pathConfig, methodConfig, authzClient);
|
||||||
String clientId = authzClient.getConfiguration().getResource();
|
String clientId = authzClient.getConfiguration().getResource();
|
||||||
String authorizationServerUri = authzClient.getServerConfiguration().getIssuer().toString() + "/authz/authorize";
|
String authorizationServerUri = authzClient.getServerConfiguration().getIssuer().toString() + "/authz/authorize";
|
||||||
response.setStatus(401);
|
response.setStatus(401);
|
||||||
@@ -74,12 +75,12 @@ public class BearerTokenPolicyEnforcer extends AbstractPolicyEnforcer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getPermissionTicket(PathConfig pathConfig, Set<String> requiredScopes, AuthzClient authzClient) {
|
private String getPermissionTicket(PathConfig pathConfig, PolicyEnforcerConfig.MethodConfig methodConfig, AuthzClient authzClient) {
|
||||||
ProtectionResource protection = authzClient.protection();
|
ProtectionResource protection = authzClient.protection();
|
||||||
PermissionResource permission = protection.permission();
|
PermissionResource permission = protection.permission();
|
||||||
PermissionRequest permissionRequest = new PermissionRequest();
|
PermissionRequest permissionRequest = new PermissionRequest();
|
||||||
permissionRequest.setResourceSetId(pathConfig.getId());
|
permissionRequest.setResourceSetId(pathConfig.getId());
|
||||||
permissionRequest.setScopes(requiredScopes);
|
permissionRequest.setScopes(new HashSet<>(methodConfig.getScopes()));
|
||||||
return permission.forResource(permissionRequest).getTicket();
|
return permission.forResource(permissionRequest).getTicket();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+8
-7
@@ -35,6 +35,7 @@ import org.keycloak.authorization.client.representation.EntitlementResponse;
|
|||||||
import org.keycloak.authorization.client.representation.PermissionRequest;
|
import org.keycloak.authorization.client.representation.PermissionRequest;
|
||||||
import org.keycloak.authorization.client.representation.PermissionResponse;
|
import org.keycloak.authorization.client.representation.PermissionResponse;
|
||||||
import org.keycloak.representations.AccessToken;
|
import org.keycloak.representations.AccessToken;
|
||||||
|
import org.keycloak.representations.adapters.config.PolicyEnforcerConfig;
|
||||||
import org.keycloak.representations.adapters.config.PolicyEnforcerConfig.PathConfig;
|
import org.keycloak.representations.adapters.config.PolicyEnforcerConfig.PathConfig;
|
||||||
import org.keycloak.representations.idm.authorization.Permission;
|
import org.keycloak.representations.idm.authorization.Permission;
|
||||||
|
|
||||||
@@ -50,14 +51,14 @@ public class KeycloakAdapterPolicyEnforcer extends AbstractPolicyEnforcer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean isAuthorized(PathConfig pathConfig, Set<String> requiredScopes, AccessToken accessToken, OIDCHttpFacade httpFacade) {
|
protected boolean isAuthorized(PathConfig pathConfig, PolicyEnforcerConfig.MethodConfig methodConfig, AccessToken accessToken, OIDCHttpFacade httpFacade) {
|
||||||
AccessToken original = accessToken;
|
AccessToken original = accessToken;
|
||||||
|
|
||||||
if (super.isAuthorized(pathConfig, requiredScopes, accessToken, httpFacade)) {
|
if (super.isAuthorized(pathConfig, methodConfig, accessToken, httpFacade)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
accessToken = requestAuthorizationToken(pathConfig, requiredScopes, httpFacade);
|
accessToken = requestAuthorizationToken(pathConfig, methodConfig, httpFacade);
|
||||||
|
|
||||||
if (accessToken == null) {
|
if (accessToken == null) {
|
||||||
return false;
|
return false;
|
||||||
@@ -78,11 +79,11 @@ public class KeycloakAdapterPolicyEnforcer extends AbstractPolicyEnforcer {
|
|||||||
|
|
||||||
original.setAuthorization(authorization);
|
original.setAuthorization(authorization);
|
||||||
|
|
||||||
return super.isAuthorized(pathConfig, requiredScopes, accessToken, httpFacade);
|
return super.isAuthorized(pathConfig, methodConfig, accessToken, httpFacade);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean challenge(PathConfig pathConfig, Set<String> requiredScopes, OIDCHttpFacade facade) {
|
protected boolean challenge(PathConfig pathConfig, PolicyEnforcerConfig.MethodConfig methodConfig, OIDCHttpFacade facade) {
|
||||||
handleAccessDenied(facade);
|
handleAccessDenied(facade);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -100,7 +101,7 @@ public class KeycloakAdapterPolicyEnforcer extends AbstractPolicyEnforcer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private AccessToken requestAuthorizationToken(PathConfig pathConfig, Set<String> requiredScopes, OIDCHttpFacade httpFacade) {
|
private AccessToken requestAuthorizationToken(PathConfig pathConfig, PolicyEnforcerConfig.MethodConfig methodConfig, OIDCHttpFacade httpFacade) {
|
||||||
try {
|
try {
|
||||||
String accessToken = httpFacade.getSecurityContext().getTokenString();
|
String accessToken = httpFacade.getSecurityContext().getTokenString();
|
||||||
AuthzClient authzClient = getAuthzClient();
|
AuthzClient authzClient = getAuthzClient();
|
||||||
@@ -111,7 +112,7 @@ public class KeycloakAdapterPolicyEnforcer extends AbstractPolicyEnforcer {
|
|||||||
PermissionRequest permissionRequest = new PermissionRequest();
|
PermissionRequest permissionRequest = new PermissionRequest();
|
||||||
|
|
||||||
permissionRequest.setResourceSetId(pathConfig.getId());
|
permissionRequest.setResourceSetId(pathConfig.getId());
|
||||||
permissionRequest.setScopes(requiredScopes);
|
permissionRequest.setScopes(new HashSet<>(methodConfig.getScopes()));
|
||||||
|
|
||||||
PermissionResponse permissionResponse = authzClient.protection().permission().forResource(permissionRequest);
|
PermissionResponse permissionResponse = authzClient.protection().permission().forResource(permissionRequest);
|
||||||
AuthorizationRequest authzRequest = new AuthorizationRequest(permissionResponse.getTicket());
|
AuthorizationRequest authzRequest = new AuthorizationRequest(permissionResponse.getTicket());
|
||||||
|
|||||||
+19
-2
@@ -37,8 +37,12 @@ import javax.security.auth.callback.PasswordCallback;
|
|||||||
import javax.security.auth.callback.UnsupportedCallbackException;
|
import javax.security.auth.callback.UnsupportedCallbackException;
|
||||||
import javax.security.auth.login.LoginException;
|
import javax.security.auth.login.LoginException;
|
||||||
import javax.security.auth.spi.LoginModule;
|
import javax.security.auth.spi.LoginModule;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.lang.reflect.Constructor;
|
import java.lang.reflect.Constructor;
|
||||||
|
import java.net.MalformedURLException;
|
||||||
|
import java.net.URL;
|
||||||
import java.security.Principal;
|
import java.security.Principal;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@@ -53,7 +57,7 @@ public abstract class AbstractKeycloakLoginModule implements LoginModule {
|
|||||||
|
|
||||||
public static final String KEYCLOAK_CONFIG_FILE_OPTION = "keycloak-config-file";
|
public static final String KEYCLOAK_CONFIG_FILE_OPTION = "keycloak-config-file";
|
||||||
public static final String ROLE_PRINCIPAL_CLASS_OPTION = "role-principal-class";
|
public static final String ROLE_PRINCIPAL_CLASS_OPTION = "role-principal-class";
|
||||||
|
public static final String PROFILE_RESOURCE = "profile:";
|
||||||
protected Subject subject;
|
protected Subject subject;
|
||||||
protected CallbackHandler callbackHandler;
|
protected CallbackHandler callbackHandler;
|
||||||
protected Auth auth;
|
protected Auth auth;
|
||||||
@@ -84,14 +88,27 @@ public abstract class AbstractKeycloakLoginModule implements LoginModule {
|
|||||||
|
|
||||||
protected KeycloakDeployment resolveDeployment(String keycloakConfigFile) {
|
protected KeycloakDeployment resolveDeployment(String keycloakConfigFile) {
|
||||||
try {
|
try {
|
||||||
InputStream is = FindFile.findFile(keycloakConfigFile);
|
InputStream is = null;
|
||||||
|
if (keycloakConfigFile.startsWith(PROFILE_RESOURCE)) {
|
||||||
|
try {
|
||||||
|
is = new URL(keycloakConfigFile).openStream();
|
||||||
|
} catch (MalformedURLException mfue) {
|
||||||
|
throw new RuntimeException(mfue);
|
||||||
|
} catch (IOException ioe) {
|
||||||
|
throw new RuntimeException(ioe);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
is = FindFile.findFile(keycloakConfigFile);
|
||||||
|
}
|
||||||
KeycloakDeployment kd = KeycloakDeploymentBuilder.build(is);
|
KeycloakDeployment kd = KeycloakDeploymentBuilder.build(is);
|
||||||
return kd;
|
return kd;
|
||||||
|
|
||||||
} catch (RuntimeException e) {
|
} catch (RuntimeException e) {
|
||||||
getLogger().debug("Unable to find or parse file " + keycloakConfigFile + " due to " + e.getMessage(), e);
|
getLogger().debug("Unable to find or parse file " + keycloakConfigFile + " due to " + e.getMessage(), e);
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean login() throws LoginException {
|
public boolean login() throws LoginException {
|
||||||
|
|||||||
+1
-1
@@ -81,7 +81,7 @@ public class JWKPublicKeyLocator implements PublicKeyLocator {
|
|||||||
|
|
||||||
|
|
||||||
private PublicKey lookupCachedKey(int publicKeyCacheTtl, int currentTime, String kid) {
|
private PublicKey lookupCachedKey(int publicKeyCacheTtl, int currentTime, String kid) {
|
||||||
if (lastRequestTime + publicKeyCacheTtl > currentTime) {
|
if (lastRequestTime + publicKeyCacheTtl > currentTime && kid != null) {
|
||||||
return currentKeys.get(kid);
|
return currentKeys.get(kid);
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-as7-integration-pom</artifactId>
|
<artifactId>keycloak-as7-integration-pom</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>3.3.0.CR1-SNAPSHOT</version>
|
<version>3.4.1.Final</version>
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-as7-integration-pom</artifactId>
|
<artifactId>keycloak-as7-integration-pom</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>3.3.0.CR1-SNAPSHOT</version>
|
<version>3.4.1.Final</version>
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|||||||
+13
@@ -0,0 +1,13 @@
|
|||||||
|
package org.keycloak.adapters.jbossweb;
|
||||||
|
|
||||||
|
import org.apache.catalina.Container;
|
||||||
|
import org.apache.catalina.Valve;
|
||||||
|
import org.keycloak.adapters.AdapterDeploymentContext;
|
||||||
|
import org.keycloak.adapters.tomcat.AbstractAuthenticatedActionsValve;
|
||||||
|
|
||||||
|
public class AuthenticatedActionsValve extends AbstractAuthenticatedActionsValve {
|
||||||
|
|
||||||
|
public AuthenticatedActionsValve(AdapterDeploymentContext deploymentContext, Valve next, Container container) {
|
||||||
|
super(deploymentContext, next, container);
|
||||||
|
}
|
||||||
|
}
|
||||||
+9
-1
@@ -17,11 +17,15 @@
|
|||||||
|
|
||||||
package org.keycloak.adapters.jbossweb;
|
package org.keycloak.adapters.jbossweb;
|
||||||
|
|
||||||
|
import org.apache.catalina.Container;
|
||||||
import org.apache.catalina.LifecycleException;
|
import org.apache.catalina.LifecycleException;
|
||||||
|
import org.apache.catalina.Valve;
|
||||||
import org.apache.catalina.connector.Request;
|
import org.apache.catalina.connector.Request;
|
||||||
import org.apache.catalina.connector.Response;
|
import org.apache.catalina.connector.Response;
|
||||||
import org.apache.catalina.core.StandardContext;
|
import org.apache.catalina.core.StandardContext;
|
||||||
import org.apache.catalina.deploy.LoginConfig;
|
import org.apache.catalina.deploy.LoginConfig;
|
||||||
|
import org.keycloak.adapters.AdapterDeploymentContext;
|
||||||
|
import org.keycloak.adapters.tomcat.AbstractAuthenticatedActionsValve;
|
||||||
import org.keycloak.adapters.tomcat.AbstractKeycloakAuthenticatorValve;
|
import org.keycloak.adapters.tomcat.AbstractKeycloakAuthenticatorValve;
|
||||||
import org.keycloak.adapters.tomcat.GenericPrincipalFactory;
|
import org.keycloak.adapters.tomcat.GenericPrincipalFactory;
|
||||||
|
|
||||||
@@ -56,7 +60,6 @@ public class KeycloakAuthenticatorValve extends AbstractKeycloakAuthenticatorVal
|
|||||||
super.start();
|
super.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void logout(Request request) {
|
public void logout(Request request) {
|
||||||
logoutInternal(request);
|
logoutInternal(request);
|
||||||
}
|
}
|
||||||
@@ -65,4 +68,9 @@ public class KeycloakAuthenticatorValve extends AbstractKeycloakAuthenticatorVal
|
|||||||
protected GenericPrincipalFactory createPrincipalFactory() {
|
protected GenericPrincipalFactory createPrincipalFactory() {
|
||||||
return new JBossWebPrincipalFactory();
|
return new JBossWebPrincipalFactory();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected AbstractAuthenticatedActionsValve createAuthenticatedActionsValve(AdapterDeploymentContext deploymentContext, Valve next, Container container) {
|
||||||
|
return new AuthenticatedActionsValve(deploymentContext, next, container);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -21,7 +21,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<artifactId>keycloak-as7-integration-pom</artifactId>
|
<artifactId>keycloak-as7-integration-pom</artifactId>
|
||||||
<version>3.3.0.CR1-SNAPSHOT</version>
|
<version>3.4.1.Final</version>
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>3.3.0.CR1-SNAPSHOT</version>
|
<version>3.4.1.Final</version>
|
||||||
<relativePath>../../../pom.xml</relativePath>
|
<relativePath>../../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<name>Keycloak AS7 / JBoss EAP 6 Integration</name>
|
<name>Keycloak AS7 / JBoss EAP 6 Integration</name>
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>3.3.0.CR1-SNAPSHOT</version>
|
<version>3.4.1.Final</version>
|
||||||
<relativePath>../../../pom.xml</relativePath>
|
<relativePath>../../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>3.3.0.CR1-SNAPSHOT</version>
|
<version>3.4.1.Final</version>
|
||||||
<relativePath>../../../pom.xml</relativePath>
|
<relativePath>../../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>3.3.0.CR1-SNAPSHOT</version>
|
<version>3.4.1.Final</version>
|
||||||
<relativePath>../../../pom.xml</relativePath>
|
<relativePath>../../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>3.3.0.CR1-SNAPSHOT</version>
|
<version>3.4.1.Final</version>
|
||||||
<relativePath>../../../../pom.xml</relativePath>
|
<relativePath>../../../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>3.3.0.CR1-SNAPSHOT</version>
|
<version>3.4.1.Final</version>
|
||||||
<relativePath>../../../../pom.xml</relativePath>
|
<relativePath>../../../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>3.3.0.CR1-SNAPSHOT</version>
|
<version>3.4.1.Final</version>
|
||||||
<relativePath>../../../../pom.xml</relativePath>
|
<relativePath>../../../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>3.3.0.CR1-SNAPSHOT</version>
|
<version>3.4.1.Final</version>
|
||||||
<relativePath>../../../../pom.xml</relativePath>
|
<relativePath>../../../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>3.3.0.CR1-SNAPSHOT</version>
|
<version>3.4.1.Final</version>
|
||||||
<relativePath>../../../../pom.xml</relativePath>
|
<relativePath>../../../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>3.3.0.CR1-SNAPSHOT</version>
|
<version>3.4.1.Final</version>
|
||||||
<relativePath>../../../../pom.xml</relativePath>
|
<relativePath>../../../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>3.3.0.CR1-SNAPSHOT</version>
|
<version>3.4.1.Final</version>
|
||||||
<relativePath>../../../pom.xml</relativePath>
|
<relativePath>../../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<name>Keycloak Jetty Integration</name>
|
<name>Keycloak Jetty Integration</name>
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>3.3.0.CR1-SNAPSHOT</version>
|
<version>3.4.1.Final</version>
|
||||||
<relativePath>../../../pom.xml</relativePath>
|
<relativePath>../../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|||||||
@@ -50,7 +50,7 @@
|
|||||||
} else if (initOptions && initOptions.adapter === 'default') {
|
} else if (initOptions && initOptions.adapter === 'default') {
|
||||||
adapter = loadAdapter();
|
adapter = loadAdapter();
|
||||||
} else {
|
} else {
|
||||||
if (window.Cordova) {
|
if (window.Cordova || window.cordova) {
|
||||||
adapter = loadAdapter('cordova');
|
adapter = loadAdapter('cordova');
|
||||||
} else {
|
} else {
|
||||||
adapter = loadAdapter();
|
adapter = loadAdapter();
|
||||||
@@ -948,7 +948,14 @@
|
|||||||
|
|
||||||
if (type == 'cordova') {
|
if (type == 'cordova') {
|
||||||
loginIframe.enable = false;
|
loginIframe.enable = false;
|
||||||
|
var cordovaOpenWindowWrapper = function(loginUrl, target, options) {
|
||||||
|
if (window.cordova && window.cordova.InAppBrowser) {
|
||||||
|
// Use inappbrowser for IOS and Android if available
|
||||||
|
return window.cordova.InAppBrowser.open(loginUrl, target, options);
|
||||||
|
} else {
|
||||||
|
return window.open(loginUrl, target, options);
|
||||||
|
}
|
||||||
|
};
|
||||||
return {
|
return {
|
||||||
login: function(options) {
|
login: function(options) {
|
||||||
var promise = createPromise();
|
var promise = createPromise();
|
||||||
@@ -959,8 +966,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
var loginUrl = kc.createLoginUrl(options);
|
var loginUrl = kc.createLoginUrl(options);
|
||||||
var ref = window.open(loginUrl, '_blank', o);
|
var ref = cordovaOpenWindowWrapper(loginUrl, '_blank', o);
|
||||||
|
|
||||||
var completed = false;
|
var completed = false;
|
||||||
|
|
||||||
ref.addEventListener('loadstart', function(event) {
|
ref.addEventListener('loadstart', function(event) {
|
||||||
@@ -993,7 +999,7 @@
|
|||||||
var promise = createPromise();
|
var promise = createPromise();
|
||||||
|
|
||||||
var logoutUrl = kc.createLogoutUrl(options);
|
var logoutUrl = kc.createLogoutUrl(options);
|
||||||
var ref = window.open(logoutUrl, '_blank', 'location=no,hidden=yes');
|
var ref = cordovaOpenWindowWrapper(logoutUrl, '_blank', 'location=no,hidden=yes');
|
||||||
|
|
||||||
var error;
|
var error;
|
||||||
|
|
||||||
@@ -1026,7 +1032,7 @@
|
|||||||
|
|
||||||
register : function() {
|
register : function() {
|
||||||
var registerUrl = kc.createRegisterUrl();
|
var registerUrl = kc.createRegisterUrl();
|
||||||
var ref = window.open(registerUrl, '_blank', 'location=no');
|
var ref = cordovaOpenWindowWrapper(registerUrl, '_blank', 'location=no');
|
||||||
ref.addEventListener('loadstart', function(event) {
|
ref.addEventListener('loadstart', function(event) {
|
||||||
if (event.url.indexOf('http://localhost') == 0) {
|
if (event.url.indexOf('http://localhost') == 0) {
|
||||||
ref.close();
|
ref.close();
|
||||||
@@ -1036,7 +1042,7 @@
|
|||||||
|
|
||||||
accountManagement : function() {
|
accountManagement : function() {
|
||||||
var accountUrl = kc.createAccountUrl();
|
var accountUrl = kc.createAccountUrl();
|
||||||
var ref = window.open(accountUrl, '_blank', 'location=no');
|
var ref = cordovaOpenWindowWrapper(accountUrl, '_blank', 'location=no');
|
||||||
ref.addEventListener('loadstart', function(event) {
|
ref.addEventListener('loadstart', function(event) {
|
||||||
if (event.url.indexOf('http://localhost') == 0) {
|
if (event.url.indexOf('http://localhost') == 0) {
|
||||||
ref.close();
|
ref.close();
|
||||||
|
|||||||
@@ -36,7 +36,7 @@
|
|||||||
|
|
||||||
req.onreadystatechange = function () {
|
req.onreadystatechange = function () {
|
||||||
if (req.readyState === 4) {
|
if (req.readyState === 4) {
|
||||||
if (req.status === 204) {
|
if (req.status === 204 || req.status === 1223) {
|
||||||
init = {
|
init = {
|
||||||
clientId: clientId,
|
clientId: clientId,
|
||||||
origin: origin
|
origin: origin
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>3.3.0.CR1-SNAPSHOT</version>
|
<version>3.4.1.Final</version>
|
||||||
<relativePath>../../../pom.xml</relativePath>
|
<relativePath>../../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>3.3.0.CR1-SNAPSHOT</version>
|
<version>3.4.1.Final</version>
|
||||||
<relativePath>../../pom.xml</relativePath>
|
<relativePath>../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<name>Keycloak OIDC Client Adapter Modules</name>
|
<name>Keycloak OIDC Client Adapter Modules</name>
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>3.3.0.CR1-SNAPSHOT</version>
|
<version>3.4.1.Final</version>
|
||||||
<relativePath>../../../pom.xml</relativePath>
|
<relativePath>../../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>3.3.0.CR1-SNAPSHOT</version>
|
<version>3.4.1.Final</version>
|
||||||
<relativePath>../../../pom.xml</relativePath>
|
<relativePath>../../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>3.3.0.CR1-SNAPSHOT</version>
|
<version>3.4.1.Final</version>
|
||||||
<relativePath>../../../pom.xml</relativePath>
|
<relativePath>../../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>spring-boot-container-bundle</artifactId>
|
<artifactId>spring-boot-container-bundle</artifactId>
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>3.3.0.CR1-SNAPSHOT</version>
|
<version>3.4.1.Final</version>
|
||||||
<relativePath>../../../pom.xml</relativePath>
|
<relativePath>../../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>3.3.0.CR1-SNAPSHOT</version>
|
<version>3.4.1.Final</version>
|
||||||
<relativePath>../../../pom.xml</relativePath>
|
<relativePath>../../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|||||||
+1
-5
@@ -45,11 +45,7 @@ public class HttpHeaderInspectingApiRequestMatcher implements RequestMatcher {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public boolean matches(HttpServletRequest request) {
|
public boolean matches(HttpServletRequest request) {
|
||||||
boolean ajax = X_REQUESTED_WITH_HEADER_AJAX_VALUE.equals(request.getHeader(X_REQUESTED_WITH_HEADER));
|
return X_REQUESTED_WITH_HEADER_AJAX_VALUE.equals(request.getHeader(X_REQUESTED_WITH_HEADER));
|
||||||
boolean html = request.getHeader(HttpHeaders.ACCEPT) != null && request.getHeader(HttpHeaders.ACCEPT).contains(
|
|
||||||
MediaType.TEXT_HTML_VALUE);
|
|
||||||
|
|
||||||
return ajax || !html;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
+15
-17
@@ -17,7 +17,16 @@
|
|||||||
|
|
||||||
package org.keycloak.adapters.springsecurity.authentication;
|
package org.keycloak.adapters.springsecurity.authentication;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import javax.servlet.ServletException;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
import org.apache.http.HttpHeaders;
|
import org.apache.http.HttpHeaders;
|
||||||
|
import org.keycloak.adapters.AdapterDeploymentContext;
|
||||||
|
import org.keycloak.adapters.spi.HttpFacade;
|
||||||
|
import org.keycloak.adapters.springsecurity.facade.SimpleHttpFacade;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
@@ -26,17 +35,6 @@ import org.springframework.security.web.AuthenticationEntryPoint;
|
|||||||
import org.springframework.security.web.util.matcher.RequestMatcher;
|
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
import javax.servlet.ServletException;
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
|
||||||
import java.io.IOException;
|
|
||||||
import org.keycloak.adapters.AdapterDeploymentContext;
|
|
||||||
import org.keycloak.adapters.spi.HttpFacade;
|
|
||||||
import org.keycloak.adapters.springsecurity.config.KeycloakWebSecurityConfigurerAdapter;
|
|
||||||
import org.keycloak.adapters.springsecurity.facade.SimpleHttpFacade;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides a Keycloak {@link AuthenticationEntryPoint authentication entry point}. Uses a
|
* Provides a Keycloak {@link AuthenticationEntryPoint authentication entry point}. Uses a
|
||||||
* {@link RequestMatcher} to determine if the request is an interactive login request or a
|
* {@link RequestMatcher} to determine if the request is an interactive login request or a
|
||||||
@@ -62,15 +60,14 @@ public class KeycloakAuthenticationEntryPoint implements AuthenticationEntryPoin
|
|||||||
private final RequestMatcher apiRequestMatcher;
|
private final RequestMatcher apiRequestMatcher;
|
||||||
private String loginUri = DEFAULT_LOGIN_URI;
|
private String loginUri = DEFAULT_LOGIN_URI;
|
||||||
private String realm = DEFAULT_REALM;
|
private String realm = DEFAULT_REALM;
|
||||||
|
|
||||||
private AdapterDeploymentContext adapterDeploymentContext;
|
private AdapterDeploymentContext adapterDeploymentContext;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new Keycloak authentication entry point.
|
* Creates a new Keycloak authentication entry point.
|
||||||
*/
|
*/
|
||||||
public KeycloakAuthenticationEntryPoint(AdapterDeploymentContext adapterDeploymentContext) {
|
public KeycloakAuthenticationEntryPoint(AdapterDeploymentContext adapterDeploymentContext) {
|
||||||
this(DEFAULT_API_REQUEST_MATCHER);
|
this(adapterDeploymentContext, DEFAULT_API_REQUEST_MATCHER);
|
||||||
this.adapterDeploymentContext = adapterDeploymentContext;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -80,14 +77,15 @@ public class KeycloakAuthenticationEntryPoint implements AuthenticationEntryPoin
|
|||||||
* @param apiRequestMatcher the <code>RequestMatcher</code> to use to determine
|
* @param apiRequestMatcher the <code>RequestMatcher</code> to use to determine
|
||||||
* if the current request is an API request or a browser request (required)
|
* if the current request is an API request or a browser request (required)
|
||||||
*/
|
*/
|
||||||
public KeycloakAuthenticationEntryPoint(RequestMatcher apiRequestMatcher) {
|
public KeycloakAuthenticationEntryPoint(AdapterDeploymentContext adapterDeploymentContext, RequestMatcher apiRequestMatcher) {
|
||||||
Assert.notNull(apiRequestMatcher, "apiRequestMatcher required");
|
Assert.notNull(apiRequestMatcher, "apiRequestMatcher required");
|
||||||
|
Assert.notNull(adapterDeploymentContext, "adapterDeploymentContext required");
|
||||||
|
this.adapterDeploymentContext = adapterDeploymentContext;
|
||||||
this.apiRequestMatcher = apiRequestMatcher;
|
this.apiRequestMatcher = apiRequestMatcher;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException
|
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {
|
||||||
{
|
|
||||||
HttpFacade facade = new SimpleHttpFacade(request, response);
|
HttpFacade facade = new SimpleHttpFacade(request, response);
|
||||||
if (apiRequestMatcher.matches(request) || adapterDeploymentContext.resolveDeployment(facade).isBearerOnly()) {
|
if (apiRequestMatcher.matches(request) || adapterDeploymentContext.resolveDeployment(facade).isBearerOnly()) {
|
||||||
commenceUnauthorizedResponse(request, response);
|
commenceUnauthorizedResponse(request, response);
|
||||||
|
|||||||
+12
-5
@@ -17,14 +17,13 @@
|
|||||||
|
|
||||||
package org.keycloak.adapters.springsecurity.authentication;
|
package org.keycloak.adapters.springsecurity.authentication;
|
||||||
|
|
||||||
import java.io.IOException;
|
import org.springframework.security.core.AuthenticationException;
|
||||||
|
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
|
||||||
|
|
||||||
import javax.servlet.ServletException;
|
import javax.servlet.ServletException;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import java.io.IOException;
|
||||||
import org.springframework.security.core.AuthenticationException;
|
|
||||||
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* To return the forbidden code with the corresponding message.
|
* To return the forbidden code with the corresponding message.
|
||||||
@@ -36,6 +35,14 @@ public class KeycloakAuthenticationFailureHandler implements AuthenticationFailu
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
|
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
|
||||||
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unable to authenticate using the Authorization header");
|
// Check that the response was not committed yet (this may happen when another
|
||||||
|
// part of the Keycloak adapter sends a challenge or a redirect).
|
||||||
|
if (!response.isCommitted()) {
|
||||||
|
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unable to authenticate using the Authorization header");
|
||||||
|
} else {
|
||||||
|
if (200 <= response.getStatus() && response.getStatus() < 300) {
|
||||||
|
throw new RuntimeException("Success response was committed while authentication failed!", exception);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+1
-1
@@ -50,7 +50,7 @@ public class KeycloakAuthenticationProvider implements AuthenticationProvider {
|
|||||||
for (String role : token.getAccount().getRoles()) {
|
for (String role : token.getAccount().getRoles()) {
|
||||||
grantedAuthorities.add(new KeycloakRole(role));
|
grantedAuthorities.add(new KeycloakRole(role));
|
||||||
}
|
}
|
||||||
return new KeycloakAuthenticationToken(token.getAccount(), mapAuthorities(grantedAuthorities));
|
return new KeycloakAuthenticationToken(token.getAccount(), token.isInteractive(), mapAuthorities(grantedAuthorities));
|
||||||
}
|
}
|
||||||
|
|
||||||
private Collection<? extends GrantedAuthority> mapAuthorities(
|
private Collection<? extends GrantedAuthority> mapAuthorities(
|
||||||
|
|||||||
+1
-1
@@ -94,7 +94,7 @@ public class SpringSecurityRequestAuthenticator extends RequestAuthenticator {
|
|||||||
|
|
||||||
logger.debug("Completing bearer authentication. Bearer roles: {} ",roles);
|
logger.debug("Completing bearer authentication. Bearer roles: {} ",roles);
|
||||||
|
|
||||||
SecurityContextHolder.getContext().setAuthentication(new KeycloakAuthenticationToken(account));
|
SecurityContextHolder.getContext().setAuthentication(new KeycloakAuthenticationToken(account, false));
|
||||||
request.setAttribute(KeycloakSecurityContext.class.getName(), securityContext);
|
request.setAttribute(KeycloakSecurityContext.class.getName(), securityContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+15
@@ -23,9 +23,11 @@ import org.keycloak.adapters.springsecurity.AdapterDeploymentContextFactoryBean;
|
|||||||
import org.keycloak.adapters.springsecurity.authentication.KeycloakAuthenticationEntryPoint;
|
import org.keycloak.adapters.springsecurity.authentication.KeycloakAuthenticationEntryPoint;
|
||||||
import org.keycloak.adapters.springsecurity.authentication.KeycloakAuthenticationProvider;
|
import org.keycloak.adapters.springsecurity.authentication.KeycloakAuthenticationProvider;
|
||||||
import org.keycloak.adapters.springsecurity.authentication.KeycloakLogoutHandler;
|
import org.keycloak.adapters.springsecurity.authentication.KeycloakLogoutHandler;
|
||||||
|
import org.keycloak.adapters.springsecurity.filter.KeycloakAuthenticatedActionsFilter;
|
||||||
import org.keycloak.adapters.springsecurity.filter.KeycloakAuthenticationProcessingFilter;
|
import org.keycloak.adapters.springsecurity.filter.KeycloakAuthenticationProcessingFilter;
|
||||||
import org.keycloak.adapters.springsecurity.filter.KeycloakCsrfRequestMatcher;
|
import org.keycloak.adapters.springsecurity.filter.KeycloakCsrfRequestMatcher;
|
||||||
import org.keycloak.adapters.springsecurity.filter.KeycloakPreAuthActionsFilter;
|
import org.keycloak.adapters.springsecurity.filter.KeycloakPreAuthActionsFilter;
|
||||||
|
import org.keycloak.adapters.springsecurity.filter.KeycloakSecurityContextRequestFilter;
|
||||||
import org.keycloak.adapters.springsecurity.management.HttpSessionManager;
|
import org.keycloak.adapters.springsecurity.management.HttpSessionManager;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
@@ -41,6 +43,7 @@ import org.springframework.security.web.AuthenticationEntryPoint;
|
|||||||
import org.springframework.security.web.authentication.logout.LogoutFilter;
|
import org.springframework.security.web.authentication.logout.LogoutFilter;
|
||||||
import org.springframework.security.web.authentication.session.SessionAuthenticationStrategy;
|
import org.springframework.security.web.authentication.session.SessionAuthenticationStrategy;
|
||||||
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
|
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
|
||||||
|
import org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides a convenient base class for creating a {@link WebSecurityConfigurer}
|
* Provides a convenient base class for creating a {@link WebSecurityConfigurer}
|
||||||
@@ -91,6 +94,11 @@ public abstract class KeycloakWebSecurityConfigurerAdapter extends WebSecurityCo
|
|||||||
return new KeycloakPreAuthActionsFilter(httpSessionManager());
|
return new KeycloakPreAuthActionsFilter(httpSessionManager());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
protected KeycloakAuthenticatedActionsFilter keycloakAuthenticatedActionsFilter() {
|
||||||
|
return new KeycloakAuthenticatedActionsFilter();
|
||||||
|
}
|
||||||
|
|
||||||
protected KeycloakCsrfRequestMatcher keycloakCsrfRequestMatcher() {
|
protected KeycloakCsrfRequestMatcher keycloakCsrfRequestMatcher() {
|
||||||
return new KeycloakCsrfRequestMatcher();
|
return new KeycloakCsrfRequestMatcher();
|
||||||
}
|
}
|
||||||
@@ -117,6 +125,8 @@ public abstract class KeycloakWebSecurityConfigurerAdapter extends WebSecurityCo
|
|||||||
.and()
|
.and()
|
||||||
.addFilterBefore(keycloakPreAuthActionsFilter(), LogoutFilter.class)
|
.addFilterBefore(keycloakPreAuthActionsFilter(), LogoutFilter.class)
|
||||||
.addFilterBefore(keycloakAuthenticationProcessingFilter(), BasicAuthenticationFilter.class)
|
.addFilterBefore(keycloakAuthenticationProcessingFilter(), BasicAuthenticationFilter.class)
|
||||||
|
.addFilterBefore(keycloakAuthenticatedActionsFilter(), BasicAuthenticationFilter.class)
|
||||||
|
.addFilterAfter(keycloakSecurityContextRequestFilter(), SecurityContextHolderAwareRequestFilter.class)
|
||||||
.exceptionHandling().authenticationEntryPoint(authenticationEntryPoint())
|
.exceptionHandling().authenticationEntryPoint(authenticationEntryPoint())
|
||||||
.and()
|
.and()
|
||||||
.logout()
|
.logout()
|
||||||
@@ -124,4 +134,9 @@ public abstract class KeycloakWebSecurityConfigurerAdapter extends WebSecurityCo
|
|||||||
.logoutUrl("/sso/logout").permitAll()
|
.logoutUrl("/sso/logout").permitAll()
|
||||||
.logoutSuccessUrl("/");
|
.logoutSuccessUrl("/");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
protected KeycloakSecurityContextRequestFilter keycloakSecurityContextRequestFilter() {
|
||||||
|
return new KeycloakSecurityContextRequestFilter();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+12
-33
@@ -24,6 +24,7 @@ import javax.servlet.ServletException;
|
|||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
import org.keycloak.OAuth2Constants;
|
||||||
import org.keycloak.adapters.AdapterDeploymentContext;
|
import org.keycloak.adapters.AdapterDeploymentContext;
|
||||||
import org.keycloak.adapters.AdapterTokenStore;
|
import org.keycloak.adapters.AdapterTokenStore;
|
||||||
import org.keycloak.adapters.KeycloakDeployment;
|
import org.keycloak.adapters.KeycloakDeployment;
|
||||||
@@ -36,6 +37,7 @@ import org.keycloak.adapters.springsecurity.authentication.KeycloakAuthenticatio
|
|||||||
import org.keycloak.adapters.springsecurity.authentication.SpringSecurityRequestAuthenticator;
|
import org.keycloak.adapters.springsecurity.authentication.SpringSecurityRequestAuthenticator;
|
||||||
import org.keycloak.adapters.springsecurity.facade.SimpleHttpFacade;
|
import org.keycloak.adapters.springsecurity.facade.SimpleHttpFacade;
|
||||||
import org.keycloak.adapters.springsecurity.token.AdapterTokenStoreFactory;
|
import org.keycloak.adapters.springsecurity.token.AdapterTokenStoreFactory;
|
||||||
|
import org.keycloak.adapters.springsecurity.token.KeycloakAuthenticationToken;
|
||||||
import org.keycloak.adapters.springsecurity.token.SpringSecurityAdapterTokenStoreFactory;
|
import org.keycloak.adapters.springsecurity.token.SpringSecurityAdapterTokenStoreFactory;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
@@ -61,19 +63,19 @@ import org.springframework.util.Assert;
|
|||||||
* @version $Revision: 1 $
|
* @version $Revision: 1 $
|
||||||
*/
|
*/
|
||||||
public class KeycloakAuthenticationProcessingFilter extends AbstractAuthenticationProcessingFilter implements ApplicationContextAware {
|
public class KeycloakAuthenticationProcessingFilter extends AbstractAuthenticationProcessingFilter implements ApplicationContextAware {
|
||||||
|
|
||||||
public static final String DEFAULT_LOGIN_URL = "/sso/login";
|
public static final String DEFAULT_LOGIN_URL = "/sso/login";
|
||||||
public static final String AUTHORIZATION_HEADER = "Authorization";
|
public static final String AUTHORIZATION_HEADER = "Authorization";
|
||||||
public static final String SCHEME_BEARER = "bearer ";
|
|
||||||
public static final String SCHEME_BASIC = "basic ";
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Request matcher that matches requests to the {@link KeycloakAuthenticationEntryPoint#DEFAULT_LOGIN_URI default login URI}
|
* Request matcher that matches requests to the {@link KeycloakAuthenticationEntryPoint#DEFAULT_LOGIN_URI default login URI}
|
||||||
* and any request with a <code>Authorization</code> header.
|
* and any request with a <code>Authorization</code> header.
|
||||||
*/
|
*/
|
||||||
public static final RequestMatcher DEFAULT_REQUEST_MATCHER =
|
public static final RequestMatcher DEFAULT_REQUEST_MATCHER =
|
||||||
new OrRequestMatcher(new AntPathRequestMatcher(DEFAULT_LOGIN_URL), new RequestHeaderRequestMatcher(AUTHORIZATION_HEADER));
|
new OrRequestMatcher(
|
||||||
|
new AntPathRequestMatcher(DEFAULT_LOGIN_URL),
|
||||||
|
new RequestHeaderRequestMatcher(AUTHORIZATION_HEADER),
|
||||||
|
new QueryParamPresenceRequestMatcher(OAuth2Constants.ACCESS_TOKEN)
|
||||||
|
);
|
||||||
|
|
||||||
private static final Logger log = LoggerFactory.getLogger(KeycloakAuthenticationProcessingFilter.class);
|
private static final Logger log = LoggerFactory.getLogger(KeycloakAuthenticationProcessingFilter.class);
|
||||||
|
|
||||||
@@ -134,6 +136,10 @@ public class KeycloakAuthenticationProcessingFilter extends AbstractAuthenticati
|
|||||||
|
|
||||||
HttpFacade facade = new SimpleHttpFacade(request, response);
|
HttpFacade facade = new SimpleHttpFacade(request, response);
|
||||||
KeycloakDeployment deployment = adapterDeploymentContext.resolveDeployment(facade);
|
KeycloakDeployment deployment = adapterDeploymentContext.resolveDeployment(facade);
|
||||||
|
|
||||||
|
// using Spring authenticationFailureHandler
|
||||||
|
deployment.setDelegateBearerErrorResponseSending(true);
|
||||||
|
|
||||||
AdapterTokenStore tokenStore = adapterTokenStoreFactory.createAdapterTokenStore(deployment, request);
|
AdapterTokenStore tokenStore = adapterTokenStoreFactory.createAdapterTokenStore(deployment, request);
|
||||||
RequestAuthenticator authenticator
|
RequestAuthenticator authenticator
|
||||||
= new SpringSecurityRequestAuthenticator(facade, request, deployment, tokenStore, -1);
|
= new SpringSecurityRequestAuthenticator(facade, request, deployment, tokenStore, -1);
|
||||||
@@ -177,36 +183,10 @@ public class KeycloakAuthenticationProcessingFilter extends AbstractAuthenticati
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns true if the request was made with a bearer token authorization header.
|
|
||||||
*
|
|
||||||
* @param request the current <code>HttpServletRequest</code>
|
|
||||||
*
|
|
||||||
* @return <code>true</code> if the <code>request</code> was made with a bearer token authorization header;
|
|
||||||
* <code>false</code> otherwise.
|
|
||||||
*/
|
|
||||||
protected boolean isBearerTokenRequest(HttpServletRequest request) {
|
|
||||||
String authValue = request.getHeader(AUTHORIZATION_HEADER);
|
|
||||||
return authValue != null && authValue.toLowerCase().startsWith(SCHEME_BEARER);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns true if the request was made with a Basic authentication authorization header.
|
|
||||||
*
|
|
||||||
* @param request the current <code>HttpServletRequest</code>
|
|
||||||
* @return <code>true</code> if the <code>request</code> was made with a Basic authentication authorization header;
|
|
||||||
* <code>false</code> otherwise.
|
|
||||||
*/
|
|
||||||
protected boolean isBasicAuthRequest(HttpServletRequest request) {
|
|
||||||
String authValue = request.getHeader(AUTHORIZATION_HEADER);
|
|
||||||
return authValue != null && authValue.toLowerCase().startsWith(SCHEME_BASIC);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain,
|
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain,
|
||||||
Authentication authResult) throws IOException, ServletException {
|
Authentication authResult) throws IOException, ServletException {
|
||||||
|
if (authResult instanceof KeycloakAuthenticationToken && ((KeycloakAuthenticationToken) authResult).isInteractive()) {
|
||||||
if (!(this.isBearerTokenRequest(request) || this.isBasicAuthRequest(request))) {
|
|
||||||
super.successfulAuthentication(request, response, chain, authResult);
|
super.successfulAuthentication(request, response, chain, authResult);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -227,7 +207,6 @@ public class KeycloakAuthenticationProcessingFilter extends AbstractAuthenticati
|
|||||||
} finally {
|
} finally {
|
||||||
SecurityContextHolder.clearContext();
|
SecurityContextHolder.clearContext();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
+113
@@ -0,0 +1,113 @@
|
|||||||
|
/*
|
||||||
|
* 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.springsecurity.filter;
|
||||||
|
|
||||||
|
import org.keycloak.KeycloakPrincipal;
|
||||||
|
import org.keycloak.KeycloakSecurityContext;
|
||||||
|
import org.keycloak.adapters.AdapterDeploymentContext;
|
||||||
|
import org.keycloak.adapters.KeycloakDeployment;
|
||||||
|
import org.keycloak.adapters.RefreshableKeycloakSecurityContext;
|
||||||
|
import org.keycloak.adapters.springsecurity.facade.SimpleHttpFacade;
|
||||||
|
import org.springframework.beans.BeansException;
|
||||||
|
import org.springframework.context.ApplicationContext;
|
||||||
|
import org.springframework.context.ApplicationContextAware;
|
||||||
|
import org.springframework.security.core.Authentication;
|
||||||
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
|
import org.springframework.web.filter.GenericFilterBean;
|
||||||
|
|
||||||
|
import javax.servlet.FilterChain;
|
||||||
|
import javax.servlet.ServletException;
|
||||||
|
import javax.servlet.ServletRequest;
|
||||||
|
import javax.servlet.ServletResponse;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||||
|
*/
|
||||||
|
public class KeycloakSecurityContextRequestFilter extends GenericFilterBean implements ApplicationContextAware {
|
||||||
|
|
||||||
|
private static final String FILTER_APPLIED = KeycloakSecurityContext.class.getPackage().getName() + ".token-refreshed";
|
||||||
|
|
||||||
|
private ApplicationContext applicationContext;
|
||||||
|
private AdapterDeploymentContext deploymentContext;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {
|
||||||
|
if (request.getAttribute(FILTER_APPLIED) != null) {
|
||||||
|
filterChain.doFilter(request, response);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
request.setAttribute(FILTER_APPLIED, Boolean.TRUE);
|
||||||
|
|
||||||
|
KeycloakSecurityContext keycloakSecurityContext = getKeycloakPrincipal();
|
||||||
|
|
||||||
|
if (keycloakSecurityContext instanceof RefreshableKeycloakSecurityContext) {
|
||||||
|
RefreshableKeycloakSecurityContext refreshableSecurityContext = (RefreshableKeycloakSecurityContext) keycloakSecurityContext;
|
||||||
|
|
||||||
|
if (refreshableSecurityContext.isActive()) {
|
||||||
|
KeycloakDeployment deployment = resolveDeployment(request, response);
|
||||||
|
|
||||||
|
if (deployment.isAlwaysRefreshToken()) {
|
||||||
|
if (refreshableSecurityContext.refreshExpiredToken(false)) {
|
||||||
|
request.setAttribute(KeycloakSecurityContext.class.getName(), refreshableSecurityContext);
|
||||||
|
} else {
|
||||||
|
clearAuthenticationContext();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
clearAuthenticationContext();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
filterChain.doFilter(request, response);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void initFilterBean() throws ServletException {
|
||||||
|
deploymentContext = applicationContext.getBean(AdapterDeploymentContext.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
|
||||||
|
this.applicationContext = applicationContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
private KeycloakSecurityContext getKeycloakPrincipal() {
|
||||||
|
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
|
||||||
|
|
||||||
|
if (authentication != null) {
|
||||||
|
Object principal = authentication.getPrincipal();
|
||||||
|
|
||||||
|
if (principal instanceof KeycloakPrincipal) {
|
||||||
|
return KeycloakPrincipal.class.cast(principal).getKeycloakSecurityContext();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private KeycloakDeployment resolveDeployment(ServletRequest servletRequest, ServletResponse servletResponse) {
|
||||||
|
return deploymentContext.resolveDeployment(new SimpleHttpFacade(HttpServletRequest.class.cast(servletRequest), HttpServletResponse.class.cast(servletResponse)));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void clearAuthenticationContext() {
|
||||||
|
SecurityContextHolder.clearContext();
|
||||||
|
}
|
||||||
|
}
|
||||||
+39
@@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
* 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.springsecurity.filter;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
|
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Spring RequestMatcher that checks for the presence of a query parameter.
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:glavoie@gmail.com">Gabriel Lavoie</a>
|
||||||
|
*/
|
||||||
|
public class QueryParamPresenceRequestMatcher implements RequestMatcher {
|
||||||
|
private String param;
|
||||||
|
|
||||||
|
public QueryParamPresenceRequestMatcher(String param) {
|
||||||
|
this.param = param;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean matches(HttpServletRequest httpServletRequest) {
|
||||||
|
return param != null && httpServletRequest.getParameter(param) != null;
|
||||||
|
}
|
||||||
|
}
|
||||||
+9
-2
@@ -38,24 +38,27 @@ import java.util.Collection;
|
|||||||
public class KeycloakAuthenticationToken extends AbstractAuthenticationToken implements Authentication {
|
public class KeycloakAuthenticationToken extends AbstractAuthenticationToken implements Authentication {
|
||||||
|
|
||||||
private Principal principal;
|
private Principal principal;
|
||||||
|
private boolean interactive;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new, unauthenticated Keycloak security token for the given account.
|
* Creates a new, unauthenticated Keycloak security token for the given account.
|
||||||
*/
|
*/
|
||||||
public KeycloakAuthenticationToken(KeycloakAccount account) {
|
public KeycloakAuthenticationToken(KeycloakAccount account, boolean interactive) {
|
||||||
super(null);
|
super(null);
|
||||||
Assert.notNull(account, "KeycloakAccount cannot be null");
|
Assert.notNull(account, "KeycloakAccount cannot be null");
|
||||||
Assert.notNull(account.getPrincipal(), "KeycloakAccount.getPrincipal() cannot be null");
|
Assert.notNull(account.getPrincipal(), "KeycloakAccount.getPrincipal() cannot be null");
|
||||||
this.principal = account.getPrincipal();
|
this.principal = account.getPrincipal();
|
||||||
this.setDetails(account);
|
this.setDetails(account);
|
||||||
|
this.interactive = interactive;
|
||||||
}
|
}
|
||||||
|
|
||||||
public KeycloakAuthenticationToken(KeycloakAccount account, Collection<? extends GrantedAuthority> authorities) {
|
public KeycloakAuthenticationToken(KeycloakAccount account, boolean interactive, Collection<? extends GrantedAuthority> authorities) {
|
||||||
super(authorities);
|
super(authorities);
|
||||||
Assert.notNull(account, "KeycloakAccount cannot be null");
|
Assert.notNull(account, "KeycloakAccount cannot be null");
|
||||||
Assert.notNull(account.getPrincipal(), "KeycloakAccount.getPrincipal() cannot be null");
|
Assert.notNull(account.getPrincipal(), "KeycloakAccount.getPrincipal() cannot be null");
|
||||||
this.principal = account.getPrincipal();
|
this.principal = account.getPrincipal();
|
||||||
this.setDetails(account);
|
this.setDetails(account);
|
||||||
|
this.interactive = interactive;
|
||||||
setAuthenticated(true);
|
setAuthenticated(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,4 +75,8 @@ public class KeycloakAuthenticationToken extends AbstractAuthenticationToken imp
|
|||||||
public OidcKeycloakAccount getAccount() {
|
public OidcKeycloakAccount getAccount() {
|
||||||
return (OidcKeycloakAccount) this.getDetails();
|
return (OidcKeycloakAccount) this.getDetails();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isInteractive() {
|
||||||
|
return interactive;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+1
-1
@@ -105,7 +105,7 @@ public class SpringSecurityTokenStore implements AdapterTokenStore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
logger.debug("Saving account info {}", account);
|
logger.debug("Saving account info {}", account);
|
||||||
SecurityContextHolder.getContext().setAuthentication(new KeycloakAuthenticationToken(account));
|
SecurityContextHolder.getContext().setAuthentication(new KeycloakAuthenticationToken(account, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
+2
-7
@@ -39,14 +39,9 @@ public class HttpHeaderInspectingApiRequestMatcherTest {
|
|||||||
request = new MockHttpServletRequest();
|
request = new MockHttpServletRequest();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testMatches() throws Exception {
|
|
||||||
assertTrue(apiRequestMatcher.matches(request));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testMatchesBrowserRequest() throws Exception {
|
public void testMatchesBrowserRequest() throws Exception {
|
||||||
request.addHeader(HttpHeaders.ACCEPT, "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
|
request.addHeader(HttpHeaders.ACCEPT, "application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
|
||||||
assertFalse(apiRequestMatcher.matches(request));
|
assertFalse(apiRequestMatcher.matches(request));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -55,7 +50,7 @@ public class HttpHeaderInspectingApiRequestMatcherTest {
|
|||||||
request.addHeader(
|
request.addHeader(
|
||||||
HttpHeaderInspectingApiRequestMatcher.X_REQUESTED_WITH_HEADER,
|
HttpHeaderInspectingApiRequestMatcher.X_REQUESTED_WITH_HEADER,
|
||||||
HttpHeaderInspectingApiRequestMatcher.X_REQUESTED_WITH_HEADER_AJAX_VALUE);
|
HttpHeaderInspectingApiRequestMatcher.X_REQUESTED_WITH_HEADER_AJAX_VALUE);
|
||||||
|
|
||||||
assertTrue(apiRequestMatcher.matches(request));
|
assertTrue(apiRequestMatcher.matches(request));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
+26
-12
@@ -17,24 +17,27 @@
|
|||||||
|
|
||||||
package org.keycloak.adapters.springsecurity.authentication;
|
package org.keycloak.adapters.springsecurity.authentication;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertNull;
|
||||||
|
import static org.mockito.Matchers.any;
|
||||||
|
import static org.mockito.Matchers.eq;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
import org.apache.http.HttpHeaders;
|
import org.apache.http.HttpHeaders;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.springframework.http.HttpStatus;
|
|
||||||
import org.springframework.mock.web.MockHttpServletRequest;
|
|
||||||
import org.springframework.mock.web.MockHttpServletResponse;
|
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
|
||||||
import static org.junit.Assert.assertNotNull;
|
|
||||||
import org.keycloak.adapters.AdapterDeploymentContext;
|
import org.keycloak.adapters.AdapterDeploymentContext;
|
||||||
import org.keycloak.adapters.KeycloakDeployment;
|
import org.keycloak.adapters.KeycloakDeployment;
|
||||||
import org.keycloak.adapters.spi.HttpFacade;
|
import org.keycloak.adapters.spi.HttpFacade;
|
||||||
import static org.mockito.Matchers.any;
|
|
||||||
import static org.mockito.Matchers.eq;
|
|
||||||
import org.mockito.Mock;
|
import org.mockito.Mock;
|
||||||
import static org.mockito.Mockito.when;
|
|
||||||
import org.mockito.MockitoAnnotations;
|
import org.mockito.MockitoAnnotations;
|
||||||
import org.springframework.context.ApplicationContext;
|
import org.springframework.context.ApplicationContext;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.mock.web.MockHttpServletRequest;
|
||||||
|
import org.springframework.mock.web.MockHttpServletResponse;
|
||||||
|
import org.springframework.security.web.util.matcher.RequestMatcher;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Keycloak authentication entry point tests.
|
* Keycloak authentication entry point tests.
|
||||||
@@ -46,13 +49,16 @@ public class KeycloakAuthenticationEntryPointTest {
|
|||||||
private MockHttpServletResponse response;
|
private MockHttpServletResponse response;
|
||||||
@Mock
|
@Mock
|
||||||
private ApplicationContext applicationContext;
|
private ApplicationContext applicationContext;
|
||||||
|
|
||||||
@Mock
|
@Mock
|
||||||
private AdapterDeploymentContext adapterDeploymentContext;
|
private AdapterDeploymentContext adapterDeploymentContext;
|
||||||
|
|
||||||
@Mock
|
@Mock
|
||||||
private KeycloakDeployment keycloakDeployment;
|
private KeycloakDeployment keycloakDeployment;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private RequestMatcher requestMatcher;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() throws Exception {
|
public void setUp() throws Exception {
|
||||||
MockitoAnnotations.initMocks(this);
|
MockitoAnnotations.initMocks(this);
|
||||||
@@ -86,8 +92,8 @@ public class KeycloakAuthenticationEntryPointTest {
|
|||||||
public void testCommenceWithUnauthorizedWithAccept() throws Exception {
|
public void testCommenceWithUnauthorizedWithAccept() throws Exception {
|
||||||
request.addHeader(HttpHeaders.ACCEPT, "application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
|
request.addHeader(HttpHeaders.ACCEPT, "application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
|
||||||
authenticationEntryPoint.commence(request, response, null);
|
authenticationEntryPoint.commence(request, response, null);
|
||||||
assertEquals(HttpStatus.UNAUTHORIZED.value(), response.getStatus());
|
assertEquals(HttpStatus.FOUND.value(), response.getStatus());
|
||||||
assertNotNull(response.getHeader(HttpHeaders.WWW_AUTHENTICATE));
|
assertNull(response.getHeader(HttpHeaders.WWW_AUTHENTICATE));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -100,6 +106,14 @@ public class KeycloakAuthenticationEntryPointTest {
|
|||||||
assertEquals(logoutUri, response.getHeader("Location"));
|
assertEquals(logoutUri, response.getHeader("Location"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCommenceWithCustomRequestMatcher() throws Exception {
|
||||||
|
new KeycloakAuthenticationEntryPoint(adapterDeploymentContext, requestMatcher)
|
||||||
|
.commence(request, response, null);
|
||||||
|
|
||||||
|
verify(requestMatcher).matches(request);
|
||||||
|
}
|
||||||
|
|
||||||
private void configureBrowserRequest() {
|
private void configureBrowserRequest() {
|
||||||
request.addHeader(HttpHeaders.ACCEPT, "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
|
request.addHeader(HttpHeaders.ACCEPT, "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
|
||||||
}
|
}
|
||||||
|
|||||||
+18
-8
@@ -44,6 +44,7 @@ import static org.mockito.Mockito.mock;
|
|||||||
public class KeycloakAuthenticationProviderTest {
|
public class KeycloakAuthenticationProviderTest {
|
||||||
private KeycloakAuthenticationProvider provider = new KeycloakAuthenticationProvider();
|
private KeycloakAuthenticationProvider provider = new KeycloakAuthenticationProvider();
|
||||||
private KeycloakAuthenticationToken token;
|
private KeycloakAuthenticationToken token;
|
||||||
|
private KeycloakAuthenticationToken interactiveToken;
|
||||||
private Set<String> roles = Sets.newSet("user", "admin");
|
private Set<String> roles = Sets.newSet("user", "admin");
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
@@ -52,18 +53,18 @@ public class KeycloakAuthenticationProviderTest {
|
|||||||
RefreshableKeycloakSecurityContext securityContext = mock(RefreshableKeycloakSecurityContext.class);
|
RefreshableKeycloakSecurityContext securityContext = mock(RefreshableKeycloakSecurityContext.class);
|
||||||
KeycloakAccount account = new SimpleKeycloakAccount(principal, roles, securityContext);
|
KeycloakAccount account = new SimpleKeycloakAccount(principal, roles, securityContext);
|
||||||
|
|
||||||
token = new KeycloakAuthenticationToken(account);
|
token = new KeycloakAuthenticationToken(account, false);
|
||||||
|
interactiveToken = new KeycloakAuthenticationToken(account, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testAuthenticate() throws Exception {
|
public void testAuthenticate() throws Exception {
|
||||||
Authentication result = provider.authenticate(token);
|
assertAuthenticationResult(provider.authenticate(token));
|
||||||
assertNotNull(result);
|
}
|
||||||
assertEquals(roles, AuthorityUtils.authorityListToSet(result.getAuthorities()));
|
|
||||||
assertTrue(result.isAuthenticated());
|
@Test
|
||||||
assertNotNull(result.getPrincipal());
|
public void testAuthenticateInteractive() throws Exception {
|
||||||
assertNotNull(result.getCredentials());
|
assertAuthenticationResult(provider.authenticate(interactiveToken));
|
||||||
assertNotNull(result.getDetails());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -83,4 +84,13 @@ public class KeycloakAuthenticationProviderTest {
|
|||||||
assertEquals(Sets.newSet("ROLE_USER", "ROLE_ADMIN"),
|
assertEquals(Sets.newSet("ROLE_USER", "ROLE_ADMIN"),
|
||||||
AuthorityUtils.authorityListToSet(result.getAuthorities()));
|
AuthorityUtils.authorityListToSet(result.getAuthorities()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void assertAuthenticationResult(Authentication result) {
|
||||||
|
assertNotNull(result);
|
||||||
|
assertEquals(roles, AuthorityUtils.authorityListToSet(result.getAuthorities()));
|
||||||
|
assertTrue(result.isAuthenticated());
|
||||||
|
assertNotNull(result.getPrincipal());
|
||||||
|
assertNotNull(result.getCredentials());
|
||||||
|
assertNotNull(result.getDetails());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+1
-1
@@ -28,7 +28,7 @@ public class SimpleHttpFacadeTest {
|
|||||||
Principal principal = mock(Principal.class);
|
Principal principal = mock(Principal.class);
|
||||||
RefreshableKeycloakSecurityContext keycloakSecurityContext = mock(RefreshableKeycloakSecurityContext.class);
|
RefreshableKeycloakSecurityContext keycloakSecurityContext = mock(RefreshableKeycloakSecurityContext.class);
|
||||||
KeycloakAccount account = new SimpleKeycloakAccount(principal, roles, keycloakSecurityContext);
|
KeycloakAccount account = new SimpleKeycloakAccount(principal, roles, keycloakSecurityContext);
|
||||||
KeycloakAuthenticationToken token = new KeycloakAuthenticationToken(account);
|
KeycloakAuthenticationToken token = new KeycloakAuthenticationToken(account, false);
|
||||||
springSecurityContext.setAuthentication(token);
|
springSecurityContext.setAuthentication(token);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+3
-32
@@ -53,7 +53,6 @@ import java.util.UUID;
|
|||||||
import static org.junit.Assert.assertFalse;
|
import static org.junit.Assert.assertFalse;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
import static org.mockito.Mockito.any;
|
import static org.mockito.Mockito.any;
|
||||||
import static org.mockito.Mockito.anyString;
|
|
||||||
import static org.mockito.Mockito.eq;
|
import static org.mockito.Mockito.eq;
|
||||||
import static org.mockito.Mockito.never;
|
import static org.mockito.Mockito.never;
|
||||||
import static org.mockito.Mockito.spy;
|
import static org.mockito.Mockito.spy;
|
||||||
@@ -124,34 +123,6 @@ public class KeycloakAuthenticationProcessingFilterTest {
|
|||||||
filter.afterPropertiesSet();
|
filter.afterPropertiesSet();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testIsBearerTokenRequest() throws Exception {
|
|
||||||
assertFalse(filter.isBearerTokenRequest(request));
|
|
||||||
this.setBearerAuthHeader(request);
|
|
||||||
assertTrue(filter.isBearerTokenRequest(request));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testIsBearerTokenRequestCaseInsensitive() throws Exception {
|
|
||||||
assertFalse(filter.isBearerTokenRequest(request));
|
|
||||||
this.setAuthorizationHeader(request, "bearer");
|
|
||||||
assertTrue(filter.isBearerTokenRequest(request));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testIsBasicAuthRequest() throws Exception {
|
|
||||||
assertFalse(filter.isBasicAuthRequest(request));
|
|
||||||
this.setBasicAuthHeader(request);
|
|
||||||
assertTrue(filter.isBasicAuthRequest(request));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testIsBasicAuthRequestCaseInsensitive() throws Exception {
|
|
||||||
assertFalse(filter.isBasicAuthRequest(request));
|
|
||||||
this.setAuthorizationHeader(request, "basic");
|
|
||||||
assertTrue(filter.isBasicAuthRequest(request));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testAttemptAuthenticationExpectRedirect() throws Exception {
|
public void testAttemptAuthenticationExpectRedirect() throws Exception {
|
||||||
when(keycloakDeployment.getAuthUrl()).thenReturn(KeycloakUriBuilder.fromUri("http://localhost:8080/auth"));
|
when(keycloakDeployment.getAuthUrl()).thenReturn(KeycloakUriBuilder.fromUri("http://localhost:8080/auth"));
|
||||||
@@ -180,7 +151,7 @@ public class KeycloakAuthenticationProcessingFilterTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSuccessfulAuthenticationInteractive() throws Exception {
|
public void testSuccessfulAuthenticationInteractive() throws Exception {
|
||||||
Authentication authentication = new KeycloakAuthenticationToken(keycloakAccount, authorities);
|
Authentication authentication = new KeycloakAuthenticationToken(keycloakAccount, true, authorities);
|
||||||
filter.successfulAuthentication(request, response, chain, authentication);
|
filter.successfulAuthentication(request, response, chain, authentication);
|
||||||
|
|
||||||
verify(successHandler).onAuthenticationSuccess(eq(request), eq(response), eq(authentication));
|
verify(successHandler).onAuthenticationSuccess(eq(request), eq(response), eq(authentication));
|
||||||
@@ -189,7 +160,7 @@ public class KeycloakAuthenticationProcessingFilterTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSuccessfulAuthenticationBearer() throws Exception {
|
public void testSuccessfulAuthenticationBearer() throws Exception {
|
||||||
Authentication authentication = new KeycloakAuthenticationToken(keycloakAccount, authorities);
|
Authentication authentication = new KeycloakAuthenticationToken(keycloakAccount, false, authorities);
|
||||||
this.setBearerAuthHeader(request);
|
this.setBearerAuthHeader(request);
|
||||||
filter.successfulAuthentication(request, response, chain, authentication);
|
filter.successfulAuthentication(request, response, chain, authentication);
|
||||||
|
|
||||||
@@ -200,7 +171,7 @@ public class KeycloakAuthenticationProcessingFilterTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSuccessfulAuthenticationBasicAuth() throws Exception {
|
public void testSuccessfulAuthenticationBasicAuth() throws Exception {
|
||||||
Authentication authentication = new KeycloakAuthenticationToken(keycloakAccount, authorities);
|
Authentication authentication = new KeycloakAuthenticationToken(keycloakAccount, false, authorities);
|
||||||
this.setBasicAuthHeader(request);
|
this.setBasicAuthHeader(request);
|
||||||
filter.successfulAuthentication(request, response, chain, authentication);
|
filter.successfulAuthentication(request, response, chain, authentication);
|
||||||
|
|
||||||
|
|||||||
+68
@@ -0,0 +1,68 @@
|
|||||||
|
/*
|
||||||
|
* 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.springsecurity.filter;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.springframework.http.HttpMethod;
|
||||||
|
import org.springframework.mock.web.MockHttpServletRequest;
|
||||||
|
|
||||||
|
public class QueryParamPresenceRequestMatcherTest {
|
||||||
|
private static final String ROOT_CONTEXT_PATH = "";
|
||||||
|
|
||||||
|
private static final String VALID_PARAMETER = "access_token";
|
||||||
|
|
||||||
|
private QueryParamPresenceRequestMatcher matcher = new QueryParamPresenceRequestMatcher(VALID_PARAMETER);
|
||||||
|
|
||||||
|
private MockHttpServletRequest request;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() throws Exception {
|
||||||
|
request = new MockHttpServletRequest();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDoesNotMatchWithoutQueryParameter() throws Exception {
|
||||||
|
prepareRequest(HttpMethod.GET, ROOT_CONTEXT_PATH, "some/random/uri", Collections.EMPTY_MAP);
|
||||||
|
assertFalse(matcher.matches(request));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMatchesWithValidParameter() throws Exception {
|
||||||
|
prepareRequest(HttpMethod.GET, ROOT_CONTEXT_PATH, "some/random/uri", Collections.singletonMap(VALID_PARAMETER, (Object) "123"));
|
||||||
|
assertTrue(matcher.matches(request));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDoesNotMatchWithInvalidParameter() throws Exception {
|
||||||
|
prepareRequest(HttpMethod.GET, ROOT_CONTEXT_PATH, "some/random/uri", Collections.singletonMap("some_parameter", (Object) "123"));
|
||||||
|
assertFalse(matcher.matches(request));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void prepareRequest(HttpMethod method, String contextPath, String uri, Map<String, Object> params) {
|
||||||
|
request.setMethod(method.name());
|
||||||
|
request.setContextPath(contextPath);
|
||||||
|
request.setRequestURI(contextPath + "/" + uri);
|
||||||
|
request.setParameters(params);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -20,7 +20,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>3.3.0.CR1-SNAPSHOT</version>
|
<version>3.4.1.Final</version>
|
||||||
<relativePath>../../../pom.xml</relativePath>
|
<relativePath>../../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<name>Keycloak Tomcat Integration</name>
|
<name>Keycloak Tomcat Integration</name>
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-tomcat-integration-pom</artifactId>
|
<artifactId>keycloak-tomcat-integration-pom</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>3.3.0.CR1-SNAPSHOT</version>
|
<version>3.4.1.Final</version>
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|||||||
+4
-5
@@ -31,7 +31,7 @@ import javax.servlet.ServletException;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pre-installed actions that must be authenticated
|
* Abstract base for pre-installed actions that must be authenticated
|
||||||
* <p/>
|
* <p/>
|
||||||
* Actions include:
|
* Actions include:
|
||||||
* <p/>
|
* <p/>
|
||||||
@@ -41,18 +41,17 @@ import java.io.IOException;
|
|||||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
* @version $Revision: 1 $
|
* @version $Revision: 1 $
|
||||||
*/
|
*/
|
||||||
public class AuthenticatedActionsValve extends ValveBase {
|
public abstract class AbstractAuthenticatedActionsValve extends ValveBase {
|
||||||
private static final Logger log = Logger.getLogger(AuthenticatedActionsValve.class);
|
private static final Logger log = Logger.getLogger(AbstractAuthenticatedActionsValve.class);
|
||||||
protected AdapterDeploymentContext deploymentContext;
|
protected AdapterDeploymentContext deploymentContext;
|
||||||
|
|
||||||
public AuthenticatedActionsValve(AdapterDeploymentContext deploymentContext, Valve next, Container container) {
|
public AbstractAuthenticatedActionsValve(AdapterDeploymentContext deploymentContext, Valve next, Container container) {
|
||||||
this.deploymentContext = deploymentContext;
|
this.deploymentContext = deploymentContext;
|
||||||
if (next == null) throw new RuntimeException("Next valve is null!!!");
|
if (next == null) throw new RuntimeException("Next valve is null!!!");
|
||||||
setNext(next);
|
setNext(next);
|
||||||
setContainer(container);
|
setContainer(container);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void invoke(Request request, Response response) throws IOException, ServletException {
|
public void invoke(Request request, Response response) throws IOException, ServletException {
|
||||||
log.debugv("AuthenticatedActionsValve.invoke {0}", request.getRequestURI());
|
log.debugv("AuthenticatedActionsValve.invoke {0}", request.getRequestURI());
|
||||||
+3
-6
@@ -17,11 +17,7 @@
|
|||||||
|
|
||||||
package org.keycloak.adapters.tomcat;
|
package org.keycloak.adapters.tomcat;
|
||||||
|
|
||||||
import org.apache.catalina.Context;
|
import org.apache.catalina.*;
|
||||||
import org.apache.catalina.Lifecycle;
|
|
||||||
import org.apache.catalina.LifecycleEvent;
|
|
||||||
import org.apache.catalina.LifecycleListener;
|
|
||||||
import org.apache.catalina.Manager;
|
|
||||||
import org.apache.catalina.authenticator.FormAuthenticator;
|
import org.apache.catalina.authenticator.FormAuthenticator;
|
||||||
import org.apache.catalina.connector.Request;
|
import org.apache.catalina.connector.Request;
|
||||||
import org.apache.catalina.connector.Response;
|
import org.apache.catalina.connector.Response;
|
||||||
@@ -136,7 +132,7 @@ public abstract class AbstractKeycloakAuthenticatorValve extends FormAuthenticat
|
|||||||
}
|
}
|
||||||
|
|
||||||
context.getServletContext().setAttribute(AdapterDeploymentContext.class.getName(), deploymentContext);
|
context.getServletContext().setAttribute(AdapterDeploymentContext.class.getName(), deploymentContext);
|
||||||
AuthenticatedActionsValve actions = new AuthenticatedActionsValve(deploymentContext, getNext(), getContainer());
|
AbstractAuthenticatedActionsValve actions = createAuthenticatedActionsValve(deploymentContext, getNext(), getContainer());
|
||||||
setNext(actions);
|
setNext(actions);
|
||||||
|
|
||||||
nodesRegistrationManagement = new NodesRegistrationManagement();
|
nodesRegistrationManagement = new NodesRegistrationManagement();
|
||||||
@@ -189,6 +185,7 @@ public abstract class AbstractKeycloakAuthenticatorValve extends FormAuthenticat
|
|||||||
|
|
||||||
protected abstract GenericPrincipalFactory createPrincipalFactory();
|
protected abstract GenericPrincipalFactory createPrincipalFactory();
|
||||||
protected abstract boolean forwardToErrorPageInternal(Request request, HttpServletResponse response, Object loginConfig) throws IOException;
|
protected abstract boolean forwardToErrorPageInternal(Request request, HttpServletResponse response, Object loginConfig) throws IOException;
|
||||||
|
protected abstract AbstractAuthenticatedActionsValve createAuthenticatedActionsValve(AdapterDeploymentContext deploymentContext, Valve next, Container container);
|
||||||
|
|
||||||
protected boolean authenticateInternal(Request request, HttpServletResponse response, Object loginConfig) throws IOException {
|
protected boolean authenticateInternal(Request request, HttpServletResponse response, Object loginConfig) throws IOException {
|
||||||
CatalinaHttpFacade facade = new OIDCCatalinaHttpFacade(request, response);
|
CatalinaHttpFacade facade = new OIDCCatalinaHttpFacade(request, response);
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-tomcat-integration-pom</artifactId>
|
<artifactId>keycloak-tomcat-integration-pom</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>3.3.0.CR1-SNAPSHOT</version>
|
<version>3.4.1.Final</version>
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|||||||
+12
@@ -0,0 +1,12 @@
|
|||||||
|
package org.keycloak.adapters.tomcat;
|
||||||
|
|
||||||
|
import org.apache.catalina.Container;
|
||||||
|
import org.apache.catalina.Valve;
|
||||||
|
import org.keycloak.adapters.AdapterDeploymentContext;
|
||||||
|
|
||||||
|
public class AuthenticatedActionsValve extends AbstractAuthenticatedActionsValve {
|
||||||
|
|
||||||
|
public AuthenticatedActionsValve(AdapterDeploymentContext deploymentContext, Valve next, Container container) {
|
||||||
|
super(deploymentContext, next, container);
|
||||||
|
}
|
||||||
|
}
|
||||||
+7
@@ -17,12 +17,15 @@
|
|||||||
|
|
||||||
package org.keycloak.adapters.tomcat;
|
package org.keycloak.adapters.tomcat;
|
||||||
|
|
||||||
|
import org.apache.catalina.Container;
|
||||||
import org.apache.catalina.LifecycleException;
|
import org.apache.catalina.LifecycleException;
|
||||||
|
import org.apache.catalina.Valve;
|
||||||
import org.apache.catalina.connector.Request;
|
import org.apache.catalina.connector.Request;
|
||||||
import org.apache.catalina.connector.Response;
|
import org.apache.catalina.connector.Response;
|
||||||
import org.apache.catalina.core.StandardContext;
|
import org.apache.catalina.core.StandardContext;
|
||||||
import org.apache.catalina.deploy.LoginConfig;
|
import org.apache.catalina.deploy.LoginConfig;
|
||||||
import org.apache.catalina.realm.GenericPrincipal;
|
import org.apache.catalina.realm.GenericPrincipal;
|
||||||
|
import org.keycloak.adapters.AdapterDeploymentContext;
|
||||||
|
|
||||||
import javax.servlet.ServletException;
|
import javax.servlet.ServletException;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
@@ -51,6 +54,10 @@ public class KeycloakAuthenticatorValve extends AbstractKeycloakAuthenticatorVal
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected AbstractAuthenticatedActionsValve createAuthenticatedActionsValve(AdapterDeploymentContext deploymentContext, Valve next, Container container) {
|
||||||
|
return new AuthenticatedActionsValve(deploymentContext, next, container);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void start() throws LifecycleException {
|
public void start() throws LifecycleException {
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-tomcat-integration-pom</artifactId>
|
<artifactId>keycloak-tomcat-integration-pom</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>3.3.0.CR1-SNAPSHOT</version>
|
<version>3.4.1.Final</version>
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|||||||
+17
@@ -0,0 +1,17 @@
|
|||||||
|
package org.keycloak.adapters.tomcat;
|
||||||
|
|
||||||
|
import org.apache.catalina.Container;
|
||||||
|
import org.apache.catalina.Valve;
|
||||||
|
import org.keycloak.adapters.AdapterDeploymentContext;
|
||||||
|
|
||||||
|
public class AuthenticatedActionsValve extends AbstractAuthenticatedActionsValve {
|
||||||
|
|
||||||
|
public AuthenticatedActionsValve(AdapterDeploymentContext deploymentContext, Valve next, Container container) {
|
||||||
|
super(deploymentContext, next, container);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isAsyncSupported() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
+8
@@ -17,11 +17,14 @@
|
|||||||
|
|
||||||
package org.keycloak.adapters.tomcat;
|
package org.keycloak.adapters.tomcat;
|
||||||
|
|
||||||
|
import org.apache.catalina.Container;
|
||||||
|
import org.apache.catalina.Valve;
|
||||||
import org.apache.catalina.connector.Request;
|
import org.apache.catalina.connector.Request;
|
||||||
import org.apache.catalina.connector.Response;
|
import org.apache.catalina.connector.Response;
|
||||||
import org.apache.catalina.core.StandardContext;
|
import org.apache.catalina.core.StandardContext;
|
||||||
import org.apache.catalina.deploy.LoginConfig;
|
import org.apache.catalina.deploy.LoginConfig;
|
||||||
import org.apache.catalina.realm.GenericPrincipal;
|
import org.apache.catalina.realm.GenericPrincipal;
|
||||||
|
import org.keycloak.adapters.AdapterDeploymentContext;
|
||||||
|
|
||||||
import javax.servlet.ServletException;
|
import javax.servlet.ServletException;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
@@ -69,4 +72,9 @@ public class KeycloakAuthenticatorValve extends AbstractKeycloakAuthenticatorVal
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected AbstractAuthenticatedActionsValve createAuthenticatedActionsValve(AdapterDeploymentContext deploymentContext, Valve next, Container container) {
|
||||||
|
return new AuthenticatedActionsValve(deploymentContext, next, container);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -21,7 +21,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-tomcat-integration-pom</artifactId>
|
<artifactId>keycloak-tomcat-integration-pom</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>3.3.0.CR1-SNAPSHOT</version>
|
<version>3.4.1.Final</version>
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|||||||
+17
@@ -0,0 +1,17 @@
|
|||||||
|
package org.keycloak.adapters.tomcat;
|
||||||
|
|
||||||
|
import org.apache.catalina.Container;
|
||||||
|
import org.apache.catalina.Valve;
|
||||||
|
import org.keycloak.adapters.AdapterDeploymentContext;
|
||||||
|
|
||||||
|
public class AuthenticatedActionsValve extends AbstractAuthenticatedActionsValve {
|
||||||
|
|
||||||
|
public AuthenticatedActionsValve(AdapterDeploymentContext deploymentContext, Valve next, Container container) {
|
||||||
|
super(deploymentContext, next, container);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isAsyncSupported() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
+8
@@ -17,11 +17,14 @@
|
|||||||
|
|
||||||
package org.keycloak.adapters.tomcat;
|
package org.keycloak.adapters.tomcat;
|
||||||
|
|
||||||
|
import org.apache.catalina.Container;
|
||||||
|
import org.apache.catalina.Valve;
|
||||||
import org.apache.catalina.authenticator.FormAuthenticator;
|
import org.apache.catalina.authenticator.FormAuthenticator;
|
||||||
import org.apache.catalina.connector.Request;
|
import org.apache.catalina.connector.Request;
|
||||||
import org.apache.catalina.core.StandardContext;
|
import org.apache.catalina.core.StandardContext;
|
||||||
import org.apache.catalina.realm.GenericPrincipal;
|
import org.apache.catalina.realm.GenericPrincipal;
|
||||||
import org.apache.tomcat.util.descriptor.web.LoginConfig;
|
import org.apache.tomcat.util.descriptor.web.LoginConfig;
|
||||||
|
import org.keycloak.adapters.AdapterDeploymentContext;
|
||||||
import org.keycloak.adapters.AdapterTokenStore;
|
import org.keycloak.adapters.AdapterTokenStore;
|
||||||
import org.keycloak.adapters.KeycloakDeployment;
|
import org.keycloak.adapters.KeycloakDeployment;
|
||||||
import org.keycloak.adapters.spi.HttpFacade;
|
import org.keycloak.adapters.spi.HttpFacade;
|
||||||
@@ -102,4 +105,9 @@ public class KeycloakAuthenticatorValve extends AbstractKeycloakAuthenticatorVal
|
|||||||
protected AdapterTokenStore getTokenStore(Request request, HttpFacade facade, KeycloakDeployment resolvedDeployment) {
|
protected AdapterTokenStore getTokenStore(Request request, HttpFacade facade, KeycloakDeployment resolvedDeployment) {
|
||||||
return super.getTokenStore(request, facade, resolvedDeployment);
|
return super.getTokenStore(request, facade, resolvedDeployment);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected AbstractAuthenticatedActionsValve createAuthenticatedActionsValve(AdapterDeploymentContext deploymentContext, Valve next, Container container) {
|
||||||
|
return new AuthenticatedActionsValve(deploymentContext, next, container);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -21,7 +21,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>3.3.0.CR1-SNAPSHOT</version>
|
<version>3.4.1.Final</version>
|
||||||
<relativePath>../../../pom.xml</relativePath>
|
<relativePath>../../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>3.3.0.CR1-SNAPSHOT</version>
|
<version>3.4.1.Final</version>
|
||||||
<relativePath>../../../pom.xml</relativePath>
|
<relativePath>../../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
@@ -40,7 +40,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.wildfly.common</groupId>
|
<groupId>org.wildfly.common</groupId>
|
||||||
<artifactId>wildfly-common</artifactId>
|
<artifactId>wildfly-common</artifactId>
|
||||||
<version>1.2.0.Beta1</version>
|
<scope>provided</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.wildfly.security</groupId>
|
<groupId>org.wildfly.security</groupId>
|
||||||
|
|||||||
+1
-1
@@ -53,7 +53,7 @@ public class ElytronSessionTokenStore implements ElytronTokeStore {
|
|||||||
@Override
|
@Override
|
||||||
public void checkCurrentToken() {
|
public void checkCurrentToken() {
|
||||||
HttpScope session = httpFacade.getScope(Scope.SESSION);
|
HttpScope session = httpFacade.getScope(Scope.SESSION);
|
||||||
if (!session.exists()) return;
|
if (session == null || !session.exists()) return;
|
||||||
RefreshableKeycloakSecurityContext securityContext = (RefreshableKeycloakSecurityContext) session.getAttachment(KeycloakSecurityContext.class.getName());
|
RefreshableKeycloakSecurityContext securityContext = (RefreshableKeycloakSecurityContext) session.getAttachment(KeycloakSecurityContext.class.getName());
|
||||||
if (securityContext == null) return;
|
if (securityContext == null) return;
|
||||||
|
|
||||||
|
|||||||
+24
-19
@@ -42,35 +42,40 @@ import java.io.InputStream;
|
|||||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||||
*/
|
*/
|
||||||
public class KeycloakConfigurationServletListener implements ServletContextListener {
|
public class KeycloakConfigurationServletListener implements ServletContextListener {
|
||||||
|
|
||||||
|
static final String ADAPTER_DEPLOYMENT_CONTEXT_ATTRIBUTE = AdapterDeploymentContext.class.getName() + ".elytron";
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void contextInitialized(ServletContextEvent sce) {
|
public void contextInitialized(ServletContextEvent sce) {
|
||||||
ServletContext servletContext = sce.getServletContext();
|
ServletContext servletContext = sce.getServletContext();
|
||||||
String configResolverClass = servletContext.getInitParameter("keycloak.config.resolver");
|
String configResolverClass = servletContext.getInitParameter("keycloak.config.resolver");
|
||||||
KeycloakConfigResolver configResolver;
|
KeycloakConfigResolver configResolver;
|
||||||
AdapterDeploymentContext deploymentContext;
|
AdapterDeploymentContext deploymentContext = (AdapterDeploymentContext) servletContext.getAttribute(AdapterDeploymentContext.class.getName());
|
||||||
|
|
||||||
if (configResolverClass != null) {
|
if (deploymentContext == null) {
|
||||||
try {
|
if (configResolverClass != null) {
|
||||||
configResolver = (KeycloakConfigResolver) servletContext.getClassLoader().loadClass(configResolverClass).newInstance();
|
try {
|
||||||
deploymentContext = new AdapterDeploymentContext(configResolver);
|
configResolver = (KeycloakConfigResolver) servletContext.getClassLoader().loadClass(configResolverClass).newInstance();
|
||||||
} catch (Exception ex) {
|
deploymentContext = new AdapterDeploymentContext(configResolver);
|
||||||
deploymentContext = new AdapterDeploymentContext(new KeycloakDeployment());
|
} catch (Exception ex) {
|
||||||
}
|
deploymentContext = new AdapterDeploymentContext(new KeycloakDeployment());
|
||||||
} else {
|
}
|
||||||
InputStream is = getConfigInputStream(servletContext);
|
|
||||||
|
|
||||||
KeycloakDeployment deployment;
|
|
||||||
|
|
||||||
if (is == null) {
|
|
||||||
deployment = new KeycloakDeployment();
|
|
||||||
} else {
|
} else {
|
||||||
deployment = KeycloakDeploymentBuilder.build(is);
|
InputStream is = getConfigInputStream(servletContext);
|
||||||
}
|
|
||||||
|
|
||||||
deploymentContext = new AdapterDeploymentContext(deployment);
|
KeycloakDeployment deployment;
|
||||||
|
|
||||||
|
if (is == null) {
|
||||||
|
deployment = new KeycloakDeployment();
|
||||||
|
} else {
|
||||||
|
deployment = KeycloakDeploymentBuilder.build(is);
|
||||||
|
}
|
||||||
|
|
||||||
|
deploymentContext = new AdapterDeploymentContext(deployment);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
servletContext.setAttribute(AdapterDeploymentContext.class.getName(), deploymentContext);
|
servletContext.setAttribute(ADAPTER_DEPLOYMENT_CONTEXT_ATTRIBUTE, deploymentContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
+1
-2
@@ -31,7 +31,6 @@ import org.keycloak.adapters.AuthenticatedActionsHandler;
|
|||||||
import org.keycloak.adapters.KeycloakDeployment;
|
import org.keycloak.adapters.KeycloakDeployment;
|
||||||
import org.keycloak.adapters.NodesRegistrationManagement;
|
import org.keycloak.adapters.NodesRegistrationManagement;
|
||||||
import org.keycloak.adapters.PreAuthActionsHandler;
|
import org.keycloak.adapters.PreAuthActionsHandler;
|
||||||
import org.keycloak.adapters.RefreshableKeycloakSecurityContext;
|
|
||||||
import org.keycloak.adapters.RequestAuthenticator;
|
import org.keycloak.adapters.RequestAuthenticator;
|
||||||
import org.keycloak.adapters.spi.AuthChallenge;
|
import org.keycloak.adapters.spi.AuthChallenge;
|
||||||
import org.keycloak.adapters.spi.AuthOutcome;
|
import org.keycloak.adapters.spi.AuthOutcome;
|
||||||
@@ -127,7 +126,7 @@ class KeycloakHttpServerAuthenticationMechanism implements HttpServerAuthenticat
|
|||||||
|
|
||||||
private AdapterDeploymentContext getDeploymentContext(HttpServerRequest request) {
|
private AdapterDeploymentContext getDeploymentContext(HttpServerRequest request) {
|
||||||
if (this.deploymentContext == null) {
|
if (this.deploymentContext == null) {
|
||||||
return (AdapterDeploymentContext) request.getScope(Scope.APPLICATION).getAttachment(AdapterDeploymentContext.class.getName());
|
return (AdapterDeploymentContext) request.getScope(Scope.APPLICATION).getAttachment(KeycloakConfigurationServletListener.ADAPTER_DEPLOYMENT_CONTEXT_ATTRIBUTE);
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.deploymentContext;
|
return this.deploymentContext;
|
||||||
|
|||||||
+4
-1
@@ -30,8 +30,10 @@ import org.keycloak.KeycloakPrincipal;
|
|||||||
import org.keycloak.adapters.RefreshableKeycloakSecurityContext;
|
import org.keycloak.adapters.RefreshableKeycloakSecurityContext;
|
||||||
import org.wildfly.security.auth.callback.AuthenticationCompleteCallback;
|
import org.wildfly.security.auth.callback.AuthenticationCompleteCallback;
|
||||||
import org.wildfly.security.auth.callback.EvidenceVerifyCallback;
|
import org.wildfly.security.auth.callback.EvidenceVerifyCallback;
|
||||||
|
import org.wildfly.security.auth.callback.IdentityCredentialCallback;
|
||||||
import org.wildfly.security.auth.callback.SecurityIdentityCallback;
|
import org.wildfly.security.auth.callback.SecurityIdentityCallback;
|
||||||
import org.wildfly.security.auth.server.SecurityIdentity;
|
import org.wildfly.security.auth.server.SecurityIdentity;
|
||||||
|
import org.wildfly.security.credential.BearerTokenCredential;
|
||||||
import org.wildfly.security.evidence.Evidence;
|
import org.wildfly.security.evidence.Evidence;
|
||||||
import org.wildfly.security.http.HttpAuthenticationException;
|
import org.wildfly.security.http.HttpAuthenticationException;
|
||||||
|
|
||||||
@@ -63,8 +65,9 @@ final class SecurityIdentityUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SecurityIdentityCallback securityIdentityCallback = new SecurityIdentityCallback();
|
SecurityIdentityCallback securityIdentityCallback = new SecurityIdentityCallback();
|
||||||
|
IdentityCredentialCallback credentialCallback = new IdentityCredentialCallback(new BearerTokenCredential(KeycloakPrincipal.class.cast(principal).getKeycloakSecurityContext().getTokenString()), true);
|
||||||
|
|
||||||
callbackHandler.handle(new Callback[]{AuthenticationCompleteCallback.SUCCEEDED, securityIdentityCallback});
|
callbackHandler.handle(new Callback[]{credentialCallback, AuthenticationCompleteCallback.SUCCEEDED, securityIdentityCallback});
|
||||||
|
|
||||||
SecurityIdentity securityIdentity = securityIdentityCallback.getSecurityIdentity();
|
SecurityIdentity securityIdentity = securityIdentityCallback.getSecurityIdentity();
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>3.3.0.CR1-SNAPSHOT</version>
|
<version>3.4.1.Final</version>
|
||||||
<relativePath>../../../pom.xml</relativePath>
|
<relativePath>../../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<name>Keycloak WildFly Integration</name>
|
<name>Keycloak WildFly Integration</name>
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<version>3.3.0.CR1-SNAPSHOT</version>
|
<version>3.4.1.Final</version>
|
||||||
<relativePath>../../../../pom.xml</relativePath>
|
<relativePath>../../../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>3.3.0.CR1-SNAPSHOT</version>
|
<version>3.4.1.Final</version>
|
||||||
<relativePath>../../../../pom.xml</relativePath>
|
<relativePath>../../../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<version>3.3.0.CR1-SNAPSHOT</version>
|
<version>3.4.1.Final</version>
|
||||||
<relativePath>../../../../pom.xml</relativePath>
|
<relativePath>../../../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|||||||
+4
-8
@@ -71,11 +71,10 @@ public class KeycloakAdapterConfigDeploymentProcessor implements DeploymentUnitP
|
|||||||
KeycloakAdapterConfigService service = KeycloakAdapterConfigService.getInstance();
|
KeycloakAdapterConfigService service = KeycloakAdapterConfigService.getInstance();
|
||||||
if (service.isSecureDeployment(deploymentUnit) && service.isDeploymentConfigured(deploymentUnit)) {
|
if (service.isSecureDeployment(deploymentUnit) && service.isDeploymentConfigured(deploymentUnit)) {
|
||||||
addKeycloakAuthData(phaseContext, service);
|
addKeycloakAuthData(phaseContext, service);
|
||||||
} else if (service.isElytronEnabled(deploymentUnit)) {
|
|
||||||
WarMetaData warMetaData = deploymentUnit.getAttachment(WarMetaData.ATTACHMENT_KEY);
|
|
||||||
addConfigurationListener(warMetaData);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
addConfigurationListener(deploymentUnit);
|
||||||
|
|
||||||
// FYI, Undertow Extension will find deployments that have auth-method set to KEYCLOAK
|
// FYI, Undertow Extension will find deployments that have auth-method set to KEYCLOAK
|
||||||
|
|
||||||
// todo notsure if we need this
|
// todo notsure if we need this
|
||||||
@@ -104,10 +103,6 @@ public class KeycloakAdapterConfigDeploymentProcessor implements DeploymentUnitP
|
|||||||
loginConfig.setAuthMethod("KEYCLOAK");
|
loginConfig.setAuthMethod("KEYCLOAK");
|
||||||
loginConfig.setRealmName(service.getRealmName(deploymentUnit));
|
loginConfig.setRealmName(service.getRealmName(deploymentUnit));
|
||||||
KeycloakLogger.ROOT_LOGGER.deploymentSecured(deploymentUnit.getName());
|
KeycloakLogger.ROOT_LOGGER.deploymentSecured(deploymentUnit.getName());
|
||||||
|
|
||||||
if (service.isElytronEnabled(deploymentUnit)) {
|
|
||||||
addConfigurationListener(warMetaData);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addJSONData(String json, WarMetaData warMetaData) {
|
private void addJSONData(String json, WarMetaData warMetaData) {
|
||||||
@@ -130,7 +125,8 @@ public class KeycloakAdapterConfigDeploymentProcessor implements DeploymentUnitP
|
|||||||
webMetaData.setContextParams(contextParams);
|
webMetaData.setContextParams(contextParams);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addConfigurationListener(WarMetaData warMetaData) {
|
private void addConfigurationListener(DeploymentUnit deploymentUnit) {
|
||||||
|
WarMetaData warMetaData = deploymentUnit.getAttachment(WarMetaData.ATTACHMENT_KEY);
|
||||||
if (warMetaData == null) {
|
if (warMetaData == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-5
@@ -276,11 +276,13 @@ public final class KeycloakAdapterConfigService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void setJSONValues(ModelNode json, ModelNode values) {
|
private void setJSONValues(ModelNode json, ModelNode values) {
|
||||||
for (Property prop : new ArrayList<>(values.asPropertyList())) {
|
synchronized (values) {
|
||||||
String name = prop.getName();
|
for (Property prop : new ArrayList<>(values.asPropertyList())) {
|
||||||
ModelNode value = prop.getValue();
|
String name = prop.getName();
|
||||||
if (value.isDefined()) {
|
ModelNode value = prop.getValue();
|
||||||
json.get(name).set(value);
|
if (value.isDefined()) {
|
||||||
|
json.get(name).set(value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-1
@@ -186,7 +186,12 @@ public class SharedAttributeDefinitons {
|
|||||||
.setDefaultValue(new ModelNode(false))
|
.setDefaultValue(new ModelNode(false))
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
protected static final SimpleAttributeDefinition CONFIDENTIAL_PORT =
|
||||||
|
new SimpleAttributeDefinitionBuilder("confidential-port", ModelType.INT, true)
|
||||||
|
.setXmlName("confidential-port")
|
||||||
|
.setAllowExpression(true)
|
||||||
|
.setDefaultValue(new ModelNode(8443))
|
||||||
|
.build();
|
||||||
|
|
||||||
|
|
||||||
protected static final List<SimpleAttributeDefinition> ATTRIBUTES = new ArrayList<SimpleAttributeDefinition>();
|
protected static final List<SimpleAttributeDefinition> ATTRIBUTES = new ArrayList<SimpleAttributeDefinition>();
|
||||||
@@ -196,6 +201,7 @@ public class SharedAttributeDefinitons {
|
|||||||
ATTRIBUTES.add(TRUSTSTORE);
|
ATTRIBUTES.add(TRUSTSTORE);
|
||||||
ATTRIBUTES.add(TRUSTSTORE_PASSWORD);
|
ATTRIBUTES.add(TRUSTSTORE_PASSWORD);
|
||||||
ATTRIBUTES.add(SSL_REQUIRED);
|
ATTRIBUTES.add(SSL_REQUIRED);
|
||||||
|
ATTRIBUTES.add(CONFIDENTIAL_PORT);
|
||||||
ATTRIBUTES.add(ALLOW_ANY_HOSTNAME);
|
ATTRIBUTES.add(ALLOW_ANY_HOSTNAME);
|
||||||
ATTRIBUTES.add(DISABLE_TRUST_MANAGER);
|
ATTRIBUTES.add(DISABLE_TRUST_MANAGER);
|
||||||
ATTRIBUTES.add(CONNECTION_POOL_SIZE);
|
ATTRIBUTES.add(CONNECTION_POOL_SIZE);
|
||||||
|
|||||||
+3
@@ -30,6 +30,7 @@ keycloak.realm.realm-public-key=Public key of the realm
|
|||||||
keycloak.realm.auth-server-url=Base URL of the Realm Auth Server
|
keycloak.realm.auth-server-url=Base URL of the Realm Auth Server
|
||||||
keycloak.realm.disable-trust-manager=Adapter will not use a trust manager when making adapter HTTPS requests
|
keycloak.realm.disable-trust-manager=Adapter will not use a trust manager when making adapter HTTPS requests
|
||||||
keycloak.realm.ssl-required=Specify if SSL is required (valid values are all, external and none)
|
keycloak.realm.ssl-required=Specify if SSL is required (valid values are all, external and none)
|
||||||
|
keycloak.realm.confidential-port=Specify the confidential port (SSL/TLS) used by the Realm Auth Server
|
||||||
keycloak.realm.allow-any-hostname=SSL Setting
|
keycloak.realm.allow-any-hostname=SSL Setting
|
||||||
keycloak.realm.truststore=Truststore used for adapter client HTTPS requests
|
keycloak.realm.truststore=Truststore used for adapter client HTTPS requests
|
||||||
keycloak.realm.truststore-password=Password of the Truststore
|
keycloak.realm.truststore-password=Password of the Truststore
|
||||||
@@ -60,6 +61,7 @@ keycloak.secure-deployment.realm-public-key=Public key of the realm
|
|||||||
keycloak.secure-deployment.auth-server-url=Base URL of the Realm Auth Server
|
keycloak.secure-deployment.auth-server-url=Base URL of the Realm Auth Server
|
||||||
keycloak.secure-deployment.disable-trust-manager=Adapter will not use a trust manager when making adapter HTTPS requests
|
keycloak.secure-deployment.disable-trust-manager=Adapter will not use a trust manager when making adapter HTTPS requests
|
||||||
keycloak.secure-deployment.ssl-required=Specify if SSL is required (valid values are all, external and none)
|
keycloak.secure-deployment.ssl-required=Specify if SSL is required (valid values are all, external and none)
|
||||||
|
keycloak.secure-deployment.confidential-port=Specify the confidential port (SSL/TLS) used by the Realm Auth Server
|
||||||
keycloak.secure-deployment.allow-any-hostname=SSL Setting
|
keycloak.secure-deployment.allow-any-hostname=SSL Setting
|
||||||
keycloak.secure-deployment.truststore=Truststore used for adapter client HTTPS requests
|
keycloak.secure-deployment.truststore=Truststore used for adapter client HTTPS requests
|
||||||
keycloak.secure-deployment.truststore-password=Password of the Truststore
|
keycloak.secure-deployment.truststore-password=Password of the Truststore
|
||||||
@@ -100,6 +102,7 @@ keycloak.secure-server.realm-public-key=Public key of the realm
|
|||||||
keycloak.secure-server.auth-server-url=Base URL of the Realm Auth Server
|
keycloak.secure-server.auth-server-url=Base URL of the Realm Auth Server
|
||||||
keycloak.secure-server.disable-trust-manager=Adapter will not use a trust manager when making adapter HTTPS requests
|
keycloak.secure-server.disable-trust-manager=Adapter will not use a trust manager when making adapter HTTPS requests
|
||||||
keycloak.secure-server.ssl-required=Specify if SSL is required (valid values are all, external and none)
|
keycloak.secure-server.ssl-required=Specify if SSL is required (valid values are all, external and none)
|
||||||
|
keycloak.secure-server.confidential-port=Specify the confidential port (SSL/TLS) used by the Realm Auth Server
|
||||||
keycloak.secure-server.allow-any-hostname=SSL Setting
|
keycloak.secure-server.allow-any-hostname=SSL Setting
|
||||||
keycloak.secure-server.truststore=Truststore used for adapter client HTTPS requests
|
keycloak.secure-server.truststore=Truststore used for adapter client HTTPS requests
|
||||||
keycloak.secure-server.truststore-password=Password of the Truststore
|
keycloak.secure-server.truststore-password=Password of the Truststore
|
||||||
|
|||||||
+2
@@ -58,6 +58,7 @@
|
|||||||
<xs:element name="expose-token" type="xs:boolean" minOccurs="0" maxOccurs="1"/>
|
<xs:element name="expose-token" type="xs:boolean" minOccurs="0" maxOccurs="1"/>
|
||||||
<xs:element name="disable-trust-manager" type="xs:boolean" minOccurs="0" maxOccurs="1" />
|
<xs:element name="disable-trust-manager" type="xs:boolean" minOccurs="0" maxOccurs="1" />
|
||||||
<xs:element name="ssl-required" type="xs:string" minOccurs="0" maxOccurs="1" />
|
<xs:element name="ssl-required" type="xs:string" minOccurs="0" maxOccurs="1" />
|
||||||
|
<xs:element name="confidential-port" type="xs:integer" minOccurs="0" maxOccurs="1" />
|
||||||
<xs:element name="cors-allowed-methods" type="xs:string" minOccurs="0" maxOccurs="1"/>
|
<xs:element name="cors-allowed-methods" type="xs:string" minOccurs="0" maxOccurs="1"/>
|
||||||
<xs:element name="cors-exposed-headers" type="xs:string" minOccurs="0" maxOccurs="1"/>
|
<xs:element name="cors-exposed-headers" type="xs:string" minOccurs="0" maxOccurs="1"/>
|
||||||
<xs:element name="realm-public-key" type="xs:string" minOccurs="1" maxOccurs="1"/>
|
<xs:element name="realm-public-key" type="xs:string" minOccurs="1" maxOccurs="1"/>
|
||||||
@@ -100,6 +101,7 @@
|
|||||||
<xs:element name="connection-pool-size" type="xs:integer" minOccurs="0" maxOccurs="1"/>
|
<xs:element name="connection-pool-size" type="xs:integer" minOccurs="0" maxOccurs="1"/>
|
||||||
<xs:element name="expose-token" type="xs:boolean" minOccurs="0" maxOccurs="1"/>
|
<xs:element name="expose-token" type="xs:boolean" minOccurs="0" maxOccurs="1"/>
|
||||||
<xs:element name="ssl-required" type="xs:string" minOccurs="0" maxOccurs="1" />
|
<xs:element name="ssl-required" type="xs:string" minOccurs="0" maxOccurs="1" />
|
||||||
|
<xs:element name="confidential-port" type="xs:integer" minOccurs="0" maxOccurs="1" />
|
||||||
<xs:element name="realm-public-key" type="xs:string" minOccurs="0" maxOccurs="1"/>
|
<xs:element name="realm-public-key" type="xs:string" minOccurs="0" maxOccurs="1"/>
|
||||||
<xs:element name="credential" type="credential-type" minOccurs="0" maxOccurs="1"/>
|
<xs:element name="credential" type="credential-type" minOccurs="0" maxOccurs="1"/>
|
||||||
<xs:element name="redirect-rewrite-rule" type="redirect-rewrite-rule-type" minOccurs="0" maxOccurs="1"/>
|
<xs:element name="redirect-rewrite-rule" type="redirect-rewrite-rule-type" minOccurs="0" maxOccurs="1"/>
|
||||||
|
|||||||
+1
@@ -51,6 +51,7 @@ public class SubsystemParsingTestCase extends AbstractSubsystemBaseTest {
|
|||||||
node.get("auth-url").set("http://localhost:8080/auth-server/rest/realms/demo/protocol/openid-connect/login");
|
node.get("auth-url").set("http://localhost:8080/auth-server/rest/realms/demo/protocol/openid-connect/login");
|
||||||
node.get("code-url").set("http://localhost:8080/auth-server/rest/realms/demo/protocol/openid-connect/access/codes");
|
node.get("code-url").set("http://localhost:8080/auth-server/rest/realms/demo/protocol/openid-connect/access/codes");
|
||||||
node.get("ssl-required").set("external");
|
node.get("ssl-required").set("external");
|
||||||
|
node.get("confidential-port").set(443);
|
||||||
node.get("expose-token").set(true);
|
node.get("expose-token").set(true);
|
||||||
|
|
||||||
ModelNode jwtCredential = new ModelNode();
|
ModelNode jwtCredential = new ModelNode();
|
||||||
|
|||||||
+4
@@ -22,6 +22,7 @@
|
|||||||
<truststore>truststore.jks</truststore>
|
<truststore>truststore.jks</truststore>
|
||||||
<truststore-password>secret</truststore-password>
|
<truststore-password>secret</truststore-password>
|
||||||
<ssl-required>EXTERNAL</ssl-required>
|
<ssl-required>EXTERNAL</ssl-required>
|
||||||
|
<confidential-port>443</confidential-port>
|
||||||
<allow-any-hostname>false</allow-any-hostname>
|
<allow-any-hostname>false</allow-any-hostname>
|
||||||
<disable-trust-manager>true</disable-trust-manager>
|
<disable-trust-manager>true</disable-trust-manager>
|
||||||
<connection-pool-size>20</connection-pool-size>
|
<connection-pool-size>20</connection-pool-size>
|
||||||
@@ -56,6 +57,7 @@
|
|||||||
</realm-public-key>
|
</realm-public-key>
|
||||||
<auth-server-url>http://localhost:8080/auth</auth-server-url>
|
<auth-server-url>http://localhost:8080/auth</auth-server-url>
|
||||||
<ssl-required>EXTERNAL</ssl-required>
|
<ssl-required>EXTERNAL</ssl-required>
|
||||||
|
<confidential-port>443</confidential-port>
|
||||||
<credential name="secret">0aa31d98-e0aa-404c-b6e0-e771dba1e798</credential>
|
<credential name="secret">0aa31d98-e0aa-404c-b6e0-e771dba1e798</credential>
|
||||||
<redirect-rewrite-rule name="^/wsmaster/api/(.*)$">api/$1/</redirect-rewrite-rule>
|
<redirect-rewrite-rule name="^/wsmaster/api/(.*)$">api/$1/</redirect-rewrite-rule>
|
||||||
</secure-deployment>
|
</secure-deployment>
|
||||||
@@ -84,5 +86,7 @@
|
|||||||
<realm>jboss-infra</realm>
|
<realm>jboss-infra</realm>
|
||||||
<resource>wildfly-console</resource>
|
<resource>wildfly-console</resource>
|
||||||
<public-client>true</public-client>
|
<public-client>true</public-client>
|
||||||
|
<ssl-required>EXTERNAL</ssl-required>
|
||||||
|
<confidential-port>443</confidential-port>
|
||||||
</secure-server>
|
</secure-server>
|
||||||
</subsystem>
|
</subsystem>
|
||||||
+1
-1
@@ -20,7 +20,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>3.3.0.CR1-SNAPSHOT</version>
|
<version>3.4.1.Final</version>
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<name>Keycloak Adapters</name>
|
<name>Keycloak Adapters</name>
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-saml-eap-integration-pom</artifactId>
|
<artifactId>keycloak-saml-eap-integration-pom</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>3.3.0.CR1-SNAPSHOT</version>
|
<version>3.4.1.Final</version>
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>3.3.0.CR1-SNAPSHOT</version>
|
<version>3.4.1.Final</version>
|
||||||
<relativePath>../../../pom.xml</relativePath>
|
<relativePath>../../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<name>Keycloak SAML EAP Integration</name>
|
<name>Keycloak SAML EAP Integration</name>
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<artifactId>keycloak-saml-eap-integration-pom</artifactId>
|
<artifactId>keycloak-saml-eap-integration-pom</artifactId>
|
||||||
<version>3.3.0.CR1-SNAPSHOT</version>
|
<version>3.4.1.Final</version>
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|||||||
+3
-2
@@ -16,7 +16,6 @@
|
|||||||
*/
|
*/
|
||||||
package org.keycloak.subsystem.saml.as7;
|
package org.keycloak.subsystem.saml.as7;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:mstrukel@redhat.com">Marko Strukelj</a>
|
* @author <a href="mailto:mstrukel@redhat.com">Marko Strukelj</a>
|
||||||
*/
|
*/
|
||||||
@@ -46,6 +45,8 @@ public class Constants {
|
|||||||
static final String SIGN_REQUEST = "signRequest";
|
static final String SIGN_REQUEST = "signRequest";
|
||||||
static final String VALIDATE_RESPONSE_SIGNATURE = "validateResponseSignature";
|
static final String VALIDATE_RESPONSE_SIGNATURE = "validateResponseSignature";
|
||||||
static final String VALIDATE_ASSERTION_SIGNATURE = "validateAssertionSignature";
|
static final String VALIDATE_ASSERTION_SIGNATURE = "validateAssertionSignature";
|
||||||
|
static final String ASSERTION_CONSUMER_SERVICE_URL = "assertionConsumerServiceUrl";
|
||||||
|
|
||||||
static final String REQUEST_BINDING = "requestBinding";
|
static final String REQUEST_BINDING = "requestBinding";
|
||||||
static final String BINDING_URL = "bindingUrl";
|
static final String BINDING_URL = "bindingUrl";
|
||||||
static final String VALIDATE_REQUEST_SIGNATURE = "validateRequestSignature";
|
static final String VALIDATE_REQUEST_SIGNATURE = "validateRequestSignature";
|
||||||
@@ -69,7 +70,6 @@ public class Constants {
|
|||||||
static final String SIGNATURES_REQUIRED = "signaturesRequired";
|
static final String SIGNATURES_REQUIRED = "signaturesRequired";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static class XML {
|
static class XML {
|
||||||
static final String SECURE_DEPLOYMENT = "secure-deployment";
|
static final String SECURE_DEPLOYMENT = "secure-deployment";
|
||||||
static final String SERVICE_PROVIDER = "SP";
|
static final String SERVICE_PROVIDER = "SP";
|
||||||
@@ -122,5 +122,6 @@ public class Constants {
|
|||||||
static final String ALIAS = "alias";
|
static final String ALIAS = "alias";
|
||||||
static final String FILE = "file";
|
static final String FILE = "file";
|
||||||
static final String SIGNATURES_REQUIRED = "signaturesRequired";
|
static final String SIGNATURES_REQUIRED = "signaturesRequired";
|
||||||
|
static final String ASSERTION_CONSUMER_SERVICE_URL = "assertionConsumerServiceUrl";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+6
-1
@@ -56,8 +56,13 @@ abstract class SingleSignOnDefinition {
|
|||||||
new SimpleAttributeDefinitionBuilder(Constants.Model.BINDING_URL, ModelType.STRING, true)
|
new SimpleAttributeDefinitionBuilder(Constants.Model.BINDING_URL, ModelType.STRING, true)
|
||||||
.setXmlName(Constants.XML.BINDING_URL)
|
.setXmlName(Constants.XML.BINDING_URL)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
|
static final SimpleAttributeDefinition ASSERTION_CONSUMER_SERVICE_URL =
|
||||||
|
new SimpleAttributeDefinitionBuilder(Constants.Model.ASSERTION_CONSUMER_SERVICE_URL, ModelType.STRING, true)
|
||||||
|
.setXmlName(Constants.XML.ASSERTION_CONSUMER_SERVICE_URL)
|
||||||
|
.build();
|
||||||
|
|
||||||
static final SimpleAttributeDefinition[] ATTRIBUTES = {SIGN_REQUEST, VALIDATE_RESPONSE_SIGNATURE, VALIDATE_ASSERTION_SIGNATURE, REQUEST_BINDING, RESPONSE_BINDING, BINDING_URL};
|
static final SimpleAttributeDefinition[] ATTRIBUTES = {SIGN_REQUEST, VALIDATE_RESPONSE_SIGNATURE, VALIDATE_ASSERTION_SIGNATURE, REQUEST_BINDING, RESPONSE_BINDING, BINDING_URL, ASSERTION_CONSUMER_SERVICE_URL};
|
||||||
|
|
||||||
static final HashMap<String, SimpleAttributeDefinition> ATTRIBUTE_MAP = new HashMap<>();
|
static final HashMap<String, SimpleAttributeDefinition> ATTRIBUTE_MAP = new HashMap<>();
|
||||||
|
|
||||||
|
|||||||
+1
@@ -71,6 +71,7 @@ keycloak-saml.IDP.SingleSignOnService.validateAssertionSignature=Validate an SSO
|
|||||||
keycloak-saml.IDP.SingleSignOnService.requestBinding=HTTP method to use for requests
|
keycloak-saml.IDP.SingleSignOnService.requestBinding=HTTP method to use for requests
|
||||||
keycloak-saml.IDP.SingleSignOnService.responseBinding=HTTP method to use for responses
|
keycloak-saml.IDP.SingleSignOnService.responseBinding=HTTP method to use for responses
|
||||||
keycloak-saml.IDP.SingleSignOnService.bindingUrl=SSO endpoint URL
|
keycloak-saml.IDP.SingleSignOnService.bindingUrl=SSO endpoint URL
|
||||||
|
keycloak-saml.IDP.SingleSignOnService.assertionConsumerServiceUrl=Endpoint of Assertion Consumer Service at SP
|
||||||
keycloak-saml.IDP.SingleLogoutService=Single logout configuration
|
keycloak-saml.IDP.SingleLogoutService=Single logout configuration
|
||||||
keycloak-saml.IDP.SingleLogoutService.validateRequestSignature=Validate a SingleLogoutService request signature
|
keycloak-saml.IDP.SingleLogoutService.validateRequestSignature=Validate a SingleLogoutService request signature
|
||||||
keycloak-saml.IDP.SingleLogoutService.validateResponseSignature=Validate a SingleLogoutService response signature
|
keycloak-saml.IDP.SingleLogoutService.validateResponseSignature=Validate a SingleLogoutService response signature
|
||||||
|
|||||||
+5
@@ -152,6 +152,11 @@
|
|||||||
<xs:documentation>SSO endpoint URL</xs:documentation>
|
<xs:documentation>SSO endpoint URL</xs:documentation>
|
||||||
</xs:annotation>
|
</xs:annotation>
|
||||||
</xs:attribute>
|
</xs:attribute>
|
||||||
|
<xs:attribute name="assertionConsumerServiceUrl" type="xs:string" use="optional">
|
||||||
|
<xs:annotation>
|
||||||
|
<xs:documentation>Endpoint of Assertion Consumer Service at SP</xs:documentation>
|
||||||
|
</xs:annotation>
|
||||||
|
</xs:attribute>
|
||||||
</xs:complexType>
|
</xs:complexType>
|
||||||
<xs:complexType name="single-logout-type">
|
<xs:complexType name="single-logout-type">
|
||||||
<xs:attribute name="validateRequestSignature" type="xs:boolean" use="optional">
|
<xs:attribute name="validateRequestSignature" type="xs:boolean" use="optional">
|
||||||
|
|||||||
+2
-1
@@ -44,7 +44,8 @@
|
|||||||
validateResponseSignature="true"
|
validateResponseSignature="true"
|
||||||
validateAssertionSignature="true"
|
validateAssertionSignature="true"
|
||||||
requestBinding="POST"
|
requestBinding="POST"
|
||||||
bindingUrl="http://localhost:8080/auth/realms/saml-demo/protocol/saml"/>
|
bindingUrl="http://localhost:8080/auth/realms/saml-demo/protocol/saml"
|
||||||
|
assertionConsumerServiceUrl="acsUrl"/>
|
||||||
<SingleLogoutService
|
<SingleLogoutService
|
||||||
validateRequestSignature="true"
|
validateRequestSignature="true"
|
||||||
validateResponseSignature="true"
|
validateResponseSignature="true"
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>3.3.0.CR1-SNAPSHOT</version>
|
<version>3.4.1.Final</version>
|
||||||
<relativePath>../../../pom.xml</relativePath>
|
<relativePath>../../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>3.3.0.CR1-SNAPSHOT</version>
|
<version>3.4.1.Final</version>
|
||||||
<relativePath>../../../pom.xml</relativePath>
|
<relativePath>../../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|||||||
Loaded 100 of 2623 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user