From d928c26e27187e38898fca90bee3c2460aaf96a9 Mon Sep 17 00:00:00 2001 From: mposolda Date: Tue, 6 Jan 2015 18:04:47 +0100 Subject: [PATCH] KEYCLOAK-539 Fuse adapter. OSGI bundling. OSGI headers in keycloak adapter maven artifacts. Rename package in jetty-core --- core/pom.xml | 41 +++++ distribution/examples-docs-zip/build.xml | 6 + .../features/src/main/resources/features.xml | 46 ++++- distribution/osgi/jaas/pom.xml | 4 +- distribution/osgi/pom.xml | 2 +- .../osgi/{core-adapter => thirdparty}/pom.xml | 53 ++---- .../src/main/resources/.gitignore | 0 examples/fuse/README.md | 33 ++++ examples/fuse/camel/pom.xml | 79 +++++++++ .../org/keycloak/example/CamelHelloBean.java | 15 ++ .../OSGI-INF/blueprint/blueprint.xml | 67 +++++++ examples/fuse/customer-app-fuse/pom.xml | 121 +++++++++++++ .../org/keycloak/example/CamelClient.java | 74 ++++++++ .../org/keycloak/example/CxfRsClient.java | 75 ++++++++ .../src/main/webapp/WEB-INF/jetty-web.xml | 10 ++ .../src/main/webapp/WEB-INF/keycloak.json | 10 ++ .../src/main/webapp/WEB-INF/web.xml | 34 ++++ .../src/main/webapp/customers/camel.jsp | 15 ++ .../src/main/webapp/customers/cxf-ws.jsp | 50 ++++++ .../src/main/webapp/index.html | 15 ++ examples/fuse/cxf-jaxrs/pom.xml | 86 +++++++++ .../example/rs/CxfCustomerService.java | 30 ++++ .../OSGI-INF/blueprint/blueprint.xml | 106 ++++++++++++ .../src/main/resources/WEB-INF/jetty-web.xml | 10 ++ .../src/main/resources/WEB-INF/keycloak.json | 10 ++ examples/fuse/cxf-jaxws/pom.xml | 107 ++++++++++++ .../java/org/keycloak/example/ws/Person.java | 27 +++ .../org/keycloak/example/ws/PersonImpl.java | 22 +++ .../example/ws/UnknownPersonFault.java | 36 ++++ .../keycloak/example/ws/types/GetPerson.java | 64 +++++++ .../example/ws/types/GetPersonResponse.java | 120 +++++++++++++ .../example/ws/types/ObjectFactory.java | 56 ++++++ .../example/ws/types/UnknownPersonFault.java | 64 +++++++ .../example/ws/types/package-info.java | 1 + .../main/resources/META-INF/spring/beans.xml | 69 ++++++++ examples/fuse/features/pom.xml | 62 +++++++ .../features/src/main/resources/features.xml | 19 ++ examples/fuse/pom.xml | 37 ++++ examples/fuse/product-app-fuse/pom.xml | 83 +++++++++ .../example/ProductPortalServlet.java | 95 ++++++++++ .../OSGI-INF/blueprint/blueprint.xml | 45 +++++ .../src/main/resources/WEB-INF/jetty-web.xml | 10 ++ .../src/main/resources/WEB-INF/keycloak.json | 10 ++ examples/fuse/testrealm.json | 137 +++++++++++++++ examples/pom.xml | 1 + integration/adapter-core/pom.xml | 44 +++++ integration/jaxrs-oauth-client/pom.xml | 1 - integration/jetty/jetty-core/pom.xml | 42 +++++ .../AbstractJettySessionTokenStore.java | 5 +- .../AbstractKeycloakJettyAuthenticator.java | 18 +- .../{ => core}/JettyCookieTokenStore.java | 2 +- .../jetty/{ => core}/JettyHttpFacade.java | 2 +- .../{ => core}/JettyRequestAuthenticator.java | 2 +- .../JettyUserSessionManagement.java | 2 +- .../jetty/core/WrappingSessionHandler.java | 30 ++++ integration/jetty/jetty8.1/pom.xml | 41 +++++ .../jetty/JettySessionTokenStore.java | 1 + .../jetty/KeycloakJettyAuthenticator.java | 1 + integration/jetty/jetty9.1/pom.xml | 42 +++++ .../jetty/JettySessionTokenStore.java | 1 + .../jetty/KeycloakJettyAuthenticator.java | 1 + integration/jetty/jetty9.2/pom.xml | 42 +++++ .../jetty/JettySessionTokenStore.java | 2 +- .../jetty/KeycloakJettyAuthenticator.java | 1 + integration/osgi-adapter/pom.xml | 104 +++++++++++ .../osgi/PaxWebIntegrationService.java | 163 ++++++++++++++++++ .../osgi/ServletUnregistrationService.java | 100 +++++++++++ integration/pom.xml | 1 + pom.xml | 20 ++- .../testsuite/jaxrs/JaxrsFilterTest.java | 4 +- .../org/keycloak/testsuite/Jetty9Test.java | 26 --- .../org/keycloak/testsuite/Jetty9Test.java | 26 --- 72 files changed, 2666 insertions(+), 115 deletions(-) rename distribution/osgi/{core-adapter => thirdparty}/pom.xml (62%) mode change 100755 => 100644 rename distribution/osgi/{core-adapter => thirdparty}/src/main/resources/.gitignore (100%) create mode 100644 examples/fuse/README.md create mode 100644 examples/fuse/camel/pom.xml create mode 100644 examples/fuse/camel/src/main/java/org/keycloak/example/CamelHelloBean.java create mode 100644 examples/fuse/camel/src/main/resources/OSGI-INF/blueprint/blueprint.xml create mode 100644 examples/fuse/customer-app-fuse/pom.xml create mode 100644 examples/fuse/customer-app-fuse/src/main/java/org/keycloak/example/CamelClient.java create mode 100644 examples/fuse/customer-app-fuse/src/main/java/org/keycloak/example/CxfRsClient.java create mode 100644 examples/fuse/customer-app-fuse/src/main/webapp/WEB-INF/jetty-web.xml create mode 100755 examples/fuse/customer-app-fuse/src/main/webapp/WEB-INF/keycloak.json create mode 100755 examples/fuse/customer-app-fuse/src/main/webapp/WEB-INF/web.xml create mode 100755 examples/fuse/customer-app-fuse/src/main/webapp/customers/camel.jsp create mode 100755 examples/fuse/customer-app-fuse/src/main/webapp/customers/cxf-ws.jsp create mode 100755 examples/fuse/customer-app-fuse/src/main/webapp/index.html create mode 100644 examples/fuse/cxf-jaxrs/pom.xml create mode 100644 examples/fuse/cxf-jaxrs/src/main/java/org/keycloak/example/rs/CxfCustomerService.java create mode 100644 examples/fuse/cxf-jaxrs/src/main/resources/OSGI-INF/blueprint/blueprint.xml create mode 100644 examples/fuse/cxf-jaxrs/src/main/resources/WEB-INF/jetty-web.xml create mode 100644 examples/fuse/cxf-jaxrs/src/main/resources/WEB-INF/keycloak.json create mode 100644 examples/fuse/cxf-jaxws/pom.xml create mode 100644 examples/fuse/cxf-jaxws/src/main/java/org/keycloak/example/ws/Person.java create mode 100644 examples/fuse/cxf-jaxws/src/main/java/org/keycloak/example/ws/PersonImpl.java create mode 100644 examples/fuse/cxf-jaxws/src/main/java/org/keycloak/example/ws/UnknownPersonFault.java create mode 100644 examples/fuse/cxf-jaxws/src/main/java/org/keycloak/example/ws/types/GetPerson.java create mode 100644 examples/fuse/cxf-jaxws/src/main/java/org/keycloak/example/ws/types/GetPersonResponse.java create mode 100644 examples/fuse/cxf-jaxws/src/main/java/org/keycloak/example/ws/types/ObjectFactory.java create mode 100644 examples/fuse/cxf-jaxws/src/main/java/org/keycloak/example/ws/types/UnknownPersonFault.java create mode 100644 examples/fuse/cxf-jaxws/src/main/java/org/keycloak/example/ws/types/package-info.java create mode 100644 examples/fuse/cxf-jaxws/src/main/resources/META-INF/spring/beans.xml create mode 100644 examples/fuse/features/pom.xml create mode 100644 examples/fuse/features/src/main/resources/features.xml create mode 100644 examples/fuse/pom.xml create mode 100644 examples/fuse/product-app-fuse/pom.xml create mode 100644 examples/fuse/product-app-fuse/src/main/java/org/keycloak/example/ProductPortalServlet.java create mode 100644 examples/fuse/product-app-fuse/src/main/resources/OSGI-INF/blueprint/blueprint.xml create mode 100644 examples/fuse/product-app-fuse/src/main/resources/WEB-INF/jetty-web.xml create mode 100644 examples/fuse/product-app-fuse/src/main/resources/WEB-INF/keycloak.json create mode 100644 examples/fuse/testrealm.json rename integration/jetty/jetty-core/src/main/java/org/keycloak/adapters/jetty/{ => core}/AbstractJettySessionTokenStore.java (93%) rename integration/jetty/jetty-core/src/main/java/org/keycloak/adapters/jetty/{ => core}/AbstractKeycloakJettyAuthenticator.java (93%) rename integration/jetty/jetty-core/src/main/java/org/keycloak/adapters/jetty/{ => core}/JettyCookieTokenStore.java (98%) rename integration/jetty/jetty-core/src/main/java/org/keycloak/adapters/jetty/{ => core}/JettyHttpFacade.java (96%) rename integration/jetty/jetty-core/src/main/java/org/keycloak/adapters/jetty/{ => core}/JettyRequestAuthenticator.java (96%) rename integration/jetty/jetty-core/src/main/java/org/keycloak/adapters/jetty/{ => core}/JettyUserSessionManagement.java (93%) create mode 100644 integration/jetty/jetty-core/src/main/java/org/keycloak/adapters/jetty/core/WrappingSessionHandler.java create mode 100644 integration/osgi-adapter/pom.xml create mode 100644 integration/osgi-adapter/src/main/java/org/keycloak/adapters/osgi/PaxWebIntegrationService.java create mode 100644 integration/osgi-adapter/src/main/java/org/keycloak/adapters/osgi/ServletUnregistrationService.java diff --git a/core/pom.xml b/core/pom.xml index 99a102e094..fb19e6c46c 100755 --- a/core/pom.xml +++ b/core/pom.xml @@ -11,11 +11,19 @@ keycloak-core Keycloak Core + jar ${maven.build.timestamp} yyyy-MM-dd HH:mm + + org.keycloak.* + + + net.iharder;version=${base64.version}, + *;resolution:=optional + @@ -60,6 +68,39 @@ ${maven.compiler.target} + + + + maven-jar-plugin + + + ${project.build.outputDirectory}/META-INF/MANIFEST.MF + + + + + org.apache.felix + maven-bundle-plugin + true + + + bundle-manifest + process-classes + + manifest + + + + + + . + ${project.name} + ${project.groupId}.${project.artifactId} + ${keycloak.osgi.import} + ${keycloak.osgi.export} + + + diff --git a/distribution/examples-docs-zip/build.xml b/distribution/examples-docs-zip/build.xml index 503dc8e4d8..37251609e6 100755 --- a/distribution/examples-docs-zip/build.xml +++ b/distribution/examples-docs-zip/build.xml @@ -93,6 +93,12 @@ + + + + + + diff --git a/distribution/osgi/features/src/main/resources/features.xml b/distribution/osgi/features/src/main/resources/features.xml index f72ac8d6b3..d56602b95b 100644 --- a/distribution/osgi/features/src/main/resources/features.xml +++ b/distribution/osgi/features/src/main/resources/features.xml @@ -1,15 +1,53 @@ - -
The keycloak core adapter stuff
- mvn:org.keycloak/keycloak-osgi-core-adapter/${project.version} + +
The keycloak adapter core stuff
+ mvn:org.keycloak/keycloak-osgi-thirdparty/${project.version} + mvn:org.bouncycastle/bcprov-jdk16/${bouncycastle.version} + mvn:org.codehaus.jackson/jackson-core-asl/${jackson.version} + mvn:org.codehaus.jackson/jackson-mapper-asl/${jackson.version} + mvn:org.codehaus.jackson/jackson-xc/${jackson.version} + mvn:org.jboss.logging/jboss-logging/${jboss.logging.version} + mvn:org.keycloak/keycloak-core/${project.version} + mvn:org.keycloak/keycloak-adapter-core/${project.version} +
+ + +
The keycloak adapter core stuff
+ keycloak-adapter-core + http-whiteboard + mvn:org.keycloak/keycloak-osgi-adapter/${project.version} +
+ + +
The keycloak Jetty8 adapter
+ keycloak-adapter-core + jetty + mvn:org.keycloak/keycloak-jetty-core/${project.version} + mvn:org.keycloak/keycloak-jetty81-adapter/${project.version}
The keycloak JAAS configuration
- keycloak-core-adapter + keycloak-adapter-core mvn:org.keycloak/keycloak-osgi-jaas/${project.version}
+ +
The keycloak adapter core stuff
+ keycloak-osgi-adapter + keycloak-jetty8-adapter + keycloak-jaas +
+ + + +
This is just simplification to upgrade paxweb to 3.1.2 in JBoss Fuse 6.1 or Karaf 2.3.X environment
+ mvn:org.ow2.asm/asm-all/5.0 + mvn:org.apache.xbean/xbean-bundleutils/3.18 + mvn:org.apache.xbean/xbean-reflect/3.18 + mvn:org.apache.xbean/xbean-finder/3.18 +
+
\ No newline at end of file diff --git a/distribution/osgi/jaas/pom.xml b/distribution/osgi/jaas/pom.xml index 8604f657ea..1c9f177227 100755 --- a/distribution/osgi/jaas/pom.xml +++ b/distribution/osgi/jaas/pom.xml @@ -7,7 +7,7 @@ 1.2.0.Beta1-SNAPSHOT ../../../pom.xml - Keycloak OSGI JAAS + Keycloak OSGI JAAS Realm Configuration 4.0.0 @@ -53,7 +53,7 @@ *;scope=compile|runtime false . --> - ${project.description} + ${project.name} ${project.groupId}.${project.artifactId} ${keycloak.osgi.import} ${keycloak.osgi.export} diff --git a/distribution/osgi/pom.xml b/distribution/osgi/pom.xml index a2e1e834ff..eb6f64dfc1 100755 --- a/distribution/osgi/pom.xml +++ b/distribution/osgi/pom.xml @@ -17,7 +17,7 @@ features jaas - core-adapter + thirdparty \ No newline at end of file diff --git a/distribution/osgi/core-adapter/pom.xml b/distribution/osgi/thirdparty/pom.xml old mode 100755 new mode 100644 similarity index 62% rename from distribution/osgi/core-adapter/pom.xml rename to distribution/osgi/thirdparty/pom.xml index 124bf82daf..6e8c8377cf --- a/distribution/osgi/core-adapter/pom.xml +++ b/distribution/osgi/thirdparty/pom.xml @@ -7,17 +7,18 @@ 1.2.0.Beta1-SNAPSHOT ../../../pom.xml - Keycloak OSGI Core Adapter Integration - + + Keycloak OSGI Thirdparty + Keycloak OSGI bundling for 3rd party libs without OSGI headers in manifest 4.0.0 - keycloak-osgi-core-adapter + keycloak-osgi-thirdparty bundle - org.keycloak.adapters.jaas, - org.keycloak.adapters + net.iharder;version="${base64.version}", + org.apache.http.*;version=${keycloak.apache.httpcomponents.version} *;resolution:=optional @@ -26,45 +27,19 @@ - org.keycloak - keycloak-core - ${project.version} + net.iharder + base64 - org.keycloak - keycloak-adapter-core - ${project.version} - - - - org.jboss.logging - jboss-logging + org.apache.httpcomponents + httpcore + ${keycloak.apache.httpcomponents.version} org.apache.httpcomponents httpclient ${keycloak.apache.httpcomponents.version} - - net.iharder - base64 - - - org.bouncycastle - bcprov-jdk16 - - - org.codehaus.jackson - jackson-core-asl - - - org.codehaus.jackson - jackson-mapper-asl - - - org.codehaus.jackson - jackson-xc - @@ -84,14 +59,14 @@ - *;scope=compile|runtime;artifactId=!keycloak-adapter-core + *;scope=compile|runtime;artifactId=!httpclient|httpcore|base64 true . - ${project.description} + ${project.name} ${project.groupId}.${project.artifactId} ${keycloak.osgi.import} ${keycloak.osgi.export} - keycloak + ${project.name} ${project.version} diff --git a/distribution/osgi/core-adapter/src/main/resources/.gitignore b/distribution/osgi/thirdparty/src/main/resources/.gitignore similarity index 100% rename from distribution/osgi/core-adapter/src/main/resources/.gitignore rename to distribution/osgi/thirdparty/src/main/resources/.gitignore diff --git a/examples/fuse/README.md b/examples/fuse/README.md new file mode 100644 index 0000000000..20593e26d5 --- /dev/null +++ b/examples/fuse/README.md @@ -0,0 +1,33 @@ +1) First step is to run Keycloak server on localhost:8080 and import realm "demo" from the file testrealm.json in this directory (Directory "fuse"). + +Running example on Karaf 3.0.2 +------------------------------ + +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 + +Running example on JBoss Fuse 6.1.0.redhat-379 +---------------------------------------------- + +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 + diff --git a/examples/fuse/camel/pom.xml b/examples/fuse/camel/pom.xml new file mode 100644 index 0000000000..2909e427b2 --- /dev/null +++ b/examples/fuse/camel/pom.xml @@ -0,0 +1,79 @@ + + + + keycloak-parent + org.keycloak + 1.1.0.Final-SNAPSHOT + ../../../pom.xml + + 4.0.0 + org.keycloak.example.demo + camel-endpoint-example + bundle + Camel endpoint example - Secured in Karaf/Fuse + + + + 2.12.5 + + + + org.eclipse.jetty.security;version="[8.1,10)", + org.eclipse.jetty.util.security;version="[8.1,10)", + org.keycloak.*;version="${project.version}", + *;resolution:=optional + + + org.keycloak.example.* + + + + + + org.apache.camel + camel-core + ${camel.version} + + + org.apache.camel + camel-blueprint + ${camel.version} + + org.apache.camel + camel-jetty + ${camel.version} + + + + + install + + + + org.apache.maven.plugins + maven-compiler-plugin + + ${maven.compiler.source} + ${maven.compiler.target} + + + + org.apache.felix + maven-bundle-plugin + true + + + ${project.name} + ${project.groupId}.${project.artifactId} + ${keycloak.osgi.import} + ${keycloak.osgi.private} + ${keycloak.osgi.export} + + + + + + + + diff --git a/examples/fuse/camel/src/main/java/org/keycloak/example/CamelHelloBean.java b/examples/fuse/camel/src/main/java/org/keycloak/example/CamelHelloBean.java new file mode 100644 index 0000000000..df5c472e68 --- /dev/null +++ b/examples/fuse/camel/src/main/java/org/keycloak/example/CamelHelloBean.java @@ -0,0 +1,15 @@ +package org.keycloak.example; + +import java.text.SimpleDateFormat; +import java.util.Date; + +/** + * @author Marek Posolda + */ +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()); + } +} diff --git a/examples/fuse/camel/src/main/resources/OSGI-INF/blueprint/blueprint.xml b/examples/fuse/camel/src/main/resources/OSGI-INF/blueprint/blueprint.xml new file mode 100644 index 0000000000..0dc0fdd1e4 --- /dev/null +++ b/examples/fuse/camel/src/main/resources/OSGI-INF/blueprint/blueprint.xml @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + + + + admin + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/examples/fuse/customer-app-fuse/pom.xml b/examples/fuse/customer-app-fuse/pom.xml new file mode 100644 index 0000000000..cd5e4dc9b9 --- /dev/null +++ b/examples/fuse/customer-app-fuse/pom.xml @@ -0,0 +1,121 @@ + + + + keycloak-parent + org.keycloak + 1.1.0.Final-SNAPSHOT + ../../../pom.xml + + 4.0.0 + org.keycloak.example.demo + customer-portal-fuse-example + war + Customer Portal - Secured in Karaf/Fuse + + + + + + + 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 + + + org.keycloak.example.* + + + + + + org.jboss.spec.javax.servlet + jboss-servlet-api_3.0_spec + provided + + + org.keycloak + keycloak-core + ${project.version} + provided + + + org.keycloak + keycloak-adapter-core + ${project.version} + provided + + + org.apache.httpcomponents + httpclient + ${keycloak.apache.httpcomponents.version} + provided + + + + + customer-portal-fuse + + + org.apache.maven.plugins + maven-deploy-plugin + + true + + + + org.apache.maven.plugins + maven-compiler-plugin + + ${maven.compiler.source} + ${maven.compiler.target} + + + + org.apache.maven.plugins + maven-war-plugin + + + ${basedir}/target/classes/META-INF/MANIFEST.MF + + + + + + org.apache.felix + maven-bundle-plugin + true + + + bundle-manifest + process-classes + + manifest + + + + + + war + + + customer-portal + customer-portal + WEB-INF/lib + .,WEB-INF/classes + ${project.name} + ${project.groupId}.${project.artifactId} + ${keycloak.osgi.import} + ${keycloak.osgi.private} + ${keycloak.osgi.export} + + + + + + diff --git a/examples/fuse/customer-app-fuse/src/main/java/org/keycloak/example/CamelClient.java b/examples/fuse/customer-app-fuse/src/main/java/org/keycloak/example/CamelClient.java new file mode 100644 index 0000000000..9ddb8f19d5 --- /dev/null +++ b/examples/fuse/customer-app-fuse/src/main/java/org/keycloak/example/CamelClient.java @@ -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 Marek Posolda + */ +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(); + + } +} diff --git a/examples/fuse/customer-app-fuse/src/main/java/org/keycloak/example/CxfRsClient.java b/examples/fuse/customer-app-fuse/src/main/java/org/keycloak/example/CxfRsClient.java new file mode 100644 index 0000000000..4d64429804 --- /dev/null +++ b/examples/fuse/customer-app-fuse/src/main/java/org/keycloak/example/CxfRsClient.java @@ -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 Bill Burke + * @version $Revision: 1 $ + */ +public class CxfRsClient { + + static class TypedList extends ArrayList { + } + + 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 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(); + } + } + +} diff --git a/examples/fuse/customer-app-fuse/src/main/webapp/WEB-INF/jetty-web.xml b/examples/fuse/customer-app-fuse/src/main/webapp/WEB-INF/jetty-web.xml new file mode 100644 index 0000000000..e3d87a2492 --- /dev/null +++ b/examples/fuse/customer-app-fuse/src/main/webapp/WEB-INF/jetty-web.xml @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/examples/fuse/customer-app-fuse/src/main/webapp/WEB-INF/keycloak.json b/examples/fuse/customer-app-fuse/src/main/webapp/WEB-INF/keycloak.json new file mode 100755 index 0000000000..b5d6b30d24 --- /dev/null +++ b/examples/fuse/customer-app-fuse/src/main/webapp/WEB-INF/keycloak.json @@ -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" + } +} diff --git a/examples/fuse/customer-app-fuse/src/main/webapp/WEB-INF/web.xml b/examples/fuse/customer-app-fuse/src/main/webapp/WEB-INF/web.xml new file mode 100755 index 0000000000..6fb7590e07 --- /dev/null +++ b/examples/fuse/customer-app-fuse/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,34 @@ + + + + customer-portal + + + index.html + + + + + Customers + /customers/* + + + user + + + + + BASIC + does-not-matter + + + + admin + + + user + + diff --git a/examples/fuse/customer-app-fuse/src/main/webapp/customers/camel.jsp b/examples/fuse/customer-app-fuse/src/main/webapp/customers/camel.jsp new file mode 100755 index 0000000000..1d29927f27 --- /dev/null +++ b/examples/fuse/customer-app-fuse/src/main/webapp/customers/camel.jsp @@ -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" %> + + + Camel page + + +

