keycloak-aplcache

Changes

.travis.yml 10(+2 -8)

services/src/main/java/org/keycloak/services/clientregistration/oidc/OIDCClientResponseRepresentation.java 77(+0 -77)

Details

.travis.yml 10(+2 -8)

diff --git a/.travis.yml b/.travis.yml
index 8146d6e..5dee839 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -3,14 +3,8 @@ language: java
 jdk:
   - oraclejdk8
 
-cache:
-    directories:
-        - $HOME/.m2
-
-before_cache:
-  - rm -rf $HOME/.m2/repository/org/keycloak
-
-install: mvn install -Pdistribution -DskipTests=true -B -V
+install: 
+  - travis_wait mvn install -Pdistribution -DskipTests=true -B -V -q
 
 script:
   - mvn test -B
diff --git a/client-registration/api/src/main/java/org/keycloak/client/registration/Auth.java b/client-registration/api/src/main/java/org/keycloak/client/registration/Auth.java
index 31ad4e8..c3dd313 100644
--- a/client-registration/api/src/main/java/org/keycloak/client/registration/Auth.java
+++ b/client-registration/api/src/main/java/org/keycloak/client/registration/Auth.java
@@ -5,6 +5,7 @@ import org.apache.http.HttpRequest;
 import org.keycloak.common.util.Base64;
 import org.keycloak.representations.idm.ClientInitialAccessPresentation;
 import org.keycloak.representations.idm.ClientRepresentation;
+import org.keycloak.representations.oidc.OIDCClientRepresentation;
 
 /**
  * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
@@ -21,11 +22,14 @@ public abstract class Auth {
         return new BearerTokenAuth(initialAccess.getToken());
     }
 
-
     public static Auth token(ClientRepresentation client) {
         return new BearerTokenAuth(client.getRegistrationAccessToken());
     }
 
+    public static Auth token(OIDCClientRepresentation client) {
+        return new BearerTokenAuth(client.getRegistrationAccessToken());
+    }
+
     public static Auth client(String clientId, String clientSecret) {
         return new BasicAuth(clientId, clientSecret);
     }
diff --git a/client-registration/api/src/main/java/org/keycloak/client/registration/ClientRegistration.java b/client-registration/api/src/main/java/org/keycloak/client/registration/ClientRegistration.java
index 2b1a991..f2215f1 100644
--- a/client-registration/api/src/main/java/org/keycloak/client/registration/ClientRegistration.java
+++ b/client-registration/api/src/main/java/org/keycloak/client/registration/ClientRegistration.java
@@ -3,8 +3,10 @@ package org.keycloak.client.registration;
 import org.apache.http.client.HttpClient;
 import org.apache.http.impl.client.HttpClients;
 import org.codehaus.jackson.map.ObjectMapper;
+import org.codehaus.jackson.map.annotate.JsonSerialize;
 import org.keycloak.representations.adapters.config.AdapterConfig;
 import org.keycloak.representations.idm.ClientRepresentation;
+import org.keycloak.representations.oidc.OIDCClientRepresentation;
 import org.keycloak.util.JsonSerialization;
 
 import java.io.IOException;
@@ -18,10 +20,17 @@ public class ClientRegistration {
     public static final ObjectMapper outputMapper = new ObjectMapper();
     static {
         outputMapper.getSerializationConfig().addMixInAnnotations(ClientRepresentation.class, ClientRepresentationMixIn.class);
+        outputMapper.getSerializationConfig().addMixInAnnotations(OIDCClientRepresentation.class, OIDCClientRepresentationMixIn.class);
+        outputMapper.setSerializationInclusion(JsonSerialize.Inclusion.NON_NULL);
     }
 
+    private final String JSON = "application/json";
+    private final String XML = "application/xml";
+
     private final String DEFAULT = "default";
     private final String INSTALLATION = "install";
+    private final String OIDC = "openid-connect";
+    private final String SAML = "saml2-entity-descriptor";
 
     private HttpUtil httpUtil;
 
@@ -47,23 +56,23 @@ public class ClientRegistration {
 
     public ClientRepresentation create(ClientRepresentation client) throws ClientRegistrationException {
         String content = serialize(client);
-        InputStream resultStream = httpUtil.doPost(content, DEFAULT);
+        InputStream resultStream = httpUtil.doPost(content, JSON, JSON, DEFAULT);
         return deserialize(resultStream, ClientRepresentation.class);
     }
 
     public ClientRepresentation get(String clientId) throws ClientRegistrationException {
-        InputStream resultStream = httpUtil.doGet(DEFAULT, clientId);
+        InputStream resultStream = httpUtil.doGet(JSON, DEFAULT, clientId);
         return resultStream != null ? deserialize(resultStream, ClientRepresentation.class) : null;
     }
 
     public AdapterConfig getAdapterConfig(String clientId) throws ClientRegistrationException {
-        InputStream resultStream = httpUtil.doGet(INSTALLATION, clientId);
+        InputStream resultStream = httpUtil.doGet(JSON, INSTALLATION, clientId);
         return resultStream != null ? deserialize(resultStream, AdapterConfig.class) : null;
     }
 
     public ClientRepresentation update(ClientRepresentation client) throws ClientRegistrationException {
         String content = serialize(client);
-        InputStream resultStream = httpUtil.doPut(content, DEFAULT, client.getClientId());
+        InputStream resultStream = httpUtil.doPut(content, JSON, JSON, DEFAULT, client.getClientId());
         return resultStream != null ? deserialize(resultStream, ClientRepresentation.class) : null;
     }
 
@@ -75,10 +84,17 @@ public class ClientRegistration {
         httpUtil.doDelete(DEFAULT, clientId);
     }
 
-    public static String serialize(ClientRepresentation client) throws ClientRegistrationException {
-        try {
+    public OIDCClientRegistration oidc() {
+        return new OIDCClientRegistration();
+    }
 
-            return outputMapper.writeValueAsString(client);
+    public SAMLClientRegistration saml() {
+        return new SAMLClientRegistration();
+    }
+
+    public static String serialize(Object obj) throws ClientRegistrationException {
+        try {
+            return outputMapper.writeValueAsString(obj);
         } catch (IOException e) {
             throw new ClientRegistrationException("Failed to write json object", e);
         }
@@ -92,6 +108,44 @@ public class ClientRegistration {
         }
     }
 
+    public class OIDCClientRegistration {
+
+        public OIDCClientRepresentation create(OIDCClientRepresentation client) throws ClientRegistrationException {
+            String content = serialize(client);
+            InputStream resultStream = httpUtil.doPost(content, JSON, JSON, OIDC);
+            return deserialize(resultStream, OIDCClientRepresentation.class);
+        }
+
+        public OIDCClientRepresentation get(String clientId) throws ClientRegistrationException {
+            InputStream resultStream = httpUtil.doGet(JSON, OIDC, clientId);
+            return resultStream != null ? deserialize(resultStream, OIDCClientRepresentation.class) : null;
+        }
+
+        public OIDCClientRepresentation update(OIDCClientRepresentation client) throws ClientRegistrationException {
+            String content = serialize(client);
+            InputStream resultStream = httpUtil.doPut(content, JSON, JSON, OIDC, client.getClientId());
+            return resultStream != null ? deserialize(resultStream, OIDCClientRepresentation.class) : null;
+        }
+
+        public void delete(OIDCClientRepresentation client) throws ClientRegistrationException {
+            delete(client.getClientId());
+        }
+
+        public void delete(String clientId) throws ClientRegistrationException {
+            httpUtil.doDelete(OIDC, clientId);
+        }
+
+    }
+
+    public class SAMLClientRegistration {
+
+        public ClientRepresentation create(String entityDescriptor) throws ClientRegistrationException {
+            InputStream resultStream = httpUtil.doPost(entityDescriptor, XML, JSON, SAML);
+            return deserialize(resultStream, ClientRepresentation.class);
+        }
+
+    }
+
     public static class ClientRegistrationBuilder {
 
         private String url;
diff --git a/client-registration/api/src/main/java/org/keycloak/client/registration/HttpUtil.java b/client-registration/api/src/main/java/org/keycloak/client/registration/HttpUtil.java
index 6444749..4d44710 100644
--- a/client-registration/api/src/main/java/org/keycloak/client/registration/HttpUtil.java
+++ b/client-registration/api/src/main/java/org/keycloak/client/registration/HttpUtil.java
@@ -33,12 +33,12 @@ class HttpUtil {
         this.auth = auth;
     }
 
-    InputStream doPost(String content, String... path) throws ClientRegistrationException {
+    InputStream doPost(String content, String contentType, String acceptType, String... path) throws ClientRegistrationException {
         try {
             HttpPost request = new HttpPost(getUrl(baseUri, path));
 
-            request.setHeader(HttpHeaders.CONTENT_TYPE, "application/json");
-            request.setHeader(HttpHeaders.ACCEPT, "application/json");
+            request.setHeader(HttpHeaders.CONTENT_TYPE, contentType);
+            request.setHeader(HttpHeaders.ACCEPT, acceptType);
             request.setEntity(new StringEntity(content));
 
             addAuth(request);
@@ -60,11 +60,11 @@ class HttpUtil {
         }
     }
 
-    InputStream doGet(String... path) throws ClientRegistrationException {
+    InputStream doGet(String acceptType, String... path) throws ClientRegistrationException {
         try {
             HttpGet request = new HttpGet(getUrl(baseUri, path));
 
-            request.setHeader(HttpHeaders.ACCEPT, "application/json");
+            request.setHeader(HttpHeaders.ACCEPT, acceptType);
 
             addAuth(request);
 
@@ -90,12 +90,12 @@ class HttpUtil {
         }
     }
 
-    InputStream doPut(String content, String... path) throws ClientRegistrationException {
+    InputStream doPut(String content, String contentType, String acceptType, String... path) throws ClientRegistrationException {
         try {
             HttpPut request = new HttpPut(getUrl(baseUri, path));
 
-            request.setHeader(HttpHeaders.CONTENT_TYPE, "application/json");
-            request.setHeader(HttpHeaders.ACCEPT, "application/json");
+            request.setHeader(HttpHeaders.CONTENT_TYPE, contentType);
+            request.setHeader(HttpHeaders.ACCEPT, acceptType);
             request.setEntity(new StringEntity(content));
 
             addAuth(request);
@@ -134,7 +134,7 @@ class HttpUtil {
                 response.getEntity().getContent().close();
             }
 
-            if (response.getStatusLine().getStatusCode() != 200) {
+            if (response.getStatusLine().getStatusCode() != 204) {
                 throw new HttpErrorException(response.getStatusLine());
             }
         } catch (IOException e) {
diff --git a/client-registration/api/src/main/java/org/keycloak/client/registration/OIDCClientRepresentationMixIn.java b/client-registration/api/src/main/java/org/keycloak/client/registration/OIDCClientRepresentationMixIn.java
new file mode 100644
index 0000000..b0dfed6
--- /dev/null
+++ b/client-registration/api/src/main/java/org/keycloak/client/registration/OIDCClientRepresentationMixIn.java
@@ -0,0 +1,22 @@
+package org.keycloak.client.registration;
+
+import org.codehaus.jackson.annotate.JsonIgnore;
+
+/**
+ * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
+ */
+abstract class OIDCClientRepresentationMixIn {
+
+    @JsonIgnore
+    private Integer client_id_issued_at;
+
+    @JsonIgnore
+    private Integer client_secret_expires_at;
+
+    @JsonIgnore
+    private String registration_client_uri;
+
+    @JsonIgnore
+    private String registration_access_token;
+
+}
diff --git a/client-registration/cli/src/main/java/org/keycloak/client/registration/cli/ClientRegistrationCLI.java b/client-registration/cli/src/main/java/org/keycloak/client/registration/cli/ClientRegistrationCLI.java
index f0b0857..986faac 100644
--- a/client-registration/cli/src/main/java/org/keycloak/client/registration/cli/ClientRegistrationCLI.java
+++ b/client-registration/cli/src/main/java/org/keycloak/client/registration/cli/ClientRegistrationCLI.java
@@ -62,6 +62,8 @@ public class ClientRegistrationCLI {
             CommandContainer command = registry.getCommand(args[0], null);
             ParserGenerator.parseAndPopulate(command, args[0], Arrays.copyOfRange(args, 1, args.length));
         }*/
+
+        //commandInvocation.getCommandRegistry().getAllCommandNames()
     }
 
 }
