keycloak-uncached
Changes
adapters/oidc/as7-eap6/as7-subsystem/src/main/java/org/keycloak/subsystem/as7/KeycloakDependencyProcessor.java 16(+15 -1)
adapters/oidc/wildfly/wf8-subsystem/src/main/java/org/keycloak/subsystem/wf8/extension/KeycloakDependencyProcessor.java 16(+15 -1)
adapters/oidc/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/extension/KeycloakDependencyProcessor.java 16(+15 -1)
adapters/saml/as7-eap6/subsystem/src/main/java/org/keycloak/subsystem/saml/as7/KeycloakDependencyProcessor.java 16(+15 -1)
adapters/saml/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/saml/extension/KeycloakDependencyProcessor.java 18(+17 -1)
examples/demo-template/admin-access-app/src/main/webapp/WEB-INF/jboss-deployment-structure.xml 4(+4 -0)
examples/demo-template/customer-app-filter/src/main/java/org/keycloak/example/CustomerDatabaseClient.java 81(+81 -0)
examples/demo-template/pom.xml 1(+1 -0)
examples/demo-template/README.md 1(+1 -0)
examples/demo-template/service-account/src/main/webapp/WEB-INF/jboss-deployment-structure.xml 6(+4 -2)
examples/demo-template/testrealm.json 14(+14 -0)
examples/demo-template/third-party-cdi/src/main/webapp/WEB-INF/jboss-deployment-structure.xml 4(+4 -0)
examples/saml/pom.xml 1(+1 -0)
examples/saml/servlet-filter/pom.xml 51(+51 -0)
examples/saml/servlet-filter/README.md 31(+31 -0)
examples/saml/testsaml.json 19(+19 -0)
Details
diff --git a/adapters/oidc/as7-eap6/as7-subsystem/src/main/java/org/keycloak/subsystem/as7/KeycloakDependencyProcessor.java b/adapters/oidc/as7-eap6/as7-subsystem/src/main/java/org/keycloak/subsystem/as7/KeycloakDependencyProcessor.java
index 07a2f9d..1d41697 100755
--- a/adapters/oidc/as7-eap6/as7-subsystem/src/main/java/org/keycloak/subsystem/as7/KeycloakDependencyProcessor.java
+++ b/adapters/oidc/as7-eap6/as7-subsystem/src/main/java/org/keycloak/subsystem/as7/KeycloakDependencyProcessor.java
@@ -24,6 +24,9 @@ import org.jboss.as.server.deployment.DeploymentUnitProcessingException;
 import org.jboss.as.server.deployment.DeploymentUnitProcessor;
 import org.jboss.as.server.deployment.module.ModuleDependency;
 import org.jboss.as.server.deployment.module.ModuleSpecification;
+import org.jboss.as.web.deployment.WarMetaData;
+import org.jboss.metadata.web.jboss.JBossWebMetaData;
+import org.jboss.metadata.web.spec.LoginConfigMetaData;
 import org.jboss.modules.Module;
 import org.jboss.modules.ModuleIdentifier;
 import org.jboss.modules.ModuleLoader;