You will receive info from camel endpoint. Endpoint is accessible just for admin user

+

Response from camel: <%= CamelClient.sendRequest(request) %>

+

+ + \ No newline at end of file diff --git a/examples/fuse/customer-app-fuse/src/main/webapp/customers/cxf-ws.jsp b/examples/fuse/customer-app-fuse/src/main/webapp/customers/cxf-ws.jsp new file mode 100755 index 0000000000..45c5dcb8a2 --- /dev/null +++ b/examples/fuse/customer-app-fuse/src/main/webapp/customers/cxf-ws.jsp @@ -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" %> + + + Customer View Page + + +<% + 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); +%> +

Goto: products | logout | manage acct

+Servlet User Principal <%=request.getUserPrincipal().getName()%> + made this request. +

Caller IDToken values (You can specify what is returned in IDToken in the customer-portal claims page in the admin console:

+

Username: <%=idToken.getPreferredUsername()%>

+

Email: <%=idToken.getEmail()%>

+

Full Name: <%=idToken.getName()%>

+

First: <%=idToken.getGivenName()%>

+

Last: <%=idToken.getFamilyName()%>

+

Customer Listing

+<% + java.util.List 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("

"); + out.print(cust); + out.println("

"); + + } +%> +

+ + \ No newline at end of file diff --git a/examples/fuse/customer-app-fuse/src/main/webapp/index.html b/examples/fuse/customer-app-fuse/src/main/webapp/index.html new file mode 100755 index 0000000000..3da0d42ce5 --- /dev/null +++ b/examples/fuse/customer-app-fuse/src/main/webapp/index.html @@ -0,0 +1,15 @@ + + + + Customer portal on Karaf/Fuse + + +

Customer Portal

+ +

Customer Listing - CXF WS endpoint

+ +

Admin Interface - Apache Camel endpoint

+ + + \ No newline at end of file diff --git a/examples/fuse/cxf-jaxrs/pom.xml b/examples/fuse/cxf-jaxrs/pom.xml new file mode 100644 index 0000000000..d96c78fc70 --- /dev/null +++ b/examples/fuse/cxf-jaxrs/pom.xml @@ -0,0 +1,86 @@ + + + + keycloak-parent + org.keycloak + 1.1.0.Final-SNAPSHOT + ../../../pom.xml + + 4.0.0 + org.keycloak.example.demo + cxf-jaxrs-example + bundle + CXF JAXRS Example - Secured in Karaf/Fuse + + + 2.7.14 + + + + 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}", + * + + + org.keycloak.example.rs.* + + + + + + org.apache.cxf + cxf-rt-frontend-jaxrs + ${cxf.version} + + + org.apache.cxf + cxf-rt-transports-http + ${cxf.version} + + + org.apache.cxf + cxf-rt-transports-http-jetty + ${cxf.version} + + + + + install + + + + org.apache.maven.plugins + maven-compiler-plugin + + ${maven.compiler.source} + ${maven.compiler.target} + + + + org.apache.felix + maven-bundle-plugin + true + + + ${project.name} + ${project.groupId}.${project.artifactId} + ${keycloak.osgi.import} + ${keycloak.osgi.private} + ${keycloak.osgi.export} + + + + + + + diff --git a/examples/fuse/cxf-jaxrs/src/main/java/org/keycloak/example/rs/CxfCustomerService.java b/examples/fuse/cxf-jaxrs/src/main/java/org/keycloak/example/rs/CxfCustomerService.java new file mode 100644 index 0000000000..c761556019 --- /dev/null +++ b/examples/fuse/cxf-jaxrs/src/main/java/org/keycloak/example/rs/CxfCustomerService.java @@ -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 Bill Burke + * @version $Revision: 1 $ + */ +@Path("/customers") +public class CxfCustomerService { + + @GET + @Produces("application/json") + public List getCustomers() { + ArrayList rtn = new ArrayList(); + 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; + } +} diff --git a/examples/fuse/cxf-jaxrs/src/main/resources/OSGI-INF/blueprint/blueprint.xml b/examples/fuse/cxf-jaxrs/src/main/resources/OSGI-INF/blueprint/blueprint.xml new file mode 100644 index 0000000000..1515416043 --- /dev/null +++ b/examples/fuse/cxf-jaxrs/src/main/resources/OSGI-INF/blueprint/blueprint.xml @@ -0,0 +1,106 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + user + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/examples/fuse/cxf-jaxrs/src/main/resources/WEB-INF/jetty-web.xml b/examples/fuse/cxf-jaxrs/src/main/resources/WEB-INF/jetty-web.xml new file mode 100644 index 0000000000..e3d87a2492 --- /dev/null +++ b/examples/fuse/cxf-jaxrs/src/main/resources/WEB-INF/jetty-web.xml @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/examples/fuse/cxf-jaxrs/src/main/resources/WEB-INF/keycloak.json b/examples/fuse/cxf-jaxrs/src/main/resources/WEB-INF/keycloak.json new file mode 100644 index 0000000000..f5d7e1a989 --- /dev/null +++ b/examples/fuse/cxf-jaxrs/src/main/resources/WEB-INF/keycloak.json @@ -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" + } +} diff --git a/examples/fuse/cxf-jaxws/pom.xml b/examples/fuse/cxf-jaxws/pom.xml new file mode 100644 index 0000000000..51ba1a46d2 --- /dev/null +++ b/examples/fuse/cxf-jaxws/pom.xml @@ -0,0 +1,107 @@ + + + + keycloak-parent + org.keycloak + 1.1.0.Final-SNAPSHOT + ../../../pom.xml + + 4.0.0 + org.keycloak.example.demo + cxf-jaxws-example + bundle + CXF JAXWS Example - Secured in Karaf/Fuse + + + + 2.7.14 + + + + 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 + + + org.keycloak.example.ws.* + + + + + + org.apache.geronimo.specs + geronimo-ws-metadata_2.0_spec + 1.1.2 + + + org.apache.geronimo.specs + geronimo-jaxws_2.2_spec + 1.0 + + + javax.xml.bind + jaxb-api + 2.2 + + + org.apache.cxf + cxf-rt-frontend-jaxws + ${cxf.version} + + + org.apache.cxf + cxf-rt-transports-http + ${cxf.version} + + + org.apache.cxf + cxf-rt-transports-http-jetty + ${cxf.version} + + + + + install + + + + org.apache.maven.plugins + maven-compiler-plugin + + ${maven.compiler.source} + ${maven.compiler.target} + + + + org.apache.felix + maven-bundle-plugin + true + + + ${project.name} + ${project.groupId}.${project.artifactId} + ${keycloak.osgi.import} + ${keycloak.osgi.private} + ${keycloak.osgi.export} + + + + + + + diff --git a/examples/fuse/cxf-jaxws/src/main/java/org/keycloak/example/ws/Person.java b/examples/fuse/cxf-jaxws/src/main/java/org/keycloak/example/ws/Person.java new file mode 100644 index 0000000000..24926e0ca0 --- /dev/null +++ b/examples/fuse/cxf-jaxws/src/main/java/org/keycloak/example/ws/Person.java @@ -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 personId, + @WebParam(mode = WebParam.Mode.OUT, name = "ssn") + javax.xml.ws.Holder ssn, + @WebParam(mode = WebParam.Mode.OUT, name = "name") + javax.xml.ws.Holder name + ) throws UnknownPersonFault; +} diff --git a/examples/fuse/cxf-jaxws/src/main/java/org/keycloak/example/ws/PersonImpl.java b/examples/fuse/cxf-jaxws/src/main/java/org/keycloak/example/ws/PersonImpl.java new file mode 100644 index 0000000000..dcaf73841f --- /dev/null +++ b/examples/fuse/cxf-jaxws/src/main/java/org/keycloak/example/ws/PersonImpl.java @@ -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 personId, Holder ssn, Holder 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"; + } + } + +} diff --git a/examples/fuse/cxf-jaxws/src/main/java/org/keycloak/example/ws/UnknownPersonFault.java b/examples/fuse/cxf-jaxws/src/main/java/org/keycloak/example/ws/UnknownPersonFault.java new file mode 100644 index 0000000000..f0136574b4 --- /dev/null +++ b/examples/fuse/cxf-jaxws/src/main/java/org/keycloak/example/ws/UnknownPersonFault.java @@ -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; + } +} diff --git a/examples/fuse/cxf-jaxws/src/main/java/org/keycloak/example/ws/types/GetPerson.java b/examples/fuse/cxf-jaxws/src/main/java/org/keycloak/example/ws/types/GetPerson.java new file mode 100644 index 0000000000..2101b1bf59 --- /dev/null +++ b/examples/fuse/cxf-jaxws/src/main/java/org/keycloak/example/ws/types/GetPerson.java @@ -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; + + +/** + *

