Compare commits
424
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ea46bb0be3 | ||
|
|
7b988d267b | ||
|
|
99372d2534 | ||
|
|
508bddc70a | ||
|
|
56d95b5414 | ||
|
|
71b9420286 | ||
|
|
024d64e0e0 | ||
|
|
e719f1af96 | ||
|
|
225aab1fed | ||
|
|
fde9e6870f | ||
|
|
90a9465caf | ||
|
|
37a61d79a6 | ||
|
|
cb2fce74a6 | ||
|
|
aaad122cff | ||
|
|
269a2e9ba9 | ||
|
|
d5b86bedd6 | ||
|
|
790f0fe7f9 | ||
|
|
8417144677 | ||
|
|
277f90e8b0 | ||
|
|
9306dc2015 | ||
|
|
e979b96923 | ||
|
|
5a362df491 | ||
|
|
1b611fef01 | ||
|
|
2f7d415cba | ||
|
|
5e992f6db9 | ||
|
|
844da0193a | ||
|
|
d42b44ee13 | ||
|
|
c3616ecb4d | ||
|
|
3a7787b1d7 | ||
|
|
47103a040f | ||
|
|
568140de4a | ||
|
|
6d2ade5f77 | ||
|
|
40427a2200 | ||
|
|
bb34cfb7d6 | ||
|
|
3fd840515b | ||
|
|
604a757665 | ||
|
|
107a3f4f11 | ||
|
|
f6fe53a44c | ||
|
|
7281c2d8ae | ||
|
|
bb8bc7f976 | ||
|
|
b4ae814567 | ||
|
|
b482396af9 | ||
|
|
9d9bf3c39b | ||
|
|
01fece902c | ||
|
|
663a145bd7 | ||
|
|
2417e49f9c | ||
|
|
b053ce70f9 | ||
|
|
a6f4588ef2 | ||
|
|
025df56796 | ||
|
|
f75f14141c | ||
|
|
f966d53f9e | ||
|
|
2c25fd3c08 | ||
|
|
e671d4429b | ||
|
|
95cf7bdeea | ||
|
|
7f96e0438e | ||
|
|
82006f812a | ||
|
|
951fb095fc | ||
|
|
06c1f0a7e9 | ||
|
|
4445989f85 | ||
|
|
c1156bb053 | ||
|
|
fc1a7908d6 | ||
|
|
70d427acea | ||
|
|
d299ae9af5 | ||
|
|
f79d7a65fd | ||
|
|
cff654b784 | ||
|
|
bdbd765e7e | ||
|
|
61bb2ee660 | ||
|
|
2472eef714 | ||
|
|
51c87609ae | ||
|
|
33c8ced3e9 | ||
|
|
94f1e43be7 | ||
|
|
13e09d2341 | ||
|
|
d3fc34752e | ||
|
|
f8ddecdf2f | ||
|
|
53a7025784 | ||
|
|
4f07522953 | ||
|
|
ad0c9adc03 | ||
|
|
16390ee4b6 | ||
|
|
ec8eee02fe | ||
|
|
db85f77b00 | ||
|
|
433fe5944c | ||
|
|
fb476e5022 | ||
|
|
29113b9398 | ||
|
|
fc0c8e898d | ||
|
|
fca9122052 | ||
|
|
f1e5cbf8fc | ||
|
|
2a6b25b840 | ||
|
|
1c9f4cfb5c | ||
|
|
4c7c2a4cd3 | ||
|
|
110c142a53 | ||
|
|
8c8f2019e9 | ||
|
|
e5557e0cde | ||
|
|
f4f7488d8a | ||
|
|
7ea27e7c28 | ||
|
|
b14b384777 | ||
|
|
7c284dc843 | ||
|
|
320e81f11b | ||
|
|
350f45ef76 | ||
|
|
20f7b444bb | ||
|
|
3da4b3a6d3 | ||
|
|
37a9f88983 | ||
|
|
d4c82dbd72 | ||
|
|
85e2b5eea0 | ||
|
|
e6cf4afc29 | ||
|
|
26ba12962c | ||
|
|
e963344f87 | ||
|
|
daf8658568 | ||
|
|
38394a6949 | ||
|
|
af34927930 | ||
|
|
fe4fbfca30 | ||
|
|
28de85f8f9 | ||
|
|
91817ea333 | ||
|
|
c285fc1cf7 | ||
|
|
45173f4063 | ||
|
|
c4271b30e9 | ||
|
|
c7205fa43d | ||
|
|
5ac65413f2 | ||
|
|
848c234e06 | ||
|
|
1b987ff2a5 | ||
|
|
8c0c80f6af | ||
|
|
8d3d80e603 | ||
|
|
3df22af3f0 | ||
|
|
199198ecb5 | ||
|
|
6180132486 | ||
|
|
7731e74c38 | ||
|
|
15f75a36b5 | ||
|
|
37eddc23fd | ||
|
|
7099dc3e51 | ||
|
|
cf1c7a319a | ||
|
|
eb68ef47b1 | ||
|
|
7f7fb23f32 | ||
|
|
846bc2ca35 | ||
|
|
ed77589a43 | ||
|
|
6ab94ce4e8 | ||
|
|
a5179907ad | ||
|
|
77bbf2afb5 | ||
|
|
85b95c5432 | ||
|
|
613a26cd1c | ||
|
|
18cc0fdaf3 | ||
|
|
39c0dfeb8f | ||
|
|
524ae68224 | ||
|
|
e63726d51c | ||
|
|
29c839602f | ||
|
|
1e20cad2ae | ||
|
|
7feeca8273 | ||
|
|
9c8d9ceb28 | ||
|
|
07a7035398 | ||
|
|
6c2f8a8f65 | ||
|
|
d1bf3c3be6 | ||
|
|
edef864ffc | ||
|
|
3effc265c4 | ||
|
|
41775bf8ef | ||
|
|
6c2464e399 | ||
|
|
17a7d04de9 | ||
|
|
b630c5b447 | ||
|
|
ab69b98766 | ||
|
|
41ac0f3b04 | ||
|
|
d78450137e | ||
|
|
1e47e28f20 | ||
|
|
80a8961878 | ||
|
|
95d555ef39 | ||
|
|
1a8f56f3d1 | ||
|
|
4e1059740a | ||
|
|
7e225d60fd | ||
|
|
b55449b739 | ||
|
|
5b298cf43c | ||
|
|
b56fe48277 | ||
|
|
4c438de595 | ||
|
|
ea006f1d77 | ||
|
|
cb4e0a9e75 | ||
|
|
7df32ba4cd | ||
|
|
89098b3726 | ||
|
|
9e45c2ac4d | ||
|
|
d4f8f833a2 | ||
|
|
e159254cd2 | ||
|
|
ee090149b9 | ||
|
|
a22c8c1d8e | ||
|
|
83ff45ce04 | ||
|
|
815e650448 | ||
|
|
777bdc908f | ||
|
|
45231b69a7 | ||
|
|
b01f522ace | ||
|
|
e840766b1f | ||
|
|
4298916013 | ||
|
|
788bdfb29b | ||
|
|
3ec8672a75 | ||
|
|
fc95067193 | ||
|
|
d14867f785 | ||
|
|
ffe483ae2d | ||
|
|
dc2d71489d | ||
|
|
42402ee6f4 | ||
|
|
f4f95cd096 | ||
|
|
dafea0cad6 | ||
|
|
b5fe63af22 | ||
|
|
a48ace4d70 | ||
|
|
5440688dd9 | ||
|
|
b21b548b9c | ||
|
|
fe44483e60 | ||
|
|
12be32f6dc | ||
|
|
524080b0ae | ||
|
|
d8dfc1ca0b | ||
|
|
bee7c077b7 | ||
|
|
a3abc0296d | ||
|
|
2d3580e2d4 | ||
|
|
3c5fcebce9 | ||
|
|
00bb2de032 | ||
|
|
013af68d74 | ||
|
|
8209c74918 | ||
|
|
4ed2c4e5a8 | ||
|
|
34e125ea80 | ||
|
|
135071b3aa | ||
|
|
38952e5b3d | ||
|
|
3eefe2438b | ||
|
|
faaf20de95 | ||
|
|
7d5cedc6eb | ||
|
|
51efc3c184 | ||
|
|
cddba23dcf | ||
|
|
5c693246ba | ||
|
|
ae0aa61b3c | ||
|
|
1cf10f1f11 | ||
|
|
b576703533 | ||
|
|
850de683db | ||
|
|
59fd461563 | ||
|
|
ddd93df503 | ||
|
|
74f98f9eb2 | ||
|
|
b32d50df2d | ||
|
|
61d1c498ef | ||
|
|
7bbc618e1b | ||
|
|
865371b58f | ||
|
|
16b1f88546 | ||
|
|
0f43e2b6f2 | ||
|
|
949ecf60d9 | ||
|
|
0024162121 | ||
|
|
958471b081 | ||
|
|
de80133ea2 | ||
|
|
13104750f6 | ||
|
|
2f575af3d2 | ||
|
|
56f99ed640 | ||
|
|
a42e7f226f | ||
|
|
d6e513f6c3 | ||
|
|
1500fff93e | ||
|
|
c37437e82b | ||
|
|
7d0bb05aaa | ||
|
|
35297a149d | ||
|
|
e68b71ba01 | ||
|
|
900be13423 | ||
|
|
02b8cc7ad3 | ||
|
|
0371c53d07 | ||
|
|
364a54f792 | ||
|
|
0016bd8744 | ||
|
|
36baf38d09 | ||
|
|
437244f61e | ||
|
|
70c85af7e2 | ||
|
|
d97dbdac36 | ||
|
|
89013c8f6e | ||
|
|
ff80f613d3 | ||
|
|
15cbddba13 | ||
|
|
7c11bd2214 | ||
|
|
7280eb3cd9 | ||
|
|
4d38c1f95d | ||
|
|
8d196500d8 | ||
|
|
a0e21c8bf6 | ||
|
|
6b85ff0d77 | ||
|
|
89b622e6a0 | ||
|
|
53e2e352fd | ||
|
|
fda48fc537 | ||
|
|
3d8721246a | ||
|
|
0b3847eb5d | ||
|
|
96606fe3da | ||
|
|
b061288d1c | ||
|
|
89080af339 | ||
|
|
7bfe51c925 | ||
|
|
07b43f11e2 | ||
|
|
8b4fe15aeb | ||
|
|
95486ef962 | ||
|
|
5a799d4c33 | ||
|
|
5da2fad0a2 | ||
|
|
6c84520021 | ||
|
|
2955c814b3 | ||
|
|
aad3b77996 | ||
|
|
109191f248 | ||
|
|
749130b689 | ||
|
|
a8732aa83c | ||
|
|
6b9aa49f79 | ||
|
|
50b701ccf0 | ||
|
|
7a67217c87 | ||
|
|
4f861dcbec | ||
|
|
4be5d27ada | ||
|
|
71b0ffa3ca | ||
|
|
7ff35067aa | ||
|
|
05ee844bf6 | ||
|
|
d05a139a5f | ||
|
|
b8da04814b | ||
|
|
5482a80fe3 | ||
|
|
2fd2812c94 | ||
|
|
bd0cd93c90 | ||
|
|
90efb232a4 | ||
|
|
431bf08c83 | ||
|
|
d6a70fb31e | ||
|
|
a049cfefe8 | ||
|
|
88725f68dd | ||
|
|
e07aefdcfd | ||
|
|
878b724ce1 | ||
|
|
d0bcb6b6aa | ||
|
|
e6489b3bc1 | ||
|
|
aebc473071 | ||
|
|
fdf43f058a | ||
|
|
6886510e32 | ||
|
|
dafa2e3401 | ||
|
|
e67d37e9d8 | ||
|
|
9422542635 | ||
|
|
f5bed87eec | ||
|
|
7d2f0fd5cf | ||
|
|
cfd8770499 | ||
|
|
a540e9a0da | ||
|
|
028059a668 | ||
|
|
1031d6b6f5 | ||
|
|
c6a0243c92 | ||
|
|
9736f56d3b | ||
|
|
662d50eeea | ||
|
|
bfbbd5375f | ||
|
|
b735106750 | ||
|
|
1857c0c0b4 | ||
|
|
157bb84bce | ||
|
|
52617e6ef1 | ||
|
|
239816f4f5 | ||
|
|
e4ee88a492 | ||
|
|
353958538c | ||
|
|
47a91ccf33 | ||
|
|
85baeeb34e | ||
|
|
ef1c8199a5 | ||
|
|
89da594735 | ||
|
|
811085f9bd | ||
|
|
b8904bc018 | ||
|
|
937d234964 | ||
|
|
b5bc4f15f8 | ||
|
|
16863f2ed1 | ||
|
|
805afbb592 | ||
|
|
977b61f91c | ||
|
|
91815c65a3 | ||
|
|
13cb6f481f | ||
|
|
dc254ff0f7 | ||
|
|
a633241d2f | ||
|
|
97b38f4ccd | ||
|
|
416e4948d7 | ||
|
|
60dff589d4 | ||
|
|
61656c6eba | ||
|
|
2affc4d847 | ||
|
|
09179159e7 | ||
|
|
b43dc8348d | ||
|
|
f3357c2b5b | ||
|
|
79c308166a | ||
|
|
2ea985fd30 | ||
|
|
385cfd5161 | ||
|
|
db3cd543df | ||
|
|
e139fadb02 | ||
|
|
10809b47ad | ||
|
|
dd449ffed0 | ||
|
|
1f5124fc8a | ||
|
|
741a251d89 | ||
|
|
1012611785 | ||
|
|
465f828d73 | ||
|
|
038294d5c1 | ||
|
|
d1b33e1638 | ||
|
|
d863a4b143 | ||
|
|
4a073b6e46 | ||
|
|
30b0c35442 | ||
|
|
ef5bb6d447 | ||
|
|
6aa0c7ca39 | ||
|
|
70b3091097 | ||
|
|
210a79a575 | ||
|
|
a4fb4fd530 | ||
|
|
6f56320177 | ||
|
|
4d13b5105e | ||
|
|
97a398790f | ||
|
|
c09da5cac8 | ||
|
|
9521e71840 | ||
|
|
e5d09e1b04 | ||
|
|
ebe6d5c5c1 | ||
|
|
0320884c72 | ||
|
|
a254d2120d | ||
|
|
4157907358 | ||
|
|
dfc8708808 | ||
|
|
67c40eb212 | ||
|
|
bafaef7060 | ||
|
|
ee06eda05c | ||
|
|
a3525dd073 | ||
|
|
f97f0e4e1b | ||
|
|
c62e93577b | ||
|
|
bcebd3fb83 | ||
|
|
0589c82242 | ||
|
|
4ddf4d1c99 | ||
|
|
a98148f19b | ||
|
|
d1072e8942 | ||
|
|
5b0254f0c7 | ||
|
|
c2b406e7d6 | ||
|
|
4821290c32 | ||
|
|
d3bb68c2b0 | ||
|
|
9560364a1c | ||
|
|
4b49bc7140 | ||
|
|
88bac57cad | ||
|
|
9630921d91 | ||
|
|
84e216c2ac | ||
|
|
0bc72e908f | ||
|
|
6910572bd2 | ||
|
|
a4dd8a38b3 | ||
|
|
f0b4127567 | ||
|
|
c4f3a4e68e | ||
|
|
c0aa4289e2 | ||
|
|
9be600cffe | ||
|
|
c998f6eb53 | ||
|
|
c901b38858 | ||
|
|
4bd09cf14b | ||
|
|
3edadb01c5 | ||
|
|
b738764442 | ||
|
|
660fd94e7f | ||
|
|
a3138b8514 | ||
|
|
627e434b73 | ||
|
|
406754f31b | ||
|
|
b371521b33 | ||
|
|
f151933d91 | ||
|
|
5ea93822e7 | ||
|
|
cafd2d80d2 | ||
|
|
c9dcd7973a |
No files matched your search
+1
-1
@@ -12,7 +12,7 @@ before_script:
|
||||
- export MAVEN_SKIP_RC=true
|
||||
|
||||
install:
|
||||
- ( mvn install -Pdistribution -DskipTests=true -B -V -q ) & ( MYPID=$!; while [ $(ps -ef | grep $MYPID | grep -v grep | wc -l) -gt 0 ]; do sleep 10; date; done; )
|
||||
- mvn install -Pdistribution -DskipTests=true -B -V -q
|
||||
|
||||
script:
|
||||
- mvn test -B
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>2.1.0.CR1</version>
|
||||
<version>1.9.3.Final</version>
|
||||
<relativePath>../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
@@ -65,11 +65,6 @@
|
||||
<artifactId>keycloak-core</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-authz-client</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-core</artifactId>
|
||||
|
||||
-10
@@ -456,16 +456,6 @@ public class AdapterDeploymentContext {
|
||||
public void setTurnOffChangeSessionIdOnLogin(boolean turnOffChangeSessionIdOnLogin) {
|
||||
delegate.setTurnOffChangeSessionIdOnLogin(turnOffChangeSessionIdOnLogin);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTokenMinimumTimeToLive() {
|
||||
return delegate.getTokenMinimumTimeToLive();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTokenMinimumTimeToLive(final int tokenMinimumTimeToLive) {
|
||||
delegate.setTokenMinimumTimeToLive(tokenMinimumTimeToLive);
|
||||
}
|
||||
}
|
||||
|
||||
protected KeycloakUriBuilder getBaseBuilder(HttpFacade facade, String base) {
|
||||
|
||||
+1
-26
@@ -18,12 +18,10 @@
|
||||
package org.keycloak.adapters;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
import org.keycloak.AuthorizationContext;
|
||||
import org.keycloak.KeycloakSecurityContext;
|
||||
import org.keycloak.adapters.authorization.PolicyEnforcer;
|
||||
import org.keycloak.common.util.UriUtils;
|
||||
import org.keycloak.constants.AdapterConstants;
|
||||
import org.keycloak.representations.AccessToken;
|
||||
import org.keycloak.common.util.UriUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Set;
|
||||
@@ -57,9 +55,6 @@ public class AuthenticatedActionsHandler {
|
||||
queryBearerToken();
|
||||
return true;
|
||||
}
|
||||
if (!isAuthorized()) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -129,24 +124,4 @@ public class AuthenticatedActionsHandler {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean isAuthorized() {
|
||||
PolicyEnforcer policyEnforcer = this.deployment.getPolicyEnforcer();
|
||||
|
||||
if (policyEnforcer == null) {
|
||||
log.debugv("Policy enforcement is disabled.");
|
||||
return true;
|
||||
}
|
||||
try {
|
||||
OIDCHttpFacade facade = (OIDCHttpFacade) this.facade;
|
||||
AuthorizationContext authorizationContext = policyEnforcer.enforce(facade);
|
||||
RefreshableKeycloakSecurityContext session = (RefreshableKeycloakSecurityContext) facade.getSecurityContext();
|
||||
|
||||
session.setAuthorizationContext(authorizationContext);
|
||||
|
||||
return authorizationContext.isGranted();
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Failed to enforce policy decisions.", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
-2
@@ -24,7 +24,6 @@ import org.apache.http.client.HttpClient;
|
||||
import org.apache.http.client.entity.UrlEncodedFormEntity;
|
||||
import org.apache.http.client.methods.HttpPost;
|
||||
import org.apache.http.message.BasicNameValuePair;
|
||||
import org.apache.http.util.EntityUtils;
|
||||
import org.jboss.logging.Logger;
|
||||
import org.keycloak.OAuth2Constants;
|
||||
import org.keycloak.adapters.authentication.ClientCredentialsProviderUtils;
|
||||
@@ -105,7 +104,6 @@ public class BasicAuthRequestAuthenticator extends BearerTokenRequestAuthenticat
|
||||
int status = response.getStatusLine().getStatusCode();
|
||||
HttpEntity entity = response.getEntity();
|
||||
if (status != 200) {
|
||||
EntityUtils.consumeQuietly(entity);
|
||||
throw new java.io.IOException("Bad status: " + status);
|
||||
}
|
||||
if (entity == null) {
|
||||
|
||||
+10
-38
@@ -17,11 +17,9 @@
|
||||
|
||||
package org.keycloak.adapters;
|
||||
|
||||
import org.apache.http.HttpHost;
|
||||
import org.apache.http.client.CookieStore;
|
||||
import org.apache.http.client.HttpClient;
|
||||
import org.apache.http.conn.ClientConnectionManager;
|
||||
import org.apache.http.conn.params.ConnRoutePNames;
|
||||
import org.apache.http.conn.scheme.PlainSocketFactory;
|
||||
import org.apache.http.conn.scheme.Scheme;
|
||||
import org.apache.http.conn.scheme.SchemeRegistry;
|
||||
@@ -36,9 +34,9 @@ import org.apache.http.impl.conn.SingleClientConnManager;
|
||||
import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
|
||||
import org.apache.http.params.BasicHttpParams;
|
||||
import org.apache.http.params.HttpConnectionParams;
|
||||
import org.keycloak.representations.adapters.config.AdapterConfig;
|
||||
import org.keycloak.common.util.EnvUtil;
|
||||
import org.keycloak.common.util.KeystoreUtil;
|
||||
import org.keycloak.representations.adapters.config.AdapterConfig;
|
||||
|
||||
import javax.net.ssl.HostnameVerifier;
|
||||
import javax.net.ssl.SSLContext;
|
||||
@@ -48,7 +46,6 @@ import javax.net.ssl.SSLSocket;
|
||||
import javax.net.ssl.TrustManager;
|
||||
import javax.net.ssl.X509TrustManager;
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.security.KeyStore;
|
||||
import java.security.SecureRandom;
|
||||
import java.security.cert.CertificateException;
|
||||
@@ -115,7 +112,6 @@ public class HttpClientBuilder {
|
||||
protected TimeUnit socketTimeoutUnits = TimeUnit.MILLISECONDS;
|
||||
protected long establishConnectionTimeout = -1;
|
||||
protected TimeUnit establishConnectionTimeoutUnits = TimeUnit.MILLISECONDS;
|
||||
protected HttpHost proxyHost;
|
||||
|
||||
|
||||
/**
|
||||
@@ -125,7 +121,8 @@ public class HttpClientBuilder {
|
||||
* @param unit
|
||||
* @return
|
||||
*/
|
||||
public HttpClientBuilder socketTimeout(long timeout, TimeUnit unit) {
|
||||
public HttpClientBuilder socketTimeout(long timeout, TimeUnit unit)
|
||||
{
|
||||
this.socketTimeout = timeout;
|
||||
this.socketTimeoutUnits = unit;
|
||||
return this;
|
||||
@@ -138,7 +135,8 @@ public class HttpClientBuilder {
|
||||
* @param unit
|
||||
* @return
|
||||
*/
|
||||
public HttpClientBuilder establishConnectionTimeout(long timeout, TimeUnit unit) {
|
||||
public HttpClientBuilder establishConnectionTimeout(long timeout, TimeUnit unit)
|
||||
{
|
||||
this.establishConnectionTimeout = timeout;
|
||||
this.establishConnectionTimeoutUnits = unit;
|
||||
return this;
|
||||
@@ -289,20 +287,16 @@ public class HttpClientBuilder {
|
||||
cm = new SingleClientConnManager(registry);
|
||||
}
|
||||
BasicHttpParams params = new BasicHttpParams();
|
||||
|
||||
if (proxyHost != null) {
|
||||
params.setParameter(ConnRoutePNames.DEFAULT_PROXY, proxyHost);
|
||||
}
|
||||
|
||||
if (socketTimeout > -1) {
|
||||
if (socketTimeout > -1)
|
||||
{
|
||||
HttpConnectionParams.setSoTimeout(params, (int) socketTimeoutUnits.toMillis(socketTimeout));
|
||||
|
||||
}
|
||||
if (establishConnectionTimeout > -1) {
|
||||
HttpConnectionParams.setConnectionTimeout(params, (int) establishConnectionTimeoutUnits.toMillis(establishConnectionTimeout));
|
||||
if (establishConnectionTimeout > -1)
|
||||
{
|
||||
HttpConnectionParams.setConnectionTimeout(params, (int)establishConnectionTimeoutUnits.toMillis(establishConnectionTimeout));
|
||||
}
|
||||
DefaultHttpClient client = new DefaultHttpClient(cm, params);
|
||||
|
||||
if (disableCookieCache) {
|
||||
client.setCookieStore(new CookieStore() {
|
||||
@Override
|
||||
@@ -370,28 +364,6 @@ public class HttpClientBuilder {
|
||||
} else {
|
||||
trustStore(truststore);
|
||||
}
|
||||
|
||||
configureProxyForAuthServerIfProvided(adapterConfig);
|
||||
|
||||
return build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures a the proxy to use for auth-server requests if provided.
|
||||
* <p>
|
||||
* If the given {@link AdapterConfig} contains the attribute {@code proxy-url} we use the
|
||||
* given URL as a proxy server, otherwise the proxy configuration is ignored.
|
||||
* </p>
|
||||
*
|
||||
* @param adapterConfig
|
||||
*/
|
||||
private void configureProxyForAuthServerIfProvided(AdapterConfig adapterConfig) {
|
||||
|
||||
if (adapterConfig == null || adapterConfig.getProxyUrl() == null || adapterConfig.getProxyUrl().trim().isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
URI uri = URI.create(adapterConfig.getProxyUrl());
|
||||
this.proxyHost = new HttpHost(uri.getHost(), uri.getPort(), uri.getScheme());
|
||||
}
|
||||
}
|
||||
-19
@@ -20,7 +20,6 @@ package org.keycloak.adapters;
|
||||
import org.apache.http.client.HttpClient;
|
||||
import org.jboss.logging.Logger;
|
||||
import org.keycloak.adapters.authentication.ClientCredentialsProvider;
|
||||
import org.keycloak.adapters.authorization.PolicyEnforcer;
|
||||
import org.keycloak.constants.ServiceUrlConstants;
|
||||
import org.keycloak.common.enums.RelativeUrlsUsed;
|
||||
import org.keycloak.common.enums.SslRequired;
|
||||
@@ -78,8 +77,6 @@ public class KeycloakDeployment {
|
||||
protected boolean turnOffChangeSessionIdOnLogin;
|
||||
|
||||
protected volatile int notBefore;
|
||||
protected int tokenMinimumTimeToLive;
|
||||
private PolicyEnforcer policyEnforcer;
|
||||
|
||||
public KeycloakDeployment() {
|
||||
}
|
||||
@@ -360,20 +357,4 @@ public class KeycloakDeployment {
|
||||
public void setTurnOffChangeSessionIdOnLogin(boolean turnOffChangeSessionIdOnLogin) {
|
||||
this.turnOffChangeSessionIdOnLogin = turnOffChangeSessionIdOnLogin;
|
||||
}
|
||||
|
||||
public int getTokenMinimumTimeToLive() {
|
||||
return tokenMinimumTimeToLive;
|
||||
}
|
||||
|
||||
public void setTokenMinimumTimeToLive(final int tokenMinimumTimeToLive) {
|
||||
this.tokenMinimumTimeToLive = tokenMinimumTimeToLive;
|
||||
}
|
||||
|
||||
public void setPolicyEnforcer(PolicyEnforcer policyEnforcer) {
|
||||
this.policyEnforcer = policyEnforcer;
|
||||
}
|
||||
|
||||
public PolicyEnforcer getPolicyEnforcer() {
|
||||
return policyEnforcer;
|
||||
}
|
||||
}
|
||||
+1
-10
@@ -21,12 +21,10 @@ import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.jboss.logging.Logger;
|
||||
import org.keycloak.adapters.authentication.ClientCredentialsProviderUtils;
|
||||
import org.keycloak.adapters.authorization.PolicyEnforcer;
|
||||
import org.keycloak.common.enums.SslRequired;
|
||||
import org.keycloak.common.util.PemUtils;
|
||||
import org.keycloak.enums.TokenStore;
|
||||
import org.keycloak.representations.adapters.config.AdapterConfig;
|
||||
import org.keycloak.representations.adapters.config.PolicyEnforcerConfig;
|
||||
import org.keycloak.common.util.PemUtils;
|
||||
import org.keycloak.util.SystemPropertiesJsonParserFactory;
|
||||
|
||||
import java.io.IOException;
|
||||
@@ -96,7 +94,6 @@ public class KeycloakDeploymentBuilder {
|
||||
deployment.setAlwaysRefreshToken(adapterConfig.isAlwaysRefreshToken());
|
||||
deployment.setRegisterNodeAtStartup(adapterConfig.isRegisterNodeAtStartup());
|
||||
deployment.setRegisterNodePeriod(adapterConfig.getRegisterNodePeriod());
|
||||
deployment.setTokenMinimumTimeToLive(adapterConfig.getTokenMinimumTimeToLive());
|
||||
|
||||
if (realmKeyPem == null && adapterConfig.isBearerOnly() && adapterConfig.getAuthServerUrl() == null) {
|
||||
throw new IllegalArgumentException("For bearer auth, you must set the realm-public-key or auth-server-url");
|
||||
@@ -112,12 +109,6 @@ public class KeycloakDeploymentBuilder {
|
||||
deployment.setTurnOffChangeSessionIdOnLogin(adapterConfig.getTurnOffChangeSessionIdOnLogin());
|
||||
}
|
||||
|
||||
PolicyEnforcerConfig policyEnforcerConfig = adapterConfig.getPolicyEnforcerConfig();
|
||||
|
||||
if (policyEnforcerConfig != null) {
|
||||
deployment.setPolicyEnforcer(new PolicyEnforcer(deployment, adapterConfig));
|
||||
}
|
||||
|
||||
log.debug("Use authServerUrl: " + deployment.getAuthServerBaseUrl() + ", tokenUrl: " + deployment.getTokenUrl() + ", relativeUrls: " + deployment.getRelativeUrls());
|
||||
return deployment;
|
||||
}
|
||||
|
||||
+2
-15
@@ -34,7 +34,6 @@ import org.keycloak.representations.AccessTokenResponse;
|
||||
import org.keycloak.representations.IDToken;
|
||||
import org.keycloak.common.util.KeycloakUriBuilder;
|
||||
import org.keycloak.common.util.UriUtils;
|
||||
import org.keycloak.util.TokenUtil;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
@@ -160,12 +159,6 @@ public class OAuthRequestAuthenticator {
|
||||
String scope = getQueryParamValue(OAuth2Constants.SCOPE);
|
||||
url = UriUtils.stripQueryParam(url, OAuth2Constants.SCOPE);
|
||||
|
||||
String prompt = getQueryParamValue(OAuth2Constants.PROMPT);
|
||||
url = UriUtils.stripQueryParam(url, OAuth2Constants.PROMPT);
|
||||
|
||||
String maxAge = getQueryParamValue(OAuth2Constants.MAX_AGE);
|
||||
url = UriUtils.stripQueryParam(url, OAuth2Constants.MAX_AGE);
|
||||
|
||||
KeycloakUriBuilder redirectUriBuilder = deployment.getAuthUrl().clone()
|
||||
.queryParam(OAuth2Constants.RESPONSE_TYPE, OAuth2Constants.CODE)
|
||||
.queryParam(OAuth2Constants.CLIENT_ID, deployment.getResourceName())
|
||||
@@ -178,15 +171,9 @@ public class OAuthRequestAuthenticator {
|
||||
if (idpHint != null && idpHint.length() > 0) {
|
||||
redirectUriBuilder.queryParam(AdapterConstants.KC_IDP_HINT,idpHint);
|
||||
}
|
||||
if (prompt != null && prompt.length() > 0) {
|
||||
redirectUriBuilder.queryParam(OAuth2Constants.PROMPT, prompt);
|
||||
if (scope != null && scope.length() > 0) {
|
||||
redirectUriBuilder.queryParam(OAuth2Constants.SCOPE, scope);
|
||||
}
|
||||
if (maxAge != null && maxAge.length() > 0) {
|
||||
redirectUriBuilder.queryParam(OAuth2Constants.MAX_AGE, maxAge);
|
||||
}
|
||||
|
||||
scope = TokenUtil.attachOIDCScope(scope);
|
||||
redirectUriBuilder.queryParam(OAuth2Constants.SCOPE, scope);
|
||||
|
||||
return redirectUriBuilder.build().toString();
|
||||
}
|
||||
|
||||
+1
-2
@@ -35,8 +35,7 @@ public class OIDCAuthenticationError implements AuthenticationError {
|
||||
CODE_TO_TOKEN_FAILURE,
|
||||
INVALID_TOKEN,
|
||||
STALE_TOKEN,
|
||||
NO_AUTHORIZATION_HEADER,
|
||||
NO_QUERY_PARAMETER_ACCESS_TOKEN
|
||||
NO_AUTHORIZATION_HEADER
|
||||
}
|
||||
|
||||
private Reason reason;
|
||||
|
||||
-54
@@ -1,54 +0,0 @@
|
||||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.keycloak.adapters;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
import org.keycloak.adapters.spi.AuthOutcome;
|
||||
import org.keycloak.adapters.spi.HttpFacade;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:froehlich.ch@gmail.com">Christian Froehlich</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class QueryParamterTokenRequestAuthenticator extends BearerTokenRequestAuthenticator {
|
||||
public static final String ACCESS_TOKEN = "access_token";
|
||||
protected Logger log = Logger.getLogger(QueryParamterTokenRequestAuthenticator.class);
|
||||
|
||||
public QueryParamterTokenRequestAuthenticator(KeycloakDeployment deployment) {
|
||||
super(deployment);
|
||||
}
|
||||
|
||||
public AuthOutcome authenticate(HttpFacade exchange) {
|
||||
tokenString = null;
|
||||
tokenString = getAccessTokenFromQueryParamter(exchange);
|
||||
if (tokenString == null || tokenString.trim().isEmpty()) {
|
||||
challenge = challengeResponse(exchange, OIDCAuthenticationError.Reason.NO_QUERY_PARAMETER_ACCESS_TOKEN, null, null);
|
||||
return AuthOutcome.NOT_ATTEMPTED;
|
||||
}
|
||||
return (authenticateToken(exchange, tokenString));
|
||||
}
|
||||
|
||||
String getAccessTokenFromQueryParamter(HttpFacade exchange) {
|
||||
try {
|
||||
if (exchange != null && exchange.getRequest() != null) {
|
||||
return exchange.getRequest().getQueryParamValue(ACCESS_TOKEN);
|
||||
}
|
||||
} catch (Exception ignore) {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+2
-19
@@ -18,11 +18,9 @@
|
||||
package org.keycloak.adapters;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
import org.keycloak.AuthorizationContext;
|
||||
import org.keycloak.KeycloakSecurityContext;
|
||||
import org.keycloak.RSATokenVerifier;
|
||||
import org.keycloak.common.VerificationException;
|
||||
import org.keycloak.common.util.Time;
|
||||
import org.keycloak.representations.AccessToken;
|
||||
import org.keycloak.representations.AccessTokenResponse;
|
||||
import org.keycloak.representations.IDToken;
|
||||
@@ -76,11 +74,7 @@ public class RefreshableKeycloakSecurityContext extends KeycloakSecurityContext
|
||||
}
|
||||
|
||||
public boolean isActive() {
|
||||
return token != null && this.token.isActive() && deployment!=null && this.token.getIssuedAt() > deployment.getNotBefore();
|
||||
}
|
||||
|
||||
public boolean isTokenTimeToLiveSufficient(AccessToken token) {
|
||||
return token != null && (token.getExpiration() - this.deployment.getTokenMinimumTimeToLive()) > Time.currentTime();
|
||||
return token != null && this.token.isActive() && this.token.getIssuedAt() > deployment.getNotBefore();
|
||||
}
|
||||
|
||||
public KeycloakDeployment getDeployment() {
|
||||
@@ -101,7 +95,7 @@ public class RefreshableKeycloakSecurityContext extends KeycloakSecurityContext
|
||||
if (log.isTraceEnabled()) {
|
||||
log.trace("checking whether to refresh.");
|
||||
}
|
||||
if (isActive() && isTokenTimeToLiveSufficient(this.token)) return true;
|
||||
if (isActive()) return true;
|
||||
}
|
||||
|
||||
if (this.deployment == null || refreshToken == null) return false; // Might be serialized in HttpSession?
|
||||
@@ -136,13 +130,6 @@ public class RefreshableKeycloakSecurityContext extends KeycloakSecurityContext
|
||||
log.error("failed verification of token");
|
||||
return false;
|
||||
}
|
||||
|
||||
// If the TTL is greater-or-equal to the expire time on the refreshed token, have to abort or go into an infinite refresh loop
|
||||
if (!isTokenTimeToLiveSufficient(token)) {
|
||||
log.error("failed to refresh the token with a longer time-to-live than the minimum");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (response.getNotBeforePolicy() > deployment.getNotBefore()) {
|
||||
deployment.setNotBefore(response.getNotBeforePolicy());
|
||||
}
|
||||
@@ -158,8 +145,4 @@ public class RefreshableKeycloakSecurityContext extends KeycloakSecurityContext
|
||||
tokenStore.refreshCallback(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
public void setAuthorizationContext(AuthorizationContext authorizationContext) {
|
||||
this.authorizationContext = authorizationContext;
|
||||
}
|
||||
}
|
||||
+2
-26
@@ -61,7 +61,7 @@ public abstract class RequestAuthenticator {
|
||||
if (log.isTraceEnabled()) {
|
||||
log.trace("try bearer");
|
||||
}
|
||||
|
||||
|
||||
AuthOutcome outcome = bearer.authenticate(facade);
|
||||
if (outcome == AuthOutcome.FAILED) {
|
||||
challenge = bearer.getChallenge();
|
||||
@@ -74,36 +74,18 @@ public abstract class RequestAuthenticator {
|
||||
return AuthOutcome.AUTHENTICATED;
|
||||
}
|
||||
|
||||
QueryParamterTokenRequestAuthenticator queryParamAuth = createQueryParamterTokenRequestAuthenticator();
|
||||
if (log.isTraceEnabled()) {
|
||||
log.trace("try query paramter auth");
|
||||
}
|
||||
|
||||
outcome = queryParamAuth.authenticate(facade);
|
||||
if (outcome == AuthOutcome.FAILED) {
|
||||
challenge = queryParamAuth.getChallenge();
|
||||
log.debug("QueryParamAuth auth FAILED");
|
||||
return AuthOutcome.FAILED;
|
||||
} else if (outcome == AuthOutcome.AUTHENTICATED) {
|
||||
if (verifySSL()) return AuthOutcome.FAILED;
|
||||
log.debug("QueryParamAuth AUTHENTICATED");
|
||||
completeAuthentication(queryParamAuth, "KEYCLOAK");
|
||||
return AuthOutcome.AUTHENTICATED;
|
||||
}
|
||||
|
||||
if (deployment.isEnableBasicAuth()) {
|
||||
BasicAuthRequestAuthenticator basicAuth = createBasicAuthAuthenticator();
|
||||
if (log.isTraceEnabled()) {
|
||||
log.trace("try basic auth");
|
||||
}
|
||||
|
||||
|
||||
outcome = basicAuth.authenticate(facade);
|
||||
if (outcome == AuthOutcome.FAILED) {
|
||||
challenge = basicAuth.getChallenge();
|
||||
log.debug("BasicAuth FAILED");
|
||||
return AuthOutcome.FAILED;
|
||||
} else if (outcome == AuthOutcome.AUTHENTICATED) {
|
||||
if (verifySSL()) return AuthOutcome.FAILED;
|
||||
log.debug("BasicAuth AUTHENTICATED");
|
||||
completeAuthentication(basicAuth, "BASIC");
|
||||
return AuthOutcome.AUTHENTICATED;
|
||||
@@ -168,10 +150,6 @@ public abstract class RequestAuthenticator {
|
||||
return new BasicAuthRequestAuthenticator(deployment);
|
||||
}
|
||||
|
||||
protected QueryParamterTokenRequestAuthenticator createQueryParamterTokenRequestAuthenticator() {
|
||||
return new QueryParamterTokenRequestAuthenticator(deployment);
|
||||
}
|
||||
|
||||
protected void completeAuthentication(OAuthRequestAuthenticator oauth) {
|
||||
RefreshableKeycloakSecurityContext session = new RefreshableKeycloakSecurityContext(deployment, tokenStore, oauth.getTokenString(), oauth.getToken(), oauth.getIdTokenString(), oauth.getIdToken(), oauth.getRefreshToken());
|
||||
final KeycloakPrincipal<RefreshableKeycloakSecurityContext> principal = new KeycloakPrincipal<RefreshableKeycloakSecurityContext>(AdapterUtils.getPrincipalName(deployment, oauth.getToken()), session);
|
||||
@@ -180,12 +158,10 @@ public abstract class RequestAuthenticator {
|
||||
}
|
||||
|
||||
protected abstract void completeOAuthAuthentication(KeycloakPrincipal<RefreshableKeycloakSecurityContext> principal);
|
||||
|
||||
protected abstract void completeBearerAuthentication(KeycloakPrincipal<RefreshableKeycloakSecurityContext> principal, String method);
|
||||
|
||||
/**
|
||||
* After code is received, we change the session id if possible to guard against https://www.owasp.org/index.php/Session_Fixation
|
||||
*
|
||||
* @param create
|
||||
* @return
|
||||
*/
|
||||
|
||||
-4
@@ -54,10 +54,6 @@ public class JWTClientCredentialsProvider implements ClientCredentialsProvider {
|
||||
this.tokenTimeout = tokenTimeout;
|
||||
}
|
||||
|
||||
protected int getTokenTimeout() {
|
||||
return tokenTimeout;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(KeycloakDeployment deployment, Object config) {
|
||||
if (config == null || !(config instanceof Map)) {
|
||||
|
||||
-265
@@ -1,265 +0,0 @@
|
||||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
package org.keycloak.adapters.authorization;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
import org.keycloak.AuthorizationContext;
|
||||
import org.keycloak.adapters.OIDCHttpFacade;
|
||||
import org.keycloak.adapters.spi.HttpFacade.Request;
|
||||
import org.keycloak.adapters.spi.HttpFacade.Response;
|
||||
import org.keycloak.authorization.client.AuthzClient;
|
||||
import org.keycloak.authorization.client.representation.ResourceRepresentation;
|
||||
import org.keycloak.authorization.client.resource.ProtectedResource;
|
||||
import org.keycloak.representations.AccessToken;
|
||||
import org.keycloak.representations.adapters.config.PolicyEnforcerConfig;
|
||||
import org.keycloak.representations.adapters.config.PolicyEnforcerConfig.EnforcementMode;
|
||||
import org.keycloak.representations.adapters.config.PolicyEnforcerConfig.PathConfig;
|
||||
import org.keycloak.representations.idm.authorization.Permission;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
*/
|
||||
public abstract class AbstractPolicyEnforcer {
|
||||
|
||||
private static Logger LOGGER = Logger.getLogger(AbstractPolicyEnforcer.class);
|
||||
private final PolicyEnforcerConfig enforcerConfig;
|
||||
private final PolicyEnforcer policyEnforcer;
|
||||
|
||||
private List<PathConfig> paths;
|
||||
private AuthzClient authzClient;
|
||||
private PathMatcher pathMatcher;
|
||||
|
||||
public AbstractPolicyEnforcer(PolicyEnforcer policyEnforcer) {
|
||||
this.policyEnforcer = policyEnforcer;
|
||||
this.enforcerConfig = policyEnforcer.getEnforcerConfig();
|
||||
this.authzClient = policyEnforcer.getClient();
|
||||
this.pathMatcher = new PathMatcher();
|
||||
this.paths = policyEnforcer.getPaths();
|
||||
}
|
||||
|
||||
public AuthorizationContext authorize(OIDCHttpFacade httpFacade) {
|
||||
EnforcementMode enforcementMode = this.enforcerConfig.getEnforcementMode();
|
||||
|
||||
if (EnforcementMode.DISABLED.equals(enforcementMode)) {
|
||||
return createEmptyAuthorizationContext(true);
|
||||
}
|
||||
|
||||
AccessToken accessToken = httpFacade.getSecurityContext().getToken();
|
||||
Request request = httpFacade.getRequest();
|
||||
Response response = httpFacade.getResponse();
|
||||
String pathInfo = URI.create(request.getURI()).getPath().substring(1);
|
||||
String path = pathInfo.substring(pathInfo.indexOf('/'), pathInfo.length());
|
||||
PathConfig pathConfig = this.pathMatcher.matches(path, this.paths);
|
||||
|
||||
LOGGER.debugf("Checking permissions for path [%s] with config [%s].", request.getURI(), pathConfig);
|
||||
|
||||
if (pathConfig == null) {
|
||||
if (EnforcementMode.PERMISSIVE.equals(enforcementMode)) {
|
||||
return createAuthorizationContext(accessToken);
|
||||
}
|
||||
|
||||
LOGGER.debugf("Could not find a configuration for path [%s]", path);
|
||||
response.sendError(403, "Could not find a configuration for path [" + path + "].");
|
||||
|
||||
return createEmptyAuthorizationContext(false);
|
||||
}
|
||||
|
||||
PathConfig actualPathConfig = resolvePathConfig(pathConfig, request);
|
||||
Set<String> requiredScopes = getRequiredScopes(actualPathConfig, request);
|
||||
|
||||
if (isAuthorized(actualPathConfig, requiredScopes, accessToken, httpFacade)) {
|
||||
try {
|
||||
return createAuthorizationContext(accessToken);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Error processing path [" + actualPathConfig.getPath() + "].", e);
|
||||
}
|
||||
}
|
||||
|
||||
if (!challenge(actualPathConfig, requiredScopes, httpFacade)) {
|
||||
LOGGER.debugf("Sending challenge to the client. Path [%s]", pathConfig);
|
||||
response.sendError(403, "Authorization failed.");
|
||||
}
|
||||
|
||||
return createEmptyAuthorizationContext(false);
|
||||
}
|
||||
|
||||
protected abstract boolean challenge(PathConfig pathConfig, Set<String> requiredScopes, OIDCHttpFacade facade);
|
||||
|
||||
protected boolean isAuthorized(PathConfig actualPathConfig, Set<String> requiredScopes, AccessToken accessToken, OIDCHttpFacade httpFacade) {
|
||||
Request request = httpFacade.getRequest();
|
||||
PolicyEnforcerConfig enforcerConfig = getEnforcerConfig();
|
||||
String accessDeniedPath = enforcerConfig.getAccessDeniedPath();
|
||||
|
||||
if (accessDeniedPath != null) {
|
||||
if (request.getURI().contains(accessDeniedPath)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
AccessToken.Authorization authorization = accessToken.getAuthorization();
|
||||
|
||||
if (authorization == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
List<Permission> permissions = authorization.getPermissions();
|
||||
|
||||
for (Permission permission : permissions) {
|
||||
if (permission.getResourceSetId() != null) {
|
||||
if (isResourcePermission(actualPathConfig, permission)) {
|
||||
if (actualPathConfig.isInstance() && !matchResourcePermission(actualPathConfig, permission)) {
|
||||
continue;
|
||||
|
||||
}
|
||||
if (hasResourceScopePermission(requiredScopes, permission, actualPathConfig)) {
|
||||
LOGGER.debugf("Authorization GRANTED for path [%s]. Permissions [%s].", actualPathConfig, permissions);
|
||||
if (request.getMethod().equalsIgnoreCase("DELETE") && actualPathConfig.isInstance()) {
|
||||
this.paths.remove(actualPathConfig);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (hasResourceScopePermission(requiredScopes, permission, actualPathConfig)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LOGGER.debugf("Authorization FAILED for path [%s]. No enough permissions [%s].", actualPathConfig, permissions);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean hasResourceScopePermission(Set<String> requiredScopes, Permission permission, PathConfig actualPathConfig) {
|
||||
Set<String> allowedScopes = permission.getScopes();
|
||||
return (allowedScopes.containsAll(requiredScopes) || allowedScopes.isEmpty());
|
||||
}
|
||||
|
||||
protected AuthzClient getAuthzClient() {
|
||||
return this.authzClient;
|
||||
}
|
||||
|
||||
protected PolicyEnforcerConfig getEnforcerConfig() {
|
||||
return enforcerConfig;
|
||||
}
|
||||
|
||||
protected PolicyEnforcer getPolicyEnforcer() {
|
||||
return policyEnforcer;
|
||||
}
|
||||
|
||||
private AuthorizationContext createEmptyAuthorizationContext(final boolean granted) {
|
||||
return new AuthorizationContext() {
|
||||
@Override
|
||||
public boolean hasPermission(String resourceName, String scopeName) {
|
||||
return granted;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasResourcePermission(String resourceName) {
|
||||
return granted;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasScopePermission(String scopeName) {
|
||||
return granted;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Permission> getPermissions() {
|
||||
return Collections.EMPTY_LIST;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isGranted() {
|
||||
return granted;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private PathConfig resolvePathConfig(PathConfig originalConfig, Request request) {
|
||||
if (originalConfig.hasPattern()) {
|
||||
String pathInfo = URI.create(request.getURI()).getPath().substring(1);
|
||||
String path = pathInfo.substring(pathInfo.indexOf('/'), pathInfo.length());
|
||||
ProtectedResource resource = this.authzClient.protection().resource();
|
||||
Set<String> search = resource.findByFilter("uri=" + path);
|
||||
|
||||
if (!search.isEmpty()) {
|
||||
// resource does exist on the server, cache it
|
||||
ResourceRepresentation targetResource = resource.findById(search.iterator().next()).getResourceDescription();
|
||||
PathConfig config = new PathConfig();
|
||||
|
||||
config.setId(targetResource.getId());
|
||||
config.setName(targetResource.getName());
|
||||
config.setType(targetResource.getType());
|
||||
config.setPath(targetResource.getUri());
|
||||
config.setScopes(originalConfig.getScopes());
|
||||
config.setMethods(originalConfig.getMethods());
|
||||
config.setParentConfig(originalConfig);
|
||||
|
||||
this.paths.add(config);
|
||||
|
||||
return config;
|
||||
}
|
||||
}
|
||||
|
||||
return originalConfig;
|
||||
}
|
||||
|
||||
private Set<String> getRequiredScopes(PathConfig pathConfig, Request request) {
|
||||
Set<String> requiredScopes = new HashSet<>();
|
||||
|
||||
requiredScopes.addAll(pathConfig.getScopes());
|
||||
|
||||
String method = request.getMethod();
|
||||
|
||||
for (PolicyEnforcerConfig.MethodConfig methodConfig : pathConfig.getMethods()) {
|
||||
if (methodConfig.getMethod().equals(method)) {
|
||||
requiredScopes.addAll(methodConfig.getScopes());
|
||||
}
|
||||
}
|
||||
|
||||
return requiredScopes;
|
||||
}
|
||||
|
||||
private AuthorizationContext createAuthorizationContext(AccessToken accessToken) {
|
||||
return new AuthorizationContext(accessToken, this.paths);
|
||||
}
|
||||
|
||||
private boolean isResourcePermission(PathConfig actualPathConfig, Permission permission) {
|
||||
// first we try a match using resource id
|
||||
boolean resourceMatch = matchResourcePermission(actualPathConfig, permission);
|
||||
|
||||
// as a fallback, check if the current path is an instance and if so, check if parent's id matches the permission
|
||||
if (!resourceMatch && actualPathConfig.isInstance()) {
|
||||
resourceMatch = matchResourcePermission(actualPathConfig.getParentConfig(), permission);
|
||||
}
|
||||
|
||||
return resourceMatch;
|
||||
}
|
||||
|
||||
private boolean matchResourcePermission(PathConfig actualPathConfig, Permission permission) {
|
||||
return permission.getResourceSetId().equals(actualPathConfig.getId());
|
||||
}
|
||||
}
|
||||
-80
@@ -1,80 +0,0 @@
|
||||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
package org.keycloak.adapters.authorization;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
import org.keycloak.adapters.OIDCHttpFacade;
|
||||
import org.keycloak.adapters.spi.HttpFacade;
|
||||
import org.keycloak.authorization.client.AuthzClient;
|
||||
import org.keycloak.authorization.client.representation.PermissionRequest;
|
||||
import org.keycloak.authorization.client.resource.PermissionResource;
|
||||
import org.keycloak.authorization.client.resource.ProtectionResource;
|
||||
import org.keycloak.representations.adapters.config.PolicyEnforcerConfig.PathConfig;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
*/
|
||||
public class BearerTokenPolicyEnforcer extends AbstractPolicyEnforcer {
|
||||
|
||||
private static Logger LOGGER = Logger.getLogger(BearerTokenPolicyEnforcer.class);
|
||||
|
||||
public BearerTokenPolicyEnforcer(PolicyEnforcer enforcer) {
|
||||
super(enforcer);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean challenge(PathConfig pathConfig, Set<String> requiredScopes, OIDCHttpFacade facade) {
|
||||
if (getEnforcerConfig().getUmaProtocolConfig() != null) {
|
||||
challengeUmaAuthentication(pathConfig, requiredScopes, facade);
|
||||
} else {
|
||||
challengeEntitlementAuthentication(facade);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void challengeEntitlementAuthentication(OIDCHttpFacade facade) {
|
||||
HttpFacade.Response response = facade.getResponse();
|
||||
AuthzClient authzClient = getAuthzClient();
|
||||
String clientId = authzClient.getConfiguration().getClientId();
|
||||
String authorizationServerUri = authzClient.getServerConfiguration().getIssuer().toString() + "/authz/entitlement";
|
||||
response.setStatus(401);
|
||||
response.setHeader("WWW-Authenticate", "KC_ETT realm=\"" + clientId + "\",as_uri=\"" + authorizationServerUri + "\"");
|
||||
}
|
||||
|
||||
private void challengeUmaAuthentication(PathConfig pathConfig, Set<String> requiredScopes, OIDCHttpFacade facade) {
|
||||
HttpFacade.Response response = facade.getResponse();
|
||||
AuthzClient authzClient = getAuthzClient();
|
||||
String ticket = getPermissionTicket(pathConfig, requiredScopes, authzClient);
|
||||
String clientId = authzClient.getConfiguration().getClientId();
|
||||
String authorizationServerUri = authzClient.getServerConfiguration().getIssuer().toString() + "/authz/authorize";
|
||||
response.setStatus(401);
|
||||
response.setHeader("WWW-Authenticate", "UMA realm=\"" + clientId + "\",as_uri=\"" + authorizationServerUri + "\",ticket=\"" + ticket + "\"");
|
||||
}
|
||||
|
||||
private String getPermissionTicket(PathConfig pathConfig, Set<String> requiredScopes, AuthzClient authzClient) {
|
||||
ProtectionResource protection = authzClient.protection();
|
||||
PermissionResource permission = protection.permission();
|
||||
PermissionRequest permissionRequest = new PermissionRequest();
|
||||
permissionRequest.setResourceSetId(pathConfig.getId());
|
||||
permissionRequest.setScopes(requiredScopes);
|
||||
return permission.forResource(permissionRequest).getTicket();
|
||||
}
|
||||
}
|
||||
-151
@@ -1,151 +0,0 @@
|
||||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
package org.keycloak.adapters.authorization;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
import org.keycloak.RSATokenVerifier;
|
||||
import org.keycloak.adapters.KeycloakDeployment;
|
||||
import org.keycloak.adapters.OIDCHttpFacade;
|
||||
import org.keycloak.adapters.spi.HttpFacade;
|
||||
import org.keycloak.authorization.client.AuthorizationDeniedException;
|
||||
import org.keycloak.authorization.client.AuthzClient;
|
||||
import org.keycloak.authorization.client.representation.AuthorizationRequest;
|
||||
import org.keycloak.authorization.client.representation.AuthorizationResponse;
|
||||
import org.keycloak.authorization.client.representation.EntitlementRequest;
|
||||
import org.keycloak.authorization.client.representation.EntitlementResponse;
|
||||
import org.keycloak.authorization.client.representation.PermissionRequest;
|
||||
import org.keycloak.authorization.client.representation.PermissionResponse;
|
||||
import org.keycloak.representations.AccessToken;
|
||||
import org.keycloak.representations.adapters.config.PolicyEnforcerConfig.PathConfig;
|
||||
import org.keycloak.representations.idm.authorization.Permission;
|
||||
import org.keycloak.util.JsonSerialization;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
*/
|
||||
public class KeycloakAdapterPolicyEnforcer extends AbstractPolicyEnforcer {
|
||||
|
||||
private static Logger LOGGER = Logger.getLogger(KeycloakAdapterPolicyEnforcer.class);
|
||||
|
||||
public KeycloakAdapterPolicyEnforcer(PolicyEnforcer policyEnforcer) {
|
||||
super(policyEnforcer);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isAuthorized(PathConfig pathConfig, Set<String> requiredScopes, AccessToken accessToken, OIDCHttpFacade httpFacade) {
|
||||
int retry = 2;
|
||||
AccessToken original = accessToken;
|
||||
|
||||
while (retry > 0) {
|
||||
if (super.isAuthorized(pathConfig, requiredScopes, accessToken, httpFacade)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
accessToken = requestAuthorizationToken(pathConfig, requiredScopes, httpFacade);
|
||||
|
||||
if (accessToken == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
AccessToken.Authorization authorization = original.getAuthorization();
|
||||
|
||||
if (authorization == null) {
|
||||
authorization = new AccessToken.Authorization();
|
||||
authorization.setPermissions(new ArrayList<Permission>());
|
||||
}
|
||||
|
||||
AccessToken.Authorization newAuthorization = accessToken.getAuthorization();
|
||||
|
||||
if (newAuthorization != null) {
|
||||
authorization.getPermissions().addAll(newAuthorization.getPermissions());
|
||||
}
|
||||
|
||||
original.setAuthorization(authorization);
|
||||
|
||||
retry--;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean challenge(PathConfig pathConfig, Set<String> requiredScopes, OIDCHttpFacade facade) {
|
||||
String accessDeniedPath = getEnforcerConfig().getAccessDeniedPath();
|
||||
HttpFacade.Response response = facade.getResponse();
|
||||
|
||||
if (accessDeniedPath != null) {
|
||||
response.setStatus(302);
|
||||
response.setHeader("Location", accessDeniedPath);
|
||||
} else {
|
||||
response.sendError(403);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private AccessToken requestAuthorizationToken(PathConfig pathConfig, Set<String> requiredScopes, OIDCHttpFacade httpFacade) {
|
||||
try {
|
||||
String accessToken = httpFacade.getSecurityContext().getTokenString();
|
||||
AuthzClient authzClient = getAuthzClient();
|
||||
KeycloakDeployment deployment = getPolicyEnforcer().getDeployment();
|
||||
|
||||
if (getEnforcerConfig().getUmaProtocolConfig() != null) {
|
||||
LOGGER.debug("Obtaining authorization for authenticated user.");
|
||||
PermissionRequest permissionRequest = new PermissionRequest();
|
||||
|
||||
permissionRequest.setResourceSetId(pathConfig.getId());
|
||||
permissionRequest.setScopes(requiredScopes);
|
||||
|
||||
PermissionResponse permissionResponse = authzClient.protection().permission().forResource(permissionRequest);
|
||||
AuthorizationRequest authzRequest = new AuthorizationRequest(permissionResponse.getTicket());
|
||||
AuthorizationResponse authzResponse = authzClient.authorization(accessToken).authorize(authzRequest);
|
||||
|
||||
if (authzResponse != null) {
|
||||
return RSATokenVerifier.verifyToken(authzResponse.getRpt(), deployment.getRealmKey(), deployment.getRealmInfoUrl());
|
||||
}
|
||||
|
||||
return null;
|
||||
} else {
|
||||
LOGGER.debug("Obtaining entitlements for authenticated user.");
|
||||
AccessToken token = httpFacade.getSecurityContext().getToken();
|
||||
|
||||
if (token.getAuthorization() == null) {
|
||||
EntitlementResponse authzResponse = authzClient.entitlement(accessToken).getAll(authzClient.getConfiguration().getClientId());
|
||||
return RSATokenVerifier.verifyToken(authzResponse.getRpt(), deployment.getRealmKey(), deployment.getRealmInfoUrl());
|
||||
} else {
|
||||
EntitlementRequest request = new EntitlementRequest();
|
||||
PermissionRequest permissionRequest = new PermissionRequest();
|
||||
permissionRequest.setResourceSetId(pathConfig.getId());
|
||||
permissionRequest.setResourceSetName(pathConfig.getName());
|
||||
permissionRequest.setScopes(new HashSet<>(pathConfig.getScopes()));
|
||||
request.addPermission(permissionRequest);
|
||||
EntitlementResponse authzResponse = authzClient.entitlement(accessToken).get(authzClient.getConfiguration().getClientId(), request);
|
||||
return RSATokenVerifier.verifyToken(authzResponse.getRpt(), deployment.getRealmKey(), deployment.getRealmInfoUrl());
|
||||
}
|
||||
}
|
||||
} catch (AuthorizationDeniedException e) {
|
||||
return null;
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Unexpected error during authorization request.", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
-103
@@ -1,103 +0,0 @@
|
||||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
package org.keycloak.adapters.authorization;
|
||||
|
||||
import org.keycloak.representations.adapters.config.PolicyEnforcerConfig.PathConfig;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
*/
|
||||
class PathMatcher {
|
||||
|
||||
private static final String ANY_RESOURCE_PATTERN = "/*";
|
||||
|
||||
PathConfig matches(final String requestedUri, List<PathConfig> paths) {
|
||||
PathConfig actualConfig = null;
|
||||
|
||||
for (PathConfig entry : paths) {
|
||||
String protectedUri = entry.getPath();
|
||||
String selectedUri = null;
|
||||
|
||||
if (protectedUri.equals(ANY_RESOURCE_PATTERN) && actualConfig == null) {
|
||||
selectedUri = protectedUri;
|
||||
}
|
||||
|
||||
int suffixIndex = protectedUri.indexOf(ANY_RESOURCE_PATTERN + ".");
|
||||
|
||||
if (suffixIndex != -1) {
|
||||
String protectedSuffix = protectedUri.substring(suffixIndex + ANY_RESOURCE_PATTERN.length());
|
||||
|
||||
if (requestedUri.endsWith(protectedSuffix)) {
|
||||
selectedUri = protectedUri;
|
||||
}
|
||||
}
|
||||
|
||||
if (protectedUri.equals(requestedUri)) {
|
||||
selectedUri = protectedUri;
|
||||
}
|
||||
|
||||
if (protectedUri.endsWith(ANY_RESOURCE_PATTERN)) {
|
||||
String formattedPattern = removeWildCardsFromUri(protectedUri);
|
||||
|
||||
if (!formattedPattern.equals("/") && requestedUri.startsWith(formattedPattern)) {
|
||||
selectedUri = protectedUri;
|
||||
}
|
||||
|
||||
if (!formattedPattern.equals("/") && formattedPattern.endsWith("/") && formattedPattern.substring(0, formattedPattern.length() - 1).equals(requestedUri)) {
|
||||
selectedUri = protectedUri;
|
||||
}
|
||||
}
|
||||
|
||||
int startRegex = protectedUri.indexOf('{');
|
||||
|
||||
if (startRegex != -1) {
|
||||
String prefix = protectedUri.substring(0, startRegex);
|
||||
|
||||
if (requestedUri.startsWith(prefix)) {
|
||||
selectedUri = protectedUri;
|
||||
}
|
||||
}
|
||||
|
||||
if (selectedUri != null) {
|
||||
selectedUri = protectedUri;
|
||||
}
|
||||
|
||||
if (selectedUri != null) {
|
||||
if (actualConfig == null) {
|
||||
actualConfig = entry;
|
||||
} else {
|
||||
if (actualConfig.equals(ANY_RESOURCE_PATTERN)) {
|
||||
actualConfig = entry;
|
||||
}
|
||||
|
||||
if (protectedUri.startsWith(removeWildCardsFromUri(actualConfig.getPath()))) {
|
||||
actualConfig = entry;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return actualConfig;
|
||||
}
|
||||
|
||||
private String removeWildCardsFromUri(String protectedUri) {
|
||||
return protectedUri.replaceAll("/[*]", "/");
|
||||
}
|
||||
}
|
||||
-203
@@ -1,203 +0,0 @@
|
||||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
package org.keycloak.adapters.authorization;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
import org.keycloak.AuthorizationContext;
|
||||
import org.keycloak.adapters.KeycloakDeployment;
|
||||
import org.keycloak.adapters.OIDCHttpFacade;
|
||||
import org.keycloak.authorization.client.AuthzClient;
|
||||
import org.keycloak.authorization.client.Configuration;
|
||||
import org.keycloak.authorization.client.representation.RegistrationResponse;
|
||||
import org.keycloak.authorization.client.representation.ResourceRepresentation;
|
||||
import org.keycloak.authorization.client.representation.ScopeRepresentation;
|
||||
import org.keycloak.authorization.client.resource.ProtectedResource;
|
||||
import org.keycloak.representations.adapters.config.AdapterConfig;
|
||||
import org.keycloak.representations.adapters.config.PolicyEnforcerConfig;
|
||||
import org.keycloak.representations.adapters.config.PolicyEnforcerConfig.PathConfig;
|
||||
import org.keycloak.representations.idm.authorization.Permission;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||
*/
|
||||
public class PolicyEnforcer {
|
||||
|
||||
private static Logger LOGGER = Logger.getLogger(PolicyEnforcer.class);
|
||||
|
||||
private final KeycloakDeployment deployment;
|
||||
private final AuthzClient authzClient;
|
||||
private final PolicyEnforcerConfig enforcerConfig;
|
||||
private final List<PathConfig> paths;
|
||||
|
||||
public PolicyEnforcer(KeycloakDeployment deployment, AdapterConfig adapterConfig) {
|
||||
this.deployment = deployment;
|
||||
this.enforcerConfig = adapterConfig.getPolicyEnforcerConfig();
|
||||
this.authzClient = AuthzClient.create(new Configuration(adapterConfig.getAuthServerUrl(), adapterConfig.getRealm(), adapterConfig.getResource(), adapterConfig.getCredentials(), deployment.getClient()));
|
||||
this.paths = configurePaths(this.authzClient.protection().resource(), this.enforcerConfig);
|
||||
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("Initialization complete. Path configurations:");
|
||||
for (PathConfig pathConfig : this.paths) {
|
||||
LOGGER.debug(pathConfig);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public AuthorizationContext enforce(OIDCHttpFacade facade) {
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debugv("Policy enforcement is enable. Enforcing policy decisions for path [{0}].", facade.getRequest().getURI());
|
||||
}
|
||||
|
||||
AuthorizationContext context;
|
||||
|
||||
if (deployment.isBearerOnly()) {
|
||||
context = new BearerTokenPolicyEnforcer(this).authorize(facade);
|
||||
} else {
|
||||
context = new KeycloakAdapterPolicyEnforcer(this).authorize(facade);
|
||||
}
|
||||
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debugv("Policy enforcement result for path [{0}] is : {1}", facade.getRequest().getURI(), context.isGranted() ? "GRANTED" : "DENIED");
|
||||
LOGGER.debugv("Returning authorization context with permissions:");
|
||||
for (Permission permission : context.getPermissions()) {
|
||||
LOGGER.debug(permission);
|
||||
}
|
||||
}
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
PolicyEnforcerConfig getEnforcerConfig() {
|
||||
return enforcerConfig;
|
||||
}
|
||||
|
||||
AuthzClient getClient() {
|
||||
return authzClient;
|
||||
}
|
||||
|
||||
List<PathConfig> getPaths() {
|
||||
return paths;
|
||||
}
|
||||
|
||||
KeycloakDeployment getDeployment() {
|
||||
return deployment;
|
||||
}
|
||||
|
||||
private List<PathConfig> configurePaths(ProtectedResource protectedResource, PolicyEnforcerConfig enforcerConfig) {
|
||||
if (enforcerConfig.getPaths().isEmpty()) {
|
||||
LOGGER.info("No path provided in configuration.");
|
||||
return configureAllPathsForResourceServer(protectedResource);
|
||||
} else {
|
||||
LOGGER.info("Paths provided in configuration.");
|
||||
return configureDefinedPaths(protectedResource, enforcerConfig);
|
||||
}
|
||||
}
|
||||
|
||||
private List<PathConfig> configureDefinedPaths(ProtectedResource protectedResource, PolicyEnforcerConfig enforcerConfig) {
|
||||
List<PathConfig> paths = new ArrayList<>();
|
||||
|
||||
for (PathConfig pathConfig : enforcerConfig.getPaths()) {
|
||||
Set<String> search;
|
||||
String resourceName = pathConfig.getName();
|
||||
String path = pathConfig.getPath();
|
||||
|
||||
if (resourceName != null) {
|
||||
LOGGER.debugf("Trying to find resource with name [%s] for path [%s].", resourceName, path);
|
||||
search = protectedResource.findByFilter("name=" + resourceName);
|
||||
} else {
|
||||
LOGGER.debugf("Trying to find resource with uri [%s] for path [%s].", path, path);
|
||||
search = protectedResource.findByFilter("uri=" + path);
|
||||
}
|
||||
|
||||
if (search.isEmpty()) {
|
||||
if (enforcerConfig.isCreateResources()) {
|
||||
LOGGER.debugf("Creating resource on server for path [%s].", pathConfig);
|
||||
ResourceRepresentation resource = new ResourceRepresentation();
|
||||
|
||||
resource.setName(resourceName);
|
||||
resource.setType(pathConfig.getType());
|
||||
resource.setUri(path);
|
||||
|
||||
HashSet<ScopeRepresentation> scopes = new HashSet<>();
|
||||
|
||||
for (String scopeName : pathConfig.getScopes()) {
|
||||
ScopeRepresentation scope = new ScopeRepresentation();
|
||||
|
||||
scope.setName(scopeName);
|
||||
|
||||
scopes.add(scope);
|
||||
}
|
||||
|
||||
resource.setScopes(scopes);
|
||||
|
||||
RegistrationResponse registrationResponse = protectedResource.create(resource);
|
||||
|
||||
pathConfig.setId(registrationResponse.getId());
|
||||
} else {
|
||||
throw new RuntimeException("Could not find matching resource on server with uri [" + path + "] or name [" + resourceName + ". Make sure you have created a resource on the server that matches with the path configuration.");
|
||||
}
|
||||
} else {
|
||||
pathConfig.setId(search.iterator().next());
|
||||
}
|
||||
|
||||
paths.add(pathConfig);
|
||||
}
|
||||
|
||||
return paths;
|
||||
}
|
||||
|
||||
private List<PathConfig> configureAllPathsForResourceServer(ProtectedResource protectedResource) {
|
||||
LOGGER.info("Querying the server for all resources associated with this application.");
|
||||
List<PathConfig> paths = new ArrayList<>();
|
||||
|
||||
for (String id : protectedResource.findAll()) {
|
||||
RegistrationResponse response = protectedResource.findById(id);
|
||||
ResourceRepresentation resourceDescription = response.getResourceDescription();
|
||||
|
||||
if (resourceDescription.getUri() != null) {
|
||||
paths.add(createPathConfig(resourceDescription));
|
||||
}
|
||||
}
|
||||
|
||||
return paths;
|
||||
}
|
||||
|
||||
private PathConfig createPathConfig(ResourceRepresentation resourceDescription) {
|
||||
PathConfig pathConfig = new PathConfig();
|
||||
|
||||
pathConfig.setId(resourceDescription.getId());
|
||||
pathConfig.setName(resourceDescription.getName());
|
||||
pathConfig.setPath(resourceDescription.getUri());
|
||||
|
||||
List<String> scopeNames = new ArrayList<>();
|
||||
|
||||
for (ScopeRepresentation scope : resourceDescription.getScopes()) {
|
||||
scopeNames.add(scope.getName());
|
||||
}
|
||||
|
||||
pathConfig.setScopes(scopeNames);
|
||||
pathConfig.setType(resourceDescription.getType());
|
||||
|
||||
return pathConfig;
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -38,13 +38,13 @@ import javax.security.auth.spi.LoginModule;
|
||||
import org.jboss.logging.Logger;
|
||||
import org.keycloak.KeycloakPrincipal;
|
||||
import org.keycloak.RSATokenVerifier;
|
||||
import org.keycloak.common.VerificationException;
|
||||
import org.keycloak.adapters.AdapterDeploymentContext;
|
||||
import org.keycloak.adapters.AdapterUtils;
|
||||
import org.keycloak.common.util.FindFile;
|
||||
import org.keycloak.adapters.KeycloakDeployment;
|
||||
import org.keycloak.adapters.KeycloakDeploymentBuilder;
|
||||
import org.keycloak.adapters.RefreshableKeycloakSecurityContext;
|
||||
import org.keycloak.common.VerificationException;
|
||||
import org.keycloak.common.util.FindFile;
|
||||
import org.keycloak.representations.AccessToken;
|
||||
import org.keycloak.common.util.reflections.Reflections;
|
||||
|
||||
|
||||
Executable → Regular
File mode changed.
Executable → Regular
File mode changed.
-1
@@ -61,7 +61,6 @@ public class KeycloakDeploymentBuilderTest {
|
||||
assertEquals(1000, deployment.getRegisterNodePeriod());
|
||||
assertEquals(TokenStore.COOKIE, deployment.getTokenStore());
|
||||
assertEquals("email", deployment.getPrincipalAttribute());
|
||||
assertEquals(10, deployment.getTokenMinimumTimeToLive());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
-23
@@ -1,23 +0,0 @@
|
||||
package org.keycloak.adapters;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.keycloak.representations.oidc.TokenMetadataRepresentation;
|
||||
/**
|
||||
* @author github.com/tubbynl
|
||||
*
|
||||
*/
|
||||
public class RefreshableKeycloakSecurityContextTest {
|
||||
|
||||
@Test
|
||||
public void isActive() {
|
||||
TokenMetadataRepresentation token = new TokenMetadataRepresentation();
|
||||
token.setActive(true);
|
||||
token.issuedNow();
|
||||
RefreshableKeycloakSecurityContext sut = new RefreshableKeycloakSecurityContext(null,null,null,token,null, null, null);
|
||||
|
||||
// verify false if null deployment (KEYCLOAK-3050; yielded a npe)
|
||||
assertFalse(sut.isActive());
|
||||
}
|
||||
}
|
||||
@@ -28,6 +28,5 @@
|
||||
"register-node-at-startup": true,
|
||||
"register-node-period": 1000,
|
||||
"token-store": "cookie",
|
||||
"principal-attribute": "email",
|
||||
"token-minimum-time-to-live": 10
|
||||
"principal-attribute": "email"
|
||||
}
|
||||
@@ -21,7 +21,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-as7-integration-pom</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>2.1.0.CR1</version>
|
||||
<version>1.9.3.Final</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-as7-integration-pom</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>2.1.0.CR1</version>
|
||||
<version>1.9.3.Final</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<parent>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-as7-integration-pom</artifactId>
|
||||
<version>2.1.0.CR1</version>
|
||||
<version>1.9.3.Final</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
||||
+7
-6
@@ -49,6 +49,7 @@ public class KeycloakAdapterConfigDeploymentProcessor implements DeploymentUnitP
|
||||
@Override
|
||||
public void deploy(DeploymentPhaseContext phaseContext) throws DeploymentUnitProcessingException {
|
||||
DeploymentUnit deploymentUnit = phaseContext.getDeploymentUnit();
|
||||
String deploymentName = deploymentUnit.getName();
|
||||
|
||||
// if it's not a web-app there's nothing to secure
|
||||
WarMetaData warMetaData = deploymentUnit.getAttachment(WarMetaData.ATTACHMENT_KEY);
|
||||
@@ -66,24 +67,24 @@ public class KeycloakAdapterConfigDeploymentProcessor implements DeploymentUnitP
|
||||
// otherwise
|
||||
LoginConfigMetaData loginConfig = webMetaData.getLoginConfig();
|
||||
|
||||
boolean hasSubsystemConfig = service.isSecureDeployment(deploymentUnit);
|
||||
boolean hasSubsystemConfig = service.isSecureDeployment(deploymentName);
|
||||
boolean webRequiresKC = loginConfig != null && "KEYCLOAK".equalsIgnoreCase(loginConfig.getAuthMethod());
|
||||
|
||||
if (hasSubsystemConfig || webRequiresKC) {
|
||||
log.debug("Setting up KEYCLOAK auth method for WAR: " + deploymentUnit.getName());
|
||||
log.debug("Setting up KEYCLOAK auth method for WAR: " + deploymentName);
|
||||
|
||||
// if secure-deployment configuration exists for web app, we force KEYCLOAK auth method on it
|
||||
if (hasSubsystemConfig) {
|
||||
addJSONData(service.getJSON(deploymentUnit), warMetaData);
|
||||
addJSONData(service.getJSON(deploymentName), warMetaData);
|
||||
if (loginConfig != null) {
|
||||
loginConfig.setAuthMethod("KEYCLOAK");
|
||||
loginConfig.setRealmName(service.getRealmName(deploymentUnit));
|
||||
loginConfig.setRealmName(service.getRealmName(deploymentName));
|
||||
} else {
|
||||
log.warn("Failed to set up KEYCLOAK auth method for WAR: " + deploymentUnit.getName() + " (loginConfig == null)");
|
||||
log.warn("Failed to set up KEYCLOAK auth method for WAR: " + deploymentName + " (loginConfig == null)");
|
||||
}
|
||||
}
|
||||
addValve(webMetaData);
|
||||
KeycloakLogger.ROOT_LOGGER.deploymentSecured(deploymentUnit.getName());
|
||||
KeycloakLogger.ROOT_LOGGER.deploymentSecured(deploymentName);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+3
-28
@@ -25,9 +25,6 @@ import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.ADDRESS;
|
||||
import org.jboss.as.server.deployment.DeploymentUnit;
|
||||
import org.jboss.as.web.deployment.WarMetaData;
|
||||
import org.jboss.metadata.web.jboss.JBossWebMetaData;
|
||||
|
||||
/**
|
||||
* This service keeps track of the entire Keycloak management model so as to provide
|
||||
@@ -157,15 +154,13 @@ public final class KeycloakAdapterConfigService {
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getRealmName(DeploymentUnit deploymentUnit) {
|
||||
String deploymentName = preferredDeploymentName(deploymentUnit);
|
||||
public String getRealmName(String deploymentName) {
|
||||
ModelNode deployment = this.secureDeployments.get(deploymentName);
|
||||
return deployment.get(RealmDefinition.TAG_NAME).asString();
|
||||
|
||||
}
|
||||
|
||||
public String getJSON(DeploymentUnit deploymentUnit) {
|
||||
String deploymentName = preferredDeploymentName(deploymentUnit);
|
||||
public String getJSON(String deploymentName) {
|
||||
ModelNode deployment = this.secureDeployments.get(deploymentName);
|
||||
String realmName = deployment.get(RealmDefinition.TAG_NAME).asString();
|
||||
ModelNode realm = this.realms.get(realmName);
|
||||
@@ -189,29 +184,9 @@ public final class KeycloakAdapterConfigService {
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isSecureDeployment(DeploymentUnit deploymentUnit) {
|
||||
public boolean isSecureDeployment(String deploymentName) {
|
||||
//log.info("********* CHECK KEYCLOAK DEPLOYMENT: deployments.size()" + deployments.size());
|
||||
|
||||
String deploymentName = preferredDeploymentName(deploymentUnit);
|
||||
return this.secureDeployments.containsKey(deploymentName);
|
||||
}
|
||||
|
||||
// KEYCLOAK-3273: prefer module name if available
|
||||
private String preferredDeploymentName(DeploymentUnit deploymentUnit) {
|
||||
String deploymentName = deploymentUnit.getName();
|
||||
WarMetaData warMetaData = deploymentUnit.getAttachment(WarMetaData.ATTACHMENT_KEY);
|
||||
if (warMetaData == null) {
|
||||
return deploymentName;
|
||||
}
|
||||
|
||||
JBossWebMetaData webMetaData = warMetaData.getMergedJBossWebMetaData();
|
||||
if (webMetaData == null) {
|
||||
return deploymentName;
|
||||
}
|
||||
|
||||
String moduleName = webMetaData.getModuleName();
|
||||
if (moduleName != null) return moduleName + ".war";
|
||||
|
||||
return deploymentName;
|
||||
}
|
||||
}
|
||||
+2
-1
@@ -46,7 +46,8 @@ public abstract class KeycloakDependencyProcessor implements DeploymentUnitProce
|
||||
public void deploy(DeploymentPhaseContext phaseContext) throws DeploymentUnitProcessingException {
|
||||
final DeploymentUnit deploymentUnit = phaseContext.getDeploymentUnit();
|
||||
|
||||
if (!KeycloakAdapterConfigService.getInstance().isSecureDeployment(deploymentUnit)) {
|
||||
String deploymentName = deploymentUnit.getName();
|
||||
if (!KeycloakAdapterConfigService.getInstance().isSecureDeployment(deploymentName)) {
|
||||
WarMetaData warMetaData = deploymentUnit.getAttachment(WarMetaData.ATTACHMENT_KEY);
|
||||
if (warMetaData == null) {
|
||||
return;
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>2.1.0.CR1</version>
|
||||
<version>1.9.3.Final</version>
|
||||
<relativePath>../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<name>Keycloak AS7 / JBoss EAP 6 Integration</name>
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>2.1.0.CR1</version>
|
||||
<version>1.9.3.Final</version>
|
||||
<relativePath>../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
-2
@@ -119,7 +119,6 @@ public class KeycloakInstalled {
|
||||
.queryParam(OAuth2Constants.CLIENT_ID, deployment.getResourceName())
|
||||
.queryParam(OAuth2Constants.REDIRECT_URI, redirectUri)
|
||||
.queryParam(OAuth2Constants.STATE, state)
|
||||
.queryParam(OAuth2Constants.SCOPE, OAuth2Constants.SCOPE_OPENID)
|
||||
.build().toString();
|
||||
|
||||
Desktop.getDesktop().browse(new URI(authUrl));
|
||||
@@ -176,7 +175,6 @@ public class KeycloakInstalled {
|
||||
.queryParam(OAuth2Constants.RESPONSE_TYPE, OAuth2Constants.CODE)
|
||||
.queryParam(OAuth2Constants.CLIENT_ID, deployment.getResourceName())
|
||||
.queryParam(OAuth2Constants.REDIRECT_URI, redirectUri)
|
||||
.queryParam(OAuth2Constants.SCOPE, OAuth2Constants.SCOPE_OPENID)
|
||||
.build().toString();
|
||||
|
||||
printer.println("Open the following URL in a browser. After login copy/paste the code back and press <enter>");
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>2.1.0.CR1</version>
|
||||
<version>1.9.3.Final</version>
|
||||
<relativePath>../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
+4
-4
@@ -20,7 +20,6 @@ package org.keycloak.jaxrs;
|
||||
import org.keycloak.AbstractOAuthClient;
|
||||
import org.keycloak.OAuth2Constants;
|
||||
import org.keycloak.representations.AccessTokenResponse;
|
||||
import org.keycloak.util.TokenUtil;
|
||||
|
||||
import javax.ws.rs.BadRequestException;
|
||||
import javax.ws.rs.InternalServerErrorException;
|
||||
@@ -86,13 +85,14 @@ public class JaxrsOAuthClient extends AbstractOAuthClient {
|
||||
}
|
||||
public Response redirect(UriInfo uriInfo, String redirectUri) {
|
||||
String state = getStateCode();
|
||||
String scopeParam = TokenUtil.attachOIDCScope(scope);
|
||||
|
||||
UriBuilder uriBuilder = UriBuilder.fromUri(authUrl)
|
||||
.queryParam(OAuth2Constants.CLIENT_ID, clientId)
|
||||
.queryParam(OAuth2Constants.REDIRECT_URI, redirectUri)
|
||||
.queryParam(OAuth2Constants.STATE, state)
|
||||
.queryParam(OAuth2Constants.SCOPE, scopeParam);
|
||||
.queryParam(OAuth2Constants.STATE, state);
|
||||
if (scope != null) {
|
||||
uriBuilder.queryParam(OAuth2Constants.SCOPE, scope);
|
||||
}
|
||||
|
||||
URI url = uriBuilder.build();
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>2.1.0.CR1</version>
|
||||
<version>1.9.3.Final</version>
|
||||
<relativePath>../../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
@@ -60,7 +60,7 @@
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-jetty-adapter-spi</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-adapter-core</artifactId>
|
||||
</dependency>
|
||||
|
||||
+2
-2
@@ -340,13 +340,13 @@ public abstract class AbstractKeycloakJettyAuthenticator extends LoginAuthentica
|
||||
Authentication authentication = request.getAuthentication();
|
||||
if (!(authentication instanceof KeycloakAuthentication)) {
|
||||
UserIdentity userIdentity = createIdentity(principal);
|
||||
authentication = createAuthentication(userIdentity, request);
|
||||
authentication = createAuthentication(userIdentity);
|
||||
request.setAuthentication(authentication);
|
||||
}
|
||||
return authentication;
|
||||
}
|
||||
|
||||
protected abstract Authentication createAuthentication(UserIdentity userIdentity, Request request);
|
||||
protected abstract Authentication createAuthentication(UserIdentity userIdentity);
|
||||
|
||||
public static abstract class KeycloakAuthentication extends UserAuthentication {
|
||||
public KeycloakAuthentication(String method, UserIdentity userIdentity) {
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>2.1.0.CR1</version>
|
||||
<version>1.9.3.Final</version>
|
||||
<relativePath>../../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
+1
-1
@@ -50,7 +50,7 @@ public class KeycloakJettyAuthenticator extends AbstractKeycloakJettyAuthenticat
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Authentication createAuthentication(UserIdentity userIdentity, Request request) {
|
||||
protected Authentication createAuthentication(UserIdentity userIdentity) {
|
||||
return new KeycloakAuthentication(getAuthMethod(), userIdentity) {
|
||||
@Override
|
||||
public void logout() {
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>2.1.0.CR1</version>
|
||||
<version>1.9.3.Final</version>
|
||||
<relativePath>../../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
+1
-1
@@ -52,7 +52,7 @@ public class KeycloakJettyAuthenticator extends AbstractKeycloakJettyAuthenticat
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Authentication createAuthentication(UserIdentity userIdentity, Request request) {
|
||||
protected Authentication createAuthentication(UserIdentity userIdentity) {
|
||||
return new KeycloakAuthentication(getAuthMethod(), userIdentity) {
|
||||
@Override
|
||||
public void logout() {
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>2.1.0.CR1</version>
|
||||
<version>1.9.3.Final</version>
|
||||
<relativePath>../../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
+1
-1
@@ -47,7 +47,7 @@ public class KeycloakJettyAuthenticator extends AbstractKeycloakJettyAuthenticat
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Authentication createAuthentication(UserIdentity userIdentity, Request request) {
|
||||
protected Authentication createAuthentication(UserIdentity userIdentity) {
|
||||
return new KeycloakAuthentication(getAuthMethod(), userIdentity) {
|
||||
@Override
|
||||
public void logout() {
|
||||
|
||||
@@ -1,156 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<!--
|
||||
~ Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
~ and other contributors as indicated by the @author tags.
|
||||
~
|
||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
||||
~ you may not use this file except in compliance with the License.
|
||||
~ You may obtain a copy of the License at
|
||||
~
|
||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
||||
~
|
||||
~ Unless required by applicable law or agreed to in writing, software
|
||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
~ See the License for the specific language governing permissions and
|
||||
~ limitations under the License.
|
||||
-->
|
||||
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>2.1.0.CR1</version>
|
||||
<relativePath>../../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>keycloak-jetty93-adapter</artifactId>
|
||||
<name>Keycloak Jetty 9.3.x Integration</name>
|
||||
<properties>
|
||||
<jetty9.version>9.3.9.v20160517</jetty9.version>
|
||||
<keycloak.osgi.export>
|
||||
org.keycloak.adapters.jetty.*
|
||||
</keycloak.osgi.export>
|
||||
<keycloak.osgi.import>
|
||||
org.eclipse.jetty.*;resolution:=optional,
|
||||
javax.servlet.*;version="[3.0,4)";resolution:=optional,
|
||||
org.keycloak.*;version="${project.version}",
|
||||
*;resolution:=optional
|
||||
</keycloak.osgi.import>
|
||||
</properties>
|
||||
<description />
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.jboss.logging</groupId>
|
||||
<artifactId>jboss-logging</artifactId>
|
||||
<version>${jboss.logging.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-adapter-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-jetty-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
<artifactId>httpclient</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.bouncycastle</groupId>
|
||||
<artifactId>bcprov-jdk15on</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-annotations</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-server</artifactId>
|
||||
<version>${jetty9.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-util</artifactId>
|
||||
<version>${jetty9.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-security</artifactId>
|
||||
<version>${jetty9.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<source>1.6</source>
|
||||
<target>1.6</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<!-- Adding OSGI metadata to the JAR without changing the packaging type. -->
|
||||
<plugin>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<configuration>
|
||||
<archive>
|
||||
<manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile>
|
||||
</archive>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.felix</groupId>
|
||||
<artifactId>maven-bundle-plugin</artifactId>
|
||||
<extensions>true</extensions>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>bundle-manifest</id>
|
||||
<phase>process-classes</phase>
|
||||
<goals>
|
||||
<goal>manifest</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<instructions>
|
||||
<Bundle-ClassPath>.</Bundle-ClassPath>
|
||||
<Bundle-Name>${project.name}</Bundle-Name>
|
||||
<Bundle-SymbolicName>${project.groupId}.${project.artifactId}</Bundle-SymbolicName>
|
||||
<Import-Package>${keycloak.osgi.import}</Import-Package>
|
||||
<Export-Package>${keycloak.osgi.export}</Export-Package>
|
||||
</instructions>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
||||
-47
@@ -1,47 +0,0 @@
|
||||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.adapters.jetty;
|
||||
|
||||
import org.eclipse.jetty.server.Request;
|
||||
import org.keycloak.adapters.AdapterTokenStore;
|
||||
import org.keycloak.adapters.KeycloakDeployment;
|
||||
import org.keycloak.adapters.jetty.core.JettyRequestAuthenticator;
|
||||
import org.keycloak.adapters.spi.HttpFacade;
|
||||
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class Jetty93RequestAuthenticator extends JettyRequestAuthenticator {
|
||||
public Jetty93RequestAuthenticator(HttpFacade facade, KeycloakDeployment deployment, AdapterTokenStore tokenStore, int sslRedirectPort, Request request) {
|
||||
super(facade, deployment, tokenStore, sslRedirectPort, request);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String changeHttpSessionId(boolean create) {
|
||||
Request request = this.request;
|
||||
HttpSession session = request.getSession(false);
|
||||
if (session == null) {
|
||||
return request.getSession(true).getId();
|
||||
}
|
||||
if (!deployment.isTurnOffChangeSessionIdOnLogin()) return request.changeSessionId();
|
||||
else return session.getId();
|
||||
}
|
||||
}
|
||||
-112
@@ -1,112 +0,0 @@
|
||||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.adapters.jetty;
|
||||
|
||||
import org.eclipse.jetty.http.HttpMethod;
|
||||
import org.eclipse.jetty.security.authentication.FormAuthenticator;
|
||||
import org.eclipse.jetty.server.Request;
|
||||
import org.eclipse.jetty.util.MultiMap;
|
||||
import org.keycloak.adapters.spi.AdapterSessionStore;
|
||||
import org.keycloak.adapters.jetty.spi.JettyHttpFacade;
|
||||
import org.keycloak.common.util.MultivaluedHashMap;
|
||||
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class JettyAdapterSessionStore implements AdapterSessionStore {
|
||||
public static final String CACHED_FORM_PARAMETERS = "__CACHED_FORM_PARAMETERS";
|
||||
protected Request myRequest;
|
||||
|
||||
public JettyAdapterSessionStore(Request request) {
|
||||
this.myRequest = request; // for IDE/compilation purposes
|
||||
}
|
||||
|
||||
protected MultiMap<String> extractFormParameters(Request base_request) {
|
||||
MultiMap<String> formParameters = new MultiMap<String>();
|
||||
base_request.extractFormParameters(formParameters);
|
||||
return formParameters;
|
||||
}
|
||||
protected void restoreFormParameters(MultiMap<String> j_post, Request base_request) {
|
||||
base_request.setContentParameters(j_post);
|
||||
}
|
||||
|
||||
public boolean restoreRequest() {
|
||||
HttpSession session = myRequest.getSession(false);
|
||||
if (session == null) return false;
|
||||
synchronized (session) {
|
||||
String j_uri = (String) session.getAttribute(FormAuthenticator.__J_URI);
|
||||
if (j_uri != null) {
|
||||
// check if the request is for the same url as the original and restore
|
||||
// params if it was a post
|
||||
StringBuffer buf = myRequest.getRequestURL();
|
||||
if (myRequest.getQueryString() != null)
|
||||
buf.append("?").append(myRequest.getQueryString());
|
||||
if (j_uri.equals(buf.toString())) {
|
||||
String method = (String)session.getAttribute(JettyHttpFacade.__J_METHOD);
|
||||
myRequest.setMethod(method);
|
||||
MultivaluedHashMap<String, String> j_post = (MultivaluedHashMap<String, String>) session.getAttribute(CACHED_FORM_PARAMETERS);
|
||||
if (j_post != null) {
|
||||
myRequest.setContentType("application/x-www-form-urlencoded");
|
||||
MultiMap<String> map = new MultiMap<String>();
|
||||
for (String key : j_post.keySet()) {
|
||||
for (String val : j_post.getList(key)) {
|
||||
map.add(key, val);
|
||||
}
|
||||
}
|
||||
restoreFormParameters(map, myRequest);
|
||||
}
|
||||
session.removeAttribute(FormAuthenticator.__J_URI);
|
||||
session.removeAttribute(JettyHttpFacade.__J_METHOD);
|
||||
session.removeAttribute(FormAuthenticator.__J_POST);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void saveRequest() {
|
||||
// remember the current URI
|
||||
HttpSession session = myRequest.getSession();
|
||||
synchronized (session) {
|
||||
// But only if it is not set already, or we save every uri that leads to a login form redirect
|
||||
if (session.getAttribute(FormAuthenticator.__J_URI) == null) {
|
||||
StringBuffer buf = myRequest.getRequestURL();
|
||||
if (myRequest.getQueryString() != null)
|
||||
buf.append("?").append(myRequest.getQueryString());
|
||||
session.setAttribute(FormAuthenticator.__J_URI, buf.toString());
|
||||
session.setAttribute(JettyHttpFacade.__J_METHOD, myRequest.getMethod());
|
||||
|
||||
if ("application/x-www-form-urlencoded".equals(myRequest.getContentType()) && "POST".equalsIgnoreCase(myRequest.getMethod())) {
|
||||
MultiMap<String> formParameters = extractFormParameters(myRequest);
|
||||
MultivaluedHashMap<String, String> map = new MultivaluedHashMap<String, String>();
|
||||
for (String key : formParameters.keySet()) {
|
||||
for (Object value : formParameters.getValues(key)) {
|
||||
map.add(key, (String) value);
|
||||
}
|
||||
}
|
||||
session.setAttribute(CACHED_FORM_PARAMETERS, map);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
-69
@@ -1,69 +0,0 @@
|
||||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.keycloak.adapters.jetty;
|
||||
|
||||
import org.eclipse.jetty.server.Authentication;
|
||||
import org.eclipse.jetty.server.Request;
|
||||
import org.eclipse.jetty.server.UserIdentity;
|
||||
import org.keycloak.adapters.AdapterTokenStore;
|
||||
import org.keycloak.adapters.KeycloakDeployment;
|
||||
import org.keycloak.adapters.jetty.core.AbstractKeycloakJettyAuthenticator;
|
||||
import org.keycloak.adapters.jetty.core.JettyRequestAuthenticator;
|
||||
import org.keycloak.adapters.jetty.core.JettySessionTokenStore;
|
||||
import org.keycloak.adapters.jetty.spi.JettyHttpFacade;
|
||||
|
||||
import javax.servlet.ServletRequest;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class KeycloakJettyAuthenticator extends AbstractKeycloakJettyAuthenticator {
|
||||
|
||||
public KeycloakJettyAuthenticator() {
|
||||
super();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected Request resolveRequest(ServletRequest req) {
|
||||
return Request.getBaseRequest(req);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Authentication createAuthentication(UserIdentity userIdentity, final Request request) {
|
||||
return new KeycloakAuthentication(getAuthMethod(), userIdentity) {
|
||||
@Override
|
||||
public void logout() {
|
||||
logoutCurrent(request);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public AdapterTokenStore createSessionTokenStore(Request request, KeycloakDeployment resolvedDeployment) {
|
||||
return new JettySessionTokenStore(request, resolvedDeployment, new JettyAdapterSessionStore(request));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected JettyRequestAuthenticator createRequestAuthenticator(Request request, JettyHttpFacade facade,
|
||||
KeycloakDeployment deployment, AdapterTokenStore tokenStore) {
|
||||
return new Jetty93RequestAuthenticator(facade, deployment, tokenStore, -1, request);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -20,7 +20,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>2.1.0.CR1</version>
|
||||
<version>1.9.3.Final</version>
|
||||
<relativePath>../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<name>Keycloak Jetty Integration</name>
|
||||
@@ -33,8 +33,7 @@
|
||||
<modules>
|
||||
<module>jetty-core</module>
|
||||
<module>jetty8.1</module>
|
||||
<module>jetty9.1</module>
|
||||
<module>jetty9.2</module>
|
||||
<module>jetty9.3</module>
|
||||
<module>jetty9.1</module>
|
||||
</modules>
|
||||
</project>
|
||||
@@ -21,7 +21,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>2.1.0.CR1</version>
|
||||
<version>1.9.3.Final</version>
|
||||
<relativePath>../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
@@ -58,25 +58,6 @@
|
||||
<goal>minify</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>min-authz-js</id>
|
||||
<phase>compile</phase>
|
||||
<configuration>
|
||||
<charset>utf-8</charset>
|
||||
<webappSourceDir>${basedir}/src/main/resources</webappSourceDir>
|
||||
<jsSourceDir>.</jsSourceDir>
|
||||
<jsSourceFiles>
|
||||
<jsSourceFile>keycloak-authz.js</jsSourceFile>
|
||||
</jsSourceFiles>
|
||||
|
||||
<webappTargetDir>${project.build.directory}/classes</webappTargetDir>
|
||||
<jsTargetDir>.</jsTargetDir>
|
||||
<jsFinalFile>keycloak-authz.js</jsFinalFile>
|
||||
</configuration>
|
||||
<goals>
|
||||
<goal>minify</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
|
||||
@@ -1,170 +0,0 @@
|
||||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
*/
|
||||
|
||||
(function( window, undefined ) {
|
||||
|
||||
var KeycloakAuthorization = function (keycloak) {
|
||||
var _instance = this;
|
||||
this.rpt = null;
|
||||
|
||||
this.init = function () {
|
||||
var request = new XMLHttpRequest();
|
||||
|
||||
request.open('GET', keycloak.authServerUrl + '/realms/' + keycloak.realm + '/.well-known/uma-configuration');
|
||||
request.onreadystatechange = function () {
|
||||
if (request.readyState == 4) {
|
||||
if (request.status == 200) {
|
||||
_instance.config = JSON.parse(request.responseText);
|
||||
} else {
|
||||
console.error('Could not obtain configuration from server.');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
request.send(null);
|
||||
};
|
||||
|
||||
/**
|
||||
* This method enables client applications to better integrate with resource servers protected by a Keycloak
|
||||
* policy enforcer.
|
||||
*
|
||||
* In this case, the resource server will respond with a 401 status code and a WWW-Authenticate header holding the
|
||||
* necessary information to ask a Keycloak server for authorization data using both UMA and Entitlement protocol,
|
||||
* depending on how the policy enforcer at the resource server was configured.
|
||||
*/
|
||||
this.authorize = function (wwwAuthenticateHeader) {
|
||||
this.then = function (onGrant, onDeny, onError) {
|
||||
if (wwwAuthenticateHeader.indexOf('UMA') != -1) {
|
||||
var params = wwwAuthenticateHeader.split(',');
|
||||
|
||||
for (i = 0; i < params.length; i++) {
|
||||
var param = params[i].split('=');
|
||||
|
||||
if (param[0] == 'ticket') {
|
||||
var request = new XMLHttpRequest();
|
||||
|
||||
request.open('POST', _instance.config.rpt_endpoint, true);
|
||||
request.setRequestHeader('Content-Type', 'application/json')
|
||||
request.setRequestHeader('Authorization', 'Bearer ' + keycloak.token)
|
||||
|
||||
request.onreadystatechange = function () {
|
||||
if (request.readyState == 4) {
|
||||
var status = request.status;
|
||||
|
||||
if (status >= 200 && status < 300) {
|
||||
var rpt = JSON.parse(request.responseText).rpt;
|
||||
_instance.rpt = rpt;
|
||||
onGrant(rpt);
|
||||
} else if (status == 403) {
|
||||
if (onDeny) {
|
||||
onDeny();
|
||||
} else {
|
||||
console.error('Authorization request was denied by the server.');
|
||||
}
|
||||
} else {
|
||||
if (onError) {
|
||||
onError();
|
||||
} else {
|
||||
console.error('Could not obtain authorization data from server.');
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var ticket = param[1].substring(1, param[1].length - 1).trim();
|
||||
|
||||
request.send(JSON.stringify(
|
||||
{
|
||||
ticket: ticket,
|
||||
rpt: _instance.rpt
|
||||
}
|
||||
));
|
||||
}
|
||||
}
|
||||
} else if (wwwAuthenticateHeader.indexOf('KC_ETT') != -1) {
|
||||
var params = wwwAuthenticateHeader.substring('KC_ETT'.length).trim().split(',');
|
||||
var clientId = null;
|
||||
|
||||
for (i = 0; i < params.length; i++) {
|
||||
var param = params[i].split('=');
|
||||
|
||||
if (param[0] == 'realm') {
|
||||
clientId = param[1].substring(1, param[1].length - 1).trim();
|
||||
}
|
||||
}
|
||||
|
||||
_instance.entitlement(clientId).then(onGrant, onDeny, onError);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Obtains all entitlements from a Keycloak Server based on a give resourceServerId.
|
||||
*/
|
||||
this.entitlement = function (resourceSeververId) {
|
||||
this.then = function (onGrant, onDeny, onError) {
|
||||
var request = new XMLHttpRequest();
|
||||
|
||||
request.open('GET', keycloak.authServerUrl + '/realms/' + keycloak.realm + '/authz/entitlement/' + resourceSeververId, true);
|
||||
request.setRequestHeader('Authorization', 'Bearer ' + keycloak.token)
|
||||
|
||||
request.onreadystatechange = function () {
|
||||
if (request.readyState == 4) {
|
||||
var status = request.status;
|
||||
|
||||
if (status >= 200 && status < 300) {
|
||||
var rpt = JSON.parse(request.responseText).rpt;
|
||||
_instance.rpt = rpt;
|
||||
onGrant(rpt);
|
||||
} else if (status == 403) {
|
||||
if (onDeny) {
|
||||
onDeny();
|
||||
} else {
|
||||
console.error('Authorization request was denied by the server.');
|
||||
}
|
||||
} else {
|
||||
if (onError) {
|
||||
onError();
|
||||
} else {
|
||||
console.error('Could not obtain authorization data from server.');
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
request.send(null);
|
||||
};
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
return this;
|
||||
};
|
||||
|
||||
this.init(this);
|
||||
};
|
||||
|
||||
if ( typeof module === "object" && module && typeof module.exports === "object" ) {
|
||||
module.exports = KeycloakAuthorization;
|
||||
} else {
|
||||
window.KeycloakAuthorization = KeycloakAuthorization;
|
||||
|
||||
if ( typeof define === "function" && define.amd ) {
|
||||
define( "keycloak-authorization", [], function () { return KeycloakAuthorization; } );
|
||||
}
|
||||
}
|
||||
})( window );
|
||||
@@ -25,7 +25,7 @@
|
||||
var kc = this;
|
||||
var adapter;
|
||||
var refreshQueue = [];
|
||||
var callbackStorage;
|
||||
var storage;
|
||||
|
||||
var loginIframe = {
|
||||
enable: true,
|
||||
@@ -36,18 +36,12 @@
|
||||
kc.init = function (initOptions) {
|
||||
kc.authenticated = false;
|
||||
|
||||
callbackStorage = createCallbackStorage();
|
||||
storage = new PersistentStorage();
|
||||
|
||||
if (initOptions && initOptions.adapter === 'cordova') {
|
||||
if (window.Cordova) {
|
||||
adapter = loadAdapter('cordova');
|
||||
} else if (initOptions && initOptions.adapter === 'default') {
|
||||
adapter = loadAdapter();
|
||||
} else {
|
||||
if (window.Cordova) {
|
||||
adapter = loadAdapter('cordova');
|
||||
} else {
|
||||
adapter = loadAdapter();
|
||||
}
|
||||
adapter = loadAdapter();
|
||||
}
|
||||
|
||||
if (initOptions) {
|
||||
@@ -103,8 +97,8 @@
|
||||
initPromise.promise.success(function() {
|
||||
kc.onReady && kc.onReady(kc.authenticated);
|
||||
promise.setSuccess(kc.authenticated);
|
||||
}).error(function(errorData) {
|
||||
promise.setError(errorData);
|
||||
}).error(function() {
|
||||
promise.setError();
|
||||
});
|
||||
|
||||
var configPromise = loadConfig(config);
|
||||
@@ -201,15 +195,13 @@
|
||||
redirectUri += (redirectUri.indexOf('?') == -1 ? '?' : '&') + 'prompt=' + options.prompt;
|
||||
}
|
||||
|
||||
callbackStorage.add({ state: state, nonce: nonce, redirectUri: encodeURIComponent(redirectUri) });
|
||||
storage.setItem('oauthState', JSON.stringify({ state: state, nonce: nonce, redirectUri: encodeURIComponent(redirectUri) }));
|
||||
|
||||
var action = 'auth';
|
||||
if (options && options.action == 'register') {
|
||||
action = 'registrations';
|
||||
}
|
||||
|
||||
var scope = (options && options.scope) ? "openid " + options.scope : "openid";
|
||||
|
||||
var url = getRealmUrl()
|
||||
+ '/protocol/openid-connect/' + action
|
||||
+ '?client_id=' + encodeURIComponent(kc.clientId)
|
||||
@@ -217,17 +209,12 @@
|
||||
+ '&state=' + encodeURIComponent(state)
|
||||
+ '&nonce=' + encodeURIComponent(nonce)
|
||||
+ '&response_mode=' + encodeURIComponent(kc.responseMode)
|
||||
+ '&response_type=' + encodeURIComponent(kc.responseType)
|
||||
+ '&scope=' + encodeURIComponent(scope);
|
||||
+ '&response_type=' + encodeURIComponent(kc.responseType);
|
||||
|
||||
if (options && options.prompt) {
|
||||
url += '&prompt=' + encodeURIComponent(options.prompt);
|
||||
}
|
||||
|
||||
if (options && options.maxAge) {
|
||||
url += '&max_age=' + encodeURIComponent(options.maxAge);
|
||||
}
|
||||
|
||||
if (options && options.loginHint) {
|
||||
url += '&login_hint=' + encodeURIComponent(options.loginHint);
|
||||
}
|
||||
@@ -236,6 +223,10 @@
|
||||
url += '&kc_idp_hint=' + encodeURIComponent(options.idpHint);
|
||||
}
|
||||
|
||||
if (options && options.scope) {
|
||||
url += '&scope=' + encodeURIComponent(options.scope);
|
||||
}
|
||||
|
||||
if (options && options.locale) {
|
||||
url += '&ui_locales=' + encodeURIComponent(options.locale);
|
||||
}
|
||||
@@ -466,9 +457,8 @@
|
||||
|
||||
if (error) {
|
||||
if (prompt != 'none') {
|
||||
var errorData = { error: error, error_description: oauth.error_description };
|
||||
kc.onAuthError && kc.onAuthError(errorData);
|
||||
promise && promise.setError(errorData);
|
||||
kc.onAuthError && kc.onAuthError();
|
||||
promise && promise.setError();
|
||||
} else {
|
||||
promise && promise.setSuccess();
|
||||
}
|
||||
@@ -701,11 +691,15 @@
|
||||
|
||||
function parseCallback(url) {
|
||||
var oauth = new CallbackParser(url, kc.responseMode).parseUri();
|
||||
var oauthState = callbackStorage.get(oauth.state);
|
||||
|
||||
if (oauthState && (oauth.code || oauth.error || oauth.access_token || oauth.id_token)) {
|
||||
oauth.redirectUri = oauthState.redirectUri;
|
||||
oauth.storedNonce = oauthState.nonce;
|
||||
var oauthState = storage.getItem('oauthState');
|
||||
var sessionState = oauthState && JSON.parse(oauthState);
|
||||
|
||||
if (sessionState && (oauth.code || oauth.error || oauth.access_token || oauth.id_token) && oauth.state && oauth.state == sessionState.state) {
|
||||
storage.removeItem('oauthState');
|
||||
|
||||
oauth.redirectUri = sessionState.redirectUri;
|
||||
oauth.storedNonce = sessionState.nonce;
|
||||
|
||||
if (oauth.fragment) {
|
||||
oauth.newUrl += '#' + oauth.fragment;
|
||||
@@ -792,22 +786,8 @@
|
||||
if (event.origin !== loginIframe.iframeOrigin) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
var data = JSON.parse(event.data);
|
||||
} catch (err) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!data.callbackId) {
|
||||
return;
|
||||
}
|
||||
|
||||
var data = JSON.parse(event.data);
|
||||
var promise = loginIframe.callbackMap[data.callbackId];
|
||||
if (!promise) {
|
||||
return;
|
||||
}
|
||||
|
||||
delete loginIframe.callbackMap[data.callbackId];
|
||||
|
||||
if ((!kc.sessionId || kc.sessionId == data.session) && data.loggedIn) {
|
||||
@@ -996,93 +976,60 @@
|
||||
throw 'invalid adapter type: ' + type;
|
||||
}
|
||||
|
||||
var LocalStorage = function() {
|
||||
if (!(this instanceof LocalStorage)) {
|
||||
return new LocalStorage();
|
||||
|
||||
var PersistentStorage = function() {
|
||||
if (!(this instanceof PersistentStorage)) {
|
||||
return new PersistentStorage();
|
||||
}
|
||||
|
||||
localStorage.setItem('kc-test', 'test');
|
||||
localStorage.removeItem('kc-test');
|
||||
|
||||
var cs = this;
|
||||
|
||||
function clearExpired() {
|
||||
var time = new Date().getTime();
|
||||
for (var i = 1; i <= localStorage.length; i++) {
|
||||
var key = localStorage.key(i);
|
||||
if (key && key.indexOf('kc-callback-') == 0) {
|
||||
var value = localStorage.getItem(key);
|
||||
if (value) {
|
||||
try {
|
||||
var expires = JSON.parse(value).expires;
|
||||
if (!expires || expires < time) {
|
||||
localStorage.removeItem(key);
|
||||
}
|
||||
} catch (err) {
|
||||
localStorage.removeItem(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
var ps = this;
|
||||
var useCookieStorage = function () {
|
||||
if (typeof localStorage === "undefined") {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
cs.get = function(state) {
|
||||
if (!state) {
|
||||
return;
|
||||
}
|
||||
|
||||
var key = 'kc-callback-' + state;
|
||||
var value = localStorage.getItem(key);
|
||||
if (value) {
|
||||
try {
|
||||
var key = '@@keycloak-session-storage/test';
|
||||
localStorage.setItem(key, 'test');
|
||||
localStorage.removeItem(key);
|
||||
value = JSON.parse(value);
|
||||
return false;
|
||||
} catch (err) {
|
||||
// Probably in Safari "private mode" where localStorage
|
||||
// quota is 0, or quota exceeded. Switching to cookie
|
||||
// storage.
|
||||
return true;
|
||||
}
|
||||
|
||||
clearExpired();
|
||||
return value;
|
||||
};
|
||||
|
||||
cs.add = function(state) {
|
||||
clearExpired();
|
||||
|
||||
var key = 'kc-callback-' + state.state;
|
||||
state.expires = new Date().getTime() + (60 * 60 * 1000);
|
||||
localStorage.setItem(key, JSON.stringify(state));
|
||||
};
|
||||
};
|
||||
|
||||
var CookieStorage = function() {
|
||||
if (!(this instanceof CookieStorage)) {
|
||||
return new CookieStorage();
|
||||
}
|
||||
|
||||
var cs = this;
|
||||
|
||||
cs.get = function(state) {
|
||||
if (!state) {
|
||||
return;
|
||||
ps.setItem = function(key, value) {
|
||||
if (useCookieStorage()) {
|
||||
setCookie(key, value, cookieExpiration(5));
|
||||
} else {
|
||||
localStorage.setItem(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
var value = getCookie('kc-callback-' + state);
|
||||
setCookie('kc-callback-' + state, '', cookieExpiration(-100));
|
||||
if (value) {
|
||||
return JSON.parse(value);
|
||||
ps.getItem = function(key) {
|
||||
if (useCookieStorage()) {
|
||||
return getCookie(key);
|
||||
}
|
||||
};
|
||||
return localStorage.getItem(key);
|
||||
}
|
||||
|
||||
cs.add = function(state) {
|
||||
setCookie('kc-callback-' + state.state, JSON.stringify(state), cookieExpiration(60));
|
||||
};
|
||||
|
||||
cs.removeItem = function(key) {
|
||||
ps.removeItem = function(key) {
|
||||
if (typeof localStorage !== "undefined") {
|
||||
try {
|
||||
// Always try to delete from localStorage.
|
||||
localStorage.removeItem(key);
|
||||
} catch (err) { }
|
||||
}
|
||||
// Always remove the cookie.
|
||||
setCookie(key, '', cookieExpiration(-100));
|
||||
};
|
||||
}
|
||||
|
||||
var cookieExpiration = function (minutes) {
|
||||
var exp = new Date();
|
||||
exp.setTime(exp.getTime() + (minutes*60*1000));
|
||||
return exp;
|
||||
};
|
||||
}
|
||||
|
||||
var getCookie = function (key) {
|
||||
var name = key + '=';
|
||||
@@ -1097,22 +1044,13 @@
|
||||
}
|
||||
}
|
||||
return '';
|
||||
};
|
||||
}
|
||||
|
||||
var setCookie = function (key, value, expirationDate) {
|
||||
var cookie = key + '=' + value + '; '
|
||||
+ 'expires=' + expirationDate.toUTCString() + '; ';
|
||||
document.cookie = cookie;
|
||||
}
|
||||
};
|
||||
|
||||
function createCallbackStorage() {
|
||||
try {
|
||||
return new LocalStorage();
|
||||
} catch (err) {
|
||||
}
|
||||
|
||||
return new CookieStorage();
|
||||
}
|
||||
|
||||
var CallbackParser = function(uriToParse, responseMode) {
|
||||
@@ -1159,7 +1097,7 @@
|
||||
}
|
||||
|
||||
var handleQueryParam = function(paramName, paramValue, oauth) {
|
||||
var supportedOAuthParams = [ 'code', 'state', 'error', 'error_description' ];
|
||||
var supportedOAuthParams = [ 'code', 'error', 'state' ];
|
||||
|
||||
for (var i = 0 ; i< supportedOAuthParams.length ; i++) {
|
||||
if (paramName === supportedOAuthParams[i]) {
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>2.1.0.CR1</version>
|
||||
<version>1.9.3.Final</version>
|
||||
<relativePath>../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
@@ -36,32 +36,15 @@
|
||||
org.keycloak.adapters.osgi.*
|
||||
</keycloak.osgi.export>
|
||||
<keycloak.osgi.import>
|
||||
org.ops4j.pax.web.*;version="[3.0,5)",
|
||||
org.ops4j.pax.web.*;version="[3.0,4)",
|
||||
javax.servlet.*;version="[2.5,4)";resolution:=optional,
|
||||
org.eclipse.jetty.*;version="[8.1,10)";resolution:=optional,
|
||||
org.keycloak.*;version="${project.version}",
|
||||
org.apache.cxf.transport.http;resolution:=optional;version="[3,4)",
|
||||
org.apache.cxf.transport.servlet;resolution:=optional;version="[3,4)",
|
||||
*;resolution:=optional
|
||||
</keycloak.osgi.import>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-core</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-adapter-core</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-adapter-spi</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jboss.logging</groupId>
|
||||
<artifactId>jboss-logging</artifactId>
|
||||
@@ -82,23 +65,12 @@
|
||||
<artifactId>pax-web-runtime</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.ops4j.pax.web</groupId>
|
||||
<artifactId>pax-web-api</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-security</artifactId>
|
||||
<version>${jetty9.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.cxf</groupId>
|
||||
<artifactId>cxf-rt-transports-http</artifactId>
|
||||
<version>${cxf.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
||||
-71
@@ -1,71 +0,0 @@
|
||||
/*
|
||||
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||
* and other contributors as indicated by the @author tags.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.keycloak.adapters.osgi;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.keycloak.adapters.KeycloakConfigResolver;
|
||||
import org.keycloak.adapters.KeycloakDeployment;
|
||||
import org.keycloak.adapters.KeycloakDeploymentBuilder;
|
||||
import org.keycloak.adapters.OIDCHttpFacade;
|
||||
|
||||
public class PathBasedKeycloakConfigResolver implements KeycloakConfigResolver {
|
||||
|
||||
private final Map<String, KeycloakDeployment> cache = new ConcurrentHashMap<String, KeycloakDeployment>();
|
||||
|
||||
@Override
|
||||
public KeycloakDeployment resolve(OIDCHttpFacade.Request request) {
|
||||
String path = request.getURI();
|
||||
String[] urlTokens = path.split("/");
|
||||
if (urlTokens.length < 4) {
|
||||
throw new IllegalStateException("Not able to determine the web-context to load the correspondent keycloak.json file");
|
||||
}
|
||||
|
||||
String webContext = urlTokens[3];
|
||||
|
||||
KeycloakDeployment deployment = cache.get(webContext);
|
||||
if (null == deployment) {
|
||||
// not found on the simple cache, try to load it from the file system
|
||||
String keycloakConfig = (String) System.getProperties().get("keycloak.config");
|
||||
if(keycloakConfig == null || "".equals(keycloakConfig.trim())){
|
||||
String karafEtc = (String) System.getProperties().get("karaf.etc");
|
||||
if(karafEtc == null || "".equals(karafEtc.trim())){
|
||||
throw new IllegalStateException("Neither \"keycloak.config\" nor \"karaf.etc\" java properties are set. Please set one of them.");
|
||||
}
|
||||
keycloakConfig = karafEtc;
|
||||
}
|
||||
|
||||
String absolutePath = keycloakConfig + File.separator + webContext + "-keycloak.json";
|
||||
InputStream is = null;
|
||||
try {
|
||||
is = new FileInputStream(absolutePath);
|
||||
} catch (FileNotFoundException e){
|
||||
throw new IllegalStateException("Not able to find the file " + absolutePath);
|
||||
}
|
||||
deployment = KeycloakDeploymentBuilder.build(is);
|
||||
cache.put(webContext, deployment);
|
||||
}
|
||||
|
||||
return deployment;
|
||||
}
|
||||
|
||||
}
|
||||
+27
-113
@@ -18,22 +18,15 @@
|
||||
package org.keycloak.adapters.osgi;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Dictionary;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Hashtable;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
|
||||
import javax.servlet.Servlet;
|
||||
|
||||
import org.apache.cxf.transport.http.DestinationRegistry;
|
||||
import org.apache.cxf.transport.servlet.CXFNonSpringServlet;
|
||||
import org.jboss.logging.Logger;
|
||||
import org.ops4j.pax.web.service.WebContainer;
|
||||
import org.osgi.framework.BundleContext;
|
||||
import org.osgi.framework.ServiceReference;
|
||||
import org.osgi.service.cm.Configuration;
|
||||
import org.osgi.service.cm.ConfigurationAdmin;
|
||||
import org.osgi.service.http.HttpContext;
|
||||
import org.osgi.util.tracker.ServiceTracker;
|
||||
import org.osgi.util.tracker.ServiceTrackerCustomizer;
|
||||
@@ -49,15 +42,13 @@ import org.osgi.util.tracker.ServiceTrackerCustomizer;
|
||||
*/
|
||||
public class ServletReregistrationService {
|
||||
|
||||
private static final String CXF_SERVLET_PREFIX = "org.apache.cxf.servlet.";
|
||||
protected static final Logger log = Logger.getLogger(ServletReregistrationService.class);
|
||||
|
||||
private static final List<String> FILTERED_PROPERTIES = Arrays.asList("objectClass", "service.id");
|
||||
|
||||
private BundleContext bundleContext;
|
||||
private ServiceReference managedServiceReference;
|
||||
private ServiceReference servletReference;
|
||||
private ServiceTracker webContainerTracker;
|
||||
private String alias;
|
||||
|
||||
public BundleContext getBundleContext() {
|
||||
return bundleContext;
|
||||
@@ -67,18 +58,24 @@ public class ServletReregistrationService {
|
||||
this.bundleContext = bundleContext;
|
||||
}
|
||||
|
||||
public ServiceReference getServletReference() {
|
||||
return servletReference;
|
||||
}
|
||||
|
||||
public void setServletReference(ServiceReference servletReference) {
|
||||
this.servletReference = servletReference;
|
||||
}
|
||||
|
||||
protected ServiceTracker getWebContainerTracker() {
|
||||
return webContainerTracker;
|
||||
}
|
||||
|
||||
public void start() {
|
||||
if ( managedServiceReference == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Dictionary properties = obtainProperties();
|
||||
alias = (String)getProp(properties, CXF_SERVLET_PREFIX + "context", "/cxf");
|
||||
if(alias == null){
|
||||
alias = "/cxf";
|
||||
if (servletReference == null) {
|
||||
throw new IllegalStateException("No servlet reference provided");
|
||||
}
|
||||
|
||||
final Servlet servlet = (Servlet) bundleContext.getService(servletReference);
|
||||
WebContainer externalWebContainer = findExternalWebContainer();
|
||||
if (externalWebContainer == null) {
|
||||
return;
|
||||
@@ -86,19 +83,18 @@ public class ServletReregistrationService {
|
||||
|
||||
// Unregister servlet from external container now
|
||||
try {
|
||||
externalWebContainer.unregister(alias);
|
||||
externalWebContainer.unregisterServlet(servlet);
|
||||
log.debug("Original servlet with alias " + getAlias() + " unregistered successfully from external web container.");
|
||||
} catch (IllegalStateException e) {
|
||||
log.warn("Can't unregister servlet due to: " + e.getMessage());
|
||||
}
|
||||
|
||||
final Dictionary finalProperties = properties;
|
||||
ServiceTrackerCustomizer trackerCustomizer = new ServiceTrackerCustomizer() {
|
||||
|
||||
@Override
|
||||
public Object addingService(ServiceReference webContainerServiceReference) {
|
||||
WebContainer ourWebContainer = (WebContainer) bundleContext.getService(webContainerServiceReference);
|
||||
registerServlet(ourWebContainer, finalProperties);
|
||||
registerServlet(ourWebContainer, servlet);
|
||||
log.debugv("Servlet with alias " + getAlias() + " registered to secured web container");
|
||||
return ourWebContainer;
|
||||
}
|
||||
@@ -126,82 +122,28 @@ public class ServletReregistrationService {
|
||||
|
||||
// Re-register servlet back to original context
|
||||
WebContainer externalWebContainer = findExternalWebContainer();
|
||||
registerServlet(externalWebContainer, obtainProperties());
|
||||
Servlet servlet = (Servlet) bundleContext.getService(servletReference);
|
||||
registerServlet(externalWebContainer, servlet);
|
||||
log.debug("Servlet with alias " + getAlias() + " registered back to external web container");
|
||||
}
|
||||
|
||||
private String getAlias() {
|
||||
return alias;
|
||||
return (String) servletReference.getProperty("alias");
|
||||
}
|
||||
|
||||
/**
|
||||
* Code comes from org.apache.cxf.transport.http.osgi.ServletExporter#updated(java.util.Dictionary)
|
||||
* @param webContainer
|
||||
* @param properties
|
||||
*/
|
||||
protected void registerServlet(WebContainer webContainer, Dictionary properties) {
|
||||
HttpContext httpContext = webContainer.createDefaultHttpContext();
|
||||
|
||||
ServiceReference destinationServiceServiceReference = bundleContext.getServiceReference("org.apache.cxf.transport.http.DestinationRegistry");
|
||||
DestinationRegistry destinationRegistry = (DestinationRegistry) bundleContext.getService(destinationServiceServiceReference);
|
||||
|
||||
Servlet servlet = new CXFNonSpringServlet(destinationRegistry, false);
|
||||
protected void registerServlet(WebContainer webContainer, Servlet servlet) {
|
||||
try {
|
||||
if (properties == null) {
|
||||
properties = new Properties();
|
||||
}
|
||||
Properties sprops = new Properties();
|
||||
sprops.put("init-prefix",
|
||||
getProp(properties, CXF_SERVLET_PREFIX + "init-prefix", ""));
|
||||
sprops.put("servlet-name",
|
||||
getProp(properties, CXF_SERVLET_PREFIX + "name", "cxf-osgi-transport-servlet"));
|
||||
sprops.put("hide-service-list-page",
|
||||
getProp(properties, CXF_SERVLET_PREFIX + "hide-service-list-page", "false"));
|
||||
sprops.put("disable-address-updates",
|
||||
getProp(properties, CXF_SERVLET_PREFIX + "disable-address-updates", "true"));
|
||||
sprops.put("base-address",
|
||||
getProp(properties, CXF_SERVLET_PREFIX + "base-address", ""));
|
||||
sprops.put("service-list-path",
|
||||
getProp(properties, CXF_SERVLET_PREFIX + "service-list-path", ""));
|
||||
sprops.put("static-resources-list",
|
||||
getProp(properties, CXF_SERVLET_PREFIX + "static-resources-list", ""));
|
||||
sprops.put("redirects-list",
|
||||
getProp(properties, CXF_SERVLET_PREFIX + "redirects-list", ""));
|
||||
sprops.put("redirect-servlet-name",
|
||||
getProp(properties, CXF_SERVLET_PREFIX + "redirect-servlet-name", ""));
|
||||
sprops.put("redirect-servlet-path",
|
||||
getProp(properties, CXF_SERVLET_PREFIX + "redirect-servlet-path", ""));
|
||||
sprops.put("service-list-all-contexts",
|
||||
getProp(properties, CXF_SERVLET_PREFIX + "service-list-all-contexts", ""));
|
||||
sprops.put("service-list-page-authenticate",
|
||||
getProp(properties, CXF_SERVLET_PREFIX + "service-list-page-authenticate", "false"));
|
||||
sprops.put("service-list-page-authenticate-realm",
|
||||
getProp(properties, CXF_SERVLET_PREFIX + "service-list-page-authenticate-realm", "karaf"));
|
||||
sprops.put("use-x-forwarded-headers",
|
||||
getProp(properties, CXF_SERVLET_PREFIX + "use-x-forwarded-headers", "false"));
|
||||
|
||||
// Accept extra properties by default, can be disabled if it is really needed
|
||||
if (Boolean.valueOf(getProp(properties, CXF_SERVLET_PREFIX + "support.extra.properties", "true").toString())) {
|
||||
Enumeration keys = properties.keys();
|
||||
while (keys.hasMoreElements()) {
|
||||
String nextKey = keys.nextElement().toString();
|
||||
if (!nextKey.startsWith(CXF_SERVLET_PREFIX)) {
|
||||
sprops.put(nextKey, properties.get(nextKey));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Hashtable<String, Object> servletInitParams = new Hashtable<String, Object>();
|
||||
Enumeration keys = sprops.keys();
|
||||
|
||||
while(keys.hasMoreElements()){
|
||||
String propName = (String) keys.nextElement();
|
||||
String[] propNames = servletReference.getPropertyKeys();
|
||||
for (String propName : propNames) {
|
||||
if (!FILTERED_PROPERTIES.contains(propName)) {
|
||||
servletInitParams.put(propName, sprops.getProperty(propName));
|
||||
servletInitParams.put(propName, servletReference.getProperty(propName));
|
||||
}
|
||||
}
|
||||
|
||||
// Try to register servlet in given web container now
|
||||
HttpContext httpContext = webContainer.createDefaultHttpContext();
|
||||
String alias = (String) servletReference.getProperty("alias");
|
||||
webContainer.registerServlet(alias, servlet, servletInitParams, httpContext);
|
||||
} catch (Exception e) {
|
||||
log.error("Can't register servlet in web container", e);
|
||||
@@ -214,7 +156,7 @@ public class ServletReregistrationService {
|
||||
* @return web container or null
|
||||
*/
|
||||
protected WebContainer findExternalWebContainer() {
|
||||
BundleContext servletBundleContext = managedServiceReference.getBundle().getBundleContext();
|
||||
BundleContext servletBundleContext = servletReference.getBundle().getBundleContext();
|
||||
ServiceReference webContainerReference = servletBundleContext.getServiceReference(WebContainer.class.getName());
|
||||
if (webContainerReference == null) {
|
||||
log.warn("Not found webContainer reference for bundle " + servletBundleContext);
|
||||
@@ -224,32 +166,4 @@ public class ServletReregistrationService {
|
||||
}
|
||||
}
|
||||
|
||||
private Dictionary obtainProperties(){
|
||||
Dictionary properties = null;
|
||||
ServiceReference reference = bundleContext.getServiceReference(ConfigurationAdmin.class.getName());
|
||||
ConfigurationAdmin admin = (ConfigurationAdmin) bundleContext.getService(reference);
|
||||
try {
|
||||
Configuration configuration = admin.getConfiguration("org.apache.cxf.osgi");
|
||||
properties = configuration.getProperties();
|
||||
} catch (Exception e){
|
||||
log.warn("Unable to obtain cxf osgi configadmin reference.", e);
|
||||
}
|
||||
return properties;
|
||||
}
|
||||
|
||||
private Object getProp(Dictionary properties, String key, Object defaultValue) {
|
||||
Object value = null;
|
||||
if(properties != null){
|
||||
value = properties.get(key);
|
||||
}
|
||||
return value == null ? defaultValue : value;
|
||||
}
|
||||
|
||||
public ServiceReference getManagedServiceReference() {
|
||||
return managedServiceReference;
|
||||
}
|
||||
|
||||
public void setManagedServiceReference(ServiceReference managedServiceReference) {
|
||||
this.managedServiceReference = managedServiceReference;
|
||||
}
|
||||
}
|
||||
@@ -20,7 +20,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>2.1.0.CR1</version>
|
||||
<version>1.9.3.Final</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<name>Keycloak OIDC Client Adapter Modules</name>
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>2.1.0.CR1</version>
|
||||
<version>1.9.3.Final</version>
|
||||
<relativePath>../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
+2
-2
@@ -19,12 +19,12 @@ package org.keycloak.adapters.servlet;
|
||||
|
||||
import org.keycloak.KeycloakSecurityContext;
|
||||
import org.keycloak.adapters.AdapterTokenStore;
|
||||
import org.keycloak.adapters.spi.HttpFacade;
|
||||
import org.keycloak.adapters.spi.KeycloakAccount;
|
||||
import org.keycloak.adapters.KeycloakDeployment;
|
||||
import org.keycloak.adapters.OidcKeycloakAccount;
|
||||
import org.keycloak.adapters.RefreshableKeycloakSecurityContext;
|
||||
import org.keycloak.adapters.RequestAuthenticator;
|
||||
import org.keycloak.adapters.spi.HttpFacade;
|
||||
import org.keycloak.adapters.spi.KeycloakAccount;
|
||||
import org.keycloak.adapters.spi.SessionIdMapper;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>2.1.0.CR1</version>
|
||||
<version>1.9.3.Final</version>
|
||||
<relativePath>../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
+4
-5
@@ -30,7 +30,6 @@ import org.keycloak.jose.jws.JWSInputException;
|
||||
import org.keycloak.representations.AccessTokenResponse;
|
||||
import org.keycloak.representations.IDToken;
|
||||
import org.keycloak.common.util.KeycloakUriBuilder;
|
||||
import org.keycloak.util.TokenUtil;
|
||||
|
||||
import javax.security.cert.X509Certificate;
|
||||
import javax.servlet.http.Cookie;
|
||||
@@ -92,15 +91,15 @@ public class ServletOAuthClient extends KeycloakDeploymentDelegateOAuthClient {
|
||||
String state = getStateCode();
|
||||
KeycloakDeployment resolvedDeployment = resolveDeployment(getDeployment(), request);
|
||||
String authUrl = resolvedDeployment.getAuthUrl().clone().build().toString();
|
||||
String scopeParam = TokenUtil.attachOIDCScope(scope);
|
||||
|
||||
KeycloakUriBuilder uriBuilder = KeycloakUriBuilder.fromUri(authUrl)
|
||||
.queryParam(OAuth2Constants.RESPONSE_TYPE, OAuth2Constants.CODE)
|
||||
.queryParam(OAuth2Constants.CLIENT_ID, getClientId())
|
||||
.queryParam(OAuth2Constants.REDIRECT_URI, redirectUri)
|
||||
.queryParam(OAuth2Constants.STATE, state)
|
||||
.queryParam(OAuth2Constants.SCOPE, scopeParam);
|
||||
|
||||
.queryParam(OAuth2Constants.STATE, state);
|
||||
if (scope != null) {
|
||||
uriBuilder.queryParam(OAuth2Constants.SCOPE, scope);
|
||||
}
|
||||
URI url = uriBuilder.build();
|
||||
|
||||
String stateCookiePath = this.stateCookiePath;
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>2.1.0.CR1</version>
|
||||
<version>1.9.3.Final</version>
|
||||
<relativePath>../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
@@ -67,45 +67,6 @@
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-server</artifactId>
|
||||
<version>${jetty9.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-security</artifactId>
|
||||
<version>${jetty9.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-webapp</artifactId>
|
||||
<version>${jetty9.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.undertow</groupId>
|
||||
<artifactId>undertow-servlet</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.undertow</groupId>
|
||||
<artifactId>undertow-core</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-undertow-adapter-spi</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
|
||||
+51
-197
@@ -17,38 +17,24 @@
|
||||
|
||||
package org.keycloak.adapters.springboot;
|
||||
|
||||
import io.undertow.servlet.api.DeploymentInfo;
|
||||
import io.undertow.servlet.api.WebResourceCollection;
|
||||
import org.apache.catalina.Context;
|
||||
import org.apache.tomcat.util.descriptor.web.LoginConfig;
|
||||
import org.apache.tomcat.util.descriptor.web.SecurityCollection;
|
||||
import org.apache.tomcat.util.descriptor.web.SecurityConstraint;
|
||||
import org.eclipse.jetty.security.ConstraintMapping;
|
||||
import org.eclipse.jetty.security.ConstraintSecurityHandler;
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.util.security.Constraint;
|
||||
import org.eclipse.jetty.webapp.WebAppContext;
|
||||
import org.keycloak.adapters.jetty.KeycloakJettyAuthenticator;
|
||||
import org.keycloak.adapters.tomcat.KeycloakAuthenticatorValve;
|
||||
import org.keycloak.adapters.undertow.KeycloakServletExtension;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
|
||||
import org.springframework.boot.context.embedded.ConfigurableEmbeddedServletContainer;
|
||||
import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizer;
|
||||
import org.springframework.boot.context.embedded.jetty.JettyEmbeddedServletContainerFactory;
|
||||
import org.springframework.boot.context.embedded.jetty.JettyServerCustomizer;
|
||||
import org.springframework.boot.context.embedded.tomcat.TomcatContextCustomizer;
|
||||
import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory;
|
||||
import org.springframework.boot.context.embedded.undertow.UndertowDeploymentInfoCustomizer;
|
||||
import org.springframework.boot.context.embedded.undertow.UndertowEmbeddedServletContainerFactory;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
@@ -75,212 +61,80 @@ public class KeycloakSpringBootConfiguration {
|
||||
return new EmbeddedServletContainerCustomizer() {
|
||||
@Override
|
||||
public void customize(ConfigurableEmbeddedServletContainer configurableEmbeddedServletContainer) {
|
||||
|
||||
if (configurableEmbeddedServletContainer instanceof TomcatEmbeddedServletContainerFactory) {
|
||||
|
||||
TomcatEmbeddedServletContainerFactory container = (TomcatEmbeddedServletContainerFactory) configurableEmbeddedServletContainer;
|
||||
|
||||
container.addContextValves(new KeycloakAuthenticatorValve());
|
||||
container.addContextCustomizers(tomcatKeycloakContextCustomizer());
|
||||
|
||||
container.addContextCustomizers(getTomcatKeycloakContextCustomizer());
|
||||
} else if (configurableEmbeddedServletContainer instanceof UndertowEmbeddedServletContainerFactory) {
|
||||
|
||||
UndertowEmbeddedServletContainerFactory container = (UndertowEmbeddedServletContainerFactory) configurableEmbeddedServletContainer;
|
||||
container.addDeploymentInfoCustomizers(undertowKeycloakContextCustomizer());
|
||||
|
||||
throw new IllegalArgumentException("Undertow Keycloak integration is not yet implemented");
|
||||
} else if (configurableEmbeddedServletContainer instanceof JettyEmbeddedServletContainerFactory) {
|
||||
|
||||
JettyEmbeddedServletContainerFactory container = (JettyEmbeddedServletContainerFactory) configurableEmbeddedServletContainer;
|
||||
container.addServerCustomizers(jettyKeycloakServerCustomizer());
|
||||
throw new IllegalArgumentException("Jetty Keycloak integration is not yet implemented");
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnClass(name = {"org.eclipse.jetty.webapp.WebAppContext"})
|
||||
public JettyServerCustomizer jettyKeycloakServerCustomizer() {
|
||||
return new KeycloakJettyServerCustomizer(keycloakProperties);
|
||||
}
|
||||
public TomcatContextCustomizer getTomcatKeycloakContextCustomizer() {
|
||||
return new TomcatContextCustomizer() {
|
||||
@Override
|
||||
public void customize(Context context) {
|
||||
LoginConfig loginConfig = new LoginConfig();
|
||||
loginConfig.setAuthMethod("KEYCLOAK");
|
||||
context.setLoginConfig(loginConfig);
|
||||
|
||||
@Bean
|
||||
@ConditionalOnClass(name = {"org.apache.catalina.startup.Tomcat"})
|
||||
public TomcatContextCustomizer tomcatKeycloakContextCustomizer() {
|
||||
return new KeycloakTomcatContextCustomizer(keycloakProperties);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnClass(name = {"io.undertow.Undertow"})
|
||||
public UndertowDeploymentInfoCustomizer undertowKeycloakContextCustomizer() {
|
||||
return new KeycloakUndertowDeploymentInfoCustomizer(keycloakProperties);
|
||||
}
|
||||
|
||||
static class KeycloakUndertowDeploymentInfoCustomizer implements UndertowDeploymentInfoCustomizer {
|
||||
|
||||
private final KeycloakSpringBootProperties keycloakProperties;
|
||||
|
||||
public KeycloakUndertowDeploymentInfoCustomizer(KeycloakSpringBootProperties keycloakProperties) {
|
||||
this.keycloakProperties = keycloakProperties;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void customize(DeploymentInfo deploymentInfo) {
|
||||
|
||||
io.undertow.servlet.api.LoginConfig loginConfig = new io.undertow.servlet.api.LoginConfig(keycloakProperties.getRealm());
|
||||
loginConfig.addFirstAuthMethod("KEYCLOAK");
|
||||
|
||||
deploymentInfo.setLoginConfig(loginConfig);
|
||||
|
||||
deploymentInfo.addInitParameter("keycloak.config.resolver", KeycloakSpringBootConfigResolver.class.getName());
|
||||
deploymentInfo.addSecurityConstraints(getSecurityConstraints());
|
||||
|
||||
deploymentInfo.addServletExtension(new KeycloakServletExtension());
|
||||
}
|
||||
|
||||
private List<io.undertow.servlet.api.SecurityConstraint> getSecurityConstraints() {
|
||||
|
||||
List<io.undertow.servlet.api.SecurityConstraint> undertowSecurityConstraints = new ArrayList<io.undertow.servlet.api.SecurityConstraint>();
|
||||
for (KeycloakSpringBootProperties.SecurityConstraint constraintDefinition : keycloakProperties.getSecurityConstraints()) {
|
||||
|
||||
for (KeycloakSpringBootProperties.SecurityCollection collectionDefinition : constraintDefinition.getSecurityCollections()) {
|
||||
|
||||
io.undertow.servlet.api.SecurityConstraint undertowSecurityConstraint = new io.undertow.servlet.api.SecurityConstraint();
|
||||
undertowSecurityConstraint.addRolesAllowed(collectionDefinition.getAuthRoles());
|
||||
|
||||
WebResourceCollection webResourceCollection = new WebResourceCollection();
|
||||
webResourceCollection.addHttpMethods(collectionDefinition.getMethods());
|
||||
webResourceCollection.addHttpMethodOmissions(collectionDefinition.getOmittedMethods());
|
||||
webResourceCollection.addUrlPatterns(collectionDefinition.getPatterns());
|
||||
|
||||
undertowSecurityConstraint.addWebResourceCollections(webResourceCollection);
|
||||
|
||||
undertowSecurityConstraints.add(undertowSecurityConstraint);
|
||||
}
|
||||
}
|
||||
return undertowSecurityConstraints;
|
||||
}
|
||||
}
|
||||
|
||||
static class KeycloakJettyServerCustomizer implements JettyServerCustomizer {
|
||||
|
||||
private final KeycloakSpringBootProperties keycloakProperties;
|
||||
|
||||
public KeycloakJettyServerCustomizer(KeycloakSpringBootProperties keycloakProperties) {
|
||||
this.keycloakProperties = keycloakProperties;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void customize(Server server) {
|
||||
|
||||
KeycloakJettyAuthenticator keycloakJettyAuthenticator = new KeycloakJettyAuthenticator();
|
||||
keycloakJettyAuthenticator.setConfigResolver(new KeycloakSpringBootConfigResolver());
|
||||
|
||||
List<ConstraintMapping> jettyConstraintMappings = new ArrayList<ConstraintMapping>();
|
||||
for (KeycloakSpringBootProperties.SecurityConstraint constraintDefinition : keycloakProperties.getSecurityConstraints()) {
|
||||
|
||||
for (KeycloakSpringBootProperties.SecurityCollection securityCollectionDefinition : constraintDefinition
|
||||
.getSecurityCollections()) {
|
||||
|
||||
Constraint jettyConstraint = new Constraint();
|
||||
jettyConstraint.setName(securityCollectionDefinition.getName());
|
||||
jettyConstraint.setAuthenticate(true);
|
||||
|
||||
if (securityCollectionDefinition.getName() != null) {
|
||||
jettyConstraint.setName(securityCollectionDefinition.getName());
|
||||
}
|
||||
|
||||
jettyConstraint.setRoles(securityCollectionDefinition.getAuthRoles().toArray(new String[0]));
|
||||
|
||||
ConstraintMapping jettyConstraintMapping = new ConstraintMapping();
|
||||
if (securityCollectionDefinition.getPatterns().size() > 0) {
|
||||
//First pattern wins
|
||||
jettyConstraintMapping.setPathSpec(securityCollectionDefinition.getPatterns().get(0));
|
||||
jettyConstraintMapping.setConstraint(jettyConstraint);
|
||||
}
|
||||
|
||||
if (securityCollectionDefinition.getMethods().size() > 0) {
|
||||
//First method wins
|
||||
jettyConstraintMapping.setMethod(securityCollectionDefinition.getMethods().get(0));
|
||||
}
|
||||
|
||||
jettyConstraintMapping.setMethodOmissions(
|
||||
securityCollectionDefinition.getOmittedMethods().toArray(new String[0]));
|
||||
|
||||
jettyConstraintMappings.add(jettyConstraintMapping);
|
||||
}
|
||||
}
|
||||
|
||||
WebAppContext webAppContext = server.getBean(WebAppContext.class);
|
||||
|
||||
ConstraintSecurityHandler securityHandler = new ConstraintSecurityHandler();
|
||||
securityHandler.setConstraintMappings(jettyConstraintMappings);
|
||||
securityHandler.setAuthenticator(keycloakJettyAuthenticator);
|
||||
|
||||
webAppContext.setHandler(securityHandler);
|
||||
}
|
||||
}
|
||||
|
||||
static class KeycloakTomcatContextCustomizer implements TomcatContextCustomizer {
|
||||
|
||||
private final KeycloakSpringBootProperties keycloakProperties;
|
||||
|
||||
public KeycloakTomcatContextCustomizer(KeycloakSpringBootProperties keycloakProperties) {
|
||||
this.keycloakProperties = keycloakProperties;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void customize(Context context) {
|
||||
LoginConfig loginConfig = new LoginConfig();
|
||||
loginConfig.setAuthMethod("KEYCLOAK");
|
||||
context.setLoginConfig(loginConfig);
|
||||
|
||||
Set<String> authRoles = new HashSet<String>();
|
||||
for (KeycloakSpringBootProperties.SecurityConstraint constraint : keycloakProperties.getSecurityConstraints()) {
|
||||
for (KeycloakSpringBootProperties.SecurityCollection collection : constraint.getSecurityCollections()) {
|
||||
for (String authRole : collection.getAuthRoles()) {
|
||||
if (!authRoles.contains(authRole)) {
|
||||
context.addSecurityRole(authRole);
|
||||
authRoles.add(authRole);
|
||||
Set<String> authRoles = new HashSet<String>();
|
||||
for (KeycloakSpringBootProperties.SecurityConstraint constraint : keycloakProperties.getSecurityConstraints()) {
|
||||
for (KeycloakSpringBootProperties.SecurityCollection collection : constraint.getSecurityCollections()) {
|
||||
for (String authRole : collection.getAuthRoles()) {
|
||||
if (!authRoles.contains(authRole)) {
|
||||
context.addSecurityRole(authRole);
|
||||
authRoles.add(authRole);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (KeycloakSpringBootProperties.SecurityConstraint constraint : keycloakProperties.getSecurityConstraints()) {
|
||||
SecurityConstraint tomcatConstraint = new SecurityConstraint();
|
||||
for (KeycloakSpringBootProperties.SecurityConstraint constraint : keycloakProperties.getSecurityConstraints()) {
|
||||
SecurityConstraint tomcatConstraint = new SecurityConstraint();
|
||||
|
||||
for (KeycloakSpringBootProperties.SecurityCollection collection : constraint.getSecurityCollections()) {
|
||||
SecurityCollection tomcatSecCollection = new SecurityCollection();
|
||||
for (KeycloakSpringBootProperties.SecurityCollection collection : constraint.getSecurityCollections()) {
|
||||
SecurityCollection tomcatSecCollection = new SecurityCollection();
|
||||
|
||||
if (collection.getName() != null) {
|
||||
tomcatSecCollection.setName(collection.getName());
|
||||
}
|
||||
if (collection.getDescription() != null) {
|
||||
tomcatSecCollection.setDescription(collection.getDescription());
|
||||
if (collection.getName() != null) {
|
||||
tomcatSecCollection.setName(collection.getName());
|
||||
}
|
||||
if (collection.getDescription() != null) {
|
||||
tomcatSecCollection.setDescription(collection.getDescription());
|
||||
}
|
||||
|
||||
for (String authRole : collection.getAuthRoles()) {
|
||||
tomcatConstraint.addAuthRole(authRole);
|
||||
}
|
||||
|
||||
for (String pattern : collection.getPatterns()) {
|
||||
tomcatSecCollection.addPattern(pattern);
|
||||
}
|
||||
|
||||
for (String method : collection.getMethods()) {
|
||||
tomcatSecCollection.addMethod(method);
|
||||
}
|
||||
|
||||
for (String method : collection.getOmittedMethods()) {
|
||||
tomcatSecCollection.addOmittedMethod(method);
|
||||
}
|
||||
|
||||
tomcatConstraint.addCollection(tomcatSecCollection);
|
||||
}
|
||||
|
||||
for (String authRole : collection.getAuthRoles()) {
|
||||
tomcatConstraint.addAuthRole(authRole);
|
||||
}
|
||||
|
||||
for (String pattern : collection.getPatterns()) {
|
||||
tomcatSecCollection.addPattern(pattern);
|
||||
}
|
||||
|
||||
for (String method : collection.getMethods()) {
|
||||
tomcatSecCollection.addMethod(method);
|
||||
}
|
||||
|
||||
for (String method : collection.getOmittedMethods()) {
|
||||
tomcatSecCollection.addOmittedMethod(method);
|
||||
}
|
||||
|
||||
tomcatConstraint.addCollection(tomcatSecCollection);
|
||||
context.addConstraint(tomcatConstraint);
|
||||
}
|
||||
|
||||
context.addConstraint(tomcatConstraint);
|
||||
context.addParameter("keycloak.config.resolver", KeycloakSpringBootConfigResolver.class.getName());
|
||||
}
|
||||
|
||||
context.addParameter("keycloak.config.resolver", KeycloakSpringBootConfigResolver.class.getName());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
@@ -21,7 +21,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>2.1.0.CR1</version>
|
||||
<version>1.9.3.Final</version>
|
||||
<relativePath>../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
@@ -71,13 +71,6 @@
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
<version>${slf4j.version}</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jboss.logging</groupId>
|
||||
<artifactId>jboss-logging</artifactId>
|
||||
<version>${jboss.logging.version}</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
@@ -128,6 +121,12 @@
|
||||
<version>${slf4j.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jboss.logging</groupId>
|
||||
<artifactId>jboss-logging</artifactId>
|
||||
<version>${jboss.logging.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>2.1.0.CR1</version>
|
||||
<version>1.9.3.Final</version>
|
||||
<relativePath>../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<name>Keycloak Tomcat Integration</name>
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-tomcat-integration-pom</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>2.1.0.CR1</version>
|
||||
<version>1.9.3.Final</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
@@ -77,13 +77,6 @@
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-annotations</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Authorization -->
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-authz-client</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!--
|
||||
<dependency>
|
||||
<groupId>org.apache.tomcat</groupId>
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-tomcat-integration-pom</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>2.1.0.CR1</version>
|
||||
<version>1.9.3.Final</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
@@ -43,7 +43,7 @@
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-adapter-core</artifactId>
|
||||
</dependency>
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-tomcat-integration-pom</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>2.1.0.CR1</version>
|
||||
<version>1.9.3.Final</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
@@ -44,7 +44,7 @@
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-adapter-core</artifactId>
|
||||
</dependency>
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-tomcat-integration-pom</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>2.1.0.CR1</version>
|
||||
<version>1.9.3.Final</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
@@ -43,7 +43,7 @@
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-adapter-core</artifactId>
|
||||
</dependency>
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>2.1.0.CR1</version>
|
||||
<version>1.9.3.Final</version>
|
||||
<relativePath>../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
+2
-2
@@ -17,16 +17,16 @@
|
||||
package org.keycloak.adapters.undertow;
|
||||
|
||||
import io.undertow.server.HttpServerExchange;
|
||||
import io.undertow.util.AttachmentKey;
|
||||
import org.keycloak.KeycloakSecurityContext;
|
||||
import org.keycloak.adapters.OIDCHttpFacade;
|
||||
|
||||
import static org.keycloak.adapters.undertow.OIDCUndertowHttpFacade.KEYCLOAK_SECURITY_CONTEXT_KEY;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class OIDCServletUndertowHttpFacade extends ServletHttpFacade implements OIDCHttpFacade {
|
||||
public static final AttachmentKey<KeycloakSecurityContext> KEYCLOAK_SECURITY_CONTEXT_KEY = AttachmentKey.create(KeycloakSecurityContext.class);
|
||||
|
||||
public OIDCServletUndertowHttpFacade(HttpServerExchange exchange) {
|
||||
super(exchange);
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>2.1.0.CR1</version>
|
||||
<version>1.9.3.Final</version>
|
||||
<relativePath>../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<name>Keycloak WildFly Integration</name>
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<parent>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<version>2.1.0.CR1</version>
|
||||
<version>1.9.3.Final</version>
|
||||
<relativePath>../../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
||||
+10
-8
@@ -46,7 +46,8 @@ public class KeycloakAdapterConfigDeploymentProcessor implements DeploymentUnitP
|
||||
|
||||
// not sure if we need this yet, keeping here just in case
|
||||
protected void addSecurityDomain(DeploymentUnit deploymentUnit, KeycloakAdapterConfigService service) {
|
||||
if (!service.isSecureDeployment(deploymentUnit)) {
|
||||
String deploymentName = deploymentUnit.getName();
|
||||
if (!service.isSecureDeployment(deploymentName)) {
|
||||
return;
|
||||
}
|
||||
WarMetaData warMetaData = deploymentUnit.getAttachment(WarMetaData.ATTACHMENT_KEY);
|
||||
@@ -66,9 +67,10 @@ public class KeycloakAdapterConfigDeploymentProcessor implements DeploymentUnitP
|
||||
public void deploy(DeploymentPhaseContext phaseContext) throws DeploymentUnitProcessingException {
|
||||
DeploymentUnit deploymentUnit = phaseContext.getDeploymentUnit();
|
||||
|
||||
String deploymentName = deploymentUnit.getName();
|
||||
KeycloakAdapterConfigService service = KeycloakAdapterConfigService.getInstance();
|
||||
if (service.isSecureDeployment(deploymentUnit)) {
|
||||
addKeycloakAuthData(phaseContext, service);
|
||||
if (service.isSecureDeployment(deploymentName)) {
|
||||
addKeycloakAuthData(phaseContext, deploymentName, service);
|
||||
}
|
||||
|
||||
// FYI, Undertow Extension will find deployments that have auth-method set to KEYCLOAK
|
||||
@@ -77,14 +79,14 @@ public class KeycloakAdapterConfigDeploymentProcessor implements DeploymentUnitP
|
||||
// addSecurityDomain(deploymentUnit, service);
|
||||
}
|
||||
|
||||
private void addKeycloakAuthData(DeploymentPhaseContext phaseContext, KeycloakAdapterConfigService service) throws DeploymentUnitProcessingException {
|
||||
private void addKeycloakAuthData(DeploymentPhaseContext phaseContext, String deploymentName, KeycloakAdapterConfigService service) throws DeploymentUnitProcessingException {
|
||||
DeploymentUnit deploymentUnit = phaseContext.getDeploymentUnit();
|
||||
WarMetaData warMetaData = deploymentUnit.getAttachment(WarMetaData.ATTACHMENT_KEY);
|
||||
if (warMetaData == null) {
|
||||
throw new DeploymentUnitProcessingException("WarMetaData not found for " + deploymentUnit.getName() + ". Make sure you have specified a WAR as your secure-deployment in the Keycloak subsystem.");
|
||||
throw new DeploymentUnitProcessingException("WarMetaData not found for " + deploymentName + ". Make sure you have specified a WAR as your secure-deployment in the Keycloak subsystem.");
|
||||
}
|
||||
|
||||
addJSONData(service.getJSON(deploymentUnit), warMetaData);
|
||||
addJSONData(service.getJSON(deploymentName), warMetaData);
|
||||
JBossWebMetaData webMetaData = warMetaData.getMergedJBossWebMetaData();
|
||||
if (webMetaData == null) {
|
||||
webMetaData = new JBossWebMetaData();
|
||||
@@ -97,8 +99,8 @@ public class KeycloakAdapterConfigDeploymentProcessor implements DeploymentUnitP
|
||||
webMetaData.setLoginConfig(loginConfig);
|
||||
}
|
||||
loginConfig.setAuthMethod("KEYCLOAK");
|
||||
loginConfig.setRealmName(service.getRealmName(deploymentUnit));
|
||||
KeycloakLogger.ROOT_LOGGER.deploymentSecured(deploymentUnit.getName());
|
||||
loginConfig.setRealmName(service.getRealmName(deploymentName));
|
||||
KeycloakLogger.ROOT_LOGGER.deploymentSecured(deploymentName);
|
||||
}
|
||||
|
||||
private void addJSONData(String json, WarMetaData warMetaData) {
|
||||
|
||||
+3
-28
@@ -24,9 +24,6 @@ import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.ADDRESS;
|
||||
import org.jboss.as.server.deployment.DeploymentUnit;
|
||||
import org.jboss.as.web.common.WarMetaData;
|
||||
import org.jboss.metadata.web.jboss.JBossWebMetaData;
|
||||
|
||||
/**
|
||||
* This service keeps track of the entire Keycloak management model so as to provide
|
||||
@@ -156,15 +153,13 @@ public final class KeycloakAdapterConfigService {
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getRealmName(DeploymentUnit deploymentUnit) {
|
||||
String deploymentName = preferredDeploymentName(deploymentUnit);
|
||||
public String getRealmName(String deploymentName) {
|
||||
ModelNode deployment = this.secureDeployments.get(deploymentName);
|
||||
return deployment.get(RealmDefinition.TAG_NAME).asString();
|
||||
|
||||
}
|
||||
|
||||
public String getJSON(DeploymentUnit deploymentUnit) {
|
||||
String deploymentName = preferredDeploymentName(deploymentUnit);
|
||||
public String getJSON(String deploymentName) {
|
||||
ModelNode deployment = this.secureDeployments.get(deploymentName);
|
||||
String realmName = deployment.get(RealmDefinition.TAG_NAME).asString();
|
||||
ModelNode realm = this.realms.get(realmName);
|
||||
@@ -188,29 +183,9 @@ public final class KeycloakAdapterConfigService {
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isSecureDeployment(DeploymentUnit deploymentUnit) {
|
||||
public boolean isSecureDeployment(String deploymentName) {
|
||||
//log.info("********* CHECK KEYCLOAK DEPLOYMENT: deployments.size()" + deployments.size());
|
||||
|
||||
String deploymentName = preferredDeploymentName(deploymentUnit);
|
||||
return this.secureDeployments.containsKey(deploymentName);
|
||||
}
|
||||
|
||||
// KEYCLOAK-3273: prefer module name if available
|
||||
private String preferredDeploymentName(DeploymentUnit deploymentUnit) {
|
||||
String deploymentName = deploymentUnit.getName();
|
||||
WarMetaData warMetaData = deploymentUnit.getAttachment(WarMetaData.ATTACHMENT_KEY);
|
||||
if (warMetaData == null) {
|
||||
return deploymentName;
|
||||
}
|
||||
|
||||
JBossWebMetaData webMetaData = warMetaData.getMergedJBossWebMetaData();
|
||||
if (webMetaData == null) {
|
||||
return deploymentName;
|
||||
}
|
||||
|
||||
String moduleName = webMetaData.getModuleName();
|
||||
if (moduleName != null) return moduleName + ".war";
|
||||
|
||||
return deploymentName;
|
||||
}
|
||||
}
|
||||
+2
-1
@@ -46,7 +46,8 @@ public abstract class KeycloakDependencyProcessor implements DeploymentUnitProce
|
||||
public void deploy(DeploymentPhaseContext phaseContext) throws DeploymentUnitProcessingException {
|
||||
final DeploymentUnit deploymentUnit = phaseContext.getDeploymentUnit();
|
||||
|
||||
if (!KeycloakAdapterConfigService.getInstance().isSecureDeployment(deploymentUnit)) {
|
||||
String deploymentName = deploymentUnit.getName();
|
||||
if (!KeycloakAdapterConfigService.getInstance().isSecureDeployment(deploymentName)) {
|
||||
WarMetaData warMetaData = deploymentUnit.getAttachment(WarMetaData.ATTACHMENT_KEY);
|
||||
if (warMetaData == null) {
|
||||
return;
|
||||
|
||||
+2
@@ -78,6 +78,8 @@ public class SubsystemParsingTestCase extends AbstractSubsystemBaseTest {
|
||||
addCredential(addr, service, "secret", "secret1");
|
||||
addCredential(addr, service, "jwt.client-keystore-file", "/tmp/foo.jks");
|
||||
addCredential(addr, service, "jwt.token-timeout", "10");
|
||||
|
||||
System.out.println("Deployment: " + service.getJSON("foo"));
|
||||
}
|
||||
|
||||
private void addCredential(PathAddress parent, KeycloakAdapterConfigService service, String key, String value) {
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>2.1.0.CR1</version>
|
||||
<version>1.9.3.Final</version>
|
||||
<relativePath>../../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
@@ -41,7 +41,7 @@
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-adapter-spi</artifactId>
|
||||
</dependency>
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<parent>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<version>2.1.0.CR1</version>
|
||||
<version>1.9.3.Final</version>
|
||||
<relativePath>../../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
||||
+10
-8
@@ -46,7 +46,8 @@ public class KeycloakAdapterConfigDeploymentProcessor implements DeploymentUnitP
|
||||
|
||||
// not sure if we need this yet, keeping here just in case
|
||||
protected void addSecurityDomain(DeploymentUnit deploymentUnit, KeycloakAdapterConfigService service) {
|
||||
if (!service.isSecureDeployment(deploymentUnit)) {
|
||||
String deploymentName = deploymentUnit.getName();
|
||||
if (!service.isSecureDeployment(deploymentName)) {
|
||||
return;
|
||||
}
|
||||
WarMetaData warMetaData = deploymentUnit.getAttachment(WarMetaData.ATTACHMENT_KEY);
|
||||
@@ -66,9 +67,10 @@ public class KeycloakAdapterConfigDeploymentProcessor implements DeploymentUnitP
|
||||
public void deploy(DeploymentPhaseContext phaseContext) throws DeploymentUnitProcessingException {
|
||||
DeploymentUnit deploymentUnit = phaseContext.getDeploymentUnit();
|
||||
|
||||
String deploymentName = deploymentUnit.getName();
|
||||
KeycloakAdapterConfigService service = KeycloakAdapterConfigService.getInstance();
|
||||
if (service.isSecureDeployment(deploymentUnit)) {
|
||||
addKeycloakAuthData(phaseContext, service);
|
||||
if (service.isSecureDeployment(deploymentName)) {
|
||||
addKeycloakAuthData(phaseContext, deploymentName, service);
|
||||
}
|
||||
|
||||
// FYI, Undertow Extension will find deployments that have auth-method set to KEYCLOAK
|
||||
@@ -77,14 +79,14 @@ public class KeycloakAdapterConfigDeploymentProcessor implements DeploymentUnitP
|
||||
// addSecurityDomain(deploymentUnit, service);
|
||||
}
|
||||
|
||||
private void addKeycloakAuthData(DeploymentPhaseContext phaseContext, KeycloakAdapterConfigService service) throws DeploymentUnitProcessingException {
|
||||
private void addKeycloakAuthData(DeploymentPhaseContext phaseContext, String deploymentName, KeycloakAdapterConfigService service) throws DeploymentUnitProcessingException {
|
||||
DeploymentUnit deploymentUnit = phaseContext.getDeploymentUnit();
|
||||
WarMetaData warMetaData = deploymentUnit.getAttachment(WarMetaData.ATTACHMENT_KEY);
|
||||
if (warMetaData == null) {
|
||||
throw new DeploymentUnitProcessingException("WarMetaData not found for " + deploymentUnit.getName() + ". Make sure you have specified a WAR as your secure-deployment in the Keycloak subsystem.");
|
||||
throw new DeploymentUnitProcessingException("WarMetaData not found for " + deploymentName + ". Make sure you have specified a WAR as your secure-deployment in the Keycloak subsystem.");
|
||||
}
|
||||
|
||||
addJSONData(service.getJSON(deploymentUnit), warMetaData);
|
||||
addJSONData(service.getJSON(deploymentName), warMetaData);
|
||||
JBossWebMetaData webMetaData = warMetaData.getMergedJBossWebMetaData();
|
||||
if (webMetaData == null) {
|
||||
webMetaData = new JBossWebMetaData();
|
||||
@@ -97,8 +99,8 @@ public class KeycloakAdapterConfigDeploymentProcessor implements DeploymentUnitP
|
||||
webMetaData.setLoginConfig(loginConfig);
|
||||
}
|
||||
loginConfig.setAuthMethod("KEYCLOAK");
|
||||
loginConfig.setRealmName(service.getRealmName(deploymentUnit));
|
||||
KeycloakLogger.ROOT_LOGGER.deploymentSecured(deploymentUnit.getName());
|
||||
loginConfig.setRealmName(service.getRealmName(deploymentName));
|
||||
KeycloakLogger.ROOT_LOGGER.deploymentSecured(deploymentName);
|
||||
}
|
||||
|
||||
private void addJSONData(String json, WarMetaData warMetaData) {
|
||||
|
||||
+3
-28
@@ -24,9 +24,6 @@ import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.ADDRESS;
|
||||
import org.jboss.as.server.deployment.DeploymentUnit;
|
||||
import org.jboss.as.web.common.WarMetaData;
|
||||
import org.jboss.metadata.web.jboss.JBossWebMetaData;
|
||||
|
||||
/**
|
||||
* This service keeps track of the entire Keycloak management model so as to provide
|
||||
@@ -156,15 +153,13 @@ public final class KeycloakAdapterConfigService {
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getRealmName(DeploymentUnit deploymentUnit) {
|
||||
String deploymentName = preferredDeploymentName(deploymentUnit);
|
||||
public String getRealmName(String deploymentName) {
|
||||
ModelNode deployment = this.secureDeployments.get(deploymentName);
|
||||
return deployment.get(RealmDefinition.TAG_NAME).asString();
|
||||
|
||||
}
|
||||
|
||||
public String getJSON(DeploymentUnit deploymentUnit) {
|
||||
String deploymentName = preferredDeploymentName(deploymentUnit);
|
||||
public String getJSON(String deploymentName) {
|
||||
ModelNode deployment = this.secureDeployments.get(deploymentName);
|
||||
String realmName = deployment.get(RealmDefinition.TAG_NAME).asString();
|
||||
ModelNode realm = this.realms.get(realmName);
|
||||
@@ -188,29 +183,9 @@ public final class KeycloakAdapterConfigService {
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isSecureDeployment(DeploymentUnit deploymentUnit) {
|
||||
public boolean isSecureDeployment(String deploymentName) {
|
||||
//log.info("********* CHECK KEYCLOAK DEPLOYMENT: deployments.size()" + deployments.size());
|
||||
|
||||
String deploymentName = preferredDeploymentName(deploymentUnit);
|
||||
return this.secureDeployments.containsKey(deploymentName);
|
||||
}
|
||||
|
||||
// KEYCLOAK-3273: prefer module name if available
|
||||
private String preferredDeploymentName(DeploymentUnit deploymentUnit) {
|
||||
String deploymentName = deploymentUnit.getName();
|
||||
WarMetaData warMetaData = deploymentUnit.getAttachment(WarMetaData.ATTACHMENT_KEY);
|
||||
if (warMetaData == null) {
|
||||
return deploymentName;
|
||||
}
|
||||
|
||||
JBossWebMetaData webMetaData = warMetaData.getMergedJBossWebMetaData();
|
||||
if (webMetaData == null) {
|
||||
return deploymentName;
|
||||
}
|
||||
|
||||
String moduleName = webMetaData.getModuleName();
|
||||
if (moduleName != null) return moduleName + ".war";
|
||||
|
||||
return deploymentName;
|
||||
}
|
||||
}
|
||||
+4
-2
@@ -45,7 +45,9 @@ public abstract class KeycloakDependencyProcessor implements DeploymentUnitProce
|
||||
@Override
|
||||
public void deploy(DeploymentPhaseContext phaseContext) throws DeploymentUnitProcessingException {
|
||||
final DeploymentUnit deploymentUnit = phaseContext.getDeploymentUnit();
|
||||
if (!KeycloakAdapterConfigService.getInstance().isSecureDeployment(deploymentUnit)) {
|
||||
|
||||
String deploymentName = deploymentUnit.getName();
|
||||
if (!KeycloakAdapterConfigService.getInstance().isSecureDeployment(deploymentName)) {
|
||||
WarMetaData warMetaData = deploymentUnit.getAttachment(WarMetaData.ATTACHMENT_KEY);
|
||||
if (warMetaData == null) {
|
||||
return;
|
||||
@@ -65,7 +67,7 @@ public abstract class KeycloakDependencyProcessor implements DeploymentUnitProce
|
||||
addCommonModules(moduleSpecification, moduleLoader);
|
||||
addPlatformSpecificModules(moduleSpecification, moduleLoader);
|
||||
}
|
||||
|
||||
|
||||
private void addCommonModules(ModuleSpecification moduleSpecification, ModuleLoader moduleLoader) {
|
||||
// ModuleDependency(ModuleLoader moduleLoader, ModuleIdentifier identifier, boolean optional, boolean export, boolean importServices, boolean userSpecified)
|
||||
moduleSpecification.addSystemDependency(new ModuleDependency(moduleLoader, KEYCLOAK_JBOSS_CORE_ADAPTER, false, false, false, false));
|
||||
|
||||
+2
@@ -78,6 +78,8 @@ public class SubsystemParsingTestCase extends AbstractSubsystemBaseTest {
|
||||
addCredential(addr, service, "secret", "secret1");
|
||||
addCredential(addr, service, "jwt.client-keystore-file", "/tmp/foo.jks");
|
||||
addCredential(addr, service, "jwt.token-timeout", "10");
|
||||
|
||||
System.out.println("Deployment: " + service.getJSON("foo"));
|
||||
}
|
||||
|
||||
private void addCredential(PathAddress parent, KeycloakAdapterConfigService service, String key, String value) {
|
||||
|
||||
+1
-1
@@ -20,7 +20,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>2.1.0.CR1</version>
|
||||
<version>1.9.3.Final</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<name>Keycloak Integration</name>
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-saml-eap-integration-pom</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>2.1.0.CR1</version>
|
||||
<version>1.9.3.Final</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>2.1.0.CR1</version>
|
||||
<version>1.9.3.Final</version>
|
||||
<relativePath>../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<name>Keycloak SAML EAP Integration</name>
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<parent>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-saml-eap-integration-pom</artifactId>
|
||||
<version>2.1.0.CR1</version>
|
||||
<version>1.9.3.Final</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
||||
+3
-26
@@ -16,11 +16,8 @@
|
||||
*/
|
||||
package org.keycloak.subsystem.saml.as7;
|
||||
|
||||
import org.jboss.as.server.deployment.DeploymentUnit;
|
||||
import org.jboss.as.web.deployment.WarMetaData;
|
||||
import org.jboss.dmr.ModelNode;
|
||||
import org.jboss.dmr.Property;
|
||||
import org.jboss.metadata.web.jboss.JBossWebMetaData;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:mstrukel@redhat.com">Marko Strukelj</a>
|
||||
@@ -49,8 +46,7 @@ public class Configuration {
|
||||
return keymodel.get(key);
|
||||
}
|
||||
|
||||
public ModelNode getSecureDeployment(DeploymentUnit deploymentUnit) {
|
||||
String name = preferredDeploymentName(deploymentUnit);
|
||||
public ModelNode getSecureDeployment(String name) {
|
||||
ModelNode secureDeployment = config.get("subsystem").get("keycloak-saml").get(Constants.Model.SECURE_DEPLOYMENT);
|
||||
if (secureDeployment.hasDefined(name)) {
|
||||
return secureDeployment.get(name);
|
||||
@@ -58,26 +54,7 @@ public class Configuration {
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean isSecureDeployment(DeploymentUnit deploymentUnit) {
|
||||
return getSecureDeployment(deploymentUnit) != null;
|
||||
}
|
||||
|
||||
// KEYCLOAK-3273: prefer module name if available
|
||||
private String preferredDeploymentName(DeploymentUnit deploymentUnit) {
|
||||
String deploymentName = deploymentUnit.getName();
|
||||
WarMetaData warMetaData = deploymentUnit.getAttachment(WarMetaData.ATTACHMENT_KEY);
|
||||
if (warMetaData == null) {
|
||||
return deploymentName;
|
||||
}
|
||||
|
||||
JBossWebMetaData webMetaData = warMetaData.getMergedJBossWebMetaData();
|
||||
if (webMetaData == null) {
|
||||
return deploymentName;
|
||||
}
|
||||
|
||||
String moduleName = webMetaData.getModuleName();
|
||||
if (moduleName != null) return moduleName + ".war";
|
||||
|
||||
return deploymentName;
|
||||
public boolean isSecureDeployment(String name) {
|
||||
return getSecureDeployment(name) != null;
|
||||
}
|
||||
}
|
||||
-2
@@ -45,7 +45,6 @@ public class Constants {
|
||||
static final String KEY_STORE = "KeyStore";
|
||||
static final String SIGN_REQUEST = "signRequest";
|
||||
static final String VALIDATE_RESPONSE_SIGNATURE = "validateResponseSignature";
|
||||
static final String VALIDATE_ASSERTION_SIGNATURE = "validateAssertionSignature";
|
||||
static final String REQUEST_BINDING = "requestBinding";
|
||||
static final String BINDING_URL = "bindingUrl";
|
||||
static final String VALIDATE_REQUEST_SIGNATURE = "validateRequestSignature";
|
||||
@@ -98,7 +97,6 @@ public class Constants {
|
||||
static final String CERTIFICATE_ALIAS = "alias";
|
||||
static final String SIGN_REQUEST = "signRequest";
|
||||
static final String VALIDATE_RESPONSE_SIGNATURE = "validateResponseSignature";
|
||||
static final String VALIDATE_ASSERTION_SIGNATURE = "validateAssertionSignature";
|
||||
static final String REQUEST_BINDING = "requestBinding";
|
||||
static final String BINDING_URL = "bindingUrl";
|
||||
static final String VALIDATE_REQUEST_SIGNATURE = "validateRequestSignature";
|
||||
|
||||
+8
-7
@@ -51,6 +51,7 @@ public class KeycloakAdapterConfigDeploymentProcessor implements DeploymentUnitP
|
||||
@Override
|
||||
public void deploy(DeploymentPhaseContext phaseContext) throws DeploymentUnitProcessingException {
|
||||
DeploymentUnit deploymentUnit = phaseContext.getDeploymentUnit();
|
||||
String deploymentName = deploymentUnit.getName();
|
||||
|
||||
WarMetaData warMetaData = deploymentUnit.getAttachment(WarMetaData.ATTACHMENT_KEY);
|
||||
if (warMetaData == null) {
|
||||
@@ -68,30 +69,30 @@ public class KeycloakAdapterConfigDeploymentProcessor implements DeploymentUnitP
|
||||
|
||||
try {
|
||||
boolean webRequiresKC = loginConfig != null && "KEYCLOAK-SAML".equalsIgnoreCase(loginConfig.getAuthMethod());
|
||||
boolean hasSubsystemConfig = Configuration.INSTANCE.isSecureDeployment(deploymentUnit);
|
||||
boolean hasSubsystemConfig = Configuration.INSTANCE.isSecureDeployment(deploymentName);
|
||||
if (hasSubsystemConfig || webRequiresKC) {
|
||||
log.debug("Setting up KEYCLOAK-SAML auth method for WAR: " + deploymentUnit.getName());
|
||||
log.debug("Setting up KEYCLOAK-SAML auth method for WAR: " + deploymentName);
|
||||
|
||||
// if secure-deployment configuration exists for web app, we force KEYCLOAK-SAML auth method on it
|
||||
if (hasSubsystemConfig) {
|
||||
addXMLData(getXML(deploymentUnit), warMetaData);
|
||||
addXMLData(getXML(deploymentName), warMetaData);
|
||||
if (loginConfig != null) {
|
||||
loginConfig.setAuthMethod("KEYCLOAK-SAML");
|
||||
//loginConfig.setRealmName(service.getRealmName(deploymentName));
|
||||
} else {
|
||||
log.warn("Failed to set up KEYCLOAK-SAML auth method for WAR: " + deploymentUnit.getName() + " (loginConfig == null)");
|
||||
log.warn("Failed to set up KEYCLOAK-SAML auth method for WAR: " + deploymentName + " (loginConfig == null)");
|
||||
}
|
||||
}
|
||||
addValve(webMetaData);
|
||||
KeycloakLogger.ROOT_LOGGER.deploymentSecured(deploymentUnit.getName());
|
||||
KeycloakLogger.ROOT_LOGGER.deploymentSecured(deploymentName);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new DeploymentUnitProcessingException("Failed to configure KeycloakSamlExtension from subsystem model", e);
|
||||
}
|
||||
}
|
||||
|
||||
private String getXML(DeploymentUnit deploymentUnit) throws XMLStreamException {
|
||||
ModelNode node = Configuration.INSTANCE.getSecureDeployment(deploymentUnit);
|
||||
private String getXML(String deploymentName) throws XMLStreamException {
|
||||
ModelNode node = Configuration.INSTANCE.getSecureDeployment(deploymentName);
|
||||
if (node != null) {
|
||||
KeycloakSubsystemParser writer = new KeycloakSubsystemParser();
|
||||
ByteArrayOutputStream output = new ByteArrayOutputStream();
|
||||
|
||||
+3
-2
@@ -46,7 +46,8 @@ public abstract class KeycloakDependencyProcessor implements DeploymentUnitProce
|
||||
public void deploy(DeploymentPhaseContext phaseContext) throws DeploymentUnitProcessingException {
|
||||
final DeploymentUnit deploymentUnit = phaseContext.getDeploymentUnit();
|
||||
|
||||
if (Configuration.INSTANCE.getSecureDeployment(deploymentUnit) == null) {
|
||||
String deploymentName = deploymentUnit.getName();
|
||||
if (Configuration.INSTANCE.getSecureDeployment(deploymentName) == null) {
|
||||
WarMetaData warMetaData = deploymentUnit.getAttachment(WarMetaData.ATTACHMENT_KEY);
|
||||
if (warMetaData == null) {
|
||||
return;
|
||||
@@ -70,8 +71,8 @@ public abstract class KeycloakDependencyProcessor implements DeploymentUnitProce
|
||||
private void addCommonModules(ModuleSpecification moduleSpecification, ModuleLoader moduleLoader) {
|
||||
// ModuleDependency(ModuleLoader moduleLoader, ModuleIdentifier identifier, boolean optional, boolean export, boolean importServices, boolean userSpecified)
|
||||
moduleSpecification.addSystemDependency(new ModuleDependency(moduleLoader, KEYCLOAK_JBOSS_CORE_ADAPTER, false, false, false, false));
|
||||
moduleSpecification.addSystemDependency(new ModuleDependency(moduleLoader, KEYCLOAK_CORE_ADAPTER, false, false, false, false));
|
||||
moduleSpecification.addSystemDependency(new ModuleDependency(moduleLoader, KEYCLOAK_API_ADAPTER, false, false, false, false));
|
||||
moduleSpecification.addSystemDependency(new ModuleDependency(moduleLoader, KEYCLOAK_CORE_ADAPTER, false, false, false, false));
|
||||
moduleSpecification.addSystemDependency(new ModuleDependency(moduleLoader, KEYCLOAK_COMMON, false, false, false, false));
|
||||
}
|
||||
|
||||
|
||||
+1
-6
@@ -37,11 +37,6 @@ abstract class SingleSignOnDefinition {
|
||||
.setXmlName(Constants.XML.VALIDATE_RESPONSE_SIGNATURE)
|
||||
.build();
|
||||
|
||||
static final SimpleAttributeDefinition VALIDATE_ASSERTION_SIGNATURE =
|
||||
new SimpleAttributeDefinitionBuilder(Constants.Model.VALIDATE_ASSERTION_SIGNATURE, ModelType.BOOLEAN, true)
|
||||
.setXmlName(Constants.XML.VALIDATE_ASSERTION_SIGNATURE)
|
||||
.build();
|
||||
|
||||
static final SimpleAttributeDefinition REQUEST_BINDING =
|
||||
new SimpleAttributeDefinitionBuilder(Constants.Model.REQUEST_BINDING, ModelType.STRING, true)
|
||||
.setXmlName(Constants.XML.REQUEST_BINDING)
|
||||
@@ -57,7 +52,7 @@ abstract class SingleSignOnDefinition {
|
||||
.setXmlName(Constants.XML.BINDING_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, REQUEST_BINDING, RESPONSE_BINDING, BINDING_URL};
|
||||
|
||||
static final HashMap<String, SimpleAttributeDefinition> ATTRIBUTE_MAP = new HashMap<>();
|
||||
|
||||
|
||||
-1
@@ -67,7 +67,6 @@ keycloak-saml.IDP.signatureCanonicalizationMethod=Signature canonicalization met
|
||||
keycloak-saml.IDP.SingleSignOnService=Single sign-on configuration
|
||||
keycloak-saml.IDP.SingleSignOnService.signRequest=Sign SSO requests
|
||||
keycloak-saml.IDP.SingleSignOnService.validateResponseSignature=Validate an SSO response signature
|
||||
keycloak-saml.IDP.SingleSignOnService.validateAssertionSignature=Validate an SSO assertion signature
|
||||
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.bindingUrl=SSO endpoint URL
|
||||
|
||||
-5
@@ -132,11 +132,6 @@
|
||||
<xs:documentation>Validate the SSO response signature</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="validateAssertionSignature" type="xs:boolean" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation>Validate the SSO assertion signature</xs:documentation>
|
||||
</xs:annotation>
|
||||
</xs:attribute>
|
||||
<xs:attribute name="requestBinding" type="xs:string" use="optional">
|
||||
<xs:annotation>
|
||||
<xs:documentation>HTTP method to use for requests</xs:documentation>
|
||||
|
||||
-1
@@ -42,7 +42,6 @@
|
||||
<IDP entityID="idp">
|
||||
<SingleSignOnService signRequest="true"
|
||||
validateResponseSignature="true"
|
||||
validateAssertionSignature="true"
|
||||
requestBinding="POST"
|
||||
bindingUrl="http://localhost:8080/auth/realms/saml-demo/protocol/saml"/>
|
||||
<SingleLogoutService
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>2.1.0.CR1</version>
|
||||
<version>1.9.3.Final</version>
|
||||
<relativePath>../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
@@ -30,7 +30,6 @@
|
||||
<name>Keycloak SAML Client Adapter Public API</name>
|
||||
<description/>
|
||||
|
||||
|
||||
<properties>
|
||||
<timestamp>${maven.build.timestamp}</timestamp>
|
||||
<maven.build.timestamp.format>yyyy-MM-dd HH:mm</maven.build.timestamp.format>
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>2.1.0.CR1</version>
|
||||
<version>1.9.3.Final</version>
|
||||
<relativePath>../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
@@ -55,7 +55,7 @@
|
||||
<artifactId>keycloak-saml-adapter-api-public</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-common</artifactId>
|
||||
<scope>provided</scope>
|
||||
|
||||
-10
@@ -34,7 +34,6 @@ public class DefaultSamlDeployment implements SamlDeployment {
|
||||
public static class DefaultSingleSignOnService implements IDP.SingleSignOnService {
|
||||
private boolean signRequest;
|
||||
private boolean validateResponseSignature;
|
||||
private boolean validateAssertionSignature;
|
||||
private Binding requestBinding;
|
||||
private Binding responseBinding;
|
||||
private String requestBindingUrl;
|
||||
@@ -49,11 +48,6 @@ public class DefaultSamlDeployment implements SamlDeployment {
|
||||
return validateResponseSignature;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean validateAssertionSignature() {
|
||||
return validateAssertionSignature;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Binding getRequestBinding() {
|
||||
return requestBinding;
|
||||
@@ -77,10 +71,6 @@ public class DefaultSamlDeployment implements SamlDeployment {
|
||||
this.validateResponseSignature = validateResponseSignature;
|
||||
}
|
||||
|
||||
public void setValidateAssertionSignature(boolean validateAssertionSignature) {
|
||||
this.validateAssertionSignature = validateAssertionSignature;
|
||||
}
|
||||
|
||||
public void setRequestBinding(Binding requestBinding) {
|
||||
this.requestBinding = requestBinding;
|
||||
}
|
||||
|
||||
@@ -50,7 +50,6 @@ public interface SamlDeployment {
|
||||
public interface SingleSignOnService {
|
||||
boolean signRequest();
|
||||
boolean validateResponseSignature();
|
||||
boolean validateAssertionSignature();
|
||||
Binding getRequestBinding();
|
||||
Binding getResponseBinding();
|
||||
String getRequestBindingUrl();
|
||||
|
||||
@@ -33,7 +33,6 @@ public class IDP implements Serializable {
|
||||
private String requestBinding;
|
||||
private String responseBinding;
|
||||
private String bindingUrl;
|
||||
private boolean validateAssertionSignature;
|
||||
|
||||
public boolean isSignRequest() {
|
||||
return signRequest;
|
||||
@@ -51,14 +50,6 @@ public class IDP implements Serializable {
|
||||
this.validateResponseSignature = validateResponseSignature;
|
||||
}
|
||||
|
||||
public boolean isValidateAssertionSignature() {
|
||||
return validateAssertionSignature;
|
||||
}
|
||||
|
||||
public void setValidateAssertionSignature(boolean validateAssertionSignature) {
|
||||
this.validateAssertionSignature = validateAssertionSignature;
|
||||
}
|
||||
|
||||
public String getRequestBinding() {
|
||||
return requestBinding;
|
||||
}
|
||||
|
||||
-1
@@ -68,7 +68,6 @@ public class ConfigXmlConstants {
|
||||
public static final String RESPONSE_BINDING_ATTR = "responseBinding";
|
||||
public static final String BINDING_URL_ATTR = "bindingUrl";
|
||||
public static final String VALIDATE_RESPONSE_SIGNATURE_ATTR = "validateResponseSignature";
|
||||
public static final String VALIDATE_ASSERTION_SIGNATURE_ATTR = "validateAssertionSignature";
|
||||
public static final String VALIDATE_REQUEST_SIGNATURE_ATTR = "validateRequestSignature";
|
||||
public static final String POST_BINDING_URL_ATTR = "postBindingUrl";
|
||||
public static final String REDIRECT_BINDING_URL_ATTR = "redirectBindingUrl";
|
||||
|
||||
Loaded 100 of 1888 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user