Compare commits
118
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0a1997f445 | ||
|
|
01da592f77 | ||
|
|
40d129cf54 | ||
|
|
8c66f520af | ||
|
|
64b391cc1b | ||
|
|
8a37395760 | ||
|
|
f5d00ddffb | ||
|
|
dafd567e68 | ||
|
|
d55ccf5312 | ||
|
|
871be4ad87 | ||
|
|
6f3c59e086 | ||
|
|
fc0d510e85 | ||
|
|
742a280f5d | ||
|
|
87126704cd | ||
|
|
1450a7fad4 | ||
|
|
65551159e0 | ||
|
|
d99dca2db3 | ||
|
|
3355399b4e | ||
|
|
dcadc61220 | ||
|
|
3c5027de3c | ||
|
|
a5d155a35a | ||
|
|
05bbd9ace3 | ||
|
|
559a8b2a2c | ||
|
|
c97e7e720e | ||
|
|
f10c47955f | ||
|
|
23db2b852b | ||
|
|
591093f867 | ||
|
|
9039b44f4d | ||
|
|
5f0c86a49f | ||
|
|
8ac7bda52c | ||
|
|
0e2e867e4a | ||
|
|
0d9ccba566 | ||
|
|
30e8071d1d | ||
|
|
39cbf4e9ab | ||
|
|
af47bd5da8 | ||
|
|
0ee5c97b1c | ||
|
|
d07f13eace | ||
|
|
fc3ca33033 | ||
|
|
2fb022e501 | ||
|
|
b478472b35 | ||
|
|
8fdadcc596 | ||
|
|
ca06043b00 | ||
|
|
3c9d3c2c04 | ||
|
|
998227ac53 | ||
|
|
30a066db41 | ||
|
|
d9f79fae79 | ||
|
|
530a710dce | ||
|
|
f5ca4840d6 | ||
|
|
d3a6b6f587 | ||
|
|
f90e0fc14c | ||
|
|
6b968796ce | ||
|
|
1277f8bb3b | ||
|
|
63a6ba53df | ||
|
|
9af51fb664 | ||
|
|
c2012a595b | ||
|
|
2fcfa5cf71 | ||
|
|
e638391182 | ||
|
|
e98fcfe56e | ||
|
|
2f366b0d5d | ||
|
|
e1a0e581b9 | ||
|
|
c43d8b3d85 | ||
|
|
6a2a121d4e | ||
|
|
9dc5709ce7 | ||
|
|
ccb09fbf45 | ||
|
|
fb883254f6 | ||
|
|
5f1f3dff5e | ||
|
|
dd93de75d9 | ||
|
|
d897159560 | ||
|
|
182c975e01 | ||
|
|
f19a324030 | ||
|
|
9cf965a157 | ||
|
|
9e42be09d7 | ||
|
|
7d466be94e | ||
|
|
a5c0cbc3b4 | ||
|
|
bb5dc4c473 | ||
|
|
132386f64d | ||
|
|
b0c89d739b | ||
|
|
6a07a7ed2c | ||
|
|
f293ab86c3 | ||
|
|
db60abc604 | ||
|
|
f55c93a1e4 | ||
|
|
08296bd3ce | ||
|
|
fca6da3a5a | ||
|
|
49407c2e4f | ||
|
|
4d1474afe0 | ||
|
|
aa128d6c07 | ||
|
|
c8c76cc03f | ||
|
|
5a9bfea419 | ||
|
|
dffe70e40a | ||
|
|
1b4d9a6147 | ||
|
|
b7fb3ec9a9 | ||
|
|
7ff18ca14b | ||
|
|
6052b1546d | ||
|
|
5a241392cf | ||
|
|
c586c63533 | ||
|
|
f8919f8baa | ||
|
|
f45ed1613e | ||
|
|
bc665fdbc3 | ||
|
|
6c3e6bc90c | ||
|
|
cb3b7f3cb2 | ||
|
|
5e8db32329 | ||
|
|
65c39763eb | ||
|
|
f429469fc8 | ||
|
|
6339b62f8d | ||
|
|
473e9ab55c | ||
|
|
77e503f5ca | ||
|
|
c64ecb1ab8 | ||
|
|
2e22dcfc47 | ||
|
|
16fd6558a6 | ||
|
|
eb97151476 | ||
|
|
b8adee4004 | ||
|
|
65f5eacdd4 | ||
|
|
2b6597e9f1 | ||
|
|
6a2f73df9c | ||
|
|
60a03d0293 | ||
|
|
dd6735285d | ||
|
|
dbf5c395b0 | ||
|
|
3391ec5377 |
No files matched your search
@@ -32,6 +32,10 @@ To build the distribution run:
|
|||||||
|
|
||||||
Once completed you will find distribution archives in `distribution`.
|
Once completed you will find distribution archives in `distribution`.
|
||||||
|
|
||||||
|
To build only the server run:
|
||||||
|
|
||||||
|
mvn -Pdistribution -pl distribution/server-dist -am -Dmaven.test.skip clean install
|
||||||
|
|
||||||
|
|
||||||
Starting Keycloak
|
Starting Keycloak
|
||||||
-----------------
|
-----------------
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>4.0.0.Beta3</version>
|
<version>4.1.0.Final</version>
|
||||||
<relativePath>../../../pom.xml</relativePath>
|
<relativePath>../../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
@@ -36,7 +36,16 @@
|
|||||||
</keycloak.osgi.export>
|
</keycloak.osgi.export>
|
||||||
<keycloak.osgi.import>
|
<keycloak.osgi.import>
|
||||||
org.keycloak.*;version="${project.version}",
|
org.keycloak.*;version="${project.version}",
|
||||||
org.apache.http.*;version=${apache.httpcomponents.version},
|
org.apache.http.auth.*;version=${apache.httpcomponents.version},
|
||||||
|
org.apache.http.client.*;version=${apache.httpcomponents.version},
|
||||||
|
org.apache.http.conn.*;version=${apache.httpcomponents.version},
|
||||||
|
org.apache.http.cookie.*;version=${apache.httpcomponents.version},
|
||||||
|
org.apache.http.impl.auth.*;version=${apache.httpcomponents.version},
|
||||||
|
org.apache.http.impl.client.*;version=${apache.httpcomponents.version},
|
||||||
|
org.apache.http.impl.conn.*;version=${apache.httpcomponents.version},
|
||||||
|
org.apache.http.impl.cookie.*;version=${apache.httpcomponents.version},
|
||||||
|
org.apache.http.impl.execchain.*;version=${apache.httpcomponents.version},
|
||||||
|
org.apache.http.*;version=${apache.httpcomponents.httpcore.version},
|
||||||
org.apache.karaf.jaas.boot.principal;resolution:=optional,
|
org.apache.karaf.jaas.boot.principal;resolution:=optional,
|
||||||
org.apache.karaf.jaas.modules;resolution:=optional,
|
org.apache.karaf.jaas.modules;resolution:=optional,
|
||||||
*;resolution:=optional
|
*;resolution:=optional
|
||||||
|
|||||||
+36
-20
@@ -28,6 +28,7 @@ import org.jboss.logging.Logger;
|
|||||||
import org.keycloak.AuthorizationContext;
|
import org.keycloak.AuthorizationContext;
|
||||||
import org.keycloak.KeycloakSecurityContext;
|
import org.keycloak.KeycloakSecurityContext;
|
||||||
import org.keycloak.adapters.OIDCHttpFacade;
|
import org.keycloak.adapters.OIDCHttpFacade;
|
||||||
|
import org.keycloak.adapters.spi.HttpFacade;
|
||||||
import org.keycloak.adapters.spi.HttpFacade.Request;
|
import org.keycloak.adapters.spi.HttpFacade.Request;
|
||||||
import org.keycloak.authorization.client.AuthzClient;
|
import org.keycloak.authorization.client.AuthzClient;
|
||||||
import org.keycloak.authorization.client.ClientAuthorizationContext;
|
import org.keycloak.authorization.client.ClientAuthorizationContext;
|
||||||
@@ -66,8 +67,12 @@ public abstract class AbstractPolicyEnforcer {
|
|||||||
KeycloakSecurityContext securityContext = httpFacade.getSecurityContext();
|
KeycloakSecurityContext securityContext = httpFacade.getSecurityContext();
|
||||||
|
|
||||||
if (securityContext == null) {
|
if (securityContext == null) {
|
||||||
|
if (!isDefaultAccessDeniedUri(request)) {
|
||||||
if (pathConfig != null) {
|
if (pathConfig != null) {
|
||||||
challenge(pathConfig, getRequiredScopes(pathConfig, request), httpFacade);
|
challenge(pathConfig, getRequiredScopes(pathConfig, request), httpFacade);
|
||||||
|
} else {
|
||||||
|
handleAccessDenied(httpFacade);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return createEmptyAuthorizationContext(false);
|
return createEmptyAuthorizationContext(false);
|
||||||
}
|
}
|
||||||
@@ -165,7 +170,7 @@ public abstract class AbstractPolicyEnforcer {
|
|||||||
policyEnforcer.getPathMatcher().removeFromCache(getPath(request));
|
policyEnforcer.getPathMatcher().removeFromCache(getPath(request));
|
||||||
}
|
}
|
||||||
|
|
||||||
return hasValidClaims(actualPathConfig, httpFacade, authorization);
|
return hasValidClaims(actualPathConfig, permission, httpFacade, authorization);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -187,29 +192,17 @@ public abstract class AbstractPolicyEnforcer {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean hasValidClaims(PathConfig actualPathConfig, OIDCHttpFacade httpFacade, Authorization authorization) {
|
private boolean hasValidClaims(PathConfig actualPathConfig, Permission permission, OIDCHttpFacade httpFacade, Authorization authorization) {
|
||||||
Map<String, Map<String, Object>> claimInformationPointConfig = actualPathConfig.getClaimInformationPointConfig();
|
Map<String, Set<String>> grantedClaims = permission.getClaims();
|
||||||
|
|
||||||
if (claimInformationPointConfig != null) {
|
|
||||||
Map<String, List<String>> claims = new HashMap<>();
|
|
||||||
|
|
||||||
for (Entry<String, Map<String, Object>> entry : claimInformationPointConfig.entrySet()) {
|
|
||||||
ClaimInformationPointProviderFactory factory = policyEnforcer.getClaimInformationPointProviderFactories().get(entry.getKey());
|
|
||||||
|
|
||||||
if (factory == null) {
|
|
||||||
throw new RuntimeException("Could not find claim information provider with name [" + entry.getKey() + "]");
|
|
||||||
}
|
|
||||||
|
|
||||||
claims.putAll(factory.create(entry.getValue()).resolve(httpFacade));
|
|
||||||
}
|
|
||||||
|
|
||||||
Map<String, List<String>> grantedClaims = authorization.getClaims();
|
|
||||||
|
|
||||||
if (grantedClaims != null) {
|
if (grantedClaims != null) {
|
||||||
|
Map<String, List<String>> claims = resolveClaims(actualPathConfig, httpFacade);
|
||||||
|
|
||||||
if (claims.isEmpty()) {
|
if (claims.isEmpty()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
for (Entry<String, List<String>> entry : grantedClaims.entrySet()) {
|
|
||||||
|
for (Entry<String, Set<String>> entry : grantedClaims.entrySet()) {
|
||||||
List<String> requestClaims = claims.get(entry.getKey());
|
List<String> requestClaims = claims.get(entry.getKey());
|
||||||
|
|
||||||
if (requestClaims == null || requestClaims.isEmpty() || !entry.getValue().containsAll(requestClaims)) {
|
if (requestClaims == null || requestClaims.isEmpty() || !entry.getValue().containsAll(requestClaims)) {
|
||||||
@@ -217,7 +210,6 @@ public abstract class AbstractPolicyEnforcer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -342,4 +334,28 @@ public abstract class AbstractPolicyEnforcer {
|
|||||||
private PathConfig getPathConfig(Request request) {
|
private PathConfig getPathConfig(Request request) {
|
||||||
return isDefaultAccessDeniedUri(request) ? null : policyEnforcer.getPathMatcher().matches(getPath(request));
|
return isDefaultAccessDeniedUri(request) ? null : policyEnforcer.getPathMatcher().matches(getPath(request));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected Map<String, List<String>> resolveClaims(PathConfig pathConfig, OIDCHttpFacade httpFacade) {
|
||||||
|
Map<String, List<String>> claims = getClaims(getEnforcerConfig().getClaimInformationPointConfig(), httpFacade);
|
||||||
|
|
||||||
|
claims.putAll(getClaims(pathConfig.getClaimInformationPointConfig(), httpFacade));
|
||||||
|
|
||||||
|
return claims;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<String, List<String>> getClaims(Map<String, Map<String, Object>>claimInformationPointConfig, HttpFacade httpFacade) {
|
||||||
|
Map<String, List<String>> claims = new HashMap<>();
|
||||||
|
|
||||||
|
if (claimInformationPointConfig != null) {
|
||||||
|
for (Entry<String, Map<String, Object>> claimDef : claimInformationPointConfig.entrySet()) {
|
||||||
|
ClaimInformationPointProviderFactory factory = getPolicyEnforcer().getClaimInformationPointProviderFactories().get(claimDef.getKey());
|
||||||
|
|
||||||
|
if (factory != null) {
|
||||||
|
claims.putAll(factory.create(claimDef.getValue()).resolve(httpFacade));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return claims;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+16
-51
@@ -22,7 +22,6 @@ 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.Map;
|
||||||
import java.util.Map.Entry;
|
|
||||||
|
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
import org.keycloak.KeycloakSecurityContext;
|
import org.keycloak.KeycloakSecurityContext;
|
||||||
@@ -87,19 +86,6 @@ public class KeycloakAdapterPolicyEnforcer extends AbstractPolicyEnforcer {
|
|||||||
grantedPermissions.add(newPermission);
|
grantedPermissions.add(newPermission);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<String, List<String>> newClaims = newAuthorization.getClaims();
|
|
||||||
|
|
||||||
if (newClaims != null) {
|
|
||||||
Map<String, List<String>> claims = authorization.getClaims();
|
|
||||||
|
|
||||||
if (claims == null) {
|
|
||||||
claims = new HashMap<>();
|
|
||||||
authorization.setClaims(claims);
|
|
||||||
}
|
|
||||||
|
|
||||||
claims.putAll(newClaims);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
original.setAuthorization(authorization);
|
original.setAuthorization(authorization);
|
||||||
@@ -136,12 +122,6 @@ public class KeycloakAdapterPolicyEnforcer extends AbstractPolicyEnforcer {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void handleAccessDenied(OIDCHttpFacade facade) {
|
protected void handleAccessDenied(OIDCHttpFacade facade) {
|
||||||
KeycloakSecurityContext securityContext = facade.getSecurityContext();
|
|
||||||
|
|
||||||
if (securityContext == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
String accessDeniedPath = getEnforcerConfig().getOnDenyRedirectTo();
|
String accessDeniedPath = getEnforcerConfig().getOnDenyRedirectTo();
|
||||||
HttpFacade.Response response = facade.getResponse();
|
HttpFacade.Response response = facade.getResponse();
|
||||||
|
|
||||||
@@ -154,7 +134,7 @@ public class KeycloakAdapterPolicyEnforcer extends AbstractPolicyEnforcer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private AccessToken requestAuthorizationToken(PathConfig pathConfig, PolicyEnforcerConfig.MethodConfig methodConfig, OIDCHttpFacade httpFacade) {
|
private AccessToken requestAuthorizationToken(PathConfig pathConfig, PolicyEnforcerConfig.MethodConfig methodConfig, OIDCHttpFacade httpFacade) {
|
||||||
if (getPolicyEnforcer().getDeployment().isBearerOnly() || (isBearerAuthorization(httpFacade) && getEnforcerConfig().getUserManagedAccess() != null)) {
|
if (getEnforcerConfig().getUserManagedAccess() != null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -165,28 +145,30 @@ public class KeycloakAdapterPolicyEnforcer extends AbstractPolicyEnforcer {
|
|||||||
AccessToken accessToken = securityContext.getToken();
|
AccessToken accessToken = securityContext.getToken();
|
||||||
AuthorizationRequest authzRequest = new AuthorizationRequest();
|
AuthorizationRequest authzRequest = new AuthorizationRequest();
|
||||||
|
|
||||||
if (getEnforcerConfig().getUserManagedAccess() != null) {
|
if (isBearerAuthorization(httpFacade) || accessToken.getAuthorization() != null) {
|
||||||
String ticket = getPermissionTicket(pathConfig, methodConfig, getAuthzClient(), httpFacade);
|
|
||||||
authzRequest.setTicket(ticket);
|
|
||||||
} else {
|
|
||||||
if (accessToken.getAuthorization() != null) {
|
|
||||||
authzRequest.addPermission(pathConfig.getId(), methodConfig.getScopes());
|
authzRequest.addPermission(pathConfig.getId(), methodConfig.getScopes());
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<String, List<String>> claims = getClaims(pathConfig, httpFacade);
|
Map<String, List<String>> claims = resolveClaims(pathConfig, httpFacade);
|
||||||
|
|
||||||
if (!claims.isEmpty()) {
|
if (!claims.isEmpty()) {
|
||||||
authzRequest.setClaimTokenFormat("urn:ietf:params:oauth:token-type:jwt");
|
authzRequest.setClaimTokenFormat("urn:ietf:params:oauth:token-type:jwt");
|
||||||
authzRequest.setClaimToken(Base64.encodeBytes(JsonSerialization.writeValueAsBytes(claims)));
|
authzRequest.setClaimToken(Base64.encodeBytes(JsonSerialization.writeValueAsBytes(claims)));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (accessToken.getAuthorization() != null) {
|
if (accessToken.getAuthorization() != null) {
|
||||||
authzRequest.setRpt(accessTokenString);
|
authzRequest.setRpt(accessTokenString);
|
||||||
}
|
}
|
||||||
|
|
||||||
LOGGER.debug("Obtaining authorization for authenticated user.");
|
LOGGER.debug("Obtaining authorization for authenticated user.");
|
||||||
AuthorizationResponse authzResponse = getAuthzClient().authorization(accessTokenString).authorize(authzRequest);
|
AuthorizationResponse authzResponse;
|
||||||
|
|
||||||
|
if (isBearerAuthorization(httpFacade)) {
|
||||||
|
authzRequest.setSubjectToken(accessTokenString);
|
||||||
|
authzResponse = getAuthzClient().authorization().authorize(authzRequest);
|
||||||
|
} else {
|
||||||
|
authzResponse = getAuthzClient().authorization(accessTokenString).authorize(authzRequest);
|
||||||
|
}
|
||||||
|
|
||||||
if (authzResponse != null) {
|
if (authzResponse != null) {
|
||||||
return AdapterRSATokenVerifier.verifyToken(authzResponse.getToken(), deployment);
|
return AdapterRSATokenVerifier.verifyToken(authzResponse.getToken(), deployment);
|
||||||
@@ -200,7 +182,7 @@ public class KeycloakAdapterPolicyEnforcer extends AbstractPolicyEnforcer {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getPermissionTicket(PathConfig pathConfig, PolicyEnforcerConfig.MethodConfig methodConfig, AuthzClient authzClient, HttpFacade httpFacade) {
|
private String getPermissionTicket(PathConfig pathConfig, PolicyEnforcerConfig.MethodConfig methodConfig, AuthzClient authzClient, OIDCHttpFacade httpFacade) {
|
||||||
if (getEnforcerConfig().getUserManagedAccess() != null) {
|
if (getEnforcerConfig().getUserManagedAccess() != null) {
|
||||||
ProtectionResource protection = authzClient.protection();
|
ProtectionResource protection = authzClient.protection();
|
||||||
PermissionResource permission = protection.permission();
|
PermissionResource permission = protection.permission();
|
||||||
@@ -209,7 +191,7 @@ public class KeycloakAdapterPolicyEnforcer extends AbstractPolicyEnforcer {
|
|||||||
permissionRequest.setResourceId(pathConfig.getId());
|
permissionRequest.setResourceId(pathConfig.getId());
|
||||||
permissionRequest.setScopes(new HashSet<>(methodConfig.getScopes()));
|
permissionRequest.setScopes(new HashSet<>(methodConfig.getScopes()));
|
||||||
|
|
||||||
Map<String, List<String>> claims = getClaims(pathConfig, httpFacade);
|
Map<String, List<String>> claims = resolveClaims(pathConfig, httpFacade);
|
||||||
|
|
||||||
if (!claims.isEmpty()) {
|
if (!claims.isEmpty()) {
|
||||||
permissionRequest.setClaims(claims);
|
permissionRequest.setClaims(claims);
|
||||||
@@ -221,35 +203,18 @@ public class KeycloakAdapterPolicyEnforcer extends AbstractPolicyEnforcer {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Map<String, List<String>> getClaims(PathConfig pathConfig, HttpFacade httpFacade) {
|
|
||||||
Map<String, List<String>> claims = new HashMap<>();
|
|
||||||
Map<String, Map<String, Object>> claimInformationPointConfig = pathConfig.getClaimInformationPointConfig();
|
|
||||||
|
|
||||||
if (claimInformationPointConfig != null) {
|
|
||||||
for (Entry<String, Map<String, Object>> claimDef : claimInformationPointConfig.entrySet()) {
|
|
||||||
ClaimInformationPointProviderFactory factory = getPolicyEnforcer().getClaimInformationPointProviderFactories().get(claimDef.getKey());
|
|
||||||
|
|
||||||
if (factory != null) {
|
|
||||||
claims.putAll(factory.create(claimDef.getValue()).resolve(httpFacade));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return claims;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isBearerAuthorization(OIDCHttpFacade httpFacade) {
|
private boolean isBearerAuthorization(OIDCHttpFacade httpFacade) {
|
||||||
List<String> authHeaders = httpFacade.getRequest().getHeaders("Authorization");
|
List<String> authHeaders = httpFacade.getRequest().getHeaders("Authorization");
|
||||||
if (authHeaders == null || authHeaders.size() == 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (authHeaders != null) {
|
||||||
for (String authHeader : authHeaders) {
|
for (String authHeader : authHeaders) {
|
||||||
String[] split = authHeader.trim().split("\\s+");
|
String[] split = authHeader.trim().split("\\s+");
|
||||||
if (split == null || split.length != 2) continue;
|
if (split == null || split.length != 2) continue;
|
||||||
if (!split[0].equalsIgnoreCase("Bearer")) continue;
|
if (!split[0].equalsIgnoreCase("Bearer")) continue;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return getPolicyEnforcer().getDeployment().isBearerOnly();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+11
@@ -271,7 +271,17 @@ public class PolicyEnforcer {
|
|||||||
List<ResourceRepresentation> matchingResources = authzClient.protection().resource().findByMatchingUri(targetUri);
|
List<ResourceRepresentation> matchingResources = authzClient.protection().resource().findByMatchingUri(targetUri);
|
||||||
|
|
||||||
if (!matchingResources.isEmpty()) {
|
if (!matchingResources.isEmpty()) {
|
||||||
|
Map<String, Map<String, Object>> cipConfig = null;
|
||||||
|
|
||||||
|
if (pathConfig != null) {
|
||||||
|
cipConfig = pathConfig.getClaimInformationPointConfig();
|
||||||
|
}
|
||||||
|
|
||||||
pathConfig = PathConfig.createPathConfig(matchingResources.get(0));
|
pathConfig = PathConfig.createPathConfig(matchingResources.get(0));
|
||||||
|
|
||||||
|
if (cipConfig != null) {
|
||||||
|
pathConfig.setClaimInformationPointConfig(cipConfig);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (Exception cause) {
|
} catch (Exception cause) {
|
||||||
LOGGER.errorf(cause, "Could not lazy load resource with path [" + targetUri + "] from server");
|
LOGGER.errorf(cause, "Could not lazy load resource with path [" + targetUri + "] from server");
|
||||||
@@ -319,6 +329,7 @@ public class PolicyEnforcer {
|
|||||||
config.setMethods(originalConfig.getMethods());
|
config.setMethods(originalConfig.getMethods());
|
||||||
config.setParentConfig(originalConfig);
|
config.setParentConfig(originalConfig);
|
||||||
config.setEnforcementMode(originalConfig.getEnforcementMode());
|
config.setEnforcementMode(originalConfig.getEnforcementMode());
|
||||||
|
config.setClaimInformationPointConfig(originalConfig.getClaimInformationPointConfig());
|
||||||
|
|
||||||
return config;
|
return config;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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>4.0.0.Beta3</version>
|
<version>4.1.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>4.0.0.Beta3</version>
|
<version>4.1.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>4.0.0.Beta3</version>
|
<version>4.1.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>4.0.0.Beta3</version>
|
<version>4.1.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-fuse7-integration-pom</artifactId>
|
<artifactId>keycloak-fuse7-integration-pom</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>4.0.0.Beta3</version>
|
<version>4.1.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-fuse7-integration-pom</artifactId>
|
<artifactId>keycloak-fuse7-integration-pom</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>4.0.0.Beta3</version>
|
<version>4.1.0.Final</version>
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
@@ -36,6 +36,7 @@
|
|||||||
</keycloak.osgi.export>
|
</keycloak.osgi.export>
|
||||||
<keycloak.osgi.import>
|
<keycloak.osgi.import>
|
||||||
!org.keycloak.adapters.osgi.jetty94,
|
!org.keycloak.adapters.osgi.jetty94,
|
||||||
|
org.ops4j.pax.web.*;version="[7.1,9)",
|
||||||
org.keycloak.*;version="${project.version}",
|
org.keycloak.*;version="${project.version}",
|
||||||
*;resolution:=optional
|
*;resolution:=optional
|
||||||
</keycloak.osgi.import>
|
</keycloak.osgi.import>
|
||||||
|
|||||||
+5
@@ -86,6 +86,9 @@ public class PaxWebIntegrationService {
|
|||||||
return httpContext;
|
return httpContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setHttpContext(HttpContext httpContext) {
|
||||||
|
this.httpContext = httpContext;
|
||||||
|
}
|
||||||
|
|
||||||
public void start() {
|
public void start() {
|
||||||
ServiceTrackerCustomizer trackerCustomizer = new ServiceTrackerCustomizer() {
|
ServiceTrackerCustomizer trackerCustomizer = new ServiceTrackerCustomizer() {
|
||||||
@@ -115,7 +118,9 @@ public class PaxWebIntegrationService {
|
|||||||
|
|
||||||
protected WebContainer addingWebContainerCallback(ServiceReference webContainerServiceReference) {
|
protected WebContainer addingWebContainerCallback(ServiceReference webContainerServiceReference) {
|
||||||
WebContainer service = (WebContainer) bundleContext.getService(webContainerServiceReference);
|
WebContainer service = (WebContainer) bundleContext.getService(webContainerServiceReference);
|
||||||
|
if (httpContext == null) {
|
||||||
httpContext = service.createDefaultHttpContext();
|
httpContext = service.createDefaultHttpContext();
|
||||||
|
}
|
||||||
|
|
||||||
addJettyWebXml(service);
|
addJettyWebXml(service);
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>4.0.0.Beta3</version>
|
<version>4.1.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-fuse7-integration-pom</artifactId>
|
<artifactId>keycloak-fuse7-integration-pom</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>4.0.0.Beta3</version>
|
<version>4.1.0.Final</version>
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
@@ -36,6 +36,7 @@
|
|||||||
</keycloak.osgi.export>
|
</keycloak.osgi.export>
|
||||||
<keycloak.osgi.import>
|
<keycloak.osgi.import>
|
||||||
!org.keycloak.adapters.osgi.tomcat,
|
!org.keycloak.adapters.osgi.tomcat,
|
||||||
|
org.ops4j.pax.web.*;version="[7.1,9)",
|
||||||
org.keycloak.*;version="${project.version}",
|
org.keycloak.*;version="${project.version}",
|
||||||
*;resolution:=optional
|
*;resolution:=optional
|
||||||
</keycloak.osgi.import>
|
</keycloak.osgi.import>
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-fuse7-integration-pom</artifactId>
|
<artifactId>keycloak-fuse7-integration-pom</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>4.0.0.Beta3</version>
|
<version>4.1.0.Final</version>
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
@@ -38,7 +38,7 @@
|
|||||||
!org.keycloak.adapters.osgi.undertow,
|
!org.keycloak.adapters.osgi.undertow,
|
||||||
org.keycloak.*;version="${project.version}",
|
org.keycloak.*;version="${project.version}",
|
||||||
org.keycloak.adapters.osgi.*;version="${project.version}",
|
org.keycloak.adapters.osgi.*;version="${project.version}",
|
||||||
org.ops4j.pax.web.*;version="[3.0,8)",
|
org.ops4j.pax.web.*;version="[7.1,9)",
|
||||||
javax.servlet.*;version="[2.5,4)";resolution:=optional,
|
javax.servlet.*;version="[2.5,4)";resolution:=optional,
|
||||||
org.apache.cxf.transport.http;resolution:=optional;version="[3,4)",
|
org.apache.cxf.transport.http;resolution:=optional;version="[3,4)",
|
||||||
org.apache.cxf.transport.http_undertow;resolution:=optional;version="[3,4)",
|
org.apache.cxf.transport.http_undertow;resolution:=optional;version="[3,4)",
|
||||||
@@ -65,11 +65,6 @@
|
|||||||
<artifactId>org.osgi.enterprise</artifactId>
|
<artifactId>org.osgi.enterprise</artifactId>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>org.ops4j.pax.web</groupId>
|
|
||||||
<artifactId>pax-web-runtime</artifactId>
|
|
||||||
<scope>provided</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.ops4j.pax.web</groupId>
|
<groupId>org.ops4j.pax.web</groupId>
|
||||||
<artifactId>pax-web-spi</artifactId>
|
<artifactId>pax-web-spi</artifactId>
|
||||||
|
|||||||
+5
@@ -70,6 +70,9 @@ public class PaxWebIntegrationService {
|
|||||||
return httpContext;
|
return httpContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setHttpContext(HttpContext httpContext) {
|
||||||
|
this.httpContext = httpContext;
|
||||||
|
}
|
||||||
|
|
||||||
public void start() {
|
public void start() {
|
||||||
ServiceTrackerCustomizer trackerCustomizer = new ServiceTrackerCustomizer() {
|
ServiceTrackerCustomizer trackerCustomizer = new ServiceTrackerCustomizer() {
|
||||||
@@ -99,7 +102,9 @@ public class PaxWebIntegrationService {
|
|||||||
|
|
||||||
protected WebContainer addingWebContainerCallback(ServiceReference webContainerServiceReference) {
|
protected WebContainer addingWebContainerCallback(ServiceReference webContainerServiceReference) {
|
||||||
WebContainer service = (WebContainer) bundleContext.getService(webContainerServiceReference);
|
WebContainer service = (WebContainer) bundleContext.getService(webContainerServiceReference);
|
||||||
|
if (httpContext == null) {
|
||||||
httpContext = service.createDefaultHttpContext();
|
httpContext = service.createDefaultHttpContext();
|
||||||
|
}
|
||||||
|
|
||||||
if (constraintMappings == null) {
|
if (constraintMappings == null) {
|
||||||
throw new IllegalStateException("constraintMappings was null!");
|
throw new IllegalStateException("constraintMappings was null!");
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>4.0.0.Beta3</version>
|
<version>4.1.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>4.0.0.Beta3</version>
|
<version>4.1.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>4.0.0.Beta3</version>
|
<version>4.1.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>4.0.0.Beta3</version>
|
<version>4.1.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>4.0.0.Beta3</version>
|
<version>4.1.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>4.0.0.Beta3</version>
|
<version>4.1.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>4.0.0.Beta3</version>
|
<version>4.1.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>4.0.0.Beta3</version>
|
<version>4.1.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>4.0.0.Beta3</version>
|
<version>4.1.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>4.0.0.Beta3</version>
|
<version>4.1.0.Final</version>
|
||||||
<relativePath>../../../pom.xml</relativePath>
|
<relativePath>../../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|||||||
@@ -161,6 +161,14 @@ declare namespace Keycloak {
|
|||||||
* the user's profile to a new preferred locale.
|
* the user's profile to a new preferred locale.
|
||||||
*/
|
*/
|
||||||
kcLocale?: string;
|
kcLocale?: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies arguments that are passed to the Cordova in-app-browser (if applicable).
|
||||||
|
* Options 'hidden' and 'location' are not affected by these arguments.
|
||||||
|
* All available options are defined at https://cordova.apache.org/docs/en/latest/reference/cordova-plugin-inappbrowser/.
|
||||||
|
* Example of use: { zoom: "no", hardwareback: "yes" }
|
||||||
|
*/
|
||||||
|
cordovaOptions?: { [optionName: string]: string };
|
||||||
}
|
}
|
||||||
|
|
||||||
type KeycloakPromiseCallback<T> = (result: T) => void;
|
type KeycloakPromiseCallback<T> = (result: T) => void;
|
||||||
|
|||||||
@@ -250,7 +250,16 @@
|
|||||||
baseUrl = kc.endpoints.authorize();
|
baseUrl = kc.endpoints.authorize();
|
||||||
}
|
}
|
||||||
|
|
||||||
var scope = (options && options.scope) ? "openid " + options.scope : "openid";
|
var scope;
|
||||||
|
if (options && options.scope) {
|
||||||
|
if (options.scope.indexOf("openid") != -1) {
|
||||||
|
scope = options.scope;
|
||||||
|
} else {
|
||||||
|
scope = "openid " + options.scope;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
scope = "openid";
|
||||||
|
}
|
||||||
|
|
||||||
var url = baseUrl
|
var url = baseUrl
|
||||||
+ '?client_id=' + encodeURIComponent(kc.clientId)
|
+ '?client_id=' + encodeURIComponent(kc.clientId)
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>4.0.0.Beta3</version>
|
<version>4.1.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>4.0.0.Beta3</version>
|
<version>4.1.0.Final</version>
|
||||||
<relativePath>../../../pom.xml</relativePath>
|
<relativePath>../../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
@@ -77,11 +77,6 @@
|
|||||||
<artifactId>org.osgi.enterprise</artifactId>
|
<artifactId>org.osgi.enterprise</artifactId>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>org.ops4j.pax.web</groupId>
|
|
||||||
<artifactId>pax-web-runtime</artifactId>
|
|
||||||
<scope>provided</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.ops4j.pax.web</groupId>
|
<groupId>org.ops4j.pax.web</groupId>
|
||||||
<artifactId>pax-web-api</artifactId>
|
<artifactId>pax-web-api</artifactId>
|
||||||
@@ -99,6 +94,12 @@
|
|||||||
<version>${cxf.version}</version>
|
<version>${cxf.version}</version>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>junit</groupId>
|
||||||
|
<artifactId>junit</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
|||||||
+28
-4
@@ -25,6 +25,7 @@ import java.io.File;
|
|||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.net.URI;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
@@ -34,13 +35,35 @@ public class PathBasedKeycloakConfigResolver implements KeycloakConfigResolver {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public KeycloakDeployment resolve(OIDCHttpFacade.Request request) {
|
public KeycloakDeployment resolve(OIDCHttpFacade.Request request) {
|
||||||
String path = request.getURI();
|
String uri = request.getURI();
|
||||||
String[] urlTokens = path.split("/");
|
String relativePath = request.getRelativePath();
|
||||||
|
String webContext = null;
|
||||||
|
if (relativePath == null || !uri.contains(relativePath)) {
|
||||||
|
String[] urlTokens = uri.split("/");
|
||||||
if (urlTokens.length < 4) {
|
if (urlTokens.length < 4) {
|
||||||
throw new IllegalStateException("Not able to determine the web-context to load the correspondent keycloak.json file");
|
throw new IllegalStateException("Not able to determine the web-context to load the correspondent keycloak.json file");
|
||||||
}
|
}
|
||||||
|
|
||||||
String webContext = urlTokens[3];
|
webContext = urlTokens[3];
|
||||||
|
} else {
|
||||||
|
URI parsedURI = URI.create(uri);
|
||||||
|
String path = parsedURI.getPath();
|
||||||
|
path = path.substring(0, path.indexOf(relativePath));
|
||||||
|
while (path.startsWith("/")) {
|
||||||
|
path = path.substring(1);
|
||||||
|
}
|
||||||
|
webContext = path;
|
||||||
|
if ("".equals(webContext)) {
|
||||||
|
path = relativePath;
|
||||||
|
while (path.startsWith("/")) {
|
||||||
|
path = path.substring(1);
|
||||||
|
}
|
||||||
|
if (path.contains("/")) {
|
||||||
|
path = path.substring(0, path.indexOf("/"));
|
||||||
|
}
|
||||||
|
webContext = path;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
KeycloakDeployment deployment = cache.get(webContext);
|
KeycloakDeployment deployment = cache.get(webContext);
|
||||||
if (null == deployment) {
|
if (null == deployment) {
|
||||||
@@ -54,7 +77,8 @@ public class PathBasedKeycloakConfigResolver implements KeycloakConfigResolver {
|
|||||||
keycloakConfig = karafEtc;
|
keycloakConfig = karafEtc;
|
||||||
}
|
}
|
||||||
|
|
||||||
String absolutePath = keycloakConfig + File.separator + webContext + "-keycloak.json";
|
String absolutePath = keycloakConfig + File.separator + webContext + ("".equals(webContext) ? "" : "-")
|
||||||
|
+ "keycloak.json";
|
||||||
InputStream is = null;
|
InputStream is = null;
|
||||||
try {
|
try {
|
||||||
is = new FileInputStream(absolutePath);
|
is = new FileInputStream(absolutePath);
|
||||||
|
|||||||
+149
@@ -0,0 +1,149 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018 Red Hat, Inc. and/or its affiliates
|
||||||
|
* and other contributors as indicated by the @author tags.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package org.keycloak.adapters.osgi;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.keycloak.adapters.KeycloakDeployment;
|
||||||
|
import org.keycloak.adapters.OIDCHttpFacade;
|
||||||
|
import org.keycloak.adapters.spi.AuthenticationError;
|
||||||
|
import org.keycloak.adapters.spi.HttpFacade;
|
||||||
|
import org.keycloak.adapters.spi.LogoutError;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
|
||||||
|
public class PathBasedKeycloakConfigResolverTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void relativeURIsAndContexts() throws Exception {
|
||||||
|
PathBasedKeycloakConfigResolver resolver = new PathBasedKeycloakConfigResolver();
|
||||||
|
|
||||||
|
assertNotNull(populate(resolver, "test")
|
||||||
|
.resolve(new MockRequest("http://localhost/test/a/b/c?d=e", "/a/b/c")));
|
||||||
|
|
||||||
|
assertNotNull(populate(resolver, "test")
|
||||||
|
.resolve(new MockRequest("http://localhost/test/a/b/c?d=e", "/a/b")));
|
||||||
|
|
||||||
|
// means default context and actually we use first segment
|
||||||
|
assertNotNull(populate(resolver, "test")
|
||||||
|
.resolve(new MockRequest("http://localhost/test/a/b/c?d=e", "/test/a/b/c")));
|
||||||
|
|
||||||
|
assertNotNull(populate(resolver, "test/a")
|
||||||
|
.resolve(new MockRequest("http://localhost/test/a/b/c?d=e", "/b/c")));
|
||||||
|
|
||||||
|
assertNotNull(populate(resolver, "")
|
||||||
|
.resolve(new MockRequest("http://localhost/", "/")));
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
private PathBasedKeycloakConfigResolver populate(PathBasedKeycloakConfigResolver resolver, String context)
|
||||||
|
throws Exception {
|
||||||
|
Field f = PathBasedKeycloakConfigResolver.class.getDeclaredField("cache");
|
||||||
|
f.setAccessible(true);
|
||||||
|
Map<String, KeycloakDeployment> cache = (Map<String, KeycloakDeployment>) f.get(resolver);
|
||||||
|
cache.clear();
|
||||||
|
cache.put(context, new KeycloakDeployment());
|
||||||
|
|
||||||
|
return resolver;
|
||||||
|
}
|
||||||
|
|
||||||
|
private class MockRequest implements OIDCHttpFacade.Request {
|
||||||
|
|
||||||
|
private String uri;
|
||||||
|
private String relativePath;
|
||||||
|
|
||||||
|
public MockRequest(String uri, String relativePath) {
|
||||||
|
this.uri = uri;
|
||||||
|
this.relativePath = relativePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getMethod() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getURI() {
|
||||||
|
return this.uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getRelativePath() {
|
||||||
|
return this.relativePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isSecure() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getFirstParam(String param) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getQueryParamValue(String param) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HttpFacade.Cookie getCookie(String cookieName) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getHeader(String name) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> getHeaders(String name) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public InputStream getInputStream() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public InputStream getInputStream(boolean buffered) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getRemoteAddr() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setError(AuthenticationError error) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setError(LogoutError error) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -20,7 +20,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>4.0.0.Beta3</version>
|
<version>4.1.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>4.0.0.Beta3</version>
|
<version>4.1.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>4.0.0.Beta3</version>
|
<version>4.1.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>4.0.0.Beta3</version>
|
<version>4.1.0.Final</version>
|
||||||
<relativePath>../../../pom.xml</relativePath>
|
<relativePath>../../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>4.0.0.Beta3</version>
|
<version>4.1.0.Final</version>
|
||||||
<relativePath>../../../pom.xml</relativePath>
|
<relativePath>../../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<artifactId>spring-boot-container-bundle</artifactId>
|
<artifactId>spring-boot-container-bundle</artifactId>
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>4.0.0.Beta3</version>
|
<version>4.1.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>4.0.0.Beta3</version>
|
<version>4.1.0.Final</version>
|
||||||
<relativePath>../../../pom.xml</relativePath>
|
<relativePath>../../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
@@ -31,7 +31,7 @@
|
|||||||
<description/>
|
<description/>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<spring-boot.version>2.0.0.RELEASE</spring-boot.version>
|
<spring-boot.version>2.0.3.RELEASE</spring-boot.version>
|
||||||
<spring.version>5.0.2.RELEASE</spring.version>
|
<spring.version>5.0.2.RELEASE</spring.version>
|
||||||
<mockito.version>1.9.5</mockito.version>
|
<mockito.version>1.9.5</mockito.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>4.0.0.Beta3</version>
|
<version>4.1.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>4.0.0.Beta3</version>
|
<version>4.1.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>4.0.0.Beta3</version>
|
<version>4.1.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>4.0.0.Beta3</version>
|
<version>4.1.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>4.0.0.Beta3</version>
|
<version>4.1.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>4.0.0.Beta3</version>
|
<version>4.1.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>4.0.0.Beta3</version>
|
<version>4.1.0.Final</version>
|
||||||
<relativePath>../../../pom.xml</relativePath>
|
<relativePath>../../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>4.0.0.Beta3</version>
|
<version>4.1.0.Final</version>
|
||||||
<relativePath>../../../pom.xml</relativePath>
|
<relativePath>../../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
@@ -95,5 +95,10 @@
|
|||||||
<artifactId>jboss-servlet-api_3.0_spec</artifactId>
|
<artifactId>jboss-servlet-api_3.0_spec</artifactId>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.undertow</groupId>
|
||||||
|
<artifactId>undertow-servlet</artifactId>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</project>
|
</project>
|
||||||
+1
-7
@@ -78,7 +78,7 @@ public class ElytronAccount implements OidcKeycloakAccount {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean tryRefresh(CallbackHandler callbackHandler) {
|
boolean tryRefresh() {
|
||||||
log.debug("Trying to refresh");
|
log.debug("Trying to refresh");
|
||||||
|
|
||||||
RefreshableKeycloakSecurityContext securityContext = getKeycloakSecurityContext();
|
RefreshableKeycloakSecurityContext securityContext = getKeycloakSecurityContext();
|
||||||
@@ -88,16 +88,10 @@ public class ElytronAccount implements OidcKeycloakAccount {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (securityContext.refreshExpiredToken(false)) {
|
if (securityContext.refreshExpiredToken(false)) {
|
||||||
SecurityIdentity securityIdentity = SecurityIdentityUtil.authorize(callbackHandler, principal);
|
|
||||||
|
|
||||||
if (securityIdentity != null) {
|
|
||||||
log.debug("refresh succeeded");
|
log.debug("refresh succeeded");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return checkActive();
|
return checkActive();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+1
-1
@@ -88,7 +88,7 @@ public class ElytronCookieTokenStore implements ElytronTokeStore {
|
|||||||
boolean active = account.checkActive();
|
boolean active = account.checkActive();
|
||||||
|
|
||||||
if (!active) {
|
if (!active) {
|
||||||
active = account.tryRefresh(this.callbackHandler);
|
active = account.tryRefresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (active) {
|
if (active) {
|
||||||
|
|||||||
+14
@@ -18,6 +18,7 @@
|
|||||||
|
|
||||||
package org.keycloak.adapters.elytron;
|
package org.keycloak.adapters.elytron;
|
||||||
|
|
||||||
|
import io.undertow.server.handlers.CookieImpl;
|
||||||
import org.bouncycastle.asn1.cmp.Challenge;
|
import org.bouncycastle.asn1.cmp.Challenge;
|
||||||
import org.keycloak.KeycloakSecurityContext;
|
import org.keycloak.KeycloakSecurityContext;
|
||||||
import org.keycloak.adapters.AdapterDeploymentContext;
|
import org.keycloak.adapters.AdapterDeploymentContext;
|
||||||
@@ -62,6 +63,8 @@ import java.util.function.Consumer;
|
|||||||
*/
|
*/
|
||||||
class ElytronHttpFacade implements OIDCHttpFacade {
|
class ElytronHttpFacade implements OIDCHttpFacade {
|
||||||
|
|
||||||
|
static final String UNDERTOW_EXCHANGE = ElytronHttpFacade.class.getName() + ".undertow.exchange";
|
||||||
|
|
||||||
private final HttpServerRequest request;
|
private final HttpServerRequest request;
|
||||||
private final CallbackHandler callbackHandler;
|
private final CallbackHandler callbackHandler;
|
||||||
private final AdapterTokenStore tokenStore;
|
private final AdapterTokenStore tokenStore;
|
||||||
@@ -312,6 +315,17 @@ class ElytronHttpFacade implements OIDCHttpFacade {
|
|||||||
@Override
|
@Override
|
||||||
public void resetCookie(final String name, final String path) {
|
public void resetCookie(final String name, final String path) {
|
||||||
responseConsumer = responseConsumer.andThen(response -> setCookie(name, "", path, null, 0, false, false, response));
|
responseConsumer = responseConsumer.andThen(response -> setCookie(name, "", path, null, 0, false, false, response));
|
||||||
|
HttpScope exchangeScope = getScope(Scope.EXCHANGE);
|
||||||
|
ProtectedHttpServerExchange undertowExchange = ProtectedHttpServerExchange.class.cast(exchangeScope.getAttachment(UNDERTOW_EXCHANGE));
|
||||||
|
|
||||||
|
if (undertowExchange != null) {
|
||||||
|
CookieImpl cookie = new CookieImpl(name, "");
|
||||||
|
|
||||||
|
cookie.setMaxAge(0);
|
||||||
|
cookie.setPath(path);
|
||||||
|
|
||||||
|
undertowExchange.getExchange().setResponseCookie(cookie);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
+1
-1
@@ -104,7 +104,7 @@ public class ElytronSessionTokenStore implements ElytronTokeStore {
|
|||||||
boolean active = account.checkActive();
|
boolean active = account.checkActive();
|
||||||
|
|
||||||
if (!active) {
|
if (!active) {
|
||||||
active = account.tryRefresh(this.callbackHandler);
|
active = account.tryRefresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (active) {
|
if (active) {
|
||||||
|
|||||||
+3
-1
@@ -43,7 +43,8 @@ import java.io.InputStream;
|
|||||||
*/
|
*/
|
||||||
public class KeycloakConfigurationServletListener implements ServletContextListener {
|
public class KeycloakConfigurationServletListener implements ServletContextListener {
|
||||||
|
|
||||||
static final String ADAPTER_DEPLOYMENT_CONTEXT_ATTRIBUTE = AdapterDeploymentContext.class.getName() + ".elytron";
|
static final String ADAPTER_DEPLOYMENT_CONTEXT_ATTRIBUTE = AdapterDeploymentContext.class.getName();
|
||||||
|
static final String ADAPTER_DEPLOYMENT_CONTEXT_ATTRIBUTE_ELYTRON = AdapterDeploymentContext.class.getName() + ".elytron";
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void contextInitialized(ServletContextEvent sce) {
|
public void contextInitialized(ServletContextEvent sce) {
|
||||||
@@ -76,6 +77,7 @@ public class KeycloakConfigurationServletListener implements ServletContextListe
|
|||||||
}
|
}
|
||||||
|
|
||||||
servletContext.setAttribute(ADAPTER_DEPLOYMENT_CONTEXT_ATTRIBUTE, deploymentContext);
|
servletContext.setAttribute(ADAPTER_DEPLOYMENT_CONTEXT_ATTRIBUTE, deploymentContext);
|
||||||
|
servletContext.setAttribute(ADAPTER_DEPLOYMENT_CONTEXT_ATTRIBUTE_ELYTRON, deploymentContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
+2
-2
@@ -46,7 +46,7 @@ import org.wildfly.security.http.Scope;
|
|||||||
*/
|
*/
|
||||||
class KeycloakHttpServerAuthenticationMechanism implements HttpServerAuthenticationMechanism {
|
class KeycloakHttpServerAuthenticationMechanism implements HttpServerAuthenticationMechanism {
|
||||||
|
|
||||||
static Logger LOGGER = Logger.getLogger(KeycloakHttpServerAuthenticationMechanismFactory.class);
|
static Logger LOGGER = Logger.getLogger(KeycloakHttpServerAuthenticationMechanism.class);
|
||||||
static final String NAME = "KEYCLOAK";
|
static final String NAME = "KEYCLOAK";
|
||||||
|
|
||||||
private final Map<String, ?> properties;
|
private final Map<String, ?> properties;
|
||||||
@@ -126,7 +126,7 @@ class KeycloakHttpServerAuthenticationMechanism implements HttpServerAuthenticat
|
|||||||
|
|
||||||
private AdapterDeploymentContext getDeploymentContext(HttpServerRequest request) {
|
private AdapterDeploymentContext getDeploymentContext(HttpServerRequest request) {
|
||||||
if (this.deploymentContext == null) {
|
if (this.deploymentContext == null) {
|
||||||
return (AdapterDeploymentContext) request.getScope(Scope.APPLICATION).getAttachment(KeycloakConfigurationServletListener.ADAPTER_DEPLOYMENT_CONTEXT_ATTRIBUTE);
|
return (AdapterDeploymentContext) request.getScope(Scope.APPLICATION).getAttachment(KeycloakConfigurationServletListener.ADAPTER_DEPLOYMENT_CONTEXT_ATTRIBUTE_ELYTRON);
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.deploymentContext;
|
return this.deploymentContext;
|
||||||
|
|||||||
+42
@@ -0,0 +1,42 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018 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.elytron;
|
||||||
|
|
||||||
|
import javax.servlet.ServletContext;
|
||||||
|
import javax.servlet.ServletRequest;
|
||||||
|
|
||||||
|
import io.undertow.server.HttpHandler;
|
||||||
|
import io.undertow.servlet.ServletExtension;
|
||||||
|
import io.undertow.servlet.api.DeploymentInfo;
|
||||||
|
import io.undertow.servlet.handlers.ServletRequestContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||||
|
*/
|
||||||
|
public class KeycloakServletExtension implements ServletExtension {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleDeployment(DeploymentInfo deploymentInfo, ServletContext servletContext) {
|
||||||
|
deploymentInfo.addOuterHandlerChainWrapper(handler -> (HttpHandler) exchange -> {
|
||||||
|
ServletRequest servletRequest = exchange.getAttachment(ServletRequestContext.ATTACHMENT_KEY).getServletRequest();
|
||||||
|
|
||||||
|
servletRequest.setAttribute(ElytronHttpFacade.UNDERTOW_EXCHANGE, new ProtectedHttpServerExchange(exchange));
|
||||||
|
|
||||||
|
handler.handleRequest(exchange);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
+42
@@ -0,0 +1,42 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018 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.elytron;
|
||||||
|
|
||||||
|
import io.undertow.server.HttpServerExchange;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>A wrapper for {@code {@link HttpServerExchange}} accessible only from classes in the same package.
|
||||||
|
*
|
||||||
|
* <p>This class is used to provide to the elytron mechanism access to the current exchange in order to allow making
|
||||||
|
* changes to the exchange (e.g. response) during the evaluation of requests. By default, changes to the exchange are only
|
||||||
|
* propagated after the execution of the mechanism. But in certain situations, such as when making a programmatic logout (HttpServletRequest.logout()) from
|
||||||
|
* within application code, any change made to the exchange is not propagated.
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||||
|
*/
|
||||||
|
class ProtectedHttpServerExchange {
|
||||||
|
|
||||||
|
private final HttpServerExchange exchange;
|
||||||
|
|
||||||
|
public ProtectedHttpServerExchange(HttpServerExchange exchange) {
|
||||||
|
this.exchange = exchange;
|
||||||
|
}
|
||||||
|
|
||||||
|
HttpServerExchange getExchange() {
|
||||||
|
return exchange;
|
||||||
|
}
|
||||||
|
}
|
||||||
+52
@@ -0,0 +1,52 @@
|
|||||||
|
#
|
||||||
|
# * Copyright 2018 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.
|
||||||
|
#
|
||||||
|
|
||||||
|
#
|
||||||
|
# * Copyright 2018 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.
|
||||||
|
#
|
||||||
|
|
||||||
|
#
|
||||||
|
# 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.
|
||||||
|
#
|
||||||
|
|
||||||
|
org.keycloak.adapters.elytron.KeycloakServletExtension
|
||||||
@@ -20,7 +20,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>4.0.0.Beta3</version>
|
<version>4.1.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>4.0.0.Beta3</version>
|
<version>4.1.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>4.0.0.Beta3</version>
|
<version>4.1.0.Final</version>
|
||||||
<relativePath>../../../../pom.xml</relativePath>
|
<relativePath>../../../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|||||||
+61
-16
@@ -17,21 +17,6 @@
|
|||||||
|
|
||||||
package org.keycloak.adapters.wildfly;
|
package org.keycloak.adapters.wildfly;
|
||||||
|
|
||||||
import io.undertow.security.api.SecurityContext;
|
|
||||||
import io.undertow.server.HttpServerExchange;
|
|
||||||
import org.jboss.logging.Logger;
|
|
||||||
import org.jboss.security.NestableGroup;
|
|
||||||
import org.jboss.security.SecurityConstants;
|
|
||||||
import org.jboss.security.SecurityContextAssociation;
|
|
||||||
import org.jboss.security.SimpleGroup;
|
|
||||||
import org.jboss.security.SimplePrincipal;
|
|
||||||
import org.keycloak.adapters.AdapterTokenStore;
|
|
||||||
import org.keycloak.adapters.KeycloakDeployment;
|
|
||||||
import org.keycloak.adapters.spi.HttpFacade;
|
|
||||||
import org.keycloak.adapters.undertow.KeycloakUndertowAccount;
|
|
||||||
import org.keycloak.adapters.undertow.ServletRequestAuthenticator;
|
|
||||||
|
|
||||||
import javax.security.auth.Subject;
|
|
||||||
import java.security.Principal;
|
import java.security.Principal;
|
||||||
import java.security.acl.Group;
|
import java.security.acl.Group;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
@@ -39,11 +24,33 @@ import java.util.Enumeration;
|
|||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import javax.security.auth.Subject;
|
||||||
|
|
||||||
|
import org.jboss.logging.Logger;
|
||||||
|
import org.jboss.security.NestableGroup;
|
||||||
|
import org.jboss.security.SecurityConstants;
|
||||||
|
import org.jboss.security.SecurityContextAssociation;
|
||||||
|
import org.jboss.security.SimpleGroup;
|
||||||
|
import org.jboss.security.SimplePrincipal;
|
||||||
|
import org.jboss.security.SubjectInfo;
|
||||||
|
import org.jboss.security.identity.RoleGroup;
|
||||||
|
import org.jboss.security.identity.plugins.SimpleRole;
|
||||||
|
import org.jboss.security.identity.plugins.SimpleRoleGroup;
|
||||||
|
import org.keycloak.adapters.AdapterTokenStore;
|
||||||
|
import org.keycloak.adapters.KeycloakDeployment;
|
||||||
|
import org.keycloak.adapters.spi.HttpFacade;
|
||||||
|
import org.keycloak.adapters.undertow.KeycloakUndertowAccount;
|
||||||
|
import org.keycloak.adapters.undertow.ServletRequestAuthenticator;
|
||||||
|
|
||||||
|
import io.undertow.security.api.SecurityContext;
|
||||||
|
import io.undertow.server.HttpServerExchange;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
* @version $Revision: 1 $
|
* @version $Revision: 1 $
|
||||||
*/
|
*/
|
||||||
public class WildflyRequestAuthenticator extends ServletRequestAuthenticator {
|
public class WildflyRequestAuthenticator extends ServletRequestAuthenticator
|
||||||
|
{
|
||||||
protected static Logger log = Logger.getLogger(WildflyRequestAuthenticator.class);
|
protected static Logger log = Logger.getLogger(WildflyRequestAuthenticator.class);
|
||||||
|
|
||||||
public WildflyRequestAuthenticator(HttpFacade facade, KeycloakDeployment deployment, int sslRedirectPort,
|
public WildflyRequestAuthenticator(HttpFacade facade, KeycloakDeployment deployment, int sslRedirectPort,
|
||||||
@@ -87,6 +94,13 @@ public class WildflyRequestAuthenticator extends ServletRequestAuthenticator {
|
|||||||
org.jboss.security.SecurityContext sc = SecurityContextAssociation.getSecurityContext();
|
org.jboss.security.SecurityContext sc = SecurityContextAssociation.getSecurityContext();
|
||||||
Principal userPrincipal = getPrincipal(subject);
|
Principal userPrincipal = getPrincipal(subject);
|
||||||
sc.getUtil().createSubjectInfo(userPrincipal, account, subject);
|
sc.getUtil().createSubjectInfo(userPrincipal, account, subject);
|
||||||
|
|
||||||
|
// Roles of subjectInfo are null, because is was constructed by
|
||||||
|
// org.jboss.security.identity.extensions.CredentialIdentityFactory
|
||||||
|
// .createIdentity(Principal [=userPrincipal], Object [=account], Role [=null]).
|
||||||
|
// Therefore the roles are only contained in the authenticatedSubject (member of subjectInfo)
|
||||||
|
// and subsequent logics do only access subjectInfo#roles instead of authenticatedSubject#roles.
|
||||||
|
mapGroupMembersOfAuthenticatedSubjectIntoSecurityContext(sc);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -150,4 +164,35 @@ public class WildflyRequestAuthenticator extends ServletRequestAuthenticator {
|
|||||||
return roleSets;
|
return roleSets;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void mapGroupMembersOfAuthenticatedSubjectIntoSecurityContext(org.jboss.security.SecurityContext sc) {
|
||||||
|
SubjectInfo subjectInfo = sc.getSubjectInfo();
|
||||||
|
if (subjectInfo == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Subject authenticatedSubject = subjectInfo.getAuthenticatedSubject();
|
||||||
|
if (authenticatedSubject == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get role group of security context in order to add roles of authenticatedSubject.
|
||||||
|
RoleGroup scRoles = sc.getUtil().getRoles();
|
||||||
|
if (scRoles == null) {
|
||||||
|
scRoles = new SimpleRoleGroup("Roles");
|
||||||
|
sc.getUtil().setRoles(scRoles);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get group roles of authenticatedSubject and add each role of the group into security context
|
||||||
|
Iterator<Principal> principalItr = authenticatedSubject.getPrincipals().iterator();
|
||||||
|
while (principalItr.hasNext()) {
|
||||||
|
Principal principal = principalItr.next();
|
||||||
|
if (principal instanceof Group) {
|
||||||
|
Enumeration<? extends Principal> members = ((Group) principal).members();
|
||||||
|
while (members.hasMoreElements()) {
|
||||||
|
Principal role = members.nextElement();
|
||||||
|
scRoles.addRole(new SimpleRole(role.getName()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -21,7 +21,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<version>4.0.0.Beta3</version>
|
<version>4.1.0.Final</version>
|
||||||
<relativePath>../../../../pom.xml</relativePath>
|
<relativePath>../../../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|||||||
+58
@@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018 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.subsystem.adapter.extension;
|
||||||
|
|
||||||
|
import org.jboss.as.server.deployment.DeploymentPhaseContext;
|
||||||
|
import org.jboss.as.server.deployment.DeploymentUnit;
|
||||||
|
import org.jboss.as.web.common.WarMetaData;
|
||||||
|
import org.jboss.metadata.web.jboss.JBossWebMetaData;
|
||||||
|
import org.jboss.msc.service.ServiceName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility class for Elytron integration
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||||
|
*/
|
||||||
|
public final class Elytron {
|
||||||
|
|
||||||
|
private static final String DEFAULT_SECURITY_DOMAIN = "other";
|
||||||
|
private static final String UNDERTOW_APPLICATION_SECURITY_DOMAIN = "org.wildfly.undertow.application-security-domain.";
|
||||||
|
|
||||||
|
static boolean isElytronEnabled(DeploymentPhaseContext phaseContext) {
|
||||||
|
String securityDomain = getSecurityDomain(phaseContext.getDeploymentUnit());
|
||||||
|
ServiceName serviceName = ServiceName.parse(new StringBuilder(UNDERTOW_APPLICATION_SECURITY_DOMAIN).append(securityDomain).toString());
|
||||||
|
return phaseContext.getServiceRegistry().getService(serviceName) != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String getSecurityDomain(DeploymentUnit deploymentUnit) {
|
||||||
|
WarMetaData warMetaData = deploymentUnit.getAttachment(WarMetaData.ATTACHMENT_KEY);
|
||||||
|
|
||||||
|
if (warMetaData != null) {
|
||||||
|
JBossWebMetaData webMetaData = warMetaData.getMergedJBossWebMetaData();
|
||||||
|
|
||||||
|
if (webMetaData != null) {
|
||||||
|
String configuredSecurityDomain = webMetaData.getSecurityDomain();
|
||||||
|
|
||||||
|
if (configuredSecurityDomain != null) {
|
||||||
|
return configuredSecurityDomain;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return DEFAULT_SECURITY_DOMAIN;
|
||||||
|
}
|
||||||
|
}
|
||||||
+8
-3
@@ -17,6 +17,8 @@
|
|||||||
|
|
||||||
package org.keycloak.subsystem.adapter.extension;
|
package org.keycloak.subsystem.adapter.extension;
|
||||||
|
|
||||||
|
import static org.keycloak.subsystem.adapter.extension.Elytron.isElytronEnabled;
|
||||||
|
|
||||||
import org.jboss.as.server.deployment.DeploymentPhaseContext;
|
import org.jboss.as.server.deployment.DeploymentPhaseContext;
|
||||||
import org.jboss.as.server.deployment.DeploymentUnit;
|
import org.jboss.as.server.deployment.DeploymentUnit;
|
||||||
import org.jboss.as.server.deployment.DeploymentUnitProcessingException;
|
import org.jboss.as.server.deployment.DeploymentUnitProcessingException;
|
||||||
@@ -73,7 +75,7 @@ public class KeycloakAdapterConfigDeploymentProcessor implements DeploymentUnitP
|
|||||||
addKeycloakAuthData(phaseContext, service);
|
addKeycloakAuthData(phaseContext, service);
|
||||||
}
|
}
|
||||||
|
|
||||||
addConfigurationListener(deploymentUnit);
|
addConfigurationListener(phaseContext);
|
||||||
|
|
||||||
// FYI, Undertow Extension will find deployments that have auth-method set to KEYCLOAK
|
// FYI, Undertow Extension will find deployments that have auth-method set to KEYCLOAK
|
||||||
|
|
||||||
@@ -125,7 +127,8 @@ public class KeycloakAdapterConfigDeploymentProcessor implements DeploymentUnitP
|
|||||||
webMetaData.setContextParams(contextParams);
|
webMetaData.setContextParams(contextParams);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addConfigurationListener(DeploymentUnit deploymentUnit) {
|
private void addConfigurationListener(DeploymentPhaseContext phaseContext) {
|
||||||
|
DeploymentUnit deploymentUnit = phaseContext.getDeploymentUnit();
|
||||||
WarMetaData warMetaData = deploymentUnit.getAttachment(WarMetaData.ATTACHMENT_KEY);
|
WarMetaData warMetaData = deploymentUnit.getAttachment(WarMetaData.ATTACHMENT_KEY);
|
||||||
if (warMetaData == null) {
|
if (warMetaData == null) {
|
||||||
return;
|
return;
|
||||||
@@ -144,16 +147,18 @@ public class KeycloakAdapterConfigDeploymentProcessor implements DeploymentUnitP
|
|||||||
if (!loginConfig.getAuthMethod().equals("KEYCLOAK")) {
|
if (!loginConfig.getAuthMethod().equals("KEYCLOAK")) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isElytronEnabled(phaseContext)) {
|
||||||
ListenerMetaData listenerMetaData = new ListenerMetaData();
|
ListenerMetaData listenerMetaData = new ListenerMetaData();
|
||||||
|
|
||||||
listenerMetaData.setListenerClass(KeycloakConfigurationServletListener.class.getName());
|
listenerMetaData.setListenerClass(KeycloakConfigurationServletListener.class.getName());
|
||||||
|
|
||||||
webMetaData.getListeners().add(listenerMetaData);
|
webMetaData.getListeners().add(listenerMetaData);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void undeploy(DeploymentUnit du) {
|
public void undeploy(DeploymentUnit du) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
+2
-2
@@ -63,7 +63,7 @@ public abstract class KeycloakDependencyProcessor implements DeploymentUnitProce
|
|||||||
final ModuleSpecification moduleSpecification = deploymentUnit.getAttachment(Attachments.MODULE_SPECIFICATION);
|
final ModuleSpecification moduleSpecification = deploymentUnit.getAttachment(Attachments.MODULE_SPECIFICATION);
|
||||||
final ModuleLoader moduleLoader = Module.getBootModuleLoader();
|
final ModuleLoader moduleLoader = Module.getBootModuleLoader();
|
||||||
addCommonModules(moduleSpecification, moduleLoader);
|
addCommonModules(moduleSpecification, moduleLoader);
|
||||||
addPlatformSpecificModules(moduleSpecification, moduleLoader);
|
addPlatformSpecificModules(phaseContext, moduleSpecification, moduleLoader);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addCommonModules(ModuleSpecification moduleSpecification, ModuleLoader moduleLoader) {
|
private void addCommonModules(ModuleSpecification moduleSpecification, ModuleLoader moduleLoader) {
|
||||||
@@ -74,7 +74,7 @@ public abstract class KeycloakDependencyProcessor implements DeploymentUnitProce
|
|||||||
moduleSpecification.addSystemDependency(new ModuleDependency(moduleLoader, KEYCLOAK_COMMON, false, false, false, false));
|
moduleSpecification.addSystemDependency(new ModuleDependency(moduleLoader, KEYCLOAK_COMMON, false, false, false, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract protected void addPlatformSpecificModules(ModuleSpecification moduleSpecification, ModuleLoader moduleLoader);
|
abstract protected void addPlatformSpecificModules(DeploymentPhaseContext phaseContext, ModuleSpecification moduleSpecification, ModuleLoader moduleLoader);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void undeploy(DeploymentUnit du) {
|
public void undeploy(DeploymentUnit du) {
|
||||||
|
|||||||
+8
-2
@@ -17,6 +17,9 @@
|
|||||||
|
|
||||||
package org.keycloak.subsystem.adapter.extension;
|
package org.keycloak.subsystem.adapter.extension;
|
||||||
|
|
||||||
|
import static org.keycloak.subsystem.adapter.extension.Elytron.isElytronEnabled;
|
||||||
|
|
||||||
|
import org.jboss.as.server.deployment.DeploymentPhaseContext;
|
||||||
import org.jboss.as.server.deployment.module.ModuleDependency;
|
import org.jboss.as.server.deployment.module.ModuleDependency;
|
||||||
import org.jboss.as.server.deployment.module.ModuleSpecification;
|
import org.jboss.as.server.deployment.module.ModuleSpecification;
|
||||||
import org.jboss.modules.ModuleIdentifier;
|
import org.jboss.modules.ModuleIdentifier;
|
||||||
@@ -34,9 +37,12 @@ public class KeycloakDependencyProcessorWildFly extends KeycloakDependencyProces
|
|||||||
private static final ModuleIdentifier KEYCLOAK_UNDERTOW_ADAPTER = ModuleIdentifier.create("org.keycloak.keycloak-undertow-adapter");
|
private static final ModuleIdentifier KEYCLOAK_UNDERTOW_ADAPTER = ModuleIdentifier.create("org.keycloak.keycloak-undertow-adapter");
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void addPlatformSpecificModules(ModuleSpecification moduleSpecification, ModuleLoader moduleLoader) {
|
protected void addPlatformSpecificModules(DeploymentPhaseContext phaseContext, ModuleSpecification moduleSpecification, ModuleLoader moduleLoader) {
|
||||||
|
if (isElytronEnabled(phaseContext)) {
|
||||||
|
moduleSpecification.addSystemDependency(new ModuleDependency(moduleLoader, KEYCLOAK_ELYTRON_ADAPTER, true, false, true, false));
|
||||||
|
} else {
|
||||||
moduleSpecification.addSystemDependency(new ModuleDependency(moduleLoader, KEYCLOAK_WILDFLY_ADAPTER, false, false, true, false));
|
moduleSpecification.addSystemDependency(new ModuleDependency(moduleLoader, KEYCLOAK_WILDFLY_ADAPTER, false, false, true, false));
|
||||||
moduleSpecification.addSystemDependency(new ModuleDependency(moduleLoader, KEYCLOAK_UNDERTOW_ADAPTER, false, false, false, false));
|
moduleSpecification.addSystemDependency(new ModuleDependency(moduleLoader, KEYCLOAK_UNDERTOW_ADAPTER, false, false, false, false));
|
||||||
moduleSpecification.addSystemDependency(new ModuleDependency(moduleLoader, KEYCLOAK_ELYTRON_ADAPTER, true, false, false, false));
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+1
-1
@@ -20,7 +20,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>4.0.0.Beta3</version>
|
<version>4.1.0.Final</version>
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<name>Keycloak Adapters</name>
|
<name>Keycloak Adapters</name>
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-saml-eap-integration-pom</artifactId>
|
<artifactId>keycloak-saml-eap-integration-pom</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>4.0.0.Beta3</version>
|
<version>4.1.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>4.0.0.Beta3</version>
|
<version>4.1.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>4.0.0.Beta3</version>
|
<version>4.1.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>4.0.0.Beta3</version>
|
<version>4.1.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>4.0.0.Beta3</version>
|
<version>4.1.0.Final</version>
|
||||||
<relativePath>../../../pom.xml</relativePath>
|
<relativePath>../../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|||||||
+1
-1
@@ -339,7 +339,7 @@ public abstract class AbstractSamlAuthenticationHandler implements SamlAuthentic
|
|||||||
return AuthOutcome.FAILED;
|
return AuthOutcome.FAILED;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
assertion = AssertionUtil.getAssertion(responseType, deployment.getDecryptionKey());
|
assertion = AssertionUtil.getAssertion(responseHolder, responseType, deployment.getDecryptionKey());
|
||||||
if (AssertionUtil.hasExpired(assertion)) {
|
if (AssertionUtil.hasExpired(assertion)) {
|
||||||
return initiateLogin();
|
return initiateLogin();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>4.0.0.Beta3</version>
|
<version>4.1.0.Final</version>
|
||||||
<relativePath>../../../../pom.xml</relativePath>
|
<relativePath>../../../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|||||||
+14
-2
@@ -66,6 +66,7 @@ import java.io.IOException;
|
|||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
@@ -119,16 +120,27 @@ public abstract class AbstractSamlAuthenticator extends LoginAuthenticator {
|
|||||||
tokenStore.logoutAccount();
|
tokenStore.logoutAccount();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static final Pattern PROTOCOL_PATTERN = Pattern.compile("^[a-zA-Z][a-zA-Z0-9+.-]*:");
|
||||||
|
|
||||||
protected void forwardToLogoutPage(Request request, HttpServletResponse response, SamlDeployment deployment) {
|
protected void forwardToLogoutPage(Request request, HttpServletResponse response, SamlDeployment deployment) {
|
||||||
RequestDispatcher disp = request.getRequestDispatcher(deployment.getLogoutPage());
|
final String location = deployment.getLogoutPage();
|
||||||
|
|
||||||
|
try {
|
||||||
//make sure the login page is never cached
|
//make sure the login page is never cached
|
||||||
response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
|
response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
|
||||||
response.setHeader("Pragma", "no-cache");
|
response.setHeader("Pragma", "no-cache");
|
||||||
response.setHeader("Expires", "0");
|
response.setHeader("Expires", "0");
|
||||||
|
|
||||||
|
if (location == null) {
|
||||||
|
log.warn("Logout page not set.");
|
||||||
|
response.sendError(HttpServletResponse.SC_NOT_FOUND);
|
||||||
|
} else if (PROTOCOL_PATTERN.matcher(location).find()) {
|
||||||
|
response.sendRedirect(response.encodeRedirectURL(location));
|
||||||
|
} else {
|
||||||
|
RequestDispatcher disp = request.getRequestDispatcher(location);
|
||||||
|
|
||||||
try {
|
|
||||||
disp.forward(request, response);
|
disp.forward(request, response);
|
||||||
|
}
|
||||||
} catch (ServletException e) {
|
} catch (ServletException e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>4.0.0.Beta3</version>
|
<version>4.1.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>4.0.0.Beta3</version>
|
<version>4.1.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>4.0.0.Beta3</version>
|
<version>4.1.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>4.0.0.Beta3</version>
|
<version>4.1.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>4.0.0.Beta3</version>
|
<version>4.1.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>4.0.0.Beta3</version>
|
<version>4.1.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>4.0.0.Beta3</version>
|
<version>4.1.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>4.0.0.Beta3</version>
|
<version>4.1.0.Final</version>
|
||||||
<relativePath>../../../pom.xml</relativePath>
|
<relativePath>../../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|||||||
+11
-3
@@ -52,6 +52,7 @@ import java.io.IOException;
|
|||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
@@ -61,6 +62,7 @@ public class SamlFilter implements Filter {
|
|||||||
protected SamlDeploymentContext deploymentContext;
|
protected SamlDeploymentContext deploymentContext;
|
||||||
protected SessionIdMapper idMapper;
|
protected SessionIdMapper idMapper;
|
||||||
private final static Logger log = Logger.getLogger("" + SamlFilter.class);
|
private final static Logger log = Logger.getLogger("" + SamlFilter.class);
|
||||||
|
private static final Pattern PROTOCOL_PATTERN = Pattern.compile("^[a-zA-Z][a-zA-Z0-9+.-]*:");
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void init(final FilterConfig filterConfig) throws ServletException {
|
public void init(final FilterConfig filterConfig) throws ServletException {
|
||||||
@@ -137,7 +139,7 @@ public class SamlFilter implements Filter {
|
|||||||
}
|
}
|
||||||
FilterSamlSessionStore tokenStore = new FilterSamlSessionStore(request, facade, 100000, idMapper);
|
FilterSamlSessionStore tokenStore = new FilterSamlSessionStore(request, facade, 100000, idMapper);
|
||||||
boolean isEndpoint = request.getRequestURI().substring(request.getContextPath().length()).endsWith("/saml");
|
boolean isEndpoint = request.getRequestURI().substring(request.getContextPath().length()).endsWith("/saml");
|
||||||
SamlAuthenticator authenticator = null;
|
SamlAuthenticator authenticator;
|
||||||
if (isEndpoint) {
|
if (isEndpoint) {
|
||||||
authenticator = new SamlAuthenticator(facade, deployment, tokenStore) {
|
authenticator = new SamlAuthenticator(facade, deployment, tokenStore) {
|
||||||
@Override
|
@Override
|
||||||
@@ -176,9 +178,15 @@ public class SamlFilter implements Filter {
|
|||||||
}
|
}
|
||||||
if (outcome == AuthOutcome.LOGGED_OUT) {
|
if (outcome == AuthOutcome.LOGGED_OUT) {
|
||||||
tokenStore.logoutAccount();
|
tokenStore.logoutAccount();
|
||||||
if (deployment.getLogoutPage() != null) {
|
String logoutPage = deployment.getLogoutPage();
|
||||||
RequestDispatcher disp = req.getRequestDispatcher(deployment.getLogoutPage());
|
if (logoutPage != null) {
|
||||||
|
if (PROTOCOL_PATTERN.matcher(logoutPage).find()) {
|
||||||
|
response.sendRedirect(logoutPage);
|
||||||
|
log.log(Level.FINE, "Redirected to logout page {0}", logoutPage);
|
||||||
|
} else {
|
||||||
|
RequestDispatcher disp = req.getRequestDispatcher(logoutPage);
|
||||||
disp.forward(req, res);
|
disp.forward(req, res);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
chain.doFilter(req, res);
|
chain.doFilter(req, res);
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>4.0.0.Beta3</version>
|
<version>4.1.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>4.0.0.Beta3</version>
|
<version>4.1.0.Final</version>
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|||||||
+15
-4
@@ -44,7 +44,7 @@ import java.io.FileNotFoundException;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.lang.reflect.*;
|
import java.lang.reflect.*;
|
||||||
import java.util.Map;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Keycloak authentication valve
|
* Keycloak authentication valve
|
||||||
@@ -189,16 +189,27 @@ public abstract class AbstractSamlAuthenticatorValve extends FormAuthenticator i
|
|||||||
|
|
||||||
protected abstract GenericPrincipalFactory createPrincipalFactory();
|
protected abstract GenericPrincipalFactory createPrincipalFactory();
|
||||||
protected abstract boolean forwardToErrorPageInternal(Request request, HttpServletResponse response, Object loginConfig) throws IOException;
|
protected abstract boolean forwardToErrorPageInternal(Request request, HttpServletResponse response, Object loginConfig) throws IOException;
|
||||||
protected void forwardToLogoutPage(Request request, HttpServletResponse response,SamlDeployment deployment) {
|
private static final Pattern PROTOCOL_PATTERN = Pattern.compile("^[a-zA-Z][a-zA-Z0-9+.-]*:");
|
||||||
RequestDispatcher disp = request.getRequestDispatcher(deployment.getLogoutPage());
|
|
||||||
|
protected void forwardToLogoutPage(Request request, HttpServletResponse response, SamlDeployment deployment) {
|
||||||
|
final String location = deployment.getLogoutPage();
|
||||||
|
|
||||||
|
try {
|
||||||
//make sure the login page is never cached
|
//make sure the login page is never cached
|
||||||
response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
|
response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
|
||||||
response.setHeader("Pragma", "no-cache");
|
response.setHeader("Pragma", "no-cache");
|
||||||
response.setHeader("Expires", "0");
|
response.setHeader("Expires", "0");
|
||||||
|
|
||||||
|
if (location == null) {
|
||||||
|
log.warn("Logout page not set.");
|
||||||
|
response.sendError(HttpServletResponse.SC_NOT_FOUND);
|
||||||
|
} else if (PROTOCOL_PATTERN.matcher(location).find()) {
|
||||||
|
response.sendRedirect(response.encodeRedirectURL(location));
|
||||||
|
} else {
|
||||||
|
RequestDispatcher disp = request.getRequestDispatcher(location);
|
||||||
|
|
||||||
try {
|
|
||||||
disp.forward(request.getRequest(), response);
|
disp.forward(request.getRequest(), response);
|
||||||
|
}
|
||||||
} catch (ServletException e) {
|
} catch (ServletException e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
|
|||||||
@@ -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>4.0.0.Beta3</version>
|
<version>4.1.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>4.0.0.Beta3</version>
|
<version>4.1.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>4.0.0.Beta3</version>
|
<version>4.1.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>4.0.0.Beta3</version>
|
<version>4.1.0.Final</version>
|
||||||
<relativePath>../../../pom.xml</relativePath>
|
<relativePath>../../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|||||||
+20
-3
@@ -33,6 +33,9 @@ import org.keycloak.adapters.spi.AuthOutcome;
|
|||||||
import org.keycloak.adapters.spi.HttpFacade;
|
import org.keycloak.adapters.spi.HttpFacade;
|
||||||
import org.keycloak.adapters.undertow.UndertowHttpFacade;
|
import org.keycloak.adapters.undertow.UndertowHttpFacade;
|
||||||
import org.keycloak.adapters.undertow.UndertowUserSessionManagement;
|
import org.keycloak.adapters.undertow.UndertowUserSessionManagement;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Abstract base class for a Keycloak-enabled Undertow AuthenticationMechanism.
|
* Abstract base class for a Keycloak-enabled Undertow AuthenticationMechanism.
|
||||||
@@ -40,6 +43,9 @@ import org.keycloak.adapters.undertow.UndertowUserSessionManagement;
|
|||||||
* @author Stan Silvert ssilvert@redhat.com (C) 2014 Red Hat Inc.
|
* @author Stan Silvert ssilvert@redhat.com (C) 2014 Red Hat Inc.
|
||||||
*/
|
*/
|
||||||
public abstract class AbstractSamlAuthMech implements AuthenticationMechanism {
|
public abstract class AbstractSamlAuthMech implements AuthenticationMechanism {
|
||||||
|
|
||||||
|
private static final Logger LOG = Logger.getLogger(AbstractSamlAuthMech.class.getName());
|
||||||
|
|
||||||
public static final AttachmentKey<AuthChallenge> KEYCLOAK_CHALLENGE_ATTACHMENT_KEY = AttachmentKey.create(AuthChallenge.class);
|
public static final AttachmentKey<AuthChallenge> KEYCLOAK_CHALLENGE_ATTACHMENT_KEY = AttachmentKey.create(AuthChallenge.class);
|
||||||
protected SamlDeploymentContext deploymentContext;
|
protected SamlDeploymentContext deploymentContext;
|
||||||
protected UndertowUserSessionManagement sessionManagement;
|
protected UndertowUserSessionManagement sessionManagement;
|
||||||
@@ -68,12 +74,23 @@ public abstract class AbstractSamlAuthMech implements AuthenticationMechanism {
|
|||||||
return StatusCodes.TEMPORARY_REDIRECT;
|
return StatusCodes.TEMPORARY_REDIRECT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static final Pattern PROTOCOL_PATTERN = Pattern.compile("^[a-zA-Z][a-zA-Z0-9+.-]*:");
|
||||||
|
|
||||||
static void sendRedirect(final HttpServerExchange exchange, final String location) {
|
static void sendRedirect(final HttpServerExchange exchange, final String location) {
|
||||||
// TODO - String concatenation to construct URLS is extremely error prone - switch to a URI which will better
|
if (location == null) {
|
||||||
// handle this.
|
LOG.log(Level.WARNING, "Logout page not set.");
|
||||||
|
exchange.setStatusCode(StatusCodes.NOT_FOUND);
|
||||||
|
exchange.endExchange();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (PROTOCOL_PATTERN.matcher(location).find()) {
|
||||||
|
exchange.getResponseHeaders().put(Headers.LOCATION, location);
|
||||||
|
} else {
|
||||||
String loc = exchange.getRequestScheme() + "://" + exchange.getHostAndPort() + location;
|
String loc = exchange.getRequestScheme() + "://" + exchange.getHostAndPort() + location;
|
||||||
exchange.getResponseHeaders().put(Headers.LOCATION, loc);
|
exchange.getResponseHeaders().put(Headers.LOCATION, loc);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected void registerNotifications(final SecurityContext securityContext) {
|
protected void registerNotifications(final SecurityContext securityContext) {
|
||||||
|
|
||||||
@@ -142,7 +159,7 @@ public abstract class AbstractSamlAuthMech implements AuthenticationMechanism {
|
|||||||
protected void redirectLogout(SamlDeployment deployment, HttpServerExchange exchange) {
|
protected void redirectLogout(SamlDeployment deployment, HttpServerExchange exchange) {
|
||||||
String page = deployment.getLogoutPage();
|
String page = deployment.getLogoutPage();
|
||||||
sendRedirect(exchange, page);
|
sendRedirect(exchange, page);
|
||||||
exchange.setResponseCode(302);
|
exchange.setStatusCode(StatusCodes.FOUND);
|
||||||
exchange.endExchange();
|
exchange.endExchange();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+5
-1
@@ -113,7 +113,11 @@ public class ServletSamlAuthMech extends AbstractSamlAuthMech {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void redirectLogout(SamlDeployment deployment, HttpServerExchange exchange) {
|
protected void redirectLogout(SamlDeployment deployment, HttpServerExchange exchange) {
|
||||||
servePage(exchange, deployment.getLogoutPage());
|
exchange.getResponseHeaders().add(Headers.CACHE_CONTROL, "no-cache, no-store, must-revalidate");
|
||||||
|
exchange.getResponseHeaders().add(Headers.PRAGMA, "no-cache");
|
||||||
|
exchange.getResponseHeaders().add(Headers.EXPIRES, "0");
|
||||||
|
|
||||||
|
super.redirectLogout(deployment, exchange);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>4.0.0.Beta3</version>
|
<version>4.1.0.Final</version>
|
||||||
<relativePath>../../../pom.xml</relativePath>
|
<relativePath>../../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|||||||
+3
-1
@@ -49,7 +49,8 @@ public class KeycloakConfigurationServletListener implements ServletContextListe
|
|||||||
|
|
||||||
protected static Logger log = Logger.getLogger(KeycloakConfigurationServletListener.class);
|
protected static Logger log = Logger.getLogger(KeycloakConfigurationServletListener.class);
|
||||||
|
|
||||||
static final String ADAPTER_DEPLOYMENT_CONTEXT_ATTRIBUTE = SamlDeploymentContext.class.getName() + ".elytron";
|
static final String ADAPTER_DEPLOYMENT_CONTEXT_ATTRIBUTE = SamlDeploymentContext.class.getName();
|
||||||
|
static final String ADAPTER_DEPLOYMENT_CONTEXT_ATTRIBUTE_ELYTRON = SamlDeploymentContext.class.getName() + ".elytron";
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void contextInitialized(ServletContextEvent sce) {
|
public void contextInitialized(ServletContextEvent sce) {
|
||||||
@@ -93,6 +94,7 @@ public class KeycloakConfigurationServletListener implements ServletContextListe
|
|||||||
}
|
}
|
||||||
|
|
||||||
servletContext.setAttribute(ADAPTER_DEPLOYMENT_CONTEXT_ATTRIBUTE, deploymentContext);
|
servletContext.setAttribute(ADAPTER_DEPLOYMENT_CONTEXT_ATTRIBUTE, deploymentContext);
|
||||||
|
servletContext.setAttribute(ADAPTER_DEPLOYMENT_CONTEXT_ATTRIBUTE_ELYTRON, deploymentContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
+14
-4
@@ -19,6 +19,7 @@ package org.keycloak.adapters.saml.elytron;
|
|||||||
|
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
import javax.security.auth.callback.CallbackHandler;
|
import javax.security.auth.callback.CallbackHandler;
|
||||||
|
|
||||||
@@ -39,7 +40,7 @@ import org.wildfly.security.http.Scope;
|
|||||||
*/
|
*/
|
||||||
class KeycloakHttpServerAuthenticationMechanism implements HttpServerAuthenticationMechanism {
|
class KeycloakHttpServerAuthenticationMechanism implements HttpServerAuthenticationMechanism {
|
||||||
|
|
||||||
static Logger LOGGER = Logger.getLogger(KeycloakHttpServerAuthenticationMechanismFactory.class);
|
static Logger LOGGER = Logger.getLogger(KeycloakHttpServerAuthenticationMechanism.class);
|
||||||
static final String NAME = "KEYCLOAK-SAML";
|
static final String NAME = "KEYCLOAK-SAML";
|
||||||
|
|
||||||
private final Map<String, ?> properties;
|
private final Map<String, ?> properties;
|
||||||
@@ -130,7 +131,7 @@ class KeycloakHttpServerAuthenticationMechanism implements HttpServerAuthenticat
|
|||||||
|
|
||||||
private SamlDeploymentContext getDeploymentContext(HttpServerRequest request) {
|
private SamlDeploymentContext getDeploymentContext(HttpServerRequest request) {
|
||||||
if (this.deploymentContext == null) {
|
if (this.deploymentContext == null) {
|
||||||
return (SamlDeploymentContext) request.getScope(Scope.APPLICATION).getAttachment(KeycloakConfigurationServletListener.ADAPTER_DEPLOYMENT_CONTEXT_ATTRIBUTE);
|
return (SamlDeploymentContext) request.getScope(Scope.APPLICATION).getAttachment(KeycloakConfigurationServletListener.ADAPTER_DEPLOYMENT_CONTEXT_ATTRIBUTE_ELYTRON);
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.deploymentContext;
|
return this.deploymentContext;
|
||||||
@@ -142,9 +143,17 @@ class KeycloakHttpServerAuthenticationMechanism implements HttpServerAuthenticat
|
|||||||
exchange.getResponse().setStatus(302);
|
exchange.getResponse().setStatus(302);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static final Pattern PROTOCOL_PATTERN = Pattern.compile("^[a-zA-Z][a-zA-Z0-9+.-]*:");
|
||||||
|
|
||||||
static void sendRedirect(final ElytronHttpFacade exchange, final String location) {
|
static void sendRedirect(final ElytronHttpFacade exchange, final String location) {
|
||||||
// TODO - String concatenation to construct URLS is extremely error prone - switch to a URI which will better
|
if (location == null) {
|
||||||
// handle this.
|
LOGGER.warn("Logout page not set.");
|
||||||
|
exchange.getResponse().setStatus(302);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (PROTOCOL_PATTERN.matcher(location).find()) {
|
||||||
|
exchange.getResponse().setHeader("Location", location);
|
||||||
|
} else {
|
||||||
URI uri = exchange.getURI();
|
URI uri = exchange.getURI();
|
||||||
String path = uri.getPath();
|
String path = uri.getPath();
|
||||||
String relativePath = exchange.getRequest().getRelativePath();
|
String relativePath = exchange.getRequest().getRelativePath();
|
||||||
@@ -152,4 +161,5 @@ class KeycloakHttpServerAuthenticationMechanism implements HttpServerAuthenticat
|
|||||||
String loc = exchange.getURI().getScheme() + "://" + exchange.getURI().getHost() + ":" + exchange.getURI().getPort() + contextPath + location;
|
String loc = exchange.getURI().getScheme() + "://" + exchange.getURI().getHost() + ":" + exchange.getURI().getPort() + contextPath + location;
|
||||||
exchange.getResponse().setHeader("Location", loc);
|
exchange.getResponse().setHeader("Location", loc);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -20,7 +20,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<artifactId>keycloak-parent</artifactId>
|
<artifactId>keycloak-parent</artifactId>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<version>4.0.0.Beta3</version>
|
<version>4.1.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>4.0.0.Beta3</version>
|
<version>4.1.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>4.0.0.Beta3</version>
|
<version>4.1.0.Final</version>
|
||||||
<relativePath>../../../../pom.xml</relativePath>
|
<relativePath>../../../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
|||||||
+58
@@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018 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.subsystem.adapter.saml.extension;
|
||||||
|
|
||||||
|
import org.jboss.as.server.deployment.DeploymentPhaseContext;
|
||||||
|
import org.jboss.as.server.deployment.DeploymentUnit;
|
||||||
|
import org.jboss.as.web.common.WarMetaData;
|
||||||
|
import org.jboss.metadata.web.jboss.JBossWebMetaData;
|
||||||
|
import org.jboss.msc.service.ServiceName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility class for Elytron integration
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
|
||||||
|
*/
|
||||||
|
public final class Elytron {
|
||||||
|
|
||||||
|
private static final String DEFAULT_SECURITY_DOMAIN = "other";
|
||||||
|
private static final String UNDERTOW_APPLICATION_SECURITY_DOMAIN = "org.wildfly.undertow.application-security-domain.";
|
||||||
|
|
||||||
|
static boolean isElytronEnabled(DeploymentPhaseContext phaseContext) {
|
||||||
|
String securityDomain = getSecurityDomain(phaseContext.getDeploymentUnit());
|
||||||
|
ServiceName serviceName = ServiceName.parse(new StringBuilder(UNDERTOW_APPLICATION_SECURITY_DOMAIN).append(securityDomain).toString());
|
||||||
|
return phaseContext.getServiceRegistry().getService(serviceName) != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String getSecurityDomain(DeploymentUnit deploymentUnit) {
|
||||||
|
WarMetaData warMetaData = deploymentUnit.getAttachment(WarMetaData.ATTACHMENT_KEY);
|
||||||
|
|
||||||
|
if (warMetaData != null) {
|
||||||
|
JBossWebMetaData webMetaData = warMetaData.getMergedJBossWebMetaData();
|
||||||
|
|
||||||
|
if (webMetaData != null) {
|
||||||
|
String configuredSecurityDomain = webMetaData.getSecurityDomain();
|
||||||
|
|
||||||
|
if (configuredSecurityDomain != null) {
|
||||||
|
return configuredSecurityDomain;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return DEFAULT_SECURITY_DOMAIN;
|
||||||
|
}
|
||||||
|
}
|
||||||
+8
-2
@@ -17,6 +17,8 @@
|
|||||||
|
|
||||||
package org.keycloak.subsystem.adapter.saml.extension;
|
package org.keycloak.subsystem.adapter.saml.extension;
|
||||||
|
|
||||||
|
import static org.keycloak.subsystem.adapter.saml.extension.Elytron.isElytronEnabled;
|
||||||
|
|
||||||
import org.jboss.as.server.deployment.DeploymentPhaseContext;
|
import org.jboss.as.server.deployment.DeploymentPhaseContext;
|
||||||
import org.jboss.as.server.deployment.DeploymentUnit;
|
import org.jboss.as.server.deployment.DeploymentUnit;
|
||||||
import org.jboss.as.server.deployment.DeploymentUnitProcessingException;
|
import org.jboss.as.server.deployment.DeploymentUnitProcessingException;
|
||||||
@@ -55,7 +57,7 @@ public class KeycloakAdapterConfigDeploymentProcessor implements DeploymentUnitP
|
|||||||
addKeycloakSamlAuthData(phaseContext);
|
addKeycloakSamlAuthData(phaseContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
addConfigurationListener(deploymentUnit);
|
addConfigurationListener(phaseContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addKeycloakSamlAuthData(DeploymentPhaseContext phaseContext) throws DeploymentUnitProcessingException {
|
private void addKeycloakSamlAuthData(DeploymentPhaseContext phaseContext) throws DeploymentUnitProcessingException {
|
||||||
@@ -129,7 +131,8 @@ public class KeycloakAdapterConfigDeploymentProcessor implements DeploymentUnitP
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addConfigurationListener(DeploymentUnit deploymentUnit) {
|
private void addConfigurationListener(DeploymentPhaseContext phaseContext) {
|
||||||
|
DeploymentUnit deploymentUnit = phaseContext.getDeploymentUnit();
|
||||||
WarMetaData warMetaData = deploymentUnit.getAttachment(WarMetaData.ATTACHMENT_KEY);
|
WarMetaData warMetaData = deploymentUnit.getAttachment(WarMetaData.ATTACHMENT_KEY);
|
||||||
if (warMetaData == null) {
|
if (warMetaData == null) {
|
||||||
return;
|
return;
|
||||||
@@ -148,10 +151,13 @@ public class KeycloakAdapterConfigDeploymentProcessor implements DeploymentUnitP
|
|||||||
if (!loginConfig.getAuthMethod().equals("KEYCLOAK-SAML")) {
|
if (!loginConfig.getAuthMethod().equals("KEYCLOAK-SAML")) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isElytronEnabled(phaseContext)) {
|
||||||
ListenerMetaData listenerMetaData = new ListenerMetaData();
|
ListenerMetaData listenerMetaData = new ListenerMetaData();
|
||||||
|
|
||||||
listenerMetaData.setListenerClass(KeycloakConfigurationServletListener.class.getName());
|
listenerMetaData.setListenerClass(KeycloakConfigurationServletListener.class.getName());
|
||||||
|
|
||||||
webMetaData.getListeners().add(listenerMetaData);
|
webMetaData.getListeners().add(listenerMetaData);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Loaded 100 of 1513 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user