diff --git a/connections/jpa-liquibase/src/main/resources/META-INF/jpa-changelog-1.7.0.xml b/connections/jpa-liquibase/src/main/resources/META-INF/jpa-changelog-1.7.0.xml
index db8b8d0..c81b062 100755
--- a/connections/jpa-liquibase/src/main/resources/META-INF/jpa-changelog-1.7.0.xml
+++ b/connections/jpa-liquibase/src/main/resources/META-INF/jpa-changelog-1.7.0.xml
@@ -73,5 +73,7 @@
             <column name="REGISTRATION_TOKEN" type="VARCHAR(255)"/>
         </addColumn>
 
+        <modifyDataType tableName="REALM" columnName="PASSWORD_POLICY" newDataType="VARCHAR(2550)"/>
+
     </changeSet>
 </databaseChangeLog>
\ No newline at end of file
diff --git a/docbook/auth-server-docs/reference/en/en-US/modules/client-registration.xml b/docbook/auth-server-docs/reference/en/en-US/modules/client-registration.xml
index 0070cc0..fab7119 100755
--- a/docbook/auth-server-docs/reference/en/en-US/modules/client-registration.xml
+++ b/docbook/auth-server-docs/reference/en/en-US/modules/client-registration.xml
@@ -10,15 +10,15 @@
     <para>
         The Client Registration Service provides built-in support for Keycloak Client Representations, OpenID Connect
         Client Meta Data and SAML Entity Descriptors. It's also possible to plugin custom client registration providers
-        if required. The Client Registration Service endpoint is <literal>&lt;KEYCLOAK URL&gt;/clients/&lt;provider&gt;</literal>.
+        if required. The Client Registration Service endpoint is <literal>&lt;KEYCLOAK URL&gt;/realms/&lt;realm&gt;/clients/&lt;provider&gt;</literal>.
     </para>
     <para>
         The built-in supported <literal>providers</literal> are:
         <itemizedlist>
             <listitem><literal>default</literal> Keycloak Representations</listitem>
             <listitem><literal>install</literal> Keycloak Adapter Configuration</listitem>
-            <!--<listitem><literal>openid-connect</literal> OpenID Connect Dynamic Client Registration</listitem>-->
-            <!--<listitem><literal>saml-ed</literal> SAML Entity Descriptors</listitem>-->
+            <listitem><literal>openid-connect</literal> OpenID Connect Dynamic Client Registration</listitem>
+            <listitem><literal>saml2-entity-descriptor</literal> SAML Entity Descriptors</listitem>
         </itemizedlist>
         The following sections will describe how to use the different providers.
     </para>
@@ -106,30 +106,30 @@ Authorization: bearer eyJhbGciOiJSUzI1NiJ9.eyJqdGkiOiJmMjJmNzQyYy04ZjNlLTQ2M....
         </para>
         <para>
             To create a client create a Client Representation (JSON) then do a HTTP POST to:
-            <literal>&lt;KEYCLOAK URL&gt;/clients/&lt;provider&gt;/default</literal>. It will return a Client Representation
+            <literal>&lt;KEYCLOAK URL&gt;/realms/&lt;realm&gt;/clients/&lt;provider&gt;/default</literal>. It will return a Client Representation
             that also includes the registration access token. You should save the registration access token somewhere
             if you want to retrieve the config, update or delete the client later.
         </para>
         <para>
             To retrieve the Client Representation then do a HTTP GET to:
-            <literal>&lt;KEYCLOAK URL&gt;/clients/&lt;provider&gt;/default/&lt;client id&gt;</literal>. It will also
+            <literal>&lt;KEYCLOAK URL&gt;/realms/&lt;realm&gt;clients/&lt;provider&gt;/default/&lt;client id&gt;</literal>. It will also
             return a new registration access token.
         </para>
         <para>
             To update the Client Representation then do a HTTP PUT to with the updated Client Representation to:
-            <literal>&lt;KEYCLOAK URL&gt;/clients/&lt;provider&gt;/default/&lt;client id&gt;</literal>. It will also
+            <literal>&lt;KEYCLOAK URL&gt;/realms/&lt;realm&gt;/clients/&lt;provider&gt;/default/&lt;client id&gt;</literal>. It will also
             return a new registration access token.
         </para>
         <para>
             To delete the Client Representation then do a HTTP DELETE to:
-            <literal>&lt;KEYCLOAK URL&gt;/clients/&lt;provider&gt;/default/&lt;client id&gt;</literal>
+            <literal>&lt;KEYCLOAK URL&gt;/realms/&lt;realm&gt;/clients/&lt;provider&gt;/default/&lt;client id&gt;</literal>
         </para>
     </section>
 
     <section>
         <title>Keycloak Adapter Configuration</title>
         <para>
-            The <default>installation</default> client registration provider can be used to retrieve the adapter configuration
+            The <literal>installation</literal> client registration provider can be used to retrieve the adapter configuration
             for a client. In addition to token authentication you can also authenticate with client credentials using
             HTTP basic authentication. To do this include the following header in the request:
 <programlisting><![CDATA[
@@ -138,7 +138,7 @@ Authorization: basic BASE64(client-id + ':' + client-secret)
         </para>
         <para>
             To retrieve the Adapter Configuration then do a HTTP GET to:
-            <literal>&lt;KEYCLOAK URL&gt;/clients/&lt;provider&gt;/installation/&lt;client id&gt;</literal>
+            <literal>&lt;KEYCLOAK URL&gt;//realms/&lt;realm&gt;clients/&lt;provider&gt;/installation/&lt;client id&gt;</literal>
         </para>
         <para>
             No authentication is required for public clients. This means that for the JavaScript adapter you can
@@ -146,23 +146,36 @@ Authorization: basic BASE64(client-id + ':' + client-secret)
         </para>
     </section>
 
-    <!--
     <section>
         <title>OpenID Connect Dynamic Client Registration</title>
         <para>
-            TODO
+            Keycloak implements <ulink url="https://openid.net/specs/openid-connect-registration-1_0.html">OpenID Connect Dynamic Client Registration</ulink>,
+            which extends <ulink url="https://tools.ietf.org/html/rfc7591">OAuth 2.0 Dynamic Client Registration Protocol</ulink> and
+            <ulink url="https://tools.ietf.org/html/rfc7592">OAuth 2.0 Dynamic Client Registration Management Protocol</ulink>.
+        </para>
+        <para>
+            The endpoint to use these specifications to register clients in Keycloak is:
+            <literal>&lt;KEYCLOAK URL&gt;/realms/&lt;realm&gt;/clients/&lt;provider&gt;/oidc[/&lt;client id&gt;]</literal>.
+        </para>
+        <para>
+            This endpoints can also be found in the OpenID Connect Discovery endpoint for the realm:
+            <literal>&lt;KEYCLOAK URL&gt;/realms/&lt;realm&gt;/.well-known/openid-configuration</literal>.
         </para>
     </section>
-    -->
 
-    <!--
     <section>
         <title>SAML Entity Descriptors</title>
         <para>
-            TODO
+            The SAML Entity Descriptor endpoint only supports using SAML v2 Entity Descriptors to create clients. It
+            doesn't support retrieving, updating or deleting clients. For those operations the Keycloak representation
+            endpoints should be used. When creating a client a Keycloak Client Representation is returned with details
+            about the created client, including a registration access token.
+        </para>
+        <para>
+            To create a client do a HTTP POST with the SAML Entity Descriptor to:
+            <literal>&lt;KEYCLOAK URL&gt;/realms/&lt;realm&gt;/clients/&lt;provider&gt;/saml2-entity-descriptor</literal>.
         </para>
     </section>
-    -->
 
     <section>
         <title>Client Registration Java API</title>
diff --git a/forms/common-freemarker/src/main/java/org/keycloak/freemarker/ExtendingThemeManager.java b/forms/common-freemarker/src/main/java/org/keycloak/freemarker/ExtendingThemeManager.java
index 020d349..0a253d1 100644
--- a/forms/common-freemarker/src/main/java/org/keycloak/freemarker/ExtendingThemeManager.java
+++ b/forms/common-freemarker/src/main/java/org/keycloak/freemarker/ExtendingThemeManager.java
@@ -153,6 +153,10 @@ public class ExtendingThemeManager implements ThemeProvider {
 
         private List<Theme> themes;
 
+        private Properties properties;
+
+        private ConcurrentHashMap<String, ConcurrentHashMap<Locale, Properties>> messages = new ConcurrentHashMap<>();
+
         public ExtendingTheme(List<Theme> themes) {
             this.themes = themes;
         }
@@ -229,28 +233,41 @@ public class ExtendingThemeManager implements ThemeProvider {
 
         @Override
         public Properties getMessages(String baseBundlename, Locale locale) throws IOException {
-            Properties messages = new Properties();
-            ListIterator<Theme> itr = themes.listIterator(themes.size());
-            while (itr.hasPrevious()) {
-                Properties m = itr.previous().getMessages(baseBundlename, locale);
-                if (m != null) {
-                    messages.putAll(m);
+            if (messages.get(baseBundlename) == null || messages.get(baseBundlename).get(locale) == null) {
+                Properties messages = new Properties();
+                ListIterator<Theme> itr = themes.listIterator(themes.size());
+                while (itr.hasPrevious()) {
+                    Properties m = itr.previous().getMessages(baseBundlename, locale);
+                    if (m != null) {
+                        messages.putAll(m);
+                    }
                 }
+
+                this.messages.putIfAbsent(baseBundlename, new ConcurrentHashMap<Locale, Properties>());
+                this.messages.get(baseBundlename).putIfAbsent(locale, messages);
+
+                return messages;
+            } else {
+                return messages.get(baseBundlename).get(locale);
             }
-            return messages;
         }
 
         @Override
         public Properties getProperties() throws IOException {
-            Properties properties = new Properties();
-            ListIterator<Theme> itr = themes.listIterator(themes.size());
-            while (itr.hasPrevious()) {
-                Properties p = itr.previous().getProperties();
-                if (p != null) {
-                    properties.putAll(p);
+            if (properties == null) {
+                Properties properties = new Properties();
+                ListIterator<Theme> itr = themes.listIterator(themes.size());
+                while (itr.hasPrevious()) {
+                    Properties p = itr.previous().getProperties();
+                    if (p != null) {
+                        properties.putAll(p);
+                    }
                 }
+                this.properties = properties;
+                return properties;
+            } else {
+                return properties;
             }
-            return properties;
         }
 
     }
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/messages/admin-messages_en.properties b/forms/common-themes/src/main/resources/theme/base/admin/messages/admin-messages_en.properties
index 09192ae..e274ca7 100644
--- a/forms/common-themes/src/main/resources/theme/base/admin/messages/admin-messages_en.properties
+++ b/forms/common-themes/src/main/resources/theme/base/admin/messages/admin-messages_en.properties
@@ -271,7 +271,7 @@ client-certificate-import=Client Certificate Import
 import-client-certificate=Import Client Certificate
 jwt-import.key-alias.tooltip=Archive alias for your certificate.
 secret=Secret
-regenerate-secret=Regenerate Secretsecret=Secret
+regenerate-secret=Regenerate Secret
 registrationAccessToken=Registration access token
 registrationAccessToken.regenerate=Regenerate registration access token
 registrationAccessToken.tooltip=The registration access token provides access for clients to the client registration service.
diff --git a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/otp-policy.html b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/otp-policy.html
index 1f8890e..eaaf811 100755
--- a/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/otp-policy.html
+++ b/forms/common-themes/src/main/resources/theme/base/admin/resources/partials/otp-policy.html
@@ -51,18 +51,18 @@
             <kc-tooltip>How far ahead should the server look just in case the token generator and server are out of time sync or counter sync?</kc-tooltip>
         </div>
 
-        <div class="form-group" data-ng-show="realm.otpPolicyType == 'hotp'">
+        <div class="form-group" data-ng-if="realm.otpPolicyType == 'hotp'">
             <label class="col-md-2 control-label" for="counter">Initial Counter</label>
             <div class="col-md-6">
-                <input class="form-control" type="number" required min="1" max="120" id="counter" name="counter" data-ng-model="realm.otpPolicyInitialCounter" autofocus>
+                <input class="form-control" type="number" data-ng-required="realm.otpPolicyType == 'hotp'" min="1" max="120" id="counter" name="counter" data-ng-model="realm.otpPolicyInitialCounter" autofocus>
             </div>
             <kc-tooltip>What should the initial counter value be?</kc-tooltip>
         </div>
 
-        <div class="form-group" data-ng-show="realm.otpPolicyType == 'totp'">
+        <div class="form-group" data-ng-if="realm.otpPolicyType == 'totp'">
             <label class="col-md-2 control-label" for="counter">OTP Token Period</label>
             <div class="col-md-6">
-                <input class="form-control" type="number" required min="1" max="120" id="period" name="period" data-ng-model="realm.otpPolicyPeriod">
+                <input class="form-control" type="number" data-ng-required="realm.otpPolicyType == 'totp'" min="1" max="120" id="period" name="period" data-ng-model="realm.otpPolicyPeriod">
             </div>
             <kc-tooltip>How many seconds should an OTP token be valid? Defaults to 30 seconds.</kc-tooltip>
         </div>
diff --git a/model/api/src/main/java/org/keycloak/models/PasswordPolicy.java b/model/api/src/main/java/org/keycloak/models/PasswordPolicy.java
index aff7d37..3674334 100755
--- a/model/api/src/main/java/org/keycloak/models/PasswordPolicy.java
+++ b/model/api/src/main/java/org/keycloak/models/PasswordPolicy.java
@@ -76,6 +76,8 @@ public class PasswordPolicy implements Serializable {
                 list.add(new PasswordHistory(arg));
             } else if (name.equals(ForceExpiredPasswordChange.NAME)) {
                 list.add(new ForceExpiredPasswordChange(arg));
+            } else {
+                throw new IllegalArgumentException("Unsupported policy");
             }
         }
         return list;
diff --git a/model/api/src/main/java/org/keycloak/models/utils/CredentialValidation.java b/model/api/src/main/java/org/keycloak/models/utils/CredentialValidation.java
index 7ce15d8..af9b6b5 100755
--- a/model/api/src/main/java/org/keycloak/models/utils/CredentialValidation.java
+++ b/model/api/src/main/java/org/keycloak/models/utils/CredentialValidation.java
@@ -51,6 +51,10 @@ public class CredentialValidation {
     }
 
     public static boolean validateHashedCredential(RealmModel realm, UserModel user, String unhashedCredValue, UserCredentialValueModel credential) {
+        if(unhashedCredValue == null){
+            return false;
+        }
+
         boolean validated = new Pbkdf2PasswordEncoder(credential.getSalt()).verify(unhashedCredValue, credential.getValue(), credential.getHashIterations());
         if (validated) {
             int iterations = hashIterations(realm);
diff --git a/model/api/src/main/java/org/keycloak/models/utils/RepresentationToModel.java b/model/api/src/main/java/org/keycloak/models/utils/RepresentationToModel.java
index dde4462..3916fd1 100755
--- a/model/api/src/main/java/org/keycloak/models/utils/RepresentationToModel.java
+++ b/model/api/src/main/java/org/keycloak/models/utils/RepresentationToModel.java
@@ -69,12 +69,12 @@ public class RepresentationToModel {
     private static Logger logger = Logger.getLogger(RepresentationToModel.class);
     public static OTPPolicy toPolicy(RealmRepresentation rep) {
         OTPPolicy policy = new OTPPolicy();
-        policy.setType(rep.getOtpPolicyType());
-        policy.setLookAheadWindow(rep.getOtpPolicyLookAheadWindow());
-        policy.setInitialCounter(rep.getOtpPolicyInitialCounter());
-        policy.setAlgorithm(rep.getOtpPolicyAlgorithm());
-        policy.setDigits(rep.getOtpPolicyDigits());
-        policy.setPeriod(rep.getOtpPolicyPeriod());
+        if (rep.getOtpPolicyType() != null) policy.setType(rep.getOtpPolicyType());
+        if (rep.getOtpPolicyLookAheadWindow() != null) policy.setLookAheadWindow(rep.getOtpPolicyLookAheadWindow());
+        if (rep.getOtpPolicyInitialCounter() != null) policy.setInitialCounter(rep.getOtpPolicyInitialCounter());
+        if (rep.getOtpPolicyAlgorithm() != null) policy.setAlgorithm(rep.getOtpPolicyAlgorithm());
+        if (rep.getOtpPolicyDigits() != null) policy.setDigits(rep.getOtpPolicyDigits());
+        if (rep.getOtpPolicyPeriod() != null) policy.setPeriod(rep.getOtpPolicyPeriod());
         return policy;
 
     }
diff --git a/model/api/src/test/java/org/keycloak/models/PasswordPolicyTest.java b/model/api/src/test/java/org/keycloak/models/PasswordPolicyTest.java
index df76588..8c662fb 100755
--- a/model/api/src/test/java/org/keycloak/models/PasswordPolicyTest.java
+++ b/model/api/src/test/java/org/keycloak/models/PasswordPolicyTest.java
@@ -83,6 +83,15 @@ public class PasswordPolicyTest {
         Assert.assertEquals("invalidPasswordNotUsernameMessage", policy.validate("jdoe", "jdoe").getMessage());
         Assert.assertNull(policy.validate("jdoe", "ab&d1234"));
     }
+
+    @Test
+    public void testInvalidPolicyName() {
+        try {
+            PasswordPolicy policy = new PasswordPolicy("noSuchPolicy");
+            Assert.fail("Expected exception");
+        } catch (IllegalArgumentException e) {
+        }
+    }
     
     @Test
     public void testRegexPatterns() {
diff --git a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/clientregistration/EntityDescriptorClientRegistrationProvider.java b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/clientregistration/EntityDescriptorClientRegistrationProvider.java
index 81c2df4..1ee3cd2 100644
--- a/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/clientregistration/EntityDescriptorClientRegistrationProvider.java
+++ b/saml/saml-protocol/src/main/java/org/keycloak/protocol/saml/clientregistration/EntityDescriptorClientRegistrationProvider.java
@@ -1,63 +1,35 @@
 package org.keycloak.protocol.saml.clientregistration;
 
-import org.jboss.logging.Logger;
-import org.keycloak.events.EventBuilder;
+import org.keycloak.exportimport.ClientDescriptionConverter;
 import org.keycloak.models.KeycloakSession;
-import org.keycloak.services.clientregistration.ClientRegistrationAuth;
-import org.keycloak.services.clientregistration.ClientRegistrationProvider;
+import org.keycloak.protocol.saml.EntityDescriptorDescriptionConverter;
+import org.keycloak.representations.idm.ClientRepresentation;
+import org.keycloak.services.clientregistration.AbstractClientRegistrationProvider;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.POST;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import java.net.URI;
 
 /**
  * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
  */
-public class EntityDescriptorClientRegistrationProvider implements ClientRegistrationProvider {
-
-    private static final Logger logger = Logger.getLogger(EntityDescriptorClientRegistrationProvider.class);
-
-    private KeycloakSession session;
-    private EventBuilder event;
-    private ClientRegistrationAuth auth;
+public class EntityDescriptorClientRegistrationProvider extends AbstractClientRegistrationProvider {
 
     public EntityDescriptorClientRegistrationProvider(KeycloakSession session) {
-        this.session = session;
-    }
-
-//    @POST
-//    @Consumes(MediaType.APPLICATION_XML)
-//    @Produces(MediaType.APPLICATION_JSON)
-//    public Response create(String descriptor) {
-//        event.event(EventType.CLIENT_REGISTER);
-//
-//        auth.requireCreate();
-//
-//        ClientRepresentation client = session.getProvider(ClientDescriptionConverter.class, EntityDescriptorDescriptionConverter.ID).convertToInternal(descriptor);
-//
-//        try {
-//            ClientModel clientModel = RepresentationToModel.createClient(session, session.getContext().getRealm(), client, true);
-//            client = ModelToRepresentation.toRepresentation(clientModel);
-//            URI uri = session.getContext().getUri().getAbsolutePathBuilder().path(clientModel.getId()).build();
-//
-//            logger.infov("Created client {0}", client.getClientId());
-//
-//            event.client(client.getClientId()).success();
-//
-//            return Response.created(uri).entity(client).build();
-//        } catch (ModelDuplicateException e) {
-//            return ErrorResponse.exists("Client " + client.getClientId() + " already exists");
-//        }
-//    }
-
-    @Override
-    public void close() {
-    }
-
-    @Override
-    public void setAuth(ClientRegistrationAuth auth) {
-        this.auth = auth;
+        super(session);
     }
 
-    @Override
-    public void setEvent(EventBuilder event) {
-        this.event = event;
+    @POST
+    @Consumes(MediaType.APPLICATION_XML)
+    @Produces(MediaType.APPLICATION_JSON)
+    public Response createSaml(String descriptor) {
+        ClientRepresentation client = session.getProvider(ClientDescriptionConverter.class, EntityDescriptorDescriptionConverter.ID).convertToInternal(descriptor);
+        client = create(client);
+        URI uri = session.getContext().getUri().getAbsolutePathBuilder().path(client.getClientId()).build();
+        return Response.created(uri).entity(client).build();
     }
 
 }
diff --git a/services/src/main/java/org/keycloak/authentication/authenticators/browser/AbstractUsernameFormAuthenticator.java b/services/src/main/java/org/keycloak/authentication/authenticators/browser/AbstractUsernameFormAuthenticator.java
index 0506f21..5afaa3d 100755
--- a/services/src/main/java/org/keycloak/authentication/authenticators/browser/AbstractUsernameFormAuthenticator.java
+++ b/services/src/main/java/org/keycloak/authentication/authenticators/browser/AbstractUsernameFormAuthenticator.java
@@ -148,24 +148,17 @@ public abstract class AbstractUsernameFormAuthenticator extends AbstractFormAuth
     public boolean validatePassword(AuthenticationFlowContext context, UserModel user, MultivaluedMap<String, String> inputData) {
         List<UserCredentialModel> credentials = new LinkedList<>();
         String password = inputData.getFirst(CredentialRepresentation.PASSWORD);
-        if (password == null || password.isEmpty()) {
-            invalidPassword(context, user);
-            return false;
-        }
         credentials.add(UserCredentialModel.password(password));
         boolean valid = context.getSession().users().validCredentials(context.getRealm(), user, credentials);
         if (!valid) {
-            invalidPassword(context, user);
+            context.getEvent().user(user);
+            context.getEvent().error(Errors.INVALID_USER_CREDENTIALS);
+            Response challengeResponse = invalidCredentials(context);
+            context.failureChallenge(AuthenticationFlowError.INVALID_CREDENTIALS, challengeResponse);
+            context.clearUser();
             return false;
         }
         return true;
     }
 
-    private void invalidPassword(AuthenticationFlowContext context, UserModel user) {
-        context.getEvent().user(user);
-        context.getEvent().error(Errors.INVALID_USER_CREDENTIALS);
-        Response challengeResponse = invalidCredentials(context);
-        context.failureChallenge(AuthenticationFlowError.INVALID_CREDENTIALS, challengeResponse);
-        context.clearUser();
-    }
 }
diff --git a/services/src/main/java/org/keycloak/authentication/authenticators/directgrant/ValidatePassword.java b/services/src/main/java/org/keycloak/authentication/authenticators/directgrant/ValidatePassword.java
index cff7f37..21aa18d 100755
--- a/services/src/main/java/org/keycloak/authentication/authenticators/directgrant/ValidatePassword.java
+++ b/services/src/main/java/org/keycloak/authentication/authenticators/directgrant/ValidatePassword.java
@@ -31,15 +31,6 @@ public class ValidatePassword extends AbstractDirectGrantAuthenticator {
         MultivaluedMap<String, String> inputData = context.getHttpRequest().getDecodedFormParameters();
         List<UserCredentialModel> credentials = new LinkedList<>();
         String password = inputData.getFirst(CredentialRepresentation.PASSWORD);
-        if (password == null || password.isEmpty()) {
-            if (context.getUser() != null) {
-                context.getEvent().user(context.getUser());
-            }
-            context.getEvent().error(Errors.INVALID_USER_CREDENTIALS);
-            Response challengeResponse = errorResponse(Response.Status.UNAUTHORIZED.getStatusCode(), "invalid_grant", "Invalid user credentials");
-            context.failure(AuthenticationFlowError.INVALID_USER, challengeResponse);
-            return;
-        }
         credentials.add(UserCredentialModel.password(password));
         boolean valid = context.getSession().users().validCredentials(context.getRealm(), context.getUser(), credentials);
         if (!valid) {
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/OIDCClientDescriptionConverter.java b/services/src/main/java/org/keycloak/protocol/oidc/OIDCClientDescriptionConverter.java
index 955dfe4..6caacd6 100644
--- a/services/src/main/java/org/keycloak/protocol/oidc/OIDCClientDescriptionConverter.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/OIDCClientDescriptionConverter.java
@@ -5,8 +5,7 @@ import org.keycloak.exportimport.ClientDescriptionConverter;
 import org.keycloak.exportimport.ClientDescriptionConverterFactory;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.KeycloakSessionFactory;
-import org.keycloak.models.utils.KeycloakModelUtils;
-import org.keycloak.protocol.oidc.representations.OIDCClientRepresentation;
+import org.keycloak.representations.oidc.OIDCClientRepresentation;
 import org.keycloak.representations.idm.ClientRepresentation;
 import org.keycloak.services.clientregistration.oidc.DescriptionConverter;
 import org.keycloak.util.JsonSerialization;
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/OIDCWellKnownProvider.java b/services/src/main/java/org/keycloak/protocol/oidc/OIDCWellKnownProvider.java
index 714c0d1..60e9f9d 100755
--- a/services/src/main/java/org/keycloak/protocol/oidc/OIDCWellKnownProvider.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/OIDCWellKnownProvider.java
@@ -4,6 +4,8 @@ import org.keycloak.OAuth2Constants;
 import org.keycloak.models.KeycloakSession;
 import org.keycloak.models.RealmModel;
 import org.keycloak.protocol.oidc.representations.OIDCConfigurationRepresentation;
+import org.keycloak.services.clientregistration.ClientRegistrationService;
+import org.keycloak.services.clientregistration.oidc.OIDCClientRegistrationProviderFactory;
 import org.keycloak.services.resources.RealmsResource;
 import org.keycloak.services.Urls;
 import org.keycloak.wellknown.WellKnownProvider;
@@ -48,6 +50,7 @@ public class OIDCWellKnownProvider implements WellKnownProvider {
         config.setUserinfoEndpoint(uriBuilder.clone().path(OIDCLoginProtocolService.class, "issueUserInfo").build(realm.getName(), OIDCLoginProtocol.LOGIN_PROTOCOL).toString());
         config.setLogoutEndpoint(uriBuilder.clone().path(OIDCLoginProtocolService.class, "logout").build(realm.getName(), OIDCLoginProtocol.LOGIN_PROTOCOL).toString());
         config.setJwksUri(uriBuilder.clone().path(OIDCLoginProtocolService.class, "certs").build(realm.getName(), OIDCLoginProtocol.LOGIN_PROTOCOL).toString());
+        config.setRegistrationEndpoint(RealmsResource.clientRegistrationUrl(uriInfo).path(ClientRegistrationService.class, "provider").build(realm.getName(), OIDCClientRegistrationProviderFactory.ID).toString());
 
         config.setIdTokenSigningAlgValuesSupported(DEFAULT_ID_TOKEN_SIGNING_ALG_VALUES_SUPPORTED);
         config.setResponseTypesSupported(DEFAULT_RESPONSE_TYPES_SUPPORTED);
diff --git a/services/src/main/java/org/keycloak/protocol/oidc/representations/OIDCConfigurationRepresentation.java b/services/src/main/java/org/keycloak/protocol/oidc/representations/OIDCConfigurationRepresentation.java
index 9245e58..0226331 100755
--- a/services/src/main/java/org/keycloak/protocol/oidc/representations/OIDCConfigurationRepresentation.java
+++ b/services/src/main/java/org/keycloak/protocol/oidc/representations/OIDCConfigurationRepresentation.java
@@ -7,7 +7,6 @@ import org.codehaus.jackson.annotate.JsonProperty;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-import java.util.Set;
 
 /**
  * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
@@ -48,6 +47,9 @@ public class OIDCConfigurationRepresentation {
     @JsonProperty("response_modes_supported")
     private List<String> responseModesSupported;
 
+    @JsonProperty("registration_endpoint")
+    private String registrationEndpoint;
+
     protected Map<String, Object> otherClaims = new HashMap<String, Object>();
 
     public String getIssuer() {
@@ -138,6 +140,14 @@ public class OIDCConfigurationRepresentation {
         this.responseModesSupported = responseModesSupported;
     }
 
+    public String getRegistrationEndpoint() {
+        return registrationEndpoint;
+    }
+
+    public void setRegistrationEndpoint(String registrationEndpoint) {
+        this.registrationEndpoint = registrationEndpoint;
+    }
+
     @JsonAnyGetter
     public Map<String, Object> getOtherClaims() {
         return otherClaims;
diff --git a/services/src/main/java/org/keycloak/services/clientregistration/AbstractClientRegistrationProvider.java b/services/src/main/java/org/keycloak/services/clientregistration/AbstractClientRegistrationProvider.java
new file mode 100644
index 0000000..0c95a37
--- /dev/null
+++ b/services/src/main/java/org/keycloak/services/clientregistration/AbstractClientRegistrationProvider.java
@@ -0,0 +1,125 @@
+package org.keycloak.services.clientregistration;
+
+import org.keycloak.events.EventBuilder;
+import org.keycloak.events.EventType;
+import org.keycloak.models.ClientInitialAccessModel;
+import org.keycloak.models.ClientModel;
+import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.ModelDuplicateException;
+import org.keycloak.models.utils.ModelToRepresentation;
+import org.keycloak.models.utils.RepresentationToModel;
+import org.keycloak.representations.idm.ClientRepresentation;
+import org.keycloak.services.ErrorResponseException;
+import org.keycloak.services.ForbiddenException;
+
+import javax.ws.rs.core.Response;
+
+/**
+ * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
+ */
+public abstract class AbstractClientRegistrationProvider implements ClientRegistrationProvider {
+
+    protected KeycloakSession session;
+    protected EventBuilder event;
+    protected ClientRegistrationAuth auth;
+
+    public AbstractClientRegistrationProvider(KeycloakSession session) {
+        this.session = session;
+    }
+
+    public ClientRepresentation create(ClientRepresentation client) {
+        event.event(EventType.CLIENT_REGISTER);
+
+        auth.requireCreate();
+
+        try {
+            ClientModel clientModel = RepresentationToModel.createClient(session, session.getContext().getRealm(), client, true);
+            if (client.getClientId() == null) {
+                clientModel.setClientId(clientModel.getId());
+            }
+
+            client = ModelToRepresentation.toRepresentation(clientModel);
+
+            String registrationAccessToken = ClientRegistrationTokenUtils.updateRegistrationAccessToken(session, clientModel);
+
+            client.setRegistrationAccessToken(registrationAccessToken);
+
+            if (auth.isInitialAccessToken()) {
+                ClientInitialAccessModel initialAccessModel = auth.getInitialAccessModel();
+                initialAccessModel.decreaseRemainingCount();
+            }
+
+            event.client(client.getClientId()).success();
+            return client;
+        } catch (ModelDuplicateException e) {
+            throw new ErrorResponseException(ErrorCodes.INVALID_CLIENT_METADATA, "Client Identifier in use", Response.Status.BAD_REQUEST);
+        }
+    }
+
+    public ClientRepresentation get(String clientId) {
+        event.event(EventType.CLIENT_INFO);
+
+        ClientModel client = session.getContext().getRealm().getClientByClientId(clientId);
+        auth.requireView(client);
+
+        ClientRepresentation rep = ModelToRepresentation.toRepresentation(client);
+
+        if (auth.isRegistrationAccessToken()) {
+            String registrationAccessToken = ClientRegistrationTokenUtils.updateRegistrationAccessToken(session, client);
+            rep.setRegistrationAccessToken(registrationAccessToken);
+        }
+
+        event.client(client.getClientId()).success();
+        return rep;
+    }
+
+    public ClientRepresentation update(String clientId, ClientRepresentation rep) {
+        event.event(EventType.CLIENT_UPDATE).client(clientId);
+
+        ClientModel client = session.getContext().getRealm().getClientByClientId(clientId);
+        auth.requireUpdate(client);
+
+        if (!client.getClientId().equals(rep.getClientId())) {
+            throw new ErrorResponseException(ErrorCodes.INVALID_CLIENT_METADATA, "Client Identifier modified", Response.Status.BAD_REQUEST);
+        }
+
+        RepresentationToModel.updateClient(rep, client);
+        rep = ModelToRepresentation.toRepresentation(client);
+
+        if (auth.isRegistrationAccessToken()) {
+            String registrationAccessToken = ClientRegistrationTokenUtils.updateRegistrationAccessToken(session, client);
+            rep.setRegistrationAccessToken(registrationAccessToken);
+        }
+
+        event.client(client.getClientId()).success();
+        return rep;
+    }
+
+    public void delete(String clientId) {
+        event.event(EventType.CLIENT_DELETE).client(clientId);
+
+        ClientModel client = session.getContext().getRealm().getClientByClientId(clientId);
+        auth.requireUpdate(client);
+
+        if (session.getContext().getRealm().removeClient(client.getId())) {
+            event.client(client.getClientId()).success();
+        } else {
+            throw new ForbiddenException();
+        }
+    }
+
+    @Override
+    public void setAuth(ClientRegistrationAuth auth) {
+        this.auth = auth;
+    }
+
+    @Override
+    public void setEvent(EventBuilder event) {
+        this.event = event;
+    }
+
+    @Override
+    public void close() {
+    }
+
+}
diff --git a/services/src/main/java/org/keycloak/services/clientregistration/ClientRegistrationService.java b/services/src/main/java/org/keycloak/services/clientregistration/ClientRegistrationService.java
index 0581388..621d5fb 100644
--- a/services/src/main/java/org/keycloak/services/clientregistration/ClientRegistrationService.java
+++ b/services/src/main/java/org/keycloak/services/clientregistration/ClientRegistrationService.java
@@ -25,7 +25,7 @@ public class ClientRegistrationService {
     }
 
     @Path("{provider}")
-    public Object getProvider(@PathParam("provider") String providerId) {
+    public Object provider(@PathParam("provider") String providerId) {
         checkSsl();
 
         ClientRegistrationProvider provider = session.getProvider(ClientRegistrationProvider.class, providerId);
diff --git a/services/src/main/java/org/keycloak/services/clientregistration/DefaultClientRegistrationProvider.java b/services/src/main/java/org/keycloak/services/clientregistration/DefaultClientRegistrationProvider.java
index 38d71f2..126d00a 100644
--- a/services/src/main/java/org/keycloak/services/clientregistration/DefaultClientRegistrationProvider.java
+++ b/services/src/main/java/org/keycloak/services/clientregistration/DefaultClientRegistrationProvider.java
@@ -2,14 +2,11 @@ package org.keycloak.services.clientregistration;
 
 import org.keycloak.events.EventBuilder;
 import org.keycloak.events.EventType;
-import org.keycloak.models.ClientInitialAccessModel;
 import org.keycloak.models.ClientModel;
 import org.keycloak.models.KeycloakSession;
-import org.keycloak.models.ModelDuplicateException;
 import org.keycloak.models.utils.ModelToRepresentation;
 import org.keycloak.models.utils.RepresentationToModel;
 import org.keycloak.representations.idm.ClientRepresentation;
-import org.keycloak.services.ErrorResponse;
 
 import javax.ws.rs.*;
 import javax.ws.rs.core.MediaType;
@@ -19,101 +16,41 @@ import java.net.URI;
 /**
  * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
  */
-public class DefaultClientRegistrationProvider implements ClientRegistrationProvider {
-
-    private KeycloakSession session;
-    private EventBuilder event;
-    private ClientRegistrationAuth auth;
+public class DefaultClientRegistrationProvider extends AbstractClientRegistrationProvider {
 
     public DefaultClientRegistrationProvider(KeycloakSession session) {
-        this.session = session;
+        super(session);
     }
 
     @POST
     @Consumes(MediaType.APPLICATION_JSON)
     @Produces(MediaType.APPLICATION_JSON)
-    public Response create(ClientRepresentation client) {
-        event.event(EventType.CLIENT_REGISTER);
-
-        auth.requireCreate();
-
-        try {
-            ClientModel clientModel = RepresentationToModel.createClient(session, session.getContext().getRealm(), client, true);
-            client = ModelToRepresentation.toRepresentation(clientModel);
-
-            String registrationAccessToken = ClientRegistrationTokenUtils.updateRegistrationAccessToken(session, clientModel);
-
-            client.setRegistrationAccessToken(registrationAccessToken);
-
-            URI uri = session.getContext().getUri().getAbsolutePathBuilder().path(clientModel.getId()).build();
-
-            if (auth.isInitialAccessToken()) {
-                ClientInitialAccessModel initialAccessModel = auth.getInitialAccessModel();
-                initialAccessModel.decreaseRemainingCount();
-            }
-
-            event.client(client.getClientId()).success();
-            return Response.created(uri).entity(client).build();
-        } catch (ModelDuplicateException e) {
-            return ErrorResponse.exists("Client " + client.getClientId() + " already exists");
-        }
+    public Response createDefault(ClientRepresentation client) {
+        client = create(client);
+        URI uri = session.getContext().getUri().getAbsolutePathBuilder().path(client.getClientId()).build();
+        return Response.created(uri).entity(client).build();
     }
 
     @GET
     @Path("{clientId}")
     @Produces(MediaType.APPLICATION_JSON)
-    public Response get(@PathParam("clientId") String clientId) {
-        event.event(EventType.CLIENT_INFO);
-
-        ClientModel client = session.getContext().getRealm().getClientByClientId(clientId);
-        auth.requireView(client);
-
-        ClientRepresentation rep = ModelToRepresentation.toRepresentation(client);
-
-        if (auth.isRegistrationAccessToken()) {
-            String registrationAccessToken = ClientRegistrationTokenUtils.updateRegistrationAccessToken(session, client);
-            rep.setRegistrationAccessToken(registrationAccessToken);
-        }
-
-        event.client(client.getClientId()).success();
-        return Response.ok(rep).build();
+    public Response getDefault(@PathParam("clientId") String clientId) {
+        ClientRepresentation client = get(clientId);
+        return Response.ok(client).build();
     }
 
     @PUT
     @Path("{clientId}")
     @Consumes(MediaType.APPLICATION_JSON)
-    public Response update(@PathParam("clientId") String clientId, ClientRepresentation rep) {
-        event.event(EventType.CLIENT_UPDATE).client(clientId);
-
-        ClientModel client = session.getContext().getRealm().getClientByClientId(clientId);
-        auth.requireUpdate(client);
-
-        RepresentationToModel.updateClient(rep, client);
-        rep = ModelToRepresentation.toRepresentation(client);
-
-        if (auth.isRegistrationAccessToken()) {
-            String registrationAccessToken = ClientRegistrationTokenUtils.updateRegistrationAccessToken(session, client);
-            rep.setRegistrationAccessToken(registrationAccessToken);
-        }
-
-        event.client(client.getClientId()).success();
-        return Response.ok(rep).build();
+    public Response updateDefault(@PathParam("clientId") String clientId, ClientRepresentation client) {
+        client = update(clientId, client);
+        return Response.ok(client).build();
     }
 
     @DELETE
     @Path("{clientId}")
-    public Response delete(@PathParam("clientId") String clientId) {
-        event.event(EventType.CLIENT_DELETE).client(clientId);
-
-        ClientModel client = session.getContext().getRealm().getClientByClientId(clientId);
-        auth.requireUpdate(client);
-
-        if (session.getContext().getRealm().removeClient(client.getId())) {
-            event.client(client.getClientId()).success();
-            return Response.ok().build();
-        } else {
-            return Response.status(Response.Status.NOT_FOUND).build();
-        }
+    public void deleteDefault(@PathParam("clientId") String clientId) {
+        delete(clientId);
     }
 
     @Override
diff --git a/services/src/main/java/org/keycloak/services/clientregistration/ErrorCodes.java b/services/src/main/java/org/keycloak/services/clientregistration/ErrorCodes.java
new file mode 100644
index 0000000..ed491de
--- /dev/null
+++ b/services/src/main/java/org/keycloak/services/clientregistration/ErrorCodes.java
@@ -0,0 +1,12 @@
+package org.keycloak.services.clientregistration;
+
+/**
+ * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
+ */
+public interface ErrorCodes {
+
+    String INVALID_REDIRECT_URI = "invalid_redirect_uri";
+
+    String INVALID_CLIENT_METADATA = "invalid_client_metadata";
+
+}
diff --git a/services/src/main/java/org/keycloak/services/clientregistration/oidc/DescriptionConverter.java b/services/src/main/java/org/keycloak/services/clientregistration/oidc/DescriptionConverter.java
index 1e0784c..a7f9f2c 100644
--- a/services/src/main/java/org/keycloak/services/clientregistration/oidc/DescriptionConverter.java
+++ b/services/src/main/java/org/keycloak/services/clientregistration/oidc/DescriptionConverter.java
@@ -1,8 +1,9 @@
 package org.keycloak.services.clientregistration.oidc;
 
-import org.keycloak.models.utils.KeycloakModelUtils;
-import org.keycloak.protocol.oidc.representations.OIDCClientRepresentation;
 import org.keycloak.representations.idm.ClientRepresentation;
+import org.keycloak.representations.oidc.OIDCClientRepresentation;
+
+import java.net.URI;
 
 /**
  * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
@@ -11,27 +12,22 @@ public class DescriptionConverter {
 
     public static ClientRepresentation toInternal(OIDCClientRepresentation clientOIDC) {
         ClientRepresentation client = new ClientRepresentation();
-        client.setClientId(KeycloakModelUtils.generateId());
+        client.setClientId(clientOIDC.getClientId());
         client.setName(clientOIDC.getClientName());
         client.setRedirectUris(clientOIDC.getRedirectUris());
         client.setBaseUrl(clientOIDC.getClientUri());
         return client;
     }
 
-    public static OIDCClientResponseRepresentation toExternalResponse(ClientRepresentation client) {
-        OIDCClientResponseRepresentation response = new OIDCClientResponseRepresentation();
+    public static OIDCClientRepresentation toExternalResponse(ClientRepresentation client, URI uri) {
+        OIDCClientRepresentation response = new OIDCClientRepresentation();
         response.setClientId(client.getClientId());
-
         response.setClientName(client.getName());
         response.setClientUri(client.getBaseUrl());
-
         response.setClientSecret(client.getSecret());
-        response.setClientSecretExpiresAt(0);
-
         response.setRedirectUris(client.getRedirectUris());
-
         response.setRegistrationAccessToken(client.getRegistrationAccessToken());
-
+        response.setRegistrationClientUri(uri.toString());
         return response;
     }
 
diff --git a/services/src/main/java/org/keycloak/services/clientregistration/oidc/OIDCClientRegistrationProvider.java b/services/src/main/java/org/keycloak/services/clientregistration/oidc/OIDCClientRegistrationProvider.java
index 961f28d..e60720b 100644
--- a/services/src/main/java/org/keycloak/services/clientregistration/oidc/OIDCClientRegistrationProvider.java
+++ b/services/src/main/java/org/keycloak/services/clientregistration/oidc/OIDCClientRegistrationProvider.java
@@ -1,72 +1,70 @@
 package org.keycloak.services.clientregistration.oidc;
 
-import org.jboss.logging.Logger;
+import org.keycloak.common.util.Time;
 import org.keycloak.events.EventBuilder;
 import org.keycloak.models.KeycloakSession;
+import org.keycloak.models.utils.KeycloakModelUtils;
+import org.keycloak.representations.oidc.OIDCClientRepresentation;
+import org.keycloak.representations.idm.ClientRepresentation;
+import org.keycloak.services.ErrorResponseException;
+import org.keycloak.services.clientregistration.AbstractClientRegistrationProvider;
 import org.keycloak.services.clientregistration.ClientRegistrationAuth;
-import org.keycloak.services.clientregistration.ClientRegistrationProvider;
+import org.keycloak.services.clientregistration.ErrorCodes;
+
+import javax.ws.rs.*;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import java.net.URI;
 
 /**
  * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
  */
-public class OIDCClientRegistrationProvider implements ClientRegistrationProvider {
+public class OIDCClientRegistrationProvider extends AbstractClientRegistrationProvider {
 
-    private static final Logger logger = Logger.getLogger(OIDCClientRegistrationProvider.class);
+    public OIDCClientRegistrationProvider(KeycloakSession session) {
+        super(session);
+    }
 
-    private KeycloakSession session;
-    private EventBuilder event;
-    private ClientRegistrationAuth auth;
+    @POST
+    @Consumes(MediaType.APPLICATION_JSON)
+    @Produces(MediaType.APPLICATION_JSON)
+    public Response createOIDC(OIDCClientRepresentation clientOIDC) {
+        if (clientOIDC.getClientId() != null) {
+            throw new ErrorResponseException(ErrorCodes.INVALID_CLIENT_METADATA, "Client Identifier included", Response.Status.BAD_REQUEST);
+        }
 
-    public OIDCClientRegistrationProvider(KeycloakSession session) {
-        this.session = session;
+        ClientRepresentation client = DescriptionConverter.toInternal(clientOIDC);
+        client = create(client);
+        URI uri = session.getContext().getUri().getAbsolutePathBuilder().path(client.getClientId()).build();
+        clientOIDC = DescriptionConverter.toExternalResponse(client, uri);
+        clientOIDC.setClientIdIssuedAt(Time.currentTime());
+        return Response.created(uri).entity(clientOIDC).build();
     }
 
-//    @POST
-//    @Consumes(MediaType.APPLICATION_JSON)
-//    @Produces(MediaType.APPLICATION_JSON)
-//    public Response create(OIDCClientRepresentation clientOIDC) {
-//        event.event(EventType.CLIENT_REGISTER);
-//
-//        auth.requireCreate();
-//
-//        ClientRepresentation client = DescriptionConverter.toInternal(clientOIDC);
-//
-//        try {
-//            ClientModel clientModel = RepresentationToModel.createClient(session, session.getContext().getRealm(), client, true);
-//
-//            client = ModelToRepresentation.toRepresentation(clientModel);
-//
-//            String registrationAccessToken = TokenGenerator.createRegistrationAccessToken();
-//
-//            clientModel.setRegistrationToken(registrationAccessToken);
-//
-//            URI uri = session.getContext().getUri().getAbsolutePathBuilder().path(clientModel.getId()).build();
-//
-//            logger.infov("Created client {0}", client.getClientId());
-//
-//            event.client(client.getClientId()).success();
-//
-//            OIDCClientResponseRepresentation response = DescriptionConverter.toExternalResponse(client);
-//
-//            response.setClientName(client.getName());
-//            response.setClientUri(client.getBaseUrl());
-//
-//            response.setClientSecret(client.getSecret());
-//            response.setClientSecretExpiresAt(0);
-//
-//            response.setRedirectUris(client.getRedirectUris());
-//
-//            response.setRegistrationAccessToken(registrationAccessToken);
-//            response.setRegistrationClientUri(uri.toString());
-//
-//            return Response.created(uri).entity(response).build();
-//        } catch (ModelDuplicateException e) {
-//            return ErrorResponse.exists("Client " + client.getClientId() + " already exists");
-//        }
-//    }
+    @GET
+    @Path("{clientId}")
+    @Produces(MediaType.APPLICATION_JSON)
+    public Response getOIDC(@PathParam("clientId") String clientId) {
+        ClientRepresentation client = get(clientId);
+        OIDCClientRepresentation clientOIDC = DescriptionConverter.toExternalResponse(client, session.getContext().getUri().getRequestUri());
+        return Response.ok(clientOIDC).build();
+    }
 
-    @Override
-    public void close() {
+    @PUT
+    @Path("{clientId}")
+    @Consumes(MediaType.APPLICATION_JSON)
+    public Response updateOIDC(@PathParam("clientId") String clientId, OIDCClientRepresentation clientOIDC) {
+        ClientRepresentation client = DescriptionConverter.toInternal(clientOIDC);
+        client = update(clientId, client);
+        URI uri = session.getContext().getUri().getAbsolutePathBuilder().path(client.getClientId()).build();
+        clientOIDC = DescriptionConverter.toExternalResponse(client, uri);
+        return Response.ok(clientOIDC).build();
+    }
+
+    @DELETE
+    @Path("{clientId}")
+    public void deleteOIDC(@PathParam("clientId") String clientId) {
+        delete(clientId);
     }
 
     @Override
@@ -79,4 +77,8 @@ public class OIDCClientRegistrationProvider implements ClientRegistrationProvide
         this.event = event;
     }
 
+    @Override
+    public void close() {
+    }
+
 }
diff --git a/services/src/main/java/org/keycloak/services/clientregistration/oidc/OIDCClientRegistrationProviderFactory.java b/services/src/main/java/org/keycloak/services/clientregistration/oidc/OIDCClientRegistrationProviderFactory.java
index 6f112f8..0144e79 100644
--- a/services/src/main/java/org/keycloak/services/clientregistration/oidc/OIDCClientRegistrationProviderFactory.java
+++ b/services/src/main/java/org/keycloak/services/clientregistration/oidc/OIDCClientRegistrationProviderFactory.java
@@ -11,6 +11,8 @@ import org.keycloak.services.clientregistration.ClientRegistrationProviderFactor
  */
 public class OIDCClientRegistrationProviderFactory implements ClientRegistrationProviderFactory {
 
+    public static final String ID = "openid-connect";
+
     @Override
     public ClientRegistrationProvider create(KeycloakSession session) {
         return new OIDCClientRegistrationProvider(session);
@@ -30,7 +32,7 @@ public class OIDCClientRegistrationProviderFactory implements ClientRegistration
 
     @Override
     public String getId() {
-        return "openid-connect";
+        return ID;
     }
 
 }
diff --git a/services/src/main/java/org/keycloak/services/resources/admin/RealmAdminResource.java b/services/src/main/java/org/keycloak/services/resources/admin/RealmAdminResource.java
index d874d1e..90eab4a 100755
--- a/services/src/main/java/org/keycloak/services/resources/admin/RealmAdminResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/admin/RealmAdminResource.java
@@ -236,7 +236,7 @@ public class RealmAdminResource {
         } catch (ModelDuplicateException e) {
             throw e;
         } catch (Exception e) {
-            logger.error(e);
+            logger.error(e.getMessage(), e);
             return ErrorResponse.error("Failed to update " + rep.getRealm() + " Realm.", Response.Status.INTERNAL_SERVER_ERROR);
         }
     }
diff --git a/services/src/main/java/org/keycloak/services/resources/RealmsResource.java b/services/src/main/java/org/keycloak/services/resources/RealmsResource.java
index 4b5e4f2..cc1e49a 100755
--- a/services/src/main/java/org/keycloak/services/resources/RealmsResource.java
+++ b/services/src/main/java/org/keycloak/services/resources/RealmsResource.java
@@ -59,6 +59,10 @@ public class RealmsResource {
         return uriInfo.getBaseUriBuilder().path(RealmsResource.class).path(RealmsResource.class, "getProtocol");
     }
 
+    public static UriBuilder clientRegistrationUrl(UriInfo uriInfo) {
+        return uriInfo.getBaseUriBuilder().path(RealmsResource.class).path(RealmsResource.class, "getClientsService");
+    }
+
     public static UriBuilder brokerUrl(UriInfo uriInfo) {
         return uriInfo.getBaseUriBuilder().path(RealmsResource.class).path(RealmsResource.class, "getBrokerService");
     }
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/admin/RealmTest.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/admin/RealmTest.java
index bb33515..42870a6 100644
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/admin/RealmTest.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/admin/RealmTest.java
@@ -180,7 +180,6 @@ public class RealmTest extends AbstractClientTest {
         String description = IOUtils.toString(getClass().getResourceAsStream("/client-descriptions/client-oidc.json"));
 
         ClientRepresentation converted = realm.convertClientDescription(description);
-        assertEquals(36, converted.getClientId().length());
         assertEquals(1, converted.getRedirectUris().size());
         assertEquals("http://localhost", converted.getRedirectUris().get(0));
     }
diff --git a/testsuite/integration/src/test/java/org/keycloak/testsuite/KeycloakServer.java b/testsuite/integration/src/test/java/org/keycloak/testsuite/KeycloakServer.java
index 126d0e5..28f0915 100755
--- a/testsuite/integration/src/test/java/org/keycloak/testsuite/KeycloakServer.java
+++ b/testsuite/integration/src/test/java/org/keycloak/testsuite/KeycloakServer.java
@@ -170,6 +170,10 @@ public class KeycloakServer {
                 System.setProperty("keycloak.theme.cacheTemplates", "false");
             }
 
+            if (!System.getProperties().containsKey("keycloak.theme.cacheThemes")) {
+                System.setProperty("keycloak.theme.cacheThemes", "false");
+            }
+
             if (!System.getProperties().containsKey("keycloak.theme.staticMaxAge")) {
                 System.setProperty("keycloak.theme.staticMaxAge", "-1");
             }
diff --git a/testsuite/integration-arquillian/tests/adapters/as7/pom.xml b/testsuite/integration-arquillian/tests/adapters/as7/pom.xml
index 313c154..15b575c 100644
--- a/testsuite/integration-arquillian/tests/adapters/as7/pom.xml
+++ b/testsuite/integration-arquillian/tests/adapters/as7/pom.xml
@@ -25,14 +25,13 @@
             <type>zip</type>
         </dependency>
         <dependency>
-            <groupId>org.keycloak</groupId>
-            <artifactId>keycloak-as7-adapter-dist</artifactId>
-            <type>zip</type>
+            <groupId>org.wildfly</groupId>
+            <artifactId>wildfly-arquillian-container-managed</artifactId>
         </dependency>
         <dependency>
-            <groupId>org.jboss.as</groupId>
-            <artifactId>jboss-as-arquillian-container-managed</artifactId>
-            <version>7.2.0.Final</version>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-eap6-adapter-dist</artifactId>
+            <type>zip</type>
         </dependency>
     </dependencies>
 
@@ -67,18 +66,20 @@
                                 <artifactItem>
                                     <groupId>org.keycloak</groupId>
                                     <artifactId>keycloak-as7-adapter-dist</artifactId>
+                                    <version>${project.version}</version>
                                     <type>zip</type>
                                     <outputDirectory>${adapter.libs.as7}</outputDirectory>
                                 </artifactItem>
                             </artifactItems>
-                            <overWriteIfNewer>true</overWriteIfNewer>
                         </configuration>
                     </execution>
                 </executions>
             </plugin>
+            
             <plugin>
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-surefire-plugin</artifactId>
+                <version>2.18.1</version>
                 <configuration>
                     <systemPropertyVariables>
                         <app.server.as7>true</app.server.as7>
@@ -90,7 +91,6 @@
         </plugins>
     </build>
     
-    
     <profiles>
         <profile>
             <id>adapter-libs-provided</id>
@@ -133,5 +133,4 @@
             </build>
         </profile>
     </profiles>        
-    
 </project>
diff --git a/testsuite/integration-arquillian/tests/adapters/as7/src/main/xslt/arquillian.xsl b/testsuite/integration-arquillian/tests/adapters/as7/src/main/xslt/arquillian.xsl
index 8970850..9ba1e94 100644
--- a/testsuite/integration-arquillian/tests/adapters/as7/src/main/xslt/arquillian.xsl
+++ b/testsuite/integration-arquillian/tests/adapters/as7/src/main/xslt/arquillian.xsl
@@ -18,6 +18,7 @@
                     <property name="jbossHome">${app.server.as7.home}</property>
                     <property name="javaVmArguments">-Djboss.socket.binding.port-offset=${app.server.port.offset} -Xms64m -Xmx512m -XX:MaxPermSize=256m ${adapter.test.props}</property>
                     <property name="managementAddress">localhost</property>
+                    <property name="managementProtocol">remote</property>
                     <property name="managementPort">${app.server.management.port.jmx}</property>
                 </configuration>
             </container>
diff --git a/testsuite/integration-arquillian/tests/adapters/as7/src/test/java/org/keycloak/testsuite/adapter/servlet/AS7DemoServletsAdapterTest.java b/testsuite/integration-arquillian/tests/adapters/as7/src/test/java/org/keycloak/testsuite/adapter/servlet/AS7DemoServletsAdapterTest.java
index f0258b2..1a4a68c 100644
--- a/testsuite/integration-arquillian/tests/adapters/as7/src/test/java/org/keycloak/testsuite/adapter/servlet/AS7DemoServletsAdapterTest.java
+++ b/testsuite/integration-arquillian/tests/adapters/as7/src/test/java/org/keycloak/testsuite/adapter/servlet/AS7DemoServletsAdapterTest.java
@@ -1,5 +1,6 @@
 package org.keycloak.testsuite.adapter.servlet;
 
+import org.keycloak.testsuite.arquillian.annotation.AdapterLibsLocationProperty;
 import org.keycloak.testsuite.arquillian.annotation.AppServerContainer;
 
 /**
@@ -7,6 +8,7 @@ import org.keycloak.testsuite.arquillian.annotation.AppServerContainer;
  * @author tkyjovsk
  */
 @AppServerContainer("app-server-as7")
+@AdapterLibsLocationProperty("adapter.libs.as7")
 public class AS7DemoServletsAdapterTest extends AbstractDemoServletsAdapterTest {
 
 }
diff --git a/testsuite/integration-arquillian/tests/adapters/as7/src/test/java/org/keycloak/testsuite/adapter/servlet/AS7SessionServletAdapterTest.java b/testsuite/integration-arquillian/tests/adapters/as7/src/test/java/org/keycloak/testsuite/adapter/servlet/AS7SessionServletAdapterTest.java
index 9362ecd..4b88033 100644
--- a/testsuite/integration-arquillian/tests/adapters/as7/src/test/java/org/keycloak/testsuite/adapter/servlet/AS7SessionServletAdapterTest.java
+++ b/testsuite/integration-arquillian/tests/adapters/as7/src/test/java/org/keycloak/testsuite/adapter/servlet/AS7SessionServletAdapterTest.java
@@ -1,5 +1,6 @@
 package org.keycloak.testsuite.adapter.servlet;
 
+import org.keycloak.testsuite.arquillian.annotation.AdapterLibsLocationProperty;
 import org.keycloak.testsuite.arquillian.annotation.AppServerContainer;
 
 /**
@@ -7,6 +8,7 @@ import org.keycloak.testsuite.arquillian.annotation.AppServerContainer;
  * @author tkyjovsk
  */
 @AppServerContainer("app-server-as7")
+@AdapterLibsLocationProperty("adapter.libs.as7")
 public class AS7SessionServletAdapterTest extends AbstractSessionServletAdapterTest {
 
 }
diff --git a/testsuite/integration-arquillian/tests/adapters/eap6/pom.xml b/testsuite/integration-arquillian/tests/adapters/eap6/pom.xml
new file mode 100644
index 0000000..433ca63
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/adapters/eap6/pom.xml
@@ -0,0 +1,135 @@
+<?xml version="1.0"?>
+<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+    <parent>
+        <groupId>org.keycloak.testsuite</groupId>
+        <artifactId>integration-arquillian-tests-adapters</artifactId>
+        <version>1.7.0.Final-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>integration-arquillian-adapters-eap6</artifactId>
+    <name>Adapter Tests on EAP 6</name>
+    
+    <properties>
+        <app.server.eap6.home>${containers.home}/jboss-eap-6.4</app.server.eap6.home>
+        <adapter.libs.eap6>${containers.home}/keycloak-eap6-adapter-dist</adapter.libs.eap6>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.jboss.as</groupId>
+            <artifactId>jboss-as-dist</artifactId>
+            <version>${jboss.version}</version>
+            <type>zip</type>
+        </dependency>
+        <dependency>
+            <groupId>org.wildfly</groupId>
+            <artifactId>wildfly-arquillian-container-managed</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.keycloak</groupId>
+            <artifactId>keycloak-eap6-adapter-dist</artifactId>
+            <type>zip</type>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-deploy-plugin</artifactId>
+                <configuration>
+                    <skip>true</skip>
+                </configuration>
+            </plugin>  
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-dependency-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>unpack-as7-and-adapter</id>
+                        <phase>generate-resources</phase>
+                        <goals>
+                            <goal>unpack</goal>
+                        </goals>
+                        <configuration>
+                            <artifactItems>
+                                <artifactItem>
+                                    <groupId>org.jboss.as</groupId>
+                                    <artifactId>jboss-as-dist</artifactId>
+                                    <version>${jboss.version}</version>
+                                    <type>zip</type>
+                                    <outputDirectory>${containers.home}</outputDirectory>
+                                </artifactItem>
+                                <artifactItem>
+                                    <groupId>org.keycloak</groupId>
+                                    <artifactId>keycloak-eap6-adapter-dist</artifactId>
+                                    <version>${project.version}</version>
+                                    <type>zip</type>
+                                    <outputDirectory>${adapter.libs.eap6}</outputDirectory>
+                                </artifactItem>
+                            </artifactItems>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+            
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-surefire-plugin</artifactId>
+                <version>2.18.1</version>
+                <configuration>
+                    <systemPropertyVariables>
+                        <app.server.eap6>true</app.server.eap6>
+                        <app.server.eap6.home>${app.server.eap6.home}</app.server.eap6.home>
+                        <adapter.libs.eap6>${adapter.libs.eap6}</adapter.libs.eap6>
+                    </systemPropertyVariables>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+    
+    <profiles>
+        <profile>
+            <id>adapter-libs-provided</id>
+            <activation>    
+                <property>
+                    <name>!adapter.libs.bundled</name>
+                </property>
+            </activation>
+            <properties>
+                <adapter.libs.eap6>${app.server.eap6.home}</adapter.libs.eap6>
+            </properties>
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.codehaus.mojo</groupId>
+                        <artifactId>xml-maven-plugin</artifactId>
+                        <executions>
+                            <execution>
+                                <id>configure-adapter-subsystem</id>
+                                <phase>process-resources</phase>
+                                <goals>
+                                    <goal>transform</goal>
+                                </goals>
+                                <configuration>
+                                    <transformationSets>
+                                        <transformationSet>
+                                            <dir>${app.server.eap6.home}/standalone/configuration</dir>
+                                            <includes>
+                                                <include>standalone.xml</include>
+                                            </includes>
+                                            <stylesheet>src/main/xslt/standalone.xsl</stylesheet>
+                                            <outputDir>${app.server.eap6.home}/standalone/configuration</outputDir>
+                                        </transformationSet>
+                                    </transformationSets>
+                                </configuration>
+                            </execution>
+                        </executions>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+    </profiles>        
+</project>
diff --git a/testsuite/integration-arquillian/tests/adapters/eap6/src/main/xslt/arquillian.xsl b/testsuite/integration-arquillian/tests/adapters/eap6/src/main/xslt/arquillian.xsl
new file mode 100644
index 0000000..fbfd50d
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/adapters/eap6/src/main/xslt/arquillian.xsl
@@ -0,0 +1,37 @@
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+                xmlns:xalan="http://xml.apache.org/xalan"
+                xmlns:a="http://jboss.org/schema/arquillian"
+                version="2.0"
+                exclude-result-prefixes="xalan a">
+
+    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" xalan:indent-amount="4" standalone="no"/>
+    <xsl:strip-space elements="*"/>
+
+    <xsl:template match="/a:arquillian">
+        <xsl:copy>
+            <xsl:apply-templates select="node()|@*"/>
+            
+            <container qualifier="app-server-eap6" mode="manual" >
+                <configuration>
+                    <property name="enabled">${app.server.eap6}</property>
+                    <property name="adapterImplClass">org.jboss.as.arquillian.container.managed.ManagedDeployableContainer</property>
+                    <property name="jbossHome">${app.server.eap6.home}</property>
+                    <property name="javaVmArguments">-Djboss.socket.binding.port-offset=${app.server.port.offset} -Xms64m -Xmx512m -XX:MaxPermSize=256m ${adapter.test.props}</property>
+                    <property name="managementAddress">localhost</property>
+                    <property name="managementProtocol">remote</property>
+                    <property name="managementPort">${app.server.management.port.jmx}</property>
+                </configuration>
+            </container>
+
+        </xsl:copy>
+    </xsl:template>
+    
+
+    <xsl:template match="@*|node()">
+        <xsl:copy>
+            <xsl:apply-templates select="@*|node()" />
+        </xsl:copy>
+    </xsl:template>
+    
+
+</xsl:stylesheet>
\ No newline at end of file
diff --git a/testsuite/integration-arquillian/tests/adapters/eap6/src/main/xslt/standalone.xsl b/testsuite/integration-arquillian/tests/adapters/eap6/src/main/xslt/standalone.xsl
new file mode 100644
index 0000000..fb3612b
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/adapters/eap6/src/main/xslt/standalone.xsl
@@ -0,0 +1,51 @@
+<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+                xmlns:xalan="http://xml.apache.org/xalan"
+                xmlns:j="urn:jboss:domain:1.7"
+                xmlns:ds="urn:jboss:domain:datasources:1.2"
+                xmlns:k="urn:jboss:domain:keycloak:1.1"
+                xmlns:sec="urn:jboss:domain:security:1.2"
+                version="2.0"
+                exclude-result-prefixes="xalan j ds k sec">
+
+    <xsl:param name="config"/>
+
+    <xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes" xalan:indent-amount="4" standalone="no"/>
+    <xsl:strip-space elements="*"/>
+
+    <xsl:template match="//j:extensions">
+        <xsl:copy>
+            <xsl:apply-templates select="node()|@*"/>
+            <extension module="org.keycloak.keycloak-adapter-subsystem"/>
+        </xsl:copy>
+    </xsl:template>
+
+    <xsl:template match="//j:profile">
+        <xsl:copy>
+            <xsl:apply-templates select="node()|@*"/>
+            <subsystem xmlns="urn:jboss:domain:keycloak:1.1"/>
+        </xsl:copy>
+    </xsl:template>
+
+    <xsl:template match="//sec:security-domains">
+        <xsl:copy>
+            <xsl:apply-templates select="node()[name(.)='security-domain']"/>
+            <security-domain name="keycloak">
+                <authentication>
+                    <login-module code="org.keycloak.adapters.jboss.KeycloakLoginModule" flag="required"/>
+                </authentication>
+            </security-domain>
+            <security-domain name="sp" cache-type="default">
+                <authentication>
+                    <login-module code="org.picketlink.identity.federation.bindings.wildfly.SAML2LoginModule" flag="required"/>
+                </authentication>
+            </security-domain>
+        </xsl:copy>
+    </xsl:template>
+
+    <xsl:template match="@*|node()">
+        <xsl:copy>
+            <xsl:apply-templates select="@*|node()" />
+        </xsl:copy>
+    </xsl:template>
+
+</xsl:stylesheet>
\ No newline at end of file
diff --git a/testsuite/integration-arquillian/tests/adapters/eap6/src/test/java/org/keycloak/testsuite/adapter/servlet/EAP6DemoServletsAdapterTest.java b/testsuite/integration-arquillian/tests/adapters/eap6/src/test/java/org/keycloak/testsuite/adapter/servlet/EAP6DemoServletsAdapterTest.java
new file mode 100644
index 0000000..5eb363e
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/adapters/eap6/src/test/java/org/keycloak/testsuite/adapter/servlet/EAP6DemoServletsAdapterTest.java
@@ -0,0 +1,14 @@
+package org.keycloak.testsuite.adapter.servlet;
+
+import org.keycloak.testsuite.arquillian.annotation.AdapterLibsLocationProperty;
+import org.keycloak.testsuite.arquillian.annotation.AppServerContainer;
+
+/**
+ *
+ * @author tkyjovsk
+ */
+@AppServerContainer("app-server-eap6")
+@AdapterLibsLocationProperty("adapter.libs.eap6")
+public class EAP6DemoServletsAdapterTest extends AbstractDemoServletsAdapterTest {
+
+}
diff --git a/testsuite/integration-arquillian/tests/adapters/eap6/src/test/java/org/keycloak/testsuite/adapter/servlet/EAP6SessionServletAdapterTest.java b/testsuite/integration-arquillian/tests/adapters/eap6/src/test/java/org/keycloak/testsuite/adapter/servlet/EAP6SessionServletAdapterTest.java
new file mode 100644
index 0000000..c187910
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/adapters/eap6/src/test/java/org/keycloak/testsuite/adapter/servlet/EAP6SessionServletAdapterTest.java
@@ -0,0 +1,14 @@
+package org.keycloak.testsuite.adapter.servlet;
+
+import org.keycloak.testsuite.arquillian.annotation.AdapterLibsLocationProperty;
+import org.keycloak.testsuite.arquillian.annotation.AppServerContainer;
+
+/**
+ *
+ * @author tkyjovsk
+ */
+@AppServerContainer("app-server-eap6")
+@AdapterLibsLocationProperty("adapter.libs.eap6")
+public class EAP6SessionServletAdapterTest extends AbstractSessionServletAdapterTest {
+
+}
diff --git a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/WaitUtils.java b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/WaitUtils.java
index 7b0fdb1..00aaed3 100644
--- a/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/WaitUtils.java
+++ b/testsuite/integration-arquillian/tests/base/src/main/java/org/keycloak/testsuite/util/WaitUtils.java
@@ -17,6 +17,7 @@
  */
 package org.keycloak.testsuite.util;
 
+import java.util.concurrent.TimeUnit;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 import static org.jboss.arquillian.graphene.Graphene.waitAjax;
@@ -31,24 +32,35 @@ import org.openqa.selenium.WebElement;
  */
 public final class WaitUtils {
 
+    public static final String PAGELOAD_TIMEOUT_PROP = "pageload.timeout";
+    public static final String IMPLICIT_TIMEOUT_PROP = "implicit.timeout";
+    public static final String SCRIPT_TIMEOUT_PROP = "script.timeout";
+    public static final String POLLING_INTERVAL_PROP = "polling.interval";
+
+    public static final Integer PAGELOAD_TIMEOUT = Integer.parseInt(System.getProperty(PAGELOAD_TIMEOUT_PROP, "5000"));
+    public static final Integer IMPLICIT_TIMEOUT = Integer.parseInt(System.getProperty(IMPLICIT_TIMEOUT_PROP, "3000"));
+    public static final Integer SCRIPT_TIMEOUT = Integer.parseInt(System.getProperty(SCRIPT_TIMEOUT_PROP, "3000"));
+
+    public static final Integer POLLING_INTERVAL = Integer.parseInt(System.getProperty(POLLING_INTERVAL_PROP, "1000"));
+
     public static void waitAjaxForElement(WebElement element) {
-        waitAjax().until()
-                .element(element).is().present();
+        waitAjax().withTimeout(SCRIPT_TIMEOUT, TimeUnit.MILLISECONDS).pollingEvery(POLLING_INTERVAL, TimeUnit.MILLISECONDS)
+                .until().element(element).is().present();
     }
 
     public static void waitAjaxForElementNotPresent(WebElement element) {
-        waitAjax().until()
-                .element(element).is().not().present();
+        waitAjax().withTimeout(SCRIPT_TIMEOUT, TimeUnit.MILLISECONDS).pollingEvery(POLLING_INTERVAL, TimeUnit.MILLISECONDS)
+                .until().element(element).is().not().present();
     }
 
     public static void waitAjaxForElementNotVisible(WebElement element) {
-        waitAjax().until()
-                .element(element).is().not().visible();
+        waitAjax().withTimeout(SCRIPT_TIMEOUT, TimeUnit.MILLISECONDS).pollingEvery(POLLING_INTERVAL, TimeUnit.MILLISECONDS)
+                .until().element(element).is().not().visible();
     }
 
     public static void waitGuiForElement(By element, String message) {
-        waitGui().until(message)
-                .element(element).is().present();
+        waitGui().withTimeout(IMPLICIT_TIMEOUT, TimeUnit.MILLISECONDS).pollingEvery(POLLING_INTERVAL, TimeUnit.MILLISECONDS)
+                .until(message).element(element).is().present();
     }
 
     public static void waitGuiForElement(By element) {
@@ -60,11 +72,13 @@ public final class WaitUtils {
     }
 
     public static void waitGuiForElementPresent(WebElement element, String message) {
-        waitGui().until(message).element(element).is().present();
+        waitGui().withTimeout(IMPLICIT_TIMEOUT, TimeUnit.MILLISECONDS).pollingEvery(POLLING_INTERVAL, TimeUnit.MILLISECONDS)
+                .until(message).element(element).is().present();
     }
 
     public static void waitGuiForElementNotPresent(WebElement element) {
-        waitGui().until().element(element).is().not().present();
+        waitGui().withTimeout(IMPLICIT_TIMEOUT, TimeUnit.MILLISECONDS).pollingEvery(POLLING_INTERVAL, TimeUnit.MILLISECONDS)
+                .until().element(element).is().not().present();
     }
 
     public static void pause(long millis) {
@@ -74,5 +88,5 @@ public final class WaitUtils {
             Logger.getLogger(WaitUtils.class.getName()).log(Level.SEVERE, null, ex);
         }
     }
-    
+
 }
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/AbstractKeycloakTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/AbstractKeycloakTest.java
index 8ed6dcd..e553b3d 100644
--- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/AbstractKeycloakTest.java
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/AbstractKeycloakTest.java
@@ -32,6 +32,7 @@ import org.keycloak.testsuite.auth.page.account.Account;
 import org.keycloak.testsuite.auth.page.login.OIDCLogin;
 import org.keycloak.testsuite.auth.page.login.UpdatePassword;
 import org.keycloak.testsuite.util.Timer;
+import org.keycloak.testsuite.util.WaitUtils;
 
 /**
  *
@@ -116,9 +117,9 @@ public abstract class AbstractKeycloakTest {
     }
 
     protected void driverSettings() {
-        driver.manage().timeouts().pageLoadTimeout(5, TimeUnit.SECONDS);
-        driver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
-        driver.manage().timeouts().setScriptTimeout(3, TimeUnit.SECONDS);
+        driver.manage().timeouts().pageLoadTimeout(WaitUtils.PAGELOAD_TIMEOUT, TimeUnit.MILLISECONDS);
+        driver.manage().timeouts().implicitlyWait(WaitUtils.IMPLICIT_TIMEOUT, TimeUnit.MILLISECONDS);
+        driver.manage().timeouts().setScriptTimeout(WaitUtils.SCRIPT_TIMEOUT, TimeUnit.MILLISECONDS);
         driver.manage().window().maximize();
     }
 
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/client/OIDCClientRegistrationTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/client/OIDCClientRegistrationTest.java
new file mode 100644
index 0000000..9696274
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/client/OIDCClientRegistrationTest.java
@@ -0,0 +1,85 @@
+package org.keycloak.testsuite.client;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.keycloak.client.registration.Auth;
+import org.keycloak.client.registration.ClientRegistrationException;
+import org.keycloak.representations.idm.ClientInitialAccessCreatePresentation;
+import org.keycloak.representations.idm.ClientInitialAccessPresentation;
+import org.keycloak.representations.oidc.OIDCClientRepresentation;
+
+import java.util.Collections;
+
+import static org.junit.Assert.*;
+
+/**
+ * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
+ */
+public class OIDCClientRegistrationTest extends AbstractClientRegistrationTest {
+
+    @Before
+    public void before() throws Exception {
+        super.before();
+
+        ClientInitialAccessPresentation token = adminClient.realm(REALM_NAME).clientInitialAccess().create(new ClientInitialAccessCreatePresentation(0, 10));
+        reg.auth(Auth.token(token));
+    }
+
+    public OIDCClientRepresentation create() throws ClientRegistrationException {
+        OIDCClientRepresentation client = new OIDCClientRepresentation();
+        client.setClientName("RegistrationAccessTokenTest");
+        client.setClientUri("http://root");
+        client.setRedirectUris(Collections.singletonList("http://redirect"));
+
+        OIDCClientRepresentation response = reg.oidc().create(client);
+
+        return response;
+    }
+
+    @Test
+    public void createClient() throws ClientRegistrationException {
+        OIDCClientRepresentation response = create();
+
+        assertNotNull(response.getRegistrationAccessToken());
+        assertNotNull(response.getClientIdIssuedAt());
+        assertNotNull(response.getClientId());
+        assertNull(response.getClientSecretExpiresAt());
+        assertNotNull(response.getRegistrationClientUri());
+        assertEquals("RegistrationAccessTokenTest", response.getClientName());
+        assertEquals("http://root", response.getClientUri());
+        assertEquals(1, response.getRedirectUris().size());
+        assertEquals("http://redirect", response.getRedirectUris().get(0));
+    }
+
+    @Test
+    public void getClient() throws ClientRegistrationException {
+        OIDCClientRepresentation response = create();
+        reg.auth(Auth.token(response));
+
+        OIDCClientRepresentation rep = reg.oidc().get(response.getClientId());
+        assertNotNull(rep);
+        assertNotEquals(response.getRegistrationAccessToken(), rep.getRegistrationAccessToken());
+    }
+
+    @Test
+    public void updateClient() throws ClientRegistrationException {
+        OIDCClientRepresentation response = create();
+        reg.auth(Auth.token(response));
+
+        response.setRedirectUris(Collections.singletonList("http://newredirect"));
+
+        OIDCClientRepresentation updated = reg.oidc().update(response);
+
+        assertEquals(1, updated.getRedirectUris().size());
+        assertEquals("http://newredirect", updated.getRedirectUris().get(0));
+    }
+
+    @Test
+    public void deleteClient() throws ClientRegistrationException {
+        OIDCClientRepresentation response = create();
+        reg.auth(Auth.token(response));
+
+        reg.oidc().delete(response);
+    }
+
+}
diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/client/SAMLClientRegistrationTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/client/SAMLClientRegistrationTest.java
new file mode 100644
index 0000000..1f5eab8
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/client/SAMLClientRegistrationTest.java
@@ -0,0 +1,42 @@
+package org.keycloak.testsuite.client;
+
+import org.apache.commons.io.IOUtils;
+import org.junit.Before;
+import org.junit.Test;
+import org.keycloak.client.registration.Auth;
+import org.keycloak.client.registration.ClientRegistrationException;
+import org.keycloak.representations.idm.ClientInitialAccessCreatePresentation;
+import org.keycloak.representations.idm.ClientInitialAccessPresentation;
+import org.keycloak.representations.idm.ClientRepresentation;
+import org.keycloak.representations.oidc.OIDCClientRepresentation;
+
+import java.io.IOException;
+import java.util.Collections;
+
+import static org.junit.Assert.*;
+
+/**
+ * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
+ */
+public class SAMLClientRegistrationTest extends AbstractClientRegistrationTest {
+
+    @Before
+    public void before() throws Exception {
+        super.before();
+
+        ClientInitialAccessPresentation token = adminClient.realm(REALM_NAME).clientInitialAccess().create(new ClientInitialAccessCreatePresentation(0, 10));
+        reg.auth(Auth.token(token));
+    }
+
+    @Test
+    public void createClient() throws ClientRegistrationException, IOException {
+        String entityDescriptor = IOUtils.toString(getClass().getResourceAsStream("/clientreg-test/saml-entity-descriptor.xml"));
+        ClientRepresentation response = reg.saml().create(entityDescriptor);
+
+        assertNotNull(response.getRegistrationAccessToken());
+        assertEquals("loadbalancer-9.siroe.com", response.getClientId());
+        assertEquals(1, response.getRedirectUris().size());
+        assertEquals("https://LoadBalancer-9.siroe.com:3443/federation/Consumer/metaAlias/sp", response.getRedirectUris().get(0));
+    }
+
+}
diff --git a/testsuite/integration-arquillian/tests/base/src/test/resources/clientreg-test/saml-entity-descriptor.xml b/testsuite/integration-arquillian/tests/base/src/test/resources/clientreg-test/saml-entity-descriptor.xml
new file mode 100644
index 0000000..b00ab25
--- /dev/null
+++ b/testsuite/integration-arquillian/tests/base/src/test/resources/clientreg-test/saml-entity-descriptor.xml
@@ -0,0 +1,82 @@
+<EntityDescriptor
+    xmlns="urn:oasis:names:tc:SAML:2.0:metadata"
+    entityID="loadbalancer-9.siroe.com">
+    <SPSSODescriptor
+        AuthnRequestsSigned="false"
+        WantAssertionsSigned="false"
+        protocolSupportEnumeration=
+            "urn:oasis:names:tc:SAML:2.0:protocol">
+        <KeyDescriptor use="signing">
+            <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
+                <X509Data>
+                    <X509Certificate>
+MIICYDCCAgqgAwIBAgICBoowDQYJKoZIhvcNAQEEBQAwgZIxCzAJBgNVBAYTAlVTMRMwEQYDVQQI
+EwpDYWxpZm9ybmlhMRQwEgYDVQQHEwtTYW50YSBDbGFyYTEeMBwGA1UEChMVU3VuIE1pY3Jvc3lz
+dGVtcyBJbmMuMRowGAYDVQQLExFJZGVudGl0eSBTZXJ2aWNlczEcMBoGA1UEAxMTQ2VydGlmaWNh
+dGUgTWFuYWdlcjAeFw0wNjExMDIxOTExMzRaFw0xMDA3MjkxOTExMzRaMDcxEjAQBgNVBAoTCXNp
+cm9lLmNvbTEhMB8GA1UEAxMYbG9hZGJhbGFuY2VyLTkuc2lyb2UuY29tMIGfMA0GCSqGSIb3DQEB
+AQUAA4GNADCBiQKBgQCjOwa5qoaUuVnknqf5pdgAJSEoWlvx/jnUYbkSDpXLzraEiy2UhvwpoBgB
+EeTSUaPPBvboCItchakPI6Z/aFdH3Wmjuij9XD8r1C+q//7sUO0IGn0ORycddHhoo0aSdnnxGf9V
+tREaqKm9dJ7Yn7kQHjo2eryMgYxtr/Z5Il5F+wIDAQABo2AwXjARBglghkgBhvhCAQEEBAMCBkAw
+DgYDVR0PAQH/BAQDAgTwMB8GA1UdIwQYMBaAFDugITflTCfsWyNLTXDl7cMDUKuuMBgGA1UdEQQR
+MA+BDW1hbGxhQHN1bi5jb20wDQYJKoZIhvcNAQEEBQADQQB/6DOB6sRqCZu2OenM9eQR0gube85e
+nTTxU4a7x1naFxzYXK1iQ1vMARKMjDb19QEJIEJKZlDK4uS7yMlf1nFS
+                    </X509Certificate>
+                </X509Data>
+            </KeyInfo>
+        </KeyDescriptor>
+        <KeyDescriptor use="encryption">
+            <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
+                <X509Data>
+                    <X509Certificate>
+MIICTDCCAfagAwIBAgICBo8wDQYJKoZIhvcNAQEEBQAwgZIxCzAJBgNVBAYTAlVTMRMwEQYDVQQI
+EwpDYWxpZm9ybmlhMRQwEgYDVQQHEwtTYW50YSBDbGFyYTEeMBwGA1UEChMVU3VuIE1pY3Jvc3lz
+dGVtcyBJbmMuMRowGAYDVQQLExFJZGVudGl0eSBTZXJ2aWNlczEcMBoGA1UEAxMTQ2VydGlmaWNh
+dGUgTWFuYWdlcjAeFw0wNjExMDcyMzU2MTdaFw0xMDA4MDMyMzU2MTdaMCMxITAfBgNVBAMTGGxv
+YWRiYWxhbmNlci05LnNpcm9lLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAw574iRU6
+HsSO4LXW/OGTXyfsbGv6XRVOoy3v+J1pZ51KKejcDjDJXNkKGn3/356AwIaqbcymWd59T0zSqYfR
+Hn+45uyjYxRBmVJseLpVnOXLub9jsjULfGx0yjH4w+KsZSZCXatoCHbj/RJtkzuZY6V9to/hkH3S
+InQB4a3UAgMCAwEAAaNgMF4wEQYJYIZIAYb4QgEBBAQDAgZAMA4GA1UdDwEB/wQEAwIE8DAfBgNV
+HSMEGDAWgBQ7oCE35Uwn7FsjS01w5e3DA1CrrjAYBgNVHREEETAPgQ1tYWxsYUBzdW4uY29tMA0G
+CSqGSIb3DQEBBAUAA0EAMlbfBg/ff0Xkv4DOR5LEqmfTZKqgdlD81cXynfzlF7XfnOqI6hPIA90I
+x5Ql0ejivIJAYcMGUyA+/YwJg2FGoA==
+                    </X509Certificate>
+                </X509Data>
+            </KeyInfo>
+            <EncryptionMethod Algorithm=
+                "https://www.w3.org/2001/04/xmlenc#aes128-cbc">
+                <KeySize xmlns="https://www.w3.org/2001/04/xmlenc#">128</KeySize>
+            </EncryptionMethod>
+        </KeyDescriptor>
+        <SingleLogoutService
+            Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
+            Location="https://LoadBalancer-9.siroe.com:3443/federation/SPSloRedirect/metaAlias/sp"
+            ResponseLocation="https://LoadBalancer-9.siroe.com:3443/federation/SPSloRedirect/metaAlias/sp"/>
+        <SingleLogoutService
+            Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP"
+            Location="https://LoadBalancer-9.siroe.com:3443/federation/SPSloSoap/metaAlias/sp"/>
+       <ManageNameIDService
+            Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
+            Location="https://LoadBalancer-9.siroe.com:3443/federation/SPMniRedirect/metaAlias/sp"
+            ResponseLocation="https://LoadBalancer-9.siroe.com:3443/federation/SPMniRedirect/metaAlias/sp"/>
+        <ManageNameIDService
+            Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP"
+            Location="https://LoadBalancer-9.siroe.com:3443/federation/SPMniSoap/metaAlias/sp"
+            ResponseLocation="https://LoadBalancer-9.siroe.com:3443/federation/SPMniSoap/metaAlias/sp"/>
+        <NameIDFormat>
+            urn:oasis:names:tc:SAML:2.0:nameid-format:persistent
+        </NameIDFormat>
+        <NameIDFormat>
+            urn:oasis:names:tc:SAML:2.0:nameid-format:transient
+        </NameIDFormat>
+        <AssertionConsumerService
+            isDefault="true"
+            index="0"
+            Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact"
+            Location="https://LoadBalancer-9.siroe.com:3443/federation/Consumer/metaAlias/sp"/>
+        <AssertionConsumerService
+            index="1"
+            Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
+            Location="https://LoadBalancer-9.siroe.com:3443/federation/Consumer/metaAlias/sp"/>
+    </SPSSODescriptor>
+</EntityDescriptor>