Java class for anonymous complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+ * <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>
+ * 
+ * + * + */ +@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; + } + +} diff --git a/examples/fuse/cxf-jaxws/src/main/java/org/keycloak/example/ws/types/GetPersonResponse.java b/examples/fuse/cxf-jaxws/src/main/java/org/keycloak/example/ws/types/GetPersonResponse.java new file mode 100644 index 0000000000..fac5e6fa41 --- /dev/null +++ b/examples/fuse/cxf-jaxws/src/main/java/org/keycloak/example/ws/types/GetPersonResponse.java @@ -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; + + +/** + *

Java class for anonymous complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+ * <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>
+ * 
+ * + * + */ +@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; + } + +} diff --git a/examples/fuse/cxf-jaxws/src/main/java/org/keycloak/example/ws/types/ObjectFactory.java b/examples/fuse/cxf-jaxws/src/main/java/org/keycloak/example/ws/types/ObjectFactory.java new file mode 100644 index 0000000000..dd2e74da09 --- /dev/null +++ b/examples/fuse/cxf-jaxws/src/main/java/org/keycloak/example/ws/types/ObjectFactory.java @@ -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. + *

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(); + } + +} diff --git a/examples/fuse/cxf-jaxws/src/main/java/org/keycloak/example/ws/types/UnknownPersonFault.java b/examples/fuse/cxf-jaxws/src/main/java/org/keycloak/example/ws/types/UnknownPersonFault.java new file mode 100644 index 0000000000..ba40a422a7 --- /dev/null +++ b/examples/fuse/cxf-jaxws/src/main/java/org/keycloak/example/ws/types/UnknownPersonFault.java @@ -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; + + +/** + *

Java class for anonymous complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+ * <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>
+ * 
+ * + * + */ +@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; + } + +} diff --git a/examples/fuse/cxf-jaxws/src/main/java/org/keycloak/example/ws/types/package-info.java b/examples/fuse/cxf-jaxws/src/main/java/org/keycloak/example/ws/types/package-info.java new file mode 100644 index 0000000000..877c2df884 --- /dev/null +++ b/examples/fuse/cxf-jaxws/src/main/java/org/keycloak/example/ws/types/package-info.java @@ -0,0 +1 @@ +package org.keycloak.example.ws.types; diff --git a/examples/fuse/cxf-jaxws/src/main/resources/META-INF/spring/beans.xml b/examples/fuse/cxf-jaxws/src/main/resources/META-INF/spring/beans.xml new file mode 100644 index 0000000000..57a7eeeb4b --- /dev/null +++ b/examples/fuse/cxf-jaxws/src/main/resources/META-INF/spring/beans.xml @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + user + + + + + + + + + + + + + + + + + + + + + + + + + + + + true + + + + + + \ No newline at end of file diff --git a/examples/fuse/features/pom.xml b/examples/fuse/features/pom.xml new file mode 100644 index 0000000000..f86e711a84 --- /dev/null +++ b/examples/fuse/features/pom.xml @@ -0,0 +1,62 @@ + + + + keycloak-parent + org.keycloak + 1.1.0.Final-SNAPSHOT + ../../../pom.xml + + 4.0.0 + org.keycloak.example.demo + keycloak-fuse-example-features + Keycloak Fuse Example - Features + + + + + + src/main/resources + true + + + + + org.apache.maven.plugins + maven-resources-plugin + + + filter + generate-resources + + resources + + + + + + org.codehaus.mojo + build-helper-maven-plugin + + + attach-artifacts + package + + attach-artifact + + + + + target/classes/features.xml + xml + features + + + + + + + + + + \ No newline at end of file diff --git a/examples/fuse/features/src/main/resources/features.xml b/examples/fuse/features/src/main/resources/features.xml new file mode 100644 index 0000000000..f888574dbb --- /dev/null +++ b/examples/fuse/features/src/main/resources/features.xml @@ -0,0 +1,19 @@ + + + + +
The keycloak fuse example
+ war + camel + camel-jetty + cxf + keycloak + mvn:org.codehaus.jackson/jackson-jaxrs/${jackson.version} + mvn:org.keycloak.example.demo/product-portal-fuse-example/${project.version} + mvn:org.keycloak.example.demo/customer-portal-fuse-example/${project.version}/war + mvn:org.keycloak.example.demo/camel-endpoint-example/${project.version} + mvn:org.keycloak.example.demo/cxf-jaxws-example/${project.version} + mvn:org.keycloak.example.demo/cxf-jaxrs-example/${project.version} +
+ +
\ No newline at end of file diff --git a/examples/fuse/pom.xml b/examples/fuse/pom.xml new file mode 100644 index 0000000000..db54315e39 --- /dev/null +++ b/examples/fuse/pom.xml @@ -0,0 +1,37 @@ + + + keycloak-parent + org.keycloak + 1.1.0.Final-SNAPSHOT + ../../pom.xml + + Fuse examples + + 4.0.0 + + fuse-pom + pom + + + + + org.apache.maven.plugins + maven-deploy-plugin + + true + + + + + + + customer-app-fuse + product-app-fuse + cxf-jaxrs + cxf-jaxws + camel + features + + + \ No newline at end of file diff --git a/examples/fuse/product-app-fuse/pom.xml b/examples/fuse/product-app-fuse/pom.xml new file mode 100644 index 0000000000..d5ed25333f --- /dev/null +++ b/examples/fuse/product-app-fuse/pom.xml @@ -0,0 +1,83 @@ + + + + keycloak-parent + org.keycloak + 1.1.0.Final-SNAPSHOT + ../../../pom.xml + + 4.0.0 + org.keycloak.example.demo + product-portal-fuse-example + bundle + + Product Portal - Secured in Karaf/Fuse + + + + + + + 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 + + + org.keycloak.example.* + + + + + + org.jboss.spec.javax.servlet + jboss-servlet-api_3.0_spec + + + org.keycloak + keycloak-core + ${project.version} + + + + + org.keycloak.example.demo + cxf-jaxws-example + ${project.version} + + + + + install + + + + org.apache.maven.plugins + maven-compiler-plugin + + ${maven.compiler.source} + ${maven.compiler.target} + + + + org.apache.felix + maven-bundle-plugin + true + + + ${project.name} + ${project.groupId}.${project.artifactId} + ${keycloak.osgi.import} + ${keycloak.osgi.private} + ${keycloak.osgi.export} + org.apache.cxf.bundle + + + + + + + + diff --git a/examples/fuse/product-app-fuse/src/main/java/org/keycloak/example/ProductPortalServlet.java b/examples/fuse/product-app-fuse/src/main/java/org/keycloak/example/ProductPortalServlet.java new file mode 100644 index 0000000000..85ecc42e81 --- /dev/null +++ b/examples/fuse/product-app-fuse/src/main/java/org/keycloak/example/ProductPortalServlet.java @@ -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 Marek Posolda + */ +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("Product Portal Page"); + + 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("

Goto: customers | logout | manage acct

"); + out.println("Servlet User Principal " + req.getUserPrincipal() + " made this request."); + + String unsecuredWsClientResponse = sendWsReq(req, false); + String securedWsClientResponse = sendWsReq(req, true); + + out.println("

Person with ID 1 - unsecured request: " + unsecuredWsClientResponse + "

"); + out.println("

Person with ID 1 - secured request: " + securedWsClientResponse + "

"); + out.println(""); + 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 _getPerson_personId = new javax.xml.ws.Holder(_getPerson_personIdVal); + javax.xml.ws.Holder _getPerson_ssn = new javax.xml.ws.Holder(); + javax.xml.ws.Holder _getPerson_name = new javax.xml.ws.Holder(); + + // Attach Authorization header + if (secured) { + Client clientProxy = ClientProxy.getClient(simpleClient); + + KeycloakSecurityContext session = (KeycloakSecurityContext) req.getAttribute(KeycloakSecurityContext.class.getName()); + Map> headers = new HashMap>(); + 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; + } + } +} diff --git a/examples/fuse/product-app-fuse/src/main/resources/OSGI-INF/blueprint/blueprint.xml b/examples/fuse/product-app-fuse/src/main/resources/OSGI-INF/blueprint/blueprint.xml new file mode 100644 index 0000000000..e6b0757994 --- /dev/null +++ b/examples/fuse/product-app-fuse/src/main/resources/OSGI-INF/blueprint/blueprint.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + user + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/examples/fuse/product-app-fuse/src/main/resources/WEB-INF/jetty-web.xml b/examples/fuse/product-app-fuse/src/main/resources/WEB-INF/jetty-web.xml new file mode 100644 index 0000000000..e3d87a2492 --- /dev/null +++ b/examples/fuse/product-app-fuse/src/main/resources/WEB-INF/jetty-web.xml @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/examples/fuse/product-app-fuse/src/main/resources/WEB-INF/keycloak.json b/examples/fuse/product-app-fuse/src/main/resources/WEB-INF/keycloak.json new file mode 100644 index 0000000000..2a52d247f7 --- /dev/null +++ b/examples/fuse/product-app-fuse/src/main/resources/WEB-INF/keycloak.json @@ -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" + } +} diff --git a/examples/fuse/testrealm.json b/examples/fuse/testrealm.json new file mode 100644 index 0000000000..7ac0319214 --- /dev/null +++ b/examples/fuse/testrealm.json @@ -0,0 +1,137 @@ +{ + "realm": "demo", + "enabled": true, + "accessTokenLifespan": 60, + "accessCodeLifespan": 60, + "accessCodeLifespanUserAction": 300, + "ssoSessionIdleTimeout": 600, + "ssoSessionMaxLifespan": 36000, + "passwordCredentialGrantAllowed": true, + "sslRequired": "external", + "registrationAllowed": false, + "social": false, + "updateProfileOnInitialSocialLogin": 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 + } + ] +} \ No newline at end of file diff --git a/examples/pom.xml b/examples/pom.xml index 3129a631b6..9a8a5853ba 100755 --- a/examples/pom.xml +++ b/examples/pom.xml @@ -32,5 +32,6 @@ js-console multi-tenant basic-auth + fuse diff --git a/integration/adapter-core/pom.xml b/integration/adapter-core/pom.xml index 567030d303..80fa568060 100755 --- a/integration/adapter-core/pom.xml +++ b/integration/adapter-core/pom.xml @@ -13,6 +13,17 @@ Keycloak Adapter Core + + + org.keycloak.adapters.* + + + org.keycloak.*;version="${project.version}", + org.apache.http.*;version=${keycloak.apache.httpcomponents.version}, + *;resolution:=optional + + + org.bouncycastle @@ -73,6 +84,39 @@ ${maven.compiler.target} + + + + maven-jar-plugin + + + ${project.build.outputDirectory}/META-INF/MANIFEST.MF + + + + + org.apache.felix + maven-bundle-plugin + true + + + bundle-manifest + process-classes + + manifest + + + + + + . + ${project.name} + ${project.groupId}.${project.artifactId} + ${keycloak.osgi.import} + ${keycloak.osgi.export} + + +
diff --git a/integration/jaxrs-oauth-client/pom.xml b/integration/jaxrs-oauth-client/pom.xml index 441f2cc598..86d43fcd0c 100755 --- a/integration/jaxrs-oauth-client/pom.xml +++ b/integration/jaxrs-oauth-client/pom.xml @@ -74,7 +74,6 @@ org.osgi org.osgi.core - 4.3.0 provided
diff --git a/integration/jetty/jetty-core/pom.xml b/integration/jetty/jetty-core/pom.xml index 4415a6990c..b42497766e 100755 --- a/integration/jetty/jetty-core/pom.xml +++ b/integration/jetty/jetty-core/pom.xml @@ -13,6 +13,15 @@ Keycloak Jetty Core Integration 8.1.16.v20140903 + + org.keycloak.adapters.jetty.core.* + + + org.eclipse.jetty.*;version="[8.1,10)";resolution:=optional, + javax.servlet.*;version="[2.5,4)";resolution:=optional, + org.keycloak.*;version="${project.version}", + *;resolution:=optional + @@ -94,6 +103,39 @@ 1.6 + + + + maven-jar-plugin + + + ${project.build.outputDirectory}/META-INF/MANIFEST.MF + + + + + org.apache.felix + maven-bundle-plugin + true + + + bundle-manifest + process-classes + + manifest + + + + + + . + ${project.name} + ${project.groupId}.${project.artifactId} + ${keycloak.osgi.import} + ${keycloak.osgi.export} + + + diff --git a/integration/jetty/jetty-core/src/main/java/org/keycloak/adapters/jetty/AbstractJettySessionTokenStore.java b/integration/jetty/jetty-core/src/main/java/org/keycloak/adapters/jetty/core/AbstractJettySessionTokenStore.java similarity index 93% rename from integration/jetty/jetty-core/src/main/java/org/keycloak/adapters/jetty/AbstractJettySessionTokenStore.java rename to integration/jetty/jetty-core/src/main/java/org/keycloak/adapters/jetty/core/AbstractJettySessionTokenStore.java index f6be3da0a6..e1b0739875 100755 --- a/integration/jetty/jetty-core/src/main/java/org/keycloak/adapters/jetty/AbstractJettySessionTokenStore.java +++ b/integration/jetty/jetty-core/src/main/java/org/keycloak/adapters/jetty/core/AbstractJettySessionTokenStore.java @@ -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; diff --git a/integration/jetty/jetty-core/src/main/java/org/keycloak/adapters/jetty/AbstractKeycloakJettyAuthenticator.java b/integration/jetty/jetty-core/src/main/java/org/keycloak/adapters/jetty/core/AbstractKeycloakJettyAuthenticator.java similarity index 93% rename from integration/jetty/jetty-core/src/main/java/org/keycloak/adapters/jetty/AbstractKeycloakJettyAuthenticator.java rename to integration/jetty/jetty-core/src/main/java/org/keycloak/adapters/jetty/core/AbstractKeycloakJettyAuthenticator.java index fc01385deb..cb3ee3f260 100755 --- a/integration/jetty/jetty-core/src/main/java/org/keycloak/adapters/jetty/AbstractKeycloakJettyAuthenticator.java +++ b/integration/jetty/jetty-core/src/main/java/org/keycloak/adapters/jetty/core/AbstractKeycloakJettyAuthenticator.java @@ -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) { diff --git a/integration/jetty/jetty-core/src/main/java/org/keycloak/adapters/jetty/JettyCookieTokenStore.java b/integration/jetty/jetty-core/src/main/java/org/keycloak/adapters/jetty/core/JettyCookieTokenStore.java similarity index 98% rename from integration/jetty/jetty-core/src/main/java/org/keycloak/adapters/jetty/JettyCookieTokenStore.java rename to integration/jetty/jetty-core/src/main/java/org/keycloak/adapters/jetty/core/JettyCookieTokenStore.java index 3020f7536a..4c5b6ec435 100755 --- a/integration/jetty/jetty-core/src/main/java/org/keycloak/adapters/jetty/JettyCookieTokenStore.java +++ b/integration/jetty/jetty-core/src/main/java/org/keycloak/adapters/jetty/core/JettyCookieTokenStore.java @@ -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; diff --git a/integration/jetty/jetty-core/src/main/java/org/keycloak/adapters/jetty/JettyHttpFacade.java b/integration/jetty/jetty-core/src/main/java/org/keycloak/adapters/jetty/core/JettyHttpFacade.java similarity index 96% rename from integration/jetty/jetty-core/src/main/java/org/keycloak/adapters/jetty/JettyHttpFacade.java rename to integration/jetty/jetty-core/src/main/java/org/keycloak/adapters/jetty/core/JettyHttpFacade.java index 5a8c4c3ade..c294106906 100755 --- a/integration/jetty/jetty-core/src/main/java/org/keycloak/adapters/jetty/JettyHttpFacade.java +++ b/integration/jetty/jetty-core/src/main/java/org/keycloak/adapters/jetty/core/JettyHttpFacade.java @@ -1,4 +1,4 @@ -package org.keycloak.adapters.jetty; +package org.keycloak.adapters.jetty.core; import org.keycloak.KeycloakSecurityContext; import org.keycloak.adapters.HttpFacade; diff --git a/integration/jetty/jetty-core/src/main/java/org/keycloak/adapters/jetty/JettyRequestAuthenticator.java b/integration/jetty/jetty-core/src/main/java/org/keycloak/adapters/jetty/core/JettyRequestAuthenticator.java similarity index 96% rename from integration/jetty/jetty-core/src/main/java/org/keycloak/adapters/jetty/JettyRequestAuthenticator.java rename to integration/jetty/jetty-core/src/main/java/org/keycloak/adapters/jetty/core/JettyRequestAuthenticator.java index 0556b01e01..4b0db24b89 100755 --- a/integration/jetty/jetty-core/src/main/java/org/keycloak/adapters/jetty/JettyRequestAuthenticator.java +++ b/integration/jetty/jetty-core/src/main/java/org/keycloak/adapters/jetty/core/JettyRequestAuthenticator.java @@ -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; diff --git a/integration/jetty/jetty-core/src/main/java/org/keycloak/adapters/jetty/JettyUserSessionManagement.java b/integration/jetty/jetty-core/src/main/java/org/keycloak/adapters/jetty/core/JettyUserSessionManagement.java similarity index 93% rename from integration/jetty/jetty-core/src/main/java/org/keycloak/adapters/jetty/JettyUserSessionManagement.java rename to integration/jetty/jetty-core/src/main/java/org/keycloak/adapters/jetty/core/JettyUserSessionManagement.java index 40fc72f440..ca226d4fde 100755 --- a/integration/jetty/jetty-core/src/main/java/org/keycloak/adapters/jetty/JettyUserSessionManagement.java +++ b/integration/jetty/jetty-core/src/main/java/org/keycloak/adapters/jetty/core/JettyUserSessionManagement.java @@ -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; diff --git a/integration/jetty/jetty-core/src/main/java/org/keycloak/adapters/jetty/core/WrappingSessionHandler.java b/integration/jetty/jetty-core/src/main/java/org/keycloak/adapters/jetty/core/WrappingSessionHandler.java new file mode 100644 index 0000000000..529b6f0d5c --- /dev/null +++ b/integration/jetty/jetty-core/src/main/java/org/keycloak/adapters/jetty/core/WrappingSessionHandler.java @@ -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 Marek Posolda + */ +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); + } + } +} diff --git a/integration/jetty/jetty8.1/pom.xml b/integration/jetty/jetty8.1/pom.xml index 3c1f6ea655..8ea3c550bf 100755 --- a/integration/jetty/jetty8.1/pom.xml +++ b/integration/jetty/jetty8.1/pom.xml @@ -13,6 +13,14 @@ Keycloak Jetty 8.1.x Integration 8.1.16.v20140903 + + org.keycloak.adapters.jetty.* + + + javax.servlet.*;version="[2.5,4)";resolution:=optional, + org.keycloak.*;version="${project.version}", + *;resolution:=optional + @@ -99,6 +107,39 @@ 1.6 + + + + maven-jar-plugin + + + ${project.build.outputDirectory}/META-INF/MANIFEST.MF + + + + + org.apache.felix + maven-bundle-plugin + true + + + bundle-manifest + process-classes + + manifest + + + + + + . + ${project.name} + ${project.groupId}.${project.artifactId} + ${keycloak.osgi.import} + ${keycloak.osgi.export} + + + diff --git a/integration/jetty/jetty8.1/src/main/java/org/keycloak/adapters/jetty/JettySessionTokenStore.java b/integration/jetty/jetty8.1/src/main/java/org/keycloak/adapters/jetty/JettySessionTokenStore.java index e2dcfa5aac..38180aae85 100755 --- a/integration/jetty/jetty8.1/src/main/java/org/keycloak/adapters/jetty/JettySessionTokenStore.java +++ b/integration/jetty/jetty8.1/src/main/java/org/keycloak/adapters/jetty/JettySessionTokenStore.java @@ -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; diff --git a/integration/jetty/jetty8.1/src/main/java/org/keycloak/adapters/jetty/KeycloakJettyAuthenticator.java b/integration/jetty/jetty8.1/src/main/java/org/keycloak/adapters/jetty/KeycloakJettyAuthenticator.java index d1ae6e0040..a3a557209d 100755 --- a/integration/jetty/jetty8.1/src/main/java/org/keycloak/adapters/jetty/KeycloakJettyAuthenticator.java +++ b/integration/jetty/jetty8.1/src/main/java/org/keycloak/adapters/jetty/KeycloakJettyAuthenticator.java @@ -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; diff --git a/integration/jetty/jetty9.1/pom.xml b/integration/jetty/jetty9.1/pom.xml index 689a0e345d..5601a8783e 100755 --- a/integration/jetty/jetty9.1/pom.xml +++ b/integration/jetty/jetty9.1/pom.xml @@ -13,6 +13,15 @@ Keycloak Jetty 9.1.x Integration 9.1.5.v20140505 + + org.keycloak.adapters.jetty.* + + + 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 + @@ -113,6 +122,39 @@ 1.6 + + + + maven-jar-plugin + + + ${project.build.outputDirectory}/META-INF/MANIFEST.MF + + + + + org.apache.felix + maven-bundle-plugin + true + + + bundle-manifest + process-classes + + manifest + + + + + + . + ${project.name} + ${project.groupId}.${project.artifactId} + ${keycloak.osgi.import} + ${keycloak.osgi.export} + + + diff --git a/integration/jetty/jetty9.1/src/main/java/org/keycloak/adapters/jetty/JettySessionTokenStore.java b/integration/jetty/jetty9.1/src/main/java/org/keycloak/adapters/jetty/JettySessionTokenStore.java index 24fc9b258b..6d4cb92eda 100755 --- a/integration/jetty/jetty9.1/src/main/java/org/keycloak/adapters/jetty/JettySessionTokenStore.java +++ b/integration/jetty/jetty9.1/src/main/java/org/keycloak/adapters/jetty/JettySessionTokenStore.java @@ -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; diff --git a/integration/jetty/jetty9.1/src/main/java/org/keycloak/adapters/jetty/KeycloakJettyAuthenticator.java b/integration/jetty/jetty9.1/src/main/java/org/keycloak/adapters/jetty/KeycloakJettyAuthenticator.java index db15f33f2a..d1ab5f32f1 100755 --- a/integration/jetty/jetty9.1/src/main/java/org/keycloak/adapters/jetty/KeycloakJettyAuthenticator.java +++ b/integration/jetty/jetty9.1/src/main/java/org/keycloak/adapters/jetty/KeycloakJettyAuthenticator.java @@ -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; diff --git a/integration/jetty/jetty9.2/pom.xml b/integration/jetty/jetty9.2/pom.xml index 0e15ff0c8e..22c0bab6e8 100755 --- a/integration/jetty/jetty9.2/pom.xml +++ b/integration/jetty/jetty9.2/pom.xml @@ -13,6 +13,15 @@ Keycloak Jetty 9.2.x Integration 9.2.4.v20141103 + + org.keycloak.adapters.jetty.* + + + org.eclipse.jetty.*;resolution:=optional, + javax.servlet.*;version="[3.0,4)";resolution:=optional, + org.keycloak.*;version="${project.version}", + *;resolution:=optional + @@ -99,6 +108,39 @@ 1.6 + + + + maven-jar-plugin + + + ${project.build.outputDirectory}/META-INF/MANIFEST.MF + + + + + org.apache.felix + maven-bundle-plugin + true + + + bundle-manifest + process-classes + + manifest + + + + + + . + ${project.name} + ${project.groupId}.${project.artifactId} + ${keycloak.osgi.import} + ${keycloak.osgi.export} + + + diff --git a/integration/jetty/jetty9.2/src/main/java/org/keycloak/adapters/jetty/JettySessionTokenStore.java b/integration/jetty/jetty9.2/src/main/java/org/keycloak/adapters/jetty/JettySessionTokenStore.java index 4ff9af9aab..f48a0d8251 100755 --- a/integration/jetty/jetty9.2/src/main/java/org/keycloak/adapters/jetty/JettySessionTokenStore.java +++ b/integration/jetty/jetty9.2/src/main/java/org/keycloak/adapters/jetty/JettySessionTokenStore.java @@ -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 Bill Burke diff --git a/integration/jetty/jetty9.2/src/main/java/org/keycloak/adapters/jetty/KeycloakJettyAuthenticator.java b/integration/jetty/jetty9.2/src/main/java/org/keycloak/adapters/jetty/KeycloakJettyAuthenticator.java index b43e27cc8d..6cd1e075f2 100755 --- a/integration/jetty/jetty9.2/src/main/java/org/keycloak/adapters/jetty/KeycloakJettyAuthenticator.java +++ b/integration/jetty/jetty9.2/src/main/java/org/keycloak/adapters/jetty/KeycloakJettyAuthenticator.java @@ -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; diff --git a/integration/osgi-adapter/pom.xml b/integration/osgi-adapter/pom.xml new file mode 100644 index 0000000000..9d462f2d9c --- /dev/null +++ b/integration/osgi-adapter/pom.xml @@ -0,0 +1,104 @@ + + + + keycloak-parent + org.keycloak + 1.1.0.Final-SNAPSHOT + ../../pom.xml + + 4.0.0 + + keycloak-osgi-adapter + Keycloak OSGI Adapter + jar + + + 8.1.16.v20140903 + + org.keycloak.adapters.osgi.* + + + 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 + + + + + + org.jboss.logging + jboss-logging + provided + + + org.osgi + org.osgi.core + provided + + + org.osgi + org.osgi.enterprise + provided + + + org.ops4j.pax.web + pax-web-runtime + provided + + + org.eclipse.jetty + jetty-security + ${jetty9.version} + provided + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + ${maven.compiler.source} + ${maven.compiler.target} + + + + + + maven-jar-plugin + + + ${project.build.outputDirectory}/META-INF/MANIFEST.MF + + + + + org.apache.felix + maven-bundle-plugin + true + + + bundle-manifest + process-classes + + manifest + + + + + + . + ${project.name} + ${project.groupId}.${project.artifactId} + ${keycloak.osgi.import} + ${keycloak.osgi.export} + + + + + + diff --git a/integration/osgi-adapter/src/main/java/org/keycloak/adapters/osgi/PaxWebIntegrationService.java b/integration/osgi-adapter/src/main/java/org/keycloak/adapters/osgi/PaxWebIntegrationService.java new file mode 100644 index 0000000000..1aa67f0f70 --- /dev/null +++ b/integration/osgi-adapter/src/main/java/org/keycloak/adapters/osgi/PaxWebIntegrationService.java @@ -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. + * + *

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

