keycloak-aplcache
Changes
adapters/oidc/osgi-adapter/pom.xml 15(+15 -0)
adapters/oidc/osgi-adapter/src/main/java/org/keycloak/adapters/osgi/PathBasedKeycloakConfigResolver.java 71(+71 -0)
examples/fuse/external-config/pom.xml 129(+129 -0)
examples/fuse/external-config/README.md 22(+22 -0)
examples/fuse/pom.xml 1(+1 -0)
examples/fuse/testrealm.json 12(+12 -0)
Details
adapters/oidc/osgi-adapter/pom.xml 15(+15 -0)
diff --git a/adapters/oidc/osgi-adapter/pom.xml b/adapters/oidc/osgi-adapter/pom.xml
index 2c8607e..6a24b29 100755
--- a/adapters/oidc/osgi-adapter/pom.xml
+++ b/adapters/oidc/osgi-adapter/pom.xml
@@ -48,6 +48,21 @@
<dependencies>
<dependency>
+ <groupId>org.keycloak</groupId>
+ <artifactId>keycloak-core</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.keycloak</groupId>
+ <artifactId>keycloak-adapter-core</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.keycloak</groupId>
+ <artifactId>keycloak-adapter-spi</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
<groupId>org.jboss.logging</groupId>
<artifactId>jboss-logging</artifactId>
<scope>provided</scope>
diff --git a/adapters/oidc/osgi-adapter/src/main/java/org/keycloak/adapters/osgi/PathBasedKeycloakConfigResolver.java b/adapters/oidc/osgi-adapter/src/main/java/org/keycloak/adapters/osgi/PathBasedKeycloakConfigResolver.java
new file mode 100644
index 0000000..93d5cb6
--- /dev/null
+++ b/adapters/oidc/osgi-adapter/src/main/java/org/keycloak/adapters/osgi/PathBasedKeycloakConfigResolver.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.keycloak.adapters.osgi;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.InputStream;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.keycloak.adapters.KeycloakConfigResolver;
+import org.keycloak.adapters.KeycloakDeployment;
+import org.keycloak.adapters.KeycloakDeploymentBuilder;
+import org.keycloak.adapters.OIDCHttpFacade;
+
+public class PathBasedKeycloakConfigResolver implements KeycloakConfigResolver {
+
+ private final Map<String, KeycloakDeployment> cache = new ConcurrentHashMap<String, KeycloakDeployment>();
+
+ @Override
+ public KeycloakDeployment resolve(OIDCHttpFacade.Request request) {
+ String path = request.getURI();
+ String[] urlTokens = path.split("/");
+ if (urlTokens.length < 4) {
+ throw new IllegalStateException("Not able to determine the web-context to load the correspondent keycloak.json file");
+ }
+
+ String webContext = urlTokens[3];
+
+ KeycloakDeployment deployment = cache.get(webContext);
+ if (null == deployment) {
+ // not found on the simple cache, try to load it from the file system
+ String keycloakConfig = (String) System.getProperties().get("keycloak.config");
+ if(keycloakConfig == null || "".equals(keycloakConfig.trim())){
+ String karafEtc = (String) System.getProperties().get("karaf.etc");
+ if(karafEtc == null || "".equals(karafEtc.trim())){
+ throw new IllegalStateException("Neither \"keycloak.config\" nor \"karaf.etc\" java properties are set. Please set one of them.");
+ }
+ keycloakConfig = karafEtc;
+ }
+
+ String absolutePath = keycloakConfig + File.separator + webContext + "-keycloak.json";
+ InputStream is = null;
+ try {
+ is = new FileInputStream(absolutePath);
+ } catch (FileNotFoundException e){
+ throw new IllegalStateException("Not able to find the file " + absolutePath);
+ }
+ deployment = KeycloakDeploymentBuilder.build(is);
+ cache.put(webContext, deployment);
+ }
+
+ return deployment;
+ }
+
+}
diff --git a/examples/fuse/external-config/external-config-keycloak.json b/examples/fuse/external-config/external-config-keycloak.json
new file mode 100644
index 0000000..920e99a
--- /dev/null
+++ b/examples/fuse/external-config/external-config-keycloak.json
@@ -0,0 +1,10 @@
+{
+ "realm": "demo",
+ "resource": "external-config",
+ "realm-public-key": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
+ "auth-server-url": "http://localhost:8080/auth",
+ "ssl-required" : "external",
+ "credentials": {
+ "secret": "password"
+ }
+}
examples/fuse/external-config/pom.xml 129(+129 -0)
diff --git a/examples/fuse/external-config/pom.xml b/examples/fuse/external-config/pom.xml
new file mode 100755
index 0000000..33ac617
--- /dev/null
+++ b/examples/fuse/external-config/pom.xml
@@ -0,0 +1,129 @@
+<!--
+ ~ Copyright 2016 Red Hat, Inc. and/or its affiliates
+ ~ and other contributors as indicated by the @author tags.
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <artifactId>keycloak-examples-parent</artifactId>
+ <groupId>org.keycloak</groupId>
+ <version>2.0.0.CR1-SNAPSHOT</version>
+ </parent>
+
+ <name>Keycloak Examples - External Config</name>
+ <artifactId>external-config</artifactId>
+ <packaging>war</packaging>
+ <groupId>org.keycloak.example.demo</groupId>
+ <description>
+ Keycloak External Config Example
+ </description>
+
+ <properties>
+ <keycloak.osgi.export>
+ </keycloak.osgi.export>
+ <keycloak.osgi.import>
+ org.apache.http.*;version=${apache.httpcomponents.version},
+ javax.servlet.*;version="[2.5,4)",
+ org.keycloak.adapters.jetty;version="${project.version}",
+ org.keycloak.adapters;version="${project.version}",
+ org.keycloak.constants;version="${project.version}",
+ org.keycloak.adapters.osgi;version="${project.version}",
+ org.keycloak.util;version="${project.version}",
+ org.keycloak.*;version="${project.version}",
+ *;resolution:=optional
+ </keycloak.osgi.import>
+ <keycloak.osgi.private>
+ org.keycloak.example.*
+ </keycloak.osgi.private>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.jboss.spec.javax.servlet</groupId>
+ <artifactId>jboss-servlet-api_3.0_spec</artifactId>
+ <scope>provided</scope>
+ </dependency>
+
+ <!-- Contains KeycloakDeployment and KeycloakConfigResolver -->
+ <dependency>
+ <groupId>org.keycloak</groupId>
+ <artifactId>keycloak-adapter-core</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.keycloak</groupId>
+ <artifactId>keycloak-adapter-spi</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.keycloak</groupId>
+ <artifactId>keycloak-adapter-spi</artifactId>
+ <scope>provided</scope>
+ </dependency>
+
+ <!-- Contains KeycloakPrincipal -->
+ <dependency>
+ <groupId>org.keycloak</groupId>
+ <artifactId>keycloak-core</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ </dependencies>
+ <build>
+ <finalName>external-config</finalName>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-war-plugin</artifactId>
+ <configuration>
+ <archive>
+ <manifestFile>${basedir}/target/classes/META-INF/MANIFEST.MF</manifestFile>
+ </archive>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <extensions>true</extensions>
+ <executions>
+ <execution>
+ <id>bundle-manifest</id>
+ <phase>process-classes</phase>
+ <goals>
+ <goal>manifest</goal>
+ </goals>
+ </execution>
+ </executions>
+ <configuration>
+ <supportedProjectTypes>
+ <supportedProjectType>war</supportedProjectType>
+ </supportedProjectTypes>
+ <instructions>
+ <Webapp-Context>external-config</Webapp-Context>
+ <Web-ContextPath>external-config</Web-ContextPath>
+ <Embed-Directory>WEB-INF/lib</Embed-Directory>
+ <Bundle-Name>${project.name}</Bundle-Name>
+ <Bundle-SymbolicName>${project.groupId}.${project.artifactId}</Bundle-SymbolicName>
+ <Import-Package>${keycloak.osgi.import}</Import-Package>
+ <Private-Package>${keycloak.osgi.private}</Private-Package>
+ <Export-Package>${keycloak.osgi.export}</Export-Package>
+ </instructions>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+</project>
+
examples/fuse/external-config/README.md 22(+22 -0)
diff --git a/examples/fuse/external-config/README.md b/examples/fuse/external-config/README.md
new file mode 100644
index 0000000..91ad73a
--- /dev/null
+++ b/examples/fuse/external-config/README.md
@@ -0,0 +1,22 @@
+Keycloak Example - Externalized keycloak.json
+=======================================
+
+The following example was tested on JBoss Fuse 6.3 and shows a way to package an OSGi compatible .war file that does not
+ include keycloak.json file in the .war archive but that automatically loads it based on a naming convention.
+
+To enable the functionality you need to add this section to your `web.xml`:
+
+```
+ <context-param>
+ <param-name>keycloak.config.resolver</param-name>
+ <param-value>org.keycloak.adapters.osgi.PathBasedKeycloakConfigResolver</param-value>
+ </context-param>
+```
+
+That component will use `keycloak.config` or `karaf.etc` java properties to look for a base folder to look for the configuration.
+
+Inside one of those folders it will look for a file called `<your_web_context>-keycloak.json`.
+
+For this example you need to copy the file `external-config-keycloak.json` to your JBoss Fuse `etc/` folder.
+
+Once you have done that, you can try to access the endpoint: http://localhost:8181/external-config/index.html
\ No newline at end of file
diff --git a/examples/fuse/external-config/src/main/java/org/keycloak/examples/ProtectedServlet.java b/examples/fuse/external-config/src/main/java/org/keycloak/examples/ProtectedServlet.java
new file mode 100755
index 0000000..ec30ccc
--- /dev/null
+++ b/examples/fuse/external-config/src/main/java/org/keycloak/examples/ProtectedServlet.java
@@ -0,0 +1,58 @@
+package org.keycloak.examples;/*
+ * 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.
+ */
+
+import org.keycloak.KeycloakPrincipal;
+
+import javax.servlet.ServletException;
+import javax.servlet.annotation.WebServlet;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.io.PrintWriter;
+
+
+@WebServlet(urlPatterns = "/servlet")
+public class ProtectedServlet extends HttpServlet {
+
+ @Override
+ protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
+ String realm = req.getPathInfo().split("/")[1];
+ if (realm.contains("?")) {
+ realm = realm.split("\\?")[0];
+ }
+
+ if (req.getPathInfo().contains("logout")) {
+ req.logout();
+ resp.sendRedirect(req.getContextPath() + "/" + realm);
+ return;
+ }
+
+ KeycloakPrincipal principal = (KeycloakPrincipal) req.getUserPrincipal();
+
+ resp.setContentType("text/html");
+ PrintWriter writer = resp.getWriter();
+
+ writer.write("Realm: ");
+ writer.write(principal.getKeycloakSecurityContext().getRealm());
+
+ writer.write("<br/>User: ");
+ writer.write(principal.getKeycloakSecurityContext().getIdToken().getPreferredUsername());
+
+ writer.write(String.format("<br/><a href=\"/multitenant/%s/logout\">Logout</a>", realm));
+ }
+ }
diff --git a/examples/fuse/external-config/src/main/webapp/index.html b/examples/fuse/external-config/src/main/webapp/index.html
new file mode 100755
index 0000000..50ac1b6
--- /dev/null
+++ b/examples/fuse/external-config/src/main/webapp/index.html
@@ -0,0 +1,31 @@
+<!--
+ ~ 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.
+ -->
+
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+ "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+ <head>
+ <title>External Config Example Karaf/Fuse</title>
+ </head>
+ <body bgcolor="#E3F6CE">
+ <h1>External configuration worked.</h1>
+
+ <p><a href="http://localhost:8080/auth/realms/demo/protocol/openid-connect/logout">Log out</a></p>
+
+
+ </body>
+</html>
\ No newline at end of file
diff --git a/examples/fuse/external-config/src/main/webapp/WEB-INF/jetty-web.xml b/examples/fuse/external-config/src/main/webapp/WEB-INF/jetty-web.xml
new file mode 100644
index 0000000..6b42d3f
--- /dev/null
+++ b/examples/fuse/external-config/src/main/webapp/WEB-INF/jetty-web.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0"?>
+<!--
+ ~ Copyright 2016 Red Hat, Inc. and/or its affiliates
+ ~ and other contributors as indicated by the @author tags.
+ ~
+ ~ Licensed under the Apache License, Version 2.0 (the "License");
+ ~ you may not use this file except in compliance with the License.
+ ~ You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+ -->
+
+<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd">
+<Configure class="org.eclipse.jetty.webapp.WebAppContext">
+ <Get name="securityHandler">
+ <Set name="authenticator">
+ <New class="org.keycloak.adapters.jetty.KeycloakJettyAuthenticator">
+ </New>
+ </Set>
+ </Get>
+</Configure>
\ No newline at end of file
diff --git a/examples/fuse/external-config/src/main/webapp/WEB-INF/web.xml b/examples/fuse/external-config/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..84aaa74
--- /dev/null
+++ b/examples/fuse/external-config/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,55 @@
+<!--
+ ~ 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.
+ -->
+
+<web-app xmlns="http://java.sun.com/xml/ns/javaee"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
+ version="3.0">
+ <module-name>External Config Example</module-name>
+
+ <context-param>
+ <param-name>keycloak.config.resolver</param-name>
+ <param-value>org.keycloak.adapters.osgi.PathBasedKeycloakConfigResolver</param-value>
+ </context-param>
+
+ <welcome-file-list>
+ <welcome-file>index.html</welcome-file>
+ </welcome-file-list>
+
+
+ <security-constraint>
+ <web-resource-collection>
+ <web-resource-name>REST endpoints</web-resource-name>
+ <url-pattern>/*</url-pattern>
+ </web-resource-collection>
+ <auth-constraint>
+ <role-name>user</role-name>
+ </auth-constraint>
+ </security-constraint>
+
+ <login-config>
+ <auth-method>BASIC</auth-method>
+ <realm-name>does-not-matter</realm-name>
+ </login-config>
+
+ <security-role>
+ <role-name>admin</role-name>
+ </security-role>
+ <security-role>
+ <role-name>user</role-name>
+ </security-role>
+</web-app>
\ No newline at end of file
examples/fuse/pom.xml 1(+1 -0)
diff --git a/examples/fuse/pom.xml b/examples/fuse/pom.xml
index 115effb..8920986 100755
--- a/examples/fuse/pom.xml
+++ b/examples/fuse/pom.xml
@@ -39,6 +39,7 @@
<module>cxf-jaxws</module>
<module>camel</module>
<module>features</module>
+ <module>external-config</module>
</modules>
</project>
examples/fuse/testrealm.json 12(+12 -0)
diff --git a/examples/fuse/testrealm.json b/examples/fuse/testrealm.json
index 88afec8..a27543a 100644
--- a/examples/fuse/testrealm.json
+++ b/examples/fuse/testrealm.json
@@ -186,7 +186,19 @@
"standardFlowEnabled": false,
"directAccessGrantsEnabled": true,
"secret": "password"
+ },
+ {
+ "clientId": "external-config",
+ "enabled": true,
+ "adminUrl": "http://localhost:8181/external-config",
+ "baseUrl": "http://localhost:8181/external-config",
+ "redirectUris": [
+ "http://localhost:8181/external-config",
+ "http://localhost:8181/external-config/*"
+ ],
+ "secret": "password"
}
+
],
"scopeMappings": [
{