@@ -43,7 +46,18 @@ public abstract class KeycloakDependencyProcessor implements DeploymentUnitProce
     public void deploy(DeploymentPhaseContext phaseContext) throws DeploymentUnitProcessingException {
         final DeploymentUnit deploymentUnit = phaseContext.getDeploymentUnit();
 
-        // Next phase, need to detect if this is a Keycloak deployment.  If not, don't add the modules.
+        String deploymentName = deploymentUnit.getName();
+        if (!KeycloakAdapterConfigService.getInstance().isSecureDeployment(deploymentName)) {
+            WarMetaData warMetaData = deploymentUnit.getAttachment(WarMetaData.ATTACHMENT_KEY);
+            JBossWebMetaData webMetaData = warMetaData.getMergedJBossWebMetaData();
+            if (webMetaData == null) {
+                return;
+            }
+            LoginConfigMetaData loginConfig = webMetaData.getLoginConfig();
+            if (loginConfig == null) return;
+            if (loginConfig.getAuthMethod() == null) return;
+            if (!loginConfig.getAuthMethod().equals("KEYCLOAK")) return;
+        }
 
         final ModuleSpecification moduleSpecification = deploymentUnit.getAttachment(Attachments.MODULE_SPECIFICATION);
         final ModuleLoader moduleLoader = Module.getBootModuleLoader();
                diff --git a/adapters/oidc/servlet-oauth-client/pom.xml b/adapters/oidc/servlet-oauth-client/pom.xml
index 0487799..ab208d6 100755
--- a/adapters/oidc/servlet-oauth-client/pom.xml
+++ b/adapters/oidc/servlet-oauth-client/pom.xml
@@ -17,12 +17,10 @@
         <dependency>
             <groupId>org.bouncycastle</groupId>
             <artifactId>bcprov-jdk15on</artifactId>
-            <scope>provided</scope>
         </dependency>
         <dependency>
             <groupId>org.keycloak</groupId>
             <artifactId>keycloak-core</artifactId>
-            <scope>provided</scope>
         </dependency>
         <dependency>
             <groupId>org.keycloak</groupId>
@@ -31,12 +29,10 @@
         <dependency>
             <groupId>org.keycloak</groupId>
             <artifactId>keycloak-adapter-core</artifactId>
-            <scope>provided</scope>
         </dependency>
         <dependency>
             <groupId>org.apache.httpcomponents</groupId>
             <artifactId>httpclient</artifactId>
-            <scope>provided</scope>
         </dependency>
         <dependency>
             <groupId>org.jboss.spec.javax.servlet</groupId>
                diff --git a/adapters/oidc/wildfly/wf8-subsystem/src/main/java/org/keycloak/subsystem/wf8/extension/KeycloakDependencyProcessor.java b/adapters/oidc/wildfly/wf8-subsystem/src/main/java/org/keycloak/subsystem/wf8/extension/KeycloakDependencyProcessor.java
index efb9681..cd72623 100755
--- a/adapters/oidc/wildfly/wf8-subsystem/src/main/java/org/keycloak/subsystem/wf8/extension/KeycloakDependencyProcessor.java
+++ b/adapters/oidc/wildfly/wf8-subsystem/src/main/java/org/keycloak/subsystem/wf8/extension/KeycloakDependencyProcessor.java
@@ -24,6 +24,9 @@ import org.jboss.as.server.deployment.DeploymentUnitProcessingException;
 import org.jboss.as.server.deployment.DeploymentUnitProcessor;
 import org.jboss.as.server.deployment.module.ModuleDependency;
 import org.jboss.as.server.deployment.module.ModuleSpecification;
+import org.jboss.as.web.common.WarMetaData;
+import org.jboss.metadata.web.jboss.JBossWebMetaData;
+import org.jboss.metadata.web.spec.LoginConfigMetaData;
 import org.jboss.modules.Module;
 import org.jboss.modules.ModuleIdentifier;
 import org.jboss.modules.ModuleLoader;
@@ -43,7 +46,18 @@ public abstract class KeycloakDependencyProcessor implements DeploymentUnitProce
     public void deploy(DeploymentPhaseContext phaseContext) throws DeploymentUnitProcessingException {
         final DeploymentUnit deploymentUnit = phaseContext.getDeploymentUnit();
 
-        // Next phase, need to detect if this is a Keycloak deployment.  If not, don't add the modules.
+        String deploymentName = deploymentUnit.getName();
+        if (!KeycloakAdapterConfigService.getInstance().isSecureDeployment(deploymentName)) {
+            WarMetaData warMetaData = deploymentUnit.getAttachment(WarMetaData.ATTACHMENT_KEY);
+            JBossWebMetaData webMetaData = warMetaData.getMergedJBossWebMetaData();
+            if (webMetaData == null) {
+                return;
+            }
+            LoginConfigMetaData loginConfig = webMetaData.getLoginConfig();
+            if (loginConfig == null) return;
+            if (loginConfig.getAuthMethod() == null) return;
+            if (!loginConfig.getAuthMethod().equals("KEYCLOAK")) return;
+        }
 
         final ModuleSpecification moduleSpecification = deploymentUnit.getAttachment(Attachments.MODULE_SPECIFICATION);
         final ModuleLoader moduleLoader = Module.getBootModuleLoader();
                diff --git a/adapters/oidc/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/extension/KeycloakDependencyProcessor.java b/adapters/oidc/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/extension/KeycloakDependencyProcessor.java
index cb246d4..8da211d 100755
--- a/adapters/oidc/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/extension/KeycloakDependencyProcessor.java
+++ b/adapters/oidc/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/extension/KeycloakDependencyProcessor.java
@@ -24,6 +24,9 @@ import org.jboss.as.server.deployment.DeploymentUnitProcessingException;
 import org.jboss.as.server.deployment.DeploymentUnitProcessor;
 import org.jboss.as.server.deployment.module.ModuleDependency;
 import org.jboss.as.server.deployment.module.ModuleSpecification;
+import org.jboss.as.web.common.WarMetaData;
+import org.jboss.metadata.web.jboss.JBossWebMetaData;
+import org.jboss.metadata.web.spec.LoginConfigMetaData;
 import org.jboss.modules.Module;
 import org.jboss.modules.ModuleIdentifier;
 import org.jboss.modules.ModuleLoader;
@@ -43,7 +46,18 @@ public abstract class KeycloakDependencyProcessor implements DeploymentUnitProce
     public void deploy(DeploymentPhaseContext phaseContext) throws DeploymentUnitProcessingException {
         final DeploymentUnit deploymentUnit = phaseContext.getDeploymentUnit();
 
-        // Next phase, need to detect if this is a Keycloak deployment.  If not, don't add the modules.
+        String deploymentName = deploymentUnit.getName();
+        if (!KeycloakAdapterConfigService.getInstance().isSecureDeployment(deploymentName)) {
+            WarMetaData warMetaData = deploymentUnit.getAttachment(WarMetaData.ATTACHMENT_KEY);
+            JBossWebMetaData webMetaData = warMetaData.getMergedJBossWebMetaData();
+            if (webMetaData == null) {
+                return;
+            }
+            LoginConfigMetaData loginConfig = webMetaData.getLoginConfig();
+            if (loginConfig == null) return;
+            if (loginConfig.getAuthMethod() == null) return;
+            if (!loginConfig.getAuthMethod().equals("KEYCLOAK")) return;
+        }
 
         final ModuleSpecification moduleSpecification = deploymentUnit.getAttachment(Attachments.MODULE_SPECIFICATION);
         final ModuleLoader moduleLoader = Module.getBootModuleLoader();
                diff --git a/adapters/saml/as7-eap6/subsystem/src/main/java/org/keycloak/subsystem/saml/as7/KeycloakDependencyProcessor.java b/adapters/saml/as7-eap6/subsystem/src/main/java/org/keycloak/subsystem/saml/as7/KeycloakDependencyProcessor.java
index c214774..76f51a1 100755
--- a/adapters/saml/as7-eap6/subsystem/src/main/java/org/keycloak/subsystem/saml/as7/KeycloakDependencyProcessor.java
+++ b/adapters/saml/as7-eap6/subsystem/src/main/java/org/keycloak/subsystem/saml/as7/KeycloakDependencyProcessor.java
@@ -24,6 +24,9 @@ import org.jboss.as.server.deployment.DeploymentUnitProcessingException;
 import org.jboss.as.server.deployment.DeploymentUnitProcessor;
 import org.jboss.as.server.deployment.module.ModuleDependency;
 import org.jboss.as.server.deployment.module.ModuleSpecification;
+import org.jboss.as.web.deployment.WarMetaData;
+import org.jboss.metadata.web.jboss.JBossWebMetaData;
+import org.jboss.metadata.web.spec.LoginConfigMetaData;
 import org.jboss.modules.Module;
 import org.jboss.modules.ModuleIdentifier;
 import org.jboss.modules.ModuleLoader;
@@ -42,7 +45,18 @@ public abstract class KeycloakDependencyProcessor implements DeploymentUnitProce
     public void deploy(DeploymentPhaseContext phaseContext) throws DeploymentUnitProcessingException {
         final DeploymentUnit deploymentUnit = phaseContext.getDeploymentUnit();
 
-        // Next phase, need to detect if this is a Keycloak deployment.  If not, don't add the modules.
+        String deploymentName = deploymentUnit.getName();
+        if (Configuration.INSTANCE.getSecureDeployment(deploymentName) == null) {
+            WarMetaData warMetaData = deploymentUnit.getAttachment(WarMetaData.ATTACHMENT_KEY);
+            JBossWebMetaData webMetaData = warMetaData.getMergedJBossWebMetaData();
+            if (webMetaData == null) {
+                return;
+            }
+            LoginConfigMetaData loginConfig = webMetaData.getLoginConfig();
+            if (loginConfig == null) return;
+            if (loginConfig.getAuthMethod() == null) return;
+            if (!loginConfig.getAuthMethod().equals("KEYCLOAK-SAML")) return;
+        }
 
         final ModuleSpecification moduleSpecification = deploymentUnit.getAttachment(Attachments.MODULE_SPECIFICATION);
         final ModuleLoader moduleLoader = Module.getBootModuleLoader();
                diff --git a/adapters/saml/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/saml/extension/KeycloakDependencyProcessor.java b/adapters/saml/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/saml/extension/KeycloakDependencyProcessor.java
index 6d30764..b68a255 100755
--- a/adapters/saml/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/saml/extension/KeycloakDependencyProcessor.java
+++ b/adapters/saml/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/saml/extension/KeycloakDependencyProcessor.java
@@ -24,6 +24,9 @@ import org.jboss.as.server.deployment.DeploymentUnitProcessingException;
 import org.jboss.as.server.deployment.DeploymentUnitProcessor;
 import org.jboss.as.server.deployment.module.ModuleDependency;
 import org.jboss.as.server.deployment.module.ModuleSpecification;
+import org.jboss.as.web.common.WarMetaData;
+import org.jboss.metadata.web.jboss.JBossWebMetaData;
+import org.jboss.metadata.web.spec.LoginConfigMetaData;
 import org.jboss.modules.Module;
 import org.jboss.modules.ModuleIdentifier;
 import org.jboss.modules.ModuleLoader;
@@ -41,7 +44,20 @@ public abstract class KeycloakDependencyProcessor implements DeploymentUnitProce
     public void deploy(DeploymentPhaseContext phaseContext) throws DeploymentUnitProcessingException {
         final DeploymentUnit deploymentUnit = phaseContext.getDeploymentUnit();
 
-        // Next phase, need to detect if this is a Keycloak deployment.  If not, don't add the modules.
+        String deploymentName = deploymentUnit.getName();
+        if (Configuration.INSTANCE.getSecureDeployment(deploymentName) == null) {
+            WarMetaData warMetaData = deploymentUnit.getAttachment(WarMetaData.ATTACHMENT_KEY);
+            JBossWebMetaData webMetaData = warMetaData.getMergedJBossWebMetaData();
+            if (webMetaData == null) {
+                return;
+            }
+            LoginConfigMetaData loginConfig = webMetaData.getLoginConfig();
+            if (loginConfig == null) return;
+            if (loginConfig.getAuthMethod() == null) return;
+            if (!loginConfig.getAuthMethod().equals("KEYCLOAK-SAML")) return;
+        }
+
+         // Next phase, need to detect if this is a Keycloak deployment.  If not, don't add the modules.
 
         final ModuleSpecification moduleSpecification = deploymentUnit.getAttachment(Attachments.MODULE_SPECIFICATION);
         final ModuleLoader moduleLoader = Module.getBootModuleLoader();
                diff --git a/docbook/auth-server-docs/reference/en/en-US/modules/MigrationFromOlderVersions.xml b/docbook/auth-server-docs/reference/en/en-US/modules/MigrationFromOlderVersions.xml
index 79a4c9f..2f91203 100755
--- a/docbook/auth-server-docs/reference/en/en-US/modules/MigrationFromOlderVersions.xml
+++ b/docbook/auth-server-docs/reference/en/en-US/modules/MigrationFromOlderVersions.xml
@@ -82,6 +82,15 @@
         <section>
             <title>Migrating to 1.9.0</title>
             <simplesect>
+                <title>Adapter Subsystems only bring in dependencies if keycloak is on</title>
+                <para>
+                    Previously, if you had installed our saml or oidc keycloak subsystem adapters into Wildfly or JBoss EAP, we would
+                    automatically include Keycloak client jars into EVERY application irregardless if you were using Keycloak or not.
+                    These libraries are now only added to your deployment if you have keycloak authentication turned on for that adapter
+                    (via the subsystem, or auth-method in web.xml
+                </para>
+            </simplesect>
+            <simplesect>
                 <title>Deprecated OpenID Connect endpoints</title>
                 <para>
                     In 1.2 we deprecated a number of endpoints that where not consistent with the OpenID Connect
                diff --git a/examples/demo-template/admin-access-app/src/main/webapp/WEB-INF/jboss-deployment-structure.xml b/examples/demo-template/admin-access-app/src/main/webapp/WEB-INF/jboss-deployment-structure.xml
index 9c1bac9..28513d5 100755
--- a/examples/demo-template/admin-access-app/src/main/webapp/WEB-INF/jboss-deployment-structure.xml
+++ b/examples/demo-template/admin-access-app/src/main/webapp/WEB-INF/jboss-deployment-structure.xml
@@ -1,6 +1,10 @@
 <jboss-deployment-structure>
     <deployment>
         <dependencies>
+            <module name="org.keycloak.keycloak-adapter-spi"/>
+            <module name="org.keycloak.keycloak-adapter-core"/>
+            <module name="org.keycloak.keycloak-common"/>
+            <module name="org.keycloak.keycloak-core"/>
             <!-- the Demo code uses classes in these modules.  These are optional to import if you are not using
                  Apache Http Client or the HttpClientBuilder that comes with the adapter core -->
             <module name="org.apache.httpcomponents"/>
                diff --git a/examples/demo-template/customer-app-filter/pom.xml b/examples/demo-template/customer-app-filter/pom.xml
new file mode 100755
index 0000000..1e9019a
--- /dev/null
+++ b/examples/demo-template/customer-app-filter/pom.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <parent>
+        <artifactId>keycloak-examples-demo-parent</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>1.9.0.CR1-SNAPSHOT</version>
+    </parent>
+
+    <modelVersion>4.0.0</modelVersion>
+    <groupId>org.keycloak.example.demo</groupId>
+    <artifactId>customer-portal-filter-example</artifactId>
+    <packaging>war</packaging>
+    <name>Customer Portal - Secured via Servlet Filter</name>
+    <description/>
+
+    <repositories>
+        <repository>
+            <id>jboss</id>
+            <name>jboss repo</name>
+            <url>http://repository.jboss.org/nexus/content/groups/public/</url>
+        </repository>
+    </repositories>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.jboss.spec.javax.servlet</groupId>
+            <artifactId>jboss-servlet-api_3.0_spec</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-servlet-filter-adapter</artifactId>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <finalName>customer-portal-filter</finalName>
+        <plugins>
+            <plugin>
+                <groupId>org.jboss.as.plugins</groupId>
+                <artifactId>jboss-as-maven-plugin</artifactId>
+                <configuration>
+                    <skip>false</skip>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.wildfly.plugins</groupId>
+                <artifactId>wildfly-maven-plugin</artifactId>
+                <configuration>
+                    <skip>false</skip>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+</project>
                diff --git a/examples/demo-template/customer-app-filter/src/main/java/org/keycloak/example/CustomerDatabaseClient.java b/examples/demo-template/customer-app-filter/src/main/java/org/keycloak/example/CustomerDatabaseClient.java
new file mode 100755
index 0000000..a2c1b31
--- /dev/null
+++ b/examples/demo-template/customer-app-filter/src/main/java/org/keycloak/example/CustomerDatabaseClient.java
@@ -0,0 +1,81 @@
+package org.keycloak.example;
+
+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.apache.http.impl.client.DefaultHttpClient;
+import org.keycloak.KeycloakSecurityContext;
+import org.keycloak.adapters.AdapterUtils;
+import org.keycloak.representations.IDToken;
+import org.keycloak.util.JsonSerialization;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpSession;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
+ * @version $Revision: 1 $
+ */
+public class CustomerDatabaseClient {
+
+    static class TypedList extends ArrayList<String> {
+    }
+
+    public static class Failure extends Exception {
+        private int status;
+
+        public Failure(int status) {
+            this.status = status;
+        }
+
+        public int getStatus() {
+            return status;
+        }
+    }
+
+    public static IDToken getIDToken(HttpServletRequest req) {
+        KeycloakSecurityContext session = (KeycloakSecurityContext) req.getAttribute(KeycloakSecurityContext.class.getName());
+        return session.getIdToken();
+
+    }
+
+    public static List<String> getCustomers(HttpServletRequest req) throws Failure {
+        KeycloakSecurityContext session = (KeycloakSecurityContext) req.getAttribute(KeycloakSecurityContext.class.getName());
+
+        HttpClient client = new DefaultHttpClient();
+        try {
+            HttpGet get = new HttpGet(AdapterUtils.getOriginForRestCalls(req.getRequestURL().toString(), session) + "/database/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();
+        }
+    }
+
+    public static String increaseAndGetCounter(HttpServletRequest req) {
+        HttpSession session = req.getSession();
+        Integer counter = (Integer)session.getAttribute("counter");
+        counter = (counter == null) ? 1 : counter + 1;
+        session.setAttribute("counter", counter);
+        return String.valueOf(counter);
+    }
+}
                diff --git a/examples/demo-template/customer-app-filter/src/main/webapp/customers/view.jsp b/examples/demo-template/customer-app-filter/src/main/webapp/customers/view.jsp
new file mode 100755
index 0000000..c2e66f1
--- /dev/null
+++ b/examples/demo-template/customer-app-filter/src/main/webapp/customers/view.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.CustomerDatabaseClient" %>
+<%@ page import="org.keycloak.representations.IDToken" %>
+<%@ page import="org.keycloak.common.util.KeycloakUriBuilder" %>
+<%@ page session="false" %>
+<html>
+<head>
+    <title>Customer View Page</title>
+</head>
+<body bgcolor="#E3F6CE">
+<%
+    String logoutUri = KeycloakUriBuilder.fromUri("/auth").path(ServiceUrlConstants.TOKEN_SERVICE_LOGOUT_PATH)
+            .queryParam("redirect_uri", "/customer-portal-filter").build("demo").toString();
+    String acctUri = KeycloakUriBuilder.fromUri("/auth").path(ServiceUrlConstants.ACCOUNT_SERVICE_PATH)
+            .queryParam("referrer", "customer-portal-filter").build("demo").toString();
+    IDToken idToken = CustomerDatabaseClient.getIDToken(request);
+%>
+<p>Goto: <a href="/product-portal">products</a> | <a href="<%=logoutUri%>">logout</a> | <a
+        href="<%=acctUri%>">manage acct</a></p>
+Servlet User Principal <b><%=request.getUserPrincipal().getName()%>
+</b> made this request.
+<p><b>Caller IDToken values</b> (<i>You can specify what is returned in IDToken in the customer-portal claims page in the admin console</i>:</p>
+<p>Username: <%=idToken.getPreferredUsername()%></p>
+<p>Email: <%=idToken.getEmail()%></p>
+<p>Full Name: <%=idToken.getName()%></p>
+<p>First: <%=idToken.getGivenName()%></p>
+<p>Last: <%=idToken.getFamilyName()%></p>
+<h2>Customer Listing</h2>
+<%
+    java.util.List<String> list = null;
+    try {
+        list = CustomerDatabaseClient.getCustomers(request);
+    } catch (CustomerDatabaseClient.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 database service?");
+        out.println("Status from database service invocation was: " + failure.getStatus());
+        return;
+    }
+    for (String cust : list) {
+        out.print("<p>");
+        out.print(cust);
+        out.println("</p>");
+
+    }
+%>
+<br><br>
+</body>
+</html>
\ No newline at end of file
                diff --git a/examples/demo-template/customer-app-filter/src/main/webapp/index.html b/examples/demo-template/customer-app-filter/src/main/webapp/index.html
new file mode 100755
index 0000000..4919eb5
--- /dev/null
+++ b/examples/demo-template/customer-app-filter/src/main/webapp/index.html
@@ -0,0 +1,14 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+        "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+    <title></title>
+</head>
+<body bgcolor="#E3F6CE">
+<h1>Customer Portal - Servlet Filter Example</h1>
+
+<p><a href="customers/view.jsp">Customer Listing</a></p>
+
+
+</body>
+</html>
\ No newline at end of file
                diff --git a/examples/demo-template/customer-app-filter/src/main/webapp/WEB-INF/keycloak.json b/examples/demo-template/customer-app-filter/src/main/webapp/WEB-INF/keycloak.json
new file mode 100755
index 0000000..14e56f5
--- /dev/null
+++ b/examples/demo-template/customer-app-filter/src/main/webapp/WEB-INF/keycloak.json
@@ -0,0 +1,11 @@
+{
+    "realm": "demo",
+    "resource": "customer-portal-filter",
+    "realm-public-key": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB",
+    "auth-server-url": "/auth",
+    "ssl-required" : "external",
+    "expose-token": true,
+    "credentials": {
+        "secret": "password"
+    }
+}
                diff --git a/examples/demo-template/customer-app-filter/src/main/webapp/WEB-INF/web.xml b/examples/demo-template/customer-app-filter/src/main/webapp/WEB-INF/web.xml
new file mode 100755
index 0000000..1b5ce2c
--- /dev/null
+++ b/examples/demo-template/customer-app-filter/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<web-app xmlns="http://java.sun.com/xml/ns/javaee"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
+         version="3.0">
+
+    <module-name>customer-portal-filter</module-name>
+
+    <filter>
+        <filter-name>Keycloak Filter</filter-name>
+        <filter-class>org.keycloak.adapters.servlet.KeycloakOIDCFilter</filter-class>
+    </filter>
+    <filter-mapping>
+        <filter-name>Keycloak Filter</filter-name>
+        <url-pattern>/customers/*</url-pattern>
+    </filter-mapping>
+
+</web-app>
                diff --git a/examples/demo-template/customer-app-filter/src/main/webapp/WEB-INF/web.xml.unconfigured b/examples/demo-template/customer-app-filter/src/main/webapp/WEB-INF/web.xml.unconfigured
new file mode 100755
index 0000000..c48f2ed
--- /dev/null
+++ b/examples/demo-template/customer-app-filter/src/main/webapp/WEB-INF/web.xml.unconfigured
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<web-app xmlns="http://java.sun.com/xml/ns/javaee"
+      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+      xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
+      version="3.0">
+
+	<module-name>customer-portal-filter</module-name>
+</web-app>
                examples/demo-template/pom.xml 1(+1 -0)
diff --git a/examples/demo-template/pom.xml b/examples/demo-template/pom.xml
index 7bf7339..1601d55 100755
--- a/examples/demo-template/pom.xml
+++ b/examples/demo-template/pom.xml
@@ -27,6 +27,7 @@
     <modules>
         <!-- <module>server</module> -->
         <module>customer-app</module>
+        <module>customer-app-filter</module>
         <module>customer-app-cli</module>
         <module>customer-app-js</module>
         <module>product-app</module>
                examples/demo-template/README.md 1(+1 -0)
diff --git a/examples/demo-template/README.md b/examples/demo-template/README.md
index 35b6db8..fa46d6c 100755
--- a/examples/demo-template/README.md
+++ b/examples/demo-template/README.md
@@ -11,6 +11,7 @@ The following examples requires Wildfly 8.0.0, JBoss EAP 6.x, or JBoss AS 7.1.1.
 There are multiple WAR projects.  These will all run on the same WildFly instance, but pretend each one is running on a different
 machine on the network or Internet.
 * **customer-app** A WAR application that does remote login using OAuth2 browser redirects with the auth server
+* **customer-app-filter** A WAR application secured by the Keycloak Servlet Filter Adapter.  Useful for EE platforms that don't have an adapter.
 * **customer-app-js** A pure HTML/Javascript application that does remote login using OAuth2 browser redirects with the auth server
 * **customer-app-cli** A pure CLI application that does remote login using OAuth2 browser redirects with the auth server
 * **product-app** A WAR application that does remote login using OAuth2 browser redirects with the auth server
                diff --git a/examples/demo-template/service-account/src/main/webapp/WEB-INF/jboss-deployment-structure.xml b/examples/demo-template/service-account/src/main/webapp/WEB-INF/jboss-deployment-structure.xml
old mode 100644
new mode 100755
index 9c1bac9..1808858
--- a/examples/demo-template/service-account/src/main/webapp/WEB-INF/jboss-deployment-structure.xml
+++ b/examples/demo-template/service-account/src/main/webapp/WEB-INF/jboss-deployment-structure.xml
@@ -1,8 +1,10 @@
 <jboss-deployment-structure>
     <deployment>
         <dependencies>
-            <!-- the Demo code uses classes in these modules.  These are optional to import if you are not using
-                 Apache Http Client or the HttpClientBuilder that comes with the adapter core -->
+            <module name="org.keycloak.keycloak-adapter-spi"/>
+            <module name="org.keycloak.keycloak-adapter-core"/>
+            <module name="org.keycloak.keycloak-common"/>
+            <module name="org.keycloak.keycloak-core"/>
             <module name="org.apache.httpcomponents"/>
         </dependencies>
     </deployment>
                examples/demo-template/testrealm.json 14(+14 -0)
diff --git a/examples/demo-template/testrealm.json b/examples/demo-template/testrealm.json
index 2542f82..e1d07ba 100755
--- a/examples/demo-template/testrealm.json
+++ b/examples/demo-template/testrealm.json
@@ -121,6 +121,16 @@
             "secret": "password"
         },
         {
+            "clientId": "customer-portal-filter",
+            "enabled": true,
+            "adminUrl": "/customer-portal-filter",
+            "baseUrl": "/customer-portal-filter",
+            "redirectUris": [
+                "/customer-portal-filter/*"
+            ],
+            "secret": "password"
+        },
+        {
             "clientId": "customer-portal-js",
             "enabled": true,
             "publicClient": true,
@@ -217,6 +227,10 @@
             {
                 "client": "customer-portal",
                 "roles": ["realm-admin"]
+            },
+            {
+                "client": "customer-portal-filter",
+                "roles": ["realm-admin"]
             }
         ]
     }
                diff --git a/examples/demo-template/third-party/src/main/webapp/WEB-INF/jboss-deployment-structure.xml b/examples/demo-template/third-party/src/main/webapp/WEB-INF/jboss-deployment-structure.xml
index 2ee04e0..69d395d 100755
--- a/examples/demo-template/third-party/src/main/webapp/WEB-INF/jboss-deployment-structure.xml
+++ b/examples/demo-template/third-party/src/main/webapp/WEB-INF/jboss-deployment-structure.xml
@@ -5,6 +5,10 @@
                  Apache Http Client or the HttpClientBuilder that comes with the adapter core -->
             <module name="org.apache.httpcomponents"/>
             <module name="org.keycloak.keycloak-servlet-oauth-client"/>
+            <module name="org.keycloak.keycloak-adapter-spi"/>
+            <module name="org.keycloak.keycloak-adapter-core"/>
+            <module name="org.keycloak.keycloak-common"/>
+            <module name="org.keycloak.keycloak-core"/>
         </dependencies>
     </deployment>
 </jboss-deployment-structure>
\ No newline at end of file
                diff --git a/examples/demo-template/third-party-cdi/src/main/webapp/WEB-INF/jboss-deployment-structure.xml b/examples/demo-template/third-party-cdi/src/main/webapp/WEB-INF/jboss-deployment-structure.xml
index 2ee04e0..69d395d 100755
--- a/examples/demo-template/third-party-cdi/src/main/webapp/WEB-INF/jboss-deployment-structure.xml
+++ b/examples/demo-template/third-party-cdi/src/main/webapp/WEB-INF/jboss-deployment-structure.xml
@@ -5,6 +5,10 @@
                  Apache Http Client or the HttpClientBuilder that comes with the adapter core -->
             <module name="org.apache.httpcomponents"/>
             <module name="org.keycloak.keycloak-servlet-oauth-client"/>
+            <module name="org.keycloak.keycloak-adapter-spi"/>
+            <module name="org.keycloak.keycloak-adapter-core"/>
+            <module name="org.keycloak.keycloak-common"/>
+            <module name="org.keycloak.keycloak-core"/>
         </dependencies>
     </deployment>
 </jboss-deployment-structure>
\ No newline at end of file
                examples/saml/pom.xml 1(+1 -0)
diff --git a/examples/saml/pom.xml b/examples/saml/pom.xml
index 4fb6e0d..ff862b3 100755
--- a/examples/saml/pom.xml
+++ b/examples/saml/pom.xml
@@ -28,5 +28,6 @@
         <module>post-with-signature</module>
         <module>post-with-encryption</module>
         <module>redirect-with-signature</module>
+        <module>servlet-filter</module>
     </modules>
 </project>
                diff --git a/examples/saml/post-with-encryption/src/main/webapp/WEB-INF/web.xml b/examples/saml/post-with-encryption/src/main/webapp/WEB-INF/web.xml
index 04bfd71..b6b7724 100755
--- a/examples/saml/post-with-encryption/src/main/webapp/WEB-INF/web.xml
+++ b/examples/saml/post-with-encryption/src/main/webapp/WEB-INF/web.xml
@@ -5,41 +5,24 @@
 
     <module-name>sales-post-enc</module-name>
 
-    <!-- Define a Security Constraint on this Application -->
+    <!-- Define a Security Constraint on this Application, only index.jsp and piechart.gif.  The rest is needed for logout.jsp -->
 	<security-constraint>
-		<web-resource-collection>
-			<web-resource-name>SALES Application</web-resource-name>
-			<url-pattern>/*</url-pattern>
-		</web-resource-collection>
+        <web-resource-collection>
+            <web-resource-name>SALES Application</web-resource-name>
+            <url-pattern>/index.jsp</url-pattern>
+        </web-resource-collection>
+        <web-resource-collection>
+            <web-resource-name>SALES Picture</web-resource-name>
+            <url-pattern>/piechart.gif</url-pattern>
+        </web-resource-collection>
 		<auth-constraint>
 			<role-name>manager</role-name>
 		</auth-constraint>
 	</security-constraint>
 
-	<!-- Define a security constraint that gives unlimted access to freezone -->
-	<security-constraint>
-		<web-resource-collection>
-			<web-resource-name>freezone</web-resource-name>
-			<url-pattern>/freezone/*</url-pattern>
-		</web-resource-collection>
-		<web-resource-collection>
-			<web-resource-name>images</web-resource-name>
-			<url-pattern>/images/*</url-pattern>
-		</web-resource-collection>
-		<web-resource-collection>
-			<web-resource-name>css</web-resource-name>
-			<url-pattern>/css/*</url-pattern>
-		</web-resource-collection>
-	</security-constraint>
-
     <!-- Define the Login Configuration for this Application -->
     <login-config>
 		<auth-method>KEYCLOAK-SAML</auth-method>
-		<realm-name>Tomcat SALES Application</realm-name>
-		<form-login-config>
-			<form-login-page>/jsp/login.jsp</form-login-page>
-			<form-error-page>/jsp/loginerror.jsp</form-error-page>
-		</form-login-config>
 	</login-config>
 
 	<!-- Security roles referenced by this web application -->
                diff --git a/examples/saml/post-with-signature/src/main/webapp/WEB-INF/web.xml b/examples/saml/post-with-signature/src/main/webapp/WEB-INF/web.xml
index 8971257..e6a334d 100755
--- a/examples/saml/post-with-signature/src/main/webapp/WEB-INF/web.xml
+++ b/examples/saml/post-with-signature/src/main/webapp/WEB-INF/web.xml
@@ -5,46 +5,29 @@
 
     <module-name>sales-post-sig</module-name>
 
-    <!-- Define a Security Constraint on this Application -->
-	<security-constraint>
-		<web-resource-collection>
-			<web-resource-name>SALES Application</web-resource-name>
-			<url-pattern>/*</url-pattern>
-		</web-resource-collection>
-		<auth-constraint>
-			<role-name>manager</role-name>
-		</auth-constraint>
-	</security-constraint>
-
-	<!-- Define a security constraint that gives unlimted access to freezone -->
-	<security-constraint>
-		<web-resource-collection>
-			<web-resource-name>freezone</web-resource-name>
-			<url-pattern>/freezone/*</url-pattern>
-		</web-resource-collection>
-		<web-resource-collection>
-			<web-resource-name>images</web-resource-name>
-			<url-pattern>/images/*</url-pattern>
-		</web-resource-collection>
-		<web-resource-collection>
-			<web-resource-name>css</web-resource-name>
-			<url-pattern>/css/*</url-pattern>
-		</web-resource-collection>
-	</security-constraint>
+    <!-- Define a Security Constraint on this Application, only index.jsp and piechart.gif.  The rest is needed for logout.jsp -->
+    <security-constraint>
+        <web-resource-collection>
+            <web-resource-name>SALES Application</web-resource-name>
+            <url-pattern>/index.jsp</url-pattern>
+        </web-resource-collection>
+        <web-resource-collection>
+            <web-resource-name>SALES Picture</web-resource-name>
+            <url-pattern>/piechart.gif</url-pattern>
+        </web-resource-collection>
+        <auth-constraint>
+            <role-name>manager</role-name>
+        </auth-constraint>
+    </security-constraint>
 
     <!-- Define the Login Configuration for this Application -->
     <login-config>
-		<auth-method>KEYCLOAK-SAML</auth-method>
-		<realm-name>Tomcat SALES Application</realm-name>
-		<form-login-config>
-			<form-login-page>/jsp/login.jsp</form-login-page>
-			<form-error-page>/jsp/loginerror.jsp</form-error-page>
-		</form-login-config>
-	</login-config>
+        <auth-method>KEYCLOAK-SAML</auth-method>
+    </login-config>
 
-	<!-- Security roles referenced by this web application -->
-	<security-role>
-		<description>The role that is required to log in to the Manager Application</description>
-		<role-name>manager</role-name>
-	</security-role>
+    <!-- Security roles referenced by this web application -->
+    <security-role>
+        <description>The role that is required to log in to the Manager Application</description>
+        <role-name>manager</role-name>
+    </security-role>
 </web-app>
                diff --git a/examples/saml/redirect-with-signature/src/main/webapp/WEB-INF/web.xml b/examples/saml/redirect-with-signature/src/main/webapp/WEB-INF/web.xml
index 96ac722..da10fbf 100755
--- a/examples/saml/redirect-with-signature/src/main/webapp/WEB-INF/web.xml
+++ b/examples/saml/redirect-with-signature/src/main/webapp/WEB-INF/web.xml
@@ -4,47 +4,29 @@
          version="3.0">
 
     <module-name>employee-sig</module-name>
-
-    <!-- Define a Security Constraint on this Application -->
-	<security-constraint>
-		<web-resource-collection>
-			<web-resource-name>EMPLOYEE Application</web-resource-name>
-			<url-pattern>/*</url-pattern>
-		</web-resource-collection>
-		<auth-constraint>
-			<role-name>manager</role-name>
-		</auth-constraint>
-	</security-constraint>
-
-	<!-- Define a security constraint that gives unlimted access to freezone -->
-	<security-constraint>
-		<web-resource-collection>
-			<web-resource-name>freezone</web-resource-name>
-			<url-pattern>/freezone/*</url-pattern>
-		</web-resource-collection>
-		<web-resource-collection>
-			<web-resource-name>images</web-resource-name>
-			<url-pattern>/images/*</url-pattern>
-		</web-resource-collection>
-		<web-resource-collection>
-			<web-resource-name>css</web-resource-name>
-			<url-pattern>/css/*</url-pattern>
-		</web-resource-collection>
-	</security-constraint>
+    <!-- Define a Security Constraint on this Application, only index.jsp and piechart.gif.  The rest is needed for logout.jsp -->
+    <security-constraint>
+        <web-resource-collection>
+            <web-resource-name>Main page</web-resource-name>
+            <url-pattern>/index.jsp</url-pattern>
+        </web-resource-collection>
+        <web-resource-collection>
+            <web-resource-name>Career picture</web-resource-name>
+            <url-pattern>/careermap.jpg</url-pattern>
+        </web-resource-collection>
+        <auth-constraint>
+            <role-name>manager</role-name>
+        </auth-constraint>
+    </security-constraint>
 
     <!-- Define the Login Configuration for this Application -->
     <login-config>
-		<auth-method>KEYCLOAK-SAML</auth-method>
-		<realm-name>Tomcat SALES Application</realm-name>
-		<form-login-config>
-			<form-login-page>/jsp/login.jsp</form-login-page>
-			<form-error-page>/jsp/loginerror.jsp</form-error-page>
-		</form-login-config>
-	</login-config>
+        <auth-method>KEYCLOAK-SAML</auth-method>
+    </login-config>
 
-	<!-- Security roles referenced by this web application -->
-	<security-role>
-		<description>The role that is required to log in to the EMPLOYEE Application</description>
-		<role-name>manager</role-name>
-	</security-role>
+    <!-- Security roles referenced by this web application -->
+    <security-role>
+        <description>The role that is required to log in to the Manager Application</description>
+        <role-name>manager</role-name>
+    </security-role>
 </web-app>
                examples/saml/servlet-filter/pom.xml 51(+51 -0)
diff --git a/examples/saml/servlet-filter/pom.xml b/examples/saml/servlet-filter/pom.xml
new file mode 100755
index 0000000..38ca902
--- /dev/null
+++ b/examples/saml/servlet-filter/pom.xml
@@ -0,0 +1,51 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <artifactId>keycloak-examples-saml-parent</artifactId>
+        <groupId>org.keycloak</groupId>
+        <version>1.9.0.CR1-SNAPSHOT</version>
+    </parent>
+
+    <artifactId>saml-servlet-filter</artifactId>
+
+    <packaging>war</packaging>
+
+    <name>Keycloak SAML Adapter as a Servlet Filter</name>
+
+    <licenses>
+        <license>
+            <name>Apache License, Version 2.0</name>
+            <distribution>repo</distribution>
+            <url>http://www.apache.org/licenses/LICENSE-2.0.html</url>
+        </license>
+    </licenses>
+    <dependencies>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-saml-servlet-filter-adapter</artifactId>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <!-- Set the name of the war, used as the context root when the app is deployed -->
+        <finalName>${project.artifactId}</finalName>
+        <plugins>
+            <plugin>
+                <groupId>org.jboss.as.plugins</groupId>
+                <artifactId>jboss-as-maven-plugin</artifactId>
+                <configuration>
+                    <skip>false</skip>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.wildfly.plugins</groupId>
+                <artifactId>wildfly-maven-plugin</artifactId>
+                <configuration>
+                    <skip>false</skip>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+</project>
\ No newline at end of file
                examples/saml/servlet-filter/README.md 31(+31 -0)
diff --git a/examples/saml/servlet-filter/README.md b/examples/saml/servlet-filter/README.md
new file mode 100755
index 0000000..3ec6520
--- /dev/null
+++ b/examples/saml/servlet-filter/README.md
@@ -0,0 +1,31 @@
+# Keycloak SAML Client Adapter using HTTP POST Binding With Signatures
+
+## Introduction
+
+Basic example that demonstrates how to setup an application as a SAML v2.0 Service Provider using SAML HTTP POST Binding with Signature Support.  This example uses the Keycloak Servlet Filter to accomplish this
+Note that no role checks are done with the servlet filter.  You would have to do this manually.
+
+## Import the test realm
+
+If you haven't already done so, you need to import the test realm for this examples.  Clicking on the below link will bring you to the
+create realm page in the Admin UI.  The username/password is admin/admin to login in.  Keycloak will ask you to
+create a new admin password before you can go to the create realm page.
+
+[http://localhost:8080/auth/admin/master/console/#/create/realm](http://localhost:8080/auth/admin/master/console/#/create/realm)
+
+Import the testsaml.json file that is in the saml/ example directory.
+
+## Build and Deploy
+
+```
+$ mvn clean install wildfly:deploy
+```
+
+## Access the application
+
+The application will be running at the following URL: <http://localhost:8080/saml-servlet-filter>.  Login with:
+
+    username: bburke
+    password: password
+
+
                diff --git a/examples/saml/servlet-filter/src/main/webapp/css/idp.css b/examples/saml/servlet-filter/src/main/webapp/css/idp.css
new file mode 100755
index 0000000..afb49ea
--- /dev/null
+++ b/examples/saml/servlet-filter/src/main/webapp/css/idp.css
@@ -0,0 +1,78 @@
+/*
+  ~ JBoss, Home of Professional Open Source.
+  ~ Copyright (c) 2011, Red Hat, Inc., and individual contributors
+  ~ as indicated by the @author tags. See the copyright.txt file in the
+  ~ distribution for a full listing of individual contributors.
+  ~
+  ~ This is free software; you can redistribute it and/or modify it
+  ~ under the terms of the GNU Lesser General Public License as
+  ~ published by the Free Software Foundation; either version 2.1 of
+  ~ the License, or (at your option) any later version.
+  ~
+  ~ This software is distributed in the hope that it will be useful,
+  ~ but WITHOUT ANY WARRANTY; without even the implied warranty of
+  ~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  ~ Lesser General Public License for more details.
+  ~
+  ~ You should have received a copy of the GNU Lesser General Public
+  ~ License along with this software; if not, write to the Free
+  ~ Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+  ~ 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+*/
+body {
+	background: url(images/rh_bg.png) repeat-x scroll 0 0 #F3F3F3;
+	color: #555555;
+	font: 12px/1.4 "Lucida Sans Unicode", "Lucida Grande", sans-serif;
+}
+
+.loginBox {
+	position:absolute;
+	top: 50%;
+	left: 50%;
+	width:30em;
+	height:3em;
+	margin-top: -9em; /*set to a negative number 1/2 of your height*/
+	margin-left: -15em; /*set to a negative number 1/2 of your width*/
+	border: 1px solid #ccc;
+	background-color: #f3f3f3;
+}
+
+.wrapper {
+	margin-left: auto;
+	margin-right: auto;
+	width: 50em;
+	text-align: left;
+}
+
+a {
+	text-decoration: none;
+	color: #5e8a9a;
+}
+
+h1 {
+	padding-top: 20px;
+	color: #7b1e1e;
+}
+
+a:hover {
+	text-decoration: underline;
+	color: #8ec6d9;
+}
+
+.content {
+	margin-left: 230px;
+}
+
+.dualbrand {
+	padding-top: 20px;
+}
+
+.as7 {
+	float: left;
+	margin-left: 10px;
+}
+
+.note {
+	font-size: 8pt;
+	color: #aaaaaa;
+}
\ No newline at end of file
                diff --git a/examples/saml/servlet-filter/src/main/webapp/error.jsp b/examples/saml/servlet-filter/src/main/webapp/error.jsp
new file mode 100755
index 0000000..7a78c2f
--- /dev/null
+++ b/examples/saml/servlet-filter/src/main/webapp/error.jsp
@@ -0,0 +1,43 @@
+<!--
+  ~ JBoss, Home of Professional Open Source.
+  ~ Copyright (c) 2011, Red Hat, Inc., and individual contributors
+  ~ as indicated by the @author tags. See the copyright.txt file in the
+  ~ distribution for a full listing of individual contributors.
+  ~
+  ~ This is free software; you can redistribute it and/or modify it
+  ~ under the terms of the GNU Lesser General Public License as
+  ~ published by the Free Software Foundation; either version 2.1 of
+  ~ the License, or (at your option) any later version.
+  ~
+  ~ This software is distributed in the hope that it will be useful,
+  ~ but WITHOUT ANY WARRANTY; without even the implied warranty of
+  ~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  ~ Lesser General Public License for more details.
+  ~
+  ~ You should have received a copy of the GNU Lesser General Public
+  ~ License along with this software; if not, write to the Free
+  ~ Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+  ~ 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+  -->
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+
+<html>
+<head>
+<title>PicketLink Example Application</title>
+<link rel="shortcut icon" href="favicon.ico" type="image/x-icon">
+<link rel="StyleSheet" href="css/idp.css" type="text/css">
+</head>
+
+<body>
+	<img src="images/picketlink-banner-1180px.png"
+		style="margin-top: -10px; margin-left: -10px; opacity: 0.4; filter: alpha(opacity =   40);" />
+	<div class="loginBox"
+		style="margin-bottom: 80px; border: 1px solid #000000; width: 440px; background-color: #F8F8F8; align: center;">
+		<center>
+			<p>
+				<b>The Service Provider could not process the request.</b>
+			</p>
+		</center>
+	</div>
+</body>
+</html>
\ No newline at end of file
                diff --git a/examples/saml/servlet-filter/src/main/webapp/favicon.ico b/examples/saml/servlet-filter/src/main/webapp/favicon.ico
new file mode 100755
index 0000000..c31d0fa
Binary files /dev/null and b/examples/saml/servlet-filter/src/main/webapp/favicon.ico differ
                diff --git a/examples/saml/servlet-filter/src/main/webapp/images/bkg.gif b/examples/saml/servlet-filter/src/main/webapp/images/bkg.gif
new file mode 100755
index 0000000..523877c
Binary files /dev/null and b/examples/saml/servlet-filter/src/main/webapp/images/bkg.gif differ
                diff --git a/examples/saml/servlet-filter/src/main/webapp/images/keycloak_default_banner-1180px.png b/examples/saml/servlet-filter/src/main/webapp/images/keycloak_default_banner-1180px.png
new file mode 100755
index 0000000..10ef213
Binary files /dev/null and b/examples/saml/servlet-filter/src/main/webapp/images/keycloak_default_banner-1180px.png differ
                diff --git a/examples/saml/servlet-filter/src/main/webapp/images/rh_bg.png b/examples/saml/servlet-filter/src/main/webapp/images/rh_bg.png
new file mode 100755
index 0000000..b0e6a00
Binary files /dev/null and b/examples/saml/servlet-filter/src/main/webapp/images/rh_bg.png differ
                diff --git a/examples/saml/servlet-filter/src/main/webapp/index.jsp b/examples/saml/servlet-filter/src/main/webapp/index.jsp
new file mode 100755
index 0000000..6669210
--- /dev/null
+++ b/examples/saml/servlet-filter/src/main/webapp/index.jsp
@@ -0,0 +1,13 @@
+<html lang="en-US">
+<head>
+    <meta charset="UTF-8">
+    <meta http-equiv="refresh" content="1;url=protected/chart.jsp">
+    <script type="text/javascript">
+        window.location.href = "protected/chart.jsp"
+    </script>
+    <title>Page Redirection</title>
+</head>
+<body>
+If you are not redirected automatically, follow the <a href='protected/chart.jsp'>link to example</a>
+</body>
+</html>
\ No newline at end of file
                diff --git a/examples/saml/servlet-filter/src/main/webapp/logout.jsp b/examples/saml/servlet-filter/src/main/webapp/logout.jsp
new file mode 100755
index 0000000..46124de
--- /dev/null
+++ b/examples/saml/servlet-filter/src/main/webapp/logout.jsp
@@ -0,0 +1,43 @@
+<!--
+  ~ JBoss, Home of Professional Open Source.
+  ~ Copyright (c) 2011, Red Hat, Inc., and individual contributors
+  ~ as indicated by the @author tags. See the copyright.txt file in the
+  ~ distribution for a full listing of individual contributors.
+  ~
+  ~ This is free software; you can redistribute it and/or modify it
+  ~ under the terms of the GNU Lesser General Public License as
+  ~ published by the Free Software Foundation; either version 2.1 of
+  ~ the License, or (at your option) any later version.
+  ~
+  ~ This software is distributed in the hope that it will be useful,
+  ~ but WITHOUT ANY WARRANTY; without even the implied warranty of
+  ~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  ~ Lesser General Public License for more details.
+  ~
+  ~ You should have received a copy of the GNU Lesser General Public
+  ~ License along with this software; if not, write to the Free
+  ~ Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+  ~ 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+  -->
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+
+<html>
+<head>
+<title>Keycloak SAML Client Adapter Example Application</title>
+<link rel="shortcut icon" href="favicon.ico" type="image/x-icon">
+<link rel="StyleSheet" href="css/idp.css" type="text/css">
+</head>
+
+<body>
+	<img src="images/keycloak_default_banner-1180px.png"
+		style="margin-top: -10px; margin-left: -10px; opacity: 0.4; filter: alpha(opacity =   40);" />
+	<div class="loginBox"
+		style="margin-bottom: 80px; border: 1px solid #000000; width: 440px; background-color: #F8F8F8; align: center;">
+		<center>
+			<p>
+				<b>Logged out.  <a href="<%= request.getContextPath() %>">Login</a> again.</b>
+			</p>
+		</center>
+	</div>
+</body>
+</html>
\ No newline at end of file
                diff --git a/examples/saml/servlet-filter/src/main/webapp/protected/chart.jsp b/examples/saml/servlet-filter/src/main/webapp/protected/chart.jsp
new file mode 100755
index 0000000..cae2fea
--- /dev/null
+++ b/examples/saml/servlet-filter/src/main/webapp/protected/chart.jsp
@@ -0,0 +1,15 @@
+<div align="center">
+<h1>SalesTool</h1>
+<br/>
+Welcome to the Sales Tool, <%=request.getUserPrincipal().getName()%>
+    <br/>
+    <a href="?GLO=true">Click to LogOut</a>
+    <br/>
+    <br/>
+Here is your sales chart:
+<br/>
+<img src="piechart.gif"/>
+
+<br/>
+
+</div>
                diff --git a/examples/saml/servlet-filter/src/main/webapp/protected/piechart.gif b/examples/saml/servlet-filter/src/main/webapp/protected/piechart.gif
new file mode 100755
index 0000000..57bfe37
Binary files /dev/null and b/examples/saml/servlet-filter/src/main/webapp/protected/piechart.gif differ
                diff --git a/examples/saml/servlet-filter/src/main/webapp/WEB-INF/keycloak-saml.xml b/examples/saml/servlet-filter/src/main/webapp/WEB-INF/keycloak-saml.xml
new file mode 100755
index 0000000..f27a39e
--- /dev/null
+++ b/examples/saml/servlet-filter/src/main/webapp/WEB-INF/keycloak-saml.xml
@@ -0,0 +1,38 @@
+<keycloak-saml-adapter>
+    <SP entityID="http://localhost:8080/saml-servlet-filter/"
+        sslPolicy="EXTERNAL"
+        logoutPage="/logout.jsp">
+        <Keys>
+            <Key signing="true">
+                <PrivateKeyPem>
+                    MIICWwIBAAKBgQDVG8a7xGN6ZIkDbeecySygcDfsypjUMNPE4QJjis8B316CvsZQ0hcTTLUyiRpHlHZys2k3xEhHBHymFC1AONcvzZzpb40tAhLHO1qtAnut00khjAdjR3muLVdGkM/zMC7G5s9iIwBVhwOQhy+VsGnCH91EzkjZ4SVEr55KJoyQJQIDAQABAoGADaTtoG/+foOZUiLjRWKL/OmyavK9vjgyFtThNkZY4qHOh0h3og0RdSbgIxAsIpEa1FUwU2W5yvI6mNeJ3ibFgCgcxqPk6GkAC7DWfQfdQ8cS+dCuaFTs8ObIQEvU50YzeNPiiFxRA+MnauCUXaKm/PnDfjd4tPgru7XZvlGh0wECQQDsBbN2cKkBKpr/b5oJiBcBaSZtWiMNuYBDn9x8uORj+Gy/49BUIMHF2EWyxOWz6ocP5YiynNRkPe21Zus7PEr1AkEA5yWQOkxUTIg43s4pxNSeHtL+Ebqcg54lY2xOQK0yufxUVZI8ODctAKmVBMiCKpU3mZQquOaQicuGtocpgxlScQI/YM31zZ5nsxLGf/5GL6KhzPJT0IYn2nk7IoFu7bjn9BjwgcPurpLA52TNMYWQsTqAKwT6DEhG1NaRqNWNpb4VAkBehObAYBwMm5udyHIeEc+CzUalm0iLLa0eRdiN7AUVNpCJ2V2Uo0NcxPux1AgeP5xXydXafDXYkwhINWcNO9qRAkEA58ckAC5loUGwU5dLaugsGH/a2Q8Ac8bmPglwfCstYDpl8Gp/eimb1eKyvDEELOhyImAv4/uZV9wN85V0xZXWsw==
+                </PrivateKeyPem>
+                <CertificatePem>
+                    MIIB1DCCAT0CBgFJGP5dZDANBgkqhkiG9w0BAQsFADAwMS4wLAYDVQQDEyVodHRwOi8vbG9jYWxob3N0OjgwODAvc2FsZXMtcG9zdC1zaWcvMB4XDTE0MTAxNjEyNDQyM1oXDTI0MTAxNjEyNDYwM1owMDEuMCwGA1UEAxMlaHR0cDovL2xvY2FsaG9zdDo4MDgwL3NhbGVzLXBvc3Qtc2lnLzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA1RvGu8RjemSJA23nnMksoHA37MqY1DDTxOECY4rPAd9egr7GUNIXE0y1MokaR5R2crNpN8RIRwR8phQtQDjXL82c6W+NLQISxztarQJ7rdNJIYwHY0d5ri1XRpDP8zAuxubPYiMAVYcDkIcvlbBpwh/dRM5I2eElRK+eSiaMkCUCAwEAATANBgkqhkiG9w0BAQsFAAOBgQCLms6htnPaY69k1ntm9a5jgwSn/K61cdai8R8B0ccY7zvinn9AfRD7fiROQpFyY29wKn8WCLrJ86NBXfgFUGyR5nLNHVy3FghE36N2oHy53uichieMxffE6vhkKJ4P8ChfJMMOZlmCPsQPDvjoAghHt4mriFiQgRdPgIy/zDjSNw==
+                </CertificatePem>
+            </Key>
+        </Keys>
+        <IDP entityID="idp"
+             signatureAlgorithm="RSA_SHA256">
+            <SingleSignOnService signRequest="true"
+                                 validateResponseSignature="true"
+                                 requestBinding="POST"
+                                 bindingUrl="http://localhost:8080/auth/realms/saml-demo/protocol/saml"/>
+            <SingleLogoutService signRequest="true"
+                                 signResponse="true"
+                                 validateRequestSignature="true"
+                                 validateResponseSignature="true"
+                                 requestBinding="POST"
+                                 responseBinding="POST"
+                                 postBindingUrl="http://localhost:8080/auth/realms/saml-demo/protocol/saml"
+                                 redirectBindingUrl="http://localhost:8080/auth/realms/saml-demo/protocol/saml"/>
+            <Keys>
+                <Key signing="true">
+                    <CertificatePem>
+                        MIIBnDCCAQUCBgFSo+s8KTANBgkqhkiG9w0BAQsFADAUMRIwEAYDVQQDDAlzYW1sLWRlbW8wHhcNMTYwMjAyMjEzNTQ4WhcNMjYwMjAyMjEzNzI4WjAUMRIwEAYDVQQDDAlzYW1sLWRlbW8wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAKtWsK5O0CtuBpnMvWG+HTG0vmZzujQ2o9WdheQu+BzCILcGMsbDW0YQaglpcO5JpGWWhubnckGGPHfdQ2/7nP9QwbiTK0FbGF41UqcvoaCqU1psxoV88s8IXyQCAqeyLv00yj6foqdJjxh5SZ5z+na+M7Y2OxIBVxYRAxWEnfUvAgMBAAEwDQYJKoZIhvcNAQELBQADgYEAi8/ltyBrrck7ixXfvNmvl50R0KmdHXoe65KVeH9CQmFPolVWeiv7rRr3QxOLjiz2EWoVRWViKHgzZt+rtVOiTDQGTFWsr84yHuFBonlSrmk21uj7Tupdu2Huv8JdHp8ueqSeIW7uV79RvxW7aB420jYCl9OSuQ0OTZ+ECcpxm8I=
+                    </CertificatePem>
+                </Key>
+            </Keys>
+        </IDP>
+    </SP>
+</keycloak-saml-adapter>
                diff --git a/examples/saml/servlet-filter/src/main/webapp/WEB-INF/web.xml b/examples/saml/servlet-filter/src/main/webapp/WEB-INF/web.xml
new file mode 100755
index 0000000..7c85fa0
--- /dev/null
+++ b/examples/saml/servlet-filter/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
+         version="3.0">
+
+    <module-name>saml-servlet-filter</module-name>
+    <filter>
+        <filter-name>Keycloak Filter</filter-name>
+        <filter-class>org.keycloak.adapters.saml.servlet.SamlFilter</filter-class>
+    </filter>
+    <filter-mapping>
+        <filter-name>Keycloak Filter</filter-name>
+        <url-pattern>/saml</url-pattern>  <!-- you have to have this as this is the saml endpoint -->
+        <url-pattern>/protected/*</url-pattern> <!-- this is for the content you want to protect -->
+    </filter-mapping>
+</web-app>
                examples/saml/testsaml.json 19(+19 -0)
diff --git a/examples/saml/testsaml.json b/examples/saml/testsaml.json
index eb666e1..aae0eb3 100755
--- a/examples/saml/testsaml.json
+++ b/examples/saml/testsaml.json
@@ -45,6 +45,25 @@
             }
         },
         {
+            "clientId": "http://localhost:8080/saml-servlet-filter/",
+            "enabled": true,
+            "protocol": "saml",
+            "fullScopeAllowed": true,
+            "baseUrl": "http://localhost:8080/saml-servlet-filter/",
+            "adminUrl": "http://localhost:8080/saml-servlet-filter/saml",
+            "redirectUris": [
+                "http://localhost:8080/saml-servlet-filter/*"
+            ],
+            "attributes": {
+                "saml.server.signature": "true",
+                "saml.signature.algorithm": "RSA_SHA256",
+                "saml.client.signature": "true",
+                "saml.authnstatement": "true",
+                "saml.signing.private.key": "MIICWwIBAAKBgQDVG8a7xGN6ZIkDbeecySygcDfsypjUMNPE4QJjis8B316CvsZQ0hcTTLUyiRpHlHZys2k3xEhHBHymFC1AONcvzZzpb40tAhLHO1qtAnut00khjAdjR3muLVdGkM/zMC7G5s9iIwBVhwOQhy+VsGnCH91EzkjZ4SVEr55KJoyQJQIDAQABAoGADaTtoG/+foOZUiLjRWKL/OmyavK9vjgyFtThNkZY4qHOh0h3og0RdSbgIxAsIpEa1FUwU2W5yvI6mNeJ3ibFgCgcxqPk6GkAC7DWfQfdQ8cS+dCuaFTs8ObIQEvU50YzeNPiiFxRA+MnauCUXaKm/PnDfjd4tPgru7XZvlGh0wECQQDsBbN2cKkBKpr/b5oJiBcBaSZtWiMNuYBDn9x8uORj+Gy/49BUIMHF2EWyxOWz6ocP5YiynNRkPe21Zus7PEr1AkEA5yWQOkxUTIg43s4pxNSeHtL+Ebqcg54lY2xOQK0yufxUVZI8ODctAKmVBMiCKpU3mZQquOaQicuGtocpgxlScQI/YM31zZ5nsxLGf/5GL6KhzPJT0IYn2nk7IoFu7bjn9BjwgcPurpLA52TNMYWQsTqAKwT6DEhG1NaRqNWNpb4VAkBehObAYBwMm5udyHIeEc+CzUalm0iLLa0eRdiN7AUVNpCJ2V2Uo0NcxPux1AgeP5xXydXafDXYkwhINWcNO9qRAkEA58ckAC5loUGwU5dLaugsGH/a2Q8Ac8bmPglwfCstYDpl8Gp/eimb1eKyvDEELOhyImAv4/uZV9wN85V0xZXWsw==",
+                "saml.signing.certificate": "MIIB1DCCAT0CBgFJGP5dZDANBgkqhkiG9w0BAQsFADAwMS4wLAYDVQQDEyVodHRwOi8vbG9jYWxob3N0OjgwODAvc2FsZXMtcG9zdC1zaWcvMB4XDTE0MTAxNjEyNDQyM1oXDTI0MTAxNjEyNDYwM1owMDEuMCwGA1UEAxMlaHR0cDovL2xvY2FsaG9zdDo4MDgwL3NhbGVzLXBvc3Qtc2lnLzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA1RvGu8RjemSJA23nnMksoHA37MqY1DDTxOECY4rPAd9egr7GUNIXE0y1MokaR5R2crNpN8RIRwR8phQtQDjXL82c6W+NLQISxztarQJ7rdNJIYwHY0d5ri1XRpDP8zAuxubPYiMAVYcDkIcvlbBpwh/dRM5I2eElRK+eSiaMkCUCAwEAATANBgkqhkiG9w0BAQsFAAOBgQCLms6htnPaY69k1ntm9a5jgwSn/K61cdai8R8B0ccY7zvinn9AfRD7fiROQpFyY29wKn8WCLrJ86NBXfgFUGyR5nLNHVy3FghE36N2oHy53uichieMxffE6vhkKJ4P8ChfJMMOZlmCPsQPDvjoAghHt4mriFiQgRdPgIy/zDjSNw=="
+            }
+        },
+        {
             "clientId": "http://localhost:8080/sales-post-enc/",
             "enabled": true,
             "protocol": "saml",