+ * + * @author Marek Posolda + */ +public class PaxWebIntegrationService { + + protected static final Logger log = Logger.getLogger(PaxWebIntegrationService.class); + + private BundleContext bundleContext; + private String jettyWebXmlLocation; + private List 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 getConstraintMappings() { + return constraintMappings; + } + + public void setConstraintMappings(List 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 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); + } + } +} diff --git a/integration/osgi-adapter/src/main/java/org/keycloak/adapters/osgi/ServletUnregistrationService.java b/integration/osgi-adapter/src/main/java/org/keycloak/adapters/osgi/ServletUnregistrationService.java new file mode 100644 index 0000000000..236c49e9f7 --- /dev/null +++ b/integration/osgi-adapter/src/main/java/org/keycloak/adapters/osgi/ServletUnregistrationService.java @@ -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. + * + *

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

+ * + * @author Marek Posolda + */ +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 servletInitParams = new Hashtable(); + 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); + } + } + +} diff --git a/integration/pom.xml b/integration/pom.xml index e114ad5ce5..c14ec5929a 100755 --- a/integration/pom.xml +++ b/integration/pom.xml @@ -28,5 +28,6 @@ js installed admin-client + osgi-adapter diff --git a/pom.xml b/pom.xml index afc7119540..243338e1e4 100755 --- a/pom.xml +++ b/pom.xml @@ -13,6 +13,7 @@ 0.33.12 + 2.3.8 1.46 1.9.9 4.2.1 @@ -48,6 +49,8 @@ 6.0.2.Final 3.2.2 9.1.0.v20131115 + 4.2.0 + 3.1.2 1.6 @@ -139,7 +142,7 @@ net.iharder base64 - 2.3.8 + ${base64.version} javax.mail @@ -508,6 +511,21 @@ liquibase-core ${liquibase.version} + + org.osgi + org.osgi.core + ${osgi.version} + + + org.osgi + org.osgi.enterprise + ${osgi.version} + + + org.ops4j.pax.web + pax-web-runtime + ${pax.web.version} + diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/jaxrs/JaxrsFilterTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/jaxrs/JaxrsFilterTest.java index 16f00f525b..2ff046c0d2 100644 --- a/testsuite/integration/src/test/java/org/keycloak/testsuite/jaxrs/JaxrsFilterTest.java +++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/jaxrs/JaxrsFilterTest.java @@ -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); diff --git a/testsuite/jetty/jetty91/src/test/java/org/keycloak/testsuite/Jetty9Test.java b/testsuite/jetty/jetty91/src/test/java/org/keycloak/testsuite/Jetty9Test.java index 22170eea59..4b87597b98 100755 --- a/testsuite/jetty/jetty91/src/test/java/org/keycloak/testsuite/Jetty9Test.java +++ b/testsuite/jetty/jetty91/src/test/java/org/keycloak/testsuite/Jetty9Test.java @@ -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; diff --git a/testsuite/jetty/jetty92/src/test/java/org/keycloak/testsuite/Jetty9Test.java b/testsuite/jetty/jetty92/src/test/java/org/keycloak/testsuite/Jetty9Test.java index e965ea6564..ceab804ac0 100755 --- a/testsuite/jetty/jetty92/src/test/java/org/keycloak/testsuite/Jetty9Test.java +++ b/testsuite/jetty/jetty92/src/test/java/org/keycloak/testsuite/Jetty9Test.java @@ -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;