Merge pull request #918 from mposolda/master
Fuse/Karaf adapter, demo example and documentation
This commit is contained in:
commit
ba0dc06252
77 changed files with 2857 additions and 117 deletions
41
core/pom.xml
41
core/pom.xml
|
@ -11,11 +11,19 @@
|
|||
|
||||
<artifactId>keycloak-core</artifactId>
|
||||
<name>Keycloak Core</name>
|
||||
<packaging>jar</packaging>
|
||||
<description/>
|
||||
|
||||
<properties>
|
||||
<timestamp>${maven.build.timestamp}</timestamp>
|
||||
<maven.build.timestamp.format>yyyy-MM-dd HH:mm</maven.build.timestamp.format>
|
||||
<keycloak.osgi.export>
|
||||
org.keycloak.*
|
||||
</keycloak.osgi.export>
|
||||
<keycloak.osgi.import>
|
||||
net.iharder;version=${base64.version},
|
||||
*;resolution:=optional
|
||||
</keycloak.osgi.import>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
|
@ -60,6 +68,39 @@
|
|||
<target>${maven.compiler.target}</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<!-- Adding OSGI metadata to the JAR without changing the packaging type. -->
|
||||
<plugin>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<configuration>
|
||||
<archive>
|
||||
<manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile>
|
||||
</archive>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.felix</groupId>
|
||||
<artifactId>maven-bundle-plugin</artifactId>
|
||||
<extensions>true</extensions>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>bundle-manifest</id>
|
||||
<phase>process-classes</phase>
|
||||
<goals>
|
||||
<goal>manifest</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<instructions>
|
||||
<Bundle-ClassPath>.</Bundle-ClassPath>
|
||||
<Bundle-Name>${project.name}</Bundle-Name>
|
||||
<Bundle-SymbolicName>${project.groupId}.${project.artifactId}</Bundle-SymbolicName>
|
||||
<Import-Package>${keycloak.osgi.import}</Import-Package>
|
||||
<Export-Package>${keycloak.osgi.export}</Export-Package>
|
||||
</instructions>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
|
|
|
@ -93,6 +93,12 @@
|
|||
<exclude name="**/README.md"/>
|
||||
</fileset>
|
||||
</copy>
|
||||
<copy todir="target/examples/fuse" overwrite="true">
|
||||
<fileset dir="../../examples/fuse">
|
||||
<exclude name="**/target/**"/>
|
||||
<exclude name="**/*.iml"/>
|
||||
</fileset>
|
||||
</copy>
|
||||
<copy file="../../examples/README.md" tofile="target/examples/README.md"/>
|
||||
<move file="target/examples/unconfigured-demo/README.md.unconfigured" tofile="target/examples/unconfigured-demo/README.md"/>
|
||||
<move file="target/examples/unconfigured-demo/customer-app/src/main/webapp/WEB-INF/web.xml.unconfigured" tofile="target/examples/unconfigured-demo/customer-app/src/main/webapp/WEB-INF/web.xml"/>
|
||||
|
|
|
@ -1,15 +1,53 @@
|
|||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<features xmlns="http://karaf.apache.org/xmlns/features/v1.0.0" name="keycloak-${project.version}">
|
||||
|
||||
<feature name="keycloak-core-adapter" version="${project.version}" resolver="(obr)">
|
||||
<details>The keycloak core adapter stuff</details>
|
||||
<bundle>mvn:org.keycloak/keycloak-osgi-core-adapter/${project.version}</bundle>
|
||||
<feature name="keycloak-adapter-core" version="${project.version}" resolver="(obr)">
|
||||
<details>The keycloak adapter core stuff</details>
|
||||
<bundle dependency="true">mvn:org.keycloak/keycloak-osgi-thirdparty/${project.version}</bundle>
|
||||
<bundle dependency="true">mvn:org.bouncycastle/bcprov-jdk16/${bouncycastle.version}</bundle>
|
||||
<bundle dependency="true">mvn:org.codehaus.jackson/jackson-core-asl/${jackson.version}</bundle>
|
||||
<bundle dependency="true">mvn:org.codehaus.jackson/jackson-mapper-asl/${jackson.version}</bundle>
|
||||
<bundle dependency="true">mvn:org.codehaus.jackson/jackson-xc/${jackson.version}</bundle>
|
||||
<bundle dependency="true">mvn:org.jboss.logging/jboss-logging/${jboss.logging.version}</bundle>
|
||||
<bundle>mvn:org.keycloak/keycloak-core/${project.version}</bundle>
|
||||
<bundle>mvn:org.keycloak/keycloak-adapter-core/${project.version}</bundle>
|
||||
</feature>
|
||||
|
||||
<feature name="keycloak-osgi-adapter" version="${project.version}" resolver="(obr)">
|
||||
<details>The keycloak adapter core stuff</details>
|
||||
<feature>keycloak-adapter-core</feature>
|
||||
<feature version="[2.3,4)">http-whiteboard</feature>
|
||||
<bundle>mvn:org.keycloak/keycloak-osgi-adapter/${project.version}</bundle>
|
||||
</feature>
|
||||
|
||||
<feature name="keycloak-jetty8-adapter" version="${project.version}" resolver="(obr)">
|
||||
<details>The keycloak Jetty8 adapter</details>
|
||||
<feature>keycloak-adapter-core</feature>
|
||||
<feature version="[8.1,9)">jetty</feature>
|
||||
<bundle>mvn:org.keycloak/keycloak-jetty-core/${project.version}</bundle>
|
||||
<bundle>mvn:org.keycloak/keycloak-jetty81-adapter/${project.version}</bundle>
|
||||
</feature>
|
||||
|
||||
<feature name="keycloak-jaas" version="${project.version}" resolver="(obr)">
|
||||
<details>The keycloak JAAS configuration</details>
|
||||
<feature>keycloak-core-adapter</feature>
|
||||
<feature>keycloak-adapter-core</feature>
|
||||
<bundle>mvn:org.keycloak/keycloak-osgi-jaas/${project.version}</bundle>
|
||||
</feature>
|
||||
|
||||
<feature name="keycloak" version="${project.version}" resolver="(obr)">
|
||||
<details>The keycloak adapter core stuff</details>
|
||||
<feature>keycloak-osgi-adapter</feature>
|
||||
<feature>keycloak-jetty8-adapter</feature>
|
||||
<feature>keycloak-jaas</feature>
|
||||
</feature>
|
||||
|
||||
<!-- This is just simplification to upgrade paxweb to 3.1.2 in JBoss Fuse 6.1 or Karaf 2.3.X environment -->
|
||||
<feature name="keycloak-pax-web-upgrade" version="${project.version}" resolver="(obr)">
|
||||
<details>This is just simplification to upgrade paxweb to 3.1.2 in JBoss Fuse 6.1 or Karaf 2.3.X environment</details>
|
||||
<bundle>mvn:org.ow2.asm/asm-all/5.0</bundle>
|
||||
<bundle>mvn:org.apache.xbean/xbean-bundleutils/3.18</bundle>
|
||||
<bundle>mvn:org.apache.xbean/xbean-reflect/3.18</bundle>
|
||||
<bundle>mvn:org.apache.xbean/xbean-finder/3.18</bundle>
|
||||
</feature>
|
||||
|
||||
</features>
|
|
@ -7,7 +7,7 @@
|
|||
<version>1.2.0.Beta1-SNAPSHOT</version>
|
||||
<relativePath>../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<name>Keycloak OSGI JAAS</name>
|
||||
<name>Keycloak OSGI JAAS Realm Configuration</name>
|
||||
<description/>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
|
@ -27,7 +27,7 @@
|
|||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-osgi-core-adapter</artifactId>
|
||||
<artifactId>keycloak-adapter-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
@ -53,7 +53,7 @@
|
|||
<Embed-Dependency>*;scope=compile|runtime</Embed-Dependency>
|
||||
<Embed-Transitive>false</Embed-Transitive>
|
||||
<Bundle-ClassPath>.</Bundle-ClassPath> -->
|
||||
<Bundle-Name>${project.description}</Bundle-Name>
|
||||
<Bundle-Name>${project.name}</Bundle-Name>
|
||||
<Bundle-SymbolicName>${project.groupId}.${project.artifactId}</Bundle-SymbolicName>
|
||||
<Import-Package>${keycloak.osgi.import}</Import-Package>
|
||||
<Export-Package>${keycloak.osgi.export}</Export-Package>
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
<modules>
|
||||
<module>features</module>
|
||||
<module>jaas</module>
|
||||
<module>core-adapter</module>
|
||||
<module>thirdparty</module>
|
||||
</modules>
|
||||
|
||||
</project>
|
53
distribution/osgi/core-adapter/pom.xml → distribution/osgi/thirdparty/pom.xml
vendored
Executable file → Normal file
53
distribution/osgi/core-adapter/pom.xml → distribution/osgi/thirdparty/pom.xml
vendored
Executable file → Normal file
|
@ -7,17 +7,18 @@
|
|||
<version>1.2.0.Beta1-SNAPSHOT</version>
|
||||
<relativePath>../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<name>Keycloak OSGI Core Adapter Integration</name>
|
||||
<description/>
|
||||
|
||||
<name>Keycloak OSGI Thirdparty</name>
|
||||
<description>Keycloak OSGI bundling for 3rd party libs without OSGI headers in manifest</description>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>keycloak-osgi-core-adapter</artifactId>
|
||||
<artifactId>keycloak-osgi-thirdparty</artifactId>
|
||||
<packaging>bundle</packaging>
|
||||
|
||||
<properties>
|
||||
<keycloak.osgi.export>
|
||||
org.keycloak.adapters.jaas,
|
||||
org.keycloak.adapters
|
||||
net.iharder;version="${base64.version}",
|
||||
org.apache.http.*;version=${keycloak.apache.httpcomponents.version}
|
||||
</keycloak.osgi.export>
|
||||
<keycloak.osgi.import>
|
||||
*;resolution:=optional
|
||||
|
@ -26,45 +27,19 @@
|
|||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<groupId>net.iharder</groupId>
|
||||
<artifactId>base64</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-adapter-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.jboss.logging</groupId>
|
||||
<artifactId>jboss-logging</artifactId>
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
<artifactId>httpcore</artifactId>
|
||||
<version>${keycloak.apache.httpcomponents.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
<artifactId>httpclient</artifactId>
|
||||
<version>${keycloak.apache.httpcomponents.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.iharder</groupId>
|
||||
<artifactId>base64</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.bouncycastle</groupId>
|
||||
<artifactId>bcprov-jdk16</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.codehaus.jackson</groupId>
|
||||
<artifactId>jackson-core-asl</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.codehaus.jackson</groupId>
|
||||
<artifactId>jackson-mapper-asl</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.codehaus.jackson</groupId>
|
||||
<artifactId>jackson-xc</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
@ -84,14 +59,14 @@
|
|||
</executions>
|
||||
<configuration>
|
||||
<instructions>
|
||||
<Embed-Dependency>*;scope=compile|runtime;artifactId=!keycloak-adapter-core</Embed-Dependency>
|
||||
<Embed-Dependency>*;scope=compile|runtime;artifactId=!httpclient|httpcore|base64</Embed-Dependency>
|
||||
<Embed-Transitive>true</Embed-Transitive>
|
||||
<Bundle-ClassPath>.</Bundle-ClassPath>
|
||||
<Bundle-Name>${project.description}</Bundle-Name>
|
||||
<Bundle-Name>${project.name}</Bundle-Name>
|
||||
<Bundle-SymbolicName>${project.groupId}.${project.artifactId}</Bundle-SymbolicName>
|
||||
<Import-Package>${keycloak.osgi.import}</Import-Package>
|
||||
<Export-Package>${keycloak.osgi.export}</Export-Package>
|
||||
<Implementation-Title>keycloak</Implementation-Title>
|
||||
<Implementation-Title>${project.name}</Implementation-Title>
|
||||
<Implementation-Version>${project.version}</Implementation-Version>
|
||||
</instructions>
|
||||
</configuration>
|
|
@ -14,9 +14,11 @@
|
|||
<!ENTITY TomcatAdapter SYSTEM "modules/tomcat-adapter.xml">
|
||||
<!ENTITY Jetty9Adapter SYSTEM "modules/jetty9-adapter.xml">
|
||||
<!ENTITY Jetty8Adapter SYSTEM "modules/jetty8-adapter.xml">
|
||||
<!ENTITY FuseAdapter SYSTEM "modules/fuse-adapter.xml">
|
||||
<!ENTITY InstalledApplications SYSTEM "modules/installed-applications.xml">
|
||||
<!ENTITY Logout SYSTEM "modules/logout.xml">
|
||||
<!ENTITY SAML SYSTEM "modules/saml.xml">
|
||||
<!ENTITY JAAS SYSTEM "modules/jaas.xml">
|
||||
<!ENTITY SocialConfig SYSTEM "modules/social-config.xml">
|
||||
<!ENTITY SocialFacebook SYSTEM "modules/social-facebook.xml">
|
||||
<!ENTITY SocialGitHub SYSTEM "modules/social-github.xml">
|
||||
|
@ -91,10 +93,12 @@ This one is short
|
|||
&TomcatAdapter;
|
||||
&Jetty9Adapter;
|
||||
&Jetty8Adapter;
|
||||
&FuseAdapter;
|
||||
&JavascriptAdapter;
|
||||
&InstalledApplications;
|
||||
&Logout;
|
||||
&MultiTenancy;
|
||||
&JAAS;
|
||||
</chapter>
|
||||
|
||||
<chapter>
|
||||
|
|
41
docbook/reference/en/en-US/modules/fuse-adapter.xml
Normal file
41
docbook/reference/en/en-US/modules/fuse-adapter.xml
Normal file
|
@ -0,0 +1,41 @@
|
|||
<section id="fuse-adapter">
|
||||
<title>JBoss Fuse and Apache Karaf Adapter</title>
|
||||
<para>
|
||||
Currently Keycloak supports securing your web applications running inside <ulink url="http://www.jboss.org/products/fuse/overview/">JBoss Fuse</ulink>
|
||||
or <ulink url="http://karaf.apache.org/">Apache Karaf</ulink> . It leverages <link linkend="jetty8-adapter">Jetty 8 adapter</link> as both JBoss Fuse 6.1
|
||||
and Apache Karaf 3 are bundled with <ulink url="http://eclipse.org/jetty/">Jetty 8.1 server</ulink> under the covers and Jetty is used for running various kinds of web applications.
|
||||
</para>
|
||||
<para>
|
||||
What is supported for Fuse/Karaf is:
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>
|
||||
Security for classic WAR applications deployed on Fuse/Karaf with <ulink url="https://ops4j1.jira.com/wiki/display/ops4j/Pax+Web+Extender+-+War">Pax Web War Extender</ulink>.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
Security for servlets deployed on Fuse/Karaf as OSGI services with <ulink url="https://ops4j1.jira.com/wiki/display/ops4j/Pax+Web+Extender+-+Whiteboard">Pax Web Whiteboard Extender</ulink>.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
Security for <ulink url="http://camel.apache.org/">Apache Camel</ulink> Jetty endpoints running with
|
||||
<ulink url="http://camel.apache.org/jetty.html">Camel Jetty</ulink> component.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
Security for <ulink url="http://cxf.apache.org/">Apache CXF</ulink> endpoints running on their own separate
|
||||
<ulink url="http://cxf.apache.org/docs/jetty-configuration.html">Jetty engine</ulink>.
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>
|
||||
Security for <ulink url="http://cxf.apache.org/">Apache CXF</ulink> endpoints running on default engine provided by CXF servlet.
|
||||
</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
</para>
|
||||
<para>The best place to start is look at Fuse demo bundled as part of Keycloak examples in directory <literal>examples/fuse</literal> .</para>
|
||||
</section>
|
37
docbook/reference/en/en-US/modules/jaas.xml
Normal file
37
docbook/reference/en/en-US/modules/jaas.xml
Normal file
|
@ -0,0 +1,37 @@
|
|||
<section id="jaas-adapter">
|
||||
<title>JAAS plugin</title>
|
||||
<para>
|
||||
It's generally not needed to use JAAS for most of the applications, especially if they are HTTP based, but directly choose one of our adapters.
|
||||
However some applications and systems may still rely on pure legacy JAAS solution. Keycloak provides couple of login modules
|
||||
to help with such use cases. Some login modules provided by Keycloak are:
|
||||
</para>
|
||||
<para>
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term>org.keycloak.adapters.jaas.DirectAccessGrantsLoginModule</term>
|
||||
<listitem>
|
||||
<para>
|
||||
This login module allows to authenticate with username/password from Keycloak database. It's using
|
||||
<link linkend="direct-access-grants">Direct Access Grants</link> Keycloak endpoint to validate on Keycloak side if provided username/password is valid.
|
||||
It's useful especially for non-web based systems, which need to rely on JAAS and want to use Keycloak credentials, but can't use classic browser based
|
||||
authentication flow due to their non-web nature. Example of such application could be messaging application or SSH system.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>org.keycloak.adapters.jaas.BearerTokenLoginModule</term>
|
||||
<listitem>
|
||||
<para>
|
||||
This login module allows to authenticate with Keycloak access token passed to it through CallbackHandler as password.
|
||||
It may be useful for example in case, when you have Keycloak access token from classic web based authentication flow
|
||||
and your web application then needs to talk to external non-web based system, which rely on JAAS. For example to JMS/messaging system.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
</para>
|
||||
<para>
|
||||
Both login modules have single configuration property <literal>keycloak-config-file</literal> where you need to provide location of keycloak.json configuration file.
|
||||
It could be either provided from filesystem or from classpath (in that case you may need value like <literal>classpath:/folder-on-classpath/keycloak.json</literal> ).
|
||||
</para>
|
||||
</section>
|
|
@ -58,3 +58,13 @@ Multi tenancy
|
|||
-------------
|
||||
|
||||
A complete application, showing how to achieve multi tenancy of web applications by using one realm per account. For more information look at `multi-tenant/README.md`
|
||||
|
||||
Basic authentication
|
||||
--------------------
|
||||
|
||||
Example REST application configured to support both basic authentication with username/password as well as authentication with bearer token. For more information look at `basic-auth/README.md`
|
||||
|
||||
Fuse
|
||||
----
|
||||
|
||||
This is set of demo applications, showing how to secure your own web applications running inside OSGI environment in JBoss Fuse or Apache Karaf. Fore more information look at `fuse/README.md`
|
||||
|
|
132
examples/fuse/README.md
Normal file
132
examples/fuse/README.md
Normal file
|
@ -0,0 +1,132 @@
|
|||
Keycloak Fuse demo
|
||||
==================
|
||||
|
||||
Currently Keycloak supports securing your web applications running inside [JBoss Fuse](http://www.jboss.org/products/fuse/overview/) or [Apache Karaf](http://karaf.apache.org/). It leverages Jetty8 adapter
|
||||
as both JBoss Fuse 6.1 and Apache Karaf 3 are bundled with [Jetty8](http://eclipse.org/jetty/) server under the covers and Jetty is used for running various kinds of web applications.
|
||||
|
||||
The Fuse example is slightly modified version of Keycloak base demo applications. The main difference among base demo is that for Fuse demo
|
||||
are applications running on separate Fuse/Karaf server. Keycloak server is supposed to run separately on Wildfly 8 or JBoss EAP 6.3.
|
||||
|
||||
What is supported for Fuse/Karaf is:
|
||||
* Security for classic WAR applications deployed on Fuse/Karaf with [pax-war extender](https://ops4j1.jira.com/wiki/display/ops4j/Pax+Web+Extender+-+War).
|
||||
* Security for servlets deployed on Fuse/Karaf as OSGI services with [pax-whiteboard extender](https://ops4j1.jira.com/wiki/display/ops4j/Pax+Web+Extender+-+Whiteboard).
|
||||
* Security for [Apache Camel](http://camel.apache.org/) Jetty endpoints running with [camel-jetty](http://camel.apache.org/jetty.html) component.
|
||||
* Security for [Apache CXF](http://cxf.apache.org/) endpoints running on their own separate [Jetty engine](http://cxf.apache.org/docs/jetty-configuration.html).
|
||||
Supports both securing JAX-RS and JAX-WS endpoints.
|
||||
* Security for [Apache CXF](http://cxf.apache.org/) endpoints running on default engine provided by CXF servlet on [http://localhost:8181/cxf](http://localhost:8181/cxf)
|
||||
|
||||
Fuse demo contains those basic applications:
|
||||
* **customer-app-fuse** A WAR application that is deployed with [pax-war extender](https://ops4j1.jira.com/wiki/display/ops4j/Pax+Web+Extender+-+War)
|
||||
* **product-app-fuse** A servlet application deployed with [pax-whiteboard extender](https://ops4j1.jira.com/wiki/display/ops4j/Pax+Web+Extender+-+Whiteboard)
|
||||
* **cxf-jaxws** [Apache CXF](http://cxf.apache.org/) JAX-WS endpoint running on separate Jetty engine on [http://localhost:8282/PersonServiceCF](http://localhost:8282/PersonServiceCF).
|
||||
The product-app-fuse invokes the endpoint to get data.
|
||||
* **camel** [Apache Camel](http://camel.apache.org/) endpoint running on separate Jetty engine on [http://localhost:8383/admin-camel-endpoint](http://localhost:8383/admin-camel-endpoint).
|
||||
The customer-app-fuse invokes the endpoint to get data.
|
||||
* **cxf-jaxrs** [Apache CXF](http://cxf.apache.org/) JAX-RS endpoint running on default Jetty on [http://localhost:8181/cxf/customerservice](http://localhost:8181/cxf/customerservice).
|
||||
The customer-app-fuse invokes the endpoint to get data
|
||||
|
||||
Running of demo consists of 2 steps. First you need to run separate Keycloak server and then Fuse/Karaf server with the applications
|
||||
|
||||
Base steps
|
||||
----------
|
||||
|
||||
* Run external instance of Keycloak server on WildFly 8 or JBoss EAP 6.3 . Fuse demo suppose that server is running on [http://localhost:8080/auth](http://localhost:8080/auth)
|
||||
* Import realm `demo` from the file testrealm.json on `examples/fuse/testrealm.json` .
|
||||
* Then build examples, which is needed so the feature repository is added to your local maven repo:
|
||||
|
||||
```
|
||||
cd examples/fuse
|
||||
mvn clean install
|
||||
```
|
||||
|
||||
Run demo applications on Apache Karaf 3.0.2
|
||||
-------------------------------------------
|
||||
|
||||
Demo is using Apache camel and Apache CXF, which are not in standalone Karaf by default. So you will need to install feature repositories for both of them.
|
||||
Next step is to add feature repository for main set of Keycloak karaf features and for the demo. Once all feature URLs are added, you just need to install `keycloak-fuse-example` feature,
|
||||
which automatically installs all other needed stuff.
|
||||
|
||||
Once you run Apache Karaf, you need to run these commands from Karaf console (Make sure to replace keycloak versions in the example with actual Keycloak version):
|
||||
|
||||
```
|
||||
feature:repo-add mvn:org.apache.camel.karaf/apache-camel/2.12.5/xml/features
|
||||
feature:repo-add mvn:org.apache.cxf.karaf/apache-cxf/2.7.14/xml/features
|
||||
feature:repo-add mvn:org.keycloak/keycloak-osgi-features/1.1.0.Final/xml/features
|
||||
feature:repo-add mvn:org.keycloak.example.demo/keycloak-fuse-example-features/1.1.0.Final/xml/features
|
||||
feature:install keycloak-fuse-example
|
||||
```
|
||||
|
||||
After that you can test running on [http://localhost:8080/customer-portal](http://localhost:8080/customer-portal) and login as "bburke@redhat.com" with password "password". Customer-portal is able to
|
||||
receive the response from the endpoints provided by `cxf-jaxrs` and `camel` applications. Note that camel endpoint is available just for users with role `admin`
|
||||
in this demo, so "bburke@redhat.com" can't access it. You may login as "admin" with password "password" in order to invoke camel endpoint.
|
||||
|
||||
From [http://localhost:8080/product-portal](http://localhost:8080/product-portal) you will see servlet endpoint, which invokes JAX-WS provided by `cxf-jaxws` application.
|
||||
|
||||
Note that this demo also secures whole default CXF endpoint on [http://localhost:8181/cxf](http://localhost:8181/cxf) hence every application running under it is secured too.
|
||||
|
||||
Running example on JBoss Fuse 6.1.0.redhat-379
|
||||
----------------------------------------------
|
||||
|
||||
Securing your applications on JBoss Fuse 6.1 is a bit more tricky. There is bug [https://ops4j1.jira.com/browse/PAXWEB-666](https://ops4j1.jira.com/browse/PAXWEB-666)
|
||||
, which doesn't easily allow to secure default Jetty engine on [http://localhost:8181](http://localhost:8181) as it's not possible to inject
|
||||
custom Jetty authenticator provided by Keycloak Jetty adapter into underlying Jetty server. Hence first step is to upgrade pax-web
|
||||
version from default 3.0.6 to newer 3.1.2 . Then you need to "refresh" cxf feature too. Final step is to install "keycloak-fuse-example" feature.
|
||||
|
||||
All the steps could be performed with these commands in Fuse console (Replace Keycloak versions with the current version number again):
|
||||
|
||||
```
|
||||
features:uninstall pax-war
|
||||
features:uninstall pax-http-whiteboard
|
||||
features:uninstall pax-http
|
||||
features:uninstall pax-jetty
|
||||
features:removeurl mvn:org.ops4j.pax.web/pax-web-features/3.0.6/xml/features
|
||||
features:addurl mvn:org.ops4j.pax.web/pax-web-features/3.1.2/xml/features
|
||||
|
||||
features:addurl mvn:org.keycloak/keycloak-osgi-features/1.1.0.Final/xml/features
|
||||
features:addurl mvn:org.keycloak.example.demo/keycloak-fuse-example-features/1.1.0.Final/xml/features
|
||||
|
||||
features:install keycloak-pax-web-upgrade
|
||||
features:install pax-http-whiteboard/3.1.2
|
||||
features:install pax-war/3.1.2
|
||||
|
||||
features:uninstall cxf
|
||||
features:install cxf
|
||||
|
||||
features:install keycloak-fuse-example
|
||||
```
|
||||
|
||||
Now you can test example applications similarly like described for "Karaf" section.
|
||||
|
||||
How to secure your own applications
|
||||
-----------------------------------
|
||||
Most of the steps should be understandable from testing and understanding the demo. Basically all mentioned applications require to
|
||||
inject Keycloak Jetty authenticator into underlying Jetty server . The steps are bit different according to application type.
|
||||
|
||||
**Classic WAR application** - Take a look at `customer-portal-app` for inspiration. The needed steps are:
|
||||
* Declare needed constraints in `/WEB-INF/web.xml`
|
||||
* Add `jetty-web.xml` file with the authenticator to `/WEB-INF/jetty-web.xml` and add `/WEB-INF/keycloak.json` with your Keycloak configuration
|
||||
* Make sure your WAR imports `org.keycloak.adapters.jetty` and maybe some more packages in MANIFEST.MF file in header `Import-Package`. It's
|
||||
recommended to use maven-bundle-plugin similarly like Fuse examples are doing, but note that "*" resolution for package doesn't import `org.keycloak.adapters.jetty` package
|
||||
as it's not used by application or Blueprint or Spring descriptor, but it's used just in jetty-web.xml file.
|
||||
|
||||
**Servlet web application deployed by pax-whiteboard-extender** - Take a look at `product-portal-app` for inspiration. The needed steps are:
|
||||
* Keycloak provides PaxWebIntegrationService, which allows to inject jetty-authenticator.xml and configure security constraints for your application.
|
||||
Example `product-portal-app` declares this in `OSGI-INF/blueprint/blueprint.xml` . Note that your servlet needs to depend on it.
|
||||
* Steps 2,3 are same like for classic WAR
|
||||
|
||||
**Apache camel application** - You can secure your Apache camel endpoint using [camel-jetty](http://camel.apache.org/jetty.html) endpoint by adding securityHandler with KeycloakJettyAuthenticator and
|
||||
proper security constraints injected. Take a look at `OSGI-INF/blueprint/blueprint.xml` configuration in `camel` application on example of how it can be done.
|
||||
|
||||
**Apache CXF endpoint** - It's recommended to run your CXF endpoints secured by Keycloak on separate Jetty engine. Application `cxf-ws` is using separate endpoint on
|
||||
[http://localhost:8282](http://localhost:8282) . All the important configuration is declared in cxf-jaxws app in `META-INF/spring/beans.xml` .
|
||||
|
||||
**Builtin web applications** - Some services automatically come with deployed servlets on startup. One of such examples is CXF servlet running on
|
||||
[http://localhost:8181/cxf](http://localhost:8181/cxf) context. Securing such endpoints is quite tricky. The approach, which Keycloak is currently using,
|
||||
is providing ServletUnregistrationService, which undeploys builtin servlet at startup, so you are able to re-deploy it again on context secured by Keycloak.
|
||||
You can see the `OSGI-INF/blueprint/blueprint.xml` inside `cxf-jaxrs` project, which adds JAX-RS "customerservice" endpoint and more importantly, it secures whole `/cxf` context.
|
||||
|
||||
As a side effect, all other CXF services running on default CXF HTTP destination will be secured too. Once you uninstall feature "keycloak-fuse-example" the
|
||||
original unsecured servlet on `/cxf` context is deployed back and hence context will become unsecured again.
|
||||
|
||||
It's recommended to use your own Jetty engine for your apps (similarly like `cxf-jaxws` application is doing).
|
||||
|
79
examples/fuse/camel/pom.xml
Normal file
79
examples/fuse/camel/pom.xml
Normal file
|
@ -0,0 +1,79 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>1.2.0.Beta1-SNAPSHOT</version>
|
||||
<relativePath>../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.keycloak.example.demo</groupId>
|
||||
<artifactId>camel-endpoint-example</artifactId>
|
||||
<packaging>bundle</packaging>
|
||||
<name>Camel endpoint example - Secured in Karaf/Fuse</name>
|
||||
<description/>
|
||||
|
||||
<properties>
|
||||
<camel.version>2.12.5</camel.version>
|
||||
<keycloak.osgi.export>
|
||||
</keycloak.osgi.export>
|
||||
<keycloak.osgi.import>
|
||||
org.eclipse.jetty.security;version="[8.1,10)",
|
||||
org.eclipse.jetty.util.security;version="[8.1,10)",
|
||||
org.keycloak.*;version="${project.version}",
|
||||
*;resolution:=optional
|
||||
</keycloak.osgi.import>
|
||||
<keycloak.osgi.private>
|
||||
org.keycloak.example.*
|
||||
</keycloak.osgi.private>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.apache.camel</groupId>
|
||||
<artifactId>camel-core</artifactId>
|
||||
<version>${camel.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.camel</groupId>
|
||||
<artifactId>camel-blueprint</artifactId>
|
||||
<version>${camel.version}</version>
|
||||
</dependency>
|
||||
<dependency><groupId>org.apache.camel</groupId>
|
||||
<artifactId>camel-jetty</artifactId>
|
||||
<version>${camel.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<defaultGoal>install</defaultGoal>
|
||||
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<source>${maven.compiler.source}</source>
|
||||
<target>${maven.compiler.target}</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.felix</groupId>
|
||||
<artifactId>maven-bundle-plugin</artifactId>
|
||||
<extensions>true</extensions>
|
||||
<configuration>
|
||||
<instructions>
|
||||
<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>
|
|
@ -0,0 +1,15 @@
|
|||
package org.keycloak.example;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||
*/
|
||||
public class CamelHelloBean {
|
||||
|
||||
public String hello() {
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
return "Hello admin! It's " + sdf.format(new Date());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:camel="http://camel.apache.org/schema/blueprint"
|
||||
xsi:schemaLocation="
|
||||
http://www.osgi.org/xmlns/blueprint/v1.0.0 http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd
|
||||
http://camel.apache.org/schema/blueprint http://camel.apache.org/schema/blueprint/camel-blueprint.xsd">
|
||||
|
||||
<bean id="kcAdapterConfig" class="org.keycloak.representations.adapters.config.AdapterConfig">
|
||||
<property name="realm" value="demo"/>
|
||||
<property name="resource" value="admin-camel-endpoint"/>
|
||||
<property name="realmKey" value="MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB"/>
|
||||
<property name="bearerOnly" value="true"/>
|
||||
<property name="sslRequired" value="EXTERNAL"/>
|
||||
</bean>
|
||||
|
||||
<bean id="keycloakAuthenticator" class="org.keycloak.adapters.jetty.KeycloakJettyAuthenticator">
|
||||
<property name="adapterConfig" ref="kcAdapterConfig"/>
|
||||
</bean>
|
||||
|
||||
<bean id="constraint" class="org.eclipse.jetty.util.security.Constraint">
|
||||
<property name="name" value="Customers"/>
|
||||
<property name="roles">
|
||||
<list>
|
||||
<value>admin</value>
|
||||
</list>
|
||||
</property>
|
||||
<property name="authenticate" value="true"/>
|
||||
<property name="dataConstraint" value="0"/>
|
||||
</bean>
|
||||
|
||||
<bean id="constraintMapping" class="org.eclipse.jetty.security.ConstraintMapping">
|
||||
<property name="constraint" ref="constraint"/>
|
||||
<property name="pathSpec" value="/*"/>
|
||||
</bean>
|
||||
|
||||
<bean id="securityHandler" class="org.eclipse.jetty.security.ConstraintSecurityHandler">
|
||||
<property name="authenticator" ref="keycloakAuthenticator" />
|
||||
<property name="constraintMappings">
|
||||
<list>
|
||||
<ref component-id="constraintMapping" />
|
||||
</list>
|
||||
</property>
|
||||
<property name="authMethod" value="BASIC"/>
|
||||
<property name="realmName" value="does-not-matter"/>
|
||||
</bean>
|
||||
|
||||
<bean id="sessionHandler" class="org.keycloak.adapters.jetty.core.WrappingSessionHandler">
|
||||
<property name="handler" ref="securityHandler" />
|
||||
</bean>
|
||||
|
||||
<bean id="helloBean" class="org.keycloak.example.CamelHelloBean" />
|
||||
|
||||
<camelContext id="blueprintContext"
|
||||
trace="false"
|
||||
xmlns="http://camel.apache.org/schema/blueprint">
|
||||
<route id="httpBridge">
|
||||
<from uri="jetty:http://0.0.0.0:8383/admin-camel-endpoint?handlers=sessionHandler&matchOnUriPrefix=true" />
|
||||
<setBody>
|
||||
<method ref="helloBean" method="hello"/>
|
||||
</setBody>
|
||||
<log message="The message from camel endpoint contains ${body}"/>
|
||||
<to uri="mock:result"/>
|
||||
</route>
|
||||
</camelContext>
|
||||
|
||||
</blueprint>
|
121
examples/fuse/customer-app-fuse/pom.xml
Normal file
121
examples/fuse/customer-app-fuse/pom.xml
Normal file
|
@ -0,0 +1,121 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>1.2.0.Beta1-SNAPSHOT</version>
|
||||
<relativePath>../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.keycloak.example.demo</groupId>
|
||||
<artifactId>customer-portal-fuse-example</artifactId>
|
||||
<packaging>war</packaging>
|
||||
<name>Customer Portal - Secured in Karaf/Fuse</name>
|
||||
<description/>
|
||||
|
||||
<properties>
|
||||
<keycloak.osgi.export>
|
||||
</keycloak.osgi.export>
|
||||
<keycloak.osgi.import>
|
||||
org.apache.http.*;version=${keycloak.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.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>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-adapter-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
<artifactId>httpclient</artifactId>
|
||||
<version>${keycloak.apache.httpcomponents.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<finalName>customer-portal-fuse</finalName>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-deploy-plugin</artifactId>
|
||||
<configuration>
|
||||
<skip>true</skip>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<source>${maven.compiler.source}</source>
|
||||
<target>${maven.compiler.target}</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<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>customer-portal</Webapp-Context>
|
||||
<Web-ContextPath>customer-portal</Web-ContextPath>
|
||||
<Embed-Directory>WEB-INF/lib</Embed-Directory>
|
||||
<Bundle-ClassPath>.,WEB-INF/classes</Bundle-ClassPath>
|
||||
<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>
|
|
@ -0,0 +1,74 @@
|
|||
package org.keycloak.example;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.apache.http.HttpEntity;
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.client.HttpClient;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.keycloak.KeycloakSecurityContext;
|
||||
import org.keycloak.adapters.HttpClientBuilder;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||
*/
|
||||
public class CamelClient {
|
||||
|
||||
public static String sendRequest(HttpServletRequest req) throws CxfRsClient.Failure {
|
||||
KeycloakSecurityContext session = (KeycloakSecurityContext) req.getAttribute(KeycloakSecurityContext.class.getName());
|
||||
|
||||
HttpClient client = new HttpClientBuilder()
|
||||
.disableTrustManager().build();
|
||||
try {
|
||||
HttpGet get = new HttpGet("http://localhost:8383/admin-camel-endpoint");
|
||||
get.addHeader("Authorization", "Bearer " + session.getTokenString());
|
||||
try {
|
||||
HttpResponse response = client.execute(get);
|
||||
if (response.getStatusLine().getStatusCode() != 200) {
|
||||
return "There was a failure processing request. You either didn't configure Keycloak properly or you don't have enought permission? Status code is "
|
||||
+ response.getStatusLine().getStatusCode();
|
||||
}
|
||||
HttpEntity entity = response.getEntity();
|
||||
InputStream is = entity.getContent();
|
||||
try {
|
||||
return getStringFromInputStream(is);
|
||||
} finally {
|
||||
is.close();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
} finally {
|
||||
client.getConnectionManager().shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
private static String getStringFromInputStream(InputStream is) {
|
||||
BufferedReader br = null;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
String line;
|
||||
try {
|
||||
br = new BufferedReader(new InputStreamReader(is));
|
||||
while ((line = br.readLine()) != null) {
|
||||
sb.append(line);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
} finally {
|
||||
if (br != null) {
|
||||
try {
|
||||
br.close();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
return sb.toString();
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
package org.keycloak.example;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.apache.http.HttpEntity;
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.client.HttpClient;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.keycloak.KeycloakSecurityContext;
|
||||
import org.keycloak.adapters.HttpClientBuilder;
|
||||
import org.keycloak.representations.IDToken;
|
||||
import org.keycloak.util.JsonSerialization;
|
||||
import org.keycloak.util.UriUtils;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class CxfRsClient {
|
||||
|
||||
static class TypedList extends ArrayList<String> {
|
||||
}
|
||||
|
||||
public static class Failure extends Exception {
|
||||
private int status;
|
||||
|
||||
public Failure(int status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
public int getStatus() {
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
public static IDToken getIDToken(HttpServletRequest req) {
|
||||
KeycloakSecurityContext session = (KeycloakSecurityContext) req.getAttribute(KeycloakSecurityContext.class.getName());
|
||||
return session.getIdToken();
|
||||
|
||||
}
|
||||
|
||||
public static List<String> getCustomers(HttpServletRequest req) throws Failure {
|
||||
KeycloakSecurityContext session = (KeycloakSecurityContext) req.getAttribute(KeycloakSecurityContext.class.getName());
|
||||
|
||||
HttpClient client = new HttpClientBuilder()
|
||||
.disableTrustManager().build();
|
||||
try {
|
||||
HttpGet get = new HttpGet(UriUtils.getOrigin(req.getRequestURL().toString()) + "/cxf/customerservice/customers");
|
||||
get.addHeader("Authorization", "Bearer " + session.getTokenString());
|
||||
try {
|
||||
HttpResponse response = client.execute(get);
|
||||
if (response.getStatusLine().getStatusCode() != 200) {
|
||||
throw new Failure(response.getStatusLine().getStatusCode());
|
||||
}
|
||||
HttpEntity entity = response.getEntity();
|
||||
InputStream is = entity.getContent();
|
||||
try {
|
||||
return JsonSerialization.readValue(is, TypedList.class);
|
||||
} finally {
|
||||
is.close();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
} finally {
|
||||
client.getConnectionManager().shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0"?>
|
||||
<!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>
|
10
examples/fuse/customer-app-fuse/src/main/webapp/WEB-INF/keycloak.json
Executable file
10
examples/fuse/customer-app-fuse/src/main/webapp/WEB-INF/keycloak.json
Executable file
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"realm": "demo",
|
||||
"resource": "customer-portal",
|
||||
"realm-public-key": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
|
||||
"auth-server-url": "http://localhost:8080/auth",
|
||||
"ssl-required" : "external",
|
||||
"credentials": {
|
||||
"secret": "password"
|
||||
}
|
||||
}
|
34
examples/fuse/customer-app-fuse/src/main/webapp/WEB-INF/web.xml
Executable file
34
examples/fuse/customer-app-fuse/src/main/webapp/WEB-INF/web.xml
Executable file
|
@ -0,0 +1,34 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<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>customer-portal</module-name>
|
||||
|
||||
<welcome-file-list>
|
||||
<welcome-file>index.html</welcome-file>
|
||||
</welcome-file-list>
|
||||
|
||||
<security-constraint>
|
||||
<web-resource-collection>
|
||||
<web-resource-name>Customers</web-resource-name>
|
||||
<url-pattern>/customers/*</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>
|
15
examples/fuse/customer-app-fuse/src/main/webapp/customers/camel.jsp
Executable file
15
examples/fuse/customer-app-fuse/src/main/webapp/customers/camel.jsp
Executable file
|
@ -0,0 +1,15 @@
|
|||
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
|
||||
pageEncoding="ISO-8859-1" %>
|
||||
<%@ page import="org.keycloak.constants.ServiceUrlConstants" %>
|
||||
<%@ page import="org.keycloak.example.CamelClient" %>
|
||||
<%@ page import="org.keycloak.representations.IDToken" %>
|
||||
<html>
|
||||
<head>
|
||||
<title>Camel page</title>
|
||||
</head>
|
||||
<body bgcolor="#E3F6CE">
|
||||
<p>You will receive info from camel endpoint. Endpoint is accessible just for admin user</p>
|
||||
<p>Response from camel: <b><%= CamelClient.sendRequest(request) %></b> </p>
|
||||
<br><br>
|
||||
</body>
|
||||
</html>
|
50
examples/fuse/customer-app-fuse/src/main/webapp/customers/cxf-ws.jsp
Executable file
50
examples/fuse/customer-app-fuse/src/main/webapp/customers/cxf-ws.jsp
Executable file
|
@ -0,0 +1,50 @@
|
|||
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
|
||||
pageEncoding="ISO-8859-1" %>
|
||||
<%@ page import="org.keycloak.constants.ServiceUrlConstants" %>
|
||||
<%@ page import="org.keycloak.example.CxfRsClient" %>
|
||||
<%@ page import="org.keycloak.representations.IDToken" %>
|
||||
<%@ page import="org.keycloak.util.KeycloakUriBuilder" %>
|
||||
<%@ page session="false" %>
|
||||
<html>
|
||||
<head>
|
||||
<title>Customer View Page</title>
|
||||
</head>
|
||||
<body bgcolor="#E3F6CE">
|
||||
<%
|
||||
String logoutUri = KeycloakUriBuilder.fromUri("http://localhost:8080/auth").path(ServiceUrlConstants.TOKEN_SERVICE_LOGOUT_PATH)
|
||||
.queryParam("redirect_uri", "http://localhost:8181/customer-portal").build("demo").toString();
|
||||
String acctUri = KeycloakUriBuilder.fromUri("http://localhost:8080/auth").path(ServiceUrlConstants.ACCOUNT_SERVICE_PATH)
|
||||
.queryParam("referrer", "customer-portal").build("demo").toString();
|
||||
IDToken idToken = CxfRsClient.getIDToken(request);
|
||||
%>
|
||||
<p>Goto: <a href="/product-portal">products</a> | <a href="<%=logoutUri%>">logout</a> | <a
|
||||
href="<%=acctUri%>">manage acct</a></p>
|
||||
Servlet User Principal <b><%=request.getUserPrincipal().getName()%>
|
||||
</b> made this request.
|
||||
<p><b>Caller IDToken values</b> (<i>You can specify what is returned in IDToken in the customer-portal claims page in the admin console</i>:</p>
|
||||
<p>Username: <%=idToken.getPreferredUsername()%></p>
|
||||
<p>Email: <%=idToken.getEmail()%></p>
|
||||
<p>Full Name: <%=idToken.getName()%></p>
|
||||
<p>First: <%=idToken.getGivenName()%></p>
|
||||
<p>Last: <%=idToken.getFamilyName()%></p>
|
||||
<h2>Customer Listing</h2>
|
||||
<%
|
||||
java.util.List<String> list = null;
|
||||
try {
|
||||
list = CxfRsClient.getCustomers(request);
|
||||
} catch (CxfRsClient.Failure failure) {
|
||||
out.println("There was a failure processing request. You either didn't configure Keycloak properly, or maybe" +
|
||||
"you just forgot to secure the cxf ws service?");
|
||||
out.println("Status from cxf ws service invocation was: " + failure.getStatus());
|
||||
return;
|
||||
}
|
||||
for (String cust : list) {
|
||||
out.print("<p>");
|
||||
out.print(cust);
|
||||
out.println("</p>");
|
||||
|
||||
}
|
||||
%>
|
||||
<br><br>
|
||||
</body>
|
||||
</html>
|
15
examples/fuse/customer-app-fuse/src/main/webapp/index.html
Executable file
15
examples/fuse/customer-app-fuse/src/main/webapp/index.html
Executable file
|
@ -0,0 +1,15 @@
|
|||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
|
||||
"http://www.w3.org/TR/html4/loose.dtd">
|
||||
<html>
|
||||
<head>
|
||||
<title>Customer portal on Karaf/Fuse</title>
|
||||
</head>
|
||||
<body bgcolor="#E3F6CE">
|
||||
<h1>Customer Portal</h1>
|
||||
|
||||
<p><a href="customers/cxf-ws.jsp">Customer Listing - CXF WS endpoint</a></p>
|
||||
|
||||
<p><a href="customers/camel.jsp">Admin Interface - Apache Camel endpoint</a></p>
|
||||
|
||||
</body>
|
||||
</html>
|
86
examples/fuse/cxf-jaxrs/pom.xml
Normal file
86
examples/fuse/cxf-jaxrs/pom.xml
Normal file
|
@ -0,0 +1,86 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>1.2.0.Beta1-SNAPSHOT</version>
|
||||
<relativePath>../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.keycloak.example.demo</groupId>
|
||||
<artifactId>cxf-jaxrs-example</artifactId>
|
||||
<packaging>bundle</packaging>
|
||||
<name>CXF JAXRS Example - Secured in Karaf/Fuse</name>
|
||||
|
||||
<properties>
|
||||
<cxf.version>2.7.14</cxf.version>
|
||||
<keycloak.osgi.export>
|
||||
</keycloak.osgi.export>
|
||||
<keycloak.osgi.import>
|
||||
META-INF.cxf,
|
||||
META-INF.cxf.osgi,
|
||||
org.apache.cxf.bus,
|
||||
org.apache.cxf.bus.spring,
|
||||
org.apache.cxf.bus.resource,
|
||||
org.apache.cxf.resource,
|
||||
org.apache.cxf.jaxrs,
|
||||
org.apache.cxf.transport.http,
|
||||
org.codehaus.jackson.jaxrs;version="${jackson.version}",
|
||||
org.keycloak.adapters.jetty;version="${project.version}",
|
||||
org.keycloak.adapters;version="${project.version}",
|
||||
*
|
||||
</keycloak.osgi.import>
|
||||
<keycloak.osgi.private>
|
||||
org.keycloak.example.rs.*
|
||||
</keycloak.osgi.private>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.apache.cxf</groupId>
|
||||
<artifactId>cxf-rt-frontend-jaxrs</artifactId>
|
||||
<version>${cxf.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.cxf</groupId>
|
||||
<artifactId>cxf-rt-transports-http</artifactId>
|
||||
<version>${cxf.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.cxf</groupId>
|
||||
<artifactId>cxf-rt-transports-http-jetty</artifactId>
|
||||
<version>${cxf.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<defaultGoal>install</defaultGoal>
|
||||
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<source>${maven.compiler.source}</source>
|
||||
<target>${maven.compiler.target}</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.felix</groupId>
|
||||
<artifactId>maven-bundle-plugin</artifactId>
|
||||
<extensions>true</extensions>
|
||||
<configuration>
|
||||
<instructions>
|
||||
<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>
|
|
@ -0,0 +1,30 @@
|
|||
package org.keycloak.example.rs;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.Produces;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
@Path("/customers")
|
||||
public class CxfCustomerService {
|
||||
|
||||
@GET
|
||||
@Produces("application/json")
|
||||
public List<String> getCustomers() {
|
||||
ArrayList<String> rtn = new ArrayList<String>();
|
||||
rtn.add("Bill Burke");
|
||||
rtn.add("Stian Thorgersen");
|
||||
rtn.add("Stan Silvert");
|
||||
rtn.add("Gabriel Cardoso");
|
||||
rtn.add("Viliam Rockai");
|
||||
rtn.add("Marek Posolda");
|
||||
rtn.add("Boleslaw Dawidowicz");
|
||||
return rtn;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,106 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:jaxrs="http://cxf.apache.org/blueprint/jaxrs"
|
||||
xmlns:cm="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.0.0"
|
||||
xsi:schemaLocation="
|
||||
http://www.osgi.org/xmlns/blueprint/v1.0.0 http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd
|
||||
http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/blueprint/jaxrs.xsd
|
||||
http://www.osgi.org/xmlns/blueprint/v1.0.0 http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd">
|
||||
|
||||
<!-- JAXRS Application -->
|
||||
|
||||
<bean id="customerBean" class="org.keycloak.example.rs.CxfCustomerService" />
|
||||
|
||||
<jaxrs:server id="cxfJaxrsServer" address="/customerservice">
|
||||
<jaxrs:providers>
|
||||
<!--<bean class="com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider" />-->
|
||||
<bean class="org.codehaus.jackson.jaxrs.JacksonJsonProvider" />
|
||||
</jaxrs:providers>
|
||||
<jaxrs:serviceBeans>
|
||||
<ref component-id="customerBean" />
|
||||
</jaxrs:serviceBeans>
|
||||
</jaxrs:server>
|
||||
|
||||
<!-- Securing of whole /cxf context by unregister default cxf servlet from paxweb and re-register with applied security constraints -->
|
||||
|
||||
<cm:property-placeholder persistent-id="org.apache.cxf.osgi" id="cxfOsgiPropertiesKCSecured">
|
||||
<cm:default-properties>
|
||||
<cm:property name="org.apache.cxf.servlet.context" value="/cxf"/>
|
||||
<cm:property name="org.apache.cxf.servlet.name" value="cxf-osgi-transport-servlet"/>
|
||||
<cm:property name="org.apache.cxf.servlet.hide-service-list-page" value="false"/>
|
||||
<cm:property name="org.apache.cxf.servlet.disable-address-updates" value="false"/>
|
||||
<cm:property name="org.apache.cxf.servlet.base-address" value=""/>
|
||||
<cm:property name="org.apache.cxf.servlet.service-list-path" value=""/>
|
||||
<cm:property name="org.apache.cxf.servlet.static-resources-list" value=""/>
|
||||
<cm:property name="org.apache.cxf.servlet.redirects-list" value=""/>
|
||||
<cm:property name="org.apache.cxf.servlet.redirect-servlet-name" value=""/>
|
||||
<cm:property name="org.apache.cxf.servlet.redirect-servlet-path" value=""/>
|
||||
<cm:property name="org.apache.cxf.servlet.service-list-all-contexts" value=""/>
|
||||
<cm:property name="org.apache.cxf.servlet.service-list-page-authenticate" value="false"/>
|
||||
<cm:property name="org.apache.cxf.servlet.service-list-page-authenticate-realm" value="karaf"/>
|
||||
</cm:default-properties>
|
||||
</cm:property-placeholder>
|
||||
|
||||
<bean id="cxfConstraintMapping" class="org.eclipse.jetty.security.ConstraintMapping">
|
||||
<property name="constraint">
|
||||
<bean class="org.eclipse.jetty.util.security.Constraint">
|
||||
<property name="name" value="cst1"/>
|
||||
<property name="roles">
|
||||
<list>
|
||||
<value>user</value>
|
||||
</list>
|
||||
</property>
|
||||
<property name="authenticate" value="true"/>
|
||||
<property name="dataConstraint" value="0"/>
|
||||
</bean>
|
||||
</property>
|
||||
<property name="pathSpec" value="/cxf/*"/>
|
||||
</bean>
|
||||
|
||||
<bean id="cxfKeycloakPaxWebIntegration" class="org.keycloak.adapters.osgi.PaxWebIntegrationService"
|
||||
init-method="start" destroy-method="stop">
|
||||
<property name="bundleContext" ref="blueprintBundleContext" />
|
||||
<property name="jettyWebXmlLocation" value="/WEB-INF/jetty-web.xml" />
|
||||
<property name="constraintMappings">
|
||||
<list>
|
||||
<ref component-id="cxfConstraintMapping" />
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="defaultCxfUnregistration" class="org.keycloak.adapters.osgi.ServletUnregistrationService"
|
||||
init-method="start" destroy-method="stop">
|
||||
<property name="bundleContext" ref="blueprintBundleContext" />
|
||||
<property name="servletReference">
|
||||
<reference interface="javax.servlet.Servlet" component-name="osgiServlet" />
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="osgiServletKCSecured" class="org.apache.cxf.transport.servlet.CXFNonSpringServlet" depends-on="cxfKeycloakPaxWebIntegration defaultCxfUnregistration">
|
||||
<argument>
|
||||
<reference interface="org.apache.cxf.transport.http.DestinationRegistry" timeout="5000"/>
|
||||
</argument>
|
||||
<argument value="false"/>
|
||||
</bean>
|
||||
|
||||
<service ref="osgiServletKCSecured" interface="javax.servlet.Servlet">
|
||||
<service-properties>
|
||||
<entry key="alias" value="${org.apache.cxf.servlet.context}"/>
|
||||
<entry key="servlet-name" value="${org.apache.cxf.servlet.name}"/>
|
||||
<entry key="hide-service-list-page" value="${org.apache.cxf.servlet.hide-service-list-page}"/>
|
||||
<entry key="disable-address-updates" value="${org.apache.cxf.servlet.disable-address-updates}"/>
|
||||
<entry key="base-address" value="${org.apache.cxf.servlet.base-address}"/>
|
||||
<entry key="service-list-path" value="${org.apache.cxf.servlet.service-list-path}"/>
|
||||
<entry key="static-resources-list" value="${org.apache.cxf.servlet.static-resources-list}"/>
|
||||
<entry key="redirects-list" value="${org.apache.cxf.servlet.redirects-list}"/>
|
||||
<entry key="redirect-servlet-name" value="${org.apache.cxf.servlet.redirect-servlet-name}"/>
|
||||
<entry key="redirect-servlet-path" value="${org.apache.cxf.servlet.redirect-servlet-path}"/>
|
||||
<entry key="service-list-all-contexts" value="${org.apache.cxf.servlet.service-list-all-contexts}"/>
|
||||
<entry key="service-list-page-authenticate" value="${org.apache.cxf.servlet.service-list-page-authenticate}"/>
|
||||
<entry key="service-list-page-authenticate-realm" value="${org.apache.cxf.servlet.service-list-page-authenticate-realm}"/>
|
||||
</service-properties>
|
||||
</service>
|
||||
|
||||
|
||||
</blueprint>
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0"?>
|
||||
<!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>
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"realm": "demo",
|
||||
"resource": "builtin-cxf-app",
|
||||
"realm-public-key": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
|
||||
"auth-server-url": "http://localhost:8080/auth",
|
||||
"ssl-required" : "external",
|
||||
"credentials": {
|
||||
"secret": "password"
|
||||
}
|
||||
}
|
107
examples/fuse/cxf-jaxws/pom.xml
Normal file
107
examples/fuse/cxf-jaxws/pom.xml
Normal file
|
@ -0,0 +1,107 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>1.2.0.Beta1-SNAPSHOT</version>
|
||||
<relativePath>../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.keycloak.example.demo</groupId>
|
||||
<artifactId>cxf-jaxws-example</artifactId>
|
||||
<packaging>bundle</packaging>
|
||||
<name>CXF JAXWS Example - Secured in Karaf/Fuse</name>
|
||||
<description/>
|
||||
|
||||
<properties>
|
||||
<cxf.version>2.7.14</cxf.version>
|
||||
<keycloak.osgi.export>
|
||||
</keycloak.osgi.export>
|
||||
<keycloak.osgi.import>
|
||||
javax.jws;resolution:=optional,
|
||||
javax.wsdl,
|
||||
javax.xml.bind,
|
||||
javax.xml.bind.annotation,
|
||||
javax.xml.namespace,
|
||||
javax.xml.ws,
|
||||
META-INF.cxf,
|
||||
META-INF.cxf.osgi,
|
||||
org.apache.cxf.bus,
|
||||
org.apache.cxf.bus.spring,
|
||||
org.apache.cxf.bus.resource,
|
||||
org.apache.cxf.configuration.spring,
|
||||
org.apache.cxf.resource,
|
||||
org.apache.cxf.jaxws,
|
||||
org.apache.cxf.transport.http,
|
||||
org.springframework.beans.factory.config,
|
||||
*;resolution:=optional
|
||||
</keycloak.osgi.import>
|
||||
<keycloak.osgi.private>
|
||||
org.keycloak.example.ws.*
|
||||
</keycloak.osgi.private>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.apache.geronimo.specs</groupId>
|
||||
<artifactId>geronimo-ws-metadata_2.0_spec</artifactId>
|
||||
<version>1.1.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.geronimo.specs</groupId>
|
||||
<artifactId>geronimo-jaxws_2.2_spec</artifactId>
|
||||
<version>1.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.xml.bind</groupId>
|
||||
<artifactId>jaxb-api</artifactId>
|
||||
<version>2.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.cxf</groupId>
|
||||
<artifactId>cxf-rt-frontend-jaxws</artifactId>
|
||||
<version>${cxf.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.cxf</groupId>
|
||||
<artifactId>cxf-rt-transports-http</artifactId>
|
||||
<version>${cxf.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.cxf</groupId>
|
||||
<artifactId>cxf-rt-transports-http-jetty</artifactId>
|
||||
<version>${cxf.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<defaultGoal>install</defaultGoal>
|
||||
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<source>${maven.compiler.source}</source>
|
||||
<target>${maven.compiler.target}</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.felix</groupId>
|
||||
<artifactId>maven-bundle-plugin</artifactId>
|
||||
<extensions>true</extensions>
|
||||
<configuration>
|
||||
<instructions>
|
||||
<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>
|
|
@ -0,0 +1,27 @@
|
|||
package org.keycloak.example.ws;
|
||||
|
||||
import javax.jws.WebMethod;
|
||||
import javax.jws.WebParam;
|
||||
import javax.jws.WebService;
|
||||
import javax.xml.bind.annotation.XmlSeeAlso;
|
||||
import javax.xml.ws.RequestWrapper;
|
||||
import javax.xml.ws.ResponseWrapper;
|
||||
|
||||
import org.keycloak.example.ws.types.ObjectFactory;
|
||||
|
||||
@WebService
|
||||
@XmlSeeAlso({ObjectFactory.class})
|
||||
public interface Person {
|
||||
|
||||
@RequestWrapper(localName = "GetPerson", className = "GetPerson")
|
||||
@ResponseWrapper(localName = "GetPersonResponse", className = "GetPersonResponse")
|
||||
@WebMethod(operationName = "GetPerson")
|
||||
public void getPerson(
|
||||
@WebParam(mode = WebParam.Mode.INOUT, name = "personId")
|
||||
javax.xml.ws.Holder<String> personId,
|
||||
@WebParam(mode = WebParam.Mode.OUT, name = "ssn")
|
||||
javax.xml.ws.Holder<String> ssn,
|
||||
@WebParam(mode = WebParam.Mode.OUT, name = "name")
|
||||
javax.xml.ws.Holder<String> name
|
||||
) throws UnknownPersonFault;
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
package org.keycloak.example.ws;
|
||||
|
||||
import javax.jws.WebService;
|
||||
import javax.xml.ws.Holder;
|
||||
|
||||
@WebService(serviceName = "PersonService", endpointInterface = "org.keycloak.example.ws.Person")
|
||||
public class PersonImpl implements Person {
|
||||
|
||||
public void getPerson(Holder<String> personId, Holder<String> ssn, Holder<String> name)
|
||||
throws UnknownPersonFault
|
||||
{
|
||||
if (personId.value == null || personId.value.length() == 0) {
|
||||
org.keycloak.example.ws.types.UnknownPersonFault fault = new org.keycloak.example.ws.types.UnknownPersonFault();
|
||||
fault.setPersonId(personId.value);
|
||||
throw new UnknownPersonFault(null,fault);
|
||||
} else {
|
||||
name.value = "John Doe";
|
||||
ssn.value = "123-456-7890";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
package org.keycloak.example.ws;
|
||||
|
||||
import javax.xml.ws.WebFault;
|
||||
|
||||
@WebFault(name = "UnknownPersonFault")
|
||||
public class UnknownPersonFault extends Exception {
|
||||
public static final long serialVersionUID = 20081110144906L;
|
||||
|
||||
private org.keycloak.example.ws.types.UnknownPersonFault unknownPersonFault;
|
||||
|
||||
public UnknownPersonFault() {
|
||||
super();
|
||||
}
|
||||
|
||||
public UnknownPersonFault(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public UnknownPersonFault(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public UnknownPersonFault(String message, org.keycloak.example.ws.types.UnknownPersonFault unknownPersonFault) {
|
||||
super(message);
|
||||
this.unknownPersonFault = unknownPersonFault;
|
||||
}
|
||||
|
||||
public UnknownPersonFault(String message, org.keycloak.example.ws.types.UnknownPersonFault unknownPersonFault, Throwable cause) {
|
||||
super(message, cause);
|
||||
this.unknownPersonFault = unknownPersonFault;
|
||||
}
|
||||
|
||||
public org.keycloak.example.ws.types.UnknownPersonFault getFaultInfo() {
|
||||
return this.unknownPersonFault;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
|
||||
package org.keycloak.example.ws.types;
|
||||
|
||||
import javax.xml.bind.annotation.XmlAccessType;
|
||||
import javax.xml.bind.annotation.XmlAccessorType;
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
import javax.xml.bind.annotation.XmlType;
|
||||
|
||||
|
||||
/**
|
||||
* <p>Java class for anonymous complex type.
|
||||
*
|
||||
* <p>The following schema fragment specifies the expected content contained within this class.
|
||||
*
|
||||
* <pre>
|
||||
* <complexType>
|
||||
* <complexContent>
|
||||
* <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
|
||||
* <sequence>
|
||||
* <element name="personId" type="{http://www.w3.org/2001/XMLSchema}string"/>
|
||||
* </sequence>
|
||||
* </restriction>
|
||||
* </complexContent>
|
||||
* </complexType>
|
||||
* </pre>
|
||||
*
|
||||
*
|
||||
*/
|
||||
@XmlAccessorType(XmlAccessType.FIELD)
|
||||
@XmlType(name = "", propOrder = {
|
||||
"personId"
|
||||
})
|
||||
@XmlRootElement(name = "GetPerson")
|
||||
public class GetPerson {
|
||||
|
||||
@XmlElement(required = true)
|
||||
protected String personId;
|
||||
|
||||
/**
|
||||
* Gets the value of the personId property.
|
||||
*
|
||||
* @return
|
||||
* possible object is
|
||||
* {@link String }
|
||||
*
|
||||
*/
|
||||
public String getPersonId() {
|
||||
return personId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of the personId property.
|
||||
*
|
||||
* @param value
|
||||
* allowed object is
|
||||
* {@link String }
|
||||
*
|
||||
*/
|
||||
public void setPersonId(String value) {
|
||||
this.personId = value;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,120 @@
|
|||
|
||||
package org.keycloak.example.ws.types;
|
||||
|
||||
import javax.xml.bind.annotation.XmlAccessType;
|
||||
import javax.xml.bind.annotation.XmlAccessorType;
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
import javax.xml.bind.annotation.XmlType;
|
||||
|
||||
|
||||
/**
|
||||
* <p>Java class for anonymous complex type.
|
||||
*
|
||||
* <p>The following schema fragment specifies the expected content contained within this class.
|
||||
*
|
||||
* <pre>
|
||||
* <complexType>
|
||||
* <complexContent>
|
||||
* <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
|
||||
* <sequence>
|
||||
* <element name="personId" type="{http://www.w3.org/2001/XMLSchema}string"/>
|
||||
* <element name="ssn" type="{http://www.w3.org/2001/XMLSchema}string"/>
|
||||
* <element name="name" type="{http://www.w3.org/2001/XMLSchema}string"/>
|
||||
* </sequence>
|
||||
* </restriction>
|
||||
* </complexContent>
|
||||
* </complexType>
|
||||
* </pre>
|
||||
*
|
||||
*
|
||||
*/
|
||||
@XmlAccessorType(XmlAccessType.FIELD)
|
||||
@XmlType(name = "", propOrder = {
|
||||
"personId",
|
||||
"ssn",
|
||||
"name"
|
||||
})
|
||||
@XmlRootElement(name = "GetPersonResponse")
|
||||
public class GetPersonResponse {
|
||||
|
||||
@XmlElement(required = true)
|
||||
protected String personId;
|
||||
@XmlElement(required = true)
|
||||
protected String ssn;
|
||||
@XmlElement(required = true)
|
||||
protected String name;
|
||||
|
||||
/**
|
||||
* Gets the value of the personId property.
|
||||
*
|
||||
* @return
|
||||
* possible object is
|
||||
* {@link String }
|
||||
*
|
||||
*/
|
||||
public String getPersonId() {
|
||||
return personId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of the personId property.
|
||||
*
|
||||
* @param value
|
||||
* allowed object is
|
||||
* {@link String }
|
||||
*
|
||||
*/
|
||||
public void setPersonId(String value) {
|
||||
this.personId = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of the ssn property.
|
||||
*
|
||||
* @return
|
||||
* possible object is
|
||||
* {@link String }
|
||||
*
|
||||
*/
|
||||
public String getSsn() {
|
||||
return ssn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of the ssn property.
|
||||
*
|
||||
* @param value
|
||||
* allowed object is
|
||||
* {@link String }
|
||||
*
|
||||
*/
|
||||
public void setSsn(String value) {
|
||||
this.ssn = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of the name property.
|
||||
*
|
||||
* @return
|
||||
* possible object is
|
||||
* {@link String }
|
||||
*
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of the name property.
|
||||
*
|
||||
* @param value
|
||||
* allowed object is
|
||||
* {@link String }
|
||||
*
|
||||
*/
|
||||
public void setName(String value) {
|
||||
this.name = value;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
|
||||
package org.keycloak.example.ws.types;
|
||||
|
||||
import javax.xml.bind.annotation.XmlRegistry;
|
||||
|
||||
|
||||
/**
|
||||
* This object contains factory methods for each
|
||||
* Java content interface and Java element interface
|
||||
* generated in the org.apache.servicemix.samples.wsdl_first.types package.
|
||||
* <p>An ObjectFactory allows you to programatically
|
||||
* construct new instances of the Java representation
|
||||
* for XML content. The Java representation of XML
|
||||
* content can consist of schema derived interfaces
|
||||
* and classes representing the binding of schema
|
||||
* type definitions, element declarations and model
|
||||
* groups. Factory methods for each of these are
|
||||
* provided in this class.
|
||||
*
|
||||
*/
|
||||
@XmlRegistry
|
||||
public class ObjectFactory {
|
||||
|
||||
|
||||
/**
|
||||
* Create a new ObjectFactory that can be used to create new instances of schema derived classes for package: org.apache.servicemix.samples.wsdl_first.types
|
||||
*
|
||||
*/
|
||||
public ObjectFactory() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an instance of {@link GetPersonResponse }
|
||||
*
|
||||
*/
|
||||
public GetPersonResponse createGetPersonResponse() {
|
||||
return new GetPersonResponse();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an instance of {@link GetPerson }
|
||||
*
|
||||
*/
|
||||
public GetPerson createGetPerson() {
|
||||
return new GetPerson();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an instance of {@link UnknownPersonFault }
|
||||
*
|
||||
*/
|
||||
public UnknownPersonFault createUnknownPersonFault() {
|
||||
return new UnknownPersonFault();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
|
||||
package org.keycloak.example.ws.types;
|
||||
|
||||
import javax.xml.bind.annotation.XmlAccessType;
|
||||
import javax.xml.bind.annotation.XmlAccessorType;
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
import javax.xml.bind.annotation.XmlType;
|
||||
|
||||
|
||||
/**
|
||||
* <p>Java class for anonymous complex type.
|
||||
*
|
||||
* <p>The following schema fragment specifies the expected content contained within this class.
|
||||
*
|
||||
* <pre>
|
||||
* <complexType>
|
||||
* <complexContent>
|
||||
* <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
|
||||
* <sequence>
|
||||
* <element name="personId" type="{http://www.w3.org/2001/XMLSchema}string"/>
|
||||
* </sequence>
|
||||
* </restriction>
|
||||
* </complexContent>
|
||||
* </complexType>
|
||||
* </pre>
|
||||
*
|
||||
*
|
||||
*/
|
||||
@XmlAccessorType(XmlAccessType.FIELD)
|
||||
@XmlType(name = "", propOrder = {
|
||||
"personId"
|
||||
})
|
||||
@XmlRootElement(name = "UnknownPersonFault")
|
||||
public class UnknownPersonFault {
|
||||
|
||||
@XmlElement(required = true)
|
||||
protected String personId;
|
||||
|
||||
/**
|
||||
* Gets the value of the personId property.
|
||||
*
|
||||
* @return
|
||||
* possible object is
|
||||
* {@link String }
|
||||
*
|
||||
*/
|
||||
public String getPersonId() {
|
||||
return personId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the value of the personId property.
|
||||
*
|
||||
* @param value
|
||||
* allowed object is
|
||||
* {@link String }
|
||||
*
|
||||
*/
|
||||
public void setPersonId(String value) {
|
||||
this.personId = value;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
package org.keycloak.example.ws.types;
|
|
@ -0,0 +1,69 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Generated by Apache ServiceMix Archetype -->
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:jaxws="http://cxf.apache.org/jaxws"
|
||||
xmlns:httpj="http://cxf.apache.org/transports/http-jetty/configuration"
|
||||
xsi:schemaLocation="
|
||||
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://cxf.apache.org/jaxws http://cxf.apache.org/schemas/jaxws.xsd
|
||||
http://www.springframework.org/schema/osgi http://www.springframework.org/schema/osgi/spring-osgi.xsd
|
||||
http://cxf.apache.org/transports/http-jetty/configuration http://cxf.apache.org/schemas/configuration/http-jetty.xsd">
|
||||
|
||||
<import resource="classpath:META-INF/cxf/cxf.xml" />
|
||||
|
||||
<bean id="kcAdapterConfig" class="org.keycloak.representations.adapters.config.AdapterConfig">
|
||||
<property name="realm" value="demo"/>
|
||||
<property name="resource" value="custom-cxf-endpoint"/>
|
||||
<property name="realmKey" value="MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB"/>
|
||||
<property name="bearerOnly" value="true"/>
|
||||
<property name="sslRequired" value="EXTERNAL"/>
|
||||
</bean>
|
||||
|
||||
<bean id="keycloakAuthenticator" class="org.keycloak.adapters.jetty.KeycloakJettyAuthenticator">
|
||||
<property name="adapterConfig">
|
||||
<ref local="kcAdapterConfig" />
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="constraint" class="org.eclipse.jetty.util.security.Constraint">
|
||||
<property name="name" value="Customers"/>
|
||||
<property name="roles">
|
||||
<list>
|
||||
<value>user</value>
|
||||
</list>
|
||||
</property>
|
||||
<property name="authenticate" value="true"/>
|
||||
<property name="dataConstraint" value="0"/>
|
||||
</bean>
|
||||
|
||||
<bean id="constraintMapping" class="org.eclipse.jetty.security.ConstraintMapping">
|
||||
<property name="constraint" ref="constraint"/>
|
||||
<property name="pathSpec" value="/*"/>
|
||||
</bean>
|
||||
|
||||
<bean id="securityHandler" class="org.eclipse.jetty.security.ConstraintSecurityHandler">
|
||||
<property name="authenticator" ref="keycloakAuthenticator" />
|
||||
<property name="constraintMappings">
|
||||
<list>
|
||||
<ref local="constraintMapping" />
|
||||
</list>
|
||||
</property>
|
||||
<property name="authMethod" value="BASIC"/>
|
||||
<property name="realmName" value="does-not-matter"/>
|
||||
</bean>
|
||||
|
||||
<httpj:engine-factory bus="cxf" id="kc-cxf-endpoint">
|
||||
<httpj:engine port="8282">
|
||||
<httpj:handlers>
|
||||
<ref local="securityHandler" />
|
||||
</httpj:handlers>
|
||||
<httpj:sessionSupport>true</httpj:sessionSupport>
|
||||
</httpj:engine>
|
||||
</httpj:engine-factory>
|
||||
|
||||
<jaxws:endpoint
|
||||
implementor="org.keycloak.example.ws.PersonImpl"
|
||||
address="http://localhost:8282/PersonServiceCF" depends-on="kc-cxf-endpoint"/>
|
||||
|
||||
</beans>
|
62
examples/fuse/features/pom.xml
Normal file
62
examples/fuse/features/pom.xml
Normal file
|
@ -0,0 +1,62 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>1.2.0.Beta1-SNAPSHOT</version>
|
||||
<relativePath>../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.keycloak.example.demo</groupId>
|
||||
<artifactId>keycloak-fuse-example-features</artifactId>
|
||||
<name>Keycloak Fuse Example - Features</name>
|
||||
<description/>
|
||||
|
||||
<build>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>src/main/resources</directory>
|
||||
<filtering>true</filtering>
|
||||
</resource>
|
||||
</resources>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-resources-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>filter</id>
|
||||
<phase>generate-resources</phase>
|
||||
<goals>
|
||||
<goal>resources</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>build-helper-maven-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>attach-artifacts</id>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>attach-artifact</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<artifacts>
|
||||
<artifact>
|
||||
<file>target/classes/features.xml</file>
|
||||
<type>xml</type>
|
||||
<classifier>features</classifier>
|
||||
</artifact>
|
||||
</artifacts>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
19
examples/fuse/features/src/main/resources/features.xml
Normal file
19
examples/fuse/features/src/main/resources/features.xml
Normal file
|
@ -0,0 +1,19 @@
|
|||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<features xmlns="http://karaf.apache.org/xmlns/features/v1.0.0" name="keycloak-${project.version}">
|
||||
|
||||
<feature name="keycloak-fuse-example" version="${project.version}">
|
||||
<details>The keycloak fuse example</details>
|
||||
<feature>war</feature>
|
||||
<feature>camel</feature>
|
||||
<feature>camel-jetty</feature>
|
||||
<feature>cxf</feature>
|
||||
<feature>keycloak</feature>
|
||||
<bundle dependency="true">mvn:org.codehaus.jackson/jackson-jaxrs/${jackson.version}</bundle>
|
||||
<bundle>mvn:org.keycloak.example.demo/product-portal-fuse-example/${project.version}</bundle>
|
||||
<bundle>mvn:org.keycloak.example.demo/customer-portal-fuse-example/${project.version}/war</bundle>
|
||||
<bundle>mvn:org.keycloak.example.demo/camel-endpoint-example/${project.version}</bundle>
|
||||
<bundle>mvn:org.keycloak.example.demo/cxf-jaxws-example/${project.version}</bundle>
|
||||
<bundle>mvn:org.keycloak.example.demo/cxf-jaxrs-example/${project.version}</bundle>
|
||||
</feature>
|
||||
|
||||
</features>
|
37
examples/fuse/pom.xml
Normal file
37
examples/fuse/pom.xml
Normal file
|
@ -0,0 +1,37 @@
|
|||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>1.2.0.Beta1-SNAPSHOT</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<name>Fuse examples</name>
|
||||
<description/>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>fuse-pom</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-deploy-plugin</artifactId>
|
||||
<configuration>
|
||||
<skip>true</skip>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<modules>
|
||||
<module>customer-app-fuse</module>
|
||||
<module>product-app-fuse</module>
|
||||
<module>cxf-jaxrs</module>
|
||||
<module>cxf-jaxws</module>
|
||||
<module>camel</module>
|
||||
<module>features</module>
|
||||
</modules>
|
||||
|
||||
</project>
|
83
examples/fuse/product-app-fuse/pom.xml
Normal file
83
examples/fuse/product-app-fuse/pom.xml
Normal file
|
@ -0,0 +1,83 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>1.2.0.Beta1-SNAPSHOT</version>
|
||||
<relativePath>../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.keycloak.example.demo</groupId>
|
||||
<artifactId>product-portal-fuse-example</artifactId>
|
||||
<packaging>bundle</packaging>
|
||||
|
||||
<name>Product Portal - Secured in Karaf/Fuse</name>
|
||||
<description/>
|
||||
|
||||
<properties>
|
||||
<keycloak.osgi.export>
|
||||
</keycloak.osgi.export>
|
||||
<keycloak.osgi.import>
|
||||
org.eclipse.jetty.security;version="[8.1,10)",
|
||||
org.eclipse.jetty.util.security;version="[8.1,10)",
|
||||
org.keycloak.adapters.jetty;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>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Dependency for jaxws client to allow sending request to jaxws endpoint provided by cxf-jaxws-example -->
|
||||
<dependency>
|
||||
<groupId>org.keycloak.example.demo</groupId>
|
||||
<artifactId>cxf-jaxws-example</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<defaultGoal>install</defaultGoal>
|
||||
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<source>${maven.compiler.source}</source>
|
||||
<target>${maven.compiler.target}</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.felix</groupId>
|
||||
<artifactId>maven-bundle-plugin</artifactId>
|
||||
<extensions>true</extensions>
|
||||
<configuration>
|
||||
<instructions>
|
||||
<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>
|
||||
<Require-Bundle>org.apache.cxf.bundle</Require-Bundle>
|
||||
</instructions>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
|
@ -0,0 +1,95 @@
|
|||
package org.keycloak.example;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.xml.ws.WebServiceException;
|
||||
|
||||
import org.apache.cxf.endpoint.Client;
|
||||
import org.apache.cxf.frontend.ClientProxy;
|
||||
import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;
|
||||
import org.apache.cxf.message.Message;
|
||||
import org.keycloak.KeycloakSecurityContext;
|
||||
import org.keycloak.constants.ServiceUrlConstants;
|
||||
import org.keycloak.example.ws.Person;
|
||||
import org.keycloak.example.ws.UnknownPersonFault;
|
||||
import org.keycloak.util.KeycloakUriBuilder;
|
||||
|
||||
/**
|
||||
* Servlet for receiving informations about products from backend JAXWS service. Actually it's about "persons" not "products" :)
|
||||
*
|
||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||
*/
|
||||
public class ProductPortalServlet extends HttpServlet {
|
||||
|
||||
@Override
|
||||
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
|
||||
resp.setContentType("text/html");
|
||||
|
||||
// Send jaxws request
|
||||
PrintWriter out = resp.getWriter();
|
||||
out.println("<html><head><title>Product Portal Page</title></head><body>");
|
||||
|
||||
String logoutUri = KeycloakUriBuilder.fromUri("http://localhost:8080/auth").path(ServiceUrlConstants.TOKEN_SERVICE_LOGOUT_PATH)
|
||||
.queryParam("redirect_uri", "http://localhost:8181/product-portal").build("demo").toString();
|
||||
String acctUri = KeycloakUriBuilder.fromUri("http://localhost:8080/auth").path(ServiceUrlConstants.ACCOUNT_SERVICE_PATH)
|
||||
.queryParam("referrer", "product-portal").build("demo").toString();
|
||||
|
||||
out.println("<p>Goto: <a href=\"/customer-portal\">customers</a> | <a href=\"" + logoutUri + "\">logout</a> | <a href=\"" + acctUri + "\">manage acct</a></p>");
|
||||
out.println("Servlet User Principal <b>" + req.getUserPrincipal() + "</b> made this request.");
|
||||
|
||||
String unsecuredWsClientResponse = sendWsReq(req, false);
|
||||
String securedWsClientResponse = sendWsReq(req, true);
|
||||
|
||||
out.println("<p>Person with ID 1 - unsecured request: <b>" + unsecuredWsClientResponse + "</b></p>");
|
||||
out.println("<p>Person with ID 1 - secured request: <b>" + securedWsClientResponse + "</b></p>");
|
||||
out.println("</body></html>");
|
||||
out.flush();
|
||||
out.close();
|
||||
}
|
||||
|
||||
private String sendWsReq(HttpServletRequest req, boolean secured) {
|
||||
JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
|
||||
factory.setServiceClass(Person.class);
|
||||
factory.setAddress("http://localhost:8282/PersonServiceCF");
|
||||
|
||||
Person simpleClient = (Person)factory.create();
|
||||
java.lang.String _getPerson_personIdVal = "1";
|
||||
javax.xml.ws.Holder<java.lang.String> _getPerson_personId = new javax.xml.ws.Holder<java.lang.String>(_getPerson_personIdVal);
|
||||
javax.xml.ws.Holder<java.lang.String> _getPerson_ssn = new javax.xml.ws.Holder<java.lang.String>();
|
||||
javax.xml.ws.Holder<java.lang.String> _getPerson_name = new javax.xml.ws.Holder<java.lang.String>();
|
||||
|
||||
// Attach Authorization header
|
||||
if (secured) {
|
||||
Client clientProxy = ClientProxy.getClient(simpleClient);
|
||||
|
||||
KeycloakSecurityContext session = (KeycloakSecurityContext) req.getAttribute(KeycloakSecurityContext.class.getName());
|
||||
Map<String, List<String>> headers = new HashMap<String, List<String>>();
|
||||
headers.put("Authorization", Arrays.asList("Bearer " + session.getTokenString()));
|
||||
|
||||
clientProxy.getRequestContext().put(Message.PROTOCOL_HEADERS, headers);
|
||||
}
|
||||
|
||||
try {
|
||||
simpleClient.getPerson(_getPerson_personId, _getPerson_ssn, _getPerson_name);
|
||||
return String.format("Person received: id=%s, name=%s, ssn=%s", _getPerson_personId.value, _getPerson_name.value, _getPerson_ssn.value);
|
||||
} catch (UnknownPersonFault upf) {
|
||||
return "UnknownPersonFault has occurred. Details: " + upf.toString();
|
||||
} catch (WebServiceException wse) {
|
||||
String error = "Can't receive person. Reason: " + wse.getMessage();
|
||||
if (wse.getCause() != null) {
|
||||
Throwable cause = wse.getCause();
|
||||
error = error + " Details: " + cause.getClass().getName() + ": " + cause.getMessage();
|
||||
}
|
||||
return error;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.osgi.org/xmlns/blueprint/v1.0.0 http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd">
|
||||
|
||||
<!-- USing jetty bean just for the compatibility with other fuse services -->
|
||||
<bean id="servletConstraintMapping" class="org.eclipse.jetty.security.ConstraintMapping">
|
||||
<property name="constraint">
|
||||
<bean class="org.eclipse.jetty.util.security.Constraint">
|
||||
<property name="name" value="cst1"/>
|
||||
<property name="roles">
|
||||
<list>
|
||||
<value>user</value>
|
||||
</list>
|
||||
</property>
|
||||
<property name="authenticate" value="true"/>
|
||||
<property name="dataConstraint" value="0"/>
|
||||
</bean>
|
||||
</property>
|
||||
<property name="pathSpec" value="/product-portal/*"/>
|
||||
</bean>
|
||||
|
||||
<bean id="keycloakPaxWebIntegration" class="org.keycloak.adapters.osgi.PaxWebIntegrationService"
|
||||
init-method="start" destroy-method="stop">
|
||||
<property name="jettyWebXmlLocation" value="/WEB-INF/jetty-web.xml" />
|
||||
<property name="bundleContext" ref="blueprintBundleContext" />
|
||||
<property name="constraintMappings">
|
||||
<list>
|
||||
<ref component-id="servletConstraintMapping" />
|
||||
</list>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="productServlet" class="org.keycloak.example.ProductPortalServlet" depends-on="keycloakPaxWebIntegration">
|
||||
</bean>
|
||||
|
||||
<service ref="productServlet" interface="javax.servlet.Servlet">
|
||||
<service-properties>
|
||||
<entry key="alias" value="/product-portal" />
|
||||
<entry key="servlet-name" value="ProductServlet" />
|
||||
<entry key="keycloak.config.file" value="/keycloak.json" />
|
||||
</service-properties>
|
||||
</service>
|
||||
|
||||
</blueprint>
|
|
@ -0,0 +1,10 @@
|
|||
<?xml version="1.0"?>
|
||||
<!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>
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"realm": "demo",
|
||||
"resource": "product-portal",
|
||||
"realm-public-key": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
|
||||
"auth-server-url": "http://localhost:8080/auth",
|
||||
"ssl-required" : "external",
|
||||
"credentials": {
|
||||
"secret": "password"
|
||||
}
|
||||
}
|
135
examples/fuse/testrealm.json
Normal file
135
examples/fuse/testrealm.json
Normal file
|
@ -0,0 +1,135 @@
|
|||
{
|
||||
"realm": "demo",
|
||||
"enabled": true,
|
||||
"accessTokenLifespan": 60,
|
||||
"accessCodeLifespan": 60,
|
||||
"accessCodeLifespanUserAction": 300,
|
||||
"ssoSessionIdleTimeout": 600,
|
||||
"ssoSessionMaxLifespan": 36000,
|
||||
"passwordCredentialGrantAllowed": true,
|
||||
"sslRequired": "external",
|
||||
"registrationAllowed": false,
|
||||
"privateKey": "MIICXAIBAAKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQABAoGAfmO8gVhyBxdqlxmIuglbz8bcjQbhXJLR2EoS8ngTXmN1bo2L90M0mUKSdc7qF10LgETBzqL8jYlQIbt+e6TH8fcEpKCjUlyq0Mf/vVbfZSNaVycY13nTzo27iPyWQHK5NLuJzn1xvxxrUeXI6A2WFpGEBLbHjwpx5WQG9A+2scECQQDvdn9NE75HPTVPxBqsEd2z10TKkl9CZxu10Qby3iQQmWLEJ9LNmy3acvKrE3gMiYNWb6xHPKiIqOR1as7L24aTAkEAtyvQOlCvr5kAjVqrEKXalj0Tzewjweuxc0pskvArTI2Oo070h65GpoIKLc9jf+UA69cRtquwP93aZKtW06U8dQJAF2Y44ks/mK5+eyDqik3koCI08qaC8HYq2wVl7G2QkJ6sbAaILtcvD92ToOvyGyeE0flvmDZxMYlvaZnaQ0lcSQJBAKZU6umJi3/xeEbkJqMfeLclD27XGEFoPeNrmdx0q10Azp4NfJAY+Z8KRyQCR2BEG+oNitBOZ+YXF9KCpH3cdmECQHEigJhYg+ykOvr1aiZUMFT72HU0jnmQe2FVekuG+LJUt2Tm7GtMjTFoGpf0JwrVuZN39fOYAlo+nTixgeW7X8Y=",
|
||||
"publicKey": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
|
||||
"requiredCredentials": [ "password" ],
|
||||
"users" : [
|
||||
{
|
||||
"username" : "bburke@redhat.com",
|
||||
"enabled": true,
|
||||
"email" : "bburke@redhat.com",
|
||||
"firstName": "Bill",
|
||||
"lastName": "Burke",
|
||||
"credentials" : [
|
||||
{ "type" : "password",
|
||||
"value" : "password" }
|
||||
],
|
||||
"realmRoles": [ "user" ],
|
||||
"applicationRoles": {
|
||||
"account": [ "manage-account" ]
|
||||
}
|
||||
},
|
||||
{
|
||||
"username" : "stian",
|
||||
"enabled": true,
|
||||
"email" : "stian@redhat.com",
|
||||
"firstName": "Stian",
|
||||
"lastName": "Thorgersen",
|
||||
"credentials" : [
|
||||
{ "type" : "password",
|
||||
"value" : "password" }
|
||||
],
|
||||
"realmRoles": [ "user" ],
|
||||
"applicationRoles": {
|
||||
"account": [ "manage-account" ]
|
||||
}
|
||||
},
|
||||
{
|
||||
"username" : "mposolda@redhat.com",
|
||||
"enabled": true,
|
||||
"email" : "mposolda@redhat.com",
|
||||
"firstName": "Marek",
|
||||
"lastName": "Posolda",
|
||||
"credentials" : [
|
||||
{ "type" : "password",
|
||||
"value" : "password" }
|
||||
],
|
||||
"realmRoles": [ "user" ],
|
||||
"applicationRoles": {
|
||||
"account": [ "manage-account" ]
|
||||
}
|
||||
},
|
||||
{
|
||||
"username" : "admin",
|
||||
"enabled": true,
|
||||
"email" : "admin@admin.com",
|
||||
"firstName": "Admin",
|
||||
"lastName": "Burke",
|
||||
"credentials" : [
|
||||
{ "type" : "password",
|
||||
"value" : "password" }
|
||||
],
|
||||
"realmRoles": [ "user","admin" ],
|
||||
"applicationRoles": {
|
||||
"realm-management": [ "realm-admin" ]
|
||||
}
|
||||
}
|
||||
],
|
||||
"roles" : {
|
||||
"realm" : [
|
||||
{
|
||||
"name": "user",
|
||||
"description": "User privileges"
|
||||
},
|
||||
{
|
||||
"name": "admin",
|
||||
"description": "Administrator privileges"
|
||||
}
|
||||
]
|
||||
},
|
||||
"applications": [
|
||||
{
|
||||
"name": "customer-portal",
|
||||
"enabled": true,
|
||||
"adminUrl": "http://localhost:8181/customer-portal",
|
||||
"baseUrl": "http://localhost:8181/customer-portal",
|
||||
"redirectUris": [
|
||||
"http://localhost:8181/customer-portal/*"
|
||||
],
|
||||
"secret": "password"
|
||||
},
|
||||
{
|
||||
"name": "product-portal",
|
||||
"enabled": true,
|
||||
"adminUrl": "http://localhost:8181/product-portal",
|
||||
"baseUrl": "http://localhost:8181/product-portal",
|
||||
"redirectUris": [
|
||||
"http://localhost:8181/product-portal/*"
|
||||
],
|
||||
"secret": "password"
|
||||
},
|
||||
{
|
||||
"name": "builtin-cxf-app",
|
||||
"enabled": true,
|
||||
"adminUrl": "http://localhost:8181/cxf",
|
||||
"baseUrl": "http://localhost:8181/cxf",
|
||||
"redirectUris": [
|
||||
"http://localhost:8181/cxf/*"
|
||||
],
|
||||
"secret": "password"
|
||||
},
|
||||
{
|
||||
"name": "custom-cxf-endpoint",
|
||||
"enabled": true,
|
||||
"adminUrl": "http://localhost:8282/PersonServiceCF",
|
||||
"baseUrl": "http://localhost:8282/PersonServiceCF",
|
||||
"bearerOnly": true
|
||||
},
|
||||
{
|
||||
"name": "admin-camel-endpoint",
|
||||
"enabled": true,
|
||||
"adminUrl": "http://localhost:8383/admin-camel-endpoint",
|
||||
"baseUrl": "http://localhost:8383/admin-camel-endpoint",
|
||||
"bearerOnly": true
|
||||
}
|
||||
]
|
||||
}
|
|
@ -32,5 +32,6 @@
|
|||
<module>js-console</module>
|
||||
<module>multi-tenant</module>
|
||||
<module>basic-auth</module>
|
||||
<module>fuse</module>
|
||||
</modules>
|
||||
</project>
|
||||
|
|
|
@ -13,6 +13,17 @@
|
|||
<name>Keycloak Adapter Core</name>
|
||||
<description/>
|
||||
|
||||
<properties>
|
||||
<keycloak.osgi.export>
|
||||
org.keycloak.adapters.*
|
||||
</keycloak.osgi.export>
|
||||
<keycloak.osgi.import>
|
||||
org.keycloak.*;version="${project.version}",
|
||||
org.apache.http.*;version=${keycloak.apache.httpcomponents.version},
|
||||
*;resolution:=optional
|
||||
</keycloak.osgi.import>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.bouncycastle</groupId>
|
||||
|
@ -73,6 +84,39 @@
|
|||
<target>${maven.compiler.target}</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<!-- Adding OSGI metadata to the JAR without changing the packaging type. -->
|
||||
<plugin>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<configuration>
|
||||
<archive>
|
||||
<manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile>
|
||||
</archive>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.felix</groupId>
|
||||
<artifactId>maven-bundle-plugin</artifactId>
|
||||
<extensions>true</extensions>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>bundle-manifest</id>
|
||||
<phase>process-classes</phase>
|
||||
<goals>
|
||||
<goal>manifest</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<instructions>
|
||||
<Bundle-ClassPath>.</Bundle-ClassPath>
|
||||
<Bundle-Name>${project.name}</Bundle-Name>
|
||||
<Bundle-SymbolicName>${project.groupId}.${project.artifactId}</Bundle-SymbolicName>
|
||||
<Import-Package>${keycloak.osgi.import}</Import-Package>
|
||||
<Export-Package>${keycloak.osgi.export}</Export-Package>
|
||||
</instructions>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ import org.keycloak.VerificationException;
|
|||
/**
|
||||
* Login module, which allows to authenticate Keycloak access token in environments, which rely on JAAS
|
||||
* <p/>
|
||||
* It expects login based on username and password where username must be equal to "Bearer" and password is keycloak access token.
|
||||
* It expects login based on username and password where username doesn't matter and password is keycloak access token.
|
||||
*
|
||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||
*/
|
||||
|
|
|
@ -74,7 +74,6 @@
|
|||
<dependency>
|
||||
<groupId>org.osgi</groupId>
|
||||
<artifactId>org.osgi.core</artifactId>
|
||||
<version>4.3.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
|
|
@ -13,6 +13,15 @@
|
|||
<name>Keycloak Jetty Core Integration</name>
|
||||
<properties>
|
||||
<jetty9.version>8.1.16.v20140903</jetty9.version>
|
||||
<keycloak.osgi.export>
|
||||
org.keycloak.adapters.jetty.core.*
|
||||
</keycloak.osgi.export>
|
||||
<keycloak.osgi.import>
|
||||
org.eclipse.jetty.*;version="[8.1,10)";resolution:=optional,
|
||||
javax.servlet.*;version="[2.5,4)";resolution:=optional,
|
||||
org.keycloak.*;version="${project.version}",
|
||||
*;resolution:=optional
|
||||
</keycloak.osgi.import>
|
||||
</properties>
|
||||
<description />
|
||||
|
||||
|
@ -94,6 +103,39 @@
|
|||
<target>1.6</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<!-- Adding OSGI metadata to the JAR without changing the packaging type. -->
|
||||
<plugin>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<configuration>
|
||||
<archive>
|
||||
<manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile>
|
||||
</archive>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.felix</groupId>
|
||||
<artifactId>maven-bundle-plugin</artifactId>
|
||||
<extensions>true</extensions>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>bundle-manifest</id>
|
||||
<phase>process-classes</phase>
|
||||
<goals>
|
||||
<goal>manifest</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<instructions>
|
||||
<Bundle-ClassPath>.</Bundle-ClassPath>
|
||||
<Bundle-Name>${project.name}</Bundle-Name>
|
||||
<Bundle-SymbolicName>${project.groupId}.${project.artifactId}</Bundle-SymbolicName>
|
||||
<Import-Package>${keycloak.osgi.import}</Import-Package>
|
||||
<Export-Package>${keycloak.osgi.export}</Export-Package>
|
||||
</instructions>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
package org.keycloak.adapters.jetty;
|
||||
package org.keycloak.adapters.jetty.core;
|
||||
|
||||
import org.eclipse.jetty.security.authentication.FormAuthenticator;
|
||||
import org.eclipse.jetty.server.Request;
|
||||
import org.eclipse.jetty.util.MultiMap;
|
||||
import org.jboss.logging.Logger;
|
||||
import org.keycloak.KeycloakPrincipal;
|
||||
import org.keycloak.KeycloakSecurityContext;
|
||||
|
@ -12,7 +10,6 @@ import org.keycloak.adapters.KeycloakAccount;
|
|||
import org.keycloak.adapters.KeycloakDeployment;
|
||||
import org.keycloak.adapters.RefreshableKeycloakSecurityContext;
|
||||
import org.keycloak.adapters.RequestAuthenticator;
|
||||
import org.keycloak.util.MultivaluedHashMap;
|
||||
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
|
@ -1,6 +1,5 @@
|
|||
package org.keycloak.adapters.jetty;
|
||||
package org.keycloak.adapters.jetty.core;
|
||||
|
||||
import org.apache.http.HttpVersion;
|
||||
import org.eclipse.jetty.security.DefaultUserIdentity;
|
||||
import org.eclipse.jetty.security.ServerAuthException;
|
||||
import org.eclipse.jetty.security.UserAuthentication;
|
||||
|
@ -162,8 +161,19 @@ public abstract class AbstractKeycloakJettyAuthenticator extends LoginAuthentica
|
|||
@SuppressWarnings("UseSpecificCatch")
|
||||
public void initializeKeycloak() {
|
||||
nodesRegistrationManagement = new NodesRegistrationManagement();
|
||||
String contextPath = ContextHandler.getCurrentContext().getContextPath();
|
||||
ServletContext theServletContext = ContextHandler.getCurrentContext().getContext(contextPath);
|
||||
|
||||
ServletContext theServletContext = null;
|
||||
ContextHandler.Context currentContext = ContextHandler.getCurrentContext();
|
||||
if (currentContext != null) {
|
||||
String contextPath = currentContext.getContextPath();
|
||||
|
||||
if ("".equals(contextPath)) {
|
||||
// This could be the case in osgi environment when deploying apps through pax whiteboard extension.
|
||||
theServletContext = currentContext;
|
||||
} else {
|
||||
theServletContext = currentContext.getContext(contextPath);
|
||||
}
|
||||
}
|
||||
|
||||
// Jetty 9.1.x servlet context will be null :(
|
||||
if (configResolver == null && theServletContext != null) {
|
|
@ -1,4 +1,4 @@
|
|||
package org.keycloak.adapters.jetty;
|
||||
package org.keycloak.adapters.jetty.core;
|
||||
|
||||
import org.eclipse.jetty.server.Request;
|
||||
import org.jboss.logging.Logger;
|
|
@ -1,4 +1,4 @@
|
|||
package org.keycloak.adapters.jetty;
|
||||
package org.keycloak.adapters.jetty.core;
|
||||
|
||||
import org.keycloak.KeycloakSecurityContext;
|
||||
import org.keycloak.adapters.HttpFacade;
|
|
@ -1,4 +1,4 @@
|
|||
package org.keycloak.adapters.jetty;
|
||||
package org.keycloak.adapters.jetty.core;
|
||||
|
||||
import org.eclipse.jetty.server.Request;
|
||||
import org.jboss.logging.Logger;
|
|
@ -1,4 +1,4 @@
|
|||
package org.keycloak.adapters.jetty;
|
||||
package org.keycloak.adapters.jetty.core;
|
||||
|
||||
import org.eclipse.jetty.server.SessionManager;
|
||||
import org.jboss.logging.Logger;
|
|
@ -0,0 +1,30 @@
|
|||
package org.keycloak.adapters.jetty.core;
|
||||
|
||||
import org.eclipse.jetty.server.Handler;
|
||||
import org.eclipse.jetty.server.SessionManager;
|
||||
import org.eclipse.jetty.server.handler.HandlerWrapper;
|
||||
import org.eclipse.jetty.server.session.SessionHandler;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||
*/
|
||||
public class WrappingSessionHandler extends SessionHandler {
|
||||
|
||||
public WrappingSessionHandler() {
|
||||
super();
|
||||
}
|
||||
|
||||
public WrappingSessionHandler(SessionManager mgr) {
|
||||
super(mgr);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setHandler(Handler handler) {
|
||||
if (getHandler() != null && getHandler() instanceof HandlerWrapper) {
|
||||
HandlerWrapper wrappedHandler = (HandlerWrapper) getHandler();
|
||||
wrappedHandler.setHandler(handler);
|
||||
} else {
|
||||
super.setHandler(handler);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -13,6 +13,14 @@
|
|||
<name>Keycloak Jetty 8.1.x Integration</name>
|
||||
<properties>
|
||||
<jetty9.version>8.1.16.v20140903</jetty9.version>
|
||||
<keycloak.osgi.export>
|
||||
org.keycloak.adapters.jetty.*
|
||||
</keycloak.osgi.export>
|
||||
<keycloak.osgi.import>
|
||||
javax.servlet.*;version="[2.5,4)";resolution:=optional,
|
||||
org.keycloak.*;version="${project.version}",
|
||||
*;resolution:=optional
|
||||
</keycloak.osgi.import>
|
||||
</properties>
|
||||
<description />
|
||||
|
||||
|
@ -99,6 +107,39 @@
|
|||
<target>1.6</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<!-- Adding OSGI metadata to the JAR without changing the packaging type. -->
|
||||
<plugin>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<configuration>
|
||||
<archive>
|
||||
<manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile>
|
||||
</archive>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.felix</groupId>
|
||||
<artifactId>maven-bundle-plugin</artifactId>
|
||||
<extensions>true</extensions>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>bundle-manifest</id>
|
||||
<phase>process-classes</phase>
|
||||
<goals>
|
||||
<goal>manifest</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<instructions>
|
||||
<Bundle-ClassPath>.</Bundle-ClassPath>
|
||||
<Bundle-Name>${project.name}</Bundle-Name>
|
||||
<Bundle-SymbolicName>${project.groupId}.${project.artifactId}</Bundle-SymbolicName>
|
||||
<Import-Package>${keycloak.osgi.import}</Import-Package>
|
||||
<Export-Package>${keycloak.osgi.export}</Export-Package>
|
||||
</instructions>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ import org.eclipse.jetty.security.authentication.FormAuthenticator;
|
|||
import org.eclipse.jetty.server.Request;
|
||||
import org.eclipse.jetty.util.MultiMap;
|
||||
import org.keycloak.adapters.KeycloakDeployment;
|
||||
import org.keycloak.adapters.jetty.core.AbstractJettySessionTokenStore;
|
||||
import org.keycloak.util.MultivaluedHashMap;
|
||||
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
|
|
@ -6,6 +6,7 @@ import org.eclipse.jetty.server.Request;
|
|||
import org.eclipse.jetty.server.UserIdentity;
|
||||
import org.keycloak.adapters.AdapterTokenStore;
|
||||
import org.keycloak.adapters.KeycloakDeployment;
|
||||
import org.keycloak.adapters.jetty.core.AbstractKeycloakJettyAuthenticator;
|
||||
|
||||
import javax.servlet.ServletRequest;
|
||||
|
||||
|
|
|
@ -13,6 +13,15 @@
|
|||
<name>Keycloak Jetty 9.1.x Integration</name>
|
||||
<properties>
|
||||
<jetty9.version>9.1.5.v20140505</jetty9.version>
|
||||
<keycloak.osgi.export>
|
||||
org.keycloak.adapters.jetty.*
|
||||
</keycloak.osgi.export>
|
||||
<keycloak.osgi.import>
|
||||
org.eclipse.jetty.*;version="[9.1,9.2)";resolution:=optional,
|
||||
javax.servlet.*;version="[3.0,4)";resolution:=optional,
|
||||
org.keycloak.*;version="${project.version}",
|
||||
*;resolution:=optional
|
||||
</keycloak.osgi.import>
|
||||
</properties>
|
||||
<description />
|
||||
|
||||
|
@ -113,6 +122,39 @@
|
|||
<target>1.6</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<!-- Adding OSGI metadata to the JAR without changing the packaging type. -->
|
||||
<plugin>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<configuration>
|
||||
<archive>
|
||||
<manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile>
|
||||
</archive>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.felix</groupId>
|
||||
<artifactId>maven-bundle-plugin</artifactId>
|
||||
<extensions>true</extensions>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>bundle-manifest</id>
|
||||
<phase>process-classes</phase>
|
||||
<goals>
|
||||
<goal>manifest</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<instructions>
|
||||
<Bundle-ClassPath>.</Bundle-ClassPath>
|
||||
<Bundle-Name>${project.name}</Bundle-Name>
|
||||
<Bundle-SymbolicName>${project.groupId}.${project.artifactId}</Bundle-SymbolicName>
|
||||
<Import-Package>${keycloak.osgi.import}</Import-Package>
|
||||
<Export-Package>${keycloak.osgi.export}</Export-Package>
|
||||
</instructions>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@ import org.eclipse.jetty.security.authentication.FormAuthenticator;
|
|||
import org.eclipse.jetty.server.Request;
|
||||
import org.eclipse.jetty.util.MultiMap;
|
||||
import org.keycloak.adapters.KeycloakDeployment;
|
||||
import org.keycloak.adapters.jetty.core.AbstractJettySessionTokenStore;
|
||||
import org.keycloak.util.MultivaluedHashMap;
|
||||
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
|
|
@ -6,6 +6,7 @@ import org.eclipse.jetty.server.Request;
|
|||
import org.eclipse.jetty.server.UserIdentity;
|
||||
import org.keycloak.adapters.AdapterTokenStore;
|
||||
import org.keycloak.adapters.KeycloakDeployment;
|
||||
import org.keycloak.adapters.jetty.core.AbstractKeycloakJettyAuthenticator;
|
||||
|
||||
import javax.servlet.ServletRequest;
|
||||
|
||||
|
|
|
@ -13,6 +13,15 @@
|
|||
<name>Keycloak Jetty 9.2.x Integration</name>
|
||||
<properties>
|
||||
<jetty9.version>9.2.4.v20141103</jetty9.version>
|
||||
<keycloak.osgi.export>
|
||||
org.keycloak.adapters.jetty.*
|
||||
</keycloak.osgi.export>
|
||||
<keycloak.osgi.import>
|
||||
org.eclipse.jetty.*;resolution:=optional,
|
||||
javax.servlet.*;version="[3.0,4)";resolution:=optional,
|
||||
org.keycloak.*;version="${project.version}",
|
||||
*;resolution:=optional
|
||||
</keycloak.osgi.import>
|
||||
</properties>
|
||||
<description />
|
||||
|
||||
|
@ -99,6 +108,39 @@
|
|||
<target>1.6</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<!-- Adding OSGI metadata to the JAR without changing the packaging type. -->
|
||||
<plugin>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<configuration>
|
||||
<archive>
|
||||
<manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile>
|
||||
</archive>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.felix</groupId>
|
||||
<artifactId>maven-bundle-plugin</artifactId>
|
||||
<extensions>true</extensions>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>bundle-manifest</id>
|
||||
<phase>process-classes</phase>
|
||||
<goals>
|
||||
<goal>manifest</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<instructions>
|
||||
<Bundle-ClassPath>.</Bundle-ClassPath>
|
||||
<Bundle-Name>${project.name}</Bundle-Name>
|
||||
<Bundle-SymbolicName>${project.groupId}.${project.artifactId}</Bundle-SymbolicName>
|
||||
<Import-Package>${keycloak.osgi.import}</Import-Package>
|
||||
<Export-Package>${keycloak.osgi.export}</Export-Package>
|
||||
</instructions>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
|
|
|
@ -5,10 +5,10 @@ import org.eclipse.jetty.security.authentication.FormAuthenticator;
|
|||
import org.eclipse.jetty.server.Request;
|
||||
import org.eclipse.jetty.util.MultiMap;
|
||||
import org.keycloak.adapters.KeycloakDeployment;
|
||||
import org.keycloak.adapters.jetty.core.AbstractJettySessionTokenStore;
|
||||
import org.keycloak.util.MultivaluedHashMap;
|
||||
|
||||
import javax.servlet.http.HttpSession;
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
|
|
|
@ -6,6 +6,7 @@ import org.eclipse.jetty.server.Request;
|
|||
import org.eclipse.jetty.server.UserIdentity;
|
||||
import org.keycloak.adapters.AdapterTokenStore;
|
||||
import org.keycloak.adapters.KeycloakDeployment;
|
||||
import org.keycloak.adapters.jetty.core.AbstractKeycloakJettyAuthenticator;
|
||||
|
||||
import javax.servlet.ServletRequest;
|
||||
|
||||
|
|
104
integration/osgi-adapter/pom.xml
Normal file
104
integration/osgi-adapter/pom.xml
Normal file
|
@ -0,0 +1,104 @@
|
|||
<?xml version="1.0"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>1.2.0.Beta1-SNAPSHOT</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>keycloak-osgi-adapter</artifactId>
|
||||
<name>Keycloak OSGI Adapter</name>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<properties>
|
||||
<jetty9.version>8.1.16.v20140903</jetty9.version>
|
||||
<keycloak.osgi.export>
|
||||
org.keycloak.adapters.osgi.*
|
||||
</keycloak.osgi.export>
|
||||
<keycloak.osgi.import>
|
||||
org.ops4j.pax.web.*;version="[3.0,4)",
|
||||
javax.servlet.*;version="[2.5,4)";resolution:=optional,
|
||||
org.eclipse.jetty.*;version="[8.1,10)";resolution:=optional,
|
||||
org.keycloak.*;version="${project.version}",
|
||||
*;resolution:=optional
|
||||
</keycloak.osgi.import>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.jboss.logging</groupId>
|
||||
<artifactId>jboss-logging</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.osgi</groupId>
|
||||
<artifactId>org.osgi.core</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.osgi</groupId>
|
||||
<artifactId>org.osgi.enterprise</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.ops4j.pax.web</groupId>
|
||||
<artifactId>pax-web-runtime</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-security</artifactId>
|
||||
<version>${jetty9.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<source>${maven.compiler.source}</source>
|
||||
<target>${maven.compiler.target}</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<!-- Adding OSGI metadata to the JAR without changing the packaging type. -->
|
||||
<plugin>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<configuration>
|
||||
<archive>
|
||||
<manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile>
|
||||
</archive>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.felix</groupId>
|
||||
<artifactId>maven-bundle-plugin</artifactId>
|
||||
<extensions>true</extensions>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>bundle-manifest</id>
|
||||
<phase>process-classes</phase>
|
||||
<goals>
|
||||
<goal>manifest</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<instructions>
|
||||
<Bundle-ClassPath>.</Bundle-ClassPath>
|
||||
<Bundle-Name>${project.name}</Bundle-Name>
|
||||
<Bundle-SymbolicName>${project.groupId}.${project.artifactId}</Bundle-SymbolicName>
|
||||
<Import-Package>${keycloak.osgi.import}</Import-Package>
|
||||
<Export-Package>${keycloak.osgi.export}</Export-Package>
|
||||
</instructions>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
|
@ -0,0 +1,163 @@
|
|||
package org.keycloak.adapters.osgi;
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
import org.eclipse.jetty.security.ConstraintMapping;
|
||||
import org.eclipse.jetty.util.security.Constraint;
|
||||
import org.jboss.logging.Logger;
|
||||
import org.ops4j.pax.web.service.WebContainer;
|
||||
import org.osgi.framework.BundleContext;
|
||||
import org.osgi.framework.ServiceReference;
|
||||
import org.osgi.service.http.HttpContext;
|
||||
import org.osgi.util.tracker.ServiceTracker;
|
||||
import org.osgi.util.tracker.ServiceTrackerCustomizer;
|
||||
|
||||
/**
|
||||
* Integration with pax-web, which allows to inject custom jetty-web.xml configuration from current bundle classpath into {@link WebContainer}
|
||||
* and allows to inject custom security constraint for securing resources by Keycloak.
|
||||
*
|
||||
* <p>It assumes that pax-web {@link WebContainer} is used as implementation of OSGI {@link org.osgi.service.http.HttpService}, which
|
||||
* is true in karaf/fuse environment</p>
|
||||
*
|
||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||
*/
|
||||
public class PaxWebIntegrationService {
|
||||
|
||||
protected static final Logger log = Logger.getLogger(PaxWebIntegrationService.class);
|
||||
|
||||
private BundleContext bundleContext;
|
||||
private String jettyWebXmlLocation;
|
||||
private List<ConstraintMapping> constraintMappings; // Using jetty constraint mapping just because of compatibility with other fuse services
|
||||
|
||||
private ServiceTracker webContainerTracker;
|
||||
private HttpContext httpContext;
|
||||
|
||||
public BundleContext getBundleContext() {
|
||||
return bundleContext;
|
||||
}
|
||||
|
||||
public void setBundleContext(BundleContext bundleContext) {
|
||||
this.bundleContext = bundleContext;
|
||||
}
|
||||
|
||||
public String getJettyWebXmlLocation() {
|
||||
return jettyWebXmlLocation;
|
||||
}
|
||||
|
||||
public void setJettyWebXmlLocation(String jettyWebXmlLocation) {
|
||||
this.jettyWebXmlLocation = jettyWebXmlLocation;
|
||||
}
|
||||
|
||||
public List<ConstraintMapping> getConstraintMappings() {
|
||||
return constraintMappings;
|
||||
}
|
||||
|
||||
public void setConstraintMappings(List<ConstraintMapping> constraintMappings) {
|
||||
this.constraintMappings = constraintMappings;
|
||||
}
|
||||
|
||||
protected ServiceTracker getWebContainerTracker() {
|
||||
return webContainerTracker;
|
||||
}
|
||||
|
||||
protected HttpContext getHttpContext() {
|
||||
return httpContext;
|
||||
}
|
||||
|
||||
|
||||
public void start() {
|
||||
ServiceTrackerCustomizer trackerCustomizer = new ServiceTrackerCustomizer() {
|
||||
|
||||
@Override
|
||||
public Object addingService(ServiceReference reference) {
|
||||
return addingWebContainerCallback(reference);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void modifiedService(ServiceReference reference, Object service) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removedService(ServiceReference reference, Object service) {
|
||||
removingWebContainerCallback(reference);
|
||||
}
|
||||
};
|
||||
|
||||
webContainerTracker = new ServiceTracker(bundleContext, WebContainer.class.getName(), trackerCustomizer);
|
||||
webContainerTracker.open();
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
webContainerTracker.remove(webContainerTracker.getServiceReference());
|
||||
}
|
||||
|
||||
protected WebContainer addingWebContainerCallback(ServiceReference webContainerServiceReference) {
|
||||
WebContainer service = (WebContainer) bundleContext.getService(webContainerServiceReference);
|
||||
httpContext = service.createDefaultHttpContext();
|
||||
|
||||
addJettyWebXml(service);
|
||||
|
||||
if (constraintMappings == null) {
|
||||
throw new IllegalStateException("constraintMappings was null!");
|
||||
}
|
||||
for (ConstraintMapping constraintMapping : constraintMappings) {
|
||||
addConstraintMapping(service, constraintMapping);
|
||||
}
|
||||
|
||||
service.registerLoginConfig("BASIC", "does-not-matter", null, null, httpContext);
|
||||
|
||||
return service;
|
||||
}
|
||||
|
||||
protected void addJettyWebXml(WebContainer service) {
|
||||
String jettyWebXmlLoc;
|
||||
if (this.jettyWebXmlLocation == null) {
|
||||
jettyWebXmlLoc = "/WEB-INF/jetty-web.xml";
|
||||
} else {
|
||||
jettyWebXmlLoc = this.jettyWebXmlLocation;
|
||||
}
|
||||
|
||||
URL jettyWebXml = bundleContext.getBundle().getResource(jettyWebXmlLoc);
|
||||
if (jettyWebXml != null) {
|
||||
log.debug("Found jetty-web XML configuration on bundle classpath on " + jettyWebXmlLoc);
|
||||
service.registerJettyWebXml(jettyWebXml, httpContext);
|
||||
} else {
|
||||
log.debug("Not found jetty-web XML configuration on bundle classpath on " + jettyWebXmlLoc);
|
||||
}
|
||||
}
|
||||
|
||||
protected void addConstraintMapping(WebContainer service, ConstraintMapping constraintMapping) {
|
||||
Constraint constraint = constraintMapping.getConstraint();
|
||||
String[] roles = constraint.getRoles();
|
||||
// name property is unavailable on constraint object :/
|
||||
String name = "Constraint-" + new Random().nextInt();
|
||||
|
||||
int dataConstraint = constraint.getDataConstraint();
|
||||
String dataConstraintStr;
|
||||
switch (dataConstraint) {
|
||||
case Constraint.DC_UNSET: dataConstraintStr = null; break;
|
||||
case Constraint.DC_NONE: dataConstraintStr = "NONE"; break;
|
||||
case Constraint.DC_CONFIDENTIAL: dataConstraintStr = "CONFIDENTIAL"; break;
|
||||
case Constraint.DC_INTEGRAL: dataConstraintStr = "INTEGRAL"; break;
|
||||
default:
|
||||
log.warnv("Unknown data constraint: " + dataConstraint);
|
||||
dataConstraintStr = "CONFIDENTIAL";
|
||||
}
|
||||
List<String> rolesList = Arrays.asList(roles);
|
||||
|
||||
log.debug("Adding security constraint name=" + name + ", url=" + constraintMapping.getPathSpec() + ", dataConstraint=" + dataConstraintStr + ", canAuthenticate="
|
||||
+ constraint.getAuthenticate() + ", roles=" + rolesList);
|
||||
service.registerConstraintMapping(name, constraintMapping.getPathSpec(), null, dataConstraintStr, constraint.getAuthenticate(), rolesList, httpContext);
|
||||
}
|
||||
|
||||
protected void removingWebContainerCallback(ServiceReference serviceReference) {
|
||||
WebContainer service = (WebContainer)bundleContext.getService(serviceReference);
|
||||
if (service != null) {
|
||||
service.unregisterLoginConfig(httpContext);
|
||||
service.unregisterConstraintMapping(httpContext);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,100 @@
|
|||
package org.keycloak.adapters.osgi;
|
||||
|
||||
import java.util.Hashtable;
|
||||
|
||||
import javax.servlet.Servlet;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
import org.ops4j.pax.web.service.WebContainer;
|
||||
import org.osgi.framework.BundleContext;
|
||||
import org.osgi.framework.ServiceReference;
|
||||
import org.osgi.service.http.HttpContext;
|
||||
|
||||
/**
|
||||
* Service, which allows to remove previously registered servlets in karaf/fuse environment. It assumes that particular servlet was previously
|
||||
* registered as service in OSGI container under {@link javax.servlet.Servlet} interface.
|
||||
*
|
||||
* <p>The point is to register automatically registered builtin servlet endpoints (like "/cxf" for instance) to allow secure them
|
||||
* by Keycloak and re-register them again</p>
|
||||
*
|
||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||
*/
|
||||
public class ServletUnregistrationService {
|
||||
|
||||
protected static final Logger log = Logger.getLogger(ServletUnregistrationService.class);
|
||||
|
||||
private BundleContext bundleContext;
|
||||
private ServiceReference servletReference;
|
||||
|
||||
public BundleContext getBundleContext() {
|
||||
return bundleContext;
|
||||
}
|
||||
|
||||
public void setBundleContext(BundleContext bundleContext) {
|
||||
this.bundleContext = bundleContext;
|
||||
}
|
||||
|
||||
public ServiceReference getServletReference() {
|
||||
return servletReference;
|
||||
}
|
||||
|
||||
public void setServletReference(ServiceReference servletReference) {
|
||||
this.servletReference = servletReference;
|
||||
}
|
||||
|
||||
// TODO: Re-register original servlet back during stop?
|
||||
public void start() {
|
||||
if (servletReference == null) {
|
||||
throw new IllegalStateException("No servlet reference provided");
|
||||
}
|
||||
|
||||
Servlet servlet = (Servlet) bundleContext.getService(servletReference);
|
||||
WebContainer webContainer = findWebContainer(servletReference);
|
||||
if (webContainer == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Unregister servlet now
|
||||
try {
|
||||
webContainer.unregisterServlet(servlet);
|
||||
log.debugv("Original servlet with alias " + servletReference.getProperty("alias") + " unregistered successfully.");
|
||||
} catch (IllegalStateException e) {
|
||||
log.warnv("Can't unregister servlet due to: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
try {
|
||||
Servlet servlet = (Servlet) bundleContext.getService(servletReference);
|
||||
WebContainer webContainer = findWebContainer(servletReference);
|
||||
if (webContainer == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Hashtable<String, Object> servletInitParams = new Hashtable<String, Object>();
|
||||
String[] propNames = servletReference.getPropertyKeys();
|
||||
for (String propName : propNames) {
|
||||
servletInitParams.put(propName, servletReference.getProperty(propName));
|
||||
}
|
||||
|
||||
// Try to register original servlet back
|
||||
HttpContext httpContext = webContainer.createDefaultHttpContext();
|
||||
String alias = (String) servletReference.getProperty("alias");
|
||||
webContainer.registerServlet(alias, servlet, servletInitParams, httpContext);
|
||||
} catch (Exception e) {
|
||||
log.warn("Can't register original servlet back", e);
|
||||
}
|
||||
}
|
||||
|
||||
protected WebContainer findWebContainer(ServiceReference servletRef) {
|
||||
BundleContext servletBundleContext = servletRef.getBundle().getBundleContext();
|
||||
ServiceReference webContainerReference = servletBundleContext.getServiceReference(WebContainer.class.getName());
|
||||
if (webContainerReference == null) {
|
||||
log.warn("Not found webContainer reference for bundle " + servletBundleContext);
|
||||
return null;
|
||||
} else {
|
||||
return (WebContainer) servletBundleContext.getService(webContainerReference);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -28,5 +28,6 @@
|
|||
<module>js</module>
|
||||
<module>installed</module>
|
||||
<module>admin-client</module>
|
||||
<module>osgi-adapter</module>
|
||||
</modules>
|
||||
</project>
|
||||
|
|
20
pom.xml
20
pom.xml
|
@ -13,6 +13,7 @@
|
|||
|
||||
<properties>
|
||||
<aesh.version>0.33.12</aesh.version>
|
||||
<base64.version>2.3.8</base64.version>
|
||||
<bouncycastle.version>1.46</bouncycastle.version>
|
||||
<jackson.version>1.9.9</jackson.version>
|
||||
<keycloak.apache.httpcomponents.version>4.2.1</keycloak.apache.httpcomponents.version>
|
||||
|
@ -48,6 +49,8 @@
|
|||
<infinispan.version>6.0.2.Final</infinispan.version>
|
||||
<liquibase.version>3.2.2</liquibase.version>
|
||||
<jetty9.version>9.1.0.v20131115</jetty9.version>
|
||||
<osgi.version>4.2.0</osgi.version>
|
||||
<pax.web.version>3.1.2</pax.web.version>
|
||||
|
||||
<!-- maven-compiler-plugin -->
|
||||
<maven.compiler.target>1.6</maven.compiler.target>
|
||||
|
@ -139,7 +142,7 @@
|
|||
<dependency>
|
||||
<groupId>net.iharder</groupId>
|
||||
<artifactId>base64</artifactId>
|
||||
<version>2.3.8</version>
|
||||
<version>${base64.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.mail</groupId>
|
||||
|
@ -508,6 +511,21 @@
|
|||
<artifactId>liquibase-core</artifactId>
|
||||
<version>${liquibase.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.osgi</groupId>
|
||||
<artifactId>org.osgi.core</artifactId>
|
||||
<version>${osgi.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.osgi</groupId>
|
||||
<artifactId>org.osgi.enterprise</artifactId>
|
||||
<version>${osgi.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.ops4j.pax.web</groupId>
|
||||
<artifactId>pax-web-runtime</artifactId>
|
||||
<version>${pax.web.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
|
|
|
@ -316,8 +316,8 @@ public class JaxrsFilterTest {
|
|||
|
||||
// @Test
|
||||
public void testCxfExample() {
|
||||
String uri = "http://localhost:9000/customerservice/customers/123";
|
||||
//String uri = "http://localhost:8080/jax_rs_basic_servlet/services/service1/customerservice/customers/123";
|
||||
//String uri = "http://localhost:9000/customerservice/customers/123";
|
||||
String uri = "http://localhost:8080/jax_rs_basic_servlet/services/service1/customerservice/customers/123";
|
||||
Response resp = client.target(uri).request()
|
||||
.get();
|
||||
Assert.assertEquals(resp.getStatus(), 401);
|
||||
|
|
|
@ -21,49 +21,23 @@
|
|||
*/
|
||||
package org.keycloak.testsuite;
|
||||
|
||||
import org.eclipse.jetty.security.ConstraintMapping;
|
||||
import org.eclipse.jetty.security.ConstraintSecurityHandler;
|
||||
import org.eclipse.jetty.security.HashLoginService;
|
||||
import org.eclipse.jetty.server.Handler;
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.server.handler.HandlerCollection;
|
||||
import org.eclipse.jetty.servlet.ServletHolder;
|
||||
import org.eclipse.jetty.util.security.Constraint;
|
||||
import org.eclipse.jetty.webapp.WebAppContext;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Assert;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.ClassRule;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.keycloak.KeycloakSecurityContext;
|
||||
import org.keycloak.OAuth2Constants;
|
||||
import org.keycloak.adapters.jetty.AbstractKeycloakJettyAuthenticator;
|
||||
import org.keycloak.adapters.jetty.KeycloakJettyAuthenticator;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.protocol.oidc.OpenIDConnectService;
|
||||
import org.keycloak.representations.idm.RealmRepresentation;
|
||||
import org.keycloak.services.managers.RealmManager;
|
||||
import org.keycloak.testsuite.adapter.AdapterTestStrategy;
|
||||
import org.keycloak.testsuite.pages.LoginPage;
|
||||
import org.keycloak.testsuite.rule.AbstractKeycloakRule;
|
||||
import org.keycloak.testsuite.rule.WebResource;
|
||||
import org.keycloak.testsuite.rule.WebRule;
|
||||
import org.keycloak.testutils.KeycloakServer;
|
||||
import org.openqa.selenium.WebDriver;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.ws.rs.core.UriBuilder;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.net.URL;
|
||||
import java.security.Principal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
|
|
|
@ -21,49 +21,23 @@
|
|||
*/
|
||||
package org.keycloak.testsuite;
|
||||
|
||||
import org.eclipse.jetty.security.ConstraintMapping;
|
||||
import org.eclipse.jetty.security.ConstraintSecurityHandler;
|
||||
import org.eclipse.jetty.security.HashLoginService;
|
||||
import org.eclipse.jetty.server.Handler;
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.server.handler.HandlerCollection;
|
||||
import org.eclipse.jetty.servlet.ServletHolder;
|
||||
import org.eclipse.jetty.util.security.Constraint;
|
||||
import org.eclipse.jetty.webapp.WebAppContext;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Assert;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.ClassRule;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.keycloak.KeycloakSecurityContext;
|
||||
import org.keycloak.OAuth2Constants;
|
||||
import org.keycloak.adapters.jetty.AbstractKeycloakJettyAuthenticator;
|
||||
import org.keycloak.adapters.jetty.KeycloakJettyAuthenticator;
|
||||
import org.keycloak.models.KeycloakSession;
|
||||
import org.keycloak.models.RealmModel;
|
||||
import org.keycloak.protocol.oidc.OpenIDConnectService;
|
||||
import org.keycloak.representations.idm.RealmRepresentation;
|
||||
import org.keycloak.services.managers.RealmManager;
|
||||
import org.keycloak.testsuite.adapter.AdapterTestStrategy;
|
||||
import org.keycloak.testsuite.pages.LoginPage;
|
||||
import org.keycloak.testsuite.rule.AbstractKeycloakRule;
|
||||
import org.keycloak.testsuite.rule.WebResource;
|
||||
import org.keycloak.testsuite.rule.WebRule;
|
||||
import org.keycloak.testutils.KeycloakServer;
|
||||
import org.openqa.selenium.WebDriver;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.ws.rs.core.UriBuilder;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.net.URL;
|
||||
import java.security.Principal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
|
|
Loading…
Reference in a new issue