keycloak-memoizeit

Changes

pom.xml 6(+3 -3)

saml/client-adapter/wildfly/wildfly9-subsystem/src/main/java/org/keycloak/subsystem/adapter/saml/extension/KeycloakSubsystemParser.java 91(+0 -91)

Details

diff --git a/distribution/demo-dist/assembly.xml b/distribution/demo-dist/assembly.xml
index f1c39c2..a06ed13 100755
--- a/distribution/demo-dist/assembly.xml
+++ b/distribution/demo-dist/assembly.xml
@@ -40,7 +40,7 @@
             </excludes>
         </fileSet>
         <fileSet>
-            <directory>${project.build.directory}/unpacked/keycloak-saml-wf9-adapter-${project.version}</directory>
+            <directory>${project.build.directory}/unpacked/keycloak-saml-wildfly-adapter-${project.version}</directory>
             <outputDirectory>keycloak</outputDirectory>
             <excludes>
                 <exclude>standalone/configuration/standalone-keycloak.xml</exclude>
diff --git a/distribution/demo-dist/pom.xml b/distribution/demo-dist/pom.xml
index 9443478..baebb36 100755
--- a/distribution/demo-dist/pom.xml
+++ b/distribution/demo-dist/pom.xml
@@ -26,7 +26,7 @@
         </dependency>
         <dependency>
             <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-saml-wf9-adapter-dist</artifactId>
+            <artifactId>keycloak-saml-wildfly-adapter-dist</artifactId>
             <type>zip</type>
         </dependency>
         <dependency>
@@ -116,9 +116,9 @@
                             <artifactItems>
                                 <artifactItem>
                                     <groupId>org.keycloak</groupId>
-                                    <artifactId>keycloak-saml-wf9-adapter-dist</artifactId>
+                                    <artifactId>keycloak-saml-wildfly-adapter-dist</artifactId>
                                     <type>zip</type>
-                                    <outputDirectory>${project.build.directory}/unpacked/keycloak-saml-wf9-adapter-${project.version}</outputDirectory>
+                                    <outputDirectory>${project.build.directory}/unpacked/keycloak-saml-wildfly-adapter-${project.version}</outputDirectory>
                                 </artifactItem>
                             </artifactItems>
                         </configuration>
diff --git a/distribution/demo-dist/src/main/xslt/standalone.xsl b/distribution/demo-dist/src/main/xslt/standalone.xsl
index 106c08f..9f52547 100755
--- a/distribution/demo-dist/src/main/xslt/standalone.xsl
+++ b/distribution/demo-dist/src/main/xslt/standalone.xsl
@@ -44,7 +44,7 @@
                 <web-context>auth</web-context>
             </subsystem>
             <subsystem xmlns="urn:jboss:domain:keycloak:1.1"/>
-            <subsystem xmlns="urn:jboss:domain:keycloak-saml:1.6"/>
+            <subsystem xmlns="urn:jboss:domain:keycloak-saml:1.1"/>
         </xsl:copy>
     </xsl:template>
 
diff --git a/distribution/downloads/pom.xml b/distribution/downloads/pom.xml
index b9daadf..9e91285 100755
--- a/distribution/downloads/pom.xml
+++ b/distribution/downloads/pom.xml
@@ -338,12 +338,12 @@
 
                                <artifactItem>
                                     <groupId>org.keycloak</groupId>
-                                    <artifactId>keycloak-saml-wf9-adapter-dist</artifactId>
+                                    <artifactId>keycloak-saml-wildfly-adapter-dist</artifactId>
                                     <type>zip</type>
                                 </artifactItem>
                                 <artifactItem>
                                     <groupId>org.keycloak</groupId>
-                                    <artifactId>keycloak-saml-wf9-adapter-dist</artifactId>
+                                    <artifactId>keycloak-saml-wildfly-adapter-dist</artifactId>
                                     <type>tar.gz</type>
                                 </artifactItem>
                             </artifactItems>
diff --git a/distribution/saml-adapters/pom.xml b/distribution/saml-adapters/pom.xml
index 456f292..ea95663 100755
--- a/distribution/saml-adapters/pom.xml
+++ b/distribution/saml-adapters/pom.xml
@@ -15,7 +15,7 @@
     <packaging>pom</packaging>
 
     <modules>
-        <module>wf9-adapter</module>
+        <module>wildfly-adapter</module>
         <module>tomcat6-adapter-zip</module>
         <module>tomcat7-adapter-zip</module>
         <module>tomcat8-adapter-zip</module>
diff --git a/docbook/saml-adapter-docs/reference/en/en-US/modules/jboss-adapter.xml b/docbook/saml-adapter-docs/reference/en/en-US/modules/jboss-adapter.xml
index fc29402..df07d8d 100755
--- a/docbook/saml-adapter-docs/reference/en/en-US/modules/jboss-adapter.xml
+++ b/docbook/saml-adapter-docs/reference/en/en-US/modules/jboss-adapter.xml
@@ -3,7 +3,7 @@
     <para>
         To be able to secure WAR apps deployed on JBoss EAP 6.x or Wildfly, you must install and
         configure the Keycloak SAML Adapter Subsystem.  You then provide a keycloak
-        config, <literal>/WEB-INF/keycloak-saml</literal> file in your WAR and change the auth-method to KEYCLOAK-SAML within web.xml.
+        config, <literal>/WEB-INF/keycloak-saml.xml</literal> file in your WAR and change the auth-method to KEYCLOAK-SAML within web.xml.
         Both methods are described in this section.
     </para>
     <section id="jboss-adapter-installation">
@@ -13,10 +13,10 @@
         the Keycloak download site.  They are also available as a maven artifact.
     </para>
     <para>
-        Install on Wildfly 9:
+        Install on Wildfly 9 or 10:
 <programlisting>
 $ cd $WILDFLY_HOME
-$ unzip keycloak-saml-wf9-adapter-dist.zip
+$ unzip keycloak-saml-wildfly-adapter-dist.zip
 </programlisting>
     </para>
     <para>
@@ -52,7 +52,7 @@ $ jboss-cli.sh -c --file=adapter-install.cli
     </extensions>
 
     <profile>
-        <subsystem xmlns="urn:jboss:domain:keycloak-saml:1.6"/>
+        <subsystem xmlns="urn:jboss:domain:keycloak-saml:1.1"/>
          ...
     </profile>
 ]]>
