Compare commits

...
Author SHA1 Message Date
stianst 9d41c8a45f KEYCLOAK-7641 Introduce a profile to allow building only server 2018-06-18 11:39:23 +02:00
Bill Burke 5398f45b85 KEYCLOAK-6226 OpenShift integration 2018-06-18 11:39:23 +02:00
stianst e98fcfe56e KEYCLOAK-7641 Add details on how to build server-only, including some fixes to poms 2018-06-18 10:38:15 +02:00
June Zhang 2f366b0d5d Fixes KEYCLOAK-7637 UI background color issue 2018-06-15 14:19:38 -04:00
stianst e1a0e581b9 Update to 4.1.0.Final-SNAPSHOT 2018-06-14 14:22:28 +02:00
Dennis Bayer c43d8b3d85 Get role list to update directly from the security context rather than from previously created subject info.
Roles within groups must be unpacked added separately in order to contain all roles.
2018-06-13 21:03:30 -03:00
Dennis Bayer 6a2a121d4e Map group members of authenticated subject into subject info.
This commit contains a POC for the issue "Roles get lost after security context was propagated back to wildfly-swarm, if using jwt for authentication" (KEYCLOAK-7309).
2018-06-13 21:03:30 -03:00
Hynek Mlnarik 9dc5709ce7 KEYCLOAK-7593 Setters for httpContext 2018-06-13 16:32:39 +02:00
vramik ccb09fbf45 KEYCLOAK-7616 fix NPE for UserStorageConsentTest 2018-06-13 15:53:41 +02:00
Hynek Mlnarik fb883254f6 KEYCLOAK-7434 2018-06-13 14:31:44 +02:00
vramik 5f1f3dff5e KEYCLOAK-7094 Support redirect to external logout page for elytron adapter 2018-06-13 12:50:38 +02:00
Pedro Igor dd93de75d9 [KEYCLOAK-7579] - Fixing test to use client scopes instead of old scope param required (#5259) 2018-06-12 15:44:03 -03:00
Stefan Guilhen d897159560 [KEYCLOAK-7598] - Set CIP config when defining paths in policy enforcer config (#5264) 2018-06-12 11:24:17 -03:00
Vlasta Ramik 182c975e01 KEYCLOAK-7597 fix logger classes (#5263) 2018-06-12 11:02:04 -03:00
vramik f19a324030 KEYCLOAK-7587 Some system properties are not included 2018-06-12 11:42:10 +02:00
vramik 9cf965a157 Ignore non-related failing ClientInitiatedAccountLinkTest#testErrorConditions 2018-06-11 13:46:59 +02:00
vramik 9e42be09d7 KEYCLOAK-7517 - adapter tests - EAP6 provider 2018-06-11 13:46:59 +02:00
vramik 7d466be94e KEYCLOAK-6541 rename AppServerContainerSPI to AppServerContainerProvider 2018-06-11 13:46:59 +02:00
vramik a5c0cbc3b4 KEYCLOAK-7473 app-server-eap provider 2018-06-11 13:46:59 +02:00
vramik bb5dc4c473 KEYCLOAK-6745 Adapter tests - remove abstract adapter test classes 2018-06-11 13:46:59 +02:00
vramik 132386f64d KEYCLOAK-6541 app server wildfly provider 2018-06-11 13:46:59 +02:00
vramik b0c89d739b KEYCLOAK-6541 app server undertow support 2018-06-11 13:46:59 +02:00
vramik 6a07a7ed2c KEYCLOAK-6541 base changes 2018-06-11 13:46:59 +02:00
vramik f293ab86c3 KEYCLOAK-7267 change a way how to install adapters in testsuite from online to offline scripts 2018-06-11 13:46:59 +02:00
Pedro Igor db60abc604 [KEYCLOAK-7543] - Policy enforcer should not delegate decisions when using UMA (#5252) 2018-06-11 08:17:40 -03:00
Lorent Lempereur f55c93a1e4 Javascript Adapter - Add 'cordovaOptions' to the Typescript definition of KeycloakLoginOptions (#5250) 2018-06-11 08:21:04 +02:00
Grzegorz Grzybek 08296bd3ce [KEYCLOAK-7508] Fix a typo: resouces -> resources (#5243) 2018-06-11 08:18:32 +02:00
Grzegorz Grzybek fca6da3a5a KEYCLOAK-7523 better context path detection in PathBasedKeycloakConfigResolver 2018-06-08 21:32:14 +02:00
Marek Posoldaandvramik 49407c2e4f KEYCLOAK-6630 Client scopes initial support (#5076)
* KEYCLOAK-6630 KEYCLOAK-349 Client Scopes

Co-authored-by: vramik <vramik@redhat.com>

* KEYCLOAK-6630 Change some clientTemplate occurences to clientScope
2018-06-08 15:38:38 +02:00
Vlasta Ramik 4d1474afe0 KEYCLOAK-7549 Update artifactId according to latest Fuse7 build (#5253) 2018-06-08 15:15:34 +02:00
Pedro Igor aa128d6c07 Merge pull request #5240 from pedroigor/KEYCLOAK-7353
[KEYCLOAK-7353] Support Policy Management in Protection API
2018-06-07 11:05:49 -03:00
Ola Bergefall c8c76cc03f KEYCLOAK-7316: Default back to false if isPassive is missing in request. 2018-06-07 08:50:32 +02:00
Federico M. Facca 5a9bfea419 [KEYCLOAK-7353] Support Policy Management in Protection API
See https://issues.jboss.org/browse/KEYCLOAK-7353
2018-06-06 19:36:42 -03:00
vramik dffe70e40a KEYCLOAK-7518 DeploymentArchiveProcessor assumes that every archive contains jboss-deployment-structure.xml file 2018-06-06 21:15:39 +02:00
Tomas Kyjovsky 1b4d9a6147 KEYCLOAK-7440 Modcluster configuration for functional cluster test is broken 2018-06-06 20:40:50 +02:00
Stan Silvert b7fb3ec9a9 KEYCLOAK-7513 Minor changes to vertical nav (#5244) 2018-06-06 14:39:00 -04:00
Hynek Mlnarik 7ff18ca14b KEYCLOAK-7331 Fix NPE when SAML Issuer not set in AuthnRequest 2018-06-06 16:21:18 +02:00
Your Name 6052b1546d removed LANG-dependent check #7444 2018-06-06 12:53:58 +02:00
Hynek Mlnarik 5a241392cf KEYCLOAK-7094 Support redirect to external logout page 2018-06-05 14:51:18 +02:00
Takashi Norimatsu c586c63533 KEYCLOAK-6771 Holder of Key mechanism
OAuth 2.0 Mutual TLS Client Authentication and Certificate Bound Access
Tokens
2018-06-05 08:18:29 +02:00
Pedro Igor f8919f8baa Merge pull request #5211 from pedroigor/KEYCLOAK-7367
[KEYCLOAK-7367] - User-Managed Policy Provider
2018-06-04 09:35:13 -03:00
Stan Silvert f45ed1613e KEYCLOAK-7334: Update vertical na/Integrate patternfly-ng (#5241) 2018-06-04 07:53:37 -04:00
Pedro Igor bc665fdbc3 Merge pull request #5195 from suem/bugfix_FilterSessionStore
NullPointerException in FilterSessionStore when restoring request
2018-06-01 10:51:28 -03:00
Pavel Drozd 6c3e6bc90c KEYCLOAK-7476 - sshLoginTest - changed command result 2018-06-01 10:35:38 +02:00
Stan Silvert cb3b7f3cb2 KEYCLOAK-5934: Disable paste for event filters (#5026) 2018-06-01 10:28:56 +02:00
June Zhang 5e8db32329 Fixes KEYCLOAK-7382 - Application Response HTML Update (#5235) 2018-05-31 13:18:25 -04:00
Jared Blashka 65c39763eb KEYCLOAK-7356 Code to Token flow fails if initial redirect_uri contains a session_state parameter 2018-05-31 08:53:11 +02:00
Martin Kanis f429469fc8 KEYCLOAK-5270 Realm cookie path for IE<=11 users (#5106) 2018-05-31 08:44:34 +02:00
Pedro Igor 6339b62f8d Merge pull request #5219 from tkyjovsk/KEYCLOAK-6759
KEYCLOAK-6759 Create the databases for import during perf tests
2018-05-30 09:51:21 -03:00
Pedro Igor 473e9ab55c Merge pull request #5227 from pedroigor/KEYCLOAK-7449
[KEYCLOAK-7449] - When clicking link or actions the row is expanded
2018-05-29 14:38:23 -03:00
June Zhang 77e503f5ca Fixes KEYCLOAK-7381 Device Activity Response - HTML update (#5230) 2018-05-29 09:30:48 -04:00
Johannes Knutsen c64ecb1ab8 Remove expired objects from cache cluster instead of local only 2018-05-29 10:27:43 +02:00
Rick van den Hof 2e22dcfc47 Add unit tests 2018-05-29 10:03:54 +02:00
Rick van den Hof 16fd6558a6 Enable adding of default groups 2018-05-29 10:03:54 +02:00
Takashi Norimatsu eb97151476 KEYCLOAK-7451 OAuth Authorization Server Metadata for Proof Key for Code Exchange 2018-05-28 22:15:43 +02:00
Tomas Kyjovsky b8adee4004 KEYCLOAK-6759 Create the databases for import during perf tests 2018-05-28 17:52:27 +02:00
Pedro Igor 65f5eacdd4 [KEYCLOAK-7449] - When clicking link or actions the row is expanded 2018-05-25 17:57:03 -03:00
Pedro Igor 2b6597e9f1 [KEYCLOAK-7367] - User-Managed Policy Provider 2018-05-25 16:18:15 -03:00
Hynek Mlnarik 6a2f73df9c KEYCLOAK-7433 Update licenses 2018-05-25 11:27:51 +02:00
Hynek Mlnarik 60a03d0293 KEYCLOAK-7434 Align versions to match EAP 7.1.3 2018-05-25 11:27:51 +02:00
Hynek Mlnarik dd6735285d KEYCLOAK-7438 Don't create symlinks in download-license-files.sh 2018-05-25 09:50:41 +02:00
Stian Thorgersen dbf5c395b0 Bump version to 4.0.0.Final (#5224) 2018-05-24 19:02:30 +02:00
Samuel Ueltschi 3391ec5377 check if content-type is null when restoring request 2018-05-09 12:47:14 +02:00
1093 changed files with 26053 additions and 11667 deletions

No files matched your search

+4
View File
@@ -32,6 +32,10 @@ To build the distribution run:
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
-----------------
+1 -1
View File
@@ -21,7 +21,7 @@
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>4.0.0.Beta3-SNAPSHOT</version>
<version>4.1.0.Final-SNAPSHOT</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -28,6 +28,7 @@ import org.jboss.logging.Logger;
import org.keycloak.AuthorizationContext;
import org.keycloak.KeycloakSecurityContext;
import org.keycloak.adapters.OIDCHttpFacade;
import org.keycloak.adapters.spi.HttpFacade;
import org.keycloak.adapters.spi.HttpFacade.Request;
import org.keycloak.authorization.client.AuthzClient;
import org.keycloak.authorization.client.ClientAuthorizationContext;
@@ -165,7 +166,7 @@ public abstract class AbstractPolicyEnforcer {
policyEnforcer.getPathMatcher().removeFromCache(getPath(request));
}
return hasValidClaims(actualPathConfig, httpFacade, authorization);
return hasValidClaims(actualPathConfig, permission, httpFacade, authorization);
}
}
} else {
@@ -187,35 +188,22 @@ public abstract class AbstractPolicyEnforcer {
return false;
}
private boolean hasValidClaims(PathConfig actualPathConfig, OIDCHttpFacade httpFacade, Authorization authorization) {
Map<String, Map<String, Object>> claimInformationPointConfig = actualPathConfig.getClaimInformationPointConfig();
private boolean hasValidClaims(PathConfig actualPathConfig, Permission permission, OIDCHttpFacade httpFacade, Authorization authorization) {
Map<String, Set<String>> grantedClaims = permission.getClaims();
if (claimInformationPointConfig != null) {
Map<String, List<String>> claims = new HashMap<>();
if (grantedClaims != null) {
Map<String, List<String>> claims = resolveClaims(actualPathConfig, httpFacade);
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));
if (claims.isEmpty()) {
return false;
}
Map<String, List<String>> grantedClaims = authorization.getClaims();
for (Entry<String, Set<String>> entry : grantedClaims.entrySet()) {
List<String> requestClaims = claims.get(entry.getKey());
if (grantedClaims != null) {
if (claims.isEmpty()) {
if (requestClaims == null || requestClaims.isEmpty() || !entry.getValue().containsAll(requestClaims)) {
return false;
}
for (Entry<String, List<String>> entry : grantedClaims.entrySet()) {
List<String> requestClaims = claims.get(entry.getKey());
if (requestClaims == null || requestClaims.isEmpty() || !entry.getValue().containsAll(requestClaims)) {
return false;
}
}
}
}
@@ -342,4 +330,28 @@ public abstract class AbstractPolicyEnforcer {
private PathConfig getPathConfig(Request 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;
}
}
@@ -22,7 +22,6 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.jboss.logging.Logger;
import org.keycloak.KeycloakSecurityContext;
@@ -87,19 +86,6 @@ public class KeycloakAdapterPolicyEnforcer extends AbstractPolicyEnforcer {
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);
@@ -154,7 +140,7 @@ public class KeycloakAdapterPolicyEnforcer extends AbstractPolicyEnforcer {
}
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;
}
@@ -165,20 +151,15 @@ public class KeycloakAdapterPolicyEnforcer extends AbstractPolicyEnforcer {
AccessToken accessToken = securityContext.getToken();
AuthorizationRequest authzRequest = new AuthorizationRequest();
if (getEnforcerConfig().getUserManagedAccess() != null) {
String ticket = getPermissionTicket(pathConfig, methodConfig, getAuthzClient(), httpFacade);
authzRequest.setTicket(ticket);
} else {
if (accessToken.getAuthorization() != null) {
authzRequest.addPermission(pathConfig.getId(), methodConfig.getScopes());
}
if (isBearerAuthorization(httpFacade) || accessToken.getAuthorization() != null) {
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()) {
authzRequest.setClaimTokenFormat("urn:ietf:params:oauth:token-type:jwt");
authzRequest.setClaimToken(Base64.encodeBytes(JsonSerialization.writeValueAsBytes(claims)));
}
if (!claims.isEmpty()) {
authzRequest.setClaimTokenFormat("urn:ietf:params:oauth:token-type:jwt");
authzRequest.setClaimToken(Base64.encodeBytes(JsonSerialization.writeValueAsBytes(claims)));
}
if (accessToken.getAuthorization() != null) {
@@ -186,7 +167,14 @@ public class KeycloakAdapterPolicyEnforcer extends AbstractPolicyEnforcer {
}
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) {
return AdapterRSATokenVerifier.verifyToken(authzResponse.getToken(), deployment);
@@ -200,7 +188,7 @@ public class KeycloakAdapterPolicyEnforcer extends AbstractPolicyEnforcer {
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) {
ProtectionResource protection = authzClient.protection();
PermissionResource permission = protection.permission();
@@ -209,7 +197,7 @@ public class KeycloakAdapterPolicyEnforcer extends AbstractPolicyEnforcer {
permissionRequest.setResourceId(pathConfig.getId());
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()) {
permissionRequest.setClaims(claims);
@@ -221,22 +209,6 @@ public class KeycloakAdapterPolicyEnforcer extends AbstractPolicyEnforcer {
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) {
List<String> authHeaders = httpFacade.getRequest().getHeaders("Authorization");
if (authHeaders == null || authHeaders.size() == 0) {
@@ -271,7 +271,17 @@ public class PolicyEnforcer {
List<ResourceRepresentation> matchingResources = authzClient.protection().resource().findByMatchingUri(targetUri);
if (!matchingResources.isEmpty()) {
Map<String, Map<String, Object>> cipConfig = null;
if (pathConfig != null) {
cipConfig = pathConfig.getClaimInformationPointConfig();
}
pathConfig = PathConfig.createPathConfig(matchingResources.get(0));
if (cipConfig != null) {
pathConfig.setClaimInformationPointConfig(cipConfig);
}
}
} catch (Exception cause) {
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.setParentConfig(originalConfig);
config.setEnforcementMode(originalConfig.getEnforcementMode());
config.setClaimInformationPointConfig(originalConfig.getClaimInformationPointConfig());
return config;
}
@@ -21,7 +21,7 @@
<parent>
<artifactId>keycloak-as7-integration-pom</artifactId>
<groupId>org.keycloak</groupId>
<version>4.0.0.Beta3-SNAPSHOT</version>
<version>4.1.0.Final-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
+1 -1
View File
@@ -21,7 +21,7 @@
<parent>
<artifactId>keycloak-as7-integration-pom</artifactId>
<groupId>org.keycloak</groupId>
<version>4.0.0.Beta3-SNAPSHOT</version>
<version>4.1.0.Final-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
+1 -1
View File
@@ -21,7 +21,7 @@
<parent>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-as7-integration-pom</artifactId>
<version>4.0.0.Beta3-SNAPSHOT</version>
<version>4.1.0.Final-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
+1 -1
View File
@@ -20,7 +20,7 @@
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>4.0.0.Beta3-SNAPSHOT</version>
<version>4.1.0.Final-SNAPSHOT</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
<name>Keycloak AS7 / JBoss EAP 6 Integration</name>
+1 -1
View File
@@ -21,7 +21,7 @@
<parent>
<artifactId>keycloak-fuse7-integration-pom</artifactId>
<groupId>org.keycloak</groupId>
<version>4.0.0.Beta3-SNAPSHOT</version>
<version>4.1.0.Final-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
+1 -1
View File
@@ -21,7 +21,7 @@
<parent>
<artifactId>keycloak-fuse7-integration-pom</artifactId>
<groupId>org.keycloak</groupId>
<version>4.0.0.Beta3-SNAPSHOT</version>
<version>4.1.0.Final-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -86,6 +86,9 @@ public class PaxWebIntegrationService {
return httpContext;
}
public void setHttpContext(HttpContext httpContext) {
this.httpContext = httpContext;
}
public void start() {
ServiceTrackerCustomizer trackerCustomizer = new ServiceTrackerCustomizer() {
@@ -115,7 +118,9 @@ public class PaxWebIntegrationService {
protected WebContainer addingWebContainerCallback(ServiceReference webContainerServiceReference) {
WebContainer service = (WebContainer) bundleContext.getService(webContainerServiceReference);
httpContext = service.createDefaultHttpContext();
if (httpContext == null) {
httpContext = service.createDefaultHttpContext();
}
addJettyWebXml(service);
+1 -1
View File
@@ -21,7 +21,7 @@
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>4.0.0.Beta3-SNAPSHOT</version>
<version>4.1.0.Final-SNAPSHOT</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
+1 -1
View File
@@ -21,7 +21,7 @@
<parent>
<artifactId>keycloak-fuse7-integration-pom</artifactId>
<groupId>org.keycloak</groupId>
<version>4.0.0.Beta3-SNAPSHOT</version>
<version>4.1.0.Final-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
+1 -1
View File
@@ -21,7 +21,7 @@
<parent>
<artifactId>keycloak-fuse7-integration-pom</artifactId>
<groupId>org.keycloak</groupId>
<version>4.0.0.Beta3-SNAPSHOT</version>
<version>4.1.0.Final-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -70,6 +70,9 @@ public class PaxWebIntegrationService {
return httpContext;
}
public void setHttpContext(HttpContext httpContext) {
this.httpContext = httpContext;
}
public void start() {
ServiceTrackerCustomizer trackerCustomizer = new ServiceTrackerCustomizer() {
@@ -99,7 +102,9 @@ public class PaxWebIntegrationService {
protected WebContainer addingWebContainerCallback(ServiceReference webContainerServiceReference) {
WebContainer service = (WebContainer) bundleContext.getService(webContainerServiceReference);
httpContext = service.createDefaultHttpContext();
if (httpContext == null) {
httpContext = service.createDefaultHttpContext();
}
if (constraintMappings == null) {
throw new IllegalStateException("constraintMappings was null!");
+1 -1
View File
@@ -21,7 +21,7 @@
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>4.0.0.Beta3-SNAPSHOT</version>
<version>4.1.0.Final-SNAPSHOT</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
+1 -1
View File
@@ -21,7 +21,7 @@
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>4.0.0.Beta3-SNAPSHOT</version>
<version>4.1.0.Final-SNAPSHOT</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
+1 -1
View File
@@ -21,7 +21,7 @@
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>4.0.0.Beta3-SNAPSHOT</version>
<version>4.1.0.Final-SNAPSHOT</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
+1 -1
View File
@@ -21,7 +21,7 @@
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>4.0.0.Beta3-SNAPSHOT</version>
<version>4.1.0.Final-SNAPSHOT</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
+1 -1
View File
@@ -21,7 +21,7 @@
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>4.0.0.Beta3-SNAPSHOT</version>
<version>4.1.0.Final-SNAPSHOT</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
+1 -1
View File
@@ -21,7 +21,7 @@
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>4.0.0.Beta3-SNAPSHOT</version>
<version>4.1.0.Final-SNAPSHOT</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
+1 -1
View File
@@ -21,7 +21,7 @@
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>4.0.0.Beta3-SNAPSHOT</version>
<version>4.1.0.Final-SNAPSHOT</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
+1 -1
View File
@@ -21,7 +21,7 @@
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>4.0.0.Beta3-SNAPSHOT</version>
<version>4.1.0.Final-SNAPSHOT</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
+1 -1
View File
@@ -20,7 +20,7 @@
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>4.0.0.Beta3-SNAPSHOT</version>
<version>4.1.0.Final-SNAPSHOT</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
<name>Keycloak Jetty Integration</name>
+1 -1
View File
@@ -21,7 +21,7 @@
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>4.0.0.Beta3-SNAPSHOT</version>
<version>4.1.0.Final-SNAPSHOT</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
+8
View File
@@ -161,6 +161,14 @@ declare namespace Keycloak {
* the user's profile to a new preferred locale.
*/
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;
@@ -250,7 +250,16 @@
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
+ '?client_id=' + encodeURIComponent(kc.clientId)
+1 -1
View File
@@ -21,7 +21,7 @@
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>4.0.0.Beta3-SNAPSHOT</version>
<version>4.1.0.Final-SNAPSHOT</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
+7 -1
View File
@@ -21,7 +21,7 @@
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>4.0.0.Beta3-SNAPSHOT</version>
<version>4.1.0.Final-SNAPSHOT</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -99,6 +99,12 @@
<version>${cxf.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
@@ -25,6 +25,7 @@ import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.net.URI;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@@ -34,13 +35,35 @@ public class PathBasedKeycloakConfigResolver implements KeycloakConfigResolver {
@Override
public KeycloakDeployment resolve(OIDCHttpFacade.Request request) {
String path = request.getURI();
String[] urlTokens = path.split("/");
if (urlTokens.length < 4) {
throw new IllegalStateException("Not able to determine the web-context to load the correspondent keycloak.json file");
}
String uri = request.getURI();
String relativePath = request.getRelativePath();
String webContext = null;
if (relativePath == null || !uri.contains(relativePath)) {
String[] urlTokens = uri.split("/");
if (urlTokens.length < 4) {
throw new IllegalStateException("Not able to determine the web-context to load the correspondent keycloak.json file");
}
String webContext = urlTokens[3];
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);
if (null == deployment) {
@@ -54,7 +77,8 @@ public class PathBasedKeycloakConfigResolver implements KeycloakConfigResolver {
keycloakConfig = karafEtc;
}
String absolutePath = keycloakConfig + File.separator + webContext + "-keycloak.json";
String absolutePath = keycloakConfig + File.separator + webContext + ("".equals(webContext) ? "" : "-")
+ "keycloak.json";
InputStream is = null;
try {
is = new FileInputStream(absolutePath);
@@ -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) {
}
}
}
+33 -20
View File
@@ -20,7 +20,7 @@
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>4.0.0.Beta3-SNAPSHOT</version>
<version>4.1.0.Final-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<name>Keycloak OIDC Client Adapter Modules</name>
@@ -31,25 +31,38 @@
<packaging>pom</packaging>
<modules>
<module>adapter-core</module>
<module>as7-eap6</module>
<module>installed</module>
<module>fuse7</module>
<module>kcinit</module>
<module>jaxrs-oauth-client</module>
<module>jetty</module>
<module>js</module>
<module>osgi-adapter</module>
<module>servlet-filter</module>
<module>servlet-oauth-client</module>
<module>spring-boot</module>
<module>spring-boot2</module>
<module>spring-boot-adapter-core</module>
<module>spring-boot-container-bundle</module>
<module>spring-security</module>
<module>tomcat</module>
<module>undertow</module>
<module>wildfly</module>
<module>wildfly-elytron</module>
</modules>
<profiles>
<profile>
<id>nonServer</id>
<activation>
<property>
<name>!serverOnly</name>
</property>
</activation>
<modules>
<module>adapter-core</module>
<module>as7-eap6</module>
<module>installed</module>
<module>fuse7</module>
<module>kcinit</module>
<module>jaxrs-oauth-client</module>
<module>jetty</module>
<module>osgi-adapter</module>
<module>servlet-filter</module>
<module>servlet-oauth-client</module>
<module>spring-boot</module>
<module>spring-boot2</module>
<module>spring-boot-adapter-core</module>
<module>spring-boot-container-bundle</module>
<module>spring-security</module>
<module>tomcat</module>
<module>undertow</module>
<module>wildfly</module>
<module>wildfly-elytron</module>
</modules>
</profile>
</profiles>
</project>
+1 -1
View File
@@ -21,7 +21,7 @@
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>4.0.0.Beta3-SNAPSHOT</version>
<version>4.1.0.Final-SNAPSHOT</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
+1 -1
View File
@@ -21,7 +21,7 @@
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>4.0.0.Beta3-SNAPSHOT</version>
<version>4.1.0.Final-SNAPSHOT</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -21,7 +21,7 @@
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>4.0.0.Beta3-SNAPSHOT</version>
<version>4.1.0.Final-SNAPSHOT</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -4,7 +4,7 @@
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>4.0.0.Beta3-SNAPSHOT</version>
<version>4.1.0.Final-SNAPSHOT</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
<artifactId>spring-boot-container-bundle</artifactId>
+1 -1
View File
@@ -21,7 +21,7 @@
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>4.0.0.Beta3-SNAPSHOT</version>
<version>4.1.0.Final-SNAPSHOT</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
+1 -1
View File
@@ -21,7 +21,7 @@
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>4.0.0.Beta3-SNAPSHOT</version>
<version>4.1.0.Final-SNAPSHOT</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
+1 -1
View File
@@ -21,7 +21,7 @@
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>4.0.0.Beta3-SNAPSHOT</version>
<version>4.1.0.Final-SNAPSHOT</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
+1 -1
View File
@@ -20,7 +20,7 @@
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>4.0.0.Beta3-SNAPSHOT</version>
<version>4.1.0.Final-SNAPSHOT</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
<name>Keycloak Tomcat Integration</name>
+1 -1
View File
@@ -21,7 +21,7 @@
<parent>
<artifactId>keycloak-tomcat-integration-pom</artifactId>
<groupId>org.keycloak</groupId>
<version>4.0.0.Beta3-SNAPSHOT</version>
<version>4.1.0.Final-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
+1 -1
View File
@@ -21,7 +21,7 @@
<parent>
<artifactId>keycloak-tomcat-integration-pom</artifactId>
<groupId>org.keycloak</groupId>
<version>4.0.0.Beta3-SNAPSHOT</version>
<version>4.1.0.Final-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
+1 -1
View File
@@ -21,7 +21,7 @@
<parent>
<artifactId>keycloak-tomcat-integration-pom</artifactId>
<groupId>org.keycloak</groupId>
<version>4.0.0.Beta3-SNAPSHOT</version>
<version>4.1.0.Final-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
+1 -1
View File
@@ -21,7 +21,7 @@
<parent>
<artifactId>keycloak-tomcat-integration-pom</artifactId>
<groupId>org.keycloak</groupId>
<version>4.0.0.Beta3-SNAPSHOT</version>
<version>4.1.0.Final-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
+1 -1
View File
@@ -21,7 +21,7 @@
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>4.0.0.Beta3-SNAPSHOT</version>
<version>4.1.0.Final-SNAPSHOT</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
+1 -1
View File
@@ -22,7 +22,7 @@
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>4.0.0.Beta3-SNAPSHOT</version>
<version>4.1.0.Final-SNAPSHOT</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -46,7 +46,7 @@ import org.wildfly.security.http.Scope;
*/
class KeycloakHttpServerAuthenticationMechanism implements HttpServerAuthenticationMechanism {
static Logger LOGGER = Logger.getLogger(KeycloakHttpServerAuthenticationMechanismFactory.class);
static Logger LOGGER = Logger.getLogger(KeycloakHttpServerAuthenticationMechanism.class);
static final String NAME = "KEYCLOAK";
private final Map<String, ?> properties;
+1 -1
View File
@@ -20,7 +20,7 @@
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>4.0.0.Beta3-SNAPSHOT</version>
<version>4.1.0.Final-SNAPSHOT</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
<name>Keycloak WildFly Integration</name>
+1 -1
View File
@@ -21,7 +21,7 @@
<parent>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-parent</artifactId>
<version>4.0.0.Beta3-SNAPSHOT</version>
<version>4.1.0.Final-SNAPSHOT</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
@@ -21,7 +21,7 @@
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>4.0.0.Beta3-SNAPSHOT</version>
<version>4.1.0.Final-SNAPSHOT</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -17,21 +17,6 @@
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.acl.Group;
import java.util.Collection;
@@ -39,11 +24,33 @@ import java.util.Enumeration;
import java.util.Iterator;
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>
* @version $Revision: 1 $
*/
public class WildflyRequestAuthenticator extends ServletRequestAuthenticator {
public class WildflyRequestAuthenticator extends ServletRequestAuthenticator
{
protected static Logger log = Logger.getLogger(WildflyRequestAuthenticator.class);
public WildflyRequestAuthenticator(HttpFacade facade, KeycloakDeployment deployment, int sslRedirectPort,
@@ -87,6 +94,13 @@ public class WildflyRequestAuthenticator extends ServletRequestAuthenticator {
org.jboss.security.SecurityContext sc = SecurityContextAssociation.getSecurityContext();
Principal userPrincipal = getPrincipal(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;
}
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>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-parent</artifactId>
<version>4.0.0.Beta3-SNAPSHOT</version>
<version>4.1.0.Final-SNAPSHOT</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
+16 -3
View File
@@ -20,7 +20,7 @@
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>4.0.0.Beta3-SNAPSHOT</version>
<version>4.1.0.Final-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<name>Keycloak Adapters</name>
@@ -31,8 +31,21 @@
<packaging>pom</packaging>
<modules>
<module>spi</module>
<module>saml</module>
<module>oidc</module>
</modules>
<profiles>
<profile>
<id>nonServer</id>
<activation>
<property>
<name>!serverOnly</name>
</property>
</activation>
<modules>
<module>spi</module>
<module>saml</module>
</modules>
</profile>
</profiles>
</project>
+1 -1
View File
@@ -21,7 +21,7 @@
<parent>
<artifactId>keycloak-saml-eap-integration-pom</artifactId>
<groupId>org.keycloak</groupId>
<version>4.0.0.Beta3-SNAPSHOT</version>
<version>4.1.0.Final-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
+1 -1
View File
@@ -20,7 +20,7 @@
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>4.0.0.Beta3-SNAPSHOT</version>
<version>4.1.0.Final-SNAPSHOT</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
<name>Keycloak SAML EAP Integration</name>
+1 -1
View File
@@ -21,7 +21,7 @@
<parent>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-saml-eap-integration-pom</artifactId>
<version>4.0.0.Beta3-SNAPSHOT</version>
<version>4.1.0.Final-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
+1 -1
View File
@@ -21,7 +21,7 @@
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>4.0.0.Beta3-SNAPSHOT</version>
<version>4.1.0.Final-SNAPSHOT</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
+1 -1
View File
@@ -21,7 +21,7 @@
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>4.0.0.Beta3-SNAPSHOT</version>
<version>4.1.0.Final-SNAPSHOT</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
+1 -1
View File
@@ -21,7 +21,7 @@
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>4.0.0.Beta3-SNAPSHOT</version>
<version>4.1.0.Final-SNAPSHOT</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -66,6 +66,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.util.HashSet;
import java.util.Set;
import java.util.regex.Pattern;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
@@ -119,16 +120,27 @@ public abstract class AbstractSamlAuthenticator extends LoginAuthenticator {
tokenStore.logoutAccount();
}
protected void forwardToLogoutPage(Request request, HttpServletResponse response, SamlDeployment deployment) {
RequestDispatcher disp = request.getRequestDispatcher(deployment.getLogoutPage());
//make sure the login page is never cached
response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
response.setHeader("Pragma", "no-cache");
response.setHeader("Expires", "0");
private static final Pattern PROTOCOL_PATTERN = Pattern.compile("^[a-zA-Z][a-zA-Z0-9+.-]*:");
protected void forwardToLogoutPage(Request request, HttpServletResponse response, SamlDeployment deployment) {
final String location = deployment.getLogoutPage();
try {
disp.forward(request, response);
//make sure the login page is never cached
response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
response.setHeader("Pragma", "no-cache");
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);
disp.forward(request, response);
}
} catch (ServletException e) {
throw new RuntimeException(e);
} catch (IOException e) {
+1 -1
View File
@@ -21,7 +21,7 @@
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>4.0.0.Beta3-SNAPSHOT</version>
<version>4.1.0.Final-SNAPSHOT</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
+1 -1
View File
@@ -21,7 +21,7 @@
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>4.0.0.Beta3-SNAPSHOT</version>
<version>4.1.0.Final-SNAPSHOT</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
+1 -1
View File
@@ -21,7 +21,7 @@
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>4.0.0.Beta3-SNAPSHOT</version>
<version>4.1.0.Final-SNAPSHOT</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
+1 -1
View File
@@ -21,7 +21,7 @@
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>4.0.0.Beta3-SNAPSHOT</version>
<version>4.1.0.Final-SNAPSHOT</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
+1 -1
View File
@@ -21,7 +21,7 @@
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>4.0.0.Beta3-SNAPSHOT</version>
<version>4.1.0.Final-SNAPSHOT</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
+1 -1
View File
@@ -20,7 +20,7 @@
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>4.0.0.Beta3-SNAPSHOT</version>
<version>4.1.0.Final-SNAPSHOT</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
<name>Keycloak SAML Jetty Integration</name>
+1 -1
View File
@@ -20,7 +20,7 @@
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>4.0.0.Beta3-SNAPSHOT</version>
<version>4.1.0.Final-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<name>Keycloak SAML Client Adapter Modules</name>
+1 -1
View File
@@ -21,7 +21,7 @@
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>4.0.0.Beta3-SNAPSHOT</version>
<version>4.1.0.Final-SNAPSHOT</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
+1 -1
View File
@@ -20,7 +20,7 @@
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>4.0.0.Beta3-SNAPSHOT</version>
<version>4.1.0.Final-SNAPSHOT</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
<name>Keycloak SAML Tomcat Integration</name>
+1 -1
View File
@@ -21,7 +21,7 @@
<parent>
<artifactId>keycloak-saml-tomcat-integration-pom</artifactId>
<groupId>org.keycloak</groupId>
<version>4.0.0.Beta3-SNAPSHOT</version>
<version>4.1.0.Final-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -44,7 +44,7 @@ import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.*;
import java.util.Map;
import java.util.regex.Pattern;
/**
* Keycloak authentication valve
@@ -189,16 +189,27 @@ public abstract class AbstractSamlAuthenticatorValve extends FormAuthenticator i
protected abstract GenericPrincipalFactory createPrincipalFactory();
protected abstract boolean forwardToErrorPageInternal(Request request, HttpServletResponse response, Object loginConfig) throws IOException;
protected void forwardToLogoutPage(Request request, HttpServletResponse response,SamlDeployment deployment) {
RequestDispatcher disp = request.getRequestDispatcher(deployment.getLogoutPage());
//make sure the login page is never cached
response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
response.setHeader("Pragma", "no-cache");
response.setHeader("Expires", "0");
private static final Pattern PROTOCOL_PATTERN = Pattern.compile("^[a-zA-Z][a-zA-Z0-9+.-]*:");
protected void forwardToLogoutPage(Request request, HttpServletResponse response, SamlDeployment deployment) {
final String location = deployment.getLogoutPage();
try {
disp.forward(request.getRequest(), response);
//make sure the login page is never cached
response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
response.setHeader("Pragma", "no-cache");
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);
disp.forward(request.getRequest(), response);
}
} catch (ServletException e) {
throw new RuntimeException(e);
} catch (IOException e) {
+1 -1
View File
@@ -21,7 +21,7 @@
<parent>
<artifactId>keycloak-saml-tomcat-integration-pom</artifactId>
<groupId>org.keycloak</groupId>
<version>4.0.0.Beta3-SNAPSHOT</version>
<version>4.1.0.Final-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
+1 -1
View File
@@ -21,7 +21,7 @@
<parent>
<artifactId>keycloak-saml-tomcat-integration-pom</artifactId>
<groupId>org.keycloak</groupId>
<version>4.0.0.Beta3-SNAPSHOT</version>
<version>4.1.0.Final-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
+1 -1
View File
@@ -21,7 +21,7 @@
<parent>
<artifactId>keycloak-saml-tomcat-integration-pom</artifactId>
<groupId>org.keycloak</groupId>
<version>4.0.0.Beta3-SNAPSHOT</version>
<version>4.1.0.Final-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
+1 -1
View File
@@ -21,7 +21,7 @@
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>4.0.0.Beta3-SNAPSHOT</version>
<version>4.1.0.Final-SNAPSHOT</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -33,6 +33,9 @@ import org.keycloak.adapters.spi.AuthOutcome;
import org.keycloak.adapters.spi.HttpFacade;
import org.keycloak.adapters.undertow.UndertowHttpFacade;
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.
@@ -40,6 +43,9 @@ import org.keycloak.adapters.undertow.UndertowUserSessionManagement;
* @author Stan Silvert ssilvert@redhat.com (C) 2014 Red Hat Inc.
*/
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);
protected SamlDeploymentContext deploymentContext;
protected UndertowUserSessionManagement sessionManagement;
@@ -68,11 +74,22 @@ public abstract class AbstractSamlAuthMech implements AuthenticationMechanism {
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) {
// TODO - String concatenation to construct URLS is extremely error prone - switch to a URI which will better
// handle this.
String loc = exchange.getRequestScheme() + "://" + exchange.getHostAndPort() + location;
exchange.getResponseHeaders().put(Headers.LOCATION, loc);
if (location == null) {
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;
exchange.getResponseHeaders().put(Headers.LOCATION, loc);
}
}
protected void registerNotifications(final SecurityContext securityContext) {
@@ -142,7 +159,7 @@ public abstract class AbstractSamlAuthMech implements AuthenticationMechanism {
protected void redirectLogout(SamlDeployment deployment, HttpServerExchange exchange) {
String page = deployment.getLogoutPage();
sendRedirect(exchange, page);
exchange.setResponseCode(302);
exchange.setStatusCode(StatusCodes.FOUND);
exchange.endExchange();
}
@@ -113,7 +113,11 @@ public class ServletSamlAuthMech extends AbstractSamlAuthMech {
@Override
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
+1 -1
View File
@@ -21,7 +21,7 @@
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>4.0.0.Beta3-SNAPSHOT</version>
<version>4.1.0.Final-SNAPSHOT</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -19,6 +19,7 @@ package org.keycloak.adapters.saml.elytron;
import java.net.URI;
import java.util.Map;
import java.util.regex.Pattern;
import javax.security.auth.callback.CallbackHandler;
@@ -39,7 +40,7 @@ import org.wildfly.security.http.Scope;
*/
class KeycloakHttpServerAuthenticationMechanism implements HttpServerAuthenticationMechanism {
static Logger LOGGER = Logger.getLogger(KeycloakHttpServerAuthenticationMechanismFactory.class);
static Logger LOGGER = Logger.getLogger(KeycloakHttpServerAuthenticationMechanism.class);
static final String NAME = "KEYCLOAK-SAML";
private final Map<String, ?> properties;
@@ -142,14 +143,23 @@ class KeycloakHttpServerAuthenticationMechanism implements HttpServerAuthenticat
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) {
// TODO - String concatenation to construct URLS is extremely error prone - switch to a URI which will better
// handle this.
URI uri = exchange.getURI();
String path = uri.getPath();
String relativePath = exchange.getRequest().getRelativePath();
String contextPath = path.substring(0, path.indexOf(relativePath));
String loc = exchange.getURI().getScheme() + "://" + exchange.getURI().getHost() + ":" + exchange.getURI().getPort() + contextPath + location;
exchange.getResponse().setHeader("Location", loc);
if (location == null) {
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();
String path = uri.getPath();
String relativePath = exchange.getRequest().getRelativePath();
String contextPath = path.substring(0, path.indexOf(relativePath));
String loc = exchange.getURI().getScheme() + "://" + exchange.getURI().getHost() + ":" + exchange.getURI().getPort() + contextPath + location;
exchange.getResponse().setHeader("Location", loc);
}
}
}
+1 -1
View File
@@ -20,7 +20,7 @@
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>4.0.0.Beta3-SNAPSHOT</version>
<version>4.1.0.Final-SNAPSHOT</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
<name>Keycloak SAML Wildfly Integration</name>
@@ -21,7 +21,7 @@
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>4.0.0.Beta3-SNAPSHOT</version>
<version>4.1.0.Final-SNAPSHOT</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -21,7 +21,7 @@
<parent>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-parent</artifactId>
<version>4.0.0.Beta3-SNAPSHOT</version>
<version>4.1.0.Final-SNAPSHOT</version>
<relativePath>../../../../pom.xml</relativePath>
</parent>
+1 -1
View File
@@ -21,7 +21,7 @@
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>4.0.0.Beta3-SNAPSHOT</version>
<version>4.1.0.Final-SNAPSHOT</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
+1 -1
View File
@@ -21,7 +21,7 @@
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>4.0.0.Beta3-SNAPSHOT</version>
<version>4.1.0.Final-SNAPSHOT</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
+1 -1
View File
@@ -21,7 +21,7 @@
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>4.0.0.Beta3-SNAPSHOT</version>
<version>4.1.0.Final-SNAPSHOT</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
+1 -1
View File
@@ -20,7 +20,7 @@
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>4.0.0.Beta3-SNAPSHOT</version>
<version>4.1.0.Final-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<name>Keycloak Client Adapter SPI Modules</name>
+1 -1
View File
@@ -21,7 +21,7 @@
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>4.0.0.Beta3-SNAPSHOT</version>
<version>4.1.0.Final-SNAPSHOT</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
@@ -111,8 +111,7 @@ public class FilterSessionStore implements AdapterSessionStore {
if (body == null) return new MultivaluedHashMap<String, String>();
String contentType = getContentType();
contentType = contentType.toLowerCase();
if (contentType.startsWith("application/x-www-form-urlencoded")) {
if (contentType != null && contentType.toLowerCase().startsWith("application/x-www-form-urlencoded")) {
ByteArrayInputStream is = new ByteArrayInputStream(body);
try {
parameters = parseForm(is);
+1 -1
View File
@@ -21,7 +21,7 @@
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>4.0.0.Beta3-SNAPSHOT</version>
<version>4.1.0.Final-SNAPSHOT</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
+1 -1
View File
@@ -21,7 +21,7 @@
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>4.0.0.Beta3-SNAPSHOT</version>
<version>4.1.0.Final-SNAPSHOT</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
+1 -1
View File
@@ -7,7 +7,7 @@
<parent>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-authz-parent</artifactId>
<version>4.0.0.Beta3-SNAPSHOT</version>
<version>4.1.0.Final-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
@@ -102,6 +102,9 @@ public class ServerConfiguration {
@JsonProperty("permission_endpoint")
private String permissionEndpoint;
@JsonProperty("policy_endpoint")
private String policyEndpoint;
public String getIssuer() {
return issuer;
@@ -206,4 +209,8 @@ public class ServerConfiguration {
public String getPermissionEndpoint() {
return permissionEndpoint;
}
public String getPolicyEndpoint() {
return policyEndpoint;
}
}
@@ -0,0 +1,187 @@
/*
* 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.authorization.client.resource;
import java.util.List;
import java.util.concurrent.Callable;
import com.fasterxml.jackson.core.type.TypeReference;
import org.keycloak.authorization.client.representation.ServerConfiguration;
import org.keycloak.authorization.client.util.Http;
import org.keycloak.authorization.client.util.Throwables;
import org.keycloak.authorization.client.util.TokenCallable;
import org.keycloak.representations.idm.authorization.UmaPermissionRepresentation;
import org.keycloak.util.JsonSerialization;
/**
* An entry point for managing user-managed permissions for a particular resource
*
* @author <a href="mailto:psilva@redhat.com">Pedro Igor</a>
*/
public class PolicyResource {
private String resourceId;
private final Http http;
private final ServerConfiguration serverConfiguration;
private final TokenCallable pat;
public PolicyResource(String resourceId, Http http, ServerConfiguration serverConfiguration, TokenCallable pat) {
this.resourceId = resourceId;
this.http = http;
this.serverConfiguration = serverConfiguration;
this.pat = pat;
}
/**
* Creates a new user-managed permission as represented by the given {@code permission}.
*
* @param permission the permission to create
* @return if successful, the permission created
*/
public UmaPermissionRepresentation create(final UmaPermissionRepresentation permission) {
if (permission == null) {
throw new IllegalArgumentException("Permission must not be null");
}
Callable<UmaPermissionRepresentation> callable = new Callable<UmaPermissionRepresentation>() {
@Override
public UmaPermissionRepresentation call() throws Exception {
return http.<UmaPermissionRepresentation>post(serverConfiguration.getPolicyEndpoint() + "/" + resourceId)
.authorizationBearer(pat.call())
.json(JsonSerialization.writeValueAsBytes(permission))
.response().json(UmaPermissionRepresentation.class).execute();
}
};
try {
return callable.call();
} catch (Exception cause) {
return Throwables.retryAndWrapExceptionIfNecessary(callable, pat, "Error creating policy for resurce [" + resourceId + "]", cause);
}
}
/**
* Updates an existing user-managed permission
*
* @param permission the permission to update
*/
public void update(final UmaPermissionRepresentation permission) {
if (permission == null) {
throw new IllegalArgumentException("Permission must not be null");
}
if (permission.getId() == null) {
throw new IllegalArgumentException("Permission id must not be null");
}
Callable<Void> callable = new Callable<Void>() {
@Override
public Void call() throws Exception {
http.<Void>put(serverConfiguration.getPolicyEndpoint() + "/"+ permission.getId())
.authorizationBearer(pat.call())
.json(JsonSerialization.writeValueAsBytes(permission)).execute();
return null;
}
};
try {
callable.call();
} catch (Exception cause) {
Throwables.retryAndWrapExceptionIfNecessary(callable, pat, "Error updating policy for resurce [" + resourceId + "]", cause);
}
}
/**
* Deletes an existing user-managed permission
*
* @param id the permission id
*/
public void delete(final String id) {
Callable<Void> callable = new Callable<Void>() {
@Override
public Void call() {
http.<UmaPermissionRepresentation>delete(serverConfiguration.getPolicyEndpoint() + "/" + id)
.authorizationBearer(pat.call())
.response().execute();
return null;
}
};
try {
callable.call();
} catch (Exception cause) {
Throwables.retryAndWrapExceptionIfNecessary(callable, pat, "Error updating policy for resurce [" + resourceId + "]", cause);
}
}
/**
* Queries the server for permission matching the given parameters.
*
* @param id the permission id
* @param name the name of the permission
* @param scope the scope associated with the permission
* @param firstResult the position of the first resource to retrieve
* @param maxResult the maximum number of resources to retrieve
* @return the permissions matching the given parameters
*/
public List<UmaPermissionRepresentation> find(final String name,
final String scope,
final Integer firstResult,
final Integer maxResult) {
Callable<List<UmaPermissionRepresentation>> callable = new Callable<List<UmaPermissionRepresentation>>() {
@Override
public List<UmaPermissionRepresentation> call() {
return http.<List<UmaPermissionRepresentation>>get(serverConfiguration.getPolicyEndpoint())
.authorizationBearer(pat.call())
.param("name", name)
.param("resource", resourceId)
.param("scope", scope)
.param("first", firstResult == null ? null : firstResult.toString())
.param("max", maxResult == null ? null : maxResult.toString())
.response().json(new TypeReference<List<UmaPermissionRepresentation>>(){}).execute();
}
};
try {
return callable.call();
} catch (Exception cause) {
return Throwables.retryAndWrapExceptionIfNecessary(callable, pat, "Error querying policies for resource [" + resourceId + "]", cause);
}
}
/**
* Queries the server for a permission with the given {@code id}.
*
* @param id the permission id
* @return the permission with the given id
*/
public UmaPermissionRepresentation findById(final String id) {
if (id == null) {
throw new IllegalArgumentException("Permission id must not be null");
}
Callable<UmaPermissionRepresentation> callable = new Callable<UmaPermissionRepresentation>() {
@Override
public UmaPermissionRepresentation call() {
return http.<UmaPermissionRepresentation>get(serverConfiguration.getPolicyEndpoint() + "/" + id)
.authorizationBearer(pat.call())
.response().json(UmaPermissionRepresentation.class).execute();
}
};
try {
return callable.call();
} catch (Exception cause) {
return Throwables.retryAndWrapExceptionIfNecessary(callable, pat, "Error creating policy for resurce [" + resourceId + "]", cause);
}
}
}
@@ -64,6 +64,10 @@ public class ProtectionResource {
return new PermissionResource(http, serverConfiguration, pat);
}
public PolicyResource policy(String resourceId) {
return new PolicyResource(resourceId, http, serverConfiguration, pat);
}
/**
* Introspects the given <code>rpt</code> using the token introspection endpoint.
*
@@ -83,6 +83,7 @@ public class HttpMethodAuthenticator<R> {
method.param("rpt", request.getRpt());
method.param("scope", request.getScope());
method.param("audience", request.getAudience());
method.param("subject_token", request.getSubjectToken());
if (permissions != null) {
for (ResourcePermission permission : permissions.getResources()) {
+1 -1
View File
@@ -25,7 +25,7 @@
<parent>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-authz-provider-parent</artifactId>
<version>4.0.0.Beta3-SNAPSHOT</version>
<version>4.1.0.Final-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
@@ -73,7 +73,7 @@ public class AggregatePolicyProviderFactory implements PolicyProviderFactory<Agg
}
@Override
public AggregatePolicyRepresentation toRepresentation(Policy policy) {
public AggregatePolicyRepresentation toRepresentation(Policy policy, AuthorizationProvider authorization) {
return new AggregatePolicyRepresentation();
}
@@ -1,6 +1,6 @@
package org.keycloak.authorization.policy.provider.client;
import java.util.function.Function;
import java.util.function.BiFunction;
import org.keycloak.authorization.AuthorizationProvider;
import org.keycloak.authorization.model.Policy;
@@ -13,15 +13,15 @@ import org.keycloak.representations.idm.authorization.ClientPolicyRepresentation
public class ClientPolicyProvider implements PolicyProvider {
private final Function<Policy, ClientPolicyRepresentation> representationFunction;
private final BiFunction<Policy, AuthorizationProvider, ClientPolicyRepresentation> representationFunction;
public ClientPolicyProvider(Function<Policy, ClientPolicyRepresentation> representationFunction) {
public ClientPolicyProvider(BiFunction<Policy, AuthorizationProvider, ClientPolicyRepresentation> representationFunction) {
this.representationFunction = representationFunction;
}
@Override
public void evaluate(Evaluation evaluation) {
ClientPolicyRepresentation representation = representationFunction.apply(evaluation.getPolicy());
ClientPolicyRepresentation representation = representationFunction.apply(evaluation.getPolicy(), evaluation.getAuthorizationProvider());
AuthorizationProvider authorizationProvider = evaluation.getAuthorizationProvider();
RealmModel realm = authorizationProvider.getKeycloakSession().getContext().getRealm();
EvaluationContext context = evaluation.getContext();
@@ -30,7 +30,7 @@ import org.keycloak.util.JsonSerialization;
public class ClientPolicyProviderFactory implements PolicyProviderFactory<ClientPolicyRepresentation> {
private ClientPolicyProvider provider = new ClientPolicyProvider(policy -> toRepresentation(policy));
private ClientPolicyProvider provider = new ClientPolicyProvider(this::toRepresentation);
@Override
public String getName() {
@@ -48,7 +48,7 @@ public class ClientPolicyProviderFactory implements PolicyProviderFactory<Client
}
@Override
public ClientPolicyRepresentation toRepresentation(Policy policy) {
public ClientPolicyRepresentation toRepresentation(Policy policy, AuthorizationProvider authorization) {
ClientPolicyRepresentation representation = new ClientPolicyRepresentation();
representation.setClients(new HashSet<>(Arrays.asList(getClients(policy))));
return representation;
@@ -75,12 +75,12 @@ public class ClientPolicyProviderFactory implements PolicyProviderFactory<Client
}
@Override
public void onExport(Policy policy, PolicyRepresentation representation, AuthorizationProvider authorizationProvider) {
ClientPolicyRepresentation userRep = toRepresentation(policy);
public void onExport(Policy policy, PolicyRepresentation representation, AuthorizationProvider authorization) {
ClientPolicyRepresentation userRep = toRepresentation(policy, authorization);
Map<String, String> config = new HashMap<>();
try {
RealmModel realm = authorizationProvider.getRealm();
RealmModel realm = authorization.getRealm();
config.put("clients", JsonSerialization.writeValueAsString(userRep.getClients().stream().map(id -> realm.getClientById(id).getClientId()).collect(Collectors.toList())));
} catch (IOException cause) {
throw new RuntimeException("Failed to export user policy [" + policy.getName() + "]", cause);
Loaded 100 of 1093 files, more files were not shown because too many files have changed in this diff. Show more