Compare commits
337
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2d3287fe47 | ||
|
|
01ddd50b96 | ||
|
|
3335e8630b | ||
|
|
ebd3d522e2 | ||
|
|
04179c5681 | ||
|
|
6c8ebdb456 | ||
|
|
85446c3b46 | ||
|
|
df7a68b709 | ||
|
|
1c65fd86ef | ||
|
|
7f9e6bbf60 | ||
|
|
2ba21485f9 | ||
|
|
c998198aac | ||
|
|
3e8d4e4eb6 | ||
|
|
b15918b745 | ||
|
|
d2b7f18480 | ||
|
|
663b99d884 | ||
|
|
e3e18913f1 | ||
|
|
f98c454775 | ||
|
|
9c2944c090 | ||
|
|
66eb9095c1 | ||
|
|
e7c73518b3 | ||
|
|
e262f8fb63 | ||
|
|
b6b3c04400 | ||
|
|
f97a3e0745 | ||
|
|
f9bccc83f9 | ||
|
|
761714036e | ||
|
|
d365d9d784 | ||
|
|
96f2985e86 | ||
|
|
7bad8e6ff3 | ||
|
|
55d53214a1 | ||
|
|
aee8398ee8 | ||
|
|
7cd63f2f8b | ||
|
|
8b5aafc4b4 | ||
|
|
f6323d94ec | ||
|
|
eb7ad07e31 | ||
|
|
7c7f87d201 | ||
|
|
18b94a2153 | ||
|
|
0b3e867362 | ||
|
|
3498273601 | ||
|
|
01a8c13ac0 | ||
|
|
194ba6009f | ||
|
|
c9c8acd029 | ||
|
|
7e2c06e301 | ||
|
|
40591cff25 | ||
|
|
5cf5168770 | ||
|
|
cb57dbf58a | ||
|
|
4b6df5d489 | ||
|
|
b6d29ccd30 | ||
|
|
16fb1e2078 | ||
|
|
ac00f7fee2 | ||
|
|
faeff029fa | ||
|
|
c6363aa146 | ||
|
|
2c70e53df6 | ||
|
|
81ab6aeeed | ||
|
|
d1a528eb07 | ||
|
|
c9c9f05e29 | ||
|
|
4e3e9ad5d4 | ||
|
|
3bd3d0285d | ||
|
|
343e678f09 | ||
|
|
b8adfcad87 | ||
|
|
ca3691e650 | ||
|
|
ad11d6e76b | ||
|
|
93cec9b3ee | ||
|
|
20c5c6b60c | ||
|
|
f29bb7d501 | ||
|
|
c3d9859c6e | ||
|
|
3b3b219a86 | ||
|
|
3f2e9c3592 | ||
|
|
787a3f8fcc | ||
|
|
a4cbf130b4 | ||
|
|
1c0e23db66 | ||
|
|
f33a1e2143 | ||
|
|
63ca9b2fe8 | ||
|
|
5453bec1bf | ||
|
|
e65dd4fbc3 | ||
|
|
7b115b4b44 | ||
|
|
4d64f0e160 | ||
|
|
7453e96f5c | ||
|
|
9be9d3f580 | ||
|
|
7d51df4eed | ||
|
|
3c2a12d019 | ||
|
|
56f9aa41d0 | ||
|
|
e5d744f7d5 | ||
|
|
394676222f | ||
|
|
5464655bc2 | ||
|
|
768c3eb9a7 | ||
|
|
e316037910 | ||
|
|
97a08a1d99 | ||
|
|
db4420e10d | ||
|
|
480d4e6f4f | ||
|
|
0b701b3cf9 | ||
|
|
40216b5e7d | ||
|
|
b1fe07ac3d | ||
|
|
642de06fb5 | ||
|
|
7ad028fcb1 | ||
|
|
76385157fc | ||
|
|
c11f65720b | ||
|
|
5006fe2292 | ||
|
|
90fdb4889c | ||
|
|
c17a57d76c | ||
|
|
efcb749771 | ||
|
|
8c99a13387 | ||
|
|
79c1650c15 | ||
|
|
63ddabe5fb | ||
|
|
5448403345 | ||
|
|
5996149a8d | ||
|
|
62029e8a33 | ||
|
|
588e1711dd | ||
|
|
35c4a379ad | ||
|
|
cf62715499 | ||
|
|
1bfdff0e25 | ||
|
|
ba14b9d942 | ||
|
|
10fc7302eb | ||
|
|
3bea8f4adb | ||
|
|
24a36e6848 | ||
|
|
5d070cbf22 | ||
|
|
5e660977aa | ||
|
|
1f0600044a | ||
|
|
d3e3990d77 | ||
|
|
4a80f1e913 | ||
|
|
0550bdb467 | ||
|
|
5f07fa8057 | ||
|
|
10064fdac9 | ||
|
|
e7f6c780e2 | ||
|
|
e03b72df00 | ||
|
|
7d8b392fd9 | ||
|
|
afa8dc735d | ||
|
|
d49a74b927 | ||
|
|
ae36b3c832 | ||
|
|
e0c62e25b2 | ||
|
|
081958e282 | ||
|
|
379d5e3228 | ||
|
|
9b18601102 | ||
|
|
7868152ffe | ||
|
|
223cc1fb50 | ||
|
|
6ae9d19843 | ||
|
|
cbe4ff324c | ||
|
|
b8c06dd560 | ||
|
|
31d2cde6e5 | ||
|
|
75e2b404c8 | ||
|
|
d163dad3fe | ||
|
|
7271fdaaaa | ||
|
|
03fbb3c853 | ||
|
|
68c8bfa0e1 | ||
|
|
f34b47d29c | ||
|
|
a0b54ebedc | ||
|
|
ddb201db6c | ||
|
|
4069be3ff6 | ||
|
|
15f23eb045 | ||
|
|
77d17de14d | ||
|
|
bab08bf8f0 | ||
|
|
0d110ceb30 | ||
|
|
9cd3034762 | ||
|
|
ba51640c61 | ||
|
|
287593d75f | ||
|
|
3826e933c1 | ||
|
|
6b1020ec34 | ||
|
|
c8b22e71f0 | ||
|
|
41a5598103 | ||
|
|
fc92639d3f | ||
|
|
6587cd2478 | ||
|
|
e55c2ae554 | ||
|
|
693d6c0e5d | ||
|
|
952c1decf0 | ||
|
|
f3dbacabf8 | ||
|
|
819105c3aa | ||
|
|
06affc0700 | ||
|
|
f03d79c7d3 | ||
|
|
b52936bc5b | ||
|
|
3c4114091f | ||
|
|
d354aa1f62 | ||
|
|
45fd114143 | ||
|
|
32da5fea0a | ||
|
|
32c23c2410 | ||
|
|
802085f158 | ||
|
|
773c88cc04 | ||
|
|
197f51e50f | ||
|
|
1c66ce7dd7 | ||
|
|
8610a02d72 | ||
|
|
d7df86d6d0 | ||
|
|
e3d0f8f6e5 | ||
|
|
e8f2527fcd | ||
|
|
305dcb2b1e | ||
|
|
0ab352706b | ||
|
|
eac0bb4b37 | ||
|
|
3bc721720f | ||
|
|
54758b800b | ||
|
|
6cd6edce64 | ||
|
|
69a1d4d192 | ||
|
|
5d4864b82d | ||
|
|
3840aed5f7 | ||
|
|
6a629aec0c | ||
|
|
8b4bb72fb3 | ||
|
|
88d08c4f38 | ||
|
|
e3f5df3894 | ||
|
|
cfbd7d469f | ||
|
|
8fd7091068 | ||
|
|
9c97245c46 | ||
|
|
257aba4331 | ||
|
|
672e1b3575 | ||
|
|
ce50b0ed29 | ||
|
|
e88af874ca | ||
|
|
aed54439c2 | ||
|
|
c8c6e36fd9 | ||
|
|
e6ace84101 | ||
|
|
815b5e5f34 | ||
|
|
c149358028 | ||
|
|
b1265f6d70 | ||
|
|
a09e78873e | ||
|
|
17d8394ab6 | ||
|
|
e6a20aa44b | ||
|
|
458ca8a7ee | ||
|
|
b56e23eded | ||
|
|
d02c9c2150 | ||
|
|
cccb532a21 | ||
|
|
5c2bf7c822 | ||
|
|
e8758a77fb | ||
|
|
b2f0acfe26 | ||
|
|
8842d88058 | ||
|
|
739178d840 | ||
|
|
2454b3b644 | ||
|
|
87b243ed59 | ||
|
|
cec6f5db14 | ||
|
|
e7dd49b453 | ||
|
|
6fdc470b0b | ||
|
|
695aa7bec9 | ||
|
|
3952dba094 | ||
|
|
209f8155d1 | ||
|
|
8621733e17 | ||
|
|
621301862c | ||
|
|
fd4c5a90ed | ||
|
|
bfec073457 | ||
|
|
dc6e869c64 | ||
|
|
bed592460d | ||
|
|
46d3555798 | ||
|
|
74967737ee | ||
|
|
a347cb591d | ||
|
|
1ae60ef8a7 | ||
|
|
f9db687385 | ||
|
|
a38544796f | ||
|
|
5ecc8d1c71 | ||
|
|
c9cf7f6564 | ||
|
|
ba406d5747 | ||
|
|
c72ceadfce | ||
|
|
1e7f1b1e54 | ||
|
|
7c0f6f6e6e | ||
|
|
3f32cb154b | ||
|
|
6fa504489f | ||
|
|
433f373f60 | ||
|
|
b771b84f56 | ||
|
|
45abaec86e | ||
|
|
d0a96d463d | ||
|
|
12f1aedcd1 | ||
|
|
f0874bf585 | ||
|
|
1a749dc7b7 | ||
|
|
ec49d10007 | ||
|
|
294dc6fbd0 | ||
|
|
9e50a45b4c | ||
|
|
72ffb9dbb9 | ||
|
|
a677ab64e3 | ||
|
|
b33afcd47c | ||
|
|
659892edcb | ||
|
|
803fde6c1d | ||
|
|
83063a5740 | ||
|
|
7efa3a3ddf | ||
|
|
c1d93e251d | ||
|
|
8f3256675a | ||
|
|
9711ac2ecb | ||
|
|
833c56e17b | ||
|
|
9bb59c0f94 | ||
|
|
629ec6383e | ||
|
|
a6b6ecf4ba | ||
|
|
e5ce080fd3 | ||
|
|
80c4b2aa31 | ||
|
|
0b8f9edb9e | ||
|
|
63458a7de7 | ||
|
|
f6a080729a | ||
|
|
1dacddb7e3 | ||
|
|
334aa37b7f | ||
|
|
725f42e185 | ||
|
|
69ce1e05f0 | ||
|
|
8d3136188d | ||
|
|
cb4f856ab6 | ||
|
|
65b269cd54 | ||
|
|
df93244373 | ||
|
|
a8de125e26 | ||
|
|
7db06b8afb | ||
|
|
7c6032cc84 | ||
|
|
939da455d7 | ||
|
|
817dbce391 | ||
|
|
0f447fadd4 | ||
|
|
79825dfa1d | ||
|
|
b640e9fe39 | ||
|
|
9dd4cbb40e | ||
|
|
82423db239 | ||
|
|
0262b64062 | ||
|
|
bd920b8ba9 | ||
|
|
57da86c598 | ||
|
|
cd92cc504b | ||
|
|
e82e584b81 | ||
|
|
ccbd8e8c70 | ||
|
|
e396261399 | ||
|
|
aae368f1e7 | ||
|
|
5ac4a852e1 | ||
|
|
fad33bc50f | ||
|
|
d5925b8ccf | ||
|
|
5e97a46afc | ||
|
|
8ee2134e05 | ||
|
|
2da9986717 | ||
|
|
c3b6b07e3a | ||
|
|
045d6ef1d0 | ||
|
|
ecba291ea0 | ||
|
|
328ab1cc27 | ||
|
|
884f84d5ed | ||
|
|
b2d48c86a6 | ||
|
|
3c5a0a3394 | ||
|
|
6ec82865d3 | ||
|
|
dab2225a39 | ||
|
|
0e93603aee | ||
|
|
d44f347b08 | ||
|
|
99f12ff720 | ||
|
|
a3cb3730b4 | ||
|
|
2cca3bf570 | ||
|
|
0c05dc093f | ||
|
|
50fc083d97 | ||
|
|
798fd84698 | ||
|
|
19575b2c8f | ||
|
|
5e731d9557 | ||
|
|
8fc5b00d91 | ||
|
|
80b071024f | ||
|
|
3efd103712 | ||
|
|
3035cbc5db | ||
|
|
facdd586a3 | ||
|
|
a119a46495 | ||
|
|
0d3a50411e | ||
|
|
3bed84d712 | ||
|
|
0485f5c43d |
No files matched your search
@@ -16,6 +16,7 @@ env:
|
|||||||
- TESTS=group1
|
- TESTS=group1
|
||||||
- TESTS=group2
|
- TESTS=group2
|
||||||
- TESTS=group3
|
- TESTS=group3
|
||||||
|
- TESTS=group4
|
||||||
- TESTS=adapter
|
- TESTS=adapter
|
||||||
|
|
||||||
jdk:
|
jdk:
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>2.4.0.Final</version>
|
<version>2.5.0.Final</version>
|
||||||
<relativePath>../../../pom.xml</relativePath>
|
<relativePath>../../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|||||||
+16
@@ -342,6 +342,12 @@ public class AdapterDeploymentContext {
|
|||||||
return delegate.getNotBefore();
|
return delegate.getNotBefore();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateNotBefore(int notBefore) {
|
||||||
|
delegate.setNotBefore(notBefore);
|
||||||
|
getPublicKeyLocator().reset(this);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setExposeToken(boolean exposeToken) {
|
public void setExposeToken(boolean exposeToken) {
|
||||||
delegate.setExposeToken(exposeToken);
|
delegate.setExposeToken(exposeToken);
|
||||||
@@ -446,6 +452,16 @@ public class AdapterDeploymentContext {
|
|||||||
public int getMinTimeBetweenJwksRequests() {
|
public int getMinTimeBetweenJwksRequests() {
|
||||||
return delegate.getMinTimeBetweenJwksRequests();
|
return delegate.getMinTimeBetweenJwksRequests();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getPublicKeyCacheTtl() {
|
||||||
|
return delegate.getPublicKeyCacheTtl();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setPublicKeyCacheTtl(int publicKeyCacheTtl) {
|
||||||
|
delegate.setPublicKeyCacheTtl(publicKeyCacheTtl);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected KeycloakUriBuilder getBaseBuilder(HttpFacade facade, String base) {
|
protected KeycloakUriBuilder getBaseBuilder(HttpFacade facade, String base) {
|
||||||
|
|||||||
+1
-8
@@ -46,14 +46,7 @@ public class HttpAdapterUtils {
|
|||||||
}
|
}
|
||||||
InputStream is = entity.getContent();
|
InputStream is = entity.getContent();
|
||||||
try {
|
try {
|
||||||
ByteArrayOutputStream os = new ByteArrayOutputStream();
|
return JsonSerialization.readValue(is, clazz);
|
||||||
int c;
|
|
||||||
while ((c = is.read()) != -1) {
|
|
||||||
os.write(c);
|
|
||||||
}
|
|
||||||
byte[] bytes = os.toByteArray();
|
|
||||||
String json = new String(bytes);
|
|
||||||
return JsonSerialization.readValue(json, clazz);
|
|
||||||
} finally {
|
} finally {
|
||||||
try {
|
try {
|
||||||
is.close();
|
is.close();
|
||||||
|
|||||||
+23
@@ -57,6 +57,7 @@ public class KeycloakDeployment {
|
|||||||
|
|
||||||
protected String resourceName;
|
protected String resourceName;
|
||||||
protected boolean bearerOnly;
|
protected boolean bearerOnly;
|
||||||
|
protected boolean autodetectBearerOnly;
|
||||||
protected boolean enableBasicAuth;
|
protected boolean enableBasicAuth;
|
||||||
protected boolean publicClient;
|
protected boolean publicClient;
|
||||||
protected Map<String, Object> resourceCredentials = new HashMap<>();
|
protected Map<String, Object> resourceCredentials = new HashMap<>();
|
||||||
@@ -81,6 +82,7 @@ public class KeycloakDeployment {
|
|||||||
protected volatile int notBefore;
|
protected volatile int notBefore;
|
||||||
protected int tokenMinimumTimeToLive;
|
protected int tokenMinimumTimeToLive;
|
||||||
protected int minTimeBetweenJwksRequests;
|
protected int minTimeBetweenJwksRequests;
|
||||||
|
protected int publicKeyCacheTtl;
|
||||||
private PolicyEnforcer policyEnforcer;
|
private PolicyEnforcer policyEnforcer;
|
||||||
|
|
||||||
public KeycloakDeployment() {
|
public KeycloakDeployment() {
|
||||||
@@ -200,6 +202,14 @@ public class KeycloakDeployment {
|
|||||||
this.bearerOnly = bearerOnly;
|
this.bearerOnly = bearerOnly;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isAutodetectBearerOnly() {
|
||||||
|
return autodetectBearerOnly;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAutodetectBearerOnly(boolean autodetectBearerOnly) {
|
||||||
|
this.autodetectBearerOnly = autodetectBearerOnly;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isEnableBasicAuth() {
|
public boolean isEnableBasicAuth() {
|
||||||
return enableBasicAuth;
|
return enableBasicAuth;
|
||||||
}
|
}
|
||||||
@@ -328,6 +338,11 @@ public class KeycloakDeployment {
|
|||||||
this.notBefore = notBefore;
|
this.notBefore = notBefore;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void updateNotBefore(int notBefore) {
|
||||||
|
this.notBefore = notBefore;
|
||||||
|
getPublicKeyLocator().reset(this);
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isAlwaysRefreshToken() {
|
public boolean isAlwaysRefreshToken() {
|
||||||
return alwaysRefreshToken;
|
return alwaysRefreshToken;
|
||||||
}
|
}
|
||||||
@@ -384,6 +399,14 @@ public class KeycloakDeployment {
|
|||||||
this.minTimeBetweenJwksRequests = minTimeBetweenJwksRequests;
|
this.minTimeBetweenJwksRequests = minTimeBetweenJwksRequests;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getPublicKeyCacheTtl() {
|
||||||
|
return publicKeyCacheTtl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPublicKeyCacheTtl(int publicKeyCacheTtl) {
|
||||||
|
this.publicKeyCacheTtl = publicKeyCacheTtl;
|
||||||
|
}
|
||||||
|
|
||||||
public void setPolicyEnforcer(PolicyEnforcer policyEnforcer) {
|
public void setPolicyEnforcer(PolicyEnforcer policyEnforcer) {
|
||||||
this.policyEnforcer = policyEnforcer;
|
this.policyEnforcer = policyEnforcer;
|
||||||
}
|
}
|
||||||
|
|||||||
+2
@@ -99,12 +99,14 @@ public class KeycloakDeploymentBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
deployment.setBearerOnly(adapterConfig.isBearerOnly());
|
deployment.setBearerOnly(adapterConfig.isBearerOnly());
|
||||||
|
deployment.setAutodetectBearerOnly(adapterConfig.isAutodetectBearerOnly());
|
||||||
deployment.setEnableBasicAuth(adapterConfig.isEnableBasicAuth());
|
deployment.setEnableBasicAuth(adapterConfig.isEnableBasicAuth());
|
||||||
deployment.setAlwaysRefreshToken(adapterConfig.isAlwaysRefreshToken());
|
deployment.setAlwaysRefreshToken(adapterConfig.isAlwaysRefreshToken());
|
||||||
deployment.setRegisterNodeAtStartup(adapterConfig.isRegisterNodeAtStartup());
|
deployment.setRegisterNodeAtStartup(adapterConfig.isRegisterNodeAtStartup());
|
||||||
deployment.setRegisterNodePeriod(adapterConfig.getRegisterNodePeriod());
|
deployment.setRegisterNodePeriod(adapterConfig.getRegisterNodePeriod());
|
||||||
deployment.setTokenMinimumTimeToLive(adapterConfig.getTokenMinimumTimeToLive());
|
deployment.setTokenMinimumTimeToLive(adapterConfig.getTokenMinimumTimeToLive());
|
||||||
deployment.setMinTimeBetweenJwksRequests(adapterConfig.getMinTimeBetweenJwksRequests());
|
deployment.setMinTimeBetweenJwksRequests(adapterConfig.getMinTimeBetweenJwksRequests());
|
||||||
|
deployment.setPublicKeyCacheTtl(adapterConfig.getPublicKeyCacheTtl());
|
||||||
|
|
||||||
if (realmKeyPem == null && adapterConfig.isBearerOnly() && adapterConfig.getAuthServerUrl() == null) {
|
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");
|
throw new IllegalArgumentException("For bearer auth, you must set the realm-public-key or auth-server-url");
|
||||||
|
|||||||
+4
-3
@@ -25,6 +25,7 @@ import org.keycloak.adapters.spi.AuthChallenge;
|
|||||||
import org.keycloak.adapters.spi.AuthOutcome;
|
import org.keycloak.adapters.spi.AuthOutcome;
|
||||||
import org.keycloak.adapters.spi.HttpFacade;
|
import org.keycloak.adapters.spi.HttpFacade;
|
||||||
import org.keycloak.common.VerificationException;
|
import org.keycloak.common.VerificationException;
|
||||||
|
import org.keycloak.common.util.Encode;
|
||||||
import org.keycloak.common.util.KeycloakUriBuilder;
|
import org.keycloak.common.util.KeycloakUriBuilder;
|
||||||
import org.keycloak.common.util.UriUtils;
|
import org.keycloak.common.util.UriUtils;
|
||||||
import org.keycloak.constants.AdapterConstants;
|
import org.keycloak.constants.AdapterConstants;
|
||||||
@@ -169,7 +170,7 @@ public class OAuthRequestAuthenticator {
|
|||||||
KeycloakUriBuilder redirectUriBuilder = deployment.getAuthUrl().clone()
|
KeycloakUriBuilder redirectUriBuilder = deployment.getAuthUrl().clone()
|
||||||
.queryParam(OAuth2Constants.RESPONSE_TYPE, OAuth2Constants.CODE)
|
.queryParam(OAuth2Constants.RESPONSE_TYPE, OAuth2Constants.CODE)
|
||||||
.queryParam(OAuth2Constants.CLIENT_ID, deployment.getResourceName())
|
.queryParam(OAuth2Constants.CLIENT_ID, deployment.getResourceName())
|
||||||
.queryParam(OAuth2Constants.REDIRECT_URI, url)
|
.queryParam(OAuth2Constants.REDIRECT_URI, Encode.encodeQueryParamAsIs(url)) // Need to encode uri ourselves as queryParam() will not encode % characters.
|
||||||
.queryParam(OAuth2Constants.STATE, state)
|
.queryParam(OAuth2Constants.STATE, state)
|
||||||
.queryParam("login", "true");
|
.queryParam("login", "true");
|
||||||
if(loginHint != null && loginHint.length() > 0){
|
if(loginHint != null && loginHint.length() > 0){
|
||||||
@@ -203,7 +204,7 @@ public class OAuthRequestAuthenticator {
|
|||||||
|
|
||||||
protected AuthChallenge loginRedirect() {
|
protected AuthChallenge loginRedirect() {
|
||||||
final String state = getStateCode();
|
final String state = getStateCode();
|
||||||
final String redirect = getRedirectUri(state);
|
final String redirect = getRedirectUri(state);
|
||||||
if (redirect == null) {
|
if (redirect == null) {
|
||||||
return challenge(403, OIDCAuthenticationError.Reason.NO_REDIRECT_URI, null);
|
return challenge(403, OIDCAuthenticationError.Reason.NO_REDIRECT_URI, null);
|
||||||
}
|
}
|
||||||
@@ -357,7 +358,7 @@ public class OAuthRequestAuthenticator {
|
|||||||
return challenge(403, OIDCAuthenticationError.Reason.INVALID_TOKEN, null);
|
return challenge(403, OIDCAuthenticationError.Reason.INVALID_TOKEN, null);
|
||||||
}
|
}
|
||||||
if (tokenResponse.getNotBeforePolicy() > deployment.getNotBefore()) {
|
if (tokenResponse.getNotBeforePolicy() > deployment.getNotBefore()) {
|
||||||
deployment.setNotBefore(tokenResponse.getNotBeforePolicy());
|
deployment.updateNotBefore(tokenResponse.getNotBeforePolicy());
|
||||||
}
|
}
|
||||||
if (token.getIssuedAt() < deployment.getNotBefore()) {
|
if (token.getIssuedAt() < deployment.getNotBefore()) {
|
||||||
log.error("Stale token");
|
log.error("Stale token");
|
||||||
|
|||||||
+2
-2
@@ -155,7 +155,7 @@ public class PreAuthActionsHandler {
|
|||||||
} else {
|
} else {
|
||||||
log.debugf("logout of all sessions for application '%s'", action.getResource());
|
log.debugf("logout of all sessions for application '%s'", action.getResource());
|
||||||
if (action.getNotBefore() > deployment.getNotBefore()) {
|
if (action.getNotBefore() > deployment.getNotBefore()) {
|
||||||
deployment.setNotBefore(action.getNotBefore());
|
deployment.updateNotBefore(action.getNotBefore());
|
||||||
}
|
}
|
||||||
userSessionManagement.logoutAll();
|
userSessionManagement.logoutAll();
|
||||||
}
|
}
|
||||||
@@ -177,7 +177,7 @@ public class PreAuthActionsHandler {
|
|||||||
}
|
}
|
||||||
PushNotBeforeAction action = JsonSerialization.readValue(token.getContent(), PushNotBeforeAction.class);
|
PushNotBeforeAction action = JsonSerialization.readValue(token.getContent(), PushNotBeforeAction.class);
|
||||||
if (!validateAction(action)) return;
|
if (!validateAction(action)) return;
|
||||||
deployment.setNotBefore(action.getNotBefore());
|
deployment.updateNotBefore(action.getNotBefore());
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -144,7 +144,7 @@ public class RefreshableKeycloakSecurityContext extends KeycloakSecurityContext
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (response.getNotBeforePolicy() > deployment.getNotBefore()) {
|
if (response.getNotBeforePolicy() > deployment.getNotBefore()) {
|
||||||
deployment.setNotBefore(response.getNotBeforePolicy());
|
deployment.updateNotBefore(response.getNotBeforePolicy());
|
||||||
}
|
}
|
||||||
|
|
||||||
this.token = token;
|
this.token = token;
|
||||||
|
|||||||
+38
@@ -17,6 +17,8 @@
|
|||||||
|
|
||||||
package org.keycloak.adapters;
|
package org.keycloak.adapters;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
import org.keycloak.KeycloakPrincipal;
|
import org.keycloak.KeycloakPrincipal;
|
||||||
import org.keycloak.adapters.spi.AuthChallenge;
|
import org.keycloak.adapters.spi.AuthChallenge;
|
||||||
@@ -116,6 +118,12 @@ public abstract class RequestAuthenticator {
|
|||||||
return AuthOutcome.NOT_ATTEMPTED;
|
return AuthOutcome.NOT_ATTEMPTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isAutodetectedBearerOnly(facade.getRequest())) {
|
||||||
|
challenge = bearer.getChallenge();
|
||||||
|
log.debug("NOT_ATTEMPTED: Treating as bearer only");
|
||||||
|
return AuthOutcome.NOT_ATTEMPTED;
|
||||||
|
}
|
||||||
|
|
||||||
if (log.isTraceEnabled()) {
|
if (log.isTraceEnabled()) {
|
||||||
log.trace("try oauth");
|
log.trace("try oauth");
|
||||||
}
|
}
|
||||||
@@ -158,6 +166,36 @@ public abstract class RequestAuthenticator {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected boolean isAutodetectedBearerOnly(HttpFacade.Request request) {
|
||||||
|
if (!deployment.isAutodetectBearerOnly()) return false;
|
||||||
|
|
||||||
|
String headerValue = facade.getRequest().getHeader("X-Requested-With");
|
||||||
|
if (headerValue != null && headerValue.equalsIgnoreCase("XMLHttpRequest")) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
headerValue = facade.getRequest().getHeader("Faces-Request");
|
||||||
|
if (headerValue != null && headerValue.startsWith("partial/")) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
headerValue = facade.getRequest().getHeader("SOAPAction");
|
||||||
|
if (headerValue != null) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<String> accepts = facade.getRequest().getHeaders("Accept");
|
||||||
|
if (accepts == null) accepts = Collections.emptyList();
|
||||||
|
|
||||||
|
for (String accept : accepts) {
|
||||||
|
if (accept.contains("text/html") || accept.contains("text/*") || accept.contains("*/*")) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
protected abstract OAuthRequestAuthenticator createOAuthAuthenticator();
|
protected abstract OAuthRequestAuthenticator createOAuthAuthenticator();
|
||||||
|
|
||||||
protected BearerTokenRequestAuthenticator createBearerTokenAuthenticator() {
|
protected BearerTokenRequestAuthenticator createBearerTokenAuthenticator() {
|
||||||
|
|||||||
+32
-24
@@ -17,6 +17,13 @@
|
|||||||
*/
|
*/
|
||||||
package org.keycloak.adapters.authorization;
|
package org.keycloak.adapters.authorization;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
import org.keycloak.AuthorizationContext;
|
import org.keycloak.AuthorizationContext;
|
||||||
import org.keycloak.KeycloakSecurityContext;
|
import org.keycloak.KeycloakSecurityContext;
|
||||||
@@ -32,13 +39,6 @@ import org.keycloak.representations.adapters.config.PolicyEnforcerConfig.Enforce
|
|||||||
import org.keycloak.representations.adapters.config.PolicyEnforcerConfig.PathConfig;
|
import org.keycloak.representations.adapters.config.PolicyEnforcerConfig.PathConfig;
|
||||||
import org.keycloak.representations.idm.authorization.Permission;
|
import org.keycloak.representations.idm.authorization.Permission;
|
||||||
|
|
||||||
import java.net.URI;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
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>
|
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||||
*/
|
*/
|
||||||
@@ -48,7 +48,7 @@ public abstract class AbstractPolicyEnforcer {
|
|||||||
private final PolicyEnforcerConfig enforcerConfig;
|
private final PolicyEnforcerConfig enforcerConfig;
|
||||||
private final PolicyEnforcer policyEnforcer;
|
private final PolicyEnforcer policyEnforcer;
|
||||||
|
|
||||||
private List<PathConfig> paths;
|
private Map<String, PathConfig> paths;
|
||||||
private AuthzClient authzClient;
|
private AuthzClient authzClient;
|
||||||
private PathMatcher pathMatcher;
|
private PathMatcher pathMatcher;
|
||||||
|
|
||||||
@@ -57,7 +57,7 @@ public abstract class AbstractPolicyEnforcer {
|
|||||||
this.enforcerConfig = policyEnforcer.getEnforcerConfig();
|
this.enforcerConfig = policyEnforcer.getEnforcerConfig();
|
||||||
this.authzClient = policyEnforcer.getClient();
|
this.authzClient = policyEnforcer.getClient();
|
||||||
this.pathMatcher = new PathMatcher();
|
this.pathMatcher = new PathMatcher();
|
||||||
this.paths = new ArrayList<>(policyEnforcer.getPaths());
|
this.paths = policyEnforcer.getPaths();
|
||||||
}
|
}
|
||||||
|
|
||||||
public AuthorizationContext authorize(OIDCHttpFacade httpFacade) {
|
public AuthorizationContext authorize(OIDCHttpFacade httpFacade) {
|
||||||
@@ -75,8 +75,7 @@ public abstract class AbstractPolicyEnforcer {
|
|||||||
if (accessToken != null) {
|
if (accessToken != null) {
|
||||||
Request request = httpFacade.getRequest();
|
Request request = httpFacade.getRequest();
|
||||||
Response response = httpFacade.getResponse();
|
Response response = httpFacade.getResponse();
|
||||||
String pathInfo = URI.create(request.getURI()).getPath().substring(1);
|
String path = getPath(request);
|
||||||
String path = pathInfo.substring(pathInfo.indexOf('/'), pathInfo.length());
|
|
||||||
PathConfig pathConfig = this.pathMatcher.matches(path, this.paths);
|
PathConfig pathConfig = this.pathMatcher.matches(path, this.paths);
|
||||||
|
|
||||||
LOGGER.debugf("Checking permissions for path [%s] with config [%s].", request.getURI(), pathConfig);
|
LOGGER.debugf("Checking permissions for path [%s] with config [%s].", request.getURI(), pathConfig);
|
||||||
@@ -122,12 +121,9 @@ public abstract class AbstractPolicyEnforcer {
|
|||||||
protected boolean isAuthorized(PathConfig actualPathConfig, Set<String> requiredScopes, AccessToken accessToken, OIDCHttpFacade httpFacade) {
|
protected boolean isAuthorized(PathConfig actualPathConfig, Set<String> requiredScopes, AccessToken accessToken, OIDCHttpFacade httpFacade) {
|
||||||
Request request = httpFacade.getRequest();
|
Request request = httpFacade.getRequest();
|
||||||
PolicyEnforcerConfig enforcerConfig = getEnforcerConfig();
|
PolicyEnforcerConfig enforcerConfig = getEnforcerConfig();
|
||||||
String accessDeniedPath = enforcerConfig.getOnDenyRedirectTo();
|
|
||||||
|
|
||||||
if (accessDeniedPath != null) {
|
if (isDefaultAccessDeniedUri(request, enforcerConfig)) {
|
||||||
if (request.getURI().contains(accessDeniedPath)) {
|
return true;
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
AccessToken.Authorization authorization = accessToken.getAuthorization();
|
AccessToken.Authorization authorization = accessToken.getAuthorization();
|
||||||
@@ -173,6 +169,17 @@ public abstract class AbstractPolicyEnforcer {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isDefaultAccessDeniedUri(Request request, PolicyEnforcerConfig enforcerConfig) {
|
||||||
|
String accessDeniedPath = enforcerConfig.getOnDenyRedirectTo();
|
||||||
|
|
||||||
|
if (accessDeniedPath != null) {
|
||||||
|
if (request.getURI().contains(accessDeniedPath)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
private boolean hasResourceScopePermission(Set<String> requiredScopes, Permission permission, PathConfig actualPathConfig) {
|
private boolean hasResourceScopePermission(Set<String> requiredScopes, Permission permission, PathConfig actualPathConfig) {
|
||||||
Set<String> allowedScopes = permission.getScopes();
|
Set<String> allowedScopes = permission.getScopes();
|
||||||
return (allowedScopes.containsAll(requiredScopes) || allowedScopes.isEmpty());
|
return (allowedScopes.containsAll(requiredScopes) || allowedScopes.isEmpty());
|
||||||
@@ -220,27 +227,23 @@ public abstract class AbstractPolicyEnforcer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private PathConfig resolvePathConfig(PathConfig originalConfig, Request request) {
|
private PathConfig resolvePathConfig(PathConfig originalConfig, Request request) {
|
||||||
|
String path = getPath(request);
|
||||||
|
|
||||||
if (originalConfig.hasPattern()) {
|
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();
|
ProtectedResource resource = this.authzClient.protection().resource();
|
||||||
Set<String> search = resource.findByFilter("uri=" + path);
|
Set<String> search = resource.findByFilter("uri=" + path);
|
||||||
|
|
||||||
if (!search.isEmpty()) {
|
if (!search.isEmpty()) {
|
||||||
// resource does exist on the server, cache it
|
// resource does exist on the server, cache it
|
||||||
ResourceRepresentation targetResource = resource.findById(search.iterator().next()).getResourceDescription();
|
ResourceRepresentation targetResource = resource.findById(search.iterator().next()).getResourceDescription();
|
||||||
PathConfig config = new PathConfig();
|
PathConfig config = PolicyEnforcer.createPathConfig(targetResource);
|
||||||
|
|
||||||
config.setId(targetResource.getId());
|
|
||||||
config.setName(targetResource.getName());
|
|
||||||
config.setType(targetResource.getType());
|
|
||||||
config.setPath(targetResource.getUri());
|
|
||||||
config.setScopes(originalConfig.getScopes());
|
config.setScopes(originalConfig.getScopes());
|
||||||
config.setMethods(originalConfig.getMethods());
|
config.setMethods(originalConfig.getMethods());
|
||||||
config.setParentConfig(originalConfig);
|
config.setParentConfig(originalConfig);
|
||||||
config.setEnforcementMode(originalConfig.getEnforcementMode());
|
config.setEnforcementMode(originalConfig.getEnforcementMode());
|
||||||
|
|
||||||
this.paths.add(config);
|
this.policyEnforcer.addPath(config);
|
||||||
|
|
||||||
return config;
|
return config;
|
||||||
}
|
}
|
||||||
@@ -249,6 +252,11 @@ public abstract class AbstractPolicyEnforcer {
|
|||||||
return originalConfig;
|
return originalConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String getPath(Request request) {
|
||||||
|
String pathInfo = URI.create(request.getURI()).getPath().substring(1);
|
||||||
|
return pathInfo.substring(pathInfo.indexOf('/'), pathInfo.length());
|
||||||
|
}
|
||||||
|
|
||||||
private Set<String> getRequiredScopes(PathConfig pathConfig, Request request) {
|
private Set<String> getRequiredScopes(PathConfig pathConfig, Request request) {
|
||||||
Set<String> requiredScopes = new HashSet<>();
|
Set<String> requiredScopes = new HashSet<>();
|
||||||
|
|
||||||
|
|||||||
+31
-34
@@ -17,6 +17,10 @@
|
|||||||
*/
|
*/
|
||||||
package org.keycloak.adapters.authorization;
|
package org.keycloak.adapters.authorization;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
import org.keycloak.adapters.KeycloakDeployment;
|
import org.keycloak.adapters.KeycloakDeployment;
|
||||||
import org.keycloak.adapters.OIDCHttpFacade;
|
import org.keycloak.adapters.OIDCHttpFacade;
|
||||||
@@ -34,10 +38,6 @@ import org.keycloak.representations.AccessToken;
|
|||||||
import org.keycloak.representations.adapters.config.PolicyEnforcerConfig.PathConfig;
|
import org.keycloak.representations.adapters.config.PolicyEnforcerConfig.PathConfig;
|
||||||
import org.keycloak.representations.idm.authorization.Permission;
|
import org.keycloak.representations.idm.authorization.Permission;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||||
*/
|
*/
|
||||||
@@ -51,39 +51,34 @@ public class KeycloakAdapterPolicyEnforcer extends AbstractPolicyEnforcer {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean isAuthorized(PathConfig pathConfig, Set<String> requiredScopes, AccessToken accessToken, OIDCHttpFacade httpFacade) {
|
protected boolean isAuthorized(PathConfig pathConfig, Set<String> requiredScopes, AccessToken accessToken, OIDCHttpFacade httpFacade) {
|
||||||
int retry = 2;
|
|
||||||
AccessToken original = accessToken;
|
AccessToken original = accessToken;
|
||||||
|
|
||||||
while (retry > 0) {
|
if (super.isAuthorized(pathConfig, requiredScopes, accessToken, httpFacade)) {
|
||||||
if (super.isAuthorized(pathConfig, requiredScopes, accessToken, httpFacade)) {
|
return true;
|
||||||
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;
|
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);
|
||||||
|
|
||||||
|
return super.isAuthorized(pathConfig, requiredScopes, accessToken, httpFacade);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -108,7 +103,7 @@ public class KeycloakAdapterPolicyEnforcer extends AbstractPolicyEnforcer {
|
|||||||
KeycloakDeployment deployment = getPolicyEnforcer().getDeployment();
|
KeycloakDeployment deployment = getPolicyEnforcer().getDeployment();
|
||||||
|
|
||||||
if (getEnforcerConfig().getUserManagedAccess() != null) {
|
if (getEnforcerConfig().getUserManagedAccess() != null) {
|
||||||
LOGGER.debug("Obtaining authorization for authenticated user.");
|
LOGGER.debug("Obtaining authorization for authenticated user.");
|
||||||
PermissionRequest permissionRequest = new PermissionRequest();
|
PermissionRequest permissionRequest = new PermissionRequest();
|
||||||
|
|
||||||
permissionRequest.setResourceSetId(pathConfig.getId());
|
permissionRequest.setResourceSetId(pathConfig.getId());
|
||||||
@@ -136,12 +131,14 @@ public class KeycloakAdapterPolicyEnforcer extends AbstractPolicyEnforcer {
|
|||||||
permissionRequest.setResourceSetId(pathConfig.getId());
|
permissionRequest.setResourceSetId(pathConfig.getId());
|
||||||
permissionRequest.setResourceSetName(pathConfig.getName());
|
permissionRequest.setResourceSetName(pathConfig.getName());
|
||||||
permissionRequest.setScopes(new HashSet<>(pathConfig.getScopes()));
|
permissionRequest.setScopes(new HashSet<>(pathConfig.getScopes()));
|
||||||
|
LOGGER.debugf("Sending entitlements request: resource_set_id [%s], resource_set_name [%s], scopes [%s].", permissionRequest.getResourceSetId(), permissionRequest.getResourceSetName(), permissionRequest.getScopes());
|
||||||
request.addPermission(permissionRequest);
|
request.addPermission(permissionRequest);
|
||||||
EntitlementResponse authzResponse = authzClient.entitlement(accessToken).get(authzClient.getConfiguration().getClientId(), request);
|
EntitlementResponse authzResponse = authzClient.entitlement(accessToken).get(authzClient.getConfiguration().getClientId(), request);
|
||||||
return AdapterRSATokenVerifier.verifyToken(authzResponse.getRpt(), deployment);
|
return AdapterRSATokenVerifier.verifyToken(authzResponse.getRpt(), deployment);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (AuthorizationDeniedException e) {
|
} catch (AuthorizationDeniedException e) {
|
||||||
|
LOGGER.debug("Authorization denied", e);
|
||||||
return null;
|
return null;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new RuntimeException("Unexpected error during authorization request.", e);
|
throw new RuntimeException("Unexpected error during authorization request.", e);
|
||||||
|
|||||||
+9
-3
@@ -19,7 +19,7 @@ package org.keycloak.adapters.authorization;
|
|||||||
|
|
||||||
import org.keycloak.representations.adapters.config.PolicyEnforcerConfig.PathConfig;
|
import org.keycloak.representations.adapters.config.PolicyEnforcerConfig.PathConfig;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||||
@@ -28,10 +28,16 @@ class PathMatcher {
|
|||||||
|
|
||||||
private static final String ANY_RESOURCE_PATTERN = "/*";
|
private static final String ANY_RESOURCE_PATTERN = "/*";
|
||||||
|
|
||||||
PathConfig matches(final String requestedUri, List<PathConfig> paths) {
|
PathConfig matches(final String requestedUri, Map<String, PathConfig> paths) {
|
||||||
|
PathConfig pathConfig = paths.get(requestedUri);
|
||||||
|
|
||||||
|
if (pathConfig != null) {
|
||||||
|
return pathConfig;
|
||||||
|
}
|
||||||
|
|
||||||
PathConfig actualConfig = null;
|
PathConfig actualConfig = null;
|
||||||
|
|
||||||
for (PathConfig entry : paths) {
|
for (PathConfig entry : paths.values()) {
|
||||||
String protectedUri = entry.getPath();
|
String protectedUri = entry.getPath();
|
||||||
String selectedUri = null;
|
String selectedUri = null;
|
||||||
|
|
||||||
|
|||||||
+20
-13
@@ -34,8 +34,10 @@ import org.keycloak.representations.idm.authorization.Permission;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -48,7 +50,7 @@ public class PolicyEnforcer {
|
|||||||
private final KeycloakDeployment deployment;
|
private final KeycloakDeployment deployment;
|
||||||
private final AuthzClient authzClient;
|
private final AuthzClient authzClient;
|
||||||
private final PolicyEnforcerConfig enforcerConfig;
|
private final PolicyEnforcerConfig enforcerConfig;
|
||||||
private final List<PathConfig> paths;
|
private final Map<String, PathConfig> paths;
|
||||||
|
|
||||||
public PolicyEnforcer(KeycloakDeployment deployment, AdapterConfig adapterConfig) {
|
public PolicyEnforcer(KeycloakDeployment deployment, AdapterConfig adapterConfig) {
|
||||||
this.deployment = deployment;
|
this.deployment = deployment;
|
||||||
@@ -58,7 +60,7 @@ public class PolicyEnforcer {
|
|||||||
|
|
||||||
if (LOGGER.isDebugEnabled()) {
|
if (LOGGER.isDebugEnabled()) {
|
||||||
LOGGER.debug("Initialization complete. Path configurations:");
|
LOGGER.debug("Initialization complete. Path configurations:");
|
||||||
for (PathConfig pathConfig : this.paths) {
|
for (PathConfig pathConfig : this.paths.values()) {
|
||||||
LOGGER.debug(pathConfig);
|
LOGGER.debug(pathConfig);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -96,15 +98,19 @@ public class PolicyEnforcer {
|
|||||||
return authzClient;
|
return authzClient;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<PathConfig> getPaths() {
|
public Map<String, PathConfig> getPaths() {
|
||||||
return Collections.unmodifiableList(paths);
|
return paths;
|
||||||
|
}
|
||||||
|
|
||||||
|
void addPath(PathConfig pathConfig) {
|
||||||
|
paths.put(pathConfig.getPath(), pathConfig);
|
||||||
}
|
}
|
||||||
|
|
||||||
KeycloakDeployment getDeployment() {
|
KeycloakDeployment getDeployment() {
|
||||||
return deployment;
|
return deployment;
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<PathConfig> configurePaths(ProtectedResource protectedResource, PolicyEnforcerConfig enforcerConfig) {
|
private Map<String, PathConfig> configurePaths(ProtectedResource protectedResource, PolicyEnforcerConfig enforcerConfig) {
|
||||||
boolean loadPathsFromServer = true;
|
boolean loadPathsFromServer = true;
|
||||||
|
|
||||||
for (PathConfig pathConfig : enforcerConfig.getPaths()) {
|
for (PathConfig pathConfig : enforcerConfig.getPaths()) {
|
||||||
@@ -123,8 +129,8 @@ public class PolicyEnforcer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<PathConfig> configureDefinedPaths(ProtectedResource protectedResource, PolicyEnforcerConfig enforcerConfig) {
|
private Map<String, PathConfig> configureDefinedPaths(ProtectedResource protectedResource, PolicyEnforcerConfig enforcerConfig) {
|
||||||
List<PathConfig> paths = new ArrayList<>();
|
Map<String, PathConfig> paths = Collections.synchronizedMap(new HashMap<String, PathConfig>());
|
||||||
|
|
||||||
for (PathConfig pathConfig : enforcerConfig.getPaths()) {
|
for (PathConfig pathConfig : enforcerConfig.getPaths()) {
|
||||||
Set<String> search;
|
Set<String> search;
|
||||||
@@ -172,7 +178,7 @@ public class PolicyEnforcer {
|
|||||||
|
|
||||||
PathConfig existingPath = null;
|
PathConfig existingPath = null;
|
||||||
|
|
||||||
for (PathConfig current : paths) {
|
for (PathConfig current : paths.values()) {
|
||||||
if (current.getId().equals(pathConfig.getId()) && current.getPath().equals(pathConfig.getPath())) {
|
if (current.getId().equals(pathConfig.getId()) && current.getPath().equals(pathConfig.getPath())) {
|
||||||
existingPath = current;
|
existingPath = current;
|
||||||
break;
|
break;
|
||||||
@@ -180,7 +186,7 @@ public class PolicyEnforcer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (existingPath == null) {
|
if (existingPath == null) {
|
||||||
paths.add(pathConfig);
|
paths.put(pathConfig.getPath(), pathConfig);
|
||||||
} else {
|
} else {
|
||||||
existingPath.getMethods().addAll(pathConfig.getMethods());
|
existingPath.getMethods().addAll(pathConfig.getMethods());
|
||||||
existingPath.getScopes().addAll(pathConfig.getScopes());
|
existingPath.getScopes().addAll(pathConfig.getScopes());
|
||||||
@@ -190,23 +196,24 @@ public class PolicyEnforcer {
|
|||||||
return paths;
|
return paths;
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<PathConfig> configureAllPathsForResourceServer(ProtectedResource protectedResource) {
|
private Map<String, PathConfig> configureAllPathsForResourceServer(ProtectedResource protectedResource) {
|
||||||
LOGGER.info("Querying the server for all resources associated with this application.");
|
LOGGER.info("Querying the server for all resources associated with this application.");
|
||||||
List<PathConfig> paths = new ArrayList<>();
|
Map<String, PathConfig> paths = Collections.synchronizedMap(new HashMap<String, PathConfig>());
|
||||||
|
|
||||||
for (String id : protectedResource.findAll()) {
|
for (String id : protectedResource.findAll()) {
|
||||||
RegistrationResponse response = protectedResource.findById(id);
|
RegistrationResponse response = protectedResource.findById(id);
|
||||||
ResourceRepresentation resourceDescription = response.getResourceDescription();
|
ResourceRepresentation resourceDescription = response.getResourceDescription();
|
||||||
|
|
||||||
if (resourceDescription.getUri() != null) {
|
if (resourceDescription.getUri() != null) {
|
||||||
paths.add(createPathConfig(resourceDescription));
|
PathConfig pathConfig = createPathConfig(resourceDescription);
|
||||||
|
paths.put(pathConfig.getPath(), pathConfig);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return paths;
|
return paths;
|
||||||
}
|
}
|
||||||
|
|
||||||
private PathConfig createPathConfig(ResourceRepresentation resourceDescription) {
|
static PathConfig createPathConfig(ResourceRepresentation resourceDescription) {
|
||||||
PathConfig pathConfig = new PathConfig();
|
PathConfig pathConfig = new PathConfig();
|
||||||
|
|
||||||
pathConfig.setId(resourceDescription.getId());
|
pathConfig.setId(resourceDescription.getId());
|
||||||
|
|||||||
+5
@@ -37,4 +37,9 @@ public class HardcodedPublicKeyLocator implements PublicKeyLocator {
|
|||||||
public PublicKey getPublicKey(String kid, KeycloakDeployment deployment) {
|
public PublicKey getPublicKey(String kid, KeycloakDeployment deployment) {
|
||||||
return publicKey;
|
return publicKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void reset(KeycloakDeployment deployment) {
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+30
-16
@@ -25,7 +25,6 @@ import org.keycloak.adapters.KeycloakDeployment;
|
|||||||
import org.keycloak.common.util.Time;
|
import org.keycloak.common.util.Time;
|
||||||
import org.keycloak.jose.jwk.JSONWebKeySet;
|
import org.keycloak.jose.jwk.JSONWebKeySet;
|
||||||
import org.keycloak.jose.jwk.JWK;
|
import org.keycloak.jose.jwk.JWK;
|
||||||
import org.keycloak.jose.jws.JWSInput;
|
|
||||||
import org.keycloak.util.JWKSUtils;
|
import org.keycloak.util.JWKSUtils;
|
||||||
|
|
||||||
import java.security.PublicKey;
|
import java.security.PublicKey;
|
||||||
@@ -48,36 +47,51 @@ public class JWKPublicKeyLocator implements PublicKeyLocator {
|
|||||||
@Override
|
@Override
|
||||||
public PublicKey getPublicKey(String kid, KeycloakDeployment deployment) {
|
public PublicKey getPublicKey(String kid, KeycloakDeployment deployment) {
|
||||||
int minTimeBetweenRequests = deployment.getMinTimeBetweenJwksRequests();
|
int minTimeBetweenRequests = deployment.getMinTimeBetweenJwksRequests();
|
||||||
|
int publicKeyCacheTtl = deployment.getPublicKeyCacheTtl();
|
||||||
|
int currentTime = Time.currentTime();
|
||||||
|
|
||||||
// Check if key is in cache.
|
// Check if key is in cache.
|
||||||
PublicKey publicKey = currentKeys.get(kid);
|
PublicKey publicKey = lookupCachedKey(publicKeyCacheTtl, currentTime, kid);
|
||||||
if (publicKey != null) {
|
if (publicKey != null) {
|
||||||
return publicKey;
|
return publicKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
int currentTime = Time.currentTime();
|
|
||||||
|
|
||||||
// Check if we are allowed to send request
|
// Check if we are allowed to send request
|
||||||
if (currentTime > lastRequestTime + minTimeBetweenRequests) {
|
synchronized (this) {
|
||||||
synchronized (this) {
|
currentTime = Time.currentTime();
|
||||||
currentTime = Time.currentTime();
|
if (currentTime > lastRequestTime + minTimeBetweenRequests) {
|
||||||
if (currentTime > lastRequestTime + minTimeBetweenRequests) {
|
sendRequest(deployment);
|
||||||
sendRequest(deployment);
|
lastRequestTime = currentTime;
|
||||||
lastRequestTime = currentTime;
|
} else {
|
||||||
} else {
|
log.debug("Won't send request to realm jwks url. Last request time was " + lastRequestTime);
|
||||||
log.debugf("Won't send request to realm jwks url. Last request time was %d", lastRequestTime);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return lookupCachedKey(publicKeyCacheTtl, currentTime, kid);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return currentKeys.get(kid);
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void reset(KeycloakDeployment deployment) {
|
||||||
|
synchronized (this) {
|
||||||
|
sendRequest(deployment);
|
||||||
|
lastRequestTime = Time.currentTime();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private PublicKey lookupCachedKey(int publicKeyCacheTtl, int currentTime, String kid) {
|
||||||
|
if (lastRequestTime + publicKeyCacheTtl > currentTime) {
|
||||||
|
return currentKeys.get(kid);
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void sendRequest(KeycloakDeployment deployment) {
|
private void sendRequest(KeycloakDeployment deployment) {
|
||||||
if (log.isTraceEnabled()) {
|
if (log.isTraceEnabled()) {
|
||||||
log.tracef("Going to send request to retrieve new set of realm public keys for client %s", deployment.getResourceName());
|
log.trace("Going to send request to retrieve new set of realm public keys for client " + deployment.getResourceName());
|
||||||
}
|
}
|
||||||
|
|
||||||
HttpGet getMethod = new HttpGet(deployment.getJwksUrl());
|
HttpGet getMethod = new HttpGet(deployment.getJwksUrl());
|
||||||
@@ -87,7 +101,7 @@ public class JWKPublicKeyLocator implements PublicKeyLocator {
|
|||||||
Map<String, PublicKey> publicKeys = JWKSUtils.getKeysForUse(jwks, JWK.Use.SIG);
|
Map<String, PublicKey> publicKeys = JWKSUtils.getKeysForUse(jwks, JWK.Use.SIG);
|
||||||
|
|
||||||
if (log.isDebugEnabled()) {
|
if (log.isDebugEnabled()) {
|
||||||
log.debugf("Realm public keys successfully retrieved for client %s. New kids: %s", deployment.getResourceName(), publicKeys.keySet().toString());
|
log.debug("Realm public keys successfully retrieved for client " + deployment.getResourceName() + ". New kids: " + publicKeys.keySet().toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update current keys
|
// Update current keys
|
||||||
|
|||||||
+7
@@ -34,4 +34,11 @@ public interface PublicKeyLocator {
|
|||||||
*/
|
*/
|
||||||
PublicKey getPublicKey(String kid, KeycloakDeployment deployment);
|
PublicKey getPublicKey(String kid, KeycloakDeployment deployment);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset the state of locator (eg. clear the cached keys)
|
||||||
|
*
|
||||||
|
* @param deployment
|
||||||
|
*/
|
||||||
|
void reset(KeycloakDeployment deployment);
|
||||||
|
|
||||||
}
|
}
|
||||||
+2
@@ -69,6 +69,7 @@ public class KeycloakDeploymentBuilderTest {
|
|||||||
assertEquals("email", deployment.getPrincipalAttribute());
|
assertEquals("email", deployment.getPrincipalAttribute());
|
||||||
assertEquals(10, deployment.getTokenMinimumTimeToLive());
|
assertEquals(10, deployment.getTokenMinimumTimeToLive());
|
||||||
assertEquals(20, deployment.getMinTimeBetweenJwksRequests());
|
assertEquals(20, deployment.getMinTimeBetweenJwksRequests());
|
||||||
|
assertEquals(120, deployment.getPublicKeyCacheTtl());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -78,6 +79,7 @@ public class KeycloakDeploymentBuilderTest {
|
|||||||
|
|
||||||
assertTrue(deployment.getPublicKeyLocator() instanceof JWKPublicKeyLocator);
|
assertTrue(deployment.getPublicKeyLocator() instanceof JWKPublicKeyLocator);
|
||||||
assertEquals(10, deployment.getMinTimeBetweenJwksRequests());
|
assertEquals(10, deployment.getMinTimeBetweenJwksRequests());
|
||||||
|
assertEquals(86400, deployment.getPublicKeyCacheTtl());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@@ -30,5 +30,6 @@
|
|||||||
"token-store": "cookie",
|
"token-store": "cookie",
|
||||||
"principal-attribute": "email",
|
"principal-attribute": "email",
|
||||||
"token-minimum-time-to-live": 10,
|
"token-minimum-time-to-live": 10,
|
||||||
"min-time-between-jwks-requests": 20
|
"min-time-between-jwks-requests": 20,
|
||||||
|
"public-key-cache-ttl": 120
|
||||||
}
|
}
|
||||||
@@ -21,7 +21,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-as7-integration-pom</artifactId>
|
<artifactId>keycloak-as7-integration-pom</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>2.4.0.Final</version>
|
<version>2.5.0.Final</version>
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-as7-integration-pom</artifactId>
|
<artifactId>keycloak-as7-integration-pom</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>2.4.0.Final</version>
|
<version>2.5.0.Final</version>
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<artifactId>keycloak-as7-integration-pom</artifactId>
|
<artifactId>keycloak-as7-integration-pom</artifactId>
|
||||||
<version>2.4.0.Final</version>
|
<version>2.5.0.Final</version>
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>2.4.0.Final</version>
|
<version>2.5.0.Final</version>
|
||||||
<relativePath>../../../pom.xml</relativePath>
|
<relativePath>../../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<name>Keycloak AS7 / JBoss EAP 6 Integration</name>
|
<name>Keycloak AS7 / JBoss EAP 6 Integration</name>
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>2.4.0.Final</version>
|
<version>2.5.0.Final</version>
|
||||||
<relativePath>../../../pom.xml</relativePath>
|
<relativePath>../../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>2.4.0.Final</version>
|
<version>2.5.0.Final</version>
|
||||||
<relativePath>../../../pom.xml</relativePath>
|
<relativePath>../../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>2.4.0.Final</version>
|
<version>2.5.0.Final</version>
|
||||||
<relativePath>../../../../pom.xml</relativePath>
|
<relativePath>../../../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>2.4.0.Final</version>
|
<version>2.5.0.Final</version>
|
||||||
<relativePath>../../../../pom.xml</relativePath>
|
<relativePath>../../../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>2.4.0.Final</version>
|
<version>2.5.0.Final</version>
|
||||||
<relativePath>../../../../pom.xml</relativePath>
|
<relativePath>../../../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>2.4.0.Final</version>
|
<version>2.5.0.Final</version>
|
||||||
<relativePath>../../../../pom.xml</relativePath>
|
<relativePath>../../../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>2.4.0.Final</version>
|
<version>2.5.0.Final</version>
|
||||||
<relativePath>../../../../pom.xml</relativePath>
|
<relativePath>../../../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>2.4.0.Final</version>
|
<version>2.5.0.Final</version>
|
||||||
<relativePath>../../../pom.xml</relativePath>
|
<relativePath>../../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<name>Keycloak Jetty Integration</name>
|
<name>Keycloak Jetty Integration</name>
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>2.4.0.Final</version>
|
<version>2.5.0.Final</version>
|
||||||
<relativePath>../../../pom.xml</relativePath>
|
<relativePath>../../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|||||||
@@ -846,14 +846,15 @@
|
|||||||
kc.clearToken();
|
kc.clearToken();
|
||||||
}
|
}
|
||||||
|
|
||||||
for (var i = loginIframe.callbackList.length - 1; i >= 0; --i) {
|
var callbacks = loginIframe.callbackList.splice(0, loginIframe.callbackList.length);
|
||||||
var promise = loginIframe.callbackList[i];
|
|
||||||
|
for (var i = callbacks.length - 1; i >= 0; --i) {
|
||||||
|
var promise = callbacks[i];
|
||||||
if (event.data == "unchanged") {
|
if (event.data == "unchanged") {
|
||||||
promise.setSuccess();
|
promise.setSuccess();
|
||||||
} else {
|
} else {
|
||||||
promise.setError();
|
promise.setError();
|
||||||
}
|
}
|
||||||
loginIframe.callbackList.splice(i, 1);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -35,14 +35,14 @@
|
|||||||
req.open('GET', url, true);
|
req.open('GET', url, true);
|
||||||
|
|
||||||
req.onreadystatechange = function () {
|
req.onreadystatechange = function () {
|
||||||
if (req.readyState == 4) {
|
if (req.readyState === 4) {
|
||||||
if (req.status == 204) {
|
if (req.status === 204) {
|
||||||
init = {
|
init = {
|
||||||
clientId: clientId,
|
clientId: clientId,
|
||||||
origin: origin
|
origin: origin
|
||||||
}
|
}
|
||||||
callback('unchanged');
|
callback('unchanged');
|
||||||
} else if (req.status = 404) {
|
} else if (req.status === 404) {
|
||||||
callback('changed');
|
callback('changed');
|
||||||
} else {
|
} else {
|
||||||
callback('error');
|
callback('error');
|
||||||
@@ -52,8 +52,8 @@
|
|||||||
|
|
||||||
req.send();
|
req.send();
|
||||||
} else {
|
} else {
|
||||||
if (clientId == init.clientId && origin == init.origin) {
|
if (clientId === init.clientId && origin === init.origin) {
|
||||||
if (sessionState == cookie) {
|
if (sessionState === cookie) {
|
||||||
callback('unchanged');
|
callback('unchanged');
|
||||||
} else {
|
} else {
|
||||||
callback('changed');
|
callback('changed');
|
||||||
@@ -71,7 +71,7 @@
|
|||||||
for(var i=0; i<ca.length; i++)
|
for(var i=0; i<ca.length; i++)
|
||||||
{
|
{
|
||||||
var c = ca[i].trim();
|
var c = ca[i].trim();
|
||||||
if (c.indexOf(name)==0) return c.substring(name.length,c.length);
|
if (c.indexOf(name)===0) return c.substring(name.length,c.length);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -95,4 +95,4 @@
|
|||||||
window.addEventListener("message", receiveMessage, false);
|
window.addEventListener("message", receiveMessage, false);
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
@@ -21,7 +21,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>2.4.0.Final</version>
|
<version>2.5.0.Final</version>
|
||||||
<relativePath>../../../pom.xml</relativePath>
|
<relativePath>../../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>2.4.0.Final</version>
|
<version>2.5.0.Final</version>
|
||||||
<relativePath>../../pom.xml</relativePath>
|
<relativePath>../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<name>Keycloak OIDC Client Adapter Modules</name>
|
<name>Keycloak OIDC Client Adapter Modules</name>
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>2.4.0.Final</version>
|
<version>2.5.0.Final</version>
|
||||||
<relativePath>../../../pom.xml</relativePath>
|
<relativePath>../../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>2.4.0.Final</version>
|
<version>2.5.0.Final</version>
|
||||||
<relativePath>../../../pom.xml</relativePath>
|
<relativePath>../../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>2.4.0.Final</version>
|
<version>2.5.0.Final</version>
|
||||||
<relativePath>../../../pom.xml</relativePath>
|
<relativePath>../../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>2.4.0.Final</version>
|
<version>2.5.0.Final</version>
|
||||||
<relativePath>../../../pom.xml</relativePath>
|
<relativePath>../../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|||||||
+12
-2
@@ -30,6 +30,12 @@ import javax.servlet.ServletException;
|
|||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import org.keycloak.adapters.AdapterDeploymentContext;
|
||||||
|
import org.keycloak.adapters.spi.HttpFacade;
|
||||||
|
import org.keycloak.adapters.springsecurity.config.KeycloakWebSecurityConfigurerAdapter;
|
||||||
|
import org.keycloak.adapters.springsecurity.facade.SimpleHttpFacade;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides a Keycloak {@link AuthenticationEntryPoint authentication entry point}. Uses a
|
* Provides a Keycloak {@link AuthenticationEntryPoint authentication entry point}. Uses a
|
||||||
@@ -56,12 +62,15 @@ public class KeycloakAuthenticationEntryPoint implements AuthenticationEntryPoin
|
|||||||
private final RequestMatcher apiRequestMatcher;
|
private final RequestMatcher apiRequestMatcher;
|
||||||
private String loginUri = DEFAULT_LOGIN_URI;
|
private String loginUri = DEFAULT_LOGIN_URI;
|
||||||
private String realm = DEFAULT_REALM;
|
private String realm = DEFAULT_REALM;
|
||||||
|
|
||||||
|
private AdapterDeploymentContext adapterDeploymentContext;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new Keycloak authentication entry point.
|
* Creates a new Keycloak authentication entry point.
|
||||||
*/
|
*/
|
||||||
public KeycloakAuthenticationEntryPoint() {
|
public KeycloakAuthenticationEntryPoint(AdapterDeploymentContext adapterDeploymentContext) {
|
||||||
this(DEFAULT_API_REQUEST_MATCHER);
|
this(DEFAULT_API_REQUEST_MATCHER);
|
||||||
|
this.adapterDeploymentContext = adapterDeploymentContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -79,7 +88,8 @@ public class KeycloakAuthenticationEntryPoint implements AuthenticationEntryPoin
|
|||||||
@Override
|
@Override
|
||||||
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException
|
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException
|
||||||
{
|
{
|
||||||
if (apiRequestMatcher.matches(request)) {
|
HttpFacade facade = new SimpleHttpFacade(request, response);
|
||||||
|
if (apiRequestMatcher.matches(request) || adapterDeploymentContext.resolveDeployment(facade).isBearerOnly()) {
|
||||||
commenceUnauthorizedResponse(request, response);
|
commenceUnauthorizedResponse(request, response);
|
||||||
} else {
|
} else {
|
||||||
commenceLoginRedirect(request, response);
|
commenceLoginRedirect(request, response);
|
||||||
|
|||||||
+2
-2
@@ -71,8 +71,8 @@ public abstract class KeycloakWebSecurityConfigurerAdapter extends WebSecurityCo
|
|||||||
return factoryBean.getObject();
|
return factoryBean.getObject();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected AuthenticationEntryPoint authenticationEntryPoint() {
|
protected AuthenticationEntryPoint authenticationEntryPoint() throws Exception {
|
||||||
return new KeycloakAuthenticationEntryPoint();
|
return new KeycloakAuthenticationEntryPoint(adapterDeploymentContext());
|
||||||
}
|
}
|
||||||
|
|
||||||
protected KeycloakAuthenticationProvider keycloakAuthenticationProvider() {
|
protected KeycloakAuthenticationProvider keycloakAuthenticationProvider() {
|
||||||
|
|||||||
+90
@@ -0,0 +1,90 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||||
|
* and other contributors as indicated by the @author tags.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.keycloak.adapters.springsecurity.filter;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import javax.servlet.FilterChain;
|
||||||
|
import javax.servlet.ServletException;
|
||||||
|
import javax.servlet.ServletRequest;
|
||||||
|
import javax.servlet.ServletResponse;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
import org.keycloak.adapters.AdapterDeploymentContext;
|
||||||
|
import org.keycloak.adapters.AuthenticatedActionsHandler;
|
||||||
|
import org.keycloak.adapters.NodesRegistrationManagement;
|
||||||
|
import org.keycloak.adapters.OIDCHttpFacade;
|
||||||
|
import org.keycloak.adapters.spi.HttpFacade;
|
||||||
|
import org.keycloak.adapters.springsecurity.facade.SimpleHttpFacade;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.BeansException;
|
||||||
|
import org.springframework.context.ApplicationContext;
|
||||||
|
import org.springframework.context.ApplicationContextAware;
|
||||||
|
import org.springframework.web.filter.GenericFilterBean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exposes a Keycloak adapter {@link AuthenticatedActionsHandler} as a Spring Security filter.
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:srossillo@smartling.com">Scott Rossillo</a>
|
||||||
|
* @version $Revision: 1 $
|
||||||
|
*/
|
||||||
|
public class KeycloakAuthenticatedActionsFilter extends GenericFilterBean implements ApplicationContextAware {
|
||||||
|
|
||||||
|
private static final Logger log = LoggerFactory.getLogger(KeycloakAuthenticatedActionsFilter.class);
|
||||||
|
|
||||||
|
private final NodesRegistrationManagement management = new NodesRegistrationManagement();
|
||||||
|
private ApplicationContext applicationContext;
|
||||||
|
private AdapterDeploymentContext deploymentContext;
|
||||||
|
|
||||||
|
|
||||||
|
public KeycloakAuthenticatedActionsFilter() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void initFilterBean() throws ServletException {
|
||||||
|
deploymentContext = applicationContext.getBean(AdapterDeploymentContext.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void destroy() {
|
||||||
|
log.debug("Unregistering deployment");
|
||||||
|
management.stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
|
||||||
|
throws IOException, ServletException {
|
||||||
|
|
||||||
|
HttpFacade facade = new SimpleHttpFacade((HttpServletRequest)request, (HttpServletResponse)response);
|
||||||
|
AuthenticatedActionsHandler handler = new AuthenticatedActionsHandler(deploymentContext.resolveDeployment(facade), (OIDCHttpFacade)facade);
|
||||||
|
boolean handled = handler.handledRequest();
|
||||||
|
if (handled) {
|
||||||
|
log.debug("Authenticated filter handled request: {}", ((HttpServletRequest) request).getRequestURI());
|
||||||
|
} else {
|
||||||
|
chain.doFilter(request, response);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
|
||||||
|
this.applicationContext = applicationContext;
|
||||||
|
}
|
||||||
|
}
|
||||||
+1
@@ -142,6 +142,7 @@ public class KeycloakAuthenticationProcessingFilter extends AbstractAuthenticati
|
|||||||
if (AuthOutcome.FAILED.equals(result)) {
|
if (AuthOutcome.FAILED.equals(result)) {
|
||||||
throw new KeycloakAuthenticationException("Auth outcome: " + result);
|
throw new KeycloakAuthenticationException("Auth outcome: " + result);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (AuthOutcome.AUTHENTICATED.equals(result)) {
|
else if (AuthOutcome.AUTHENTICATED.equals(result)) {
|
||||||
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
|
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
|
||||||
Assert.notNull(authentication, "Authentication SecurityContextHolder was null");
|
Assert.notNull(authentication, "Authentication SecurityContextHolder was null");
|
||||||
|
|||||||
+22
-1
@@ -26,6 +26,15 @@ import org.springframework.mock.web.MockHttpServletResponse;
|
|||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertNotNull;
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
import org.keycloak.adapters.AdapterDeploymentContext;
|
||||||
|
import org.keycloak.adapters.KeycloakDeployment;
|
||||||
|
import org.keycloak.adapters.spi.HttpFacade;
|
||||||
|
import static org.mockito.Matchers.any;
|
||||||
|
import static org.mockito.Matchers.eq;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
import org.mockito.MockitoAnnotations;
|
||||||
|
import org.springframework.context.ApplicationContext;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Keycloak authentication entry point tests.
|
* Keycloak authentication entry point tests.
|
||||||
@@ -35,12 +44,24 @@ public class KeycloakAuthenticationEntryPointTest {
|
|||||||
private KeycloakAuthenticationEntryPoint authenticationEntryPoint;
|
private KeycloakAuthenticationEntryPoint authenticationEntryPoint;
|
||||||
private MockHttpServletRequest request;
|
private MockHttpServletRequest request;
|
||||||
private MockHttpServletResponse response;
|
private MockHttpServletResponse response;
|
||||||
|
@Mock
|
||||||
|
private ApplicationContext applicationContext;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private AdapterDeploymentContext adapterDeploymentContext;
|
||||||
|
|
||||||
|
@Mock
|
||||||
|
private KeycloakDeployment keycloakDeployment;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() throws Exception {
|
public void setUp() throws Exception {
|
||||||
authenticationEntryPoint = new KeycloakAuthenticationEntryPoint();
|
MockitoAnnotations.initMocks(this);
|
||||||
|
authenticationEntryPoint = new KeycloakAuthenticationEntryPoint(adapterDeploymentContext);
|
||||||
request = new MockHttpServletRequest();
|
request = new MockHttpServletRequest();
|
||||||
response = new MockHttpServletResponse();
|
response = new MockHttpServletResponse();
|
||||||
|
when(applicationContext.getBean(eq(AdapterDeploymentContext.class))).thenReturn(adapterDeploymentContext);
|
||||||
|
when(adapterDeploymentContext.resolveDeployment(any(HttpFacade.class))).thenReturn(keycloakDeployment);
|
||||||
|
when(keycloakDeployment.isBearerOnly()).thenReturn(Boolean.FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
+1
@@ -154,6 +154,7 @@ public class KeycloakAuthenticationProcessingFilterTest {
|
|||||||
when(keycloakDeployment.getResourceName()).thenReturn("resource-name");
|
when(keycloakDeployment.getResourceName()).thenReturn("resource-name");
|
||||||
when(keycloakDeployment.getStateCookieName()).thenReturn("kc-cookie");
|
when(keycloakDeployment.getStateCookieName()).thenReturn("kc-cookie");
|
||||||
when(keycloakDeployment.getSslRequired()).thenReturn(SslRequired.NONE);
|
when(keycloakDeployment.getSslRequired()).thenReturn(SslRequired.NONE);
|
||||||
|
when(keycloakDeployment.isBearerOnly()).thenReturn(Boolean.FALSE);
|
||||||
filter.attemptAuthentication(request, response);
|
filter.attemptAuthentication(request, response);
|
||||||
|
|
||||||
verify(response).setStatus(302);
|
verify(response).setStatus(302);
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>2.4.0.Final</version>
|
<version>2.5.0.Final</version>
|
||||||
<relativePath>../../../pom.xml</relativePath>
|
<relativePath>../../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<name>Keycloak Tomcat Integration</name>
|
<name>Keycloak Tomcat Integration</name>
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-tomcat-integration-pom</artifactId>
|
<artifactId>keycloak-tomcat-integration-pom</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>2.4.0.Final</version>
|
<version>2.5.0.Final</version>
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-tomcat-integration-pom</artifactId>
|
<artifactId>keycloak-tomcat-integration-pom</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>2.4.0.Final</version>
|
<version>2.5.0.Final</version>
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-tomcat-integration-pom</artifactId>
|
<artifactId>keycloak-tomcat-integration-pom</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>2.4.0.Final</version>
|
<version>2.5.0.Final</version>
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-tomcat-integration-pom</artifactId>
|
<artifactId>keycloak-tomcat-integration-pom</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>2.4.0.Final</version>
|
<version>2.5.0.Final</version>
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>2.4.0.Final</version>
|
<version>2.5.0.Final</version>
|
||||||
<relativePath>../../../pom.xml</relativePath>
|
<relativePath>../../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>2.4.0.Final</version>
|
<version>2.5.0.Final</version>
|
||||||
<relativePath>../../../pom.xml</relativePath>
|
<relativePath>../../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<name>Keycloak WildFly Integration</name>
|
<name>Keycloak WildFly Integration</name>
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<version>2.4.0.Final</version>
|
<version>2.5.0.Final</version>
|
||||||
<relativePath>../../../../pom.xml</relativePath>
|
<relativePath>../../../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>2.4.0.Final</version>
|
<version>2.5.0.Final</version>
|
||||||
<relativePath>../../../../pom.xml</relativePath>
|
<relativePath>../../../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<version>2.4.0.Final</version>
|
<version>2.5.0.Final</version>
|
||||||
<relativePath>../../../../pom.xml</relativePath>
|
<relativePath>../../../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -20,10 +20,10 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>2.4.0.Final</version>
|
<version>2.5.0.Final</version>
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<name>Keycloak Integration</name>
|
<name>Keycloak Adapters</name>
|
||||||
<description/>
|
<description/>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-saml-eap-integration-pom</artifactId>
|
<artifactId>keycloak-saml-eap-integration-pom</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>2.4.0.Final</version>
|
<version>2.5.0.Final</version>
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>2.4.0.Final</version>
|
<version>2.5.0.Final</version>
|
||||||
<relativePath>../../../pom.xml</relativePath>
|
<relativePath>../../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<name>Keycloak SAML EAP Integration</name>
|
<name>Keycloak SAML EAP Integration</name>
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<artifactId>keycloak-saml-eap-integration-pom</artifactId>
|
<artifactId>keycloak-saml-eap-integration-pom</artifactId>
|
||||||
<version>2.4.0.Final</version>
|
<version>2.5.0.Final</version>
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>2.4.0.Final</version>
|
<version>2.5.0.Final</version>
|
||||||
<relativePath>../../../pom.xml</relativePath>
|
<relativePath>../../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>2.4.0.Final</version>
|
<version>2.5.0.Final</version>
|
||||||
<relativePath>../../../pom.xml</relativePath>
|
<relativePath>../../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ public class SamlUtil {
|
|||||||
httpFacade.getResponse().setHeader("Content-Type", "text/html");
|
httpFacade.getResponse().setHeader("Content-Type", "text/html");
|
||||||
httpFacade.getResponse().setHeader("Pragma", "no-cache");
|
httpFacade.getResponse().setHeader("Pragma", "no-cache");
|
||||||
httpFacade.getResponse().setHeader("Cache-Control", "no-cache, no-store");
|
httpFacade.getResponse().setHeader("Cache-Control", "no-cache, no-store");
|
||||||
httpFacade.getResponse().getOutputStream().write(html.getBytes());
|
httpFacade.getResponse().getOutputStream().write(html.getBytes(GeneralConstants.SAML_CHARSET));
|
||||||
httpFacade.getResponse().end();
|
httpFacade.getResponse().end();
|
||||||
} else {
|
} else {
|
||||||
String uri = asRequest ? binding.redirectBinding(document).requestURI(actionUrl).toString() : binding.redirectBinding(document).responseURI(actionUrl).toString();
|
String uri = asRequest ? binding.redirectBinding(document).requestURI(actionUrl).toString() : binding.redirectBinding(document).responseURI(actionUrl).toString();
|
||||||
|
|||||||
+1
-5
@@ -571,12 +571,8 @@ public abstract class AbstractSamlAuthenticationHandler implements SamlAuthentic
|
|||||||
key = locator.getKey(keyId);
|
key = locator.getKey(keyId);
|
||||||
boolean keyLocated = key != null;
|
boolean keyLocated = key != null;
|
||||||
|
|
||||||
if (validateRedirectBindingSignatureForKey(sigAlg, rawQueryBytes, decodedSignature, key)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (keyLocated) {
|
if (keyLocated) {
|
||||||
return false;
|
return validateRedirectBindingSignatureForKey(sigAlg, rawQueryBytes, decodedSignature, key);
|
||||||
}
|
}
|
||||||
} catch (KeyManagementException ex) {
|
} catch (KeyManagementException ex) {
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>2.4.0.Final</version>
|
<version>2.5.0.Final</version>
|
||||||
<relativePath>../../../../pom.xml</relativePath>
|
<relativePath>../../../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>2.4.0.Final</version>
|
<version>2.5.0.Final</version>
|
||||||
<relativePath>../../../../pom.xml</relativePath>
|
<relativePath>../../../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>2.4.0.Final</version>
|
<version>2.5.0.Final</version>
|
||||||
<relativePath>../../../../pom.xml</relativePath>
|
<relativePath>../../../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>2.4.0.Final</version>
|
<version>2.5.0.Final</version>
|
||||||
<relativePath>../../../../pom.xml</relativePath>
|
<relativePath>../../../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>2.4.0.Final</version>
|
<version>2.5.0.Final</version>
|
||||||
<relativePath>../../../../pom.xml</relativePath>
|
<relativePath>../../../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>2.4.0.Final</version>
|
<version>2.5.0.Final</version>
|
||||||
<relativePath>../../../pom.xml</relativePath>
|
<relativePath>../../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<name>Keycloak SAML Jetty Integration</name>
|
<name>Keycloak SAML Jetty Integration</name>
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>2.4.0.Final</version>
|
<version>2.5.0.Final</version>
|
||||||
<relativePath>../../pom.xml</relativePath>
|
<relativePath>../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<name>Keycloak SAML Client Adapter Modules</name>
|
<name>Keycloak SAML Client Adapter Modules</name>
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>2.4.0.Final</version>
|
<version>2.5.0.Final</version>
|
||||||
<relativePath>../../../pom.xml</relativePath>
|
<relativePath>../../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>2.4.0.Final</version>
|
<version>2.5.0.Final</version>
|
||||||
<relativePath>../../../pom.xml</relativePath>
|
<relativePath>../../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<name>Keycloak SAML Tomcat Integration</name>
|
<name>Keycloak SAML Tomcat Integration</name>
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-saml-tomcat-integration-pom</artifactId>
|
<artifactId>keycloak-saml-tomcat-integration-pom</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>2.4.0.Final</version>
|
<version>2.5.0.Final</version>
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-saml-tomcat-integration-pom</artifactId>
|
<artifactId>keycloak-saml-tomcat-integration-pom</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>2.4.0.Final</version>
|
<version>2.5.0.Final</version>
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-saml-tomcat-integration-pom</artifactId>
|
<artifactId>keycloak-saml-tomcat-integration-pom</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>2.4.0.Final</version>
|
<version>2.5.0.Final</version>
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-saml-tomcat-integration-pom</artifactId>
|
<artifactId>keycloak-saml-tomcat-integration-pom</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>2.4.0.Final</version>
|
<version>2.5.0.Final</version>
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>2.4.0.Final</version>
|
<version>2.5.0.Final</version>
|
||||||
<relativePath>../../../pom.xml</relativePath>
|
<relativePath>../../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>2.4.0.Final</version>
|
<version>2.5.0.Final</version>
|
||||||
<relativePath>../../../pom.xml</relativePath>
|
<relativePath>../../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<name>Keycloak SAML Wildfly Integration</name>
|
<name>Keycloak SAML Wildfly Integration</name>
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>2.4.0.Final</version>
|
<version>2.5.0.Final</version>
|
||||||
<relativePath>../../../../pom.xml</relativePath>
|
<relativePath>../../../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<version>2.4.0.Final</version>
|
<version>2.5.0.Final</version>
|
||||||
<relativePath>../../../../pom.xml</relativePath>
|
<relativePath>../../../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>2.4.0.Final</version>
|
<version>2.5.0.Final</version>
|
||||||
<relativePath>../../../pom.xml</relativePath>
|
<relativePath>../../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>2.4.0.Final</version>
|
<version>2.5.0.Final</version>
|
||||||
<relativePath>../../../pom.xml</relativePath>
|
<relativePath>../../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>2.4.0.Final</version>
|
<version>2.5.0.Final</version>
|
||||||
<relativePath>../../../pom.xml</relativePath>
|
<relativePath>../../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>2.4.0.Final</version>
|
<version>2.5.0.Final</version>
|
||||||
<relativePath>../../pom.xml</relativePath>
|
<relativePath>../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<name>Keycloak Client Adapter SPI Modules</name>
|
<name>Keycloak Client Adapter SPI Modules</name>
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>2.4.0.Final</version>
|
<version>2.5.0.Final</version>
|
||||||
<relativePath>../../../pom.xml</relativePath>
|
<relativePath>../../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>2.4.0.Final</version>
|
<version>2.5.0.Final</version>
|
||||||
<relativePath>../../../pom.xml</relativePath>
|
<relativePath>../../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>2.4.0.Final</version>
|
<version>2.5.0.Final</version>
|
||||||
<relativePath>../../../pom.xml</relativePath>
|
<relativePath>../../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<artifactId>keycloak-authz-parent</artifactId>
|
<artifactId>keycloak-authz-parent</artifactId>
|
||||||
<version>2.4.0.Final</version>
|
<version>2.5.0.Final</version>
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|||||||
@@ -25,7 +25,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<artifactId>keycloak-authz-provider-parent</artifactId>
|
<artifactId>keycloak-authz-provider-parent</artifactId>
|
||||||
<version>2.4.0.Final</version>
|
<version>2.5.0.Final</version>
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|||||||
+8
-14
@@ -17,6 +17,8 @@
|
|||||||
*/
|
*/
|
||||||
package org.keycloak.authorization.policy.provider.aggregated;
|
package org.keycloak.authorization.policy.provider.aggregated;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import org.keycloak.authorization.AuthorizationProvider;
|
import org.keycloak.authorization.AuthorizationProvider;
|
||||||
import org.keycloak.authorization.model.Policy;
|
import org.keycloak.authorization.model.Policy;
|
||||||
import org.keycloak.authorization.policy.evaluation.DecisionResultCollector;
|
import org.keycloak.authorization.policy.evaluation.DecisionResultCollector;
|
||||||
@@ -26,21 +28,11 @@ import org.keycloak.authorization.policy.evaluation.Result;
|
|||||||
import org.keycloak.authorization.policy.provider.PolicyProvider;
|
import org.keycloak.authorization.policy.provider.PolicyProvider;
|
||||||
import org.keycloak.authorization.policy.provider.PolicyProviderFactory;
|
import org.keycloak.authorization.policy.provider.PolicyProviderFactory;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||||
*/
|
*/
|
||||||
public class AggregatePolicyProvider implements PolicyProvider {
|
public class AggregatePolicyProvider implements PolicyProvider {
|
||||||
|
|
||||||
private final Policy policy;
|
|
||||||
private final AuthorizationProvider authorization;
|
|
||||||
|
|
||||||
public AggregatePolicyProvider(Policy policy, AuthorizationProvider authorization) {
|
|
||||||
this.policy = policy;
|
|
||||||
this.authorization = authorization;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void evaluate(Evaluation evaluation) {
|
public void evaluate(Evaluation evaluation) {
|
||||||
//TODO: need to detect deep recursions
|
//TODO: need to detect deep recursions
|
||||||
@@ -59,10 +51,12 @@ public class AggregatePolicyProvider implements PolicyProvider {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
this.policy.getAssociatedPolicies().forEach(associatedPolicy -> {
|
Policy policy = evaluation.getPolicy();
|
||||||
PolicyProviderFactory providerFactory = authorization.getProviderFactory(associatedPolicy.getType());
|
AuthorizationProvider authorization = evaluation.getAuthorizationProvider();
|
||||||
PolicyProvider policyProvider = providerFactory.create(associatedPolicy, authorization);
|
|
||||||
policyProvider.evaluate(new DefaultEvaluation(evaluation.getPermission(), evaluation.getContext(), policy, associatedPolicy, decision));
|
policy.getAssociatedPolicies().forEach(associatedPolicy -> {
|
||||||
|
PolicyProvider policyProvider = authorization.getProvider(associatedPolicy.getType());
|
||||||
|
policyProvider.evaluate(new DefaultEvaluation(evaluation.getPermission(), evaluation.getContext(), policy, associatedPolicy, decision, authorization));
|
||||||
});
|
});
|
||||||
|
|
||||||
decision.onComplete();
|
decision.onComplete();
|
||||||
|
|||||||
+4
-3
@@ -19,7 +19,6 @@ package org.keycloak.authorization.policy.provider.aggregated;
|
|||||||
|
|
||||||
import org.keycloak.Config;
|
import org.keycloak.Config;
|
||||||
import org.keycloak.authorization.AuthorizationProvider;
|
import org.keycloak.authorization.AuthorizationProvider;
|
||||||
import org.keycloak.authorization.model.Policy;
|
|
||||||
import org.keycloak.authorization.model.ResourceServer;
|
import org.keycloak.authorization.model.ResourceServer;
|
||||||
import org.keycloak.authorization.policy.provider.PolicyProvider;
|
import org.keycloak.authorization.policy.provider.PolicyProvider;
|
||||||
import org.keycloak.authorization.policy.provider.PolicyProviderAdminService;
|
import org.keycloak.authorization.policy.provider.PolicyProviderAdminService;
|
||||||
@@ -32,6 +31,8 @@ import org.keycloak.models.KeycloakSessionFactory;
|
|||||||
*/
|
*/
|
||||||
public class AggregatePolicyProviderFactory implements PolicyProviderFactory {
|
public class AggregatePolicyProviderFactory implements PolicyProviderFactory {
|
||||||
|
|
||||||
|
private AggregatePolicyProvider provider = new AggregatePolicyProvider();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return "Aggregated";
|
return "Aggregated";
|
||||||
@@ -43,8 +44,8 @@ public class AggregatePolicyProviderFactory implements PolicyProviderFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PolicyProvider create(Policy policy, AuthorizationProvider authorization) {
|
public PolicyProvider create(AuthorizationProvider authorization) {
|
||||||
return new AggregatePolicyProvider(policy, authorization);
|
return provider;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
+38
@@ -0,0 +1,38 @@
|
|||||||
|
package org.keycloak.authorization.policy.provider.client;
|
||||||
|
|
||||||
|
import static org.keycloak.authorization.policy.provider.client.ClientPolicyProviderFactory.getClients;
|
||||||
|
|
||||||
|
import org.keycloak.authorization.AuthorizationProvider;
|
||||||
|
import org.keycloak.authorization.model.Policy;
|
||||||
|
import org.keycloak.authorization.policy.evaluation.Evaluation;
|
||||||
|
import org.keycloak.authorization.policy.evaluation.EvaluationContext;
|
||||||
|
import org.keycloak.authorization.policy.provider.PolicyProvider;
|
||||||
|
import org.keycloak.models.ClientModel;
|
||||||
|
import org.keycloak.models.RealmModel;
|
||||||
|
|
||||||
|
public class ClientPolicyProvider implements PolicyProvider {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void evaluate(Evaluation evaluation) {
|
||||||
|
Policy policy = evaluation.getPolicy();
|
||||||
|
EvaluationContext context = evaluation.getContext();
|
||||||
|
String[] clients = getClients(policy);
|
||||||
|
AuthorizationProvider authorizationProvider = evaluation.getAuthorizationProvider();
|
||||||
|
RealmModel realm = authorizationProvider.getKeycloakSession().getContext().getRealm();
|
||||||
|
|
||||||
|
if (clients.length > 0) {
|
||||||
|
for (String client : clients) {
|
||||||
|
ClientModel clientModel = realm.getClientById(client);
|
||||||
|
if (context.getAttributes().containsValue("kc.client.id", clientModel.getClientId())) {
|
||||||
|
evaluation.grant();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
+120
@@ -0,0 +1,120 @@
|
|||||||
|
package org.keycloak.authorization.policy.provider.client;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.keycloak.Config;
|
||||||
|
import org.keycloak.authorization.AuthorizationProvider;
|
||||||
|
import org.keycloak.authorization.model.Policy;
|
||||||
|
import org.keycloak.authorization.model.ResourceServer;
|
||||||
|
import org.keycloak.authorization.policy.provider.PolicyProvider;
|
||||||
|
import org.keycloak.authorization.policy.provider.PolicyProviderAdminService;
|
||||||
|
import org.keycloak.authorization.policy.provider.PolicyProviderFactory;
|
||||||
|
import org.keycloak.authorization.store.PolicyStore;
|
||||||
|
import org.keycloak.authorization.store.ResourceServerStore;
|
||||||
|
import org.keycloak.authorization.store.StoreFactory;
|
||||||
|
import org.keycloak.models.ClientModel;
|
||||||
|
import org.keycloak.models.KeycloakSession;
|
||||||
|
import org.keycloak.models.KeycloakSessionFactory;
|
||||||
|
import org.keycloak.models.RealmModel.ClientRemovedEvent;
|
||||||
|
import org.keycloak.util.JsonSerialization;
|
||||||
|
|
||||||
|
public class ClientPolicyProviderFactory implements PolicyProviderFactory {
|
||||||
|
|
||||||
|
private ClientPolicyProvider provider = new ClientPolicyProvider();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "Client";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getGroup() {
|
||||||
|
return "Identity Based";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PolicyProvider create(AuthorizationProvider authorization) {
|
||||||
|
return provider;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PolicyProviderAdminService getAdminResource(ResourceServer resourceServer) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PolicyProvider create(KeycloakSession session) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void init(Config.Scope config) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void postInit(KeycloakSessionFactory factory) {
|
||||||
|
factory.register(event -> {
|
||||||
|
if (event instanceof ClientRemovedEvent) {
|
||||||
|
KeycloakSession keycloakSession = ((ClientRemovedEvent) event).getKeycloakSession();
|
||||||
|
AuthorizationProvider provider = keycloakSession.getProvider(AuthorizationProvider.class);
|
||||||
|
StoreFactory storeFactory = provider.getStoreFactory();
|
||||||
|
PolicyStore policyStore = storeFactory.getPolicyStore();
|
||||||
|
ClientModel removedClient = ((ClientRemovedEvent) event).getClient();
|
||||||
|
ResourceServerStore resourceServerStore = storeFactory.getResourceServerStore();
|
||||||
|
ResourceServer resourceServer = resourceServerStore.findByClient(removedClient.getId());
|
||||||
|
|
||||||
|
if (resourceServer != null) {
|
||||||
|
policyStore.findByType(getId(), resourceServer.getId()).forEach(policy -> {
|
||||||
|
List<String> clients = new ArrayList<>();
|
||||||
|
|
||||||
|
for (String clientId : getClients(policy)) {
|
||||||
|
if (!clientId.equals(removedClient.getId())) {
|
||||||
|
clients.add(clientId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (clients.isEmpty()) {
|
||||||
|
policyStore.findDependentPolicies(policy.getId(), resourceServer.getId()).forEach(dependentPolicy -> {
|
||||||
|
dependentPolicy.removeAssociatedPolicy(policy);
|
||||||
|
});
|
||||||
|
policyStore.delete(policy.getId());
|
||||||
|
} else {
|
||||||
|
policy.getConfig().put("clients", JsonSerialization.writeValueAsString(clients));
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException("Error while synchronizing clients with policy [" + policy.getName() + "].", e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getId() {
|
||||||
|
return "client";
|
||||||
|
}
|
||||||
|
|
||||||
|
static String[] getClients(Policy policy) {
|
||||||
|
String clients = policy.getConfig().get("clients");
|
||||||
|
|
||||||
|
if (clients != null) {
|
||||||
|
try {
|
||||||
|
return JsonSerialization.readValue(clients.getBytes(), String[].class);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException("Could not parse clients [" + clients + "] from policy config [" + policy.getName() + "].", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new String[]{};
|
||||||
|
}
|
||||||
|
}
|
||||||
+11
-9
@@ -17,32 +17,34 @@
|
|||||||
*/
|
*/
|
||||||
package org.keycloak.authorization.policy.provider.js;
|
package org.keycloak.authorization.policy.provider.js;
|
||||||
|
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
import javax.script.ScriptEngine;
|
||||||
|
import javax.script.ScriptException;
|
||||||
|
|
||||||
import org.keycloak.authorization.model.Policy;
|
import org.keycloak.authorization.model.Policy;
|
||||||
import org.keycloak.authorization.policy.evaluation.Evaluation;
|
import org.keycloak.authorization.policy.evaluation.Evaluation;
|
||||||
import org.keycloak.authorization.policy.provider.PolicyProvider;
|
import org.keycloak.authorization.policy.provider.PolicyProvider;
|
||||||
|
|
||||||
import javax.script.ScriptEngine;
|
|
||||||
import javax.script.ScriptEngineManager;
|
|
||||||
import javax.script.ScriptException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||||
*/
|
*/
|
||||||
public class JSPolicyProvider implements PolicyProvider {
|
public class JSPolicyProvider implements PolicyProvider {
|
||||||
|
|
||||||
private final Policy policy;
|
private Supplier<ScriptEngine> engineProvider;
|
||||||
|
|
||||||
public JSPolicyProvider(Policy policy) {
|
public JSPolicyProvider(Supplier<ScriptEngine> engineProvider) {
|
||||||
this.policy = policy;
|
this.engineProvider = engineProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void evaluate(Evaluation evaluation) {
|
public void evaluate(Evaluation evaluation) {
|
||||||
ScriptEngineManager manager = new ScriptEngineManager();
|
ScriptEngine engine = engineProvider.get();
|
||||||
ScriptEngine engine = manager.getEngineByName("nashorn");
|
|
||||||
|
|
||||||
engine.put("$evaluation", evaluation);
|
engine.put("$evaluation", evaluation);
|
||||||
|
|
||||||
|
Policy policy = evaluation.getPolicy();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
engine.eval(policy.getConfig().get("code"));
|
engine.eval(policy.getConfig().get("code"));
|
||||||
} catch (ScriptException e) {
|
} catch (ScriptException e) {
|
||||||
|
|||||||
+14
-3
@@ -1,8 +1,12 @@
|
|||||||
package org.keycloak.authorization.policy.provider.js;
|
package org.keycloak.authorization.policy.provider.js;
|
||||||
|
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
import javax.script.ScriptEngine;
|
||||||
|
import javax.script.ScriptEngineManager;
|
||||||
|
|
||||||
import org.keycloak.Config;
|
import org.keycloak.Config;
|
||||||
import org.keycloak.authorization.AuthorizationProvider;
|
import org.keycloak.authorization.AuthorizationProvider;
|
||||||
import org.keycloak.authorization.model.Policy;
|
|
||||||
import org.keycloak.authorization.model.ResourceServer;
|
import org.keycloak.authorization.model.ResourceServer;
|
||||||
import org.keycloak.authorization.policy.provider.PolicyProvider;
|
import org.keycloak.authorization.policy.provider.PolicyProvider;
|
||||||
import org.keycloak.authorization.policy.provider.PolicyProviderAdminService;
|
import org.keycloak.authorization.policy.provider.PolicyProviderAdminService;
|
||||||
@@ -15,6 +19,13 @@ import org.keycloak.models.KeycloakSessionFactory;
|
|||||||
*/
|
*/
|
||||||
public class JSPolicyProviderFactory implements PolicyProviderFactory {
|
public class JSPolicyProviderFactory implements PolicyProviderFactory {
|
||||||
|
|
||||||
|
private JSPolicyProvider provider = new JSPolicyProvider(new Supplier<ScriptEngine>() {
|
||||||
|
@Override
|
||||||
|
public ScriptEngine get() {
|
||||||
|
return new ScriptEngineManager().getEngineByName("nashorn");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return "JavaScript";
|
return "JavaScript";
|
||||||
@@ -26,8 +37,8 @@ public class JSPolicyProviderFactory implements PolicyProviderFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PolicyProvider create(Policy policy, AuthorizationProvider authorization) {
|
public PolicyProvider create(AuthorizationProvider authorization) {
|
||||||
return new JSPolicyProvider(policy);
|
return provider;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
+1
-2
@@ -17,7 +17,6 @@
|
|||||||
*/
|
*/
|
||||||
package org.keycloak.authorization.policy.provider.resource;
|
package org.keycloak.authorization.policy.provider.resource;
|
||||||
|
|
||||||
import org.keycloak.authorization.model.Policy;
|
|
||||||
import org.keycloak.authorization.policy.evaluation.Evaluation;
|
import org.keycloak.authorization.policy.evaluation.Evaluation;
|
||||||
import org.keycloak.authorization.policy.provider.PolicyProvider;
|
import org.keycloak.authorization.policy.provider.PolicyProvider;
|
||||||
|
|
||||||
@@ -26,7 +25,7 @@ import org.keycloak.authorization.policy.provider.PolicyProvider;
|
|||||||
*/
|
*/
|
||||||
public class ResourcePolicyProvider implements PolicyProvider {
|
public class ResourcePolicyProvider implements PolicyProvider {
|
||||||
|
|
||||||
public ResourcePolicyProvider(Policy policy) {
|
public ResourcePolicyProvider() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+4
-3
@@ -2,7 +2,6 @@ package org.keycloak.authorization.policy.provider.resource;
|
|||||||
|
|
||||||
import org.keycloak.Config;
|
import org.keycloak.Config;
|
||||||
import org.keycloak.authorization.AuthorizationProvider;
|
import org.keycloak.authorization.AuthorizationProvider;
|
||||||
import org.keycloak.authorization.model.Policy;
|
|
||||||
import org.keycloak.authorization.model.ResourceServer;
|
import org.keycloak.authorization.model.ResourceServer;
|
||||||
import org.keycloak.authorization.policy.provider.PolicyProvider;
|
import org.keycloak.authorization.policy.provider.PolicyProvider;
|
||||||
import org.keycloak.authorization.policy.provider.PolicyProviderAdminService;
|
import org.keycloak.authorization.policy.provider.PolicyProviderAdminService;
|
||||||
@@ -15,6 +14,8 @@ import org.keycloak.models.KeycloakSessionFactory;
|
|||||||
*/
|
*/
|
||||||
public class ResourcePolicyProviderFactory implements PolicyProviderFactory {
|
public class ResourcePolicyProviderFactory implements PolicyProviderFactory {
|
||||||
|
|
||||||
|
private ResourcePolicyProvider provider = new ResourcePolicyProvider();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return "Resource-Based";
|
return "Resource-Based";
|
||||||
@@ -26,8 +27,8 @@ public class ResourcePolicyProviderFactory implements PolicyProviderFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PolicyProvider create(Policy policy, AuthorizationProvider authorization) {
|
public PolicyProvider create(AuthorizationProvider authorization) {
|
||||||
return new ResourcePolicyProvider(policy);
|
return provider;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
+12
-25
@@ -17,6 +17,10 @@
|
|||||||
*/
|
*/
|
||||||
package org.keycloak.authorization.policy.provider.role;
|
package org.keycloak.authorization.policy.provider.role;
|
||||||
|
|
||||||
|
import static org.keycloak.authorization.policy.provider.role.RolePolicyProviderFactory.getRoles;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import org.keycloak.authorization.AuthorizationProvider;
|
import org.keycloak.authorization.AuthorizationProvider;
|
||||||
import org.keycloak.authorization.identity.Identity;
|
import org.keycloak.authorization.identity.Identity;
|
||||||
import org.keycloak.authorization.model.Policy;
|
import org.keycloak.authorization.model.Policy;
|
||||||
@@ -26,39 +30,26 @@ import org.keycloak.models.ClientModel;
|
|||||||
import org.keycloak.models.RealmModel;
|
import org.keycloak.models.RealmModel;
|
||||||
import org.keycloak.models.RoleModel;
|
import org.keycloak.models.RoleModel;
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import static org.keycloak.authorization.policy.provider.role.RolePolicyProviderFactory.getRoles;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||||
*/
|
*/
|
||||||
public class RolePolicyProvider implements PolicyProvider {
|
public class RolePolicyProvider implements PolicyProvider {
|
||||||
|
|
||||||
private final Policy policy;
|
|
||||||
private final AuthorizationProvider authorization;
|
|
||||||
|
|
||||||
public RolePolicyProvider(Policy policy, AuthorizationProvider authorization) {
|
|
||||||
this.policy = policy;
|
|
||||||
this.authorization = authorization;
|
|
||||||
}
|
|
||||||
|
|
||||||
public RolePolicyProvider() {
|
|
||||||
this(null, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void evaluate(Evaluation evaluation) {
|
public void evaluate(Evaluation evaluation) {
|
||||||
Map<String, Object>[] roleIds = getRoles(this.policy);
|
Policy policy = evaluation.getPolicy();
|
||||||
|
Map<String, Object>[] roleIds = getRoles(policy);
|
||||||
|
AuthorizationProvider authorizationProvider = evaluation.getAuthorizationProvider();
|
||||||
|
RealmModel realm = authorizationProvider.getKeycloakSession().getContext().getRealm();
|
||||||
|
|
||||||
if (roleIds.length > 0) {
|
if (roleIds.length > 0) {
|
||||||
Identity identity = evaluation.getContext().getIdentity();
|
Identity identity = evaluation.getContext().getIdentity();
|
||||||
|
|
||||||
for (Map<String, Object> current : roleIds) {
|
for (Map<String, Object> current : roleIds) {
|
||||||
RoleModel role = getCurrentRealm().getRoleById((String) current.get("id"));
|
RoleModel role = realm.getRoleById((String) current.get("id"));
|
||||||
|
|
||||||
if (role != null) {
|
if (role != null) {
|
||||||
boolean hasRole = hasRole(identity, role);
|
boolean hasRole = hasRole(identity, role, realm);
|
||||||
|
|
||||||
if (!hasRole && Boolean.valueOf(isRequired(current))) {
|
if (!hasRole && Boolean.valueOf(isRequired(current))) {
|
||||||
evaluation.deny();
|
evaluation.deny();
|
||||||
@@ -75,19 +66,15 @@ public class RolePolicyProvider implements PolicyProvider {
|
|||||||
return (boolean) current.getOrDefault("required", false);
|
return (boolean) current.getOrDefault("required", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean hasRole(Identity identity, RoleModel role) {
|
private boolean hasRole(Identity identity, RoleModel role, RealmModel realm) {
|
||||||
String roleName = role.getName();
|
String roleName = role.getName();
|
||||||
if (role.isClientRole()) {
|
if (role.isClientRole()) {
|
||||||
ClientModel clientModel = getCurrentRealm().getClientById(role.getContainerId());
|
ClientModel clientModel = realm.getClientById(role.getContainerId());
|
||||||
return identity.hasClientRole(clientModel.getClientId(), roleName);
|
return identity.hasClientRole(clientModel.getClientId(), roleName);
|
||||||
}
|
}
|
||||||
return identity.hasRealmRole(roleName);
|
return identity.hasRealmRole(roleName);
|
||||||
}
|
}
|
||||||
|
|
||||||
private RealmModel getCurrentRealm() {
|
|
||||||
return this.authorization.getKeycloakSession().getContext().getRealm();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void close() {
|
public void close() {
|
||||||
|
|
||||||
|
|||||||
+61
-33
@@ -26,8 +26,13 @@ import org.keycloak.authorization.policy.provider.PolicyProvider;
|
|||||||
import org.keycloak.authorization.policy.provider.PolicyProviderAdminService;
|
import org.keycloak.authorization.policy.provider.PolicyProviderAdminService;
|
||||||
import org.keycloak.authorization.policy.provider.PolicyProviderFactory;
|
import org.keycloak.authorization.policy.provider.PolicyProviderFactory;
|
||||||
import org.keycloak.authorization.store.PolicyStore;
|
import org.keycloak.authorization.store.PolicyStore;
|
||||||
|
import org.keycloak.authorization.store.ResourceServerStore;
|
||||||
|
import org.keycloak.authorization.store.StoreFactory;
|
||||||
|
import org.keycloak.models.ClientModel;
|
||||||
import org.keycloak.models.KeycloakSession;
|
import org.keycloak.models.KeycloakSession;
|
||||||
import org.keycloak.models.KeycloakSessionFactory;
|
import org.keycloak.models.KeycloakSessionFactory;
|
||||||
|
import org.keycloak.models.RealmModel;
|
||||||
|
import org.keycloak.models.RoleContainerModel;
|
||||||
import org.keycloak.models.RoleContainerModel.RoleRemovedEvent;
|
import org.keycloak.models.RoleContainerModel.RoleRemovedEvent;
|
||||||
import org.keycloak.models.RoleModel;
|
import org.keycloak.models.RoleModel;
|
||||||
import org.keycloak.util.JsonSerialization;
|
import org.keycloak.util.JsonSerialization;
|
||||||
@@ -37,12 +42,15 @@ import java.util.ArrayList;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||||
*/
|
*/
|
||||||
public class RolePolicyProviderFactory implements PolicyProviderFactory {
|
public class RolePolicyProviderFactory implements PolicyProviderFactory {
|
||||||
|
|
||||||
|
private RolePolicyProvider provider = new RolePolicyProvider();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return "Role";
|
return "Role";
|
||||||
@@ -54,8 +62,8 @@ public class RolePolicyProviderFactory implements PolicyProviderFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PolicyProvider create(Policy policy, AuthorizationProvider authorization) {
|
public PolicyProvider create(AuthorizationProvider authorization) {
|
||||||
return new RolePolicyProvider(policy, authorization);
|
return provider;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -79,43 +87,63 @@ public class RolePolicyProviderFactory implements PolicyProviderFactory {
|
|||||||
if (event instanceof RoleRemovedEvent) {
|
if (event instanceof RoleRemovedEvent) {
|
||||||
KeycloakSession keycloakSession = ((RoleRemovedEvent) event).getKeycloakSession();
|
KeycloakSession keycloakSession = ((RoleRemovedEvent) event).getKeycloakSession();
|
||||||
AuthorizationProvider provider = keycloakSession.getProvider(AuthorizationProvider.class);
|
AuthorizationProvider provider = keycloakSession.getProvider(AuthorizationProvider.class);
|
||||||
PolicyStore policyStore = provider.getStoreFactory().getPolicyStore();
|
StoreFactory storeFactory = provider.getStoreFactory();
|
||||||
|
PolicyStore policyStore = storeFactory.getPolicyStore();
|
||||||
RoleModel removedRole = ((RoleRemovedEvent) event).getRole();
|
RoleModel removedRole = ((RoleRemovedEvent) event).getRole();
|
||||||
|
RoleContainerModel container = removedRole.getContainer();
|
||||||
|
ResourceServerStore resourceServerStore = storeFactory.getResourceServerStore();
|
||||||
|
|
||||||
policyStore.findByType(getId()).forEach(policy -> {
|
if (container instanceof RealmModel) {
|
||||||
List<Map> roles = new ArrayList<>();
|
RealmModel realm = (RealmModel) container;
|
||||||
|
realm.getClients().forEach(clientModel -> updateResourceServer(clientModel, removedRole, resourceServerStore, policyStore));
|
||||||
for (Map<String,Object> role : getRoles(policy)) {
|
} else {
|
||||||
if (!role.get("id").equals(removedRole.getId())) {
|
ClientModel clientModel = (ClientModel) container;
|
||||||
Map updated = new HashMap();
|
updateResourceServer(clientModel, removedRole, resourceServerStore, policyStore);
|
||||||
updated.put("id", role.get("id"));
|
}
|
||||||
Object required = role.get("required");
|
|
||||||
if (required != null) {
|
|
||||||
updated.put("required", required);
|
|
||||||
}
|
|
||||||
roles.add(updated);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
if (roles.isEmpty()) {
|
|
||||||
policyStore.findDependentPolicies(policy.getId()).forEach(dependentPolicy -> {
|
|
||||||
dependentPolicy.removeAssociatedPolicy(policy);
|
|
||||||
});
|
|
||||||
policyStore.delete(policy.getId());
|
|
||||||
} else {
|
|
||||||
Map<String, String> config = policy.getConfig();
|
|
||||||
config.put("roles", JsonSerialization.writeValueAsString(roles));
|
|
||||||
policy.setConfig(config);
|
|
||||||
}
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new RuntimeException("Error while synchronizing roles with policy [" + policy.getName() + "].", e);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void updateResourceServer(ClientModel clientModel, RoleModel removedRole, ResourceServerStore resourceServerStore, PolicyStore policyStore) {
|
||||||
|
ResourceServer resourceServer = resourceServerStore.findByClient(clientModel.getId());
|
||||||
|
|
||||||
|
if (resourceServer != null) {
|
||||||
|
policyStore.findByType(getId(), resourceServer.getId()).forEach(policy -> {
|
||||||
|
List<Map> roles = new ArrayList<>();
|
||||||
|
|
||||||
|
for (Map<String,Object> role : getRoles(policy)) {
|
||||||
|
if (!role.get("id").equals(removedRole.getId())) {
|
||||||
|
Map updated = new HashMap();
|
||||||
|
updated.put("id", role.get("id"));
|
||||||
|
Object required = role.get("required");
|
||||||
|
if (required != null) {
|
||||||
|
updated.put("required", required);
|
||||||
|
}
|
||||||
|
roles.add(updated);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (roles.isEmpty()) {
|
||||||
|
policyStore.findDependentPolicies(policy.getId(), resourceServer.getId()).forEach(dependentPolicy -> {
|
||||||
|
dependentPolicy.removeAssociatedPolicy(policy);
|
||||||
|
if (dependentPolicy.getAssociatedPolicies().isEmpty()) {
|
||||||
|
policyStore.delete(dependentPolicy.getId());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
policyStore.delete(policy.getId());
|
||||||
|
} else {
|
||||||
|
Map<String, String> config = policy.getConfig();
|
||||||
|
config.put("roles", JsonSerialization.writeValueAsString(roles));
|
||||||
|
policy.setConfig(config);
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException("Error while synchronizing roles with policy [" + policy.getName() + "].", e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void close() {
|
public void close() {
|
||||||
|
|
||||||
|
|||||||
Loaded 100 of 1142 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user