@@ -185,4 +185,92 @@ public class CustomerService {
 </programlisting>
         </para>
     </section>
+    <section>
+        <title>Securing WARs via Keycloak SAML Subsystem</title>
+        <para>
+            You do not have to crack open a WAR to secure it with Keycloak.  Alternatively, you can externally secure
+            it via the Keycloak SAML Adapter Subsystem.  While you don't have to specify KEYCLOAK-SAML as an <literal>auth-method</literal>,
+            you still have to define the <literal>security-constraints</literal> in <literal>web.xml</literal>.  You do
+            not, however, have to create a <literal>WEB-INF/keycloak-saml.xml</literal> file.  This metadata is instead defined
+            within XML in your server's <literal>domain.xml</literal> or <literal>standalone.xml</literal> subsystem
+            configuration section.
+        </para>
+        <para>
+            <programlisting><![CDATA[
+<extensions>
+  <extension module="org.keycloak.keycloak-saml-adapter-subsystem"/>
+</extensions>
+
+<profile>
+  <subsystem xmlns="urn:jboss:domain:keycloak-saml:1.1">
+    <secure-deployment name="WAR MODULE NAME.war">
+      <SP entityID="APPLICATION URL">
+        ...
+      </SP>
+    </secure-deployment>
+  </subsystem>
+</profile>
+]]>
+            </programlisting>
+        </para>
+        <para>
+            The <literal>secure-deployment</literal> <literal>name</literal> attribute identifies the WAR you want
+            to secure.  Its value is the <literal>module-name</literal> defined in <literal>web.xml</literal> with
+            <literal>.war</literal> appended.  The rest of the configuration uses the same XML syntax as
+            <literal>keycloak-saml.xml</literal> configuration defined in <link linkend='adapter-config'>general adapter configuration</link>.
+        </para>
+        <para>
+            An example configuration:
+        </para>
+        <para>
+            <programlisting><![CDATA[
+<subsystem xmlns="urn:jboss:domain:keycloak-saml:1.1">
+  <secure-deployment name="saml-post-encryption.war">
+    <SP entityID="http://localhost:8080/sales-post-enc/"
+        sslPolicy="EXTERNAL"
+        nameIDPolicyFormat="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified"
+        logoutPage="/logout.jsp"
+        forceAuthentication="false">
+      <Keys>
+        <Key signing="true" encryption="true">
+          <KeyStore resource="/WEB-INF/keystore.jks" password="store123">
+            <PrivateKey alias="http://localhost:8080/sales-post-enc/" password="test123"/>
+            <Certificate alias="http://localhost:8080/sales-post-enc/"/>
+          </KeyStore>
+        </Key>
+      </Keys>
+      <PrincipalNameMapping policy="FROM_NAME_ID"/>
+      <RoleIdentifiers>
+        <Attribute name="Role"/>
+      </RoleIdentifiers>
+      <IDP entityID="idp">
+        <SingleSignOnService signRequest="true"
+            validateResponseSignature="true"
+            requestBinding="POST"
+            bindingUrl="http://localhost:8080/auth/realms/saml-demo/protocol/saml"/>
+
+        <SingleLogoutService
+            validateRequestSignature="true"
+            validateResponseSignature="true"
+            signRequest="true"
+            signResponse="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" >
+            <KeyStore resource="/WEB-INF/keystore.jks" password="store123">
+              <Certificate alias="saml-demo"/>
+            </KeyStore>
+          </Key>
+        </Keys>
+      </IDP>
+    </SP>
+   </secure-deployment>
+</subsystem>
+]]>
+            </programlisting>
+        </para>
+    </section>
 </chapter>
\ No newline at end of file

pom.xml 6(+3 -3)

diff --git a/pom.xml b/pom.xml
index 62ae25c..b81ec57 100755
--- a/pom.xml
+++ b/pom.xml
@@ -1048,7 +1048,7 @@
             </dependency>
             <dependency>
                 <groupId>org.keycloak</groupId>
-                <artifactId>keycloak-saml-wf9-subsystem</artifactId>
+                <artifactId>keycloak-saml-wildfly-subsystem</artifactId>
                 <version>${project.version}</version>
             </dependency>
             <dependency>
@@ -1143,7 +1143,7 @@
             </dependency>
             <dependency>
                 <groupId>org.keycloak</groupId>
-                <artifactId>keycloak-saml-wf9-modules</artifactId>
+                <artifactId>keycloak-saml-wildfly-modules</artifactId>
                 <version>${project.version}</version>
                 <type>zip</type>
             </dependency>
@@ -1155,7 +1155,7 @@
             </dependency>
             <dependency>
                 <groupId>org.keycloak</groupId>
-                <artifactId>keycloak-saml-wf9-adapter-dist</artifactId>
+                <artifactId>keycloak-saml-wildfly-adapter-dist</artifactId>
                 <version>${project.version}</version>
                 <type>zip</type>
             </dependency>
diff --git a/saml/client-adapter/as7-eap6/adapter/pom.xml b/saml/client-adapter/as7-eap6/adapter/pom.xml
index 6d1ace8..da632c7 100755
--- a/saml/client-adapter/as7-eap6/adapter/pom.xml
+++ b/saml/client-adapter/as7-eap6/adapter/pom.xml
@@ -31,10 +31,6 @@
             <artifactId>keycloak-saml-adapter-core</artifactId>
         </dependency>
         <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-saml-adapter-core</artifactId>
-        </dependency>
-        <dependency>
             <groupId>org.bouncycastle</groupId>
             <artifactId>bcprov-jdk15on</artifactId>
         </dependency>
diff --git a/saml/client-adapter/as7-eap6/subsystem/pom.xml b/saml/client-adapter/as7-eap6/subsystem/pom.xml
index fa87dcf..872e5d1 100755
--- a/saml/client-adapter/as7-eap6/subsystem/pom.xml
+++ b/saml/client-adapter/as7-eap6/subsystem/pom.xml
@@ -101,9 +101,9 @@ projects that depend on this project.-->
         </dependency>
 
         <dependency>
-            <groupId>org.jboss.msc</groupId>
-            <artifactId>jboss-msc</artifactId>
-            <version>1.0.2.GA</version>
+            <groupId>org.jboss.as</groupId>
+            <artifactId>jboss-as-controller</artifactId>
+            <version>${jboss.version}</version>
         </dependency>
 
         <dependency>
diff --git a/saml/client-adapter/as7-eap6/subsystem/src/main/java/org/keycloak/subsystem/saml/as7/Configuration.java b/saml/client-adapter/as7-eap6/subsystem/src/main/java/org/keycloak/subsystem/saml/as7/Configuration.java
new file mode 100644
index 0000000..966cd67
--- /dev/null
+++ b/saml/client-adapter/as7-eap6/subsystem/src/main/java/org/keycloak/subsystem/saml/as7/Configuration.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2015 Red Hat Inc. and/or its affiliates and other contributors
+ * as indicated by the @author tags. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package org.keycloak.subsystem.saml.as7;
+
+import org.jboss.dmr.ModelNode;
+import org.jboss.dmr.Property;
+
+/**
+ * @author <a href="mailto:mstrukel@redhat.com">Marko Strukelj</a>
+ */
+public class Configuration {
+
+    static final Configuration INSTANCE = new Configuration();
+
+    private ModelNode config = new ModelNode();
+
+    private Configuration() {
+    }
+
+    void updateModel(ModelNode operation, ModelNode model) {
+        ModelNode node = config;
+        ModelNode addr = operation.get("address");
+        for (Property item : addr.asPropertyList()) {
+            node = getNodeForAddressElement(node, item);
+        }
+        node.set(model);
+    }
+
+    private ModelNode getNodeForAddressElement(ModelNode node, Property item) {
+        String key = item.getValue().asString();
+        ModelNode keymodel = node.get(item.getName());
+        return keymodel.get(key);
+    }
+
+    public ModelNode getSecureDeployment(String name) {
+        ModelNode secureDeployment = config.get("subsystem").get("keycloak-saml").get(Constants.Model.SECURE_DEPLOYMENT);
+        if (secureDeployment.hasDefined(name)) {
+            return secureDeployment.get(name);
+        }
+        return null;
+    }
+
+    public boolean isSecureDeployment(String name) {
+        return getSecureDeployment(name) != null;
+    }
+}
diff --git a/saml/client-adapter/as7-eap6/subsystem/src/main/java/org/keycloak/subsystem/saml/as7/Constants.java b/saml/client-adapter/as7-eap6/subsystem/src/main/java/org/keycloak/subsystem/saml/as7/Constants.java
new file mode 100644
index 0000000..07af4f7
--- /dev/null
+++ b/saml/client-adapter/as7-eap6/subsystem/src/main/java/org/keycloak/subsystem/saml/as7/Constants.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright 2015 Red Hat Inc. and/or its affiliates and other contributors
+ * as indicated by the @author tags. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package org.keycloak.subsystem.saml.as7;
+
+
+/**
+ * @author <a href="mailto:mstrukel@redhat.com">Marko Strukelj</a>
+ */
+public class Constants {
+
+    static class Model {
+        static final String SECURE_DEPLOYMENT = "secure-deployment";
+        static final String SERVICE_PROVIDER = "service-provider";
+
+        static final String SSL_POLICY = "ssl-policy";
+        static final String NAME_ID_POLICY_FORMAT = "name-id-policy-format";
+        static final String LOGOUT_PAGE = "logout-page";
+        static final String FORCE_AUTHENTICATION = "force-authentication";
+        static final String ROLE_ATTRIBUTES = "role-attributes";
+        static final String SIGNING = "signing";
+        static final String ENCRYPTION = "encryption";
+        static final String KEY = "key";
+        static final String RESOURCE = "resource";
+        static final String PASSWORD = "password";
+
+        static final String PRIVATE_KEY_ALIAS = "private-key-alias";
+        static final String PRIVATE_KEY_PASSWORD = "private-key-password";
+        static final String CERTIFICATE_ALIAS = "certificate-alias";
+        static final String KEY_STORE = "key-store";
+        static final String SIGN_REQUEST = "sign-request";
+        static final String VALIDATE_RESPONSE_SIGNATURE = "validate-response-signature";
+        static final String REQUEST_BINDING = "request-binding";
+        static final String BINDING_URL = "binding-url";
+        static final String VALIDATE_REQUEST_SIGNATURE = "validate-request-signature";
+        static final String SIGN_RESPONSE = "sign-response";
+        static final String RESPONSE_BINDING = "response-binding";
+        static final String POST_BINDING_URL = "post-binding-url";
+        static final String REDIRECT_BINDING_URL = "redirect-binding-url";
+        static final String SINGLE_SIGN_ON = "single-sign-on";
+        static final String SINGLE_LOGOUT = "single-logout";
+        static final String IDENTITY_PROVIDER = "identity-provider";
+        static final String PRINCIPAL_NAME_MAPPING_POLICY = "principal-name-mapping-policy";
+        static final String PRINCIPAL_NAME_MAPPING_ATTRIBUTE_NAME = "principal-name-mapping-attribute-name";
+        static final String SIGNATURE_ALGORITHM = "signature-algorithm";
+        static final String SIGNATURE_CANONICALIZATION_METHOD = "signature-canonicalization-method";
+        static final String PRIVATE_KEY_PEM = "private-key-pem";
+        static final String PUBLIC_KEY_PEM = "public-key-pem";
+        static final String CERTIFICATE_PEM = "certificate-pem";
+        static final String TYPE = "type";
+        static final String ALIAS = "alias";
+        static final String FILE = "file";
+        static final String SIGNATURES_REQUIRED = "signatures-required";
+    }
+
+
+    static class XML {
+        static final String SECURE_DEPLOYMENT = "secure-deployment";
+        static final String SERVICE_PROVIDER = "SP";
+
+        static final String NAME = "name";
+        static final String ENTITY_ID = "entityID";
+        static final String SSL_POLICY = "sslPolicy";
+        static final String NAME_ID_POLICY_FORMAT = "nameIDPolicyFormat";
+        static final String LOGOUT_PAGE = "logoutPage";
+        static final String FORCE_AUTHENTICATION = "forceAuthentication";
+        static final String ROLE_IDENTIFIERS = "RoleIdentifiers";
+        static final String SIGNING = "signing";
+        static final String ENCRYPTION = "encryption";
+        static final String KEYS = "Keys";
+        static final String KEY = "Key";
+        static final String RESOURCE = "resource";
+        static final String PASSWORD = "password";
+        static final String KEY_STORE = "KeyStore";
+        static final String PRIVATE_KEY = "PrivateKey";
+        static final String CERTIFICATE = "Certificate";
+
+        static final String PRIVATE_KEY_ALIAS = "alias";
+        static final String PRIVATE_KEY_PASSWORD = "password";
+        static final String CERTIFICATE_ALIAS = "alias";
+        static final String SIGN_REQUEST = "signRequest";
+        static final String VALIDATE_RESPONSE_SIGNATURE = "validateResponseSignature";
+        static final String REQUEST_BINDING = "requestBinding";
+        static final String BINDING_URL = "bindingUrl";
+        static final String VALIDATE_REQUEST_SIGNATURE = "validateRequestSignature";
+        static final String SIGN_RESPONSE = "signResponse";
+        static final String RESPONSE_BINDING = "responseBinding";
+        static final String POST_BINDING_URL = "postBindingUrl";
+        static final String REDIRECT_BINDING_URL = "redirectBindingUrl";
+        static final String SINGLE_SIGN_ON = "SingleSignOnService";
+        static final String SINGLE_LOGOUT = "SingleLogoutService";
+        static final String IDENTITY_PROVIDER = "IDP";
+        static final String PRINCIPAL_NAME_MAPPING = "PrincipalNameMapping";
+        static final String PRINCIPAL_NAME_MAPPING_POLICY = "policy";
+        static final String PRINCIPAL_NAME_MAPPING_ATTRIBUTE_NAME = "attribute";
+        static final String ATTRIBUTE = "Attribute";
+        static final String SIGNATURE_ALGORITHM = "signatureAlgorithm";
+        static final String SIGNATURE_CANONICALIZATION_METHOD = "signatureCanonicalizationMethod";
+        static final String PRIVATE_KEY_PEM = "PrivateKeyPem";
+        static final String PUBLIC_KEY_PEM = "PublicKeyPem";
+        static final String CERTIFICATE_PEM = "CertificatePem";
+        static final String TYPE = "type";
+        static final String ALIAS = "alias";
+        static final String FILE = "file";
+        static final String SIGNATURES_REQUIRED = "signaturesRequired";
+    }
+}
diff --git a/saml/client-adapter/as7-eap6/subsystem/src/main/java/org/keycloak/subsystem/saml/as7/IdentityProviderAddHandler.java b/saml/client-adapter/as7-eap6/subsystem/src/main/java/org/keycloak/subsystem/saml/as7/IdentityProviderAddHandler.java
new file mode 100644
index 0000000..679658b
--- /dev/null
+++ b/saml/client-adapter/as7-eap6/subsystem/src/main/java/org/keycloak/subsystem/saml/as7/IdentityProviderAddHandler.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2015 Red Hat Inc. and/or its affiliates and other contributors
+ * as indicated by the @author tags. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package org.keycloak.subsystem.saml.as7;
+
+import org.jboss.as.controller.AbstractAddStepHandler;
+import org.jboss.as.controller.OperationContext;
+import org.jboss.as.controller.OperationFailedException;
+import org.jboss.as.controller.ServiceVerificationHandler;
+import org.jboss.dmr.ModelNode;
+import org.jboss.msc.service.ServiceController;
+
+import java.util.List;
+
+/**
+ * @author <a href="mailto:mstrukel@redhat.com">Marko Strukelj</a>
+ */
+class IdentityProviderAddHandler extends AbstractAddStepHandler {
+
+    IdentityProviderAddHandler() {
+        super(IdentityProviderDefinition.ALL_ATTRIBUTES);
+    }
+
+    @Override
+    protected void performRuntime(OperationContext context, ModelNode operation, ModelNode model, ServiceVerificationHandler verificationHandler, List<ServiceController<?>> newControllers) throws OperationFailedException {
+        Configuration.INSTANCE.updateModel(operation, model);
+    }
+}
diff --git a/saml/client-adapter/as7-eap6/subsystem/src/main/java/org/keycloak/subsystem/saml/as7/IdentityProviderDefinition.java b/saml/client-adapter/as7-eap6/subsystem/src/main/java/org/keycloak/subsystem/saml/as7/IdentityProviderDefinition.java
new file mode 100644
index 0000000..09262f9
--- /dev/null
+++ b/saml/client-adapter/as7-eap6/subsystem/src/main/java/org/keycloak/subsystem/saml/as7/IdentityProviderDefinition.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2015 Red Hat Inc. and/or its affiliates and other contributors
+ * as indicated by the @author tags. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package org.keycloak.subsystem.saml.as7;
+
+import org.jboss.as.controller.AttributeDefinition;
+import org.jboss.as.controller.ObjectTypeAttributeDefinition;
+import org.jboss.as.controller.OperationStepHandler;
+import org.jboss.as.controller.PathElement;
+import org.jboss.as.controller.ReloadRequiredRemoveStepHandler;
+import org.jboss.as.controller.ReloadRequiredWriteAttributeHandler;
+import org.jboss.as.controller.SimpleAttributeDefinition;
+import org.jboss.as.controller.SimpleAttributeDefinitionBuilder;
+import org.jboss.as.controller.SimpleResourceDefinition;
+import org.jboss.as.controller.operations.common.GenericSubsystemDescribeHandler;
+import org.jboss.as.controller.registry.ManagementResourceRegistration;
+import org.jboss.dmr.ModelType;
+
+import java.util.HashMap;
+
+/**
+ * @author <a href="mailto:mstrukel@redhat.com">Marko Strukelj</a>
+ */
+public class IdentityProviderDefinition extends SimpleResourceDefinition {
+
+    static final SimpleAttributeDefinition SIGNATURES_REQUIRED =
+            new SimpleAttributeDefinitionBuilder(Constants.Model.SIGNATURES_REQUIRED, ModelType.BOOLEAN, true)
+                    .setXmlName(Constants.XML.SIGNATURES_REQUIRED)
+                    .build();
+
+    static final SimpleAttributeDefinition SIGNATURE_ALGORITHM =
+            new SimpleAttributeDefinitionBuilder(Constants.Model.SIGNATURE_ALGORITHM, ModelType.STRING, true)
+                    .setXmlName(Constants.XML.SIGNATURE_ALGORITHM)
+                    .build();
+
+    static final SimpleAttributeDefinition SIGNATURE_CANONICALIZATION_METHOD =
+            new SimpleAttributeDefinitionBuilder(Constants.Model.SIGNATURE_CANONICALIZATION_METHOD, ModelType.STRING, true)
+                    .setXmlName(Constants.XML.SIGNATURE_CANONICALIZATION_METHOD)
+                    .build();
+
+    static final ObjectTypeAttributeDefinition SINGLE_SIGN_ON =
+            ObjectTypeAttributeDefinition.Builder.of(Constants.Model.SINGLE_SIGN_ON,
+                    SingleSignOnDefinition.ATTRIBUTES)
+                    .setAllowNull(false)
+                    .build();
+
+    static final ObjectTypeAttributeDefinition SINGLE_LOGOUT =
+            ObjectTypeAttributeDefinition.Builder.of(Constants.Model.SINGLE_LOGOUT,
+                    SingleLogoutDefinition.ATTRIBUTES)
+                    .setAllowNull(false)
+                    .build();
+
+    static final SimpleAttributeDefinition[] ATTRIBUTES = {SIGNATURES_REQUIRED, SIGNATURE_ALGORITHM, SIGNATURE_CANONICALIZATION_METHOD};
+
+    static final SimpleAttributeDefinition[] ALL_ATTRIBUTES = {SIGNATURES_REQUIRED, SIGNATURE_ALGORITHM, SIGNATURE_CANONICALIZATION_METHOD, SINGLE_SIGN_ON, SINGLE_LOGOUT};
+
+    static final HashMap<String, SimpleAttributeDefinition> ATTRIBUTE_MAP = new HashMap<>();
+
+    static {
+        for (SimpleAttributeDefinition def : ALL_ATTRIBUTES) {
+            ATTRIBUTE_MAP.put(def.getXmlName(), def);
+        }
+    }
+
+    static final IdentityProviderDefinition INSTANCE = new IdentityProviderDefinition();
+
+    private IdentityProviderDefinition() {
+        super(PathElement.pathElement(Constants.Model.IDENTITY_PROVIDER),
+                KeycloakSamlExtension.getResourceDescriptionResolver(Constants.Model.IDENTITY_PROVIDER),
+                new IdentityProviderAddHandler(),
+                ReloadRequiredRemoveStepHandler.INSTANCE);
+    }
+
+    @Override
+    public void registerOperations(ManagementResourceRegistration resourceRegistration) {
+        super.registerOperations(resourceRegistration);
+        resourceRegistration.registerOperationHandler(GenericSubsystemDescribeHandler.DEFINITION, GenericSubsystemDescribeHandler.INSTANCE);
+    }
+
+    @Override
+    public void registerAttributes(ManagementResourceRegistration resourceRegistration) {
+        super.registerAttributes(resourceRegistration);
+
+        final OperationStepHandler writeHandler = new ReloadRequiredWriteAttributeHandler(ALL_ATTRIBUTES);
+        for (AttributeDefinition attribute : ALL_ATTRIBUTES) {
+            resourceRegistration.registerReadWriteAttribute(attribute, null, writeHandler);
+        }
+    }
+
+    static SimpleAttributeDefinition lookup(String xmlName) {
+        return ATTRIBUTE_MAP.get(xmlName);
+    }
+}
\ No newline at end of file
diff --git a/saml/client-adapter/as7-eap6/subsystem/src/main/java/org/keycloak/subsystem/saml/as7/KeyAddHandler.java b/saml/client-adapter/as7-eap6/subsystem/src/main/java/org/keycloak/subsystem/saml/as7/KeyAddHandler.java
new file mode 100644
index 0000000..b362d4f
--- /dev/null
+++ b/saml/client-adapter/as7-eap6/subsystem/src/main/java/org/keycloak/subsystem/saml/as7/KeyAddHandler.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2015 Red Hat Inc. and/or its affiliates and other contributors
+ * as indicated by the @author tags. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package org.keycloak.subsystem.saml.as7;
+
+import org.jboss.as.controller.AbstractAddStepHandler;
+import org.jboss.as.controller.OperationContext;
+import org.jboss.as.controller.OperationFailedException;
+import org.jboss.as.controller.ServiceVerificationHandler;
+import org.jboss.dmr.ModelNode;
+import org.jboss.msc.service.ServiceController;
+
+import java.util.List;
+
+/**
+ * @author <a href="mailto:mstrukel@redhat.com">Marko Strukelj</a>
+ */
+class KeyAddHandler extends AbstractAddStepHandler {
+
+    KeyAddHandler() {
+        super(KeyDefinition.ALL_ATTRIBUTES);
+    }
+
+    @Override
+    protected void performRuntime(OperationContext context, ModelNode operation, ModelNode model, ServiceVerificationHandler verificationHandler, List<ServiceController<?>> newControllers) throws OperationFailedException {
+        Configuration.INSTANCE.updateModel(operation, model);
+    }
+}
diff --git a/saml/client-adapter/as7-eap6/subsystem/src/main/java/org/keycloak/subsystem/saml/as7/KeycloakAdapterConfigDeploymentProcessor.java b/saml/client-adapter/as7-eap6/subsystem/src/main/java/org/keycloak/subsystem/saml/as7/KeycloakAdapterConfigDeploymentProcessor.java
index 31008d4..68e4679 100755
--- a/saml/client-adapter/as7-eap6/subsystem/src/main/java/org/keycloak/subsystem/saml/as7/KeycloakAdapterConfigDeploymentProcessor.java
+++ b/saml/client-adapter/as7-eap6/subsystem/src/main/java/org/keycloak/subsystem/saml/as7/KeycloakAdapterConfigDeploymentProcessor.java
@@ -21,13 +21,22 @@ import org.jboss.as.server.deployment.DeploymentUnit;
 import org.jboss.as.server.deployment.DeploymentUnitProcessingException;
 import org.jboss.as.server.deployment.DeploymentUnitProcessor;
 import org.jboss.as.web.deployment.WarMetaData;
+import org.jboss.dmr.ModelNode;
 import org.jboss.logging.Logger;
 import org.jboss.metadata.javaee.spec.ParamValueMetaData;
 import org.jboss.metadata.web.jboss.JBossWebMetaData;
 import org.jboss.metadata.web.jboss.ValveMetaData;
 import org.jboss.metadata.web.spec.LoginConfigMetaData;
+import org.jboss.staxmapper.XMLExtendedStreamWriter;
+import org.keycloak.adapters.saml.AdapterConstants;
 import org.keycloak.adapters.saml.jbossweb.SamlAuthenticatorValve;
+import org.keycloak.subsystem.saml.as7.logging.KeycloakLogger;
+import org.keycloak.subsystem.saml.as7.xml.FormattingXMLStreamWriter;
 
+import javax.xml.stream.XMLOutputFactory;
+import javax.xml.stream.XMLStreamException;
+import java.io.ByteArrayOutputStream;
+import java.nio.charset.Charset;
 import java.util.ArrayList;
 import java.util.List;
 
@@ -39,22 +48,16 @@ import java.util.List;
 public class KeycloakAdapterConfigDeploymentProcessor implements DeploymentUnitProcessor {
     protected Logger log = Logger.getLogger(KeycloakAdapterConfigDeploymentProcessor.class);
 
-    // This param name is defined again in Keycloak Undertow Integration class
-    // org.keycloak.adapters.undertow.KeycloakServletExtension.  We have this value in
-    // two places to avoid dependency between Keycloak Subsystem and Keyclaok Undertow Integration.
-    public static final String AUTH_DATA_PARAM_NAME = "org.keycloak.saml.adapterConfig";
-
-
     @Override
     public void deploy(DeploymentPhaseContext phaseContext) throws DeploymentUnitProcessingException {
         DeploymentUnit deploymentUnit = phaseContext.getDeploymentUnit();
         String deploymentName = deploymentUnit.getName();
 
-        // if it's not a web-app there's nothing to secure
         WarMetaData warMetaData = deploymentUnit.getAttachment(WarMetaData.ATTACHMENT_KEY);
         if (warMetaData == null) {
             return;
         }
+
         JBossWebMetaData webMetaData = warMetaData.getMergedJBossWebMetaData();
         if (webMetaData == null) {
             webMetaData = new JBossWebMetaData();
@@ -64,12 +67,66 @@ public class KeycloakAdapterConfigDeploymentProcessor implements DeploymentUnitP
         // otherwise
         LoginConfigMetaData loginConfig = webMetaData.getLoginConfig();
 
-        boolean webRequiresKC = loginConfig != null && "KEYCLOAK-SAML".equalsIgnoreCase(loginConfig.getAuthMethod());
+        try {
+            boolean webRequiresKC = loginConfig != null && "KEYCLOAK-SAML".equalsIgnoreCase(loginConfig.getAuthMethod());
+            boolean hasSubsystemConfig = Configuration.INSTANCE.isSecureDeployment(deploymentName);
+            if (hasSubsystemConfig || webRequiresKC) {
+                log.debug("Setting up KEYCLOAK-SAML auth method for WAR: " + deploymentName);
+
+                // if secure-deployment configuration exists for web app, we force KEYCLOAK-SAML auth method on it
+                if (hasSubsystemConfig) {
+                    addXMLData(getXML(deploymentName), warMetaData);
+                    if (loginConfig != null) {
+                        loginConfig.setAuthMethod("KEYCLOAK-SAML");
+                        //loginConfig.setRealmName(service.getRealmName(deploymentName));
+                    } else {
+                        log.warn("Failed to set up KEYCLOAK-SAML auth method for WAR: " + deploymentName + " (loginConfig == null)");
+                    }
+                }
+                addValve(webMetaData);
+                KeycloakLogger.ROOT_LOGGER.deploymentSecured(deploymentName);
+            }
+        } catch (Exception e) {
+            throw new DeploymentUnitProcessingException("Failed to configure KeycloakSamlExtension from subsystem model", e);
+        }
+    }
+
+    private String getXML(String deploymentName) throws XMLStreamException {
+        ModelNode node = Configuration.INSTANCE.getSecureDeployment(deploymentName);
+        if (node != null) {
+            KeycloakSubsystemParser writer = new KeycloakSubsystemParser();
+            ByteArrayOutputStream output = new ByteArrayOutputStream();
+            XMLExtendedStreamWriter streamWriter = new FormattingXMLStreamWriter(XMLOutputFactory.newInstance().createXMLStreamWriter(output));
+            try {
+                streamWriter.writeStartElement("keycloak-saml-adapter");
+                writer.writeSps(streamWriter, node);
+                streamWriter.writeEndElement();
+            } finally {
+                streamWriter.close();
+            }
+            return new String(output.toByteArray(), Charset.forName("utf-8"));
+        }
+        return null;
+    }
+
+    private void addXMLData(String xml, WarMetaData warMetaData) {
+        JBossWebMetaData webMetaData = warMetaData.getMergedJBossWebMetaData();
+        if (webMetaData == null) {
+            webMetaData = new JBossWebMetaData();
+            warMetaData.setMergedJBossWebMetaData(webMetaData);
+        }
 
-        if (webRequiresKC) {
-            log.debug("Setting up KEYCLOAK-SAML auth method for WAR: " + deploymentName);
-            addValve(webMetaData);
+        List<ParamValueMetaData> contextParams = webMetaData.getContextParams();
+        if (contextParams == null) {
+            contextParams = new ArrayList<>();
         }
+
+        ParamValueMetaData param = new ParamValueMetaData();
+        param.setParamName(AdapterConstants.AUTH_DATA_PARAM_NAME);
+        param.setParamValue(xml);
+        contextParams.add(param);
+
+        webMetaData.setContextParams(contextParams);
     }
 
     private void addValve(JBossWebMetaData webMetaData) {
@@ -89,5 +146,4 @@ public class KeycloakAdapterConfigDeploymentProcessor implements DeploymentUnitP
     public void undeploy(DeploymentUnit du) {
 
     }
-
 }
diff --git a/saml/client-adapter/as7-eap6/subsystem/src/main/java/org/keycloak/subsystem/saml/as7/KeycloakSamlExtension.java b/saml/client-adapter/as7-eap6/subsystem/src/main/java/org/keycloak/subsystem/saml/as7/KeycloakSamlExtension.java
index c52f2b5..d936982 100755
--- a/saml/client-adapter/as7-eap6/subsystem/src/main/java/org/keycloak/subsystem/saml/as7/KeycloakSamlExtension.java
+++ b/saml/client-adapter/as7-eap6/subsystem/src/main/java/org/keycloak/subsystem/saml/as7/KeycloakSamlExtension.java
@@ -18,6 +18,7 @@ package org.keycloak.subsystem.saml.as7;
 
 import org.jboss.as.controller.Extension;
 import org.jboss.as.controller.ExtensionContext;
+import org.jboss.as.controller.ModelVersion;
 import org.jboss.as.controller.PathElement;
 import org.jboss.as.controller.ResourceDefinition;
 import org.jboss.as.controller.SubsystemRegistration;
@@ -36,15 +37,12 @@ import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.SUB
 public class KeycloakSamlExtension implements Extension {
 
     public static final String SUBSYSTEM_NAME = "keycloak-saml";
-    public static final String NAMESPACE = "urn:jboss:domain:keycloak-saml:1.6";
+    public static final String NAMESPACE = "urn:jboss:domain:keycloak-saml:1.1";
     private static final KeycloakSubsystemParser PARSER = new KeycloakSubsystemParser();
     static final PathElement PATH_SUBSYSTEM = PathElement.pathElement(SUBSYSTEM, SUBSYSTEM_NAME);
     private static final String RESOURCE_NAME = KeycloakSamlExtension.class.getPackage().getName() + ".LocalDescriptions";
-    private static final int MGMT_API_VERSION_MAJOR = 1;
-    private static final int MGMT_API_VERSION_MINOR = 1;
-
+    private static final ModelVersion MGMT_API_VERSION = ModelVersion.create(1, 1, 0);
     static final PathElement SUBSYSTEM_PATH = PathElement.pathElement(SUBSYSTEM, SUBSYSTEM_NAME);
-    private static final ResourceDefinition KEYCLOAK_SUBSYSTEM_RESOURCE = new KeycloakSubsystemDefinition();
 
     public static StandardResourceDescriptionResolver getResourceDescriptionResolver(final String... keyPrefix) {
         StringBuilder prefix = new StringBuilder(SUBSYSTEM_NAME);
@@ -67,10 +65,15 @@ public class KeycloakSamlExtension implements Extension {
      */
     @Override
     public void initialize(final ExtensionContext context) {
-        final SubsystemRegistration subsystem = context.registerSubsystem(SUBSYSTEM_NAME, MGMT_API_VERSION_MAJOR, MGMT_API_VERSION_MINOR);
-
-        ManagementResourceRegistration registration = subsystem.registerSubsystemModel(KEYCLOAK_SUBSYSTEM_RESOURCE);
+        final SubsystemRegistration subsystem = context.registerSubsystem(SUBSYSTEM_NAME,
+                MGMT_API_VERSION.getMajor(), MGMT_API_VERSION.getMinor(), MGMT_API_VERSION.getMicro());
 
+        ManagementResourceRegistration registration = subsystem.registerSubsystemModel(KeycloakSubsystemDefinition.INSTANCE);
+        ManagementResourceRegistration secureDeploymentRegistration = registration.registerSubModel(SecureDeploymentDefinition.INSTANCE);
+        ManagementResourceRegistration serviceProviderRegistration = secureDeploymentRegistration.registerSubModel(ServiceProviderDefinition.INSTANCE);
+        serviceProviderRegistration.registerSubModel(KeyDefinition.INSTANCE);
+        ManagementResourceRegistration idpRegistration = serviceProviderRegistration.registerSubModel(IdentityProviderDefinition.INSTANCE);
+        idpRegistration.registerSubModel(KeyDefinition.INSTANCE);
         subsystem.registerXMLElementWriter(PARSER);
     }
 }
diff --git a/saml/client-adapter/as7-eap6/subsystem/src/main/java/org/keycloak/subsystem/saml/as7/KeycloakSubsystemAdd.java b/saml/client-adapter/as7-eap6/subsystem/src/main/java/org/keycloak/subsystem/saml/as7/KeycloakSubsystemAdd.java
index 2a7fd55..eda678f 100755
--- a/saml/client-adapter/as7-eap6/subsystem/src/main/java/org/keycloak/subsystem/saml/as7/KeycloakSubsystemAdd.java
+++ b/saml/client-adapter/as7-eap6/subsystem/src/main/java/org/keycloak/subsystem/saml/as7/KeycloakSubsystemAdd.java
@@ -16,13 +16,12 @@
  */
 package org.keycloak.subsystem.saml.as7;
 
-
 import org.jboss.as.controller.AbstractBoottimeAddStepHandler;
 import org.jboss.as.controller.OperationContext;
-import org.jboss.as.controller.OperationFailedException;
 import org.jboss.as.controller.ServiceVerificationHandler;
 import org.jboss.as.server.AbstractDeploymentChainStep;
 import org.jboss.as.server.DeploymentProcessorTarget;
+import org.jboss.as.server.deployment.DeploymentUnitProcessor;
 import org.jboss.as.server.deployment.Phase;
 import org.jboss.dmr.ModelNode;
 import org.jboss.msc.service.ServiceController;
@@ -43,17 +42,20 @@ class KeycloakSubsystemAdd extends AbstractBoottimeAddStepHandler {
         context.addStep(new AbstractDeploymentChainStep() {
             @Override
             protected void execute(DeploymentProcessorTarget processorTarget) {
-                processorTarget.addDeploymentProcessor(Phase.DEPENDENCIES, 0, new KeycloakDependencyProcessorAS7());
-                processorTarget.addDeploymentProcessor(
+                processorTarget.addDeploymentProcessor(KeycloakSamlExtension.SUBSYSTEM_NAME, Phase.DEPENDENCIES, 0, chooseDependencyProcessor());
+                processorTarget.addDeploymentProcessor(KeycloakSamlExtension.SUBSYSTEM_NAME,
                         Phase.POST_MODULE, // PHASE
                         Phase.POST_MODULE_VALIDATOR_FACTORY - 1, // PRIORITY
-                        new KeycloakAdapterConfigDeploymentProcessor());
+                        chooseConfigDeploymentProcessor());
             }
         }, OperationContext.Stage.RUNTIME);
     }
 
-    @Override
-    protected void populateModel(ModelNode operation, ModelNode model) throws OperationFailedException {
-        model.setEmptyObject();
+    private DeploymentUnitProcessor chooseDependencyProcessor() {
+        return new KeycloakDependencyProcessorAS7();
+    }
+
+    private DeploymentUnitProcessor chooseConfigDeploymentProcessor() {
+        return new KeycloakAdapterConfigDeploymentProcessor();
     }
 }
diff --git a/saml/client-adapter/as7-eap6/subsystem/src/main/java/org/keycloak/subsystem/saml/as7/KeycloakSubsystemDefinition.java b/saml/client-adapter/as7-eap6/subsystem/src/main/java/org/keycloak/subsystem/saml/as7/KeycloakSubsystemDefinition.java
index 400822e..4b7ef3f 100755
--- a/saml/client-adapter/as7-eap6/subsystem/src/main/java/org/keycloak/subsystem/saml/as7/KeycloakSubsystemDefinition.java
+++ b/saml/client-adapter/as7-eap6/subsystem/src/main/java/org/keycloak/subsystem/saml/as7/KeycloakSubsystemDefinition.java
@@ -14,23 +14,23 @@
  * License for the specific language governing permissions and limitations under
  * the License.
  */
-
 package org.keycloak.subsystem.saml.as7;
 
 import org.jboss.as.controller.ReloadRequiredRemoveStepHandler;
 import org.jboss.as.controller.SimpleResourceDefinition;
-import org.jboss.as.controller.descriptions.ModelDescriptionConstants;
 import org.jboss.as.controller.operations.common.GenericSubsystemDescribeHandler;
 import org.jboss.as.controller.registry.ManagementResourceRegistration;
-import org.jboss.as.controller.registry.OperationEntry;
 
 /**
- * Definition of subsystem=keycloak.
+ * Definition of subsystem=keycloak-saml.
  *
  * @author Stan Silvert ssilvert@redhat.com (C) 2013 Red Hat Inc.
  */
 public class KeycloakSubsystemDefinition extends SimpleResourceDefinition {
-    protected KeycloakSubsystemDefinition() {
+
+    static final KeycloakSubsystemDefinition INSTANCE = new KeycloakSubsystemDefinition();
+
+    private KeycloakSubsystemDefinition() {
         super(KeycloakSamlExtension.SUBSYSTEM_PATH,
                 KeycloakSamlExtension.getResourceDescriptionResolver("subsystem"),
                 KeycloakSubsystemAdd.INSTANCE,
@@ -41,7 +41,6 @@ public class KeycloakSubsystemDefinition extends SimpleResourceDefinition {
     @Override
     public void registerOperations(ManagementResourceRegistration resourceRegistration) {
         super.registerOperations(resourceRegistration);
-        resourceRegistration.registerOperationHandler(ModelDescriptionConstants.DESCRIBE, GenericSubsystemDescribeHandler.INSTANCE, GenericSubsystemDescribeHandler.INSTANCE, false, OperationEntry.EntryType.PRIVATE);
+        resourceRegistration.registerOperationHandler(GenericSubsystemDescribeHandler.DEFINITION, GenericSubsystemDescribeHandler.INSTANCE);
     }
-
 }
diff --git a/saml/client-adapter/as7-eap6/subsystem/src/main/java/org/keycloak/subsystem/saml/as7/KeycloakSubsystemParser.java b/saml/client-adapter/as7-eap6/subsystem/src/main/java/org/keycloak/subsystem/saml/as7/KeycloakSubsystemParser.java
index 14899e1..0b2cef9 100755
--- a/saml/client-adapter/as7-eap6/subsystem/src/main/java/org/keycloak/subsystem/saml/as7/KeycloakSubsystemParser.java
+++ b/saml/client-adapter/as7-eap6/subsystem/src/main/java/org/keycloak/subsystem/saml/as7/KeycloakSubsystemParser.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2014 Red Hat Inc. and/or its affiliates and other contributors
+ * Copyright 2015 Red Hat Inc. and/or its affiliates and other contributors
  * as indicated by the @author tags. All rights reserved.
  *
  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
@@ -17,9 +17,14 @@
 package org.keycloak.subsystem.saml.as7;
 
 import org.jboss.as.controller.PathAddress;
+import org.jboss.as.controller.PathElement;
+import org.jboss.as.controller.SimpleAttributeDefinition;
+import org.jboss.as.controller.descriptions.ModelDescriptionConstants;
+import org.jboss.as.controller.operations.common.Util;
 import org.jboss.as.controller.parsing.ParseUtils;
 import org.jboss.as.controller.persistence.SubsystemMarshallingContext;
 import org.jboss.dmr.ModelNode;
+import org.jboss.dmr.Property;
 import org.jboss.staxmapper.XMLElementReader;
 import org.jboss.staxmapper.XMLElementWriter;
 import org.jboss.staxmapper.XMLExtendedStreamReader;
@@ -27,6 +32,10 @@ import org.jboss.staxmapper.XMLExtendedStreamWriter;
 
 import javax.xml.stream.XMLStreamConstants;
 import javax.xml.stream.XMLStreamException;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.LinkedList;
 import java.util.List;
 
 /**
@@ -41,10 +50,15 @@ class KeycloakSubsystemParser implements XMLStreamConstants, XMLElementReader<Li
     public void readElement(final XMLExtendedStreamReader reader, final List<ModelNode> list) throws XMLStreamException {
         // Require no attributes
         ParseUtils.requireNoAttributes(reader);
-        ModelNode addKeycloakSub = org.jboss.as.controller.operations.common.Util.createAddOperation(PathAddress.pathAddress(KeycloakSamlExtension.PATH_SUBSYSTEM));
+        ModelNode addKeycloakSub = Util.createAddOperation(PathAddress.pathAddress(KeycloakSamlExtension.PATH_SUBSYSTEM));
         list.add(addKeycloakSub);
 
         while (reader.hasNext() && nextTag(reader) != END_ELEMENT) {
+            if (reader.getLocalName().equals(Constants.XML.SECURE_DEPLOYMENT)) {
+                readSecureDeployment(reader, list);
+            } else {
+                throw ParseUtils.unexpectedElement(reader);
+            }
         }
     }
 
@@ -53,6 +67,319 @@ class KeycloakSubsystemParser implements XMLStreamConstants, XMLElementReader<Li
         return reader.nextTag();
     }
 
+    void readSecureDeployment(XMLExtendedStreamReader reader, List<ModelNode> list) throws XMLStreamException {
+        String name = readRequiredAttribute(reader, Constants.XML.NAME);
+
+        PathAddress addr = PathAddress.pathAddress(
+                PathElement.pathElement(ModelDescriptionConstants.SUBSYSTEM, KeycloakSamlExtension.SUBSYSTEM_NAME),
+                PathElement.pathElement(Constants.Model.SECURE_DEPLOYMENT, name));
+        ModelNode addSecureDeployment = Util.createAddOperation(addr);
+        list.add(addSecureDeployment);
+
+        while (reader.hasNext() && nextTag(reader) != END_ELEMENT) {
+            String tagName = reader.getLocalName();
+            if (tagName.equals(Constants.XML.SERVICE_PROVIDER)) {
+                readServiceProvider(reader, list, addr);
+            } else {
+                throw ParseUtils.unexpectedElement(reader);
+            }
+        }
+    }
+
+    void readServiceProvider(XMLExtendedStreamReader reader, List<ModelNode> list, PathAddress parentAddr) throws XMLStreamException {
+        String entityId = readRequiredAttribute(reader, Constants.XML.ENTITY_ID);
+
+        PathAddress addr = PathAddress.pathAddress(parentAddr,
+                PathElement.pathElement(Constants.Model.SERVICE_PROVIDER, entityId));
+        ModelNode addServiceProvider = Util.createAddOperation(addr);
+        list.add(addServiceProvider);
+
+        for (int i = 0; i < reader.getAttributeCount(); i++) {
+            String name = reader.getAttributeLocalName(i);
+            if (Constants.XML.ENTITY_ID.equals(name)) {
+                continue;
+            }
+
+            String value = reader.getAttributeValue(i);
+
+            SimpleAttributeDefinition attr = ServiceProviderDefinition.lookup(name);
+            if (attr == null) {
+                throw ParseUtils.unexpectedAttribute(reader, i);
+            }
+            attr.parseAndSetParameter(value, addServiceProvider, reader);
+        }
+
+        while (reader.hasNext() && nextTag(reader) != END_ELEMENT) {
+            String tagName = reader.getLocalName();
+
+            if (Constants.XML.KEYS.equals(tagName)) {
+                readKeys(list, reader, addr);
+            } else if (Constants.XML.PRINCIPAL_NAME_MAPPING.equals(tagName)) {
+                readPrincipalNameMapping(addServiceProvider, reader);
+            } else if (Constants.XML.ROLE_IDENTIFIERS.equals(tagName)) {
+                readRoleIdentifiers(addServiceProvider, reader);
+            } else if (Constants.XML.IDENTITY_PROVIDER.equals(tagName)) {
+                readIdentityProvider(list, reader, addr);
+            } else {
+                throw ParseUtils.unexpectedElement(reader);
+            }
+        }
+    }
+
+    void readIdentityProvider(List<ModelNode> list, XMLExtendedStreamReader reader, PathAddress parentAddr) throws XMLStreamException {
+        String entityId = readRequiredAttribute(reader, Constants.XML.ENTITY_ID);
+
+        PathAddress addr = PathAddress.pathAddress(parentAddr,
+                PathElement.pathElement(Constants.Model.IDENTITY_PROVIDER, entityId));
+        ModelNode addIdentityProvider = Util.createAddOperation(addr);
+        list.add(addIdentityProvider);
+
+        for (int i = 0; i < reader.getAttributeCount(); i++) {
+            String name = reader.getAttributeLocalName(i);
+            String value = reader.getAttributeValue(i);
+
+            if (Constants.XML.ENTITY_ID.equals(name)
+                    // don't break if encountering this noop attr from client-adapter/core keycloak_saml_adapter_1_6.xsd
+                    || "encryption".equals(name)) {
+                continue;
+            }
+            SimpleAttributeDefinition attr = IdentityProviderDefinition.lookup(name);
+            if (attr == null) {
+                throw ParseUtils.unexpectedAttribute(reader, i);
+            }
+            attr.parseAndSetParameter(value, addIdentityProvider, reader);
+        }
+
+        while (reader.hasNext() && nextTag(reader) != END_ELEMENT) {
+            String tagName = reader.getLocalName();
+
+            if (Constants.XML.SINGLE_SIGN_ON.equals(tagName)) {
+                readSingleSignOn(addIdentityProvider, reader);
+            } else if (Constants.XML.SINGLE_LOGOUT.equals(tagName)) {
+                readSingleLogout(addIdentityProvider, reader);
+            } else if (Constants.XML.KEYS.equals(tagName)) {
+                readKeys(list, reader, addr);
+            } else {
+                throw ParseUtils.unexpectedElement(reader);
+            }
+        }
+    }
+
+    void readSingleSignOn(ModelNode addIdentityProvider, XMLExtendedStreamReader reader) throws XMLStreamException {
+        ModelNode sso = addIdentityProvider.get(Constants.Model.SINGLE_SIGN_ON);
+        for (int i = 0; i < reader.getAttributeCount(); i++) {
+            String name = reader.getAttributeLocalName(i);
+            String value = reader.getAttributeValue(i);
+
+            SimpleAttributeDefinition attr = SingleSignOnDefinition.lookup(name);
+            if (attr == null) {
+                throw ParseUtils.unexpectedAttribute(reader, i);
+            }
+            attr.parseAndSetParameter(value, sso, reader);
+        }
+        ParseUtils.requireNoContent(reader);
+    }
+
+    void readSingleLogout(ModelNode addIdentityProvider, XMLExtendedStreamReader reader) throws XMLStreamException {
+        ModelNode slo = addIdentityProvider.get(Constants.Model.SINGLE_LOGOUT);
+        for (int i = 0; i < reader.getAttributeCount(); i++) {
+            String name = reader.getAttributeLocalName(i);
+            String value = reader.getAttributeValue(i);
+
+            SimpleAttributeDefinition attr = SingleLogoutDefinition.lookup(name);
+            if (attr == null) {
+                throw ParseUtils.unexpectedAttribute(reader, i);
+            }
+            attr.parseAndSetParameter(value, slo, reader);
+        }
+        ParseUtils.requireNoContent(reader);
+    }
+
+    void readKeys(List<ModelNode> list, XMLExtendedStreamReader reader, PathAddress parentAddr) throws XMLStreamException {
+        ParseUtils.requireNoAttributes(reader);
+        List<ModelNode> keyList = new LinkedList<>();
+        while (reader.hasNext() && nextTag(reader) != END_ELEMENT) {
+            String tagName = reader.getLocalName();
+            if (!Constants.XML.KEY.equals(tagName)) {
+                throw ParseUtils.unexpectedElement(reader);
+            }
+            readKey(keyList, reader, parentAddr);
+        }
+        list.addAll(keyList);
+    }
+
+    void readKey(List<ModelNode> list, XMLExtendedStreamReader reader, PathAddress parentAddr) throws XMLStreamException {
+        PathAddress addr = PathAddress.pathAddress(parentAddr,
+                PathElement.pathElement(Constants.Model.KEY, "key-" + list.size()));
+        ModelNode addKey = Util.createAddOperation(addr);
+        list.add(addKey);
+
+        for (int i = 0; i < reader.getAttributeCount(); i++) {
+            String name = reader.getAttributeLocalName(i);
+            String value = reader.getAttributeValue(i);
+
+            SimpleAttributeDefinition attr = KeyDefinition.lookup(name);
+            if (attr == null) {
+                throw ParseUtils.unexpectedAttribute(reader, i);
+            }
+            attr.parseAndSetParameter(value, addKey, reader);
+        }
+
+        while (reader.hasNext() && nextTag(reader) != END_ELEMENT) {
+            String tagName = reader.getLocalName();
+
+            if (Constants.XML.KEY_STORE.equals(tagName)) {
+                readKeyStore(addKey, reader);
+            } else if (Constants.XML.PRIVATE_KEY_PEM.equals(tagName)
+                    || Constants.XML.PUBLIC_KEY_PEM.equals(tagName)
+                    || Constants.XML.CERTIFICATE_PEM.equals(tagName)) {
+
+                readNoAttrElementContent(KeyDefinition.lookupElement(tagName), addKey, reader);
+            } else {
+                throw ParseUtils.unexpectedElement(reader);
+            }
+        }
+    }
+
+    void readNoAttrElementContent(SimpleAttributeDefinition attr, ModelNode model, XMLExtendedStreamReader reader) throws XMLStreamException {
+        ParseUtils.requireNoAttributes(reader);
+        String value = reader.getElementText();
+        attr.parseAndSetParameter(value, model, reader);
+    }
+
+    void readKeyStore(ModelNode addKey, XMLExtendedStreamReader reader) throws XMLStreamException {
+        ModelNode addKeyStore = addKey.get(Constants.Model.KEY_STORE);
+
+        for (int i = 0; i < reader.getAttributeCount(); i++) {
+            String name = reader.getAttributeLocalName(i);
+            String value = reader.getAttributeValue(i);
+
+            SimpleAttributeDefinition attr = KeyStoreDefinition.lookup(name);
+            if (attr == null) {
+                throw ParseUtils.unexpectedAttribute(reader, i);
+            }
+            attr.parseAndSetParameter(value, addKeyStore, reader);
+        }
+
+        if (!addKeyStore.hasDefined(Constants.Model.FILE) && !addKeyStore.hasDefined(Constants.Model.RESOURCE)) {
+            throw new XMLStreamException("KeyStore element must have 'file' or 'resource' attribute set", reader.getLocation());
+        }
+        if (!addKeyStore.hasDefined(Constants.Model.PASSWORD)) {
+            throw ParseUtils.missingRequired(reader, Constants.XML.PASSWORD);
+        }
+
+        while (reader.hasNext() && nextTag(reader) != END_ELEMENT) {
+            String tagName = reader.getLocalName();
+            if (Constants.XML.PRIVATE_KEY.equals(tagName)) {
+                readPrivateKey(reader, addKeyStore);
+            } else if (Constants.XML.CERTIFICATE.equals(tagName)) {
+                readCertificate(reader, addKeyStore);
+            } else {
+                throw ParseUtils.unexpectedElement(reader);
+            }
+        }
+    }
+
+
+    void readPrivateKey(XMLExtendedStreamReader reader, ModelNode addKeyStore) throws XMLStreamException {
+        for (int i = 0; i < reader.getAttributeCount(); i++) {
+            String name = reader.getAttributeLocalName(i);
+            String value = reader.getAttributeValue(i);
+
+            SimpleAttributeDefinition attr = KeyStorePrivateKeyDefinition.lookup(name);
+            if (attr == null) {
+                throw ParseUtils.unexpectedAttribute(reader, i);
+            }
+            attr.parseAndSetParameter(value, addKeyStore, reader);
+        }
+
+        if (!addKeyStore.hasDefined(Constants.Model.PRIVATE_KEY_ALIAS)) {
+            throw ParseUtils.missingRequired(reader, Constants.XML.PRIVATE_KEY_ALIAS);
+        }
+        if (!addKeyStore.hasDefined(Constants.Model.PRIVATE_KEY_PASSWORD)) {
+            throw ParseUtils.missingRequired(reader, Constants.XML.PRIVATE_KEY_PASSWORD);
+        }
+
+        ParseUtils.requireNoContent(reader);
+    }
+
+    void readCertificate(XMLExtendedStreamReader reader, ModelNode addKeyStore) throws XMLStreamException {
+        for (int i = 0; i < reader.getAttributeCount(); i++) {
+            String name = reader.getAttributeLocalName(i);
+            String value = reader.getAttributeValue(i);
+
+            SimpleAttributeDefinition attr = KeyStoreCertificateDefinition.lookup(name);
+            if (attr == null) {
+                throw ParseUtils.unexpectedAttribute(reader, i);
+            }
+            attr.parseAndSetParameter(value, addKeyStore, reader);
+        }
+
+        if (!addKeyStore.hasDefined(Constants.Model.CERTIFICATE_ALIAS)) {
+            throw ParseUtils.missingRequired(reader, Constants.XML.CERTIFICATE_ALIAS);
+        }
+
+        ParseUtils.requireNoContent(reader);
+    }
+
+    void readRoleIdentifiers(ModelNode addServiceProvider, XMLExtendedStreamReader reader) throws XMLStreamException {
+        ParseUtils.requireNoAttributes(reader);
+
+        while (reader.hasNext() && nextTag(reader) != END_ELEMENT) {
+            String tagName = reader.getLocalName();
+
+            if (!Constants.XML.ATTRIBUTE.equals(tagName)) {
+                throw ParseUtils.unexpectedElement(reader);
+            }
+
+            ParseUtils.requireSingleAttribute(reader, Constants.XML.NAME);
+            String name = ParseUtils.readStringAttributeElement(reader, Constants.XML.NAME);
+
+            ServiceProviderDefinition.ROLE_ATTRIBUTES.parseAndAddParameterElement(name, addServiceProvider, reader);
+        }
+    }
+
+    void readPrincipalNameMapping(ModelNode addServiceProvider, XMLExtendedStreamReader reader) throws XMLStreamException {
+
+        boolean policySet = false;
+
+        for (int i = 0; i < reader.getAttributeCount(); i++) {
+            String name = reader.getAttributeLocalName(i);
+            String value = reader.getAttributeValue(i);
+
+            if (Constants.XML.PRINCIPAL_NAME_MAPPING_POLICY.equals(name)) {
+                policySet = true;
+                ServiceProviderDefinition.PRINCIPAL_NAME_MAPPING_POLICY.parseAndSetParameter(value, addServiceProvider, reader);
+            } else if (Constants.XML.PRINCIPAL_NAME_MAPPING_ATTRIBUTE_NAME.equals(name)) {
+                ServiceProviderDefinition.PRINCIPAL_NAME_MAPPING_ATTRIBUTE_NAME.parseAndSetParameter(value, addServiceProvider, reader);
+            } else {
+                throw ParseUtils.unexpectedAttribute(reader, i);
+            }
+        }
+
+        if (!policySet) {
+            throw ParseUtils.missingRequired(reader, Constants.XML.PRINCIPAL_NAME_MAPPING_POLICY);
+        }
+        ParseUtils.requireNoContent(reader);
+    }
+
+    /**
+     * Read an attribute, and throw exception if attribute is not present
+     */
+    String readRequiredAttribute(XMLExtendedStreamReader reader, String attrName) throws XMLStreamException {
+        String value = null;
+        for (int i = 0; i < reader.getAttributeCount(); i++) {
+            String attr = reader.getAttributeLocalName(i);
+            if (attr.equals(attrName)) {
+                value = reader.getAttributeValue(i);
+                break;
+            }
+        }
+        if (value == null) {
+            throw ParseUtils.missingRequired(reader, Collections.singleton(attrName));
+        }
+        return value;
+    }
 
     /**
      * {@inheritDoc}
@@ -60,8 +387,183 @@ class KeycloakSubsystemParser implements XMLStreamConstants, XMLElementReader<Li
     @Override
     public void writeContent(final XMLExtendedStreamWriter writer, final SubsystemMarshallingContext context) throws XMLStreamException {
         context.startSubsystemElement(KeycloakSamlExtension.NAMESPACE, false);
+        writeSecureDeployment(writer, context.getModelNode());
+        writer.writeEndElement();
+    }
+
+    public void writeSecureDeployment(XMLExtendedStreamWriter writer, ModelNode model) throws XMLStreamException {
+        if (!model.get(Constants.Model.SECURE_DEPLOYMENT).isDefined()) {
+            return;
+        }
+
+        for (Property sp : model.get(Constants.Model.SECURE_DEPLOYMENT).asPropertyList()) {
+            writer.writeStartElement(Constants.XML.SECURE_DEPLOYMENT);
+            writer.writeAttribute(Constants.XML.NAME, sp.getName());
+
+            writeSps(writer, sp.getValue());
+            writer.writeEndElement();
+        }
+    }
+
+    void writeSps(final XMLExtendedStreamWriter writer, final ModelNode model) throws XMLStreamException {
+        if (!model.isDefined()) {
+            return;
+        }
+        for (Property sp : model.get(Constants.Model.SERVICE_PROVIDER).asPropertyList()) {
+            writer.writeStartElement(Constants.XML.SERVICE_PROVIDER);
+            writer.writeAttribute(Constants.XML.ENTITY_ID, sp.getName());
+            ModelNode spAttributes = sp.getValue();
+            for (SimpleAttributeDefinition attr : ServiceProviderDefinition.ATTRIBUTES) {
+                attr.getAttributeMarshaller().marshallAsAttribute(attr, spAttributes, false, writer);
+            }
+            writeKeys(writer, spAttributes.get(Constants.Model.KEY));
+            writePrincipalNameMapping(writer, spAttributes);
+            writeRoleIdentifiers(writer, spAttributes);
+            writeIdentityProvider(writer, spAttributes.get(Constants.Model.IDENTITY_PROVIDER));
+
+            writer.writeEndElement();
+        }
+    }
+
+    void writeIdentityProvider(XMLExtendedStreamWriter writer, ModelNode model) throws XMLStreamException {
+        if (!model.isDefined()) {
+            return;
+        }
+
+        for (Property idp : model.asPropertyList()) {
+            writer.writeStartElement(Constants.XML.IDENTITY_PROVIDER);
+            writer.writeAttribute(Constants.XML.ENTITY_ID, idp.getName());
+
+            ModelNode idpAttributes = idp.getValue();
+            for (SimpleAttributeDefinition attr : IdentityProviderDefinition.ATTRIBUTES) {
+                attr.getAttributeMarshaller().marshallAsAttribute(attr, idpAttributes, false, writer);
+            }
+
+            writeSingleSignOn(writer, idpAttributes.get(Constants.Model.SINGLE_SIGN_ON));
+            writeSingleLogout(writer, idpAttributes.get(Constants.Model.SINGLE_LOGOUT));
+            writeKeys(writer, idpAttributes.get(Constants.Model.KEY));
+        }
+        writer.writeEndElement();
+    }
+
+    void writeSingleSignOn(XMLExtendedStreamWriter writer, ModelNode model) throws XMLStreamException {
+        if (!model.isDefined()) {
+            return;
+        }
+        writer.writeStartElement(Constants.XML.SINGLE_SIGN_ON);
+        for (SimpleAttributeDefinition attr : SingleSignOnDefinition.ATTRIBUTES) {
+            attr.getAttributeMarshaller().marshallAsAttribute(attr, model, false, writer);
+        }
         writer.writeEndElement();
     }
 
+    void writeSingleLogout(XMLExtendedStreamWriter writer, ModelNode model) throws XMLStreamException {
+        if (!model.isDefined()) {
+            return;
+        }
+        writer.writeStartElement(Constants.XML.SINGLE_LOGOUT);
+        for (SimpleAttributeDefinition attr : SingleLogoutDefinition.ATTRIBUTES) {
+            attr.getAttributeMarshaller().marshallAsAttribute(attr, model, false, writer);
+        }
+        writer.writeEndElement();
+    }
+
+    void writeKeys(XMLExtendedStreamWriter writer, ModelNode model) throws XMLStreamException {
+        if (!model.isDefined()) {
+            return;
+        }
+        boolean contains = false;
+        for (Property key : model.asPropertyList()) {
+            if (!contains) {
+                writer.writeStartElement(Constants.XML.KEYS);
+                contains = true;
+            }
+            writer.writeStartElement(Constants.XML.KEY);
 
+            ModelNode keyAttributes = key.getValue();
+            for (SimpleAttributeDefinition attr : KeyDefinition.ATTRIBUTES) {
+                attr.getAttributeMarshaller().marshallAsAttribute(attr, keyAttributes, false, writer);
+            }
+            for (SimpleAttributeDefinition attr : KeyDefinition.ELEMENTS) {
+                attr.getAttributeMarshaller().marshallAsElement(attr, keyAttributes, false, writer);
+            }
+            writeKeyStore(writer, keyAttributes.get(Constants.Model.KEY_STORE));
+
+            writer.writeEndElement();
+        }
+        if (contains) {
+            writer.writeEndElement();
+        }
+    }
+
+    void writeKeyStore(XMLExtendedStreamWriter writer, ModelNode model) throws XMLStreamException {
+        if (!model.isDefined()) {
+            return;
+        }
+        writer.writeStartElement(Constants.XML.KEY_STORE);
+        for (SimpleAttributeDefinition attr : KeyStoreDefinition.ATTRIBUTES) {
+            attr.getAttributeMarshaller().marshallAsAttribute(attr, model, false, writer);
+        }
+        writePrivateKey(writer, model);
+        writeCertificate(writer, model);
+        writer.writeEndElement();
+    }
+
+    void writeCertificate(XMLExtendedStreamWriter writer, ModelNode model) throws XMLStreamException {
+        ModelNode value = model.get(Constants.Model.CERTIFICATE_ALIAS);
+        if (!value.isDefined()) {
+            return;
+        }
+        writer.writeStartElement(Constants.XML.CERTIFICATE);
+        SimpleAttributeDefinition attr = KeyStoreCertificateDefinition.CERTIFICATE_ALIAS;
+        attr.getAttributeMarshaller().marshallAsAttribute(attr, model, false, writer);
+        writer.writeEndElement();
+    }
+
+    void writePrivateKey(XMLExtendedStreamWriter writer, ModelNode model) throws XMLStreamException {
+        ModelNode pk_alias = model.get(Constants.Model.PRIVATE_KEY_ALIAS);
+        ModelNode pk_password = model.get(Constants.Model.PRIVATE_KEY_PASSWORD);
+
+        if (!pk_alias.isDefined() && !pk_password.isDefined()) {
+            return;
+        }
+        writer.writeStartElement(Constants.XML.PRIVATE_KEY);
+        for (SimpleAttributeDefinition attr : KeyStorePrivateKeyDefinition.ATTRIBUTES) {
+            attr.getAttributeMarshaller().marshallAsAttribute(attr, model, false, writer);
+        }
+        writer.writeEndElement();
+    }
+
+    void writeRoleIdentifiers(XMLExtendedStreamWriter writer, ModelNode model) throws XMLStreamException {
+        ModelNode value = model.get(Constants.Model.ROLE_ATTRIBUTES);
+        if (!value.isDefined()) {
+            return;
+        }
+
+        List<ModelNode> items = value.asList();
+        if (items.size() == 0) {
+            return;
+        }
+
+        writer.writeStartElement(Constants.XML.ROLE_IDENTIFIERS);
+        for (ModelNode item : items) {
+            writer.writeStartElement(Constants.XML.ATTRIBUTE);
+            writer.writeAttribute("name", item.asString());
+            writer.writeEndElement();
+        }
+        writer.writeEndElement();
+    }
+
+    void writePrincipalNameMapping(XMLExtendedStreamWriter writer, ModelNode model) throws XMLStreamException {
+        writer.writeStartElement(Constants.XML.PRINCIPAL_NAME_MAPPING);
+        ModelNode value = model.get(Constants.Model.PRINCIPAL_NAME_MAPPING_POLICY);
+        if (value.isDefined()) {
+            writer.writeAttribute(Constants.XML.PRINCIPAL_NAME_MAPPING_POLICY, value.asString());
+        }
+        value = model.get(Constants.Model.PRINCIPAL_NAME_MAPPING_ATTRIBUTE_NAME);
+        if (value.isDefined()) {
+            writer.writeAttribute(Constants.XML.PRINCIPAL_NAME_MAPPING_ATTRIBUTE_NAME, value.asString());
+        }
+        writer.writeEndElement();
+    }
 }
diff --git a/saml/client-adapter/as7-eap6/subsystem/src/main/java/org/keycloak/subsystem/saml/as7/KeyDefinition.java b/saml/client-adapter/as7-eap6/subsystem/src/main/java/org/keycloak/subsystem/saml/as7/KeyDefinition.java
new file mode 100644
index 0000000..0f76399
--- /dev/null
+++ b/saml/client-adapter/as7-eap6/subsystem/src/main/java/org/keycloak/subsystem/saml/as7/KeyDefinition.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright 2015 Red Hat Inc. and/or its affiliates and other contributors
+ * as indicated by the @author tags. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package org.keycloak.subsystem.saml.as7;
+
+import org.jboss.as.controller.AttributeDefinition;
+import org.jboss.as.controller.ObjectTypeAttributeDefinition;
+import org.jboss.as.controller.OperationStepHandler;
+import org.jboss.as.controller.PathElement;
+import org.jboss.as.controller.ReloadRequiredRemoveStepHandler;
+import org.jboss.as.controller.ReloadRequiredWriteAttributeHandler;
+import org.jboss.as.controller.SimpleAttributeDefinition;
+import org.jboss.as.controller.SimpleAttributeDefinitionBuilder;
+import org.jboss.as.controller.SimpleResourceDefinition;
+import org.jboss.as.controller.operations.common.GenericSubsystemDescribeHandler;
+import org.jboss.as.controller.registry.ManagementResourceRegistration;
+import org.jboss.dmr.ModelType;
+
+import java.util.HashMap;
+
+/**
+ * @author <a href="mailto:mstrukel@redhat.com">Marko Strukelj</a>
+ */
+public class KeyDefinition extends SimpleResourceDefinition {
+
+    static final SimpleAttributeDefinition SIGNING =
+            new SimpleAttributeDefinitionBuilder(Constants.Model.SIGNING, ModelType.BOOLEAN, true)
+                    .setXmlName(Constants.XML.SIGNING)
+                    .build();
+
+    static final SimpleAttributeDefinition ENCRYPTION =
+            new SimpleAttributeDefinitionBuilder(Constants.Model.ENCRYPTION, ModelType.BOOLEAN, true)
+                    .setXmlName(Constants.XML.ENCRYPTION)
+                    .build();
+
+    static final SimpleAttributeDefinition PRIVATE_KEY_PEM =
+            new SimpleAttributeDefinitionBuilder(Constants.Model.PRIVATE_KEY_PEM, ModelType.STRING, true)
+                    .setXmlName(Constants.XML.PRIVATE_KEY_PEM)
+                    .build();
+
+    static final SimpleAttributeDefinition PUBLIC_KEY_PEM =
+            new SimpleAttributeDefinitionBuilder(Constants.Model.PUBLIC_KEY_PEM, ModelType.STRING, true)
+                    .setXmlName(Constants.XML.PUBLIC_KEY_PEM)
+                    .build();
+
+    static final SimpleAttributeDefinition CERTIFICATE_PEM =
+            new SimpleAttributeDefinitionBuilder(Constants.Model.CERTIFICATE_PEM, ModelType.STRING, true)
+                    .setXmlName(Constants.XML.CERTIFICATE_PEM)
+                    .build();
+
+    static final ObjectTypeAttributeDefinition KEY_STORE =
+            ObjectTypeAttributeDefinition.Builder.of(Constants.Model.KEY_STORE,
+                    KeyStoreDefinition.ALL_ATTRIBUTES)
+                    .setAllowNull(false)
+                    .build();
+
+    static final SimpleAttributeDefinition[] ATTRIBUTES = {SIGNING, ENCRYPTION};
+    static final SimpleAttributeDefinition[] ELEMENTS = {PRIVATE_KEY_PEM, PUBLIC_KEY_PEM, CERTIFICATE_PEM};
+    static final AttributeDefinition[] ALL_ATTRIBUTES = {SIGNING, ENCRYPTION, PRIVATE_KEY_PEM, PUBLIC_KEY_PEM, CERTIFICATE_PEM, KEY_STORE};
+
+    static final HashMap<String, SimpleAttributeDefinition> ATTRIBUTE_MAP = new HashMap<>();
+
+    static {
+        for (SimpleAttributeDefinition def : ATTRIBUTES) {
+            ATTRIBUTE_MAP.put(def.getXmlName(), def);
+        }
+    }
+
+    static final HashMap<String, SimpleAttributeDefinition> ELEMENT_MAP = new HashMap<>();
+
+    static {
+        for (SimpleAttributeDefinition def : ELEMENTS) {
+            ELEMENT_MAP.put(def.getXmlName(), def);
+        }
+    }
+
+    static final KeyDefinition INSTANCE = new KeyDefinition();
+
+    private KeyDefinition() {
+        super(PathElement.pathElement(Constants.Model.KEY),
+                KeycloakSamlExtension.getResourceDescriptionResolver(Constants.Model.KEY),
+                new KeyAddHandler(),
+                ReloadRequiredRemoveStepHandler.INSTANCE);
+    }
+
+    @Override
+    public void registerOperations(ManagementResourceRegistration resourceRegistration) {
+        super.registerOperations(resourceRegistration);
+        resourceRegistration.registerOperationHandler(GenericSubsystemDescribeHandler.DEFINITION, GenericSubsystemDescribeHandler.INSTANCE);
+    }
+
+    @Override
+    public void registerAttributes(ManagementResourceRegistration resourceRegistration) {
+        super.registerAttributes(resourceRegistration);
+
+        final OperationStepHandler writeHandler = new ReloadRequiredWriteAttributeHandler(ALL_ATTRIBUTES);
+        for (AttributeDefinition attribute : ALL_ATTRIBUTES) {
+            resourceRegistration.registerReadWriteAttribute(attribute, null, writeHandler);
+        }
+    }
+
+    static SimpleAttributeDefinition lookup(String xmlName) {
+        return ATTRIBUTE_MAP.get(xmlName);
+    }
+
+    static SimpleAttributeDefinition lookupElement(String xmlName) {
+        return ELEMENT_MAP.get(xmlName);
+    }
+}
diff --git a/saml/client-adapter/as7-eap6/subsystem/src/main/java/org/keycloak/subsystem/saml/as7/KeyStoreCertificateDefinition.java b/saml/client-adapter/as7-eap6/subsystem/src/main/java/org/keycloak/subsystem/saml/as7/KeyStoreCertificateDefinition.java
new file mode 100644
index 0000000..7ae2ff1
--- /dev/null
+++ b/saml/client-adapter/as7-eap6/subsystem/src/main/java/org/keycloak/subsystem/saml/as7/KeyStoreCertificateDefinition.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2015 Red Hat Inc. and/or its affiliates and other contributors
+ * as indicated by the @author tags. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package org.keycloak.subsystem.saml.as7;
+
+import org.jboss.as.controller.SimpleAttributeDefinition;
+import org.jboss.as.controller.SimpleAttributeDefinitionBuilder;
+import org.jboss.dmr.ModelType;
+
+/**
+ * @author <a href="mailto:mstrukel@redhat.com">Marko Strukelj</a>
+ */
+public class KeyStoreCertificateDefinition {
+
+    static final SimpleAttributeDefinition CERTIFICATE_ALIAS =
+            new SimpleAttributeDefinitionBuilder(Constants.Model.CERTIFICATE_ALIAS, ModelType.STRING, true)
+                    .setXmlName(Constants.XML.CERTIFICATE_ALIAS)
+                    .build();
+
+    static SimpleAttributeDefinition lookup(String xmlName) {
+        return Constants.XML.CERTIFICATE_ALIAS.equals(xmlName) ? CERTIFICATE_ALIAS : null;
+    }
+}
diff --git a/saml/client-adapter/as7-eap6/subsystem/src/main/java/org/keycloak/subsystem/saml/as7/KeyStoreDefinition.java b/saml/client-adapter/as7-eap6/subsystem/src/main/java/org/keycloak/subsystem/saml/as7/KeyStoreDefinition.java
new file mode 100644
index 0000000..2fb14f5
--- /dev/null
+++ b/saml/client-adapter/as7-eap6/subsystem/src/main/java/org/keycloak/subsystem/saml/as7/KeyStoreDefinition.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2015 Red Hat Inc. and/or its affiliates and other contributors
+ * as indicated by the @author tags. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package org.keycloak.subsystem.saml.as7;
+
+import org.jboss.as.controller.SimpleAttributeDefinition;
+import org.jboss.as.controller.SimpleAttributeDefinitionBuilder;
+import org.jboss.dmr.ModelType;
+
+import java.util.HashMap;
+
+/**
+ * @author <a href="mailto:mstrukel@redhat.com">Marko Strukelj</a>
+ */
+abstract class KeyStoreDefinition {
+
+    static final SimpleAttributeDefinition RESOURCE =
+            new SimpleAttributeDefinitionBuilder(Constants.Model.RESOURCE, ModelType.STRING, true)
+                    .setXmlName(Constants.XML.RESOURCE)
+                    .build();
+
+    static final SimpleAttributeDefinition PASSWORD =
+            new SimpleAttributeDefinitionBuilder(Constants.Model.PASSWORD, ModelType.STRING, true)
+                    .setXmlName(Constants.XML.PASSWORD)
+                    .build();
+
+    static final SimpleAttributeDefinition FILE =
+            new SimpleAttributeDefinitionBuilder(Constants.Model.FILE, ModelType.STRING, true)
+                    .setXmlName(Constants.XML.FILE)
+                    .build();
+
+    static final SimpleAttributeDefinition TYPE =
+            new SimpleAttributeDefinitionBuilder(Constants.Model.TYPE, ModelType.STRING, true)
+                    .setXmlName(Constants.XML.TYPE)
+                    .build();
+
+    static final SimpleAttributeDefinition ALIAS =
+            new SimpleAttributeDefinitionBuilder(Constants.Model.ALIAS, ModelType.STRING, true)
+                    .setXmlName(Constants.XML.ALIAS)
+                    .build();
+
+    static final SimpleAttributeDefinition[] ATTRIBUTES = {RESOURCE, PASSWORD, FILE, TYPE, ALIAS};
+    static final SimpleAttributeDefinition[] ALL_ATTRIBUTES = {RESOURCE, PASSWORD, FILE, TYPE, ALIAS,
+            KeyStorePrivateKeyDefinition.PRIVATE_KEY_ALIAS,
+            KeyStorePrivateKeyDefinition.PRIVATE_KEY_PASSWORD,
+            KeyStoreCertificateDefinition.CERTIFICATE_ALIAS
+    };
+
+    static final HashMap<String, SimpleAttributeDefinition> ATTRIBUTE_MAP = new HashMap<>();
+
+    static {
+        for (SimpleAttributeDefinition def : ATTRIBUTES) {
+            ATTRIBUTE_MAP.put(def.getXmlName(), def);
+        }
+    }
+
+    static SimpleAttributeDefinition lookup(String xmlName) {
+        return ATTRIBUTE_MAP.get(xmlName);
+    }
+}
diff --git a/saml/client-adapter/as7-eap6/subsystem/src/main/java/org/keycloak/subsystem/saml/as7/KeyStorePrivateKeyDefinition.java b/saml/client-adapter/as7-eap6/subsystem/src/main/java/org/keycloak/subsystem/saml/as7/KeyStorePrivateKeyDefinition.java
new file mode 100644
index 0000000..1947ca9
--- /dev/null
+++ b/saml/client-adapter/as7-eap6/subsystem/src/main/java/org/keycloak/subsystem/saml/as7/KeyStorePrivateKeyDefinition.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2015 Red Hat Inc. and/or its affiliates and other contributors
+ * as indicated by the @author tags. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package org.keycloak.subsystem.saml.as7;
+
+import org.jboss.as.controller.SimpleAttributeDefinition;
+import org.jboss.as.controller.SimpleAttributeDefinitionBuilder;
+import org.jboss.dmr.ModelType;
+
+import java.util.HashMap;
+
+/**
+ * @author <a href="mailto:mstrukel@redhat.com">Marko Strukelj</a>
+ */
+public class KeyStorePrivateKeyDefinition {
+    static final SimpleAttributeDefinition PRIVATE_KEY_ALIAS =
+            new SimpleAttributeDefinitionBuilder(Constants.Model.PRIVATE_KEY_ALIAS, ModelType.STRING, true)
+                    .setXmlName(Constants.XML.PRIVATE_KEY_ALIAS)
+                    .build();
+
+    static final SimpleAttributeDefinition PRIVATE_KEY_PASSWORD =
+            new SimpleAttributeDefinitionBuilder(Constants.Model.PRIVATE_KEY_PASSWORD, ModelType.STRING, true)
+                    .setXmlName(Constants.XML.PRIVATE_KEY_PASSWORD)
+                    .build();
+
+    static final SimpleAttributeDefinition[] ATTRIBUTES = {PRIVATE_KEY_ALIAS, PRIVATE_KEY_PASSWORD};
+
+    static final HashMap<String, SimpleAttributeDefinition> ATTRIBUTE_MAP = new HashMap<>();
+
+    static {
+        for (SimpleAttributeDefinition def : ATTRIBUTES) {
+            ATTRIBUTE_MAP.put(def.getXmlName(), def);
+        }
+    }
+
+    static SimpleAttributeDefinition lookup(String xmlName) {
+        return ATTRIBUTE_MAP.get(xmlName);
+    }
+}
diff --git a/saml/client-adapter/as7-eap6/subsystem/src/main/java/org/keycloak/subsystem/saml/as7/logging/KeycloakLogger.java b/saml/client-adapter/as7-eap6/subsystem/src/main/java/org/keycloak/subsystem/saml/as7/logging/KeycloakLogger.java
new file mode 100755
index 0000000..8bd7ac1
--- /dev/null
+++ b/saml/client-adapter/as7-eap6/subsystem/src/main/java/org/keycloak/subsystem/saml/as7/logging/KeycloakLogger.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2013 Red Hat Inc. and/or its affiliates and other contributors
+ * as indicated by the @author tags. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package org.keycloak.subsystem.saml.as7.logging;
+
+import org.jboss.logging.BasicLogger;
+import org.jboss.logging.LogMessage;
+import org.jboss.logging.Logger;
+import org.jboss.logging.Message;
+import org.jboss.logging.MessageLogger;
+
+import static org.jboss.logging.Logger.Level.DEBUG;
+import static org.jboss.logging.Logger.Level.INFO;
+
+/**
+ * This interface to be fleshed out later when error messages are fully externalized.
+ *
+ * @author Stan Silvert ssilvert@redhat.com (C) 2013 Red Hat Inc.
+ */
+@MessageLogger(projectCode = "KEYCLOAK")
+public interface KeycloakLogger extends BasicLogger {
+
+    /**
+     * A logger with a category of the package name.
+     */
+    KeycloakLogger ROOT_LOGGER = Logger.getMessageLogger(KeycloakLogger.class, "org.jboss.keycloak");
+
+    @LogMessage(level = INFO)
+    @Message(value = "Keycloak SAML subsystem override for deployment %s")
+    void deploymentSecured(String deployment);
+
+    @LogMessage(level = DEBUG)
+    @Message(value = "Keycloak SAML has overriden and secured deployment %s")
+    void warSecured(String deployment);
+
+}
diff --git a/saml/client-adapter/as7-eap6/subsystem/src/main/java/org/keycloak/subsystem/saml/as7/logging/KeycloakMessages.java b/saml/client-adapter/as7-eap6/subsystem/src/main/java/org/keycloak/subsystem/saml/as7/logging/KeycloakMessages.java
new file mode 100755
index 0000000..f4917b1
--- /dev/null
+++ b/saml/client-adapter/as7-eap6/subsystem/src/main/java/org/keycloak/subsystem/saml/as7/logging/KeycloakMessages.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2013 Red Hat Inc. and/or its affiliates and other contributors
+ * as indicated by the @author tags. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package org.keycloak.subsystem.saml.as7.logging;
+
+import org.jboss.logging.MessageBundle;
+import org.jboss.logging.Messages;
+
+/**
+ * This interface to be fleshed out later when error messages are fully externalized.
+ *
+ * @author Stan Silvert ssilvert@redhat.com (C) 2012 Red Hat Inc.
+ */
+@MessageBundle(projectCode = "TLIP")
+public interface KeycloakMessages {
+
+    /**
+     * The messages
+     */
+    KeycloakMessages MESSAGES = Messages.getBundle(KeycloakMessages.class);
+}
diff --git a/saml/client-adapter/as7-eap6/subsystem/src/main/java/org/keycloak/subsystem/saml/as7/SecureDeploymentAddHandler.java b/saml/client-adapter/as7-eap6/subsystem/src/main/java/org/keycloak/subsystem/saml/as7/SecureDeploymentAddHandler.java
new file mode 100644
index 0000000..c5325f6
--- /dev/null
+++ b/saml/client-adapter/as7-eap6/subsystem/src/main/java/org/keycloak/subsystem/saml/as7/SecureDeploymentAddHandler.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2015 Red Hat Inc. and/or its affiliates and other contributors
+ * as indicated by the @author tags. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package org.keycloak.subsystem.saml.as7;
+
+import org.jboss.as.controller.AbstractAddStepHandler;
+import org.jboss.as.controller.OperationContext;
+import org.jboss.as.controller.OperationFailedException;
+import org.jboss.as.controller.ServiceVerificationHandler;
+import org.jboss.dmr.ModelNode;
+import org.jboss.msc.service.ServiceController;
+
+import java.util.List;
+
+/**
+ * @author <a href="mailto:mstrukel@redhat.com">Marko Strukelj</a>
+ */
+class SecureDeploymentAddHandler extends AbstractAddStepHandler {
+
+    static SecureDeploymentAddHandler INSTANCE = new SecureDeploymentAddHandler();
+
+    private SecureDeploymentAddHandler() {
+    }
+
+    @Override
+    protected void performRuntime(OperationContext context, ModelNode operation, ModelNode model, ServiceVerificationHandler verificationHandler, List<ServiceController<?>> newControllers) throws OperationFailedException {
+        Configuration.INSTANCE.updateModel(operation, model);
+    }
+}
diff --git a/saml/client-adapter/as7-eap6/subsystem/src/main/java/org/keycloak/subsystem/saml/as7/SecureDeploymentDefinition.java b/saml/client-adapter/as7-eap6/subsystem/src/main/java/org/keycloak/subsystem/saml/as7/SecureDeploymentDefinition.java
new file mode 100644
index 0000000..75f4dca
--- /dev/null
+++ b/saml/client-adapter/as7-eap6/subsystem/src/main/java/org/keycloak/subsystem/saml/as7/SecureDeploymentDefinition.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2015 Red Hat Inc. and/or its affiliates and other contributors
+ * as indicated by the @author tags. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package org.keycloak.subsystem.saml.as7;
+
+import org.jboss.as.controller.PathElement;
+import org.jboss.as.controller.ReloadRequiredRemoveStepHandler;
+import org.jboss.as.controller.SimpleResourceDefinition;
+import org.jboss.as.controller.operations.common.GenericSubsystemDescribeHandler;
+import org.jboss.as.controller.registry.ManagementResourceRegistration;
+
+/**
+ * Defines attributes and operations for a secure-deployment.
+ */
+public class SecureDeploymentDefinition extends SimpleResourceDefinition {
+
+    static final SecureDeploymentDefinition INSTANCE = new SecureDeploymentDefinition();
+
+    private SecureDeploymentDefinition() {
+        super(PathElement.pathElement(Constants.Model.SECURE_DEPLOYMENT),
+                KeycloakSamlExtension.getResourceDescriptionResolver(Constants.Model.SECURE_DEPLOYMENT),
+                SecureDeploymentAddHandler.INSTANCE,
+                ReloadRequiredRemoveStepHandler.INSTANCE);
+    }
+
+    @Override
+    public void registerOperations(ManagementResourceRegistration resourceRegistration) {
+        super.registerOperations(resourceRegistration);
+        resourceRegistration.registerOperationHandler(GenericSubsystemDescribeHandler.DEFINITION, GenericSubsystemDescribeHandler.INSTANCE);
+    }
+}
diff --git a/saml/client-adapter/as7-eap6/subsystem/src/main/java/org/keycloak/subsystem/saml/as7/ServiceProviderAddHandler.java b/saml/client-adapter/as7-eap6/subsystem/src/main/java/org/keycloak/subsystem/saml/as7/ServiceProviderAddHandler.java
new file mode 100644
index 0000000..33d6015
--- /dev/null
+++ b/saml/client-adapter/as7-eap6/subsystem/src/main/java/org/keycloak/subsystem/saml/as7/ServiceProviderAddHandler.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2015 Red Hat Inc. and/or its affiliates and other contributors
+ * as indicated by the @author tags. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package org.keycloak.subsystem.saml.as7;
+
+import org.jboss.as.controller.AbstractAddStepHandler;
+import org.jboss.as.controller.OperationContext;
+import org.jboss.as.controller.OperationFailedException;
+import org.jboss.as.controller.ServiceVerificationHandler;
+import org.jboss.dmr.ModelNode;
+import org.jboss.msc.service.ServiceController;
+
+import java.util.List;
+
+/**
+ * @author <a href="mailto:mstrukel@redhat.com">Marko Strukelj</a>
+ */
+class ServiceProviderAddHandler extends AbstractAddStepHandler {
+
+    static final ServiceProviderAddHandler INSTANCE = new ServiceProviderAddHandler();
+
+    ServiceProviderAddHandler() {
+        super(ServiceProviderDefinition.ALL_ATTRIBUTES);
+    }
+
+    @Override
+    protected void performRuntime(OperationContext context, ModelNode operation, ModelNode model, ServiceVerificationHandler verificationHandler, List<ServiceController<?>> newControllers) throws OperationFailedException {
+        Configuration.INSTANCE.updateModel(operation, model);
+    }
+}
diff --git a/saml/client-adapter/as7-eap6/subsystem/src/main/java/org/keycloak/subsystem/saml/as7/ServiceProviderDefinition.java b/saml/client-adapter/as7-eap6/subsystem/src/main/java/org/keycloak/subsystem/saml/as7/ServiceProviderDefinition.java
new file mode 100644
index 0000000..02ecc8f
--- /dev/null
+++ b/saml/client-adapter/as7-eap6/subsystem/src/main/java/org/keycloak/subsystem/saml/as7/ServiceProviderDefinition.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2015 Red Hat Inc. and/or its affiliates and other contributors
+ * as indicated by the @author tags. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package org.keycloak.subsystem.saml.as7;
+
+import org.jboss.as.controller.AttributeDefinition;
+import org.jboss.as.controller.ListAttributeDefinition;
+import org.jboss.as.controller.OperationStepHandler;
+import org.jboss.as.controller.PathElement;
+import org.jboss.as.controller.ReloadRequiredRemoveStepHandler;
+import org.jboss.as.controller.ReloadRequiredWriteAttributeHandler;
+import org.jboss.as.controller.SimpleAttributeDefinition;
+import org.jboss.as.controller.SimpleAttributeDefinitionBuilder;
+import org.jboss.as.controller.SimpleResourceDefinition;
+import org.jboss.as.controller.StringListAttributeDefinition;
+import org.jboss.as.controller.operations.common.GenericSubsystemDescribeHandler;
+import org.jboss.as.controller.registry.ManagementResourceRegistration;
+import org.jboss.dmr.ModelType;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+
+/**
+ * @author <a href="mailto:mstrukel@redhat.com">Marko Strukelj</a>
+ */
+public class ServiceProviderDefinition extends SimpleResourceDefinition {
+
+    static final SimpleAttributeDefinition SSL_POLICY =
+            new SimpleAttributeDefinitionBuilder(Constants.Model.SSL_POLICY, ModelType.STRING, true)
+                    .setXmlName(Constants.XML.SSL_POLICY)
+                    .build();
+
+    static final SimpleAttributeDefinition NAME_ID_POLICY_FORMAT =
+            new SimpleAttributeDefinitionBuilder(Constants.Model.NAME_ID_POLICY_FORMAT, ModelType.STRING, true)
+                    .setXmlName(Constants.XML.NAME_ID_POLICY_FORMAT)
+                    .build();
+
+    static final SimpleAttributeDefinition LOGOUT_PAGE =
+            new SimpleAttributeDefinitionBuilder(Constants.Model.LOGOUT_PAGE, ModelType.STRING, true)
+                    .setXmlName(Constants.XML.LOGOUT_PAGE)
+                    .build();
+
+    static final SimpleAttributeDefinition FORCE_AUTHENTICATION =
+            new SimpleAttributeDefinitionBuilder(Constants.Model.FORCE_AUTHENTICATION, ModelType.BOOLEAN, true)
+                    .setXmlName(Constants.XML.FORCE_AUTHENTICATION)
+                    .build();
+
+    static final SimpleAttributeDefinition PRINCIPAL_NAME_MAPPING_POLICY =
+            new SimpleAttributeDefinitionBuilder(Constants.Model.PRINCIPAL_NAME_MAPPING_POLICY, ModelType.STRING, true)
+                    .setXmlName(Constants.XML.PRINCIPAL_NAME_MAPPING_POLICY)
+                    .build();
+
+    static final SimpleAttributeDefinition PRINCIPAL_NAME_MAPPING_ATTRIBUTE_NAME =
+            new SimpleAttributeDefinitionBuilder(Constants.Model.PRINCIPAL_NAME_MAPPING_ATTRIBUTE_NAME, ModelType.STRING, true)
+                    .setXmlName(Constants.XML.PRINCIPAL_NAME_MAPPING_ATTRIBUTE_NAME)
+                    .build();
+
+    static final ListAttributeDefinition ROLE_ATTRIBUTES =
+            new StringListAttributeDefinition.Builder(Constants.Model.ROLE_ATTRIBUTES)
+                    .setAllowNull(false)
+                    .build();
+
+    static final SimpleAttributeDefinition[] ATTRIBUTES = {SSL_POLICY, NAME_ID_POLICY_FORMAT, LOGOUT_PAGE, FORCE_AUTHENTICATION};
+    static final AttributeDefinition[] ELEMENTS = {PRINCIPAL_NAME_MAPPING_POLICY, PRINCIPAL_NAME_MAPPING_ATTRIBUTE_NAME, ROLE_ATTRIBUTES};
+
+
+    static final HashMap<String, SimpleAttributeDefinition> ATTRIBUTE_MAP = new HashMap<>();
+    static final HashMap<String, AttributeDefinition> ALL_MAP = new HashMap<>();
+    static final Collection<AttributeDefinition> ALL_ATTRIBUTES;
+
+    static {
+        for (SimpleAttributeDefinition def : ATTRIBUTES) {
+            ATTRIBUTE_MAP.put(def.getXmlName(), def);
+        }
+
+        ALL_MAP.putAll(ATTRIBUTE_MAP);
+        for (AttributeDefinition def : ELEMENTS) {
+            ALL_MAP.put(def.getXmlName(), def);
+        }
+        ALL_ATTRIBUTES = Collections.unmodifiableCollection(ALL_MAP.values());
+    }
+
+    static final ServiceProviderDefinition INSTANCE = new ServiceProviderDefinition();
+
+    private ServiceProviderDefinition() {
+        super(PathElement.pathElement(Constants.Model.SERVICE_PROVIDER),
+                KeycloakSamlExtension.getResourceDescriptionResolver(Constants.Model.SERVICE_PROVIDER),
+                ServiceProviderAddHandler.INSTANCE,
+                ReloadRequiredRemoveStepHandler.INSTANCE);
+    }
+
+    @Override
+    public void registerOperations(ManagementResourceRegistration resourceRegistration) {
+        super.registerOperations(resourceRegistration);
+        resourceRegistration.registerOperationHandler(GenericSubsystemDescribeHandler.DEFINITION, GenericSubsystemDescribeHandler.INSTANCE);
+    }
+
+    @Override
+    public void registerAttributes(ManagementResourceRegistration resourceRegistration) {
+        super.registerAttributes(resourceRegistration);
+
+        final OperationStepHandler writeHandler = new ReloadRequiredWriteAttributeHandler(ALL_ATTRIBUTES);
+        for (AttributeDefinition attribute : ALL_ATTRIBUTES) {
+            resourceRegistration.registerReadWriteAttribute(attribute, null, writeHandler);
+        }
+    }
+
+    static SimpleAttributeDefinition lookup(String xmlName) {
+        return ATTRIBUTE_MAP.get(xmlName);
+    }
+}
diff --git a/saml/client-adapter/as7-eap6/subsystem/src/main/java/org/keycloak/subsystem/saml/as7/SingleLogoutDefinition.java b/saml/client-adapter/as7-eap6/subsystem/src/main/java/org/keycloak/subsystem/saml/as7/SingleLogoutDefinition.java
new file mode 100644
index 0000000..beb884c
--- /dev/null
+++ b/saml/client-adapter/as7-eap6/subsystem/src/main/java/org/keycloak/subsystem/saml/as7/SingleLogoutDefinition.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2015 Red Hat Inc. and/or its affiliates and other contributors
+ * as indicated by the @author tags. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package org.keycloak.subsystem.saml.as7;
+
+import org.jboss.as.controller.SimpleAttributeDefinition;
+import org.jboss.as.controller.SimpleAttributeDefinitionBuilder;
+import org.jboss.dmr.ModelType;
+
+import java.util.HashMap;
+
+/**
+ * @author <a href="mailto:mstrukel@redhat.com">Marko Strukelj</a>
+ */
+abstract class SingleLogoutDefinition {
+
+    static final SimpleAttributeDefinition VALIDATE_REQUEST_SIGNATURE =
+            new SimpleAttributeDefinitionBuilder(Constants.Model.VALIDATE_REQUEST_SIGNATURE, ModelType.BOOLEAN, true)
+                    .setXmlName(Constants.XML.VALIDATE_REQUEST_SIGNATURE)
+                    .build();
+
+    static final SimpleAttributeDefinition VALIDATE_RESPONSE_SIGNATURE =
+            new SimpleAttributeDefinitionBuilder(Constants.Model.VALIDATE_RESPONSE_SIGNATURE, ModelType.BOOLEAN, true)
+                    .setXmlName(Constants.XML.VALIDATE_RESPONSE_SIGNATURE)
+                    .build();
+
+    static final SimpleAttributeDefinition SIGN_REQUEST =
+            new SimpleAttributeDefinitionBuilder(Constants.Model.SIGN_REQUEST, ModelType.BOOLEAN, true)
+                    .setXmlName(Constants.XML.SIGN_REQUEST)
+                    .build();
+
+    static final SimpleAttributeDefinition SIGN_RESPONSE =
+            new SimpleAttributeDefinitionBuilder(Constants.Model.SIGN_RESPONSE, ModelType.BOOLEAN, true)
+                    .setXmlName(Constants.XML.SIGN_RESPONSE)
+                    .build();
+
+    static final SimpleAttributeDefinition REQUEST_BINDING =
+            new SimpleAttributeDefinitionBuilder(Constants.Model.REQUEST_BINDING, ModelType.STRING, true)
+                    .setXmlName(Constants.XML.REQUEST_BINDING)
+                    .build();
+
+    static final SimpleAttributeDefinition RESPONSE_BINDING =
+            new SimpleAttributeDefinitionBuilder(Constants.Model.RESPONSE_BINDING, ModelType.STRING, true)
+                    .setXmlName(Constants.XML.RESPONSE_BINDING)
+                    .build();
+
+    static final SimpleAttributeDefinition POST_BINDING_URL =
+            new SimpleAttributeDefinitionBuilder(Constants.Model.POST_BINDING_URL, ModelType.STRING, true)
+                    .setXmlName(Constants.XML.POST_BINDING_URL)
+                    .build();
+
+    static final SimpleAttributeDefinition REDIRECT_BINDING_URL =
+            new SimpleAttributeDefinitionBuilder(Constants.Model.REDIRECT_BINDING_URL, ModelType.STRING, true)
+                    .setXmlName(Constants.XML.REDIRECT_BINDING_URL)
+                    .build();
+
+    static final SimpleAttributeDefinition[] ATTRIBUTES = {VALIDATE_REQUEST_SIGNATURE, VALIDATE_RESPONSE_SIGNATURE,
+            SIGN_REQUEST, SIGN_RESPONSE, REQUEST_BINDING, RESPONSE_BINDING, POST_BINDING_URL, REDIRECT_BINDING_URL};
+
+    static final HashMap<String, SimpleAttributeDefinition> ATTRIBUTE_MAP = new HashMap<>();
+
+    static {
+        for (SimpleAttributeDefinition def : ATTRIBUTES) {
+            ATTRIBUTE_MAP.put(def.getXmlName(), def);
+        }
+    }
+
+    static SimpleAttributeDefinition lookup(String xmlName) {
+        return ATTRIBUTE_MAP.get(xmlName);
+    }
+}
diff --git a/saml/client-adapter/as7-eap6/subsystem/src/main/java/org/keycloak/subsystem/saml/as7/SingleSignOnDefinition.java b/saml/client-adapter/as7-eap6/subsystem/src/main/java/org/keycloak/subsystem/saml/as7/SingleSignOnDefinition.java
new file mode 100644
index 0000000..827be9b
--- /dev/null
+++ b/saml/client-adapter/as7-eap6/subsystem/src/main/java/org/keycloak/subsystem/saml/as7/SingleSignOnDefinition.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2015 Red Hat Inc. and/or its affiliates and other contributors
+ * as indicated by the @author tags. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package org.keycloak.subsystem.saml.as7;
+
+import org.jboss.as.controller.SimpleAttributeDefinition;
+import org.jboss.as.controller.SimpleAttributeDefinitionBuilder;
+import org.jboss.dmr.ModelType;
+
+import java.util.HashMap;
+
+/**
+ * @author <a href="mailto:mstrukel@redhat.com">Marko Strukelj</a>
+ */
+abstract class SingleSignOnDefinition {
+
+    static final SimpleAttributeDefinition SIGN_REQUEST =
+            new SimpleAttributeDefinitionBuilder(Constants.Model.SIGN_REQUEST, ModelType.BOOLEAN, true)
+                    .setXmlName(Constants.XML.SIGN_REQUEST)
+                    .build();
+
+    static final SimpleAttributeDefinition VALIDATE_RESPONSE_SIGNATURE =
+            new SimpleAttributeDefinitionBuilder(Constants.Model.VALIDATE_RESPONSE_SIGNATURE, ModelType.BOOLEAN, true)
+                    .setXmlName(Constants.XML.VALIDATE_RESPONSE_SIGNATURE)
+                    .build();
+
+    static final SimpleAttributeDefinition REQUEST_BINDING =
+            new SimpleAttributeDefinitionBuilder(Constants.Model.REQUEST_BINDING, ModelType.STRING, true)
+                    .setXmlName(Constants.XML.REQUEST_BINDING)
+                    .build();
+
+    static final SimpleAttributeDefinition RESPONSE_BINDING =
+            new SimpleAttributeDefinitionBuilder(Constants.Model.RESPONSE_BINDING, ModelType.STRING, true)
+                    .setXmlName(Constants.XML.RESPONSE_BINDING)
+                    .build();
+
+    static final SimpleAttributeDefinition BINDING_URL =
+            new SimpleAttributeDefinitionBuilder(Constants.Model.BINDING_URL, ModelType.STRING, true)
+                    .setXmlName(Constants.XML.BINDING_URL)
+                    .build();
+
+    static final SimpleAttributeDefinition[] ATTRIBUTES = {SIGN_REQUEST, VALIDATE_RESPONSE_SIGNATURE, REQUEST_BINDING, RESPONSE_BINDING, BINDING_URL};
+
+    static final HashMap<String, SimpleAttributeDefinition> ATTRIBUTE_MAP = new HashMap<>();
+
+    static {
+        for (SimpleAttributeDefinition def : ATTRIBUTES) {
+            ATTRIBUTE_MAP.put(def.getXmlName(), def);
+        }
+    }
+
+    static SimpleAttributeDefinition lookup(String xmlName) {
+        return ATTRIBUTE_MAP.get(xmlName);
+    }
+}
diff --git a/saml/client-adapter/as7-eap6/subsystem/src/main/java/org/keycloak/subsystem/saml/as7/xml/FormattingXMLStreamWriter.java b/saml/client-adapter/as7-eap6/subsystem/src/main/java/org/keycloak/subsystem/saml/as7/xml/FormattingXMLStreamWriter.java
new file mode 100644
index 0000000..dda3ed3
--- /dev/null
+++ b/saml/client-adapter/as7-eap6/subsystem/src/main/java/org/keycloak/subsystem/saml/as7/xml/FormattingXMLStreamWriter.java
@@ -0,0 +1,534 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2010, 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.
+ */
+
+package org.keycloak.subsystem.saml.as7.xml;
+
+import org.jboss.staxmapper.XMLExtendedStreamWriter;
+
+import java.lang.reflect.UndeclaredThrowableException;
+import java.util.ArrayDeque;
+import java.util.Iterator;
+
+import javax.xml.namespace.NamespaceContext;
+import javax.xml.stream.XMLStreamConstants;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamWriter;
+
+/**
+ * An XML stream writer which nicely formats the XML for configuration files.
+ *
+ * @author <a href="mailto:david.lloyd@redhat.com">David M. Lloyd</a>
+ */
+public final class FormattingXMLStreamWriter implements XMLExtendedStreamWriter, XMLStreamConstants {
+    private static final String NO_NAMESPACE = new String();
+    private final XMLStreamWriter delegate;
+    private final ArrayDeque<ArgRunnable> attrQueue = new ArrayDeque<ArgRunnable>();
+    private int level;
+    private int state = START_DOCUMENT;
+    private boolean indentEndElement = false;
+    private ArrayDeque<String> unspecifiedNamespaces = new ArrayDeque<String>();
+
+
+    public FormattingXMLStreamWriter(final XMLStreamWriter delegate) {
+        this.delegate = delegate;
+        unspecifiedNamespaces.push(NO_NAMESPACE);
+    }
+
+    private void nl() throws XMLStreamException {
+        delegate.writeCharacters("\n");
+    }
+
+    private void indent() throws XMLStreamException {
+        int level = this.level;
+        final XMLStreamWriter delegate = this.delegate;
+        for (int i = 0; i < level; i ++) {
+            delegate.writeCharacters("    ");
+        }
+    }
+
+    private interface ArgRunnable {
+        public void run(int arg) throws XMLStreamException;
+    }
+
+    @Override
+    public void setUnspecifiedElementNamespace(final String namespace) {
+        ArrayDeque<String> namespaces = this.unspecifiedNamespaces;
+        namespaces.pop();
+        namespaces.push(namespace == null ? NO_NAMESPACE : namespace);
+    }
+
+    private String nestUnspecifiedNamespace() {
+        ArrayDeque<String> namespaces = unspecifiedNamespaces;
+        String clone = namespaces.getFirst();
+        namespaces.push(clone);
+        return clone;
+    }
+
+    @Override
+    public void writeStartElement(final String localName) throws XMLStreamException {
+        ArrayDeque<String> namespaces = unspecifiedNamespaces;
+        String namespace = namespaces.getFirst();
+        if (namespace != NO_NAMESPACE) {
+            writeStartElement(namespace, localName);
+            return;
+        }
+
+        unspecifiedNamespaces.push(namespace);
+
+        // If this is a nested element flush the outer
+        runAttrQueue();
+        nl();
+        indent();
+        attrQueue.add(new ArgRunnable() {
+            public void run(int arg) throws XMLStreamException {
+                if (arg == 0) {
+                    delegate.writeStartElement(localName);
+                } else {
+                    delegate.writeEmptyElement(localName);
+                }
+            }
+        });
+
+        level++;
+        state = START_ELEMENT;
+        indentEndElement = false;
+    }
+
+    @Override
+    public void writeStartElement(final String namespaceURI, final String localName) throws XMLStreamException {
+        nestUnspecifiedNamespace();
+
+        // If this is a nested element flush the outer
+        runAttrQueue();
+        nl();
+        indent();
+        attrQueue.add(new ArgRunnable() {
+            public void run(int arg) throws XMLStreamException {
+                if (arg == 0) {
+                    delegate.writeStartElement(namespaceURI, localName);
+                } else {
+                    delegate.writeEmptyElement(namespaceURI, localName);
+                }
+            }
+        });
+        level++;
+        state = START_ELEMENT;
+        indentEndElement = false;
+    }
+
+    @Override
+    public void writeStartElement(final String prefix, final String localName, final String namespaceURI) throws XMLStreamException {
+        nestUnspecifiedNamespace();
+
+        // If this is a nested element flush the outer
+        runAttrQueue();
+        nl();
+        indent();
+        attrQueue.add(new ArgRunnable() {
+            public void run(int arg) throws XMLStreamException {
+                if (arg == 0) {
+                    delegate.writeStartElement(prefix, namespaceURI, localName);
+                } else {
+                    delegate.writeEmptyElement(prefix, namespaceURI, localName);
+                }
+            }
+        });
+        level++;
+        state = START_ELEMENT;
+        indentEndElement = false;
+    }
+
+    @Override
+    public void writeEmptyElement(final String namespaceURI, final String localName) throws XMLStreamException {
+        runAttrQueue();
+        nl();
+        indent();
+        delegate.writeEmptyElement(namespaceURI, localName);
+        state = END_ELEMENT;
+    }
+
+    @Override
+    public void writeEmptyElement(final String prefix, final String localName, final String namespaceURI) throws XMLStreamException {
+        runAttrQueue();
+        nl();
+        indent();
+        delegate.writeEmptyElement(prefix, namespaceURI, localName);
+        state = END_ELEMENT;
+    }
+
+    @Override
+    public void writeEmptyElement(final String localName) throws XMLStreamException {
+        String namespace = unspecifiedNamespaces.getFirst();
+        if (namespace != NO_NAMESPACE) {
+            writeEmptyElement(namespace, localName);
+            return;
+        }
+
+        runAttrQueue();
+        nl();
+        indent();
+        delegate.writeEmptyElement(localName);
+        state = END_ELEMENT;
+    }
+
+    @Override
+    public void writeEndElement() throws XMLStreamException {
+        level--;
+        if (state != START_ELEMENT) {
+            runAttrQueue();
+            if (state != CHARACTERS || indentEndElement) {
+                nl();
+                indent();
+                indentEndElement = false;
+            }
+            delegate.writeEndElement();
+        } else {
+            // Change the start element to an empty element
+            ArgRunnable start = attrQueue.poll();
+            if (start == null) {
+                delegate.writeEndElement();
+            } else {
+                start.run(1);
+                // Write everything else
+                runAttrQueue();
+            }
+        }
+
+        unspecifiedNamespaces.pop();
+        state = END_ELEMENT;
+    }
+
+    private void runAttrQueue() throws XMLStreamException {
+        ArgRunnable attr;
+        while ((attr = attrQueue.poll()) != null) {
+            attr.run(0);
+        }
+    }
+
+    @Override
+    public void writeEndDocument() throws XMLStreamException {
+        delegate.writeEndDocument();
+        state = END_DOCUMENT;
+    }
+
+    @Override
+    public void close() throws XMLStreamException {
+        delegate.close();
+        state = END_DOCUMENT;
+    }
+
+    @Override
+    public void flush() throws XMLStreamException {
+        delegate.flush();
+    }
+
+    @Override
+    public void writeAttribute(final String localName, final String value) throws XMLStreamException {
+        attrQueue.add(new ArgRunnable() {
+            public void run(int arg) throws XMLStreamException {
+                try {
+                    delegate.writeAttribute(localName, value);
+                } catch (XMLStreamException e) {
+                    throw new UndeclaredThrowableException(e);
+                }
+            }
+        });
+    }
+
+    @Override
+    public void writeAttribute(final String prefix, final String namespaceURI, final String localName, final String value) throws XMLStreamException {
+        attrQueue.add(new ArgRunnable() {
+            public void run(int arg) throws XMLStreamException {
+                delegate.writeAttribute(prefix, namespaceURI, localName, value);
+            }
+        });
+    }
+
+    @Override
+    public void writeAttribute(final String namespaceURI, final String localName, final String value) throws XMLStreamException {
+        attrQueue.add(new ArgRunnable() {
+            public void run(int arg) throws XMLStreamException {
+                delegate.writeAttribute(namespaceURI, localName, value);
+            }
+        });
+    }
+
+    @Override
+    public void writeAttribute(final String localName, final String[] values) throws XMLStreamException {
+        attrQueue.add(new ArgRunnable() {
+            public void run(int arg) throws XMLStreamException {
+                delegate.writeAttribute(localName, join(values));
+            }
+        });
+    }
+
+    @Override
+    public void writeAttribute(final String prefix, final String namespaceURI, final String localName, final String[] values) throws XMLStreamException {
+        attrQueue.add(new ArgRunnable() {
+            public void run(int arg) throws XMLStreamException {
+                delegate.writeAttribute(prefix, namespaceURI, localName, join(values));
+            }
+        });
+    }
+
+    @Override
+    public void writeAttribute(final String namespaceURI, final String localName, final String[] values) throws XMLStreamException {
+        attrQueue.add(new ArgRunnable() {
+            public void run(int arg) throws XMLStreamException {
+                delegate.writeAttribute(namespaceURI, localName, join(values));
+            }
+        });
+    }
+
+    @Override
+    public void writeAttribute(final String localName, final Iterable<String> values) throws XMLStreamException {
+        attrQueue.add(new ArgRunnable() {
+            public void run(int arg) throws XMLStreamException {
+                delegate.writeAttribute(localName, join(values));
+            }
+        });
+    }
+
+    @Override
+    public void writeAttribute(final String prefix, final String namespaceURI, final String localName, final Iterable<String> values) throws XMLStreamException {
+        attrQueue.add(new ArgRunnable() {
+            public void run(int arg) throws XMLStreamException {
+                delegate.writeAttribute(prefix, namespaceURI, localName, join(values));
+            }
+        });
+    }
+
+    @Override
+    public void writeAttribute(final String namespaceURI, final String localName, final Iterable<String> values) throws XMLStreamException {
+        attrQueue.add(new ArgRunnable() {
+            public void run(int arg) throws XMLStreamException {
+                delegate.writeAttribute(namespaceURI, localName, join(values));
+            }
+        });
+    }
+
+    @Override
+    public void writeNamespace(final String prefix, final String namespaceURI) throws XMLStreamException {
+        attrQueue.add(new ArgRunnable() {
+            public void run(int arg) throws XMLStreamException {
+                delegate.writeNamespace(prefix, namespaceURI);
+            }
+        });
+    }
+
+    @Override
+    public void writeDefaultNamespace(final String namespaceURI) throws XMLStreamException {
+        attrQueue.add(new ArgRunnable() {
+            public void run(int arg) throws XMLStreamException {
+                delegate.writeDefaultNamespace(namespaceURI);
+            }
+        });
+    }
+
+    @Override
+    public void writeComment(final String data) throws XMLStreamException {
+        runAttrQueue();
+        nl();
+        nl();
+        indent();
+        final StringBuilder b = new StringBuilder(data.length());
+        final Iterator<String> i = Spliterator.over(data, '\n');
+        if (! i.hasNext()) {
+            return;
+        } else {
+            final String first = i.next();
+            if (! i.hasNext()) {
+                delegate.writeComment(" " + first + " ");
+                state = COMMENT;
+                return;
+            } else {
+                b.append('\n');
+                for (int q = 0; q < level; q++) {
+                    b.append("    ");
+                }
+                b.append("  ~ ");
+                b.append(first);
+                do {
+                    b.append('\n');
+                    for (int q = 0; q < level; q++) {
+                        b.append("    ");
+                    }
+                    b.append("  ~ ");
+                    b.append(i.next());
+                } while (i.hasNext());
+            }
+            b.append('\n');
+            for (int q = 0; q < level; q ++) {
+                b.append("    ");
+            }
+            b.append("  ");
+            delegate.writeComment(b.toString());
+            state = COMMENT;
+        }
+    }
+
+    @Override
+    public void writeProcessingInstruction(final String target) throws XMLStreamException {
+        runAttrQueue();
+        nl();
+        indent();
+        delegate.writeProcessingInstruction(target);
+        state = PROCESSING_INSTRUCTION;
+    }
+
+    @Override
+    public void writeProcessingInstruction(final String target, final String data) throws XMLStreamException {
+        runAttrQueue();
+        nl();
+        indent();
+        delegate.writeProcessingInstruction(target, data);
+        state = PROCESSING_INSTRUCTION;
+    }
+
+    @Override
+    public void writeCData(final String data) throws XMLStreamException {
+        runAttrQueue();
+        delegate.writeCData(data);
+        state = CDATA;
+    }
+
+    @Override
+    public void writeDTD(final String dtd) throws XMLStreamException {
+        nl();
+        indent();
+        delegate.writeDTD(dtd);
+        state = DTD;
+    }
+
+    @Override
+    public void writeEntityRef(final String name) throws XMLStreamException {
+        runAttrQueue();
+        delegate.writeEntityRef(name);
+        state = ENTITY_REFERENCE;
+    }
+
+    @Override
+    public void writeStartDocument() throws XMLStreamException {
+        delegate.writeStartDocument();
+        nl();
+        state = START_DOCUMENT;
+    }
+
+    @Override
+    public void writeStartDocument(final String version) throws XMLStreamException {
+        delegate.writeStartDocument(version);
+        nl();
+        state = START_DOCUMENT;
+    }
+
+    @Override
+    public void writeStartDocument(final String encoding, final String version) throws XMLStreamException {
+        delegate.writeStartDocument(encoding, version);
+        nl();
+        state = START_DOCUMENT;
+    }
+
+    @Override
+    public void writeCharacters(final String text) throws XMLStreamException {
+        runAttrQueue();
+        if (state != CHARACTERS) {
+            nl();
+            indent();
+        }
+        final Iterator<String> iterator = Spliterator.over(text, '\n');
+        while (iterator.hasNext()) {
+            final String t = iterator.next();
+            delegate.writeCharacters(t);
+            if (iterator.hasNext()) {
+                nl();
+                indent();
+            }
+        }
+        state = CHARACTERS;
+        indentEndElement = true;
+    }
+
+    @Override
+    public void writeCharacters(final char[] text, final int start, final int len) throws XMLStreamException {
+        runAttrQueue();
+        delegate.writeCharacters(text, start, len);
+        state = CHARACTERS;
+    }
+
+    @Override
+    public String getPrefix(final String uri) throws XMLStreamException {
+        return delegate.getPrefix(uri);
+    }
+
+    @Override
+    public void setPrefix(final String prefix, final String uri) throws XMLStreamException {
+        delegate.setPrefix(prefix, uri);
+    }
+
+    @Override
+    public void setDefaultNamespace(final String uri) throws XMLStreamException {
+        runAttrQueue();
+        delegate.setDefaultNamespace(uri);
+    }
+
+    @Override
+    public void setNamespaceContext(final NamespaceContext context) throws XMLStreamException {
+        delegate.setNamespaceContext(context);
+    }
+
+    @Override
+    public NamespaceContext getNamespaceContext() {
+        return delegate.getNamespaceContext();
+    }
+
+    @Override
+    public Object getProperty(final String name) throws IllegalArgumentException {
+        return delegate.getProperty(name);
+    }
+
+    private static String join(final String[] values) {
+        final StringBuilder b = new StringBuilder();
+        for (int i = 0, valuesLength = values.length; i < valuesLength; i++) {
+            final String s = values[i];
+            if (s != null) {
+                if (i > 0) {
+                    b.append(' ');
+                }
+                b.append(s);
+            }
+        }
+        return b.toString();
+    }
+
+    private static String join(final Iterable<String> values) {
+        final StringBuilder b = new StringBuilder();
+        Iterator<String> iterator = values.iterator();
+        while (iterator.hasNext()) {
+            final String s = iterator.next();
+            if (s != null) {
+                b.append(s);
+                if (iterator.hasNext()) b.append(' ');
+            }
+        }
+        return b.toString();
+    }
+}
diff --git a/saml/client-adapter/as7-eap6/subsystem/src/main/java/org/keycloak/subsystem/saml/as7/xml/Spliterator.java b/saml/client-adapter/as7-eap6/subsystem/src/main/java/org/keycloak/subsystem/saml/as7/xml/Spliterator.java
new file mode 100644
index 0000000..e9cb5c6
--- /dev/null
+++ b/saml/client-adapter/as7-eap6/subsystem/src/main/java/org/keycloak/subsystem/saml/as7/xml/Spliterator.java
@@ -0,0 +1,66 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2010, 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.
+ */
+
+package org.keycloak.subsystem.saml.as7.xml;
+
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+
+/**
+ * @author <a href="mailto:david.lloyd@redhat.com">David M. Lloyd</a>
+ */
+final class Spliterator implements Iterator<String> {
+    private final String subject;
+    private final char delimiter;
+    private int i;
+
+    Spliterator(final String subject, final char delimiter) {
+        this.subject = subject;
+        this.delimiter = delimiter;
+        i = 0;
+    }
+
+    static Spliterator over(String subject, char delimiter) {
+        return new Spliterator(subject, delimiter);
+    }
+
+    public boolean hasNext() {
+        return i != -1;
+    }
+
+    public String next() {
+        final int i = this.i;
+        if (i == -1) {
+            throw new NoSuchElementException();
+        }
+        int n = subject.indexOf(delimiter, i);
+        try {
+            return n == -1 ? subject.substring(i) : subject.substring(i, n);
+        } finally {
+            this.i = n == -1 ? -1 : n + 1;
+        }
+    }
+
+    public void remove() {
+        throw new UnsupportedOperationException();
+    }
+}
diff --git a/saml/client-adapter/as7-eap6/subsystem/src/main/resources/org/keycloak/subsystem/saml/as7/LocalDescriptions.properties b/saml/client-adapter/as7-eap6/subsystem/src/main/resources/org/keycloak/subsystem/saml/as7/LocalDescriptions.properties
new file mode 100755
index 0000000..f8a4a11
--- /dev/null
+++ b/saml/client-adapter/as7-eap6/subsystem/src/main/resources/org/keycloak/subsystem/saml/as7/LocalDescriptions.properties
@@ -0,0 +1,63 @@
+keycloak-saml.subsystem=Keycloak adapter subsystem
+keycloak-saml.subsystem.add=Operation Adds Keycloak adapter subsystem
+keycloak-saml.subsystem.remove=Operation removes Keycloak adapter subsystem
+keycloak-saml.subsystem.secure-deployment=A deployment secured by Keycloak.
+
+keycloak-saml.secure-deployment=A deployment secured by Keycloak
+keycloak-saml.secure-deployment.add=Add a deployment to be secured by Keycloak
+keycloak-saml.secure-deployment.remove=Remove a deployment to be secured by Keycloak
+keycloak-saml.secure-deployment.service-provider=A security provider configuration for secure deployment
+
+keycloak-saml.service-provider=A security provider configuration for secure deployment
+keycloak-saml.service-provider.add=Add a security provider configuration to deployment secured by Keycloak SAML
+keycloak-saml.service-provider.remove=Remove a security provider definition from deployment secured by Keycloak SAML
+keycloak-saml.service-provider.ssl-policy=SSL Policy to use
+keycloak-saml.service-provider.name-id-policy-format=Name ID policy format URN
+keycloak-saml.service-provider.logout-page=URI to a logout page
+keycloak-saml.service-provider.force-authentication=Redirected unauthenticated request to a login page
+keycloak-saml.service-provider.role-attributes=Role identifiers
+keycloak-saml.service-provider.principal-name-mapping-policy=Principal name mapping policy
+keycloak-saml.service-provider.principal-name-mapping-attribute-name=Principal name mapping attribute name
+keycloak-saml.service-provider.key=A key definition
+keycloak-saml.service-provider.identity-provider=Identity provider definition
+
+keycloak-saml.key=A key configuration for service provider or identity provider
+keycloak-saml.key.add=Add a key definition
+keycloak-saml.key.remove=Remove a key definition
+keycloak-saml.key.signing=Key can be used for signing
+keycloak-saml.key.encryption=Key can be used for encryption
+keycloak-saml.key.private-key-pem=Private key string in pem format
+keycloak-saml.key.public-key-pem=Public key string in pem format
+keycloak-saml.key.certificate-pem=Certificate key string in pem format
+keycloak-saml.key.key-store=Key store definition
+keycloak-saml.key.key-store.file=Key store filesystem path
+keycloak-saml.key.key-store.resource=Key store resource URI
+keycloak-saml.key.key-store.password=Key store password
+keycloak-saml.key.key-store.type=Key store format
+keycloak-saml.key.key-store.alias=Key alias
+keycloak-saml.key.key-store.private-key-alias=Private key alias
+keycloak-saml.key.key-store.private-key-password=Private key password
+keycloak-saml.key.key-store.certificate-alias=Certificate alias
+
+keycloak-saml.identity-provider=An identity provider configuration
+keycloak-saml.identity-provider.add=Add an identity provider
+keycloak-saml.identity-provider.remove=Remove an identity provider
+keycloak-saml.identity-provider.signatures-required=Require signatures for single-sign-on and single-logout
+keycloak-saml.identity-provider.signature-algorithm=Signature algorithm
+keycloak-saml.identity-provider.signature-canonicalization-method=Signature canonicalization method
+keycloak-saml.identity-provider.single-sign-on=Single sign-on configuration
+keycloak-saml.identity-provider.single-sign-on.sign-request=Sign SSO requests
+keycloak-saml.identity-provider.single-sign-on.validate-response-signature=Validate an SSO response signature
+keycloak-saml.identity-provider.single-sign-on.request-binding=HTTP method to use for requests
+keycloak-saml.identity-provider.single-sign-on.response-binding=HTTP method to use for responses
+keycloak-saml.identity-provider.single-sign-on.binding-url=SSO endpoint URL
+keycloak-saml.identity-provider.single-logout=Single logout configuration
+keycloak-saml.identity-provider.single-logout.validate-request-signature=Validate a single-logout request signature
+keycloak-saml.identity-provider.single-logout.validate-response-signature=Validate a single-logout response signature
+keycloak-saml.identity-provider.single-logout.sign-request=Sign single-logout requests
+keycloak-saml.identity-provider.single-logout.sign-response=Sign single-logout responses
+keycloak-saml.identity-provider.single-logout.request-binding=HTTP method to use for request
+keycloak-saml.identity-provider.single-logout.response-binding=HTTP method to use for response
+keycloak-saml.identity-provider.single-logout.post-binding-url=Endpoint URL for posting
+keycloak-saml.identity-provider.single-logout.redirect-binding-url=Endpoint URL for redirects
+keycloak-saml.identity-provider.key=Key definition for identity provider
\ No newline at end of file
diff --git a/saml/client-adapter/as7-eap6/subsystem/src/main/resources/schema/wildfly-keycloak-saml_1_1.xsd b/saml/client-adapter/as7-eap6/subsystem/src/main/resources/schema/wildfly-keycloak-saml_1_1.xsd
new file mode 100644
index 0000000..725104b
--- /dev/null
+++ b/saml/client-adapter/as7-eap6/subsystem/src/main/resources/schema/wildfly-keycloak-saml_1_1.xsd
@@ -0,0 +1,268 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
+           targetNamespace="urn:jboss:domain:keycloak-saml:1.1"
+           xmlns="urn:jboss:domain:keycloak-saml:1.1"
+           elementFormDefault="qualified"
+           attributeFormDefault="unqualified"
+           version="1.0">
+
+    <!-- The subsystem root element -->
+    <xs:element name="subsystem" type="subsystem-type"/>
+
+    <xs:complexType name="subsystem-type">
+        <xs:annotation>
+            <xs:documentation>
+                <![CDATA[
+                    The Keycloak SAML adapter subsystem, used to register deployments managed by Keycloak SAML adapter
+                ]]>
+            </xs:documentation>
+        </xs:annotation>
+        <xs:all>
+            <xs:element name="secure-deployment" minOccurs="0" type="secure-deployment-type"/>
+        </xs:all>
+    </xs:complexType>
+
+    <xs:complexType name="secure-deployment-type">
+        <xs:all>
+            <xs:element name="SP" minOccurs="1" maxOccurs="1" type="sp-type"/>
+        </xs:all>
+        <xs:attribute name="name" type="xs:string" use="required">
+            <xs:annotation>
+                <xs:documentation>The name of the realm.</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+    </xs:complexType>
+
+    <xs:complexType name="sp-type">
+        <xs:all>
+            <xs:element name="Keys" minOccurs="0" maxOccurs="1" type="keys-type"/>
+            <xs:element name="PrincipalNameMapping" minOccurs="0" maxOccurs="1" type="principal-name-mapping-type"/>
+            <xs:element name="RoleIdentifiers" minOccurs="0" maxOccurs="1" type="role-identifiers-type"/>
+            <xs:element name="IDP" minOccurs="1" maxOccurs="1" type="identity-provider-type"/>
+        </xs:all>
+        <xs:attribute name="entityID" type="xs:string" use="required">
+            <xs:annotation>
+                <xs:documentation>The entity ID for SAML service provider</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="sslPolicy" type="xs:string" use="required">
+            <xs:annotation>
+                <xs:documentation>The ssl policy</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="nameIDPolicyFormat" type="xs:string" use="required">
+            <xs:annotation>
+                <xs:documentation>Name ID policy format URN</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="logoutPage" type="xs:string" use="required">
+            <xs:annotation>
+                <xs:documentation>URI to a logout page</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="forceAuthentication" type="xs:boolean" use="required">
+            <xs:annotation>
+                <xs:documentation>Redirected unauthenticated request to a login page</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+    </xs:complexType>
+    <xs:complexType name="identity-provider-type">
+        <xs:all minOccurs="1" maxOccurs="1">
+            <xs:element name="SingleSignOnService" minOccurs="1" maxOccurs="1" type="single-signon-type"/>
+            <xs:element name="SingleLogoutService" minOccurs="0" maxOccurs="1" type="single-logout-type"/>
+            <xs:element name="Keys" minOccurs="0" maxOccurs="1" type="keys-type"/>
+        </xs:all>
+        <xs:attribute name="entityID" type="xs:string" use="required">
+            <xs:annotation>
+                <xs:documentation>The entity ID for SAML service provider</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="signaturesRequired" type="xs:boolean" use="required">
+            <xs:annotation>
+                <xs:documentation>Require signatures for single-sign-on and single-logout</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="signatureAlgorithm" type="xs:string" use="optional">
+            <xs:annotation>
+                <xs:documentation>Algorithm used for signatures</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="signatureCanonicalizationMethod" type="xs:string" use="optional">
+            <xs:annotation>
+                <xs:documentation>Canonicalization method used for signatures</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+    </xs:complexType>
+    <xs:complexType name="single-signon-type">
+        <xs:attribute name="signRequest" type="xs:boolean" use="optional">
+            <xs:annotation>
+                <xs:documentation>Sign the SSO requests</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="validateResponseSignature" type="xs:boolean" use="optional">
+            <xs:annotation>
+                <xs:documentation>Validate the SSO response signature</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="requestBinding" type="xs:string" use="optional">
+            <xs:annotation>
+                <xs:documentation>HTTP method to use for requests</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="responseBinding" type="xs:string" use="optional">
+            <xs:annotation>
+                <xs:documentation>HTTP method to use for response</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="bindingUrl" type="xs:string" use="optional">
+            <xs:annotation>
+                <xs:documentation>SSO endpoint URL</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+    </xs:complexType>
+    <xs:complexType name="single-logout-type">
+        <xs:attribute name="validateRequestSignature" type="xs:boolean" use="optional">
+            <xs:annotation>
+                <xs:documentation>Validate a single-logout request signature</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="validateResponseSignature" type="xs:boolean" use="optional">
+            <xs:annotation>
+                <xs:documentation>Validate a single-logout response signature</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="signRequest" type="xs:boolean" use="optional">
+            <xs:annotation>
+                <xs:documentation>Sign single-logout requests</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="signResponse" type="xs:boolean" use="optional">
+            <xs:annotation>
+                <xs:documentation>Sign single-logout responses</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="requestBinding" type="xs:string" use="optional">
+            <xs:annotation>
+                <xs:documentation>HTTP method to use for request</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="responseBinding" type="xs:string" use="optional">
+            <xs:annotation>
+                <xs:documentation>HTTP method to use for response</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="postBindingUrl" type="xs:string" use="optional">
+            <xs:annotation>
+                <xs:documentation>Endpoint URL for posting</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="redirectBindingUrl" type="xs:string" use="optional">
+            <xs:annotation>
+                <xs:documentation>Endpoint URL for redirects</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+    </xs:complexType>
+    <xs:complexType name="keys-type">
+        <xs:sequence>
+            <xs:element name="Key" minOccurs="1" maxOccurs="2" type="key-type"/>
+        </xs:sequence>
+    </xs:complexType>
+    <xs:complexType name="key-type">
+        <xs:all>
+            <xs:element name="KeyStore" minOccurs="0" maxOccurs="1" type="keystore-type"/>
+            <xs:element name="PrivateKeyPem" minOccurs="0" maxOccurs="1" type="xs:string"/>
+            <xs:element name="PublicKeyPem" minOccurs="0" maxOccurs="1" type="xs:string"/>
+            <xs:element name="CertificatePem" minOccurs="0" maxOccurs="1" type="xs:string"/>
+        </xs:all>
+        <xs:attribute name="signing" type="xs:boolean" use="optional">
+            <xs:annotation>
+                <xs:documentation>Key can be used for signing</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="encryption" type="xs:boolean" use="optional">
+            <xs:annotation>
+                <xs:documentation>Key can be used for encryption</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+    </xs:complexType>
+    <xs:complexType name="keystore-type">
+        <xs:sequence minOccurs="0" maxOccurs="1">
+            <xs:element name="PrivateKey" minOccurs="0" maxOccurs="1" type="privatekey-type"/>
+            <xs:element name="Certificate" minOccurs="0" maxOccurs="1" type="certificate-type"/>
+        </xs:sequence>
+        <xs:attribute name="file" type="xs:string" use="optional">
+            <xs:annotation>
+                <xs:documentation>Key store filesystem path</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="resource" type="xs:string" use="optional">
+            <xs:annotation>
+                <xs:documentation>Key store resource URI</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="password" type="xs:string" use="required">
+            <xs:annotation>
+                <xs:documentation>Key store password</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="type" type="xs:string" use="optional">
+            <xs:annotation>
+                <xs:documentation>Key store format</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="alias" type="xs:string" use="optional">
+            <xs:annotation>
+                <xs:documentation>Key alias</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+    </xs:complexType>
+
+    <xs:complexType name="privatekey-type">
+        <xs:attribute name="alias" type="xs:string" use="required">
+            <xs:annotation>
+                <xs:documentation>Private key alias</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="password" type="xs:string" use="required">
+            <xs:annotation>
+                <xs:documentation>Private key password</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+    </xs:complexType>
+
+    <xs:complexType name="certificate-type">
+        <xs:attribute name="alias" type="xs:string" use="required">
+            <xs:annotation>
+                <xs:documentation>Certificate alias</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+    </xs:complexType>
+
+    <xs:complexType name="principal-name-mapping-type">
+        <xs:attribute name="policy" type="xs:string" use="required">
+            <xs:annotation>
+                <xs:documentation>Principal name mapping policy. Possible values: FROM_NAME_ID</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="attribute" type="xs:string" use="optional">
+            <xs:annotation>
+                <xs:documentation>Name of the attribute to use for principal name mapping</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+    </xs:complexType>
+
+    <xs:complexType name="role-identifiers-type">
+        <xs:sequence minOccurs="0" maxOccurs="unbounded">
+            <xs:element name="Attribute" minOccurs="0" maxOccurs="unbounded" type="attribute-type"/>
+        </xs:sequence>
+    </xs:complexType>
+
+    <xs:complexType name="attribute-type">
+        <xs:attribute name="name" type="xs:string" use="required">
+            <xs:annotation>
+                <xs:documentation>Role attribute</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+    </xs:complexType>
+</xs:schema>
diff --git a/saml/client-adapter/as7-eap6/subsystem/src/test/resources/org/keycloak/subsystem/saml/as7/keycloak-saml-1.1.xml b/saml/client-adapter/as7-eap6/subsystem/src/test/resources/org/keycloak/subsystem/saml/as7/keycloak-saml-1.1.xml
new file mode 100644
index 0000000..19d7528
--- /dev/null
+++ b/saml/client-adapter/as7-eap6/subsystem/src/test/resources/org/keycloak/subsystem/saml/as7/keycloak-saml-1.1.xml
@@ -0,0 +1,49 @@
+<subsystem xmlns="urn:jboss:domain:keycloak-saml:1.1">
+    <secure-deployment name="my-app.war">
+        <SP entityID="http://localhost:8080/sales-post-enc/"
+            sslPolicy="EXTERNAL"
+            nameIDPolicyFormat="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified"
+            logoutPage="/logout.jsp"
+            forceAuthentication="false">
+
+            <Keys>
+                <Key encryption="true" signing="true">
+                    <PrivateKeyPem>my_key.pem</PrivateKeyPem>
+                    <PublicKeyPem>my_key.pub</PublicKeyPem>
+                    <CertificatePem>cert.cer</CertificatePem>
+                    <KeyStore resource="/WEB-INF/keystore.jks" password="store123">
+                        <PrivateKey alias="http://localhost:8080/sales-post-enc/" password="test123"/>
+                        <Certificate alias="http://localhost:8080/sales-post-enc/"/>
+                    </KeyStore>
+                </Key>
+            </Keys>
+            <PrincipalNameMapping policy="FROM_NAME_ID"/>
+            <RoleIdentifiers>
+                <Attribute name="Role"/>
+                <Attribute name="Role2"/>
+            </RoleIdentifiers>
+            <IDP entityID="idp">
+                <SingleSignOnService signRequest="true"
+                                     validateResponseSignature="true"
+                                     requestBinding="POST"
+                                     bindingUrl="http://localhost:8080/auth/realms/saml-demo/protocol/saml"/>
+                <SingleLogoutService
+                        validateRequestSignature="true"
+                        validateResponseSignature="true"
+                        signRequest="true"
+                        signResponse="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">
+                        <KeyStore resource="/WEB-INF/keystore.jks" password="store123">
+                            <Certificate alias="saml-demo"/>
+                        </KeyStore>
+                    </Key>
+                </Keys>
+            </IDP>
+        </SP>
+    </secure-deployment>
+</subsystem>
\ No newline at end of file
diff --git a/saml/client-adapter/core/src/main/java/org/keycloak/adapters/saml/AdapterConstants.java b/saml/client-adapter/core/src/main/java/org/keycloak/adapters/saml/AdapterConstants.java
index 280b5f8..e921d15 100755
--- a/saml/client-adapter/core/src/main/java/org/keycloak/adapters/saml/AdapterConstants.java
+++ b/saml/client-adapter/core/src/main/java/org/keycloak/adapters/saml/AdapterConstants.java
@@ -5,5 +5,5 @@ package org.keycloak.adapters.saml;
  * @version $Revision: 1 $
  */
 public class AdapterConstants {
-    public static final String AUTH_DATA_PARAM_NAME="org.keycloak.auth.deployment.data";
+    public static final String AUTH_DATA_PARAM_NAME="org.keycloak.saml.xml.adapterConfig";
 }
diff --git a/saml/client-adapter/undertow/src/main/java/org/keycloak/adapters/saml/undertow/SamlServletExtension.java b/saml/client-adapter/undertow/src/main/java/org/keycloak/adapters/saml/undertow/SamlServletExtension.java
index 615e4a6..ad22718 100755
--- a/saml/client-adapter/undertow/src/main/java/org/keycloak/adapters/saml/undertow/SamlServletExtension.java
+++ b/saml/client-adapter/undertow/src/main/java/org/keycloak/adapters/saml/undertow/SamlServletExtension.java
@@ -28,6 +28,7 @@ import io.undertow.servlet.api.DeploymentInfo;
 import io.undertow.servlet.api.LoginConfig;
 import io.undertow.servlet.api.ServletSessionConfig;
 import org.jboss.logging.Logger;
+import org.keycloak.adapters.saml.AdapterConstants;
 import org.keycloak.adapters.saml.DefaultSamlDeployment;
 import org.keycloak.adapters.saml.SamlConfigResolver;
 import org.keycloak.adapters.saml.SamlDeployment;
@@ -38,6 +39,7 @@ import org.keycloak.adapters.undertow.UndertowUserSessionManagement;
 import org.keycloak.saml.common.exceptions.ParsingException;
 
 import javax.servlet.ServletContext;
+import java.io.ByteArrayInputStream;
 import java.io.FileInputStream;
 import java.io.FileNotFoundException;
 import java.io.InputStream;
@@ -64,8 +66,16 @@ public class SamlServletExtension implements ServletExtension {
         return false;
     }
 
+    private static InputStream getXMLFromServletContext(ServletContext servletContext) {
+        String json = servletContext.getInitParameter(AdapterConstants.AUTH_DATA_PARAM_NAME);
+        if (json == null) {
+            return null;
+        }
+        return new ByteArrayInputStream(json.getBytes());
+    }
+
     private static InputStream getConfigInputStream(ServletContext context) {
-        InputStream is = null;
+        InputStream is = getXMLFromServletContext(context);
         if (is == null) {
             String path = context.getInitParameter("keycloak.config.file");
             if (path == null) {
diff --git a/saml/client-adapter/wildfly/pom.xml b/saml/client-adapter/wildfly/pom.xml
index 2b5eb25..d9014b6 100755
--- a/saml/client-adapter/wildfly/pom.xml
+++ b/saml/client-adapter/wildfly/pom.xml
@@ -15,6 +15,6 @@
 
     <modules>
         <module>wildfly-adapter</module>
-        <module>wildfly9-subsystem</module>
+        <module>wildfly-subsystem</module>
     </modules>
 </project>
diff --git a/saml/client-adapter/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/saml/extension/Configuration.java b/saml/client-adapter/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/saml/extension/Configuration.java
new file mode 100644
index 0000000..e364e2d
--- /dev/null
+++ b/saml/client-adapter/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/saml/extension/Configuration.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2015 Red Hat Inc. and/or its affiliates and other contributors
+ * as indicated by the @author tags. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package org.keycloak.subsystem.adapter.saml.extension;
+
+import org.jboss.dmr.ModelNode;
+import org.jboss.dmr.Property;
+
+/**
+ * @author <a href="mailto:mstrukel@redhat.com">Marko Strukelj</a>
+ */
+public class Configuration {
+
+    static Configuration INSTANCE = new Configuration();
+
+    private ModelNode config = new ModelNode();
+
+    private Configuration() {
+    }
+
+    void updateModel(ModelNode operation, ModelNode model) {
+        ModelNode node = config;
+        ModelNode addr = operation.get("address");
+        for (Property item : addr.asPropertyList()) {
+            node = getNodeForAddressElement(node, item);
+        }
+        node.set(model);
+    }
+
+    private ModelNode getNodeForAddressElement(ModelNode node, Property item) {
+        String key = item.getValue().asString();
+        ModelNode keymodel = node.get(item.getName());
+        return keymodel.get(key);
+    }
+
+    public ModelNode getSecureDeployment(String name) {
+        ModelNode secureDeployment = config.get("subsystem").get("keycloak-saml").get(Constants.Model.SECURE_DEPLOYMENT);
+        if (secureDeployment.hasDefined(name)) {
+            return secureDeployment.get(name);
+        }
+        return null;
+    }
+}
diff --git a/saml/client-adapter/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/saml/extension/Constants.java b/saml/client-adapter/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/saml/extension/Constants.java
new file mode 100644
index 0000000..9b89fb2
--- /dev/null
+++ b/saml/client-adapter/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/saml/extension/Constants.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright 2015 Red Hat Inc. and/or its affiliates and other contributors
+ * as indicated by the @author tags. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package org.keycloak.subsystem.adapter.saml.extension;
+
+
+/**
+ * @author <a href="mailto:mstrukel@redhat.com">Marko Strukelj</a>
+ */
+public class Constants {
+
+    static class Model {
+        static final String SECURE_DEPLOYMENT = "secure-deployment";
+        static final String SERVICE_PROVIDER = "service-provider";
+
+        static final String SSL_POLICY = "ssl-policy";
+        static final String NAME_ID_POLICY_FORMAT = "name-id-policy-format";
+        static final String LOGOUT_PAGE = "logout-page";
+        static final String FORCE_AUTHENTICATION = "force-authentication";
+        static final String ROLE_ATTRIBUTES = "role-attributes";
+        static final String SIGNING = "signing";
+        static final String ENCRYPTION = "encryption";
+        static final String KEY = "key";
+        static final String RESOURCE = "resource";
+        static final String PASSWORD = "password";
+
+        static final String PRIVATE_KEY_ALIAS = "private-key-alias";
+        static final String PRIVATE_KEY_PASSWORD = "private-key-password";
+        static final String CERTIFICATE_ALIAS = "certificate-alias";
+        static final String KEY_STORE = "key-store";
+        static final String SIGN_REQUEST = "sign-request";
+        static final String VALIDATE_RESPONSE_SIGNATURE = "validate-response-signature";
+        static final String REQUEST_BINDING = "request-binding";
+        static final String BINDING_URL = "binding-url";
+        static final String VALIDATE_REQUEST_SIGNATURE = "validate-request-signature";
+        static final String SIGN_RESPONSE = "sign-response";
+        static final String RESPONSE_BINDING = "response-binding";
+        static final String POST_BINDING_URL = "post-binding-url";
+        static final String REDIRECT_BINDING_URL = "redirect-binding-url";
+        static final String SINGLE_SIGN_ON = "single-sign-on";
+        static final String SINGLE_LOGOUT = "single-logout";
+        static final String IDENTITY_PROVIDER = "identity-provider";
+        static final String PRINCIPAL_NAME_MAPPING_POLICY = "principal-name-mapping-policy";
+        static final String PRINCIPAL_NAME_MAPPING_ATTRIBUTE_NAME = "principal-name-mapping-attribute-name";
+        static final String SIGNATURE_ALGORITHM = "signature-algorithm";
+        static final String SIGNATURE_CANONICALIZATION_METHOD = "signature-canonicalization-method";
+        static final String PRIVATE_KEY_PEM = "private-key-pem";
+        static final String PUBLIC_KEY_PEM = "public-key-pem";
+        static final String CERTIFICATE_PEM = "certificate-pem";
+        static final String TYPE = "type";
+        static final String ALIAS = "alias";
+        static final String FILE = "file";
+        static final String SIGNATURES_REQUIRED = "signatures-required";
+    }
+
+
+    static class XML {
+        static final String SECURE_DEPLOYMENT = "secure-deployment";
+        static final String SERVICE_PROVIDER = "SP";
+
+        static final String NAME = "name";
+        static final String ENTITY_ID = "entityID";
+        static final String SSL_POLICY = "sslPolicy";
+        static final String NAME_ID_POLICY_FORMAT = "nameIDPolicyFormat";
+        static final String LOGOUT_PAGE = "logoutPage";
+        static final String FORCE_AUTHENTICATION = "forceAuthentication";
+        static final String ROLE_IDENTIFIERS = "RoleIdentifiers";
+        static final String SIGNING = "signing";
+        static final String ENCRYPTION = "encryption";
+        static final String KEYS = "Keys";
+        static final String KEY = "Key";
+        static final String RESOURCE = "resource";
+        static final String PASSWORD = "password";
+        static final String KEY_STORE = "KeyStore";
+        static final String PRIVATE_KEY = "PrivateKey";
+        static final String CERTIFICATE = "Certificate";
+
+        static final String PRIVATE_KEY_ALIAS = "alias";
+        static final String PRIVATE_KEY_PASSWORD = "password";
+        static final String CERTIFICATE_ALIAS = "alias";
+        static final String SIGN_REQUEST = "signRequest";
+        static final String VALIDATE_RESPONSE_SIGNATURE = "validateResponseSignature";
+        static final String REQUEST_BINDING = "requestBinding";
+        static final String BINDING_URL = "bindingUrl";
+        static final String VALIDATE_REQUEST_SIGNATURE = "validateRequestSignature";
+        static final String SIGN_RESPONSE = "signResponse";
+        static final String RESPONSE_BINDING = "responseBinding";
+        static final String POST_BINDING_URL = "postBindingUrl";
+        static final String REDIRECT_BINDING_URL = "redirectBindingUrl";
+        static final String SINGLE_SIGN_ON = "SingleSignOnService";
+        static final String SINGLE_LOGOUT = "SingleLogoutService";
+        static final String IDENTITY_PROVIDER = "IDP";
+        static final String PRINCIPAL_NAME_MAPPING = "PrincipalNameMapping";
+        static final String PRINCIPAL_NAME_MAPPING_POLICY = "policy";
+        static final String PRINCIPAL_NAME_MAPPING_ATTRIBUTE_NAME = "attribute";
+        static final String ATTRIBUTE = "Attribute";
+        static final String SIGNATURE_ALGORITHM = "signatureAlgorithm";
+        static final String SIGNATURE_CANONICALIZATION_METHOD = "signatureCanonicalizationMethod";
+        static final String PRIVATE_KEY_PEM = "PrivateKeyPem";
+        static final String PUBLIC_KEY_PEM = "PublicKeyPem";
+        static final String CERTIFICATE_PEM = "CertificatePem";
+        static final String TYPE = "type";
+        static final String ALIAS = "alias";
+        static final String FILE = "file";
+        static final String SIGNATURES_REQUIRED = "signaturesRequired";
+    }
+}
diff --git a/saml/client-adapter/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/saml/extension/IdentityProviderAddHandler.java b/saml/client-adapter/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/saml/extension/IdentityProviderAddHandler.java
new file mode 100644
index 0000000..7648ba3
--- /dev/null
+++ b/saml/client-adapter/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/saml/extension/IdentityProviderAddHandler.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2015 Red Hat Inc. and/or its affiliates and other contributors
+ * as indicated by the @author tags. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package org.keycloak.subsystem.adapter.saml.extension;
+
+import org.jboss.as.controller.AbstractAddStepHandler;
+import org.jboss.as.controller.OperationContext;
+import org.jboss.as.controller.OperationFailedException;
+import org.jboss.dmr.ModelNode;
+
+/**
+ * @author <a href="mailto:mstrukel@redhat.com">Marko Strukelj</a>
+ */
+class IdentityProviderAddHandler extends AbstractAddStepHandler {
+
+    IdentityProviderAddHandler() {
+        super(IdentityProviderDefinition.ALL_ATTRIBUTES);
+    }
+
+    @Override
+    protected void performRuntime(OperationContext context, ModelNode operation, ModelNode model) throws OperationFailedException {
+        Configuration.INSTANCE.updateModel(operation, model);
+    }
+}
diff --git a/saml/client-adapter/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/saml/extension/IdentityProviderDefinition.java b/saml/client-adapter/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/saml/extension/IdentityProviderDefinition.java
new file mode 100644
index 0000000..1459f15
--- /dev/null
+++ b/saml/client-adapter/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/saml/extension/IdentityProviderDefinition.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2015 Red Hat Inc. and/or its affiliates and other contributors
+ * as indicated by the @author tags. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package org.keycloak.subsystem.adapter.saml.extension;
+
+import org.jboss.as.controller.AttributeDefinition;
+import org.jboss.as.controller.ObjectTypeAttributeDefinition;
+import org.jboss.as.controller.OperationStepHandler;
+import org.jboss.as.controller.PathElement;
+import org.jboss.as.controller.ReloadRequiredRemoveStepHandler;
+import org.jboss.as.controller.ReloadRequiredWriteAttributeHandler;
+import org.jboss.as.controller.SimpleAttributeDefinition;
+import org.jboss.as.controller.SimpleAttributeDefinitionBuilder;
+import org.jboss.as.controller.SimpleResourceDefinition;
+import org.jboss.as.controller.operations.common.GenericSubsystemDescribeHandler;
+import org.jboss.as.controller.registry.ManagementResourceRegistration;
+import org.jboss.dmr.ModelType;
+
+import java.util.HashMap;
+
+/**
+ * @author <a href="mailto:mstrukel@redhat.com">Marko Strukelj</a>
+ */
+public class IdentityProviderDefinition extends SimpleResourceDefinition {
+
+    static final SimpleAttributeDefinition SIGNATURES_REQUIRED =
+            new SimpleAttributeDefinitionBuilder(Constants.Model.SIGNATURES_REQUIRED, ModelType.BOOLEAN, true)
+                    .setXmlName(Constants.XML.SIGNATURES_REQUIRED)
+                    .build();
+
+    static final SimpleAttributeDefinition SIGNATURE_ALGORITHM =
+            new SimpleAttributeDefinitionBuilder(Constants.Model.SIGNATURE_ALGORITHM, ModelType.STRING, true)
+                    .setXmlName(Constants.XML.SIGNATURE_ALGORITHM)
+                    .build();
+
+    static final SimpleAttributeDefinition SIGNATURE_CANONICALIZATION_METHOD =
+            new SimpleAttributeDefinitionBuilder(Constants.Model.SIGNATURE_CANONICALIZATION_METHOD, ModelType.STRING, true)
+                    .setXmlName(Constants.XML.SIGNATURE_CANONICALIZATION_METHOD)
+                    .build();
+
+    static final ObjectTypeAttributeDefinition SINGLE_SIGN_ON =
+            ObjectTypeAttributeDefinition.Builder.of(Constants.Model.SINGLE_SIGN_ON,
+                    SingleSignOnDefinition.ATTRIBUTES)
+                    .setAllowNull(false)
+                    .build();
+
+    static final ObjectTypeAttributeDefinition SINGLE_LOGOUT =
+            ObjectTypeAttributeDefinition.Builder.of(Constants.Model.SINGLE_LOGOUT,
+                    SingleLogoutDefinition.ATTRIBUTES)
+                    .setAllowNull(false)
+                    .build();
+
+    static final SimpleAttributeDefinition[] ATTRIBUTES = {SIGNATURES_REQUIRED, SIGNATURE_ALGORITHM, SIGNATURE_CANONICALIZATION_METHOD};
+
+    static final SimpleAttributeDefinition[] ALL_ATTRIBUTES = {SIGNATURES_REQUIRED, SIGNATURE_ALGORITHM, SIGNATURE_CANONICALIZATION_METHOD, SINGLE_SIGN_ON, SINGLE_LOGOUT};
+
+    static final HashMap<String, SimpleAttributeDefinition> ATTRIBUTE_MAP = new HashMap<>();
+
+    static {
+        for (SimpleAttributeDefinition def : ALL_ATTRIBUTES) {
+            ATTRIBUTE_MAP.put(def.getXmlName(), def);
+        }
+    }
+
+    static final IdentityProviderDefinition INSTANCE = new IdentityProviderDefinition();
+
+    private IdentityProviderDefinition() {
+        super(PathElement.pathElement(Constants.Model.IDENTITY_PROVIDER),
+                KeycloakSamlExtension.getResourceDescriptionResolver(Constants.Model.IDENTITY_PROVIDER),
+                new IdentityProviderAddHandler(),
+                ReloadRequiredRemoveStepHandler.INSTANCE);
+    }
+
+    @Override
+    public void registerOperations(ManagementResourceRegistration resourceRegistration) {
+        super.registerOperations(resourceRegistration);
+        resourceRegistration.registerOperationHandler(GenericSubsystemDescribeHandler.DEFINITION, GenericSubsystemDescribeHandler.INSTANCE);
+    }
+
+    @Override
+    public void registerAttributes(ManagementResourceRegistration resourceRegistration) {
+        super.registerAttributes(resourceRegistration);
+
+        final OperationStepHandler writeHandler = new ReloadRequiredWriteAttributeHandler(ALL_ATTRIBUTES);
+        for (AttributeDefinition attribute : ALL_ATTRIBUTES) {
+            resourceRegistration.registerReadWriteAttribute(attribute, null, writeHandler);
+        }
+    }
+
+    static SimpleAttributeDefinition lookup(String xmlName) {
+        return ATTRIBUTE_MAP.get(xmlName);
+    }
+}
\ No newline at end of file
diff --git a/saml/client-adapter/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/saml/extension/KeyAddHandler.java b/saml/client-adapter/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/saml/extension/KeyAddHandler.java
new file mode 100644
index 0000000..1799290
--- /dev/null
+++ b/saml/client-adapter/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/saml/extension/KeyAddHandler.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2015 Red Hat Inc. and/or its affiliates and other contributors
+ * as indicated by the @author tags. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package org.keycloak.subsystem.adapter.saml.extension;
+
+import org.jboss.as.controller.AbstractAddStepHandler;
+import org.jboss.as.controller.OperationContext;
+import org.jboss.as.controller.OperationFailedException;
+import org.jboss.dmr.ModelNode;
+
+/**
+ * @author <a href="mailto:mstrukel@redhat.com">Marko Strukelj</a>
+ */
+class KeyAddHandler extends AbstractAddStepHandler {
+
+    KeyAddHandler() {
+        super(KeyDefinition.ALL_ATTRIBUTES);
+    }
+
+    @Override
+    protected void performRuntime(OperationContext context, ModelNode operation, ModelNode model) throws OperationFailedException {
+        Configuration.INSTANCE.updateModel(operation, model);
+    }
+}
diff --git a/saml/client-adapter/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/saml/extension/KeycloakSubsystemParser.java b/saml/client-adapter/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/saml/extension/KeycloakSubsystemParser.java
new file mode 100755
index 0000000..8b20565
--- /dev/null
+++ b/saml/client-adapter/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/saml/extension/KeycloakSubsystemParser.java
@@ -0,0 +1,569 @@
+/*
+ * Copyright 2015 Red Hat Inc. and/or its affiliates and other contributors
+ * as indicated by the @author tags. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package org.keycloak.subsystem.adapter.saml.extension;
+
+import org.jboss.as.controller.PathAddress;
+import org.jboss.as.controller.PathElement;
+import org.jboss.as.controller.SimpleAttributeDefinition;
+import org.jboss.as.controller.descriptions.ModelDescriptionConstants;
+import org.jboss.as.controller.operations.common.Util;
+import org.jboss.as.controller.parsing.ParseUtils;
+import org.jboss.as.controller.persistence.SubsystemMarshallingContext;
+import org.jboss.dmr.ModelNode;
+import org.jboss.dmr.Property;
+import org.jboss.staxmapper.XMLElementReader;
+import org.jboss.staxmapper.XMLElementWriter;
+import org.jboss.staxmapper.XMLExtendedStreamReader;
+import org.jboss.staxmapper.XMLExtendedStreamWriter;
+
+import javax.xml.stream.XMLStreamConstants;
+import javax.xml.stream.XMLStreamException;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * The subsystem parser, which uses stax to read and write to and from xml
+ */
+class KeycloakSubsystemParser implements XMLStreamConstants, XMLElementReader<List<ModelNode>>, XMLElementWriter<SubsystemMarshallingContext> {
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void readElement(final XMLExtendedStreamReader reader, final List<ModelNode> list) throws XMLStreamException {
+        // Require no attributes
+        ParseUtils.requireNoAttributes(reader);
+        ModelNode addKeycloakSub = Util.createAddOperation(PathAddress.pathAddress(KeycloakSamlExtension.PATH_SUBSYSTEM));
+        list.add(addKeycloakSub);
+
+        while (reader.hasNext() && nextTag(reader) != END_ELEMENT) {
+            if (reader.getLocalName().equals(Constants.XML.SECURE_DEPLOYMENT)) {
+                readSecureDeployment(reader, list);
+            } else {
+                throw ParseUtils.unexpectedElement(reader);
+            }
+        }
+    }
+
+    // used for debugging
+    private int nextTag(XMLExtendedStreamReader reader) throws XMLStreamException {
+        return reader.nextTag();
+    }
+
+    void readSecureDeployment(XMLExtendedStreamReader reader, List<ModelNode> list) throws XMLStreamException {
+        String name = readRequiredAttribute(reader, Constants.XML.NAME);
+
+        PathAddress addr = PathAddress.pathAddress(
+                PathElement.pathElement(ModelDescriptionConstants.SUBSYSTEM, KeycloakSamlExtension.SUBSYSTEM_NAME),
+                PathElement.pathElement(Constants.Model.SECURE_DEPLOYMENT, name));
+        ModelNode addSecureDeployment = Util.createAddOperation(addr);
+        list.add(addSecureDeployment);
+
+        while (reader.hasNext() && nextTag(reader) != END_ELEMENT) {
+            String tagName = reader.getLocalName();
+            if (tagName.equals(Constants.XML.SERVICE_PROVIDER)) {
+                readServiceProvider(reader, list, addr);
+            } else {
+                throw ParseUtils.unexpectedElement(reader);
+            }
+        }
+    }
+
+    void readServiceProvider(XMLExtendedStreamReader reader, List<ModelNode> list, PathAddress parentAddr) throws XMLStreamException {
+        String entityId = readRequiredAttribute(reader, Constants.XML.ENTITY_ID);
+
+        PathAddress addr = PathAddress.pathAddress(parentAddr,
+                PathElement.pathElement(Constants.Model.SERVICE_PROVIDER, entityId));
+        ModelNode addServiceProvider = Util.createAddOperation(addr);
+        list.add(addServiceProvider);
+
+        for (int i = 0; i < reader.getAttributeCount(); i++) {
+            String name = reader.getAttributeLocalName(i);
+            if (Constants.XML.ENTITY_ID.equals(name)) {
+                continue;
+            }
+
+            String value = reader.getAttributeValue(i);
+
+            SimpleAttributeDefinition attr = ServiceProviderDefinition.lookup(name);
+            if (attr == null) {
+                throw ParseUtils.unexpectedAttribute(reader, i);
+            }
+            attr.parseAndSetParameter(value, addServiceProvider, reader);
+        }
+
+        while (reader.hasNext() && nextTag(reader) != END_ELEMENT) {
+            String tagName = reader.getLocalName();
+
+            if (Constants.XML.KEYS.equals(tagName)) {
+                readKeys(list, reader, addr);
+            } else if (Constants.XML.PRINCIPAL_NAME_MAPPING.equals(tagName)) {
+                readPrincipalNameMapping(addServiceProvider, reader);
+            } else if (Constants.XML.ROLE_IDENTIFIERS.equals(tagName)) {
+                readRoleIdentifiers(addServiceProvider, reader);
+            } else if (Constants.XML.IDENTITY_PROVIDER.equals(tagName)) {
+                readIdentityProvider(list, reader, addr);
+            } else {
+                throw ParseUtils.unexpectedElement(reader);
+            }
+        }
+    }
+
+    void readIdentityProvider(List<ModelNode> list, XMLExtendedStreamReader reader, PathAddress parentAddr) throws XMLStreamException {
+        String entityId = readRequiredAttribute(reader, Constants.XML.ENTITY_ID);
+
+        PathAddress addr = PathAddress.pathAddress(parentAddr,
+                PathElement.pathElement(Constants.Model.IDENTITY_PROVIDER, entityId));
+        ModelNode addIdentityProvider = Util.createAddOperation(addr);
+        list.add(addIdentityProvider);
+
+        for (int i = 0; i < reader.getAttributeCount(); i++) {
+            String name = reader.getAttributeLocalName(i);
+            String value = reader.getAttributeValue(i);
+
+            if (Constants.XML.ENTITY_ID.equals(name)
+                    // don't break if encountering this noop attr from client-adapter/core keycloak_saml_adapter_1_6.xsd
+                    || "encryption".equals(name)) {
+                continue;
+            }
+            SimpleAttributeDefinition attr = IdentityProviderDefinition.lookup(name);
+            if (attr == null) {
+                throw ParseUtils.unexpectedAttribute(reader, i);
+            }
+            attr.parseAndSetParameter(value, addIdentityProvider, reader);
+        }
+
+        while (reader.hasNext() && nextTag(reader) != END_ELEMENT) {
+            String tagName = reader.getLocalName();
+
+            if (Constants.XML.SINGLE_SIGN_ON.equals(tagName)) {
+                readSingleSignOn(addIdentityProvider, reader);
+            } else if (Constants.XML.SINGLE_LOGOUT.equals(tagName)) {
+                readSingleLogout(addIdentityProvider, reader);
+            } else if (Constants.XML.KEYS.equals(tagName)) {
+                readKeys(list, reader, addr);
+            } else {
+                throw ParseUtils.unexpectedElement(reader);
+            }
+        }
+    }
+
+    void readSingleSignOn(ModelNode addIdentityProvider, XMLExtendedStreamReader reader) throws XMLStreamException {
+        ModelNode sso = addIdentityProvider.get(Constants.Model.SINGLE_SIGN_ON);
+        for (int i = 0; i < reader.getAttributeCount(); i++) {
+            String name = reader.getAttributeLocalName(i);
+            String value = reader.getAttributeValue(i);
+
+            SimpleAttributeDefinition attr = SingleSignOnDefinition.lookup(name);
+            if (attr == null) {
+                throw ParseUtils.unexpectedAttribute(reader, i);
+            }
+            attr.parseAndSetParameter(value, sso, reader);
+        }
+        ParseUtils.requireNoContent(reader);
+    }
+
+    void readSingleLogout(ModelNode addIdentityProvider, XMLExtendedStreamReader reader) throws XMLStreamException {
+        ModelNode slo = addIdentityProvider.get(Constants.Model.SINGLE_LOGOUT);
+        for (int i = 0; i < reader.getAttributeCount(); i++) {
+            String name = reader.getAttributeLocalName(i);
+            String value = reader.getAttributeValue(i);
+
+            SimpleAttributeDefinition attr = SingleLogoutDefinition.lookup(name);
+            if (attr == null) {
+                throw ParseUtils.unexpectedAttribute(reader, i);
+            }
+            attr.parseAndSetParameter(value, slo, reader);
+        }
+        ParseUtils.requireNoContent(reader);
+    }
+
+    void readKeys(List<ModelNode> list, XMLExtendedStreamReader reader, PathAddress parentAddr) throws XMLStreamException {
+        ParseUtils.requireNoAttributes(reader);
+        List<ModelNode> keyList = new LinkedList<>();
+        while (reader.hasNext() && nextTag(reader) != END_ELEMENT) {
+            String tagName = reader.getLocalName();
+            if (!Constants.XML.KEY.equals(tagName)) {
+                throw ParseUtils.unexpectedElement(reader);
+            }
+            readKey(keyList, reader, parentAddr);
+        }
+        list.addAll(keyList);
+    }
+
+    void readKey(List<ModelNode> list, XMLExtendedStreamReader reader, PathAddress parentAddr) throws XMLStreamException {
+        PathAddress addr = PathAddress.pathAddress(parentAddr,
+                PathElement.pathElement(Constants.Model.KEY, "key-" + list.size()));
+        ModelNode addKey = Util.createAddOperation(addr);
+        list.add(addKey);
+
+        for (int i = 0; i < reader.getAttributeCount(); i++) {
+            String name = reader.getAttributeLocalName(i);
+            String value = reader.getAttributeValue(i);
+
+            SimpleAttributeDefinition attr = KeyDefinition.lookup(name);
+            if (attr == null) {
+                throw ParseUtils.unexpectedAttribute(reader, i);
+            }
+            attr.parseAndSetParameter(value, addKey, reader);
+        }
+
+        while (reader.hasNext() && nextTag(reader) != END_ELEMENT) {
+            String tagName = reader.getLocalName();
+
+            if (Constants.XML.KEY_STORE.equals(tagName)) {
+                readKeyStore(addKey, reader);
+            } else if (Constants.XML.PRIVATE_KEY_PEM.equals(tagName)
+                    || Constants.XML.PUBLIC_KEY_PEM.equals(tagName)
+                    || Constants.XML.CERTIFICATE_PEM.equals(tagName)) {
+
+                readNoAttrElementContent(KeyDefinition.lookupElement(tagName), addKey, reader);
+            } else {
+                throw ParseUtils.unexpectedElement(reader);
+            }
+        }
+    }
+
+    void readNoAttrElementContent(SimpleAttributeDefinition attr, ModelNode model, XMLExtendedStreamReader reader) throws XMLStreamException {
+        ParseUtils.requireNoAttributes(reader);
+        String value = reader.getElementText();
+        attr.parseAndSetParameter(value, model, reader);
+    }
+
+    void readKeyStore(ModelNode addKey, XMLExtendedStreamReader reader) throws XMLStreamException {
+        ModelNode addKeyStore = addKey.get(Constants.Model.KEY_STORE);
+
+        for (int i = 0; i < reader.getAttributeCount(); i++) {
+            String name = reader.getAttributeLocalName(i);
+            String value = reader.getAttributeValue(i);
+
+            SimpleAttributeDefinition attr = KeyStoreDefinition.lookup(name);
+            if (attr == null) {
+                throw ParseUtils.unexpectedAttribute(reader, i);
+            }
+            attr.parseAndSetParameter(value, addKeyStore, reader);
+        }
+
+        if (!addKeyStore.hasDefined(Constants.Model.FILE) && !addKeyStore.hasDefined(Constants.Model.RESOURCE)) {
+            throw new XMLStreamException("KeyStore element must have 'file' or 'resource' attribute set", reader.getLocation());
+        }
+        if (!addKeyStore.hasDefined(Constants.Model.PASSWORD)) {
+            throw ParseUtils.missingRequired(reader, Constants.XML.PASSWORD);
+        }
+
+        while (reader.hasNext() && nextTag(reader) != END_ELEMENT) {
+            String tagName = reader.getLocalName();
+            if (Constants.XML.PRIVATE_KEY.equals(tagName)) {
+                readPrivateKey(reader, addKeyStore);
+            } else if (Constants.XML.CERTIFICATE.equals(tagName)) {
+                readCertificate(reader, addKeyStore);
+            } else {
+                throw ParseUtils.unexpectedElement(reader);
+            }
+        }
+    }
+
+
+    void readPrivateKey(XMLExtendedStreamReader reader, ModelNode addKeyStore) throws XMLStreamException {
+        for (int i = 0; i < reader.getAttributeCount(); i++) {
+            String name = reader.getAttributeLocalName(i);
+            String value = reader.getAttributeValue(i);
+
+            SimpleAttributeDefinition attr = KeyStorePrivateKeyDefinition.lookup(name);
+            if (attr == null) {
+                throw ParseUtils.unexpectedAttribute(reader, i);
+            }
+            attr.parseAndSetParameter(value, addKeyStore, reader);
+        }
+
+        if (!addKeyStore.hasDefined(Constants.Model.PRIVATE_KEY_ALIAS)) {
+            throw ParseUtils.missingRequired(reader, Constants.XML.PRIVATE_KEY_ALIAS);
+        }
+        if (!addKeyStore.hasDefined(Constants.Model.PRIVATE_KEY_PASSWORD)) {
+            throw ParseUtils.missingRequired(reader, Constants.XML.PRIVATE_KEY_PASSWORD);
+        }
+
+        ParseUtils.requireNoContent(reader);
+    }
+
+    void readCertificate(XMLExtendedStreamReader reader, ModelNode addKeyStore) throws XMLStreamException {
+        for (int i = 0; i < reader.getAttributeCount(); i++) {
+            String name = reader.getAttributeLocalName(i);
+            String value = reader.getAttributeValue(i);
+
+            SimpleAttributeDefinition attr = KeyStoreCertificateDefinition.lookup(name);
+            if (attr == null) {
+                throw ParseUtils.unexpectedAttribute(reader, i);
+            }
+            attr.parseAndSetParameter(value, addKeyStore, reader);
+        }
+
+        if (!addKeyStore.hasDefined(Constants.Model.CERTIFICATE_ALIAS)) {
+            throw ParseUtils.missingRequired(reader, Constants.XML.CERTIFICATE_ALIAS);
+        }
+
+        ParseUtils.requireNoContent(reader);
+    }
+
+    void readRoleIdentifiers(ModelNode addServiceProvider, XMLExtendedStreamReader reader) throws XMLStreamException {
+        ParseUtils.requireNoAttributes(reader);
+
+        while (reader.hasNext() && nextTag(reader) != END_ELEMENT) {
+            String tagName = reader.getLocalName();
+
+            if (!Constants.XML.ATTRIBUTE.equals(tagName)) {
+                throw ParseUtils.unexpectedElement(reader);
+            }
+
+            ParseUtils.requireSingleAttribute(reader, Constants.XML.NAME);
+            String name = ParseUtils.readStringAttributeElement(reader, Constants.XML.NAME);
+
+            ServiceProviderDefinition.ROLE_ATTRIBUTES.parseAndAddParameterElement(name, addServiceProvider, reader);
+        }
+    }
+
+    void readPrincipalNameMapping(ModelNode addServiceProvider, XMLExtendedStreamReader reader) throws XMLStreamException {
+
+        boolean policySet = false;
+
+        for (int i = 0; i < reader.getAttributeCount(); i++) {
+            String name = reader.getAttributeLocalName(i);
+            String value = reader.getAttributeValue(i);
+
+            if (Constants.XML.PRINCIPAL_NAME_MAPPING_POLICY.equals(name)) {
+                policySet = true;
+                ServiceProviderDefinition.PRINCIPAL_NAME_MAPPING_POLICY.parseAndSetParameter(value, addServiceProvider, reader);
+            } else if (Constants.XML.PRINCIPAL_NAME_MAPPING_ATTRIBUTE_NAME.equals(name)) {
+                ServiceProviderDefinition.PRINCIPAL_NAME_MAPPING_ATTRIBUTE_NAME.parseAndSetParameter(value, addServiceProvider, reader);
+            } else {
+                throw ParseUtils.unexpectedAttribute(reader, i);
+            }
+        }
+
+        if (!policySet) {
+            throw ParseUtils.missingRequired(reader, Constants.XML.PRINCIPAL_NAME_MAPPING_POLICY);
+        }
+        ParseUtils.requireNoContent(reader);
+    }
+
+    /**
+     * Read an attribute, and throw exception if attribute is not present
+     */
+    String readRequiredAttribute(XMLExtendedStreamReader reader, String attrName) throws XMLStreamException {
+        String value = null;
+        for (int i = 0; i < reader.getAttributeCount(); i++) {
+            String attr = reader.getAttributeLocalName(i);
+            if (attr.equals(attrName)) {
+                value = reader.getAttributeValue(i);
+                break;
+            }
+        }
+        if (value == null) {
+            throw ParseUtils.missingRequired(reader, Collections.singleton(attrName));
+        }
+        return value;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void writeContent(final XMLExtendedStreamWriter writer, final SubsystemMarshallingContext context) throws XMLStreamException {
+        context.startSubsystemElement(KeycloakSamlExtension.NAMESPACE, false);
+        writeSecureDeployment(writer, context.getModelNode());
+        writer.writeEndElement();
+    }
+
+    public void writeSecureDeployment(XMLExtendedStreamWriter writer, ModelNode model) throws XMLStreamException {
+        if (!model.get(Constants.Model.SECURE_DEPLOYMENT).isDefined()) {
+            return;
+        }
+
+        for (Property sp : model.get(Constants.Model.SECURE_DEPLOYMENT).asPropertyList()) {
+            writer.writeStartElement(Constants.XML.SECURE_DEPLOYMENT);
+            writer.writeAttribute(Constants.XML.NAME, sp.getName());
+
+            writeSps(writer, sp.getValue());
+            writer.writeEndElement();
+        }
+    }
+
+    void writeSps(final XMLExtendedStreamWriter writer, final ModelNode model) throws XMLStreamException {
+        if (!model.isDefined()) {
+            return;
+        }
+        for (Property sp : model.get(Constants.Model.SERVICE_PROVIDER).asPropertyList()) {
+            writer.writeStartElement(Constants.XML.SERVICE_PROVIDER);
+            writer.writeAttribute(Constants.XML.ENTITY_ID, sp.getName());
+            ModelNode spAttributes = sp.getValue();
+            for (SimpleAttributeDefinition attr : ServiceProviderDefinition.ATTRIBUTES) {
+                attr.getAttributeMarshaller().marshallAsAttribute(attr, spAttributes, false, writer);
+            }
+            writeKeys(writer, spAttributes.get(Constants.Model.KEY));
+            writePrincipalNameMapping(writer, spAttributes);
+            writeRoleIdentifiers(writer, spAttributes);
+            writeIdentityProvider(writer, spAttributes.get(Constants.Model.IDENTITY_PROVIDER));
+
+            writer.writeEndElement();
+        }
+    }
+
+    void writeIdentityProvider(XMLExtendedStreamWriter writer, ModelNode model) throws XMLStreamException {
+        if (!model.isDefined()) {
+            return;
+        }
+
+        for (Property idp : model.asPropertyList()) {
+            writer.writeStartElement(Constants.XML.IDENTITY_PROVIDER);
+            writer.writeAttribute(Constants.XML.ENTITY_ID, idp.getName());
+
+            ModelNode idpAttributes = idp.getValue();
+            for (SimpleAttributeDefinition attr : IdentityProviderDefinition.ATTRIBUTES) {
+                attr.getAttributeMarshaller().marshallAsAttribute(attr, idpAttributes, false, writer);
+            }
+
+            writeSingleSignOn(writer, idpAttributes.get(Constants.Model.SINGLE_SIGN_ON));
+            writeSingleLogout(writer, idpAttributes.get(Constants.Model.SINGLE_LOGOUT));
+            writeKeys(writer, idpAttributes.get(Constants.Model.KEY));
+        }
+        writer.writeEndElement();
+    }
+
+    void writeSingleSignOn(XMLExtendedStreamWriter writer, ModelNode model) throws XMLStreamException {
+        if (!model.isDefined()) {
+            return;
+        }
+        writer.writeStartElement(Constants.XML.SINGLE_SIGN_ON);
+        for (SimpleAttributeDefinition attr : SingleSignOnDefinition.ATTRIBUTES) {
+            attr.getAttributeMarshaller().marshallAsAttribute(attr, model, false, writer);
+        }
+        writer.writeEndElement();
+    }
+
+    void writeSingleLogout(XMLExtendedStreamWriter writer, ModelNode model) throws XMLStreamException {
+        if (!model.isDefined()) {
+            return;
+        }
+        writer.writeStartElement(Constants.XML.SINGLE_LOGOUT);
+        for (SimpleAttributeDefinition attr : SingleLogoutDefinition.ATTRIBUTES) {
+            attr.getAttributeMarshaller().marshallAsAttribute(attr, model, false, writer);
+        }
+        writer.writeEndElement();
+    }
+
+    void writeKeys(XMLExtendedStreamWriter writer, ModelNode model) throws XMLStreamException {
+        if (!model.isDefined()) {
+            return;
+        }
+        boolean contains = false;
+        for (Property key : model.asPropertyList()) {
+            if (!contains) {
+                writer.writeStartElement(Constants.XML.KEYS);
+                contains = true;
+            }
+            writer.writeStartElement(Constants.XML.KEY);
+
+            ModelNode keyAttributes = key.getValue();
+            for (SimpleAttributeDefinition attr : KeyDefinition.ATTRIBUTES) {
+                attr.getAttributeMarshaller().marshallAsAttribute(attr, keyAttributes, false, writer);
+            }
+            for (SimpleAttributeDefinition attr : KeyDefinition.ELEMENTS) {
+                attr.getAttributeMarshaller().marshallAsElement(attr, keyAttributes, false, writer);
+            }
+            writeKeyStore(writer, keyAttributes.get(Constants.Model.KEY_STORE));
+
+            writer.writeEndElement();
+        }
+        if (contains) {
+            writer.writeEndElement();
+        }
+    }
+
+    void writeKeyStore(XMLExtendedStreamWriter writer, ModelNode model) throws XMLStreamException {
+        if (!model.isDefined()) {
+            return;
+        }
+        writer.writeStartElement(Constants.XML.KEY_STORE);
+        for (SimpleAttributeDefinition attr : KeyStoreDefinition.ATTRIBUTES) {
+            attr.getAttributeMarshaller().marshallAsAttribute(attr, model, false, writer);
+        }
+        writePrivateKey(writer, model);
+        writeCertificate(writer, model);
+        writer.writeEndElement();
+    }
+
+    void writeCertificate(XMLExtendedStreamWriter writer, ModelNode model) throws XMLStreamException {
+        ModelNode value = model.get(Constants.Model.CERTIFICATE_ALIAS);
+        if (!value.isDefined()) {
+            return;
+        }
+        writer.writeStartElement(Constants.XML.CERTIFICATE);
+        SimpleAttributeDefinition attr = KeyStoreCertificateDefinition.CERTIFICATE_ALIAS;
+        attr.getAttributeMarshaller().marshallAsAttribute(attr, model, false, writer);
+        writer.writeEndElement();
+    }
+
+    void writePrivateKey(XMLExtendedStreamWriter writer, ModelNode model) throws XMLStreamException {
+        ModelNode pk_alias = model.get(Constants.Model.PRIVATE_KEY_ALIAS);
+        ModelNode pk_password = model.get(Constants.Model.PRIVATE_KEY_PASSWORD);
+
+        if (!pk_alias.isDefined() && !pk_password.isDefined()) {
+            return;
+        }
+        writer.writeStartElement(Constants.XML.PRIVATE_KEY);
+        for (SimpleAttributeDefinition attr : KeyStorePrivateKeyDefinition.ATTRIBUTES) {
+            attr.getAttributeMarshaller().marshallAsAttribute(attr, model, false, writer);
+        }
+        writer.writeEndElement();
+    }
+
+    void writeRoleIdentifiers(XMLExtendedStreamWriter writer, ModelNode model) throws XMLStreamException {
+        ModelNode value = model.get(Constants.Model.ROLE_ATTRIBUTES);
+        if (!value.isDefined()) {
+            return;
+        }
+
+        List<ModelNode> items = value.asList();
+        if (items.size() == 0) {
+            return;
+        }
+
+        writer.writeStartElement(Constants.XML.ROLE_IDENTIFIERS);
+        for (ModelNode item : items) {
+            writer.writeStartElement(Constants.XML.ATTRIBUTE);
+            writer.writeAttribute("name", item.asString());
+            writer.writeEndElement();
+        }
+        writer.writeEndElement();
+    }
+
+    void writePrincipalNameMapping(XMLExtendedStreamWriter writer, ModelNode model) throws XMLStreamException {
+        writer.writeStartElement(Constants.XML.PRINCIPAL_NAME_MAPPING);
+        ModelNode value = model.get(Constants.Model.PRINCIPAL_NAME_MAPPING_POLICY);
+        if (value.isDefined()) {
+            writer.writeAttribute(Constants.XML.PRINCIPAL_NAME_MAPPING_POLICY, value.asString());
+        }
+        value = model.get(Constants.Model.PRINCIPAL_NAME_MAPPING_ATTRIBUTE_NAME);
+        if (value.isDefined()) {
+            writer.writeAttribute(Constants.XML.PRINCIPAL_NAME_MAPPING_ATTRIBUTE_NAME, value.asString());
+        }
+        writer.writeEndElement();
+    }
+}
diff --git a/saml/client-adapter/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/saml/extension/KeyDefinition.java b/saml/client-adapter/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/saml/extension/KeyDefinition.java
new file mode 100644
index 0000000..7d19994
--- /dev/null
+++ b/saml/client-adapter/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/saml/extension/KeyDefinition.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright 2015 Red Hat Inc. and/or its affiliates and other contributors
+ * as indicated by the @author tags. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package org.keycloak.subsystem.adapter.saml.extension;
+
+import org.jboss.as.controller.AttributeDefinition;
+import org.jboss.as.controller.ObjectTypeAttributeDefinition;
+import org.jboss.as.controller.OperationStepHandler;
+import org.jboss.as.controller.PathElement;
+import org.jboss.as.controller.ReloadRequiredRemoveStepHandler;
+import org.jboss.as.controller.ReloadRequiredWriteAttributeHandler;
+import org.jboss.as.controller.SimpleAttributeDefinition;
+import org.jboss.as.controller.SimpleAttributeDefinitionBuilder;
+import org.jboss.as.controller.SimpleResourceDefinition;
+import org.jboss.as.controller.operations.common.GenericSubsystemDescribeHandler;
+import org.jboss.as.controller.registry.ManagementResourceRegistration;
+import org.jboss.dmr.ModelType;
+
+import java.util.HashMap;
+
+/**
+ * @author <a href="mailto:mstrukel@redhat.com">Marko Strukelj</a>
+ */
+public class KeyDefinition extends SimpleResourceDefinition {
+
+    static final SimpleAttributeDefinition SIGNING =
+            new SimpleAttributeDefinitionBuilder(Constants.Model.SIGNING, ModelType.BOOLEAN, true)
+                    .setXmlName(Constants.XML.SIGNING)
+                    .build();
+
+    static final SimpleAttributeDefinition ENCRYPTION =
+            new SimpleAttributeDefinitionBuilder(Constants.Model.ENCRYPTION, ModelType.BOOLEAN, true)
+                    .setXmlName(Constants.XML.ENCRYPTION)
+                    .build();
+
+    static final SimpleAttributeDefinition PRIVATE_KEY_PEM =
+            new SimpleAttributeDefinitionBuilder(Constants.Model.PRIVATE_KEY_PEM, ModelType.STRING, true)
+                    .setXmlName(Constants.XML.PRIVATE_KEY_PEM)
+                    .build();
+
+    static final SimpleAttributeDefinition PUBLIC_KEY_PEM =
+            new SimpleAttributeDefinitionBuilder(Constants.Model.PUBLIC_KEY_PEM, ModelType.STRING, true)
+                    .setXmlName(Constants.XML.PUBLIC_KEY_PEM)
+                    .build();
+
+    static final SimpleAttributeDefinition CERTIFICATE_PEM =
+            new SimpleAttributeDefinitionBuilder(Constants.Model.CERTIFICATE_PEM, ModelType.STRING, true)
+                    .setXmlName(Constants.XML.CERTIFICATE_PEM)
+                    .build();
+
+    static final ObjectTypeAttributeDefinition KEY_STORE =
+            ObjectTypeAttributeDefinition.Builder.of(Constants.Model.KEY_STORE,
+                    KeyStoreDefinition.ALL_ATTRIBUTES)
+                    .setAllowNull(false)
+                    .build();
+
+    static final SimpleAttributeDefinition[] ATTRIBUTES = {SIGNING, ENCRYPTION};
+    static final SimpleAttributeDefinition[] ELEMENTS = {PRIVATE_KEY_PEM, PUBLIC_KEY_PEM, CERTIFICATE_PEM};
+    static final AttributeDefinition[] ALL_ATTRIBUTES = {SIGNING, ENCRYPTION, PRIVATE_KEY_PEM, PUBLIC_KEY_PEM, CERTIFICATE_PEM, KEY_STORE};
+
+    static final HashMap<String, SimpleAttributeDefinition> ATTRIBUTE_MAP = new HashMap<>();
+
+    static {
+        for (SimpleAttributeDefinition def : ATTRIBUTES) {
+            ATTRIBUTE_MAP.put(def.getXmlName(), def);
+        }
+    }
+
+    static final HashMap<String, SimpleAttributeDefinition> ELEMENT_MAP = new HashMap<>();
+
+    static {
+        for (SimpleAttributeDefinition def : ELEMENTS) {
+            ELEMENT_MAP.put(def.getXmlName(), def);
+        }
+    }
+
+    static final KeyDefinition INSTANCE = new KeyDefinition();
+
+    private KeyDefinition() {
+        super(PathElement.pathElement(Constants.Model.KEY),
+                KeycloakSamlExtension.getResourceDescriptionResolver(Constants.Model.KEY),
+                new KeyAddHandler(),
+                ReloadRequiredRemoveStepHandler.INSTANCE);
+    }
+
+    @Override
+    public void registerOperations(ManagementResourceRegistration resourceRegistration) {
+        super.registerOperations(resourceRegistration);
+        resourceRegistration.registerOperationHandler(GenericSubsystemDescribeHandler.DEFINITION, GenericSubsystemDescribeHandler.INSTANCE);
+    }
+
+    @Override
+    public void registerAttributes(ManagementResourceRegistration resourceRegistration) {
+        super.registerAttributes(resourceRegistration);
+
+        final OperationStepHandler writeHandler = new ReloadRequiredWriteAttributeHandler(ALL_ATTRIBUTES);
+        for (AttributeDefinition attribute : ALL_ATTRIBUTES) {
+            resourceRegistration.registerReadWriteAttribute(attribute, null, writeHandler);
+        }
+    }
+
+    static SimpleAttributeDefinition lookup(String xmlName) {
+        return ATTRIBUTE_MAP.get(xmlName);
+    }
+
+    static SimpleAttributeDefinition lookupElement(String xmlName) {
+        return ELEMENT_MAP.get(xmlName);
+    }
+}
diff --git a/saml/client-adapter/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/saml/extension/KeyStoreCertificateDefinition.java b/saml/client-adapter/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/saml/extension/KeyStoreCertificateDefinition.java
new file mode 100644
index 0000000..83dc057
--- /dev/null
+++ b/saml/client-adapter/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/saml/extension/KeyStoreCertificateDefinition.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2015 Red Hat Inc. and/or its affiliates and other contributors
+ * as indicated by the @author tags. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package org.keycloak.subsystem.adapter.saml.extension;
+
+import org.jboss.as.controller.SimpleAttributeDefinition;
+import org.jboss.as.controller.SimpleAttributeDefinitionBuilder;
+import org.jboss.dmr.ModelType;
+
+/**
+ * @author <a href="mailto:mstrukel@redhat.com">Marko Strukelj</a>
+ */
+public class KeyStoreCertificateDefinition {
+
+    static final SimpleAttributeDefinition CERTIFICATE_ALIAS =
+            new SimpleAttributeDefinitionBuilder(Constants.Model.CERTIFICATE_ALIAS, ModelType.STRING, true)
+                    .setXmlName(Constants.XML.CERTIFICATE_ALIAS)
+                    .build();
+
+    static SimpleAttributeDefinition lookup(String xmlName) {
+        return Constants.XML.CERTIFICATE_ALIAS.equals(xmlName) ? CERTIFICATE_ALIAS : null;
+    }
+}
diff --git a/saml/client-adapter/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/saml/extension/KeyStoreDefinition.java b/saml/client-adapter/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/saml/extension/KeyStoreDefinition.java
new file mode 100644
index 0000000..a71e89a
--- /dev/null
+++ b/saml/client-adapter/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/saml/extension/KeyStoreDefinition.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2015 Red Hat Inc. and/or its affiliates and other contributors
+ * as indicated by the @author tags. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package org.keycloak.subsystem.adapter.saml.extension;
+
+import org.jboss.as.controller.SimpleAttributeDefinition;
+import org.jboss.as.controller.SimpleAttributeDefinitionBuilder;
+import org.jboss.dmr.ModelType;
+
+import java.util.HashMap;
+
+/**
+ * @author <a href="mailto:mstrukel@redhat.com">Marko Strukelj</a>
+ */
+abstract class KeyStoreDefinition {
+
+    static final SimpleAttributeDefinition RESOURCE =
+            new SimpleAttributeDefinitionBuilder(Constants.Model.RESOURCE, ModelType.STRING, true)
+                    .setXmlName(Constants.XML.RESOURCE)
+                    .build();
+
+    static final SimpleAttributeDefinition PASSWORD =
+            new SimpleAttributeDefinitionBuilder(Constants.Model.PASSWORD, ModelType.STRING, true)
+                    .setXmlName(Constants.XML.PASSWORD)
+                    .build();
+
+    static final SimpleAttributeDefinition FILE =
+            new SimpleAttributeDefinitionBuilder(Constants.Model.FILE, ModelType.STRING, true)
+                    .setXmlName(Constants.XML.FILE)
+                    .build();
+
+    static final SimpleAttributeDefinition TYPE =
+            new SimpleAttributeDefinitionBuilder(Constants.Model.TYPE, ModelType.STRING, true)
+                    .setXmlName(Constants.XML.TYPE)
+                    .build();
+
+    static final SimpleAttributeDefinition ALIAS =
+            new SimpleAttributeDefinitionBuilder(Constants.Model.ALIAS, ModelType.STRING, true)
+                    .setXmlName(Constants.XML.ALIAS)
+                    .build();
+
+    static final SimpleAttributeDefinition[] ATTRIBUTES = {RESOURCE, PASSWORD, FILE, TYPE, ALIAS};
+    static final SimpleAttributeDefinition[] ALL_ATTRIBUTES = {RESOURCE, PASSWORD, FILE, TYPE, ALIAS,
+            KeyStorePrivateKeyDefinition.PRIVATE_KEY_ALIAS,
+            KeyStorePrivateKeyDefinition.PRIVATE_KEY_PASSWORD,
+            KeyStoreCertificateDefinition.CERTIFICATE_ALIAS
+    };
+
+    static final HashMap<String, SimpleAttributeDefinition> ATTRIBUTE_MAP = new HashMap<>();
+
+    static {
+        for (SimpleAttributeDefinition def : ATTRIBUTES) {
+            ATTRIBUTE_MAP.put(def.getXmlName(), def);
+        }
+    }
+
+    static SimpleAttributeDefinition lookup(String xmlName) {
+        return ATTRIBUTE_MAP.get(xmlName);
+    }
+}
diff --git a/saml/client-adapter/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/saml/extension/KeyStorePrivateKeyDefinition.java b/saml/client-adapter/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/saml/extension/KeyStorePrivateKeyDefinition.java
new file mode 100644
index 0000000..bbb398d
--- /dev/null
+++ b/saml/client-adapter/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/saml/extension/KeyStorePrivateKeyDefinition.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2015 Red Hat Inc. and/or its affiliates and other contributors
+ * as indicated by the @author tags. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package org.keycloak.subsystem.adapter.saml.extension;
+
+import org.jboss.as.controller.SimpleAttributeDefinition;
+import org.jboss.as.controller.SimpleAttributeDefinitionBuilder;
+import org.jboss.dmr.ModelType;
+
+import java.util.HashMap;
+
+/**
+ * @author <a href="mailto:mstrukel@redhat.com">Marko Strukelj</a>
+ */
+public class KeyStorePrivateKeyDefinition {
+    static final SimpleAttributeDefinition PRIVATE_KEY_ALIAS =
+            new SimpleAttributeDefinitionBuilder(Constants.Model.PRIVATE_KEY_ALIAS, ModelType.STRING, true)
+                    .setXmlName(Constants.XML.PRIVATE_KEY_ALIAS)
+                    .build();
+
+    static final SimpleAttributeDefinition PRIVATE_KEY_PASSWORD =
+            new SimpleAttributeDefinitionBuilder(Constants.Model.PRIVATE_KEY_PASSWORD, ModelType.STRING, true)
+                    .setXmlName(Constants.XML.PRIVATE_KEY_PASSWORD)
+                    .build();
+
+    static final SimpleAttributeDefinition[] ATTRIBUTES = {PRIVATE_KEY_ALIAS, PRIVATE_KEY_PASSWORD};
+
+    static final HashMap<String, SimpleAttributeDefinition> ATTRIBUTE_MAP = new HashMap<>();
+
+    static {
+        for (SimpleAttributeDefinition def : ATTRIBUTES) {
+            ATTRIBUTE_MAP.put(def.getXmlName(), def);
+        }
+    }
+
+    static SimpleAttributeDefinition lookup(String xmlName) {
+        return ATTRIBUTE_MAP.get(xmlName);
+    }
+}
diff --git a/saml/client-adapter/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/saml/extension/logging/KeycloakLogger.java b/saml/client-adapter/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/saml/extension/logging/KeycloakLogger.java
new file mode 100755
index 0000000..d068b64
--- /dev/null
+++ b/saml/client-adapter/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/saml/extension/logging/KeycloakLogger.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2013 Red Hat Inc. and/or its affiliates and other contributors
+ * as indicated by the @author tags. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package org.keycloak.subsystem.adapter.saml.extension.logging;
+
+import org.jboss.logging.BasicLogger;
+import org.jboss.logging.Logger;
+import org.jboss.logging.annotations.LogMessage;
+import org.jboss.logging.annotations.Message;
+import org.jboss.logging.annotations.MessageLogger;
+
+import static org.jboss.logging.Logger.Level.INFO;
+
+/**
+ * This interface to be fleshed out later when error messages are fully externalized.
+ *
+ * @author Stan Silvert ssilvert@redhat.com (C) 2013 Red Hat Inc.
+ */
+@MessageLogger(projectCode = "KEYCLOAK")
+public interface KeycloakLogger extends BasicLogger {
+
+    /**
+     * A logger with a category of the package name.
+     */
+    KeycloakLogger ROOT_LOGGER = Logger.getMessageLogger(KeycloakLogger.class, "org.jboss.keycloak");
+
+    @LogMessage(level = INFO)
+    @Message(value = "Keycloak subsystem override for deployment %s")
+    void deploymentSecured(String deployment);
+
+
+}
diff --git a/saml/client-adapter/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/saml/extension/logging/KeycloakMessages.java b/saml/client-adapter/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/saml/extension/logging/KeycloakMessages.java
new file mode 100755
index 0000000..be44809
--- /dev/null
+++ b/saml/client-adapter/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/saml/extension/logging/KeycloakMessages.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2013 Red Hat Inc. and/or its affiliates and other contributors
+ * as indicated by the @author tags. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package org.keycloak.subsystem.adapter.saml.extension.logging;
+
+import org.jboss.logging.Messages;
+import org.jboss.logging.annotations.MessageBundle;
+
+/**
+ * This interface to be fleshed out later when error messages are fully externalized.
+ *
+ * @author Stan Silvert ssilvert@redhat.com (C) 2012 Red Hat Inc.
+ */
+@MessageBundle(projectCode = "KEYCLOAK")
+public interface KeycloakMessages {
+
+    /**
+     * The messages
+     */
+    KeycloakMessages MESSAGES = Messages.getBundle(KeycloakMessages.class);
+}
diff --git a/saml/client-adapter/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/saml/extension/SecureDeploymentAddHandler.java b/saml/client-adapter/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/saml/extension/SecureDeploymentAddHandler.java
new file mode 100644
index 0000000..22de93d
--- /dev/null
+++ b/saml/client-adapter/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/saml/extension/SecureDeploymentAddHandler.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2015 Red Hat Inc. and/or its affiliates and other contributors
+ * as indicated by the @author tags. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package org.keycloak.subsystem.adapter.saml.extension;
+
+import org.jboss.as.controller.AbstractAddStepHandler;
+import org.jboss.as.controller.OperationContext;
+import org.jboss.as.controller.OperationFailedException;
+import org.jboss.dmr.ModelNode;
+
+/**
+ * @author <a href="mailto:mstrukel@redhat.com">Marko Strukelj</a>
+ */
+class SecureDeploymentAddHandler extends AbstractAddStepHandler {
+
+    static SecureDeploymentAddHandler INSTANCE = new SecureDeploymentAddHandler();
+
+    private SecureDeploymentAddHandler() {
+    }
+
+    @Override
+    protected void performRuntime(OperationContext context, ModelNode operation, ModelNode model) throws OperationFailedException {
+        Configuration.INSTANCE.updateModel(operation, model);
+    }
+}
diff --git a/saml/client-adapter/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/saml/extension/SecureDeploymentDefinition.java b/saml/client-adapter/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/saml/extension/SecureDeploymentDefinition.java
new file mode 100644
index 0000000..bf6cab5
--- /dev/null
+++ b/saml/client-adapter/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/saml/extension/SecureDeploymentDefinition.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2015 Red Hat Inc. and/or its affiliates and other contributors
+ * as indicated by the @author tags. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package org.keycloak.subsystem.adapter.saml.extension;
+
+import org.jboss.as.controller.*;
+import org.jboss.as.controller.operations.common.GenericSubsystemDescribeHandler;
+import org.jboss.as.controller.registry.ManagementResourceRegistration;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Defines attributes and operations for a secure-deployment.
+ */
+public class SecureDeploymentDefinition extends SimpleResourceDefinition {
+
+    static final SecureDeploymentDefinition INSTANCE = new SecureDeploymentDefinition();
+
+    private SecureDeploymentDefinition() {
+        super(PathElement.pathElement(Constants.Model.SECURE_DEPLOYMENT),
+                KeycloakSamlExtension.getResourceDescriptionResolver(Constants.Model.SECURE_DEPLOYMENT),
+                SecureDeploymentAddHandler.INSTANCE,
+                ReloadRequiredRemoveStepHandler.INSTANCE);
+    }
+
+    @Override
+    public void registerOperations(ManagementResourceRegistration resourceRegistration) {
+        super.registerOperations(resourceRegistration);
+        resourceRegistration.registerOperationHandler(GenericSubsystemDescribeHandler.DEFINITION, GenericSubsystemDescribeHandler.INSTANCE);
+    }
+}
diff --git a/saml/client-adapter/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/saml/extension/ServiceProviderAddHandler.java b/saml/client-adapter/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/saml/extension/ServiceProviderAddHandler.java
new file mode 100644
index 0000000..f9f3070
--- /dev/null
+++ b/saml/client-adapter/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/saml/extension/ServiceProviderAddHandler.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2015 Red Hat Inc. and/or its affiliates and other contributors
+ * as indicated by the @author tags. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package org.keycloak.subsystem.adapter.saml.extension;
+
+import org.jboss.as.controller.AbstractAddStepHandler;
+import org.jboss.as.controller.OperationContext;
+import org.jboss.as.controller.OperationFailedException;
+import org.jboss.dmr.ModelNode;
+
+/**
+ * @author <a href="mailto:mstrukel@redhat.com">Marko Strukelj</a>
+ */
+class ServiceProviderAddHandler extends AbstractAddStepHandler {
+
+    static final ServiceProviderAddHandler INSTANCE = new ServiceProviderAddHandler();
+
+    ServiceProviderAddHandler() {
+        super(ServiceProviderDefinition.ALL_ATTRIBUTES);
+    }
+
+    @Override
+    protected void performRuntime(OperationContext context, ModelNode operation, ModelNode model) throws OperationFailedException {
+        Configuration.INSTANCE.updateModel(operation, model);
+    }
+}
diff --git a/saml/client-adapter/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/saml/extension/ServiceProviderDefinition.java b/saml/client-adapter/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/saml/extension/ServiceProviderDefinition.java
new file mode 100644
index 0000000..cb84f12
--- /dev/null
+++ b/saml/client-adapter/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/saml/extension/ServiceProviderDefinition.java
@@ -0,0 +1,125 @@
+/*
+ * Copyright 2015 Red Hat Inc. and/or its affiliates and other contributors
+ * as indicated by the @author tags. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package org.keycloak.subsystem.adapter.saml.extension;
+
+import org.jboss.as.controller.AttributeDefinition;
+import org.jboss.as.controller.ListAttributeDefinition;
+import org.jboss.as.controller.OperationStepHandler;
+import org.jboss.as.controller.PathElement;
+import org.jboss.as.controller.ReloadRequiredRemoveStepHandler;
+import org.jboss.as.controller.ReloadRequiredWriteAttributeHandler;
+import org.jboss.as.controller.SimpleAttributeDefinition;
+import org.jboss.as.controller.SimpleAttributeDefinitionBuilder;
+import org.jboss.as.controller.SimpleResourceDefinition;
+import org.jboss.as.controller.StringListAttributeDefinition;
+import org.jboss.as.controller.operations.common.GenericSubsystemDescribeHandler;
+import org.jboss.as.controller.registry.ManagementResourceRegistration;
+import org.jboss.dmr.ModelType;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+
+/**
+ * @author <a href="mailto:mstrukel@redhat.com">Marko Strukelj</a>
+ */
+public class ServiceProviderDefinition extends SimpleResourceDefinition {
+
+    static final SimpleAttributeDefinition SSL_POLICY =
+            new SimpleAttributeDefinitionBuilder(Constants.Model.SSL_POLICY, ModelType.STRING, true)
+                    .setXmlName(Constants.XML.SSL_POLICY)
+                    .build();
+
+    static final SimpleAttributeDefinition NAME_ID_POLICY_FORMAT =
+            new SimpleAttributeDefinitionBuilder(Constants.Model.NAME_ID_POLICY_FORMAT, ModelType.STRING, true)
+                    .setXmlName(Constants.XML.NAME_ID_POLICY_FORMAT)
+                    .build();
+
+    static final SimpleAttributeDefinition LOGOUT_PAGE =
+            new SimpleAttributeDefinitionBuilder(Constants.Model.LOGOUT_PAGE, ModelType.STRING, true)
+                    .setXmlName(Constants.XML.LOGOUT_PAGE)
+                    .build();
+
+    static final SimpleAttributeDefinition FORCE_AUTHENTICATION =
+            new SimpleAttributeDefinitionBuilder(Constants.Model.FORCE_AUTHENTICATION, ModelType.BOOLEAN, true)
+                    .setXmlName(Constants.XML.FORCE_AUTHENTICATION)
+                    .build();
+
+    static final SimpleAttributeDefinition PRINCIPAL_NAME_MAPPING_POLICY =
+            new SimpleAttributeDefinitionBuilder(Constants.Model.PRINCIPAL_NAME_MAPPING_POLICY, ModelType.STRING, true)
+                    .setXmlName(Constants.XML.PRINCIPAL_NAME_MAPPING_POLICY)
+                    .build();
+
+    static final SimpleAttributeDefinition PRINCIPAL_NAME_MAPPING_ATTRIBUTE_NAME =
+            new SimpleAttributeDefinitionBuilder(Constants.Model.PRINCIPAL_NAME_MAPPING_ATTRIBUTE_NAME, ModelType.STRING, true)
+                    .setXmlName(Constants.XML.PRINCIPAL_NAME_MAPPING_ATTRIBUTE_NAME)
+                    .build();
+
+    static final ListAttributeDefinition ROLE_ATTRIBUTES =
+            new StringListAttributeDefinition.Builder(Constants.Model.ROLE_ATTRIBUTES)
+                    .setAllowNull(false)
+                    .build();
+
+    static final SimpleAttributeDefinition[] ATTRIBUTES = {SSL_POLICY, NAME_ID_POLICY_FORMAT, LOGOUT_PAGE, FORCE_AUTHENTICATION};
+    static final AttributeDefinition[] ELEMENTS = {PRINCIPAL_NAME_MAPPING_POLICY, PRINCIPAL_NAME_MAPPING_ATTRIBUTE_NAME, ROLE_ATTRIBUTES};
+
+
+    static final HashMap<String, SimpleAttributeDefinition> ATTRIBUTE_MAP = new HashMap<>();
+    static final HashMap<String, AttributeDefinition> ALL_MAP = new HashMap<>();
+    static final Collection<AttributeDefinition> ALL_ATTRIBUTES;
+
+    static {
+        for (SimpleAttributeDefinition def : ATTRIBUTES) {
+            ATTRIBUTE_MAP.put(def.getXmlName(), def);
+        }
+
+        ALL_MAP.putAll(ATTRIBUTE_MAP);
+        for (AttributeDefinition def : ELEMENTS) {
+            ALL_MAP.put(def.getXmlName(), def);
+        }
+        ALL_ATTRIBUTES = Collections.unmodifiableCollection(ALL_MAP.values());
+    }
+
+    static final ServiceProviderDefinition INSTANCE = new ServiceProviderDefinition();
+
+    private ServiceProviderDefinition() {
+        super(PathElement.pathElement(Constants.Model.SERVICE_PROVIDER),
+                KeycloakSamlExtension.getResourceDescriptionResolver(Constants.Model.SERVICE_PROVIDER),
+                ServiceProviderAddHandler.INSTANCE,
+                ReloadRequiredRemoveStepHandler.INSTANCE);
+    }
+
+    @Override
+    public void registerOperations(ManagementResourceRegistration resourceRegistration) {
+        super.registerOperations(resourceRegistration);
+        resourceRegistration.registerOperationHandler(GenericSubsystemDescribeHandler.DEFINITION, GenericSubsystemDescribeHandler.INSTANCE);
+    }
+
+    @Override
+    public void registerAttributes(ManagementResourceRegistration resourceRegistration) {
+        super.registerAttributes(resourceRegistration);
+
+        final OperationStepHandler writeHandler = new ReloadRequiredWriteAttributeHandler(ALL_ATTRIBUTES);
+        for (AttributeDefinition attribute : ALL_ATTRIBUTES) {
+            resourceRegistration.registerReadWriteAttribute(attribute, null, writeHandler);
+        }
+    }
+
+    static SimpleAttributeDefinition lookup(String xmlName) {
+        return ATTRIBUTE_MAP.get(xmlName);
+    }
+}
diff --git a/saml/client-adapter/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/saml/extension/SingleLogoutDefinition.java b/saml/client-adapter/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/saml/extension/SingleLogoutDefinition.java
new file mode 100644
index 0000000..6ad99b1
--- /dev/null
+++ b/saml/client-adapter/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/saml/extension/SingleLogoutDefinition.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2015 Red Hat Inc. and/or its affiliates and other contributors
+ * as indicated by the @author tags. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package org.keycloak.subsystem.adapter.saml.extension;
+
+import org.jboss.as.controller.SimpleAttributeDefinition;
+import org.jboss.as.controller.SimpleAttributeDefinitionBuilder;
+import org.jboss.dmr.ModelType;
+
+import java.util.HashMap;
+
+/**
+ * @author <a href="mailto:mstrukel@redhat.com">Marko Strukelj</a>
+ */
+abstract class SingleLogoutDefinition {
+
+    static final SimpleAttributeDefinition VALIDATE_REQUEST_SIGNATURE =
+            new SimpleAttributeDefinitionBuilder(Constants.Model.VALIDATE_REQUEST_SIGNATURE, ModelType.BOOLEAN, true)
+                    .setXmlName(Constants.XML.VALIDATE_REQUEST_SIGNATURE)
+                    .build();
+
+    static final SimpleAttributeDefinition VALIDATE_RESPONSE_SIGNATURE =
+            new SimpleAttributeDefinitionBuilder(Constants.Model.VALIDATE_RESPONSE_SIGNATURE, ModelType.BOOLEAN, true)
+                    .setXmlName(Constants.XML.VALIDATE_RESPONSE_SIGNATURE)
+                    .build();
+
+    static final SimpleAttributeDefinition SIGN_REQUEST =
+            new SimpleAttributeDefinitionBuilder(Constants.Model.SIGN_REQUEST, ModelType.BOOLEAN, true)
+                    .setXmlName(Constants.XML.SIGN_REQUEST)
+                    .build();
+
+    static final SimpleAttributeDefinition SIGN_RESPONSE =
+            new SimpleAttributeDefinitionBuilder(Constants.Model.SIGN_RESPONSE, ModelType.BOOLEAN, true)
+                    .setXmlName(Constants.XML.SIGN_RESPONSE)
+                    .build();
+
+    static final SimpleAttributeDefinition REQUEST_BINDING =
+            new SimpleAttributeDefinitionBuilder(Constants.Model.REQUEST_BINDING, ModelType.STRING, true)
+                    .setXmlName(Constants.XML.REQUEST_BINDING)
+                    .build();
+
+    static final SimpleAttributeDefinition RESPONSE_BINDING =
+            new SimpleAttributeDefinitionBuilder(Constants.Model.RESPONSE_BINDING, ModelType.STRING, true)
+                    .setXmlName(Constants.XML.RESPONSE_BINDING)
+                    .build();
+
+    static final SimpleAttributeDefinition POST_BINDING_URL =
+            new SimpleAttributeDefinitionBuilder(Constants.Model.POST_BINDING_URL, ModelType.STRING, true)
+                    .setXmlName(Constants.XML.POST_BINDING_URL)
+                    .build();
+
+    static final SimpleAttributeDefinition REDIRECT_BINDING_URL =
+            new SimpleAttributeDefinitionBuilder(Constants.Model.REDIRECT_BINDING_URL, ModelType.STRING, true)
+                    .setXmlName(Constants.XML.REDIRECT_BINDING_URL)
+                    .build();
+
+    static final SimpleAttributeDefinition[] ATTRIBUTES = {VALIDATE_REQUEST_SIGNATURE, VALIDATE_RESPONSE_SIGNATURE,
+            SIGN_REQUEST, SIGN_RESPONSE, REQUEST_BINDING, RESPONSE_BINDING, POST_BINDING_URL, REDIRECT_BINDING_URL};
+
+    static final HashMap<String, SimpleAttributeDefinition> ATTRIBUTE_MAP = new HashMap<>();
+
+    static {
+        for (SimpleAttributeDefinition def : ATTRIBUTES) {
+            ATTRIBUTE_MAP.put(def.getXmlName(), def);
+        }
+    }
+
+    static SimpleAttributeDefinition lookup(String xmlName) {
+        return ATTRIBUTE_MAP.get(xmlName);
+    }
+}
diff --git a/saml/client-adapter/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/saml/extension/SingleSignOnDefinition.java b/saml/client-adapter/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/saml/extension/SingleSignOnDefinition.java
new file mode 100644
index 0000000..fe78c02
--- /dev/null
+++ b/saml/client-adapter/wildfly/wildfly-subsystem/src/main/java/org/keycloak/subsystem/adapter/saml/extension/SingleSignOnDefinition.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2015 Red Hat Inc. and/or its affiliates and other contributors
+ * as indicated by the @author tags. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package org.keycloak.subsystem.adapter.saml.extension;
+
+import org.jboss.as.controller.SimpleAttributeDefinition;
+import org.jboss.as.controller.SimpleAttributeDefinitionBuilder;
+import org.jboss.dmr.ModelType;
+
+import java.util.HashMap;
+
+/**
+ * @author <a href="mailto:mstrukel@redhat.com">Marko Strukelj</a>
+ */
+abstract class SingleSignOnDefinition {
+
+    static final SimpleAttributeDefinition SIGN_REQUEST =
+            new SimpleAttributeDefinitionBuilder(Constants.Model.SIGN_REQUEST, ModelType.BOOLEAN, true)
+                    .setXmlName(Constants.XML.SIGN_REQUEST)
+                    .build();
+
+    static final SimpleAttributeDefinition VALIDATE_RESPONSE_SIGNATURE =
+            new SimpleAttributeDefinitionBuilder(Constants.Model.VALIDATE_RESPONSE_SIGNATURE, ModelType.BOOLEAN, true)
+                    .setXmlName(Constants.XML.VALIDATE_RESPONSE_SIGNATURE)
+                    .build();
+
+    static final SimpleAttributeDefinition REQUEST_BINDING =
+            new SimpleAttributeDefinitionBuilder(Constants.Model.REQUEST_BINDING, ModelType.STRING, true)
+                    .setXmlName(Constants.XML.REQUEST_BINDING)
+                    .build();
+
+    static final SimpleAttributeDefinition RESPONSE_BINDING =
+            new SimpleAttributeDefinitionBuilder(Constants.Model.RESPONSE_BINDING, ModelType.STRING, true)
+                    .setXmlName(Constants.XML.RESPONSE_BINDING)
+                    .build();
+
+    static final SimpleAttributeDefinition BINDING_URL =
+            new SimpleAttributeDefinitionBuilder(Constants.Model.BINDING_URL, ModelType.STRING, true)
+                    .setXmlName(Constants.XML.BINDING_URL)
+                    .build();
+
+    static final SimpleAttributeDefinition[] ATTRIBUTES = {SIGN_REQUEST, VALIDATE_RESPONSE_SIGNATURE, REQUEST_BINDING, RESPONSE_BINDING, BINDING_URL};
+
+    static final HashMap<String, SimpleAttributeDefinition> ATTRIBUTE_MAP = new HashMap<>();
+
+    static {
+        for (SimpleAttributeDefinition def : ATTRIBUTES) {
+            ATTRIBUTE_MAP.put(def.getXmlName(), def);
+        }
+    }
+
+    static SimpleAttributeDefinition lookup(String xmlName) {
+        return ATTRIBUTE_MAP.get(xmlName);
+    }
+}
diff --git a/saml/client-adapter/wildfly/wildfly-subsystem/src/main/resources/org/keycloak/subsystem/adapter/saml/extension/LocalDescriptions.properties b/saml/client-adapter/wildfly/wildfly-subsystem/src/main/resources/org/keycloak/subsystem/adapter/saml/extension/LocalDescriptions.properties
new file mode 100755
index 0000000..f8a4a11
--- /dev/null
+++ b/saml/client-adapter/wildfly/wildfly-subsystem/src/main/resources/org/keycloak/subsystem/adapter/saml/extension/LocalDescriptions.properties
@@ -0,0 +1,63 @@
+keycloak-saml.subsystem=Keycloak adapter subsystem
+keycloak-saml.subsystem.add=Operation Adds Keycloak adapter subsystem
+keycloak-saml.subsystem.remove=Operation removes Keycloak adapter subsystem
+keycloak-saml.subsystem.secure-deployment=A deployment secured by Keycloak.
+
+keycloak-saml.secure-deployment=A deployment secured by Keycloak
+keycloak-saml.secure-deployment.add=Add a deployment to be secured by Keycloak
+keycloak-saml.secure-deployment.remove=Remove a deployment to be secured by Keycloak
+keycloak-saml.secure-deployment.service-provider=A security provider configuration for secure deployment
+
+keycloak-saml.service-provider=A security provider configuration for secure deployment
+keycloak-saml.service-provider.add=Add a security provider configuration to deployment secured by Keycloak SAML
+keycloak-saml.service-provider.remove=Remove a security provider definition from deployment secured by Keycloak SAML
+keycloak-saml.service-provider.ssl-policy=SSL Policy to use
+keycloak-saml.service-provider.name-id-policy-format=Name ID policy format URN
+keycloak-saml.service-provider.logout-page=URI to a logout page
+keycloak-saml.service-provider.force-authentication=Redirected unauthenticated request to a login page
+keycloak-saml.service-provider.role-attributes=Role identifiers
+keycloak-saml.service-provider.principal-name-mapping-policy=Principal name mapping policy
+keycloak-saml.service-provider.principal-name-mapping-attribute-name=Principal name mapping attribute name
+keycloak-saml.service-provider.key=A key definition
+keycloak-saml.service-provider.identity-provider=Identity provider definition
+
+keycloak-saml.key=A key configuration for service provider or identity provider
+keycloak-saml.key.add=Add a key definition
+keycloak-saml.key.remove=Remove a key definition
+keycloak-saml.key.signing=Key can be used for signing
+keycloak-saml.key.encryption=Key can be used for encryption
+keycloak-saml.key.private-key-pem=Private key string in pem format
+keycloak-saml.key.public-key-pem=Public key string in pem format
+keycloak-saml.key.certificate-pem=Certificate key string in pem format
+keycloak-saml.key.key-store=Key store definition
+keycloak-saml.key.key-store.file=Key store filesystem path
+keycloak-saml.key.key-store.resource=Key store resource URI
+keycloak-saml.key.key-store.password=Key store password
+keycloak-saml.key.key-store.type=Key store format
+keycloak-saml.key.key-store.alias=Key alias
+keycloak-saml.key.key-store.private-key-alias=Private key alias
+keycloak-saml.key.key-store.private-key-password=Private key password
+keycloak-saml.key.key-store.certificate-alias=Certificate alias
+
+keycloak-saml.identity-provider=An identity provider configuration
+keycloak-saml.identity-provider.add=Add an identity provider
+keycloak-saml.identity-provider.remove=Remove an identity provider
+keycloak-saml.identity-provider.signatures-required=Require signatures for single-sign-on and single-logout
+keycloak-saml.identity-provider.signature-algorithm=Signature algorithm
+keycloak-saml.identity-provider.signature-canonicalization-method=Signature canonicalization method
+keycloak-saml.identity-provider.single-sign-on=Single sign-on configuration
+keycloak-saml.identity-provider.single-sign-on.sign-request=Sign SSO requests
+keycloak-saml.identity-provider.single-sign-on.validate-response-signature=Validate an SSO response signature
+keycloak-saml.identity-provider.single-sign-on.request-binding=HTTP method to use for requests
+keycloak-saml.identity-provider.single-sign-on.response-binding=HTTP method to use for responses
+keycloak-saml.identity-provider.single-sign-on.binding-url=SSO endpoint URL
+keycloak-saml.identity-provider.single-logout=Single logout configuration
+keycloak-saml.identity-provider.single-logout.validate-request-signature=Validate a single-logout request signature
+keycloak-saml.identity-provider.single-logout.validate-response-signature=Validate a single-logout response signature
+keycloak-saml.identity-provider.single-logout.sign-request=Sign single-logout requests
+keycloak-saml.identity-provider.single-logout.sign-response=Sign single-logout responses
+keycloak-saml.identity-provider.single-logout.request-binding=HTTP method to use for request
+keycloak-saml.identity-provider.single-logout.response-binding=HTTP method to use for response
+keycloak-saml.identity-provider.single-logout.post-binding-url=Endpoint URL for posting
+keycloak-saml.identity-provider.single-logout.redirect-binding-url=Endpoint URL for redirects
+keycloak-saml.identity-provider.key=Key definition for identity provider
\ No newline at end of file
diff --git a/saml/client-adapter/wildfly/wildfly-subsystem/src/main/resources/schema/wildfly-keycloak-saml_1_1.xsd b/saml/client-adapter/wildfly/wildfly-subsystem/src/main/resources/schema/wildfly-keycloak-saml_1_1.xsd
new file mode 100755
index 0000000..725104b
--- /dev/null
+++ b/saml/client-adapter/wildfly/wildfly-subsystem/src/main/resources/schema/wildfly-keycloak-saml_1_1.xsd
@@ -0,0 +1,268 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
+           targetNamespace="urn:jboss:domain:keycloak-saml:1.1"
+           xmlns="urn:jboss:domain:keycloak-saml:1.1"
+           elementFormDefault="qualified"
+           attributeFormDefault="unqualified"
+           version="1.0">
+
+    <!-- The subsystem root element -->
+    <xs:element name="subsystem" type="subsystem-type"/>
+
+    <xs:complexType name="subsystem-type">
+        <xs:annotation>
+            <xs:documentation>
+                <![CDATA[
+                    The Keycloak SAML adapter subsystem, used to register deployments managed by Keycloak SAML adapter
+                ]]>
+            </xs:documentation>
+        </xs:annotation>
+        <xs:all>
+            <xs:element name="secure-deployment" minOccurs="0" type="secure-deployment-type"/>
+        </xs:all>
+    </xs:complexType>
+
+    <xs:complexType name="secure-deployment-type">
+        <xs:all>
+            <xs:element name="SP" minOccurs="1" maxOccurs="1" type="sp-type"/>
+        </xs:all>
+        <xs:attribute name="name" type="xs:string" use="required">
+            <xs:annotation>
+                <xs:documentation>The name of the realm.</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+    </xs:complexType>
+
+    <xs:complexType name="sp-type">
+        <xs:all>
+            <xs:element name="Keys" minOccurs="0" maxOccurs="1" type="keys-type"/>
+            <xs:element name="PrincipalNameMapping" minOccurs="0" maxOccurs="1" type="principal-name-mapping-type"/>
+            <xs:element name="RoleIdentifiers" minOccurs="0" maxOccurs="1" type="role-identifiers-type"/>
+            <xs:element name="IDP" minOccurs="1" maxOccurs="1" type="identity-provider-type"/>
+        </xs:all>
+        <xs:attribute name="entityID" type="xs:string" use="required">
+            <xs:annotation>
+                <xs:documentation>The entity ID for SAML service provider</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="sslPolicy" type="xs:string" use="required">
+            <xs:annotation>
+                <xs:documentation>The ssl policy</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="nameIDPolicyFormat" type="xs:string" use="required">
+            <xs:annotation>
+                <xs:documentation>Name ID policy format URN</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="logoutPage" type="xs:string" use="required">
+            <xs:annotation>
+                <xs:documentation>URI to a logout page</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="forceAuthentication" type="xs:boolean" use="required">
+            <xs:annotation>
+                <xs:documentation>Redirected unauthenticated request to a login page</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+    </xs:complexType>
+    <xs:complexType name="identity-provider-type">
+        <xs:all minOccurs="1" maxOccurs="1">
+            <xs:element name="SingleSignOnService" minOccurs="1" maxOccurs="1" type="single-signon-type"/>
+            <xs:element name="SingleLogoutService" minOccurs="0" maxOccurs="1" type="single-logout-type"/>
+            <xs:element name="Keys" minOccurs="0" maxOccurs="1" type="keys-type"/>
+        </xs:all>
+        <xs:attribute name="entityID" type="xs:string" use="required">
+            <xs:annotation>
+                <xs:documentation>The entity ID for SAML service provider</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="signaturesRequired" type="xs:boolean" use="required">
+            <xs:annotation>
+                <xs:documentation>Require signatures for single-sign-on and single-logout</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="signatureAlgorithm" type="xs:string" use="optional">
+            <xs:annotation>
+                <xs:documentation>Algorithm used for signatures</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="signatureCanonicalizationMethod" type="xs:string" use="optional">
+            <xs:annotation>
+                <xs:documentation>Canonicalization method used for signatures</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+    </xs:complexType>
+    <xs:complexType name="single-signon-type">
+        <xs:attribute name="signRequest" type="xs:boolean" use="optional">
+            <xs:annotation>
+                <xs:documentation>Sign the SSO requests</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="validateResponseSignature" type="xs:boolean" use="optional">
+            <xs:annotation>
+                <xs:documentation>Validate the SSO response signature</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="requestBinding" type="xs:string" use="optional">
+            <xs:annotation>
+                <xs:documentation>HTTP method to use for requests</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="responseBinding" type="xs:string" use="optional">
+            <xs:annotation>
+                <xs:documentation>HTTP method to use for response</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="bindingUrl" type="xs:string" use="optional">
+            <xs:annotation>
+                <xs:documentation>SSO endpoint URL</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+    </xs:complexType>
+    <xs:complexType name="single-logout-type">
+        <xs:attribute name="validateRequestSignature" type="xs:boolean" use="optional">
+            <xs:annotation>
+                <xs:documentation>Validate a single-logout request signature</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="validateResponseSignature" type="xs:boolean" use="optional">
+            <xs:annotation>
+                <xs:documentation>Validate a single-logout response signature</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="signRequest" type="xs:boolean" use="optional">
+            <xs:annotation>
+                <xs:documentation>Sign single-logout requests</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="signResponse" type="xs:boolean" use="optional">
+            <xs:annotation>
+                <xs:documentation>Sign single-logout responses</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="requestBinding" type="xs:string" use="optional">
+            <xs:annotation>
+                <xs:documentation>HTTP method to use for request</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="responseBinding" type="xs:string" use="optional">
+            <xs:annotation>
+                <xs:documentation>HTTP method to use for response</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="postBindingUrl" type="xs:string" use="optional">
+            <xs:annotation>
+                <xs:documentation>Endpoint URL for posting</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="redirectBindingUrl" type="xs:string" use="optional">
+            <xs:annotation>
+                <xs:documentation>Endpoint URL for redirects</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+    </xs:complexType>
+    <xs:complexType name="keys-type">
+        <xs:sequence>
+            <xs:element name="Key" minOccurs="1" maxOccurs="2" type="key-type"/>
+        </xs:sequence>
+    </xs:complexType>
+    <xs:complexType name="key-type">
+        <xs:all>
+            <xs:element name="KeyStore" minOccurs="0" maxOccurs="1" type="keystore-type"/>
+            <xs:element name="PrivateKeyPem" minOccurs="0" maxOccurs="1" type="xs:string"/>
+            <xs:element name="PublicKeyPem" minOccurs="0" maxOccurs="1" type="xs:string"/>
+            <xs:element name="CertificatePem" minOccurs="0" maxOccurs="1" type="xs:string"/>
+        </xs:all>
+        <xs:attribute name="signing" type="xs:boolean" use="optional">
+            <xs:annotation>
+                <xs:documentation>Key can be used for signing</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="encryption" type="xs:boolean" use="optional">
+            <xs:annotation>
+                <xs:documentation>Key can be used for encryption</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+    </xs:complexType>
+    <xs:complexType name="keystore-type">
+        <xs:sequence minOccurs="0" maxOccurs="1">
+            <xs:element name="PrivateKey" minOccurs="0" maxOccurs="1" type="privatekey-type"/>
+            <xs:element name="Certificate" minOccurs="0" maxOccurs="1" type="certificate-type"/>
+        </xs:sequence>
+        <xs:attribute name="file" type="xs:string" use="optional">
+            <xs:annotation>
+                <xs:documentation>Key store filesystem path</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="resource" type="xs:string" use="optional">
+            <xs:annotation>
+                <xs:documentation>Key store resource URI</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="password" type="xs:string" use="required">
+            <xs:annotation>
+                <xs:documentation>Key store password</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="type" type="xs:string" use="optional">
+            <xs:annotation>
+                <xs:documentation>Key store format</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="alias" type="xs:string" use="optional">
+            <xs:annotation>
+                <xs:documentation>Key alias</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+    </xs:complexType>
+
+    <xs:complexType name="privatekey-type">
+        <xs:attribute name="alias" type="xs:string" use="required">
+            <xs:annotation>
+                <xs:documentation>Private key alias</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="password" type="xs:string" use="required">
+            <xs:annotation>
+                <xs:documentation>Private key password</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+    </xs:complexType>
+
+    <xs:complexType name="certificate-type">
+        <xs:attribute name="alias" type="xs:string" use="required">
+            <xs:annotation>
+                <xs:documentation>Certificate alias</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+    </xs:complexType>
+
+    <xs:complexType name="principal-name-mapping-type">
+        <xs:attribute name="policy" type="xs:string" use="required">
+            <xs:annotation>
+                <xs:documentation>Principal name mapping policy. Possible values: FROM_NAME_ID</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+        <xs:attribute name="attribute" type="xs:string" use="optional">
+            <xs:annotation>
+                <xs:documentation>Name of the attribute to use for principal name mapping</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+    </xs:complexType>
+
+    <xs:complexType name="role-identifiers-type">
+        <xs:sequence minOccurs="0" maxOccurs="unbounded">
+            <xs:element name="Attribute" minOccurs="0" maxOccurs="unbounded" type="attribute-type"/>
+        </xs:sequence>
+    </xs:complexType>
+
+    <xs:complexType name="attribute-type">
+        <xs:attribute name="name" type="xs:string" use="required">
+            <xs:annotation>
+                <xs:documentation>Role attribute</xs:documentation>
+            </xs:annotation>
+        </xs:attribute>
+    </xs:complexType>
+</xs:schema>
diff --git a/saml/client-adapter/wildfly/wildfly-subsystem/src/test/java/org/keycloak/subsystem/adapter/saml/extension/SubsystemParsingTestCase.java b/saml/client-adapter/wildfly/wildfly-subsystem/src/test/java/org/keycloak/subsystem/adapter/saml/extension/SubsystemParsingTestCase.java
new file mode 100755
index 0000000..fdd8ee2
--- /dev/null
+++ b/saml/client-adapter/wildfly/wildfly-subsystem/src/test/java/org/keycloak/subsystem/adapter/saml/extension/SubsystemParsingTestCase.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2013 Red Hat Inc. and/or its affiliates and other contributors
+ * as indicated by the @author tags. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package org.keycloak.subsystem.adapter.saml.extension;
+
+import org.jboss.as.subsystem.test.AbstractSubsystemBaseTest;
+
+import java.io.IOException;
+
+
+/**
+ * Tests all management expects for subsystem, parsing, marshaling, model definition and other
+ * Here is an example that allows you a fine grained controller over what is tested and how. So it can give you ideas what can be done and tested.
+ * If you have no need for advanced testing of subsystem you look at {@link SubsystemBaseParsingTestCase} that testes same stuff but most of the code
+ * is hidden inside of test harness
+ *
+ * @author <a href="kabir.khan@jboss.com">Kabir Khan</a>
+ * @author Tomaz Cerar
+ * @author <a href="marko.strukelj@gmail.com">Marko Strukelj</a>
+ */
+public class SubsystemParsingTestCase extends AbstractSubsystemBaseTest {
+
+    public SubsystemParsingTestCase() {
+        super(KeycloakSamlExtension.SUBSYSTEM_NAME, new KeycloakSamlExtension());
+    }
+
+    @Override
+    protected String getSubsystemXml() throws IOException {
+        return readResource("keycloak-saml-1.1.xml");
+    }
+
+    @Override
+    protected String getSubsystemXsdPath() throws Exception {
+        return "schema/wildfly-keycloak-saml_1_1.xsd";
+    }
+
+    @Override
+    protected String[] getSubsystemTemplatePaths() throws IOException {
+        return new String[]{
+                "/subsystem-templates/keycloak-saml-adapter.xml"
+        };
+    }
+}
diff --git a/saml/client-adapter/wildfly/wildfly-subsystem/src/test/resources/org/keycloak/subsystem/adapter/saml/extension/keycloak-saml-1.1.xml b/saml/client-adapter/wildfly/wildfly-subsystem/src/test/resources/org/keycloak/subsystem/adapter/saml/extension/keycloak-saml-1.1.xml
new file mode 100644
index 0000000..6f56fb0
--- /dev/null
+++ b/saml/client-adapter/wildfly/wildfly-subsystem/src/test/resources/org/keycloak/subsystem/adapter/saml/extension/keycloak-saml-1.1.xml
@@ -0,0 +1,50 @@
+<subsystem xmlns="urn:jboss:domain:keycloak-saml:1.1">
+    <secure-deployment name="my-app.war">
+        <SP entityID="http://localhost:8080/sales-post-enc/"
+            sslPolicy="EXTERNAL"
+            nameIDPolicyFormat="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified"
+            logoutPage="/logout.jsp"
+            forceAuthentication="false">
+
+            <Keys>
+                <Key encryption="true" signing="true">
+                    <PrivateKeyPem>my_key.pem</PrivateKeyPem>
+                    <PublicKeyPem>my_key.pub</PublicKeyPem>
+                    <CertificatePem>cert.cer</CertificatePem>
+                    <KeyStore resource="/WEB-INF/keystore.jks" password="store123" file="test" alias="test" type="jks">
+                        <PrivateKey alias="http://localhost:8080/sales-post-enc/" password="test123"/>
+                        <Certificate alias="http://localhost:8080/sales-post-enc/"/>
+                    </KeyStore>
+                </Key>
+            </Keys>
+            <PrincipalNameMapping policy="FROM_NAME_ID" attribute="test"/>
+            <RoleIdentifiers>
+                <Attribute name="Role"/>
+                <Attribute name="Role2"/>
+            </RoleIdentifiers>
+            <IDP entityID="idp" signaturesRequired="true" signatureAlgorithm="test" signatureCanonicalizationMethod="test">
+                <SingleSignOnService signRequest="true"
+                                     validateResponseSignature="true"
+                                     requestBinding="POST"
+                                     responseBinding="POST"
+                                     bindingUrl="http://localhost:8080/auth/realms/saml-demo/protocol/saml"/>
+                <SingleLogoutService
+                        validateRequestSignature="true"
+                        validateResponseSignature="true"
+                        signRequest="true"
+                        signResponse="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">
+                        <KeyStore resource="/WEB-INF/keystore.jks" password="store123">
+                            <Certificate alias="saml-demo"/>
+                        </KeyStore>
+                    </Key>
+                </Keys>
+            </IDP>
+        </SP>
+    </secure-deployment>
+</subsystem>
\ No newline at end of file
diff --git a/saml/client-adapter/wildfly/wildfly-subsystem/src/test/resources/org/keycloak/subsystem/adapter/saml/extension/keycloak-saml-1.1-err.xml b/saml/client-adapter/wildfly/wildfly-subsystem/src/test/resources/org/keycloak/subsystem/adapter/saml/extension/keycloak-saml-1.1-err.xml
new file mode 100644
index 0000000..26d0e98
--- /dev/null
+++ b/saml/client-adapter/wildfly/wildfly-subsystem/src/test/resources/org/keycloak/subsystem/adapter/saml/extension/keycloak-saml-1.1-err.xml
@@ -0,0 +1,50 @@
+<subsystem xmlns="urn:jboss:domain:keycloak-saml:1.1">
+    <secure-deployment name="my-app.war">
+        <SP entityID="http://localhost:8080/sales-post-enc/"
+            sslPolicy="EXTERNAL"
+            nameIDPolicyFormat="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified"
+            logoutPage="/logout.jsp"
+            forceAuthentication="false">
+
+            <Keys>
+                <Key encryption="true" signing="true">
+                    <PrivateKeyPem>my_key.pem</PrivateKeyPem>
+                    <PublicKeyPem>my_key.pub</PublicKeyPem>
+                    <CertificatePem>cert.cer</CertificatePem>
+                    <KeyStore resource="/WEB-INF/keystore.jks" password="store123" file="test" alias="test" type="jks">
+                        <PrivateKey alias="http://localhost:8080/sales-post-enc/" password="test123"/>
+                        <Certificate alias="http://localhost:8080/sales-post-enc/"/>
+                    </KeyStore>
+                </Key>
+            </Keys>
+            <PrincipalNameMapping policy="FROM_NAME_ID" attribute="test"/>
+            <RoleIdentifiers>
+                <Attribute name="Role"/>
+                <Attribute name="Role2"/>
+            </RoleIdentifiers>
+            <IDP entityID="idp" signaturesRequired="true" signatureAlgorithm="test" signatureCanonicalizationMethod="test" encryption="test">
+                <SingleSignOnService signRequest="true"
+                                     validateResponseSignature="true"
+                                     requestBinding="POST"
+                                     responseBinding="POST"
+                                     bindingUrl="http://localhost:8080/auth/realms/saml-demo/protocol/saml"/>
+                <SingleLogoutService
+                        validateRequestSignature="true"
+                        validateResponseSignature="true"
+                        signRequest="true"
+                        signResponse="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">
+                        <KeyStore resource="/WEB-INF/keystore.jks" password="store123">
+                            <Certificate alias="saml-demo"/>
+                        </KeyStore>
+                    </Key>
+                </Keys>
+            </IDP>
+        </SP>
+    </secure-deployment>
+</subsystem>
\ No newline at end of file