This is an automated email from the ASF dual-hosted git repository.

ilgrosso pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/syncope.git

commit ef1d8f7a4f940eac3d93e24bf6cba40204eba5f5
Author: Francesco Chicchiriccò <[email protected]>
AuthorDate: Tue Jun 4 14:27:18 2019 +0200

    Adding Maven profile sso-it to check SAML 2.0 and OpenID Connect 1.0 SSO 
from Admin Console and Enduser UI
---
 fit/enduser-reference/pom.xml                      |  121 +-
 .../org/apache/syncope/fit/AbstractITCase.java     |   51 +
 .../org/apache/syncope/fit/OIDCClientITCase.java   |  144 ++
 .../java/org/apache/syncope/fit/SAML2SPITCase.java |  222 ++
 .../src/test/resources/sso/delayed-init            |   28 +
 .../src/test/resources/sso/init.sh                 |   18 +
 .../src/test/resources/sso/oidc-syncope.json       |  131 ++
 .../src/test/resources/sso/realm.json              | 2171 ++++++++++++++++++++
 .../test/resources/sso/saml2syncope-console.json   |  131 ++
 .../test/resources/sso/saml2syncope-enduser.json   |  131 ++
 10 files changed, 3147 insertions(+), 1 deletion(-)

diff --git a/fit/enduser-reference/pom.xml b/fit/enduser-reference/pom.xml
index e924a5f..0bac13a 100644
--- a/fit/enduser-reference/pom.xml
+++ b/fit/enduser-reference/pom.xml
@@ -99,6 +99,16 @@ under the License.
       <type>war</type>
       <scope>test</scope>
     </dependency>
+    <dependency>
+      <groupId>org.apache.httpcomponents</groupId>
+      <artifactId>httpclient</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.junit.jupiter</groupId>
+      <artifactId>junit-jupiter</artifactId>
+      <scope>test</scope>
+    </dependency>
   </dependencies>
 
   <build>
@@ -314,7 +324,116 @@ under the License.
         </resources>
       </build>
     </profile>
-    
+
+    <profile>
+      <id>sso-it</id>
+
+      <build>
+        <plugins>          
+          <plugin>
+            <groupId>io.fabric8</groupId>
+            <artifactId>docker-maven-plugin</artifactId>
+            <configuration>
+              <images>
+                <image>
+                  <name>jboss/keycloak:6.0.1</name>
+                  <run>
+                    <hostname>keycloak</hostname>
+                    <env>
+                      <DB_VENDOR>h2</DB_VENDOR>
+                      <KEYCLOAK_USER>admin</KEYCLOAK_USER>
+                      <KEYCLOAK_PASSWORD>password</KEYCLOAK_PASSWORD>
+                    </env>
+                    <ports>
+                      <port>9090:8080</port>
+                    </ports>
+                    <volumes>
+                      <bind>
+                        
<volume>${basedir}/src/test/resources/sso/init.sh:/opt/jboss/startup-scripts/init.sh</volume>
+                        
<volume>${project.build.testOutputDirectory}/sso/delayed-init:/tmp/delayed-init</volume>
+                        
<volume>${project.build.testOutputDirectory}/sso/saml2syncope-console.json:/tmp/saml2syncope-console.json</volume>
+                        
<volume>${project.build.testOutputDirectory}/sso/saml2syncope-enduser.json:/tmp/saml2syncope-enduser.json</volume>
+                        
<volume>${project.build.testOutputDirectory}/sso/oidc-syncope.json:/tmp/oidc-syncope.json</volume>
+                      </bind>
+                    </volumes>
+                  </run>
+                </image>
+              </images>
+            </configuration>
+            <executions>
+              <execution>
+                <id>start-keycloak</id>
+                <phase>pre-integration-test</phase>
+                <goals>
+                  <goal>start</goal>
+                </goals>
+              </execution>
+              <execution>
+                <id>stop-keycloak</id>
+                <phase>post-integration-test</phase>
+                <goals>
+                  <goal>stop</goal>
+                  <goal>remove</goal>
+                </goals>
+              </execution>
+            </executions>
+          </plugin>
+
+          <plugin>
+            <groupId>org.codehaus.cargo</groupId>
+            <artifactId>cargo-maven2-plugin</artifactId>
+            <inherited>true</inherited>
+            <configuration>
+              <configuration>
+                <properties>
+                  <cargo.jvmargs>
+                    -Dspring.profiles.active=embedded
+                    
-Dwicket.core.settings.general.configuration-type=development
+                    -XX:+CMSClassUnloadingEnabled -XX:+UseG1GC -Xmx1024m 
-Xms512m</cargo.jvmargs>
+                </properties>
+              </configuration>
+            </configuration>
+            <executions>
+              <execution>
+                <id>start-container</id>
+                <phase>pre-integration-test</phase>
+                <goals>
+                  <goal>start</goal>
+                </goals>
+                <configuration>
+                  <skip>${skipTests}</skip>
+                </configuration>
+              </execution>
+              <execution>
+                <id>stop-container</id>
+                <phase>post-integration-test</phase>
+                <goals>
+                  <goal>stop</goal>
+                </goals>
+                <configuration>
+                  <skip>${skipTests}</skip>
+                </configuration>
+              </execution>
+            </executions>
+          </plugin>
+
+          <plugin>
+            <groupId>org.apache.maven.plugins</groupId>
+            <artifactId>maven-failsafe-plugin</artifactId>
+            <inherited>true</inherited>
+            <executions>
+              <execution>
+                <id>verify</id>
+                <goals>
+                  <goal>verify</goal>
+                </goals>
+              </execution>
+            </executions>
+          </plugin>
+        </plugins>
+      </build>
+    </profile>
+
     <profile>
       <id>apache-release</id>
 
diff --git 
a/fit/enduser-reference/src/test/java/org/apache/syncope/fit/AbstractITCase.java
 
b/fit/enduser-reference/src/test/java/org/apache/syncope/fit/AbstractITCase.java
new file mode 100644
index 0000000..7f43492
--- /dev/null
+++ 
b/fit/enduser-reference/src/test/java/org/apache/syncope/fit/AbstractITCase.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.fit;
+
+import org.apache.syncope.client.lib.SyncopeClient;
+import org.apache.syncope.client.lib.SyncopeClientFactoryBean;
+import org.apache.syncope.common.rest.api.service.OIDCProviderService;
+import org.apache.syncope.common.rest.api.service.SAML2IdPService;
+import org.junit.jupiter.api.BeforeAll;
+
+public abstract class AbstractITCase {
+
+    protected static final String ADMIN_UNAME = "admin";
+
+    protected static final String ADMIN_PWD = "password";
+
+    protected static final String ADDRESS = 
"http://localhost:9080/syncope/rest";;
+
+    protected static SyncopeClientFactoryBean clientFactory;
+
+    protected static SyncopeClient adminClient;
+
+    protected static SAML2IdPService saml2IdPService;
+
+    protected static OIDCProviderService oidcProviderService;
+
+    @BeforeAll
+    public static void restSetup() {
+        clientFactory = new SyncopeClientFactoryBean().setAddress(ADDRESS);
+        adminClient = clientFactory.create(ADMIN_UNAME, ADMIN_PWD);
+
+        saml2IdPService = adminClient.getService(SAML2IdPService.class);
+        oidcProviderService = 
adminClient.getService(OIDCProviderService.class);
+    }
+}
diff --git 
a/fit/enduser-reference/src/test/java/org/apache/syncope/fit/OIDCClientITCase.java
 
b/fit/enduser-reference/src/test/java/org/apache/syncope/fit/OIDCClientITCase.java
new file mode 100644
index 0000000..6058ad2
--- /dev/null
+++ 
b/fit/enduser-reference/src/test/java/org/apache/syncope/fit/OIDCClientITCase.java
@@ -0,0 +1,144 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.fit;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.http.Consts;
+import org.apache.http.HttpHeaders;
+import org.apache.http.HttpStatus;
+import org.apache.http.NameValuePair;
+import org.apache.http.client.entity.UrlEncodedFormEntity;
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.client.protocol.HttpClientContext;
+import org.apache.http.impl.client.BasicCookieStore;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.http.message.BasicHeader;
+import org.apache.http.message.BasicNameValuePair;
+import org.apache.http.util.EntityUtils;
+import org.apache.syncope.common.lib.to.ItemTO;
+import org.apache.syncope.common.lib.to.OIDCProviderTO;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+
+public class OIDCClientITCase extends AbstractITCase {
+
+    @BeforeAll
+    public static void samlSetup() {
+        OIDCProviderTO keycloak = new OIDCProviderTO();
+        keycloak.setName("Keyloack");
+        keycloak.setClientID("oidc-syncope");
+        keycloak.setClientSecret("oidc-syncope");
+        
keycloak.setAuthorizationEndpoint("http://localhost:9090/auth/realms/master/protocol/openid-connect/auth";);
+        
keycloak.setTokenEndpoint("http://localhost:9090/auth/realms/master/protocol/openid-connect/token";);
+        keycloak.setIssuer("http://localhost:9090/auth/realms/master";);
+        
keycloak.setJwksUri("http://localhost:9090/auth/realms/master/protocol/openid-connect/certs";);
+        
keycloak.setUserinfoEndpoint("http://localhost:9090/auth/realms/master/protocol/openid-connect/userinfo";);
+        
keycloak.setEndSessionEndpoint("http://localhost:9090/auth/realms/master/protocol/openid-connect/logout";);
+        keycloak.setCreateUnmatching(true);
+
+        ItemTO item = new ItemTO();
+        item.setIntAttrName("username");
+        item.setExtAttrName("preferred_username");
+        item.setConnObjectKey(true);
+        keycloak.getItems().add(item);
+
+        item = new ItemTO();
+        item.setIntAttrName("email");
+        item.setExtAttrName("email");
+        keycloak.getItems().add(item);
+
+        item = new ItemTO();
+        item.setIntAttrName("userId");
+        item.setExtAttrName("email");
+        keycloak.getItems().add(item);
+
+        item = new ItemTO();
+        item.setIntAttrName("firstname");
+        item.setExtAttrName("given_name");
+        keycloak.getItems().add(item);
+
+        item = new ItemTO();
+        item.setIntAttrName("surname");
+        item.setExtAttrName("family_name");
+        keycloak.getItems().add(item);
+
+        item = new ItemTO();
+        item.setIntAttrName("fullname");
+        item.setExtAttrName("fullName");
+        keycloak.getItems().add(item);
+
+        oidcProviderService.create(keycloak);
+    }
+
+    private void sso(final String baseURL) throws IOException {
+        CloseableHttpClient httpclient = 
HttpClients.custom().setMaxConnPerRoute(100).build();
+        HttpClientContext context = HttpClientContext.create();
+        context.setCookieStore(new BasicCookieStore());
+
+        // 1. fetch login page
+        HttpGet get = new HttpGet(baseURL);
+        CloseableHttpResponse response = httpclient.execute(get, context);
+        assertEquals(HttpStatus.SC_OK, 
response.getStatusLine().getStatusCode());
+
+        // 2. click on the OpenID Connect Provider
+        get = new HttpGet(baseURL + "oidcclient/login?op=Keyloack");
+        response = httpclient.execute(get, context);
+
+        // 3. get login form from Keycloack and submit with expected username 
and password
+        String action = StringUtils.substringBefore(
+                
StringUtils.substringAfter(EntityUtils.toString(response.getEntity()),
+                        "<form id=\"kc-form-login\" onsubmit=\"login.disabled 
= true; return true;\" action=\""),
+                "\" method=\"post\">").replace("&amp;", "&");
+
+        List<NameValuePair> toSubmit = new ArrayList<>();
+        toSubmit.add(new BasicNameValuePair("username", "john.doe"));
+        toSubmit.add(new BasicNameValuePair("password", "password"));
+
+        HttpPost post = new HttpPost(action);
+        post.addHeader(new BasicHeader(HttpHeaders.ACCEPT_LANGUAGE, 
"en-US,en;q=0.5"));
+        post.setEntity(new UrlEncodedFormEntity(toSubmit, Consts.UTF_8));
+        response = httpclient.execute(post, context);
+        assertEquals(HttpStatus.SC_MOVED_TEMPORARILY, 
response.getStatusLine().getStatusCode());
+
+        // 4. verify that user is now authenticated
+        get = new 
HttpGet(response.getFirstHeader(HttpHeaders.LOCATION).getValue());
+        response = httpclient.execute(get, context);
+        assertEquals(HttpStatus.SC_OK, 
response.getStatusLine().getStatusCode());
+        
assertTrue(EntityUtils.toString(response.getEntity()).contains("john.doe"));
+    }
+
+    @Test
+    public void sso2Console() throws IOException {
+        sso("http://localhost:9080/syncope-console/";);
+    }
+
+    @Test
+    public void sso2Enduser() throws IOException {
+        sso("http://localhost:9080/syncope-enduser/";);
+    }
+}
diff --git 
a/fit/enduser-reference/src/test/java/org/apache/syncope/fit/SAML2SPITCase.java 
b/fit/enduser-reference/src/test/java/org/apache/syncope/fit/SAML2SPITCase.java
new file mode 100644
index 0000000..7ad7e78
--- /dev/null
+++ 
b/fit/enduser-reference/src/test/java/org/apache/syncope/fit/SAML2SPITCase.java
@@ -0,0 +1,222 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.syncope.fit;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+import javax.ws.rs.core.MediaType;
+import javax.xml.stream.XMLStreamException;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.cxf.jaxrs.client.WebClient;
+import org.apache.cxf.staxutils.StaxUtils;
+import org.apache.http.Consts;
+import org.apache.http.HttpHeaders;
+import org.apache.http.HttpStatus;
+import org.apache.http.NameValuePair;
+import org.apache.http.client.entity.UrlEncodedFormEntity;
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.client.protocol.HttpClientContext;
+import org.apache.http.impl.client.BasicCookieStore;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.http.message.BasicHeader;
+import org.apache.http.message.BasicNameValuePair;
+import org.apache.http.util.EntityUtils;
+import org.apache.syncope.common.lib.to.ItemTO;
+import org.apache.syncope.common.lib.to.SAML2IdPTO;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+public class SAML2SPITCase extends AbstractITCase {
+
+    @BeforeAll
+    public static void samlSetup() {
+        WebClient.client(saml2IdPService).
+                accept(MediaType.APPLICATION_XML_TYPE).
+                type(MediaType.APPLICATION_XML_TYPE);
+        try {
+            saml2IdPService.importFromMetadata((InputStream) WebClient.create(
+                    
"http://localhost:9090/auth/realms/master/protocol/saml/descriptor/";).get().getEntity());
+        } finally {
+            WebClient.client(saml2IdPService).
+                    accept(clientFactory.getContentType().getMediaType()).
+                    type(clientFactory.getContentType().getMediaType());
+        }
+
+        List<SAML2IdPTO> idps = saml2IdPService.list();
+        assertEquals(1, idps.size());
+
+        SAML2IdPTO keycloak = idps.get(0);
+        keycloak.setName("Keyloack");
+        keycloak.setCreateUnmatching(true);
+        keycloak.getItems().clear();
+
+        ItemTO item = new ItemTO();
+        item.setIntAttrName("username");
+        item.setExtAttrName("username");
+        item.setConnObjectKey(true);
+        keycloak.getItems().add(item);
+
+        item = new ItemTO();
+        item.setIntAttrName("email");
+        item.setExtAttrName("email");
+        keycloak.getItems().add(item);
+
+        item = new ItemTO();
+        item.setIntAttrName("userId");
+        item.setExtAttrName("email");
+        keycloak.getItems().add(item);
+
+        item = new ItemTO();
+        item.setIntAttrName("firstname");
+        item.setExtAttrName("givenName");
+        keycloak.getItems().add(item);
+
+        item = new ItemTO();
+        item.setIntAttrName("surname");
+        item.setExtAttrName("surname");
+        keycloak.getItems().add(item);
+
+        item = new ItemTO();
+        item.setIntAttrName("fullname");
+        item.setExtAttrName("fullName");
+        keycloak.getItems().add(item);
+
+        saml2IdPService.update(keycloak);
+    }
+
+    private List<Node> find(final NodeList children, final String match) {
+        List<Node> nodes = new ArrayList<>();
+        for (int i = 0; i < children.getLength(); i++) {
+            if (match.equals(children.item(i).getNodeName())) {
+                nodes.add(children.item(i));
+            }
+        }
+        return nodes;
+    }
+
+    private void sso(final String baseURL) throws IOException, 
XMLStreamException {
+        CloseableHttpClient httpclient = 
HttpClients.custom().setMaxConnPerRoute(100).build();
+        HttpClientContext context = HttpClientContext.create();
+        context.setCookieStore(new BasicCookieStore());
+
+        // 1. fetch login page
+        HttpGet get = new HttpGet(baseURL);
+        CloseableHttpResponse response = httpclient.execute(get, context);
+        assertEquals(HttpStatus.SC_OK, 
response.getStatusLine().getStatusCode());
+
+        // 2. click on the SAML 2.0 IdP
+        get = new HttpGet(baseURL + 
"saml2sp/login?idp=http%3A%2F%2Flocalhost%3A9090%2Fauth%2Frealms%2Fmaster");
+        response = httpclient.execute(get, context);
+
+        // 3. process autosubmit form for login request
+        Document autosubmitForm = 
StaxUtils.read(response.getEntity().getContent());
+
+        Node body = 
find(autosubmitForm.getChildNodes().item(0).getChildNodes(), "body").get(0);
+        assertNotNull(body);
+
+        Node form = find(body.getChildNodes(), "form").get(0);
+        assertNotNull(form);
+
+        List<NameValuePair> toSubmit = new ArrayList<>();
+        for (Node input : find(form.getChildNodes(), "input")) {
+            Node name = input.getAttributes().getNamedItem("name");
+            Node value = input.getAttributes().getNamedItem("value");
+            if (name != null && value != null) {
+                toSubmit.add(new BasicNameValuePair(name.getTextContent(), 
value.getTextContent()));
+            }
+        }
+
+        HttpPost post = new 
HttpPost(form.getAttributes().getNamedItem("action").getTextContent());
+        post.setEntity(new UrlEncodedFormEntity(toSubmit, Consts.UTF_8));
+        response = httpclient.execute(post, context);
+        assertEquals(HttpStatus.SC_MOVED_TEMPORARILY, 
response.getStatusLine().getStatusCode());
+
+        // 4. get login form from Keycloack and submit with expected username 
and password
+        get = new 
HttpGet(response.getFirstHeader(HttpHeaders.LOCATION).getValue());
+        response = httpclient.execute(get, context);
+
+        String action = StringUtils.substringBefore(
+                
StringUtils.substringAfter(EntityUtils.toString(response.getEntity()),
+                        "<form id=\"kc-form-login\" onsubmit=\"login.disabled 
= true; return true;\" action=\""),
+                "\" method=\"post\">").replace("&amp;", "&");
+
+        toSubmit.clear();
+        toSubmit.add(new BasicNameValuePair("username", "john.doe"));
+        toSubmit.add(new BasicNameValuePair("password", "password"));
+
+        post = new HttpPost(action);
+        post.addHeader(new BasicHeader(HttpHeaders.ACCEPT_LANGUAGE, 
"en-US,en;q=0.5"));
+        post.setEntity(new UrlEncodedFormEntity(toSubmit, Consts.UTF_8));
+        response = httpclient.execute(post, context);
+
+        // 5. process autosubmit form for login response
+        autosubmitForm = StaxUtils.read(
+                new 
ByteArrayInputStream(EntityUtils.toString(response.getEntity()).replace("&", 
"&amp;").getBytes()));
+
+        body = find(autosubmitForm.getChildNodes().item(0).getChildNodes(), 
"BODY").get(0);
+        assertNotNull(body);
+
+        form = find(body.getChildNodes(), "FORM").get(0);
+        assertNotNull(form);
+
+        toSubmit.clear();
+        for (Node input : find(form.getChildNodes(), "INPUT")) {
+            Node name = input.getAttributes().getNamedItem("NAME");
+            Node value = input.getAttributes().getNamedItem("VALUE");
+            if (name != null && value != null) {
+                toSubmit.add(new BasicNameValuePair(name.getTextContent(), 
value.getTextContent()));
+            }
+        }
+
+        post = new 
HttpPost(form.getAttributes().getNamedItem("ACTION").getTextContent());
+        post.setEntity(new UrlEncodedFormEntity(toSubmit, Consts.UTF_8));
+        response = httpclient.execute(post, context);
+        assertEquals(HttpStatus.SC_MOVED_TEMPORARILY, 
response.getStatusLine().getStatusCode());
+
+        // 6. verify that user is now authenticated
+        get = new HttpGet(baseURL + StringUtils.removeStart(
+                response.getFirstHeader(HttpHeaders.LOCATION).getValue(), 
"../"));
+        response = httpclient.execute(get, context);
+        assertEquals(HttpStatus.SC_OK, 
response.getStatusLine().getStatusCode());
+        
assertTrue(EntityUtils.toString(response.getEntity()).contains("john.doe"));
+    }
+
+    @Test
+    public void sso2Console() throws IOException, XMLStreamException {
+        sso("http://localhost:9080/syncope-console/";);
+    }
+
+    @Test
+    public void sso2Enduser() throws IOException, XMLStreamException {
+        sso("http://localhost:9080/syncope-enduser/";);
+    }
+}
diff --git a/fit/enduser-reference/src/test/resources/sso/delayed-init 
b/fit/enduser-reference/src/test/resources/sso/delayed-init
new file mode 100644
index 0000000..a432550
--- /dev/null
+++ b/fit/enduser-reference/src/test/resources/sso/delayed-init
@@ -0,0 +1,28 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+timeout 300 bash -c 'while [[ "$(curl -s -o /dev/null -w ''%{http_code}'' 
keycloak:8080)" != "200" ]]; do sleep 5; done' || false
+
+/opt/jboss/keycloak/bin/kcadm.sh config credentials --server 
http://keycloak:8080/auth --realm master --user admin --password password
+
+/opt/jboss/keycloak/bin/kcadm.sh create users -r master -s username=john.doe 
-s [email protected] -s lastName=Doe -s firstName=John -s 
'attributes.fullName=John Doe' -s enabled=true
+/opt/jboss/keycloak/bin/kcadm.sh set-password -r master --username john.doe 
--new-password password
+
+/opt/jboss/keycloak/bin/kcadm.sh create clients -r master -f 
/tmp/saml2syncope-console.json
+/opt/jboss/keycloak/bin/kcadm.sh create clients -r master -f 
/tmp/saml2syncope-enduser.json
+
+/opt/jboss/keycloak/bin/kcadm.sh create clients -r master -f 
/tmp/oidc-syncope.json
diff --git a/fit/enduser-reference/src/test/resources/sso/init.sh 
b/fit/enduser-reference/src/test/resources/sso/init.sh
new file mode 100755
index 0000000..7cb523a
--- /dev/null
+++ b/fit/enduser-reference/src/test/resources/sso/init.sh
@@ -0,0 +1,18 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+nohup bash /tmp/delayed-init&
diff --git a/fit/enduser-reference/src/test/resources/sso/oidc-syncope.json 
b/fit/enduser-reference/src/test/resources/sso/oidc-syncope.json
new file mode 100644
index 0000000..8d582c1
--- /dev/null
+++ b/fit/enduser-reference/src/test/resources/sso/oidc-syncope.json
@@ -0,0 +1,131 @@
+{
+    "clientId": "oidc-syncope",
+    "surrogateAuthRequired": false,
+    "enabled": true,
+    "clientAuthenticatorType": "client-secret",
+    "redirectUris": [
+        "http://localhost:9080/syncope-enduser/oidcclient/code-consumer";,
+        "http://localhost:9080/syncope-enduser/oidcclient/logout";,
+        "http://localhost:9080/syncope-console/oidcclient/code-consumer";,
+        "http://localhost:9080/syncope-console/oidcclient/logout";
+    ],
+    "webOrigins": [],
+    "notBefore": 0,
+    "bearerOnly": false,
+    "consentRequired": false,
+    "standardFlowEnabled": true,
+    "implicitFlowEnabled": false,
+    "directAccessGrantsEnabled": true,
+    "serviceAccountsEnabled": false,
+    "publicClient": true,
+    "frontchannelLogout": false,
+    "protocol": "openid-connect",
+    "attributes": {
+        "saml.assertion.signature": "false",
+        "saml.force.post.binding": "false",
+        "saml.multivalued.roles": "false",
+        "saml.encrypt": "false",
+        "saml.server.signature": "false",
+        "saml.server.signature.keyinfo.ext": "false",
+        "exclude.session.state.from.auth.response": "false",
+        "saml_force_name_id_format": "false",
+        "saml.client.signature": "false",
+        "tls.client.certificate.bound.access.tokens": "false",
+        "saml.authnstatement": "false",
+        "display.on.consent.screen": "false",
+        "saml.onetimeuse.condition": "false"
+    },
+    "authenticationFlowBindingOverrides": {},
+    "fullScopeAllowed": true,
+    "nodeReRegistrationTimeout": -1,
+    "protocolMappers": [
+        {
+            "name": "family name",
+            "protocol": "openid-connect",
+            "protocolMapper": "oidc-usermodel-property-mapper",
+            "consentRequired": false,
+            "config": {
+                "userinfo.token.claim": "true",
+                "user.attribute": "lastName",
+                "id.token.claim": "true",
+                "access.token.claim": "true",
+                "claim.name": "family_name",
+                "jsonType.label": "String"
+            }
+        },
+        {
+            "name": "given name",
+            "protocol": "openid-connect",
+            "protocolMapper": "oidc-usermodel-property-mapper",
+            "consentRequired": false,
+            "config": {
+                "userinfo.token.claim": "true",
+                "user.attribute": "firstName",
+                "id.token.claim": "true",
+                "access.token.claim": "true",
+                "claim.name": "given_name",
+                "jsonType.label": "String"
+            }
+        },
+        {
+            "name": "username",
+            "protocol": "openid-connect",
+            "protocolMapper": "oidc-usermodel-property-mapper",
+            "consentRequired": false,
+            "config": {
+                "userinfo.token.claim": "true",
+                "user.attribute": "username",
+                "id.token.claim": "true",
+                "access.token.claim": "true",
+                "claim.name": "preferred_username",
+                "jsonType.label": "String"
+            }
+        },
+        {
+            "name": "fullName",
+            "protocol": "openid-connect",
+            "protocolMapper": "oidc-usermodel-attribute-mapper",
+            "consentRequired": false,
+            "config": {
+                "userinfo.token.claim": "true",
+                "user.attribute": "fullName",
+                "id.token.claim": "true",
+                "access.token.claim": "true",
+                "claim.name": "fullName",
+                "jsonType.label": "String"
+            }
+        },
+        {
+            "name": "email",
+            "protocol": "openid-connect",
+            "protocolMapper": "oidc-usermodel-property-mapper",
+            "consentRequired": false,
+            "config": {
+                "userinfo.token.claim": "true",
+                "user.attribute": "email",
+                "id.token.claim": "true",
+                "access.token.claim": "true",
+                "claim.name": "email",
+                "jsonType.label": "String"
+            }
+        }
+    ],
+    "defaultClientScopes": [
+        "web-origins",
+        "role_list",
+        "roles",
+        "profile",
+        "email"
+    ],
+    "optionalClientScopes": [
+        "address",
+        "phone",
+        "offline_access",
+        "microprofile-jwt"
+    ],
+    "access": {
+        "view": true,
+        "configure": true,
+        "manage": true
+    }
+}
\ No newline at end of file
diff --git a/fit/enduser-reference/src/test/resources/sso/realm.json 
b/fit/enduser-reference/src/test/resources/sso/realm.json
new file mode 100644
index 0000000..a591048
--- /dev/null
+++ b/fit/enduser-reference/src/test/resources/sso/realm.json
@@ -0,0 +1,2171 @@
+{
+  "id": "master",
+  "realm": "master",
+  "displayName": "Keycloak",
+  "displayNameHtml": "<div class=\"kc-logo-text\"><span>Keycloak</span></div>",
+  "notBefore": 0,
+  "revokeRefreshToken": false,
+  "refreshTokenMaxReuse": 0,
+  "accessTokenLifespan": 60,
+  "accessTokenLifespanForImplicitFlow": 900,
+  "ssoSessionIdleTimeout": 1800,
+  "ssoSessionMaxLifespan": 36000,
+  "ssoSessionIdleTimeoutRememberMe": 0,
+  "ssoSessionMaxLifespanRememberMe": 0,
+  "offlineSessionIdleTimeout": 2592000,
+  "offlineSessionMaxLifespanEnabled": false,
+  "offlineSessionMaxLifespan": 5184000,
+  "accessCodeLifespan": 60,
+  "accessCodeLifespanUserAction": 300,
+  "accessCodeLifespanLogin": 1800,
+  "actionTokenGeneratedByAdminLifespan": 43200,
+  "actionTokenGeneratedByUserLifespan": 300,
+  "enabled": true,
+  "sslRequired": "external",
+  "registrationAllowed": false,
+  "registrationEmailAsUsername": false,
+  "rememberMe": false,
+  "verifyEmail": false,
+  "loginWithEmailAllowed": true,
+  "duplicateEmailsAllowed": false,
+  "resetPasswordAllowed": false,
+  "editUsernameAllowed": false,
+  "bruteForceProtected": false,
+  "permanentLockout": false,
+  "maxFailureWaitSeconds": 900,
+  "minimumQuickLoginWaitSeconds": 60,
+  "waitIncrementSeconds": 60,
+  "quickLoginCheckMilliSeconds": 1000,
+  "maxDeltaTimeSeconds": 43200,
+  "failureFactor": 30,
+  "roles": {
+    "realm": [
+      {
+        "id": "3650e688-c539-4646-8222-010d51a34b2a",
+        "name": "admin",
+        "description": "${role_admin}",
+        "composite": true,
+        "composites": {
+          "realm": [
+            "create-realm"
+          ],
+          "client": {
+            "master-realm": [
+              "query-groups",
+              "manage-events",
+              "manage-authorization",
+              "impersonation",
+              "query-realms",
+              "view-clients",
+              "manage-realm",
+              "manage-users",
+              "create-client",
+              "view-authorization",
+              "manage-clients",
+              "manage-identity-providers",
+              "query-users",
+              "view-users",
+              "view-identity-providers",
+              "view-realm",
+              "view-events",
+              "query-clients"
+            ]
+          }
+        },
+        "clientRole": false,
+        "containerId": "master",
+        "attributes": {}
+      },
+      {
+        "id": "8dfabd84-8072-412e-af5f-5fb57c4a58e5",
+        "name": "create-realm",
+        "description": "${role_create-realm}",
+        "composite": false,
+        "clientRole": false,
+        "containerId": "master",
+        "attributes": {}
+      },
+      {
+        "id": "747ed7d7-6e7a-4339-b7ff-033fceb99af6",
+        "name": "offline_access",
+        "description": "${role_offline-access}",
+        "composite": false,
+        "clientRole": false,
+        "containerId": "master",
+        "attributes": {}
+      },
+      {
+        "id": "7d35cede-58ce-40cb-a63d-7ce27ceaf4db",
+        "name": "uma_authorization",
+        "description": "${role_uma_authorization}",
+        "composite": false,
+        "clientRole": false,
+        "containerId": "master",
+        "attributes": {}
+      }
+    ],
+    "client": {
+      "oidc-test": [
+        {
+          "id": "894b2e32-3f57-461a-9bd1-c94342a365df",
+          "name": "uma_protection",
+          "composite": false,
+          "clientRole": true,
+          "containerId": "0543361e-6007-4b9a-ad3c-dcc473feaa68",
+          "attributes": {}
+        }
+      ],
+      "security-admin-console": [],
+      "admin-cli": [],
+      "http://localhost:9080/syncope-enduser/": [],
+      "master-realm": [
+        {
+          "id": "4167efac-ca8a-429d-b145-9ca572571073",
+          "name": "query-groups",
+          "description": "${role_query-groups}",
+          "composite": false,
+          "clientRole": true,
+          "containerId": "f44a4b58-3873-4b1f-8907-8cdda73ba648",
+          "attributes": {}
+        },
+        {
+          "id": "91947892-bd70-487f-8909-c66dedb50adf",
+          "name": "manage-events",
+          "description": "${role_manage-events}",
+          "composite": false,
+          "clientRole": true,
+          "containerId": "f44a4b58-3873-4b1f-8907-8cdda73ba648",
+          "attributes": {}
+        },
+        {
+          "id": "fe614065-daf1-472a-ac24-c8731a793123",
+          "name": "manage-authorization",
+          "description": "${role_manage-authorization}",
+          "composite": false,
+          "clientRole": true,
+          "containerId": "f44a4b58-3873-4b1f-8907-8cdda73ba648",
+          "attributes": {}
+        },
+        {
+          "id": "af81c41f-c56b-4b17-b70e-8df75ac312ff",
+          "name": "impersonation",
+          "description": "${role_impersonation}",
+          "composite": false,
+          "clientRole": true,
+          "containerId": "f44a4b58-3873-4b1f-8907-8cdda73ba648",
+          "attributes": {}
+        },
+        {
+          "id": "4ba3ad04-ed50-4a0c-a3e1-b35df435f617",
+          "name": "query-realms",
+          "description": "${role_query-realms}",
+          "composite": false,
+          "clientRole": true,
+          "containerId": "f44a4b58-3873-4b1f-8907-8cdda73ba648",
+          "attributes": {}
+        },
+        {
+          "id": "f05e152c-4498-4fba-b921-ab8460518de4",
+          "name": "view-clients",
+          "description": "${role_view-clients}",
+          "composite": true,
+          "composites": {
+            "client": {
+              "master-realm": [
+                "query-clients"
+              ]
+            }
+          },
+          "clientRole": true,
+          "containerId": "f44a4b58-3873-4b1f-8907-8cdda73ba648",
+          "attributes": {}
+        },
+        {
+          "id": "30a080da-f204-40ad-b05e-0b44f2fcd272",
+          "name": "manage-realm",
+          "description": "${role_manage-realm}",
+          "composite": false,
+          "clientRole": true,
+          "containerId": "f44a4b58-3873-4b1f-8907-8cdda73ba648",
+          "attributes": {}
+        },
+        {
+          "id": "1271c59f-e5af-4d14-873c-1464adf49cfc",
+          "name": "manage-users",
+          "description": "${role_manage-users}",
+          "composite": false,
+          "clientRole": true,
+          "containerId": "f44a4b58-3873-4b1f-8907-8cdda73ba648",
+          "attributes": {}
+        },
+        {
+          "id": "0dbeecc1-7dc8-4b1b-af79-454764baec72",
+          "name": "create-client",
+          "description": "${role_create-client}",
+          "composite": false,
+          "clientRole": true,
+          "containerId": "f44a4b58-3873-4b1f-8907-8cdda73ba648",
+          "attributes": {}
+        },
+        {
+          "id": "f8242770-20b7-4ca4-80a2-e93d738f88a7",
+          "name": "manage-clients",
+          "description": "${role_manage-clients}",
+          "composite": false,
+          "clientRole": true,
+          "containerId": "f44a4b58-3873-4b1f-8907-8cdda73ba648",
+          "attributes": {}
+        },
+        {
+          "id": "827dde28-89de-484d-9a86-cc46a45aa212",
+          "name": "view-authorization",
+          "description": "${role_view-authorization}",
+          "composite": false,
+          "clientRole": true,
+          "containerId": "f44a4b58-3873-4b1f-8907-8cdda73ba648",
+          "attributes": {}
+        },
+        {
+          "id": "22240518-a563-49f3-8c76-e545b1940870",
+          "name": "manage-identity-providers",
+          "description": "${role_manage-identity-providers}",
+          "composite": false,
+          "clientRole": true,
+          "containerId": "f44a4b58-3873-4b1f-8907-8cdda73ba648",
+          "attributes": {}
+        },
+        {
+          "id": "678abcca-231e-419a-b319-54e79626e851",
+          "name": "query-users",
+          "description": "${role_query-users}",
+          "composite": false,
+          "clientRole": true,
+          "containerId": "f44a4b58-3873-4b1f-8907-8cdda73ba648",
+          "attributes": {}
+        },
+        {
+          "id": "175cd662-fdd4-4080-88c8-2f3aa7e45a0b",
+          "name": "view-identity-providers",
+          "description": "${role_view-identity-providers}",
+          "composite": false,
+          "clientRole": true,
+          "containerId": "f44a4b58-3873-4b1f-8907-8cdda73ba648",
+          "attributes": {}
+        },
+        {
+          "id": "38bda15b-0ef5-4d14-b477-07a9a66057d4",
+          "name": "view-users",
+          "description": "${role_view-users}",
+          "composite": true,
+          "composites": {
+            "client": {
+              "master-realm": [
+                "query-groups",
+                "query-users"
+              ]
+            }
+          },
+          "clientRole": true,
+          "containerId": "f44a4b58-3873-4b1f-8907-8cdda73ba648",
+          "attributes": {}
+        },
+        {
+          "id": "aa13c02e-fe23-46c4-b8df-1ee0d74c1af8",
+          "name": "view-realm",
+          "description": "${role_view-realm}",
+          "composite": false,
+          "clientRole": true,
+          "containerId": "f44a4b58-3873-4b1f-8907-8cdda73ba648",
+          "attributes": {}
+        },
+        {
+          "id": "9820eacb-e9b8-43bc-ac91-295f8a1361f4",
+          "name": "query-clients",
+          "description": "${role_query-clients}",
+          "composite": false,
+          "clientRole": true,
+          "containerId": "f44a4b58-3873-4b1f-8907-8cdda73ba648",
+          "attributes": {}
+        },
+        {
+          "id": "1c2fe26f-bfa4-4321-b96b-2e7353eb6665",
+          "name": "view-events",
+          "description": "${role_view-events}",
+          "composite": false,
+          "clientRole": true,
+          "containerId": "f44a4b58-3873-4b1f-8907-8cdda73ba648",
+          "attributes": {}
+        }
+      ],
+      "broker": [
+        {
+          "id": "c90009b0-6879-495e-9f85-c9d39c5fa1ba",
+          "name": "read-token",
+          "description": "${role_read-token}",
+          "composite": false,
+          "clientRole": true,
+          "containerId": "e5f1365e-8227-4f63-b03d-8c5b8ffed1ff",
+          "attributes": {}
+        }
+      ],
+      "account": [
+        {
+          "id": "0f834554-e8f0-4954-96c4-5df669b55a95",
+          "name": "view-profile",
+          "description": "${role_view-profile}",
+          "composite": false,
+          "clientRole": true,
+          "containerId": "9cb0aa44-7e89-4ed2-8702-7bee34b39fdc",
+          "attributes": {}
+        },
+        {
+          "id": "61eef459-9623-4420-b7c5-83d209f79ff9",
+          "name": "uma_protection",
+          "composite": false,
+          "clientRole": true,
+          "containerId": "9cb0aa44-7e89-4ed2-8702-7bee34b39fdc",
+          "attributes": {}
+        },
+        {
+          "id": "e8b0e7f0-d57d-40b4-81d3-a10d999f925f",
+          "name": "manage-account",
+          "description": "${role_manage-account}",
+          "composite": true,
+          "composites": {
+            "client": {
+              "account": [
+                "manage-account-links"
+              ]
+            }
+          },
+          "clientRole": true,
+          "containerId": "9cb0aa44-7e89-4ed2-8702-7bee34b39fdc",
+          "attributes": {}
+        },
+        {
+          "id": "95244445-b81c-43e6-9439-1bfb746a4632",
+          "name": "manage-account-links",
+          "description": "${role_manage-account-links}",
+          "composite": false,
+          "clientRole": true,
+          "containerId": "9cb0aa44-7e89-4ed2-8702-7bee34b39fdc",
+          "attributes": {}
+        }
+      ]
+    }
+  },
+  "groups": [],
+  "defaultRoles": [
+    "offline_access",
+    "uma_authorization"
+  ],
+  "requiredCredentials": [
+    "password"
+  ],
+  "otpPolicyType": "totp",
+  "otpPolicyAlgorithm": "HmacSHA1",
+  "otpPolicyInitialCounter": 0,
+  "otpPolicyDigits": 6,
+  "otpPolicyLookAheadWindow": 1,
+  "otpPolicyPeriod": 30,
+  "otpSupportedApplications": [
+    "FreeOTP",
+    "Google Authenticator"
+  ],
+  "scopeMappings": [
+    {
+      "clientScope": "offline_access",
+      "roles": [
+        "offline_access"
+      ]
+    }
+  ],
+  "clients": [
+    {
+      "id": "9ae76ff0-02bd-4219-be28-1ad02acc24c9",
+      "clientId": "admin-cli",
+      "name": "${client_admin-cli}",
+      "surrogateAuthRequired": false,
+      "enabled": true,
+      "clientAuthenticatorType": "client-secret",
+      "secret": "**********",
+      "redirectUris": [],
+      "webOrigins": [],
+      "notBefore": 0,
+      "bearerOnly": false,
+      "consentRequired": false,
+      "standardFlowEnabled": false,
+      "implicitFlowEnabled": false,
+      "directAccessGrantsEnabled": true,
+      "serviceAccountsEnabled": false,
+      "publicClient": true,
+      "frontchannelLogout": false,
+      "protocol": "openid-connect",
+      "attributes": {},
+      "authenticationFlowBindingOverrides": {},
+      "fullScopeAllowed": false,
+      "nodeReRegistrationTimeout": 0,
+      "defaultClientScopes": [
+        "web-origins",
+        "role_list",
+        "profile",
+        "roles",
+        "email"
+      ],
+      "optionalClientScopes": [
+        "address",
+        "phone",
+        "offline_access",
+        "microprofile-jwt"
+      ]
+    },
+    {
+      "id": "afead16d-8b07-4b25-930a-034922529245",
+      "clientId": "http://localhost:9080/syncope-enduser/";,
+      "name": "SAML Test",
+      "adminUrl": "http://localhost:9090/auth/realms/master";,
+      "surrogateAuthRequired": false,
+      "enabled": true,
+      "clientAuthenticatorType": "client-secret",
+      "secret": "**********",
+      "redirectUris": [
+        "http://localhost:9080/*";
+      ],
+      "webOrigins": [
+        "http://localhost:9080";
+      ],
+      "notBefore": 0,
+      "bearerOnly": false,
+      "consentRequired": false,
+      "standardFlowEnabled": true,
+      "implicitFlowEnabled": false,
+      "directAccessGrantsEnabled": false,
+      "serviceAccountsEnabled": false,
+      "publicClient": false,
+      "frontchannelLogout": true,
+      "protocol": "saml",
+      "attributes": {
+        "saml.assertion.signature": "true",
+        "saml_assertion_consumer_url_redirect": 
"http://localhost:9080/syncope-enduser/saml2sp/assertion-consumer";,
+        "saml_single_logout_service_url_post": 
"http://localhost:9080/syncope-enduser/saml2sp/logout";,
+        "saml.force.post.binding": "true",
+        "saml.multivalued.roles": "false",
+        "saml.encrypt": "false",
+        "saml_assertion_consumer_url_post": 
"http://localhost:9080/syncope-enduser/saml2sp/assertion-consumer";,
+        "saml.server.signature": "true",
+        "saml.server.signature.keyinfo.ext": "false",
+        "exclude.session.state.from.auth.response": "false",
+        "saml.signing.certificate": 
"MIIC9TCCAd0CBgFrCC7kezANBgkqhkiG9w0BAQsFADA+MTwwOgYDVQQDDDNodHRwOi8vc3luY29wZS1zYW1sMi10ZXN0LWNvbTo5MDgwL3N5bmNvcGUtZW5kdXNlci8wHhcNMTkwNTMwMDk1ODM5WhcNMjkwNTMwMTAwMDE5WjA+MTwwOgYDVQQDDDNodHRwOi8vc3luY29wZS1zYW1sMi10ZXN0LWNvbTo5MDgwL3N5bmNvcGUtZW5kdXNlci8wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCF4QsiRZGD7BNx0Bglh4rgtACaIr7R/nDQfdGLN9uSA2HkEPygJzBRyluQLiQv9o/LKQMwvmia5fK4Xt99cgJnmrzKXraKo1KsZNz8vpygMpGJzCA2XUMLe065lYg28PV2bjk6hyUcMehlubjKFQ6USAJG5db
 [...]
+        "saml_single_logout_service_url_redirect": 
"http://localhost:9080/syncope-enduser/saml2sp/logout";,
+        "saml.signature.algorithm": "RSA_SHA256",
+        "saml_force_name_id_format": "false",
+        "tls.client.certificate.bound.access.tokens": "false",
+        "saml.client.signature": "false",
+        "saml.authnstatement": "true",
+        "display.on.consent.screen": "false",
+        "saml_name_id_format": "persistent",
+        "saml.signing.private.key": 
"MIIEowIBAAKCAQEAheELIkWRg+wTcdAYJYeK4LQAmiK+0f5w0H3RizfbkgNh5BD8oCcwUcpbkC4kL/aPyykDML5omuXyuF7ffXICZ5q8yl62iqNSrGTc/L6coDKRicwgNl1DC3tOuZWINvD1dm45OoclHDHoZbm4yhUOlEgCRuXW660s+4ktox0GXMQmQHTzxaWlGaXCTzV1PJ/bPqXkLz3omEbvUFBAf6nv6J70P1iVF8RK8djx5rRvcniECqGnEr6w+q0h8AoMMSYKPrVtdkuG0V4+DcJtoffevT60DvC/HoApBeUS0ntIAWlqmp/R2CEOgf084LBq1DyBsO2QOFluxoC97WaV72WGSwIDAQABAoIBABXnJY0r2Iy+uMesBedN75inmlmdSZ7Ng+N4Uin2r4OJ7iAD73C8OJmJA8Xo5p66NfhE83KsFC0TZcxoKSQ63M3
 [...]
+        "saml_signature_canonicalization_method": 
"http://www.w3.org/2001/10/xml-exc-c14n#";,
+        "saml.onetimeuse.condition": "false"
+      },
+      "authenticationFlowBindingOverrides": {},
+      "fullScopeAllowed": true,
+      "nodeReRegistrationTimeout": -1,
+      "protocolMappers": [
+        {
+          "id": "9cd8a79b-97f9-459f-a2fb-802f217059f3",
+          "name": "lastName",
+          "protocol": "saml",
+          "protocolMapper": "saml-user-attribute-mapper",
+          "consentRequired": false,
+          "config": {
+            "attribute.nameformat": "Basic",
+            "user.attribute": "lastName",
+            "friendly.name": "lastName",
+            "attribute.name": "lastName"
+          }
+        },
+        {
+          "id": "c3bb90a6-8443-4dfa-9755-6cb90294b488",
+          "name": "fullName",
+          "protocol": "saml",
+          "protocolMapper": "saml-user-attribute-mapper",
+          "consentRequired": false,
+          "config": {
+            "attribute.nameformat": "Basic",
+            "user.attribute": "fullName",
+            "friendly.name": "fullName",
+            "attribute.name": "fullName"
+          }
+        },
+        {
+          "id": "8b599498-cd22-4bf0-b999-2b8822b27c2b",
+          "name": "username",
+          "protocol": "saml",
+          "protocolMapper": "saml-user-attribute-mapper",
+          "consentRequired": false,
+          "config": {
+            "attribute.nameformat": "Basic",
+            "user.attribute": "username",
+            "friendly.name": "username",
+            "attribute.name": "username"
+          }
+        },
+        {
+          "id": "a927aea7-2c71-460b-9eff-cdb1c1979f88",
+          "name": "email",
+          "protocol": "saml",
+          "protocolMapper": "saml-user-attribute-mapper",
+          "consentRequired": false,
+          "config": {
+            "attribute.nameformat": "Basic",
+            "user.attribute": "email",
+            "friendly.name": "email",
+            "attribute.name": "email"
+          }
+        }
+      ],
+      "defaultClientScopes": [
+        "web-origins",
+        "role_list",
+        "profile",
+        "roles",
+        "email"
+      ],
+      "optionalClientScopes": [
+        "address",
+        "phone",
+        "offline_access",
+        "microprofile-jwt"
+      ]
+    },
+    {
+      "id": "f44a4b58-3873-4b1f-8907-8cdda73ba648",
+      "clientId": "master-realm",
+      "name": "master Realm",
+      "surrogateAuthRequired": false,
+      "enabled": true,
+      "clientAuthenticatorType": "client-secret",
+      "secret": "**********",
+      "redirectUris": [],
+      "webOrigins": [],
+      "notBefore": 0,
+      "bearerOnly": true,
+      "consentRequired": false,
+      "standardFlowEnabled": true,
+      "implicitFlowEnabled": false,
+      "directAccessGrantsEnabled": false,
+      "serviceAccountsEnabled": false,
+      "publicClient": false,
+      "frontchannelLogout": false,
+      "attributes": {},
+      "authenticationFlowBindingOverrides": {},
+      "fullScopeAllowed": true,
+      "nodeReRegistrationTimeout": 0,
+      "defaultClientScopes": [
+        "web-origins",
+        "role_list",
+        "profile",
+        "roles",
+        "email"
+      ],
+      "optionalClientScopes": [
+        "address",
+        "phone",
+        "offline_access",
+        "microprofile-jwt"
+      ]
+    },
+    {
+      "id": "95e0b6dc-15fe-416c-be90-cc4a78aab0de",
+      "clientId": "security-admin-console",
+      "name": "${client_security-admin-console}",
+      "baseUrl": "/auth/admin/master/console/index.html",
+      "surrogateAuthRequired": false,
+      "enabled": true,
+      "clientAuthenticatorType": "client-secret",
+      "secret": "**********",
+      "redirectUris": [
+        "/auth/admin/master/console/*"
+      ],
+      "webOrigins": [],
+      "notBefore": 0,
+      "bearerOnly": false,
+      "consentRequired": false,
+      "standardFlowEnabled": true,
+      "implicitFlowEnabled": false,
+      "directAccessGrantsEnabled": false,
+      "serviceAccountsEnabled": false,
+      "publicClient": true,
+      "frontchannelLogout": false,
+      "protocol": "openid-connect",
+      "attributes": {},
+      "authenticationFlowBindingOverrides": {},
+      "fullScopeAllowed": false,
+      "nodeReRegistrationTimeout": 0,
+      "protocolMappers": [
+        {
+          "id": "e23cb190-a256-443f-8099-78f7e48fbff2",
+          "name": "locale",
+          "protocol": "openid-connect",
+          "protocolMapper": "oidc-usermodel-attribute-mapper",
+          "consentRequired": false,
+          "config": {
+            "userinfo.token.claim": "true",
+            "user.attribute": "locale",
+            "id.token.claim": "true",
+            "access.token.claim": "true",
+            "claim.name": "locale",
+            "jsonType.label": "String"
+          }
+        }
+      ],
+      "defaultClientScopes": [
+        "web-origins",
+        "role_list",
+        "profile",
+        "roles",
+        "email"
+      ],
+      "optionalClientScopes": [
+        "address",
+        "phone",
+        "offline_access",
+        "microprofile-jwt"
+      ]
+    },
+    {
+      "id": "0543361e-6007-4b9a-ad3c-dcc473feaa68",
+      "clientId": "oidc-test",
+      "name": "OIDC Test",
+      "baseUrl": "/auth/realms/master/oidc-test",
+      "surrogateAuthRequired": false,
+      "enabled": true,
+      "clientAuthenticatorType": "client-secret",
+      "secret": "**********",
+      "redirectUris": [
+        "http://localhost:9080/syncope-console/oidcclient/code-consumer";,
+        "/auth/realms/master/oidc-test/*",
+        "http://localhost:9080/syncope-enduser/oidcclient/code-consumer";
+      ],
+      "webOrigins": [],
+      "notBefore": 0,
+      "bearerOnly": false,
+      "consentRequired": false,
+      "standardFlowEnabled": true,
+      "implicitFlowEnabled": true,
+      "directAccessGrantsEnabled": true,
+      "serviceAccountsEnabled": true,
+      "authorizationServicesEnabled": true,
+      "publicClient": false,
+      "frontchannelLogout": false,
+      "protocol": "openid-connect",
+      "attributes": {
+        "saml.assertion.signature": "false",
+        "saml.multivalued.roles": "false",
+        "saml.force.post.binding": "false",
+        "saml.encrypt": "false",
+        "saml.server.signature": "false",
+        "saml.server.signature.keyinfo.ext": "false",
+        "exclude.session.state.from.auth.response": "false",
+        "saml_force_name_id_format": "false",
+        "saml.client.signature": "false",
+        "tls.client.certificate.bound.access.tokens": "false",
+        "saml.authnstatement": "false",
+        "display.on.consent.screen": "false",
+        "saml.onetimeuse.condition": "false"
+      },
+      "authenticationFlowBindingOverrides": {},
+      "fullScopeAllowed": true,
+      "nodeReRegistrationTimeout": -1,
+      "protocolMappers": [
+        {
+          "id": "3bbeb91e-7a38-4a03-aafc-5e364e4ef3ea",
+          "name": "Client Host",
+          "protocol": "openid-connect",
+          "protocolMapper": "oidc-usersessionmodel-note-mapper",
+          "consentRequired": false,
+          "config": {
+            "user.session.note": "clientHost",
+            "id.token.claim": "true",
+            "access.token.claim": "true",
+            "claim.name": "clientHost",
+            "jsonType.label": "String"
+          }
+        },
+        {
+          "id": "f6049611-4378-4aeb-8423-b8166df0e046",
+          "name": "Client ID",
+          "protocol": "openid-connect",
+          "protocolMapper": "oidc-usersessionmodel-note-mapper",
+          "consentRequired": false,
+          "config": {
+            "user.session.note": "clientId",
+            "id.token.claim": "true",
+            "access.token.claim": "true",
+            "claim.name": "clientId",
+            "jsonType.label": "String"
+          }
+        },
+        {
+          "id": "173d39bf-8c71-4c0f-9264-44d9bd143fd0",
+          "name": "Client IP Address",
+          "protocol": "openid-connect",
+          "protocolMapper": "oidc-usersessionmodel-note-mapper",
+          "consentRequired": false,
+          "config": {
+            "user.session.note": "clientAddress",
+            "id.token.claim": "true",
+            "access.token.claim": "true",
+            "claim.name": "clientAddress",
+            "jsonType.label": "String"
+          }
+        }
+      ],
+      "defaultClientScopes": [
+        "web-origins",
+        "role_list",
+        "profile",
+        "roles",
+        "email"
+      ],
+      "optionalClientScopes": [
+        "address",
+        "phone",
+        "offline_access",
+        "microprofile-jwt"
+      ],
+      "authorizationSettings": {
+        "allowRemoteResourceManagement": true,
+        "policyEnforcementMode": "ENFORCING",
+        "resources": [
+          {
+            "name": "Default Resource",
+            "type": "urn:oidc-test:resources:default",
+            "ownerManagedAccess": false,
+            "attributes": {},
+            "_id": "f044b62c-be85-40b1-a646-ab000764337e",
+            "uris": [
+              "/*"
+            ]
+          }
+        ],
+        "policies": [
+          {
+            "id": "4077b1d8-acb5-4aab-b88a-0d4f07da107e",
+            "name": "Default Policy",
+            "description": "A policy that grants access only for users within 
this realm",
+            "type": "js",
+            "logic": "POSITIVE",
+            "decisionStrategy": "AFFIRMATIVE",
+            "config": {
+              "code": "// by default, grants any permission associated with 
this policy\n$evaluation.grant();\n"
+            }
+          },
+          {
+            "id": "5e54be75-0d3f-483a-b47e-c24e36d0b666",
+            "name": "Default Permission",
+            "description": "A permission that applies to the default resource 
type",
+            "type": "resource",
+            "logic": "POSITIVE",
+            "decisionStrategy": "UNANIMOUS",
+            "config": {
+              "defaultResourceType": "urn:oidc-test:resources:default",
+              "applyPolicies": "[\"Default Policy\"]"
+            }
+          }
+        ],
+        "scopes": []
+      }
+    },
+    {
+      "id": "9cb0aa44-7e89-4ed2-8702-7bee34b39fdc",
+      "clientId": "account",
+      "name": "${client_account}",
+      "baseUrl": "/auth/realms/master/account",
+      "surrogateAuthRequired": false,
+      "enabled": true,
+      "clientAuthenticatorType": "client-secret",
+      "secret": "**********",
+      "defaultRoles": [
+        "view-profile",
+        "manage-account"
+      ],
+      "redirectUris": [
+        "http://localhost:9080/syncope-console/oidcclient/code-consumer";,
+        "/auth/realms/master/account/*",
+        "http://localhost:9080/syncope-enduser/oidcclient/code-consumer";
+      ],
+      "webOrigins": [],
+      "notBefore": 0,
+      "bearerOnly": false,
+      "consentRequired": true,
+      "standardFlowEnabled": true,
+      "implicitFlowEnabled": true,
+      "directAccessGrantsEnabled": true,
+      "serviceAccountsEnabled": true,
+      "authorizationServicesEnabled": true,
+      "publicClient": false,
+      "frontchannelLogout": false,
+      "protocol": "openid-connect",
+      "attributes": {
+        "saml.assertion.signature": "false",
+        "saml.force.post.binding": "false",
+        "saml.multivalued.roles": "false",
+        "saml.encrypt": "false",
+        "saml.server.signature": "false",
+        "saml.server.signature.keyinfo.ext": "false",
+        "exclude.session.state.from.auth.response": "false",
+        "saml_force_name_id_format": "false",
+        "saml.client.signature": "false",
+        "tls.client.certificate.bound.access.tokens": "false",
+        "saml.authnstatement": "false",
+        "display.on.consent.screen": "false",
+        "saml.onetimeuse.condition": "false"
+      },
+      "authenticationFlowBindingOverrides": {},
+      "fullScopeAllowed": false,
+      "nodeReRegistrationTimeout": 0,
+      "protocolMappers": [
+        {
+          "id": "6db42642-9862-4b48-a986-1fe7d2bf2a24",
+          "name": "name",
+          "protocol": "openid-connect",
+          "protocolMapper": "oidc-usermodel-attribute-mapper",
+          "consentRequired": false,
+          "config": {
+            "userinfo.token.claim": "true",
+            "user.attribute": "name",
+            "id.token.claim": "true",
+            "access.token.claim": "true",
+            "claim.name": "name",
+            "jsonType.label": "String"
+          }
+        },
+        {
+          "id": "6efff622-0813-49f8-baf2-01c117cd9744",
+          "name": "Client IP Address",
+          "protocol": "openid-connect",
+          "protocolMapper": "oidc-usersessionmodel-note-mapper",
+          "consentRequired": false,
+          "config": {
+            "user.session.note": "clientAddress",
+            "id.token.claim": "true",
+            "access.token.claim": "true",
+            "claim.name": "clientAddress",
+            "jsonType.label": "String"
+          }
+        },
+        {
+          "id": "e46eb849-c977-425a-b2fe-c032ea0f4b95",
+          "name": "Client ID",
+          "protocol": "openid-connect",
+          "protocolMapper": "oidc-usersessionmodel-note-mapper",
+          "consentRequired": false,
+          "config": {
+            "user.session.note": "clientId",
+            "id.token.claim": "true",
+            "access.token.claim": "true",
+            "claim.name": "clientId",
+            "jsonType.label": "String"
+          }
+        },
+        {
+          "id": "76a37cf4-2f46-4f89-b7cd-cb1e75dc95a2",
+          "name": "fullName",
+          "protocol": "openid-connect",
+          "protocolMapper": "oidc-usermodel-attribute-mapper",
+          "consentRequired": false,
+          "config": {
+            "userinfo.token.claim": "true",
+            "user.attribute": "fullName",
+            "id.token.claim": "true",
+            "access.token.claim": "true",
+            "claim.name": "fullName",
+            "jsonType.label": "String"
+          }
+        },
+        {
+          "id": "f6121e29-62b9-44e9-8e76-1c98d98b48d5",
+          "name": "email",
+          "protocol": "openid-connect",
+          "protocolMapper": "oidc-usermodel-attribute-mapper",
+          "consentRequired": false,
+          "config": {
+            "userinfo.token.claim": "true",
+            "user.attribute": "email",
+            "id.token.claim": "true",
+            "access.token.claim": "true",
+            "claim.name": "email",
+            "jsonType.label": "String"
+          }
+        },
+        {
+          "id": "e3adc691-0b44-491a-9778-769909091969",
+          "name": "lastName",
+          "protocol": "openid-connect",
+          "protocolMapper": "oidc-usermodel-attribute-mapper",
+          "consentRequired": false,
+          "config": {
+            "userinfo.token.claim": "true",
+            "user.attribute": "lastName",
+            "id.token.claim": "true",
+            "access.token.claim": "true",
+            "claim.name": "lastName",
+            "jsonType.label": "String"
+          }
+        },
+        {
+          "id": "b5618073-5b83-4528-bd9a-99ca9807847d",
+          "name": "Client Host",
+          "protocol": "openid-connect",
+          "protocolMapper": "oidc-usersessionmodel-note-mapper",
+          "consentRequired": false,
+          "config": {
+            "user.session.note": "clientHost",
+            "id.token.claim": "true",
+            "access.token.claim": "true",
+            "claim.name": "clientHost",
+            "jsonType.label": "String"
+          }
+        }
+      ],
+      "defaultClientScopes": [
+        "web-origins",
+        "role_list",
+        "profile",
+        "roles",
+        "email"
+      ],
+      "optionalClientScopes": [
+        "address",
+        "phone",
+        "offline_access",
+        "microprofile-jwt"
+      ],
+      "authorizationSettings": {
+        "allowRemoteResourceManagement": true,
+        "policyEnforcementMode": "ENFORCING",
+        "resources": [
+          {
+            "name": "Default Resource",
+            "type": "urn:account:resources:default",
+            "ownerManagedAccess": false,
+            "attributes": {},
+            "_id": "e85a7be3-724c-4846-9d60-67296333ef02",
+            "uris": [
+              "/*"
+            ]
+          }
+        ],
+        "policies": [
+          {
+            "id": "a75fd4f9-6936-4e39-a535-589ad7356f8f",
+            "name": "Default Policy",
+            "description": "A policy that grants access only for users within 
this realm",
+            "type": "js",
+            "logic": "POSITIVE",
+            "decisionStrategy": "AFFIRMATIVE",
+            "config": {
+              "code": "// by default, grants any permission associated with 
this policy\n$evaluation.grant();\n"
+            }
+          },
+          {
+            "id": "92627286-24a8-4bf3-ad26-d618da21ea80",
+            "name": "Default Permission",
+            "description": "A permission that applies to the default resource 
type",
+            "type": "resource",
+            "logic": "POSITIVE",
+            "decisionStrategy": "UNANIMOUS",
+            "config": {
+              "defaultResourceType": "urn:account:resources:default",
+              "applyPolicies": "[\"Default Policy\"]"
+            }
+          }
+        ],
+        "scopes": []
+      }
+    },
+    {
+      "id": "e5f1365e-8227-4f63-b03d-8c5b8ffed1ff",
+      "clientId": "broker",
+      "name": "${client_broker}",
+      "surrogateAuthRequired": false,
+      "enabled": true,
+      "clientAuthenticatorType": "client-secret",
+      "secret": "**********",
+      "redirectUris": [],
+      "webOrigins": [],
+      "notBefore": 0,
+      "bearerOnly": false,
+      "consentRequired": false,
+      "standardFlowEnabled": true,
+      "implicitFlowEnabled": false,
+      "directAccessGrantsEnabled": false,
+      "serviceAccountsEnabled": false,
+      "publicClient": false,
+      "frontchannelLogout": false,
+      "protocol": "openid-connect",
+      "attributes": {},
+      "authenticationFlowBindingOverrides": {},
+      "fullScopeAllowed": false,
+      "nodeReRegistrationTimeout": 0,
+      "defaultClientScopes": [
+        "web-origins",
+        "role_list",
+        "profile",
+        "roles",
+        "email"
+      ],
+      "optionalClientScopes": [
+        "address",
+        "phone",
+        "offline_access",
+        "microprofile-jwt"
+      ]
+    }
+  ],
+  "clientScopes": [
+    {
+      "id": "207751c3-8697-414d-a451-adee6328df75",
+      "name": "microprofile-jwt",
+      "description": "Microprofile - JWT built-in scope",
+      "protocol": "openid-connect",
+      "attributes": {
+        "include.in.token.scope": "true",
+        "display.on.consent.screen": "false"
+      },
+      "protocolMappers": [
+        {
+          "id": "b1bfd849-9f78-4e31-a3fd-f4c85ddfd37b",
+          "name": "upn",
+          "protocol": "openid-connect",
+          "protocolMapper": "oidc-usermodel-property-mapper",
+          "consentRequired": false,
+          "config": {
+            "userinfo.token.claim": "true",
+            "user.attribute": "username",
+            "id.token.claim": "true",
+            "access.token.claim": "true",
+            "claim.name": "upn",
+            "jsonType.label": "String"
+          }
+        },
+        {
+          "id": "27ab40ce-ce70-49a4-b153-d5375d2cc5b0",
+          "name": "groups",
+          "protocol": "openid-connect",
+          "protocolMapper": "oidc-usermodel-realm-role-mapper",
+          "consentRequired": false,
+          "config": {
+            "multivalued": "true",
+            "user.attribute": "foo",
+            "id.token.claim": "true",
+            "access.token.claim": "true",
+            "claim.name": "groups",
+            "jsonType.label": "String"
+          }
+        }
+      ]
+    },
+    {
+      "id": "66d7c7ef-1ddf-48ec-b6f1-0d8119b5b151",
+      "name": "web-origins",
+      "description": "OpenID Connect scope for add allowed web origins to the 
access token",
+      "protocol": "openid-connect",
+      "attributes": {
+        "include.in.token.scope": "false",
+        "display.on.consent.screen": "false",
+        "consent.screen.text": ""
+      },
+      "protocolMappers": [
+        {
+          "id": "f1458f25-d330-496f-9c42-55f176dfe47c",
+          "name": "allowed web origins",
+          "protocol": "openid-connect",
+          "protocolMapper": "oidc-allowed-origins-mapper",
+          "consentRequired": false,
+          "config": {}
+        }
+      ]
+    },
+    {
+      "id": "c89df48d-160a-4e7f-b9e9-41f7b7de9bdb",
+      "name": "roles",
+      "description": "OpenID Connect scope for add user roles to the access 
token",
+      "protocol": "openid-connect",
+      "attributes": {
+        "include.in.token.scope": "false",
+        "display.on.consent.screen": "true",
+        "consent.screen.text": "${rolesScopeConsentText}"
+      },
+      "protocolMappers": [
+        {
+          "id": "fa759cdc-914f-4012-bee0-0b6c89dde9f7",
+          "name": "realm roles",
+          "protocol": "openid-connect",
+          "protocolMapper": "oidc-usermodel-realm-role-mapper",
+          "consentRequired": false,
+          "config": {
+            "multivalued": "true",
+            "user.attribute": "foo",
+            "access.token.claim": "true",
+            "claim.name": "realm_access.roles",
+            "jsonType.label": "String"
+          }
+        },
+        {
+          "id": "a833736e-c483-4205-9172-038fd9f2e58e",
+          "name": "client roles",
+          "protocol": "openid-connect",
+          "protocolMapper": "oidc-usermodel-client-role-mapper",
+          "consentRequired": false,
+          "config": {
+            "multivalued": "true",
+            "user.attribute": "foo",
+            "access.token.claim": "true",
+            "claim.name": "resource_access.${client_id}.roles",
+            "jsonType.label": "String"
+          }
+        },
+        {
+          "id": "6cfa6171-fc45-4048-854e-3971f34feae7",
+          "name": "audience resolve",
+          "protocol": "openid-connect",
+          "protocolMapper": "oidc-audience-resolve-mapper",
+          "consentRequired": false,
+          "config": {}
+        }
+      ]
+    },
+    {
+      "id": "13bd781f-9c09-4586-b21f-0b4f793352b3",
+      "name": "phone",
+      "description": "OpenID Connect built-in scope: phone",
+      "protocol": "openid-connect",
+      "attributes": {
+        "include.in.token.scope": "true",
+        "display.on.consent.screen": "true",
+        "consent.screen.text": "${phoneScopeConsentText}"
+      },
+      "protocolMappers": [
+        {
+          "id": "9821b172-56a1-4ba3-aee3-1c7fa12e2c41",
+          "name": "phone number",
+          "protocol": "openid-connect",
+          "protocolMapper": "oidc-usermodel-attribute-mapper",
+          "consentRequired": false,
+          "config": {
+            "userinfo.token.claim": "true",
+            "user.attribute": "phoneNumber",
+            "id.token.claim": "true",
+            "access.token.claim": "true",
+            "claim.name": "phone_number",
+            "jsonType.label": "String"
+          }
+        },
+        {
+          "id": "554855cc-a829-4bdb-9bcf-c1f150df0c9b",
+          "name": "phone number verified",
+          "protocol": "openid-connect",
+          "protocolMapper": "oidc-usermodel-attribute-mapper",
+          "consentRequired": false,
+          "config": {
+            "userinfo.token.claim": "true",
+            "user.attribute": "phoneNumberVerified",
+            "id.token.claim": "true",
+            "access.token.claim": "true",
+            "claim.name": "phone_number_verified",
+            "jsonType.label": "boolean"
+          }
+        }
+      ]
+    },
+    {
+      "id": "a99a4e9a-196b-4977-ba63-24c238f28ff6",
+      "name": "address",
+      "description": "OpenID Connect built-in scope: address",
+      "protocol": "openid-connect",
+      "attributes": {
+        "include.in.token.scope": "true",
+        "display.on.consent.screen": "true",
+        "consent.screen.text": "${addressScopeConsentText}"
+      },
+      "protocolMappers": [
+        {
+          "id": "bd77d1a7-e786-4a27-bf0a-3ed299346f95",
+          "name": "address",
+          "protocol": "openid-connect",
+          "protocolMapper": "oidc-address-mapper",
+          "consentRequired": false,
+          "config": {
+            "user.attribute.formatted": "formatted",
+            "user.attribute.country": "country",
+            "user.attribute.postal_code": "postal_code",
+            "userinfo.token.claim": "true",
+            "user.attribute.street": "street",
+            "id.token.claim": "true",
+            "user.attribute.region": "region",
+            "access.token.claim": "true",
+            "user.attribute.locality": "locality"
+          }
+        }
+      ]
+    },
+    {
+      "id": "103bef92-6694-4dd9-bb94-860cf3891ea0",
+      "name": "email",
+      "description": "OpenID Connect built-in scope: email",
+      "protocol": "openid-connect",
+      "attributes": {
+        "include.in.token.scope": "true",
+        "display.on.consent.screen": "true",
+        "consent.screen.text": "${emailScopeConsentText}"
+      },
+      "protocolMappers": [
+        {
+          "id": "2caa0eee-d72d-4f4d-8515-3625f046f274",
+          "name": "email",
+          "protocol": "openid-connect",
+          "protocolMapper": "oidc-usermodel-property-mapper",
+          "consentRequired": false,
+          "config": {
+            "userinfo.token.claim": "true",
+            "user.attribute": "email",
+            "id.token.claim": "true",
+            "access.token.claim": "true",
+            "claim.name": "email",
+            "jsonType.label": "String"
+          }
+        },
+        {
+          "id": "e95028fa-6f26-4dad-bb10-89d39a466ab5",
+          "name": "email verified",
+          "protocol": "openid-connect",
+          "protocolMapper": "oidc-usermodel-property-mapper",
+          "consentRequired": false,
+          "config": {
+            "userinfo.token.claim": "true",
+            "user.attribute": "emailVerified",
+            "id.token.claim": "true",
+            "access.token.claim": "true",
+            "claim.name": "email_verified",
+            "jsonType.label": "boolean"
+          }
+        }
+      ]
+    },
+    {
+      "id": "2165534b-1305-480e-8be6-e08428bd7710",
+      "name": "profile",
+      "description": "OpenID Connect built-in scope: profile",
+      "protocol": "openid-connect",
+      "attributes": {
+        "include.in.token.scope": "true",
+        "display.on.consent.screen": "true",
+        "consent.screen.text": "${profileScopeConsentText}"
+      },
+      "protocolMappers": [
+        {
+          "id": "b0a63a0f-d4a5-420e-b8c8-2b9e3de310df",
+          "name": "birthdate",
+          "protocol": "openid-connect",
+          "protocolMapper": "oidc-usermodel-attribute-mapper",
+          "consentRequired": false,
+          "config": {
+            "userinfo.token.claim": "true",
+            "user.attribute": "birthdate",
+            "id.token.claim": "true",
+            "access.token.claim": "true",
+            "claim.name": "birthdate",
+            "jsonType.label": "String"
+          }
+        },
+        {
+          "id": "f32785d8-3963-4570-b77a-5710326b32b6",
+          "name": "middle name",
+          "protocol": "openid-connect",
+          "protocolMapper": "oidc-usermodel-attribute-mapper",
+          "consentRequired": false,
+          "config": {
+            "userinfo.token.claim": "true",
+            "user.attribute": "middleName",
+            "id.token.claim": "true",
+            "access.token.claim": "true",
+            "claim.name": "middle_name",
+            "jsonType.label": "String"
+          }
+        },
+        {
+          "id": "ac364875-5fe9-443e-bdab-c779998ec18a",
+          "name": "given name",
+          "protocol": "openid-connect",
+          "protocolMapper": "oidc-usermodel-property-mapper",
+          "consentRequired": false,
+          "config": {
+            "userinfo.token.claim": "true",
+            "user.attribute": "firstName",
+            "id.token.claim": "true",
+            "access.token.claim": "true",
+            "claim.name": "given_name",
+            "jsonType.label": "String"
+          }
+        },
+        {
+          "id": "61244f24-5f5b-4bd1-a738-08f0d5147da0",
+          "name": "updated at",
+          "protocol": "openid-connect",
+          "protocolMapper": "oidc-usermodel-attribute-mapper",
+          "consentRequired": false,
+          "config": {
+            "userinfo.token.claim": "true",
+            "user.attribute": "updatedAt",
+            "id.token.claim": "true",
+            "access.token.claim": "true",
+            "claim.name": "updated_at",
+            "jsonType.label": "String"
+          }
+        },
+        {
+          "id": "e3ae74e7-11e3-469b-ad10-69419062e61e",
+          "name": "full name",
+          "protocol": "openid-connect",
+          "protocolMapper": "oidc-full-name-mapper",
+          "consentRequired": false,
+          "config": {
+            "id.token.claim": "true",
+            "access.token.claim": "true",
+            "userinfo.token.claim": "true"
+          }
+        },
+        {
+          "id": "d39af8e4-7804-4209-b8fc-361c199e4eff",
+          "name": "gender",
+          "protocol": "openid-connect",
+          "protocolMapper": "oidc-usermodel-attribute-mapper",
+          "consentRequired": false,
+          "config": {
+            "userinfo.token.claim": "true",
+            "user.attribute": "gender",
+            "id.token.claim": "true",
+            "access.token.claim": "true",
+            "claim.name": "gender",
+            "jsonType.label": "String"
+          }
+        },
+        {
+          "id": "9b944fe3-04a5-4ed6-9743-57b1d93b3c12",
+          "name": "username",
+          "protocol": "openid-connect",
+          "protocolMapper": "oidc-usermodel-property-mapper",
+          "consentRequired": false,
+          "config": {
+            "userinfo.token.claim": "true",
+            "user.attribute": "username",
+            "id.token.claim": "true",
+            "access.token.claim": "true",
+            "claim.name": "preferred_username",
+            "jsonType.label": "String"
+          }
+        },
+        {
+          "id": "63a62a59-48aa-41c8-a878-6e2a49170671",
+          "name": "profile",
+          "protocol": "openid-connect",
+          "protocolMapper": "oidc-usermodel-attribute-mapper",
+          "consentRequired": false,
+          "config": {
+            "userinfo.token.claim": "true",
+            "user.attribute": "profile",
+            "id.token.claim": "true",
+            "access.token.claim": "true",
+            "claim.name": "profile",
+            "jsonType.label": "String"
+          }
+        },
+        {
+          "id": "d2b9e956-9f84-4239-b9fb-4aaa66efe5d3",
+          "name": "nickname",
+          "protocol": "openid-connect",
+          "protocolMapper": "oidc-usermodel-attribute-mapper",
+          "consentRequired": false,
+          "config": {
+            "userinfo.token.claim": "true",
+            "user.attribute": "nickname",
+            "id.token.claim": "true",
+            "access.token.claim": "true",
+            "claim.name": "nickname",
+            "jsonType.label": "String"
+          }
+        },
+        {
+          "id": "13172ca3-1175-433d-b5a9-e3e8904c76cb",
+          "name": "family name",
+          "protocol": "openid-connect",
+          "protocolMapper": "oidc-usermodel-property-mapper",
+          "consentRequired": false,
+          "config": {
+            "userinfo.token.claim": "true",
+            "user.attribute": "lastName",
+            "id.token.claim": "true",
+            "access.token.claim": "true",
+            "claim.name": "family_name",
+            "jsonType.label": "String"
+          }
+        },
+        {
+          "id": "d9d54937-de59-4040-a5e4-f721a9facaef",
+          "name": "zoneinfo",
+          "protocol": "openid-connect",
+          "protocolMapper": "oidc-usermodel-attribute-mapper",
+          "consentRequired": false,
+          "config": {
+            "userinfo.token.claim": "true",
+            "user.attribute": "zoneinfo",
+            "id.token.claim": "true",
+            "access.token.claim": "true",
+            "claim.name": "zoneinfo",
+            "jsonType.label": "String"
+          }
+        },
+        {
+          "id": "07e30efd-7f88-4e7e-9d65-eef422e3ba3c",
+          "name": "locale",
+          "protocol": "openid-connect",
+          "protocolMapper": "oidc-usermodel-attribute-mapper",
+          "consentRequired": false,
+          "config": {
+            "userinfo.token.claim": "true",
+            "user.attribute": "locale",
+            "id.token.claim": "true",
+            "access.token.claim": "true",
+            "claim.name": "locale",
+            "jsonType.label": "String"
+          }
+        },
+        {
+          "id": "6d69ff26-82d8-4750-bc1c-2c6a54951dc1",
+          "name": "website",
+          "protocol": "openid-connect",
+          "protocolMapper": "oidc-usermodel-attribute-mapper",
+          "consentRequired": false,
+          "config": {
+            "userinfo.token.claim": "true",
+            "user.attribute": "website",
+            "id.token.claim": "true",
+            "access.token.claim": "true",
+            "claim.name": "website",
+            "jsonType.label": "String"
+          }
+        },
+        {
+          "id": "fcc5ca45-020e-4edc-8279-e6e7d8a5df29",
+          "name": "picture",
+          "protocol": "openid-connect",
+          "protocolMapper": "oidc-usermodel-attribute-mapper",
+          "consentRequired": false,
+          "config": {
+            "userinfo.token.claim": "true",
+            "user.attribute": "picture",
+            "id.token.claim": "true",
+            "access.token.claim": "true",
+            "claim.name": "picture",
+            "jsonType.label": "String"
+          }
+        }
+      ]
+    },
+    {
+      "id": "07e46091-35cc-491e-9776-03077bae3a0c",
+      "name": "role_list",
+      "description": "SAML role list",
+      "protocol": "saml",
+      "attributes": {
+        "consent.screen.text": "${samlRoleListScopeConsentText}",
+        "display.on.consent.screen": "true"
+      },
+      "protocolMappers": [
+        {
+          "id": "ff63d4a8-358f-4e0b-9807-32dfcc889bdc",
+          "name": "role list",
+          "protocol": "saml",
+          "protocolMapper": "saml-role-list-mapper",
+          "consentRequired": false,
+          "config": {
+            "single": "false",
+            "attribute.nameformat": "Basic",
+            "attribute.name": "Role"
+          }
+        }
+      ]
+    },
+    {
+      "id": "ff466f99-32f2-4584-bc41-72b6a13a6fbd",
+      "name": "offline_access",
+      "description": "OpenID Connect built-in scope: offline_access",
+      "protocol": "openid-connect",
+      "attributes": {
+        "consent.screen.text": "${offlineAccessScopeConsentText}",
+        "display.on.consent.screen": "true"
+      }
+    }
+  ],
+  "defaultDefaultClientScopes": [
+    "role_list",
+    "profile",
+    "email",
+    "roles",
+    "web-origins"
+  ],
+  "defaultOptionalClientScopes": [
+    "offline_access",
+    "address",
+    "phone",
+    "microprofile-jwt"
+  ],
+  "browserSecurityHeaders": {
+    "contentSecurityPolicyReportOnly": "",
+    "xContentTypeOptions": "nosniff",
+    "xRobotsTag": "none",
+    "xFrameOptions": "SAMEORIGIN",
+    "xXSSProtection": "1; mode=block",
+    "contentSecurityPolicy": "frame-src 'self'; frame-ancestors 'self'; 
object-src 'none';",
+    "strictTransportSecurity": "max-age=31536000; includeSubDomains"
+  },
+  "smtpServer": {},
+  "eventsEnabled": false,
+  "eventsListeners": [
+    "jboss-logging"
+  ],
+  "enabledEventTypes": [],
+  "adminEventsEnabled": false,
+  "adminEventsDetailsEnabled": false,
+  "components": {
+    
"org.keycloak.services.clientregistration.policy.ClientRegistrationPolicy": [
+      {
+        "id": "f57951e7-7557-4c48-b779-b59216e9b1d8",
+        "name": "Allowed Client Scopes",
+        "providerId": "allowed-client-templates",
+        "subType": "authenticated",
+        "subComponents": {},
+        "config": {
+          "allow-default-scopes": [
+            "true"
+          ]
+        }
+      },
+      {
+        "id": "0fd0e4b7-b5d5-4132-9e84-d72bb95c976b",
+        "name": "Trusted Hosts",
+        "providerId": "trusted-hosts",
+        "subType": "anonymous",
+        "subComponents": {},
+        "config": {
+          "host-sending-registration-request-must-match": [
+            "true"
+          ],
+          "client-uris-must-match": [
+            "true"
+          ]
+        }
+      },
+      {
+        "id": "db90a46c-a2d9-44af-ae23-9af115b07134",
+        "name": "Max Clients Limit",
+        "providerId": "max-clients",
+        "subType": "anonymous",
+        "subComponents": {},
+        "config": {
+          "max-clients": [
+            "200"
+          ]
+        }
+      },
+      {
+        "id": "cff490e0-3924-4c22-bb4a-0f457a7bb37f",
+        "name": "Allowed Protocol Mapper Types",
+        "providerId": "allowed-protocol-mappers",
+        "subType": "authenticated",
+        "subComponents": {},
+        "config": {
+          "allowed-protocol-mapper-types": [
+            "saml-user-property-mapper",
+            "oidc-usermodel-property-mapper",
+            "oidc-usermodel-attribute-mapper",
+            "oidc-full-name-mapper",
+            "oidc-address-mapper",
+            "saml-role-list-mapper",
+            "oidc-sha256-pairwise-sub-mapper",
+            "saml-user-attribute-mapper"
+          ]
+        }
+      },
+      {
+        "id": "04570181-3b70-4571-b203-b53f2a34123a",
+        "name": "Consent Required",
+        "providerId": "consent-required",
+        "subType": "anonymous",
+        "subComponents": {},
+        "config": {}
+      },
+      {
+        "id": "6397ae12-ae0d-4918-aa08-ee404d5144d8",
+        "name": "Allowed Protocol Mapper Types",
+        "providerId": "allowed-protocol-mappers",
+        "subType": "anonymous",
+        "subComponents": {},
+        "config": {
+          "allowed-protocol-mapper-types": [
+            "saml-role-list-mapper",
+            "saml-user-attribute-mapper",
+            "oidc-address-mapper",
+            "oidc-usermodel-property-mapper",
+            "oidc-full-name-mapper",
+            "saml-user-property-mapper",
+            "oidc-usermodel-attribute-mapper",
+            "oidc-sha256-pairwise-sub-mapper"
+          ]
+        }
+      },
+      {
+        "id": "1b0218ee-94a7-4021-b46d-5edcc45af48a",
+        "name": "Full Scope Disabled",
+        "providerId": "scope",
+        "subType": "anonymous",
+        "subComponents": {},
+        "config": {}
+      },
+      {
+        "id": "92eacde8-5c64-46d4-b75d-986330f0faf8",
+        "name": "Allowed Client Scopes",
+        "providerId": "allowed-client-templates",
+        "subType": "anonymous",
+        "subComponents": {},
+        "config": {
+          "allow-default-scopes": [
+            "true"
+          ]
+        }
+      }
+    ],
+    "org.keycloak.keys.KeyProvider": [
+      {
+        "id": "127db379-920f-49ba-a289-408038d1166d",
+        "name": "aes-generated",
+        "providerId": "aes-generated",
+        "subComponents": {},
+        "config": {
+          "priority": [
+            "100"
+          ]
+        }
+      },
+      {
+        "id": "d9601add-c0f8-48c3-9f65-e41f870dc28d",
+        "name": "hmac-generated",
+        "providerId": "hmac-generated",
+        "subComponents": {},
+        "config": {
+          "priority": [
+            "100"
+          ],
+          "algorithm": [
+            "HS256"
+          ]
+        }
+      },
+      {
+        "id": "d2b8c49a-c968-496d-9750-3ad7387ac7c7",
+        "name": "rsa-generated",
+        "providerId": "rsa-generated",
+        "subComponents": {},
+        "config": {
+          "priority": [
+            "100"
+          ]
+        }
+      }
+    ]
+  },
+  "internationalizationEnabled": false,
+  "supportedLocales": [],
+  "authenticationFlows": [
+    {
+      "id": "1a57c929-5fa2-432c-9113-574cc75cd0e0",
+      "alias": "Handle Existing Account",
+      "description": "Handle what to do if there is existing account with same 
email/username like authenticated identity provider",
+      "providerId": "basic-flow",
+      "topLevel": false,
+      "builtIn": true,
+      "authenticationExecutions": [
+        {
+          "authenticator": "idp-confirm-link",
+          "requirement": "REQUIRED",
+          "priority": 10,
+          "userSetupAllowed": false,
+          "autheticatorFlow": false
+        },
+        {
+          "authenticator": "idp-email-verification",
+          "requirement": "ALTERNATIVE",
+          "priority": 20,
+          "userSetupAllowed": false,
+          "autheticatorFlow": false
+        },
+        {
+          "requirement": "ALTERNATIVE",
+          "priority": 30,
+          "flowAlias": "Verify Existing Account by Re-authentication",
+          "userSetupAllowed": false,
+          "autheticatorFlow": true
+        }
+      ]
+    },
+    {
+      "id": "8cf6d3b5-e804-4b1e-8839-d3e5ce0c99ce",
+      "alias": "Verify Existing Account by Re-authentication",
+      "description": "Reauthentication of existing account",
+      "providerId": "basic-flow",
+      "topLevel": false,
+      "builtIn": true,
+      "authenticationExecutions": [
+        {
+          "authenticator": "idp-username-password-form",
+          "requirement": "REQUIRED",
+          "priority": 10,
+          "userSetupAllowed": false,
+          "autheticatorFlow": false
+        },
+        {
+          "authenticator": "auth-otp-form",
+          "requirement": "OPTIONAL",
+          "priority": 20,
+          "userSetupAllowed": false,
+          "autheticatorFlow": false
+        }
+      ]
+    },
+    {
+      "id": "575a7ece-2a59-4432-ba6e-fafa3e7b73e8",
+      "alias": "browser",
+      "description": "browser based authentication",
+      "providerId": "basic-flow",
+      "topLevel": true,
+      "builtIn": true,
+      "authenticationExecutions": [
+        {
+          "authenticator": "auth-cookie",
+          "requirement": "ALTERNATIVE",
+          "priority": 10,
+          "userSetupAllowed": false,
+          "autheticatorFlow": false
+        },
+        {
+          "authenticator": "auth-spnego",
+          "requirement": "DISABLED",
+          "priority": 20,
+          "userSetupAllowed": false,
+          "autheticatorFlow": false
+        },
+        {
+          "authenticator": "identity-provider-redirector",
+          "requirement": "ALTERNATIVE",
+          "priority": 25,
+          "userSetupAllowed": false,
+          "autheticatorFlow": false
+        },
+        {
+          "requirement": "ALTERNATIVE",
+          "priority": 30,
+          "flowAlias": "forms",
+          "userSetupAllowed": false,
+          "autheticatorFlow": true
+        }
+      ]
+    },
+    {
+      "id": "9290c4f5-e470-495a-b1d0-2d03eb9cbaf0",
+      "alias": "clients",
+      "description": "Base authentication for clients",
+      "providerId": "client-flow",
+      "topLevel": true,
+      "builtIn": true,
+      "authenticationExecutions": [
+        {
+          "authenticator": "client-secret",
+          "requirement": "ALTERNATIVE",
+          "priority": 10,
+          "userSetupAllowed": false,
+          "autheticatorFlow": false
+        },
+        {
+          "authenticator": "client-jwt",
+          "requirement": "ALTERNATIVE",
+          "priority": 20,
+          "userSetupAllowed": false,
+          "autheticatorFlow": false
+        },
+        {
+          "authenticator": "client-secret-jwt",
+          "requirement": "ALTERNATIVE",
+          "priority": 30,
+          "userSetupAllowed": false,
+          "autheticatorFlow": false
+        },
+        {
+          "authenticator": "client-x509",
+          "requirement": "ALTERNATIVE",
+          "priority": 40,
+          "userSetupAllowed": false,
+          "autheticatorFlow": false
+        }
+      ]
+    },
+    {
+      "id": "1f8d6e9b-8859-4128-aa45-5e75cc234110",
+      "alias": "direct grant",
+      "description": "OpenID Connect Resource Owner Grant",
+      "providerId": "basic-flow",
+      "topLevel": true,
+      "builtIn": true,
+      "authenticationExecutions": [
+        {
+          "authenticator": "direct-grant-validate-username",
+          "requirement": "REQUIRED",
+          "priority": 10,
+          "userSetupAllowed": false,
+          "autheticatorFlow": false
+        },
+        {
+          "authenticator": "direct-grant-validate-password",
+          "requirement": "REQUIRED",
+          "priority": 20,
+          "userSetupAllowed": false,
+          "autheticatorFlow": false
+        },
+        {
+          "authenticator": "direct-grant-validate-otp",
+          "requirement": "OPTIONAL",
+          "priority": 30,
+          "userSetupAllowed": false,
+          "autheticatorFlow": false
+        }
+      ]
+    },
+    {
+      "id": "5b09e811-0edc-45b1-ab78-abacb6cdf02b",
+      "alias": "docker auth",
+      "description": "Used by Docker clients to authenticate against the IDP",
+      "providerId": "basic-flow",
+      "topLevel": true,
+      "builtIn": true,
+      "authenticationExecutions": [
+        {
+          "authenticator": "docker-http-basic-authenticator",
+          "requirement": "REQUIRED",
+          "priority": 10,
+          "userSetupAllowed": false,
+          "autheticatorFlow": false
+        }
+      ]
+    },
+    {
+      "id": "5a59a45d-5795-4d35-ba9f-522b2564b289",
+      "alias": "first broker login",
+      "description": "Actions taken after first broker login with identity 
provider account, which is not yet linked to any Keycloak account",
+      "providerId": "basic-flow",
+      "topLevel": true,
+      "builtIn": true,
+      "authenticationExecutions": [
+        {
+          "authenticatorConfig": "review profile config",
+          "authenticator": "idp-review-profile",
+          "requirement": "REQUIRED",
+          "priority": 10,
+          "userSetupAllowed": false,
+          "autheticatorFlow": false
+        },
+        {
+          "authenticatorConfig": "create unique user config",
+          "authenticator": "idp-create-user-if-unique",
+          "requirement": "ALTERNATIVE",
+          "priority": 20,
+          "userSetupAllowed": false,
+          "autheticatorFlow": false
+        },
+        {
+          "requirement": "ALTERNATIVE",
+          "priority": 30,
+          "flowAlias": "Handle Existing Account",
+          "userSetupAllowed": false,
+          "autheticatorFlow": true
+        }
+      ]
+    },
+    {
+      "id": "c7e0573a-560e-44e6-b226-c33126f56b60",
+      "alias": "forms",
+      "description": "Username, password, otp and other auth forms.",
+      "providerId": "basic-flow",
+      "topLevel": false,
+      "builtIn": true,
+      "authenticationExecutions": [
+        {
+          "authenticator": "auth-username-password-form",
+          "requirement": "REQUIRED",
+          "priority": 10,
+          "userSetupAllowed": false,
+          "autheticatorFlow": false
+        },
+        {
+          "authenticator": "auth-otp-form",
+          "requirement": "OPTIONAL",
+          "priority": 20,
+          "userSetupAllowed": false,
+          "autheticatorFlow": false
+        }
+      ]
+    },
+    {
+      "id": "84931984-b55d-47fc-a0a0-d667fe94331a",
+      "alias": "http challenge",
+      "description": "An authentication flow based on challenge-response HTTP 
Authentication Schemes",
+      "providerId": "basic-flow",
+      "topLevel": true,
+      "builtIn": true,
+      "authenticationExecutions": [
+        {
+          "authenticator": "no-cookie-redirect",
+          "requirement": "REQUIRED",
+          "priority": 10,
+          "userSetupAllowed": false,
+          "autheticatorFlow": false
+        },
+        {
+          "authenticator": "basic-auth",
+          "requirement": "REQUIRED",
+          "priority": 20,
+          "userSetupAllowed": false,
+          "autheticatorFlow": false
+        },
+        {
+          "authenticator": "basic-auth-otp",
+          "requirement": "DISABLED",
+          "priority": 30,
+          "userSetupAllowed": false,
+          "autheticatorFlow": false
+        },
+        {
+          "authenticator": "auth-spnego",
+          "requirement": "DISABLED",
+          "priority": 40,
+          "userSetupAllowed": false,
+          "autheticatorFlow": false
+        }
+      ]
+    },
+    {
+      "id": "4d70a60e-37f4-454e-86e6-982f7e146758",
+      "alias": "registration",
+      "description": "registration flow",
+      "providerId": "basic-flow",
+      "topLevel": true,
+      "builtIn": true,
+      "authenticationExecutions": [
+        {
+          "authenticator": "registration-page-form",
+          "requirement": "REQUIRED",
+          "priority": 10,
+          "flowAlias": "registration form",
+          "userSetupAllowed": false,
+          "autheticatorFlow": true
+        }
+      ]
+    },
+    {
+      "id": "90511fb9-b046-48cc-b0ac-700dba9ed988",
+      "alias": "registration form",
+      "description": "registration form",
+      "providerId": "form-flow",
+      "topLevel": false,
+      "builtIn": true,
+      "authenticationExecutions": [
+        {
+          "authenticator": "registration-user-creation",
+          "requirement": "REQUIRED",
+          "priority": 20,
+          "userSetupAllowed": false,
+          "autheticatorFlow": false
+        },
+        {
+          "authenticator": "registration-profile-action",
+          "requirement": "REQUIRED",
+          "priority": 40,
+          "userSetupAllowed": false,
+          "autheticatorFlow": false
+        },
+        {
+          "authenticator": "registration-password-action",
+          "requirement": "REQUIRED",
+          "priority": 50,
+          "userSetupAllowed": false,
+          "autheticatorFlow": false
+        },
+        {
+          "authenticator": "registration-recaptcha-action",
+          "requirement": "DISABLED",
+          "priority": 60,
+          "userSetupAllowed": false,
+          "autheticatorFlow": false
+        }
+      ]
+    },
+    {
+      "id": "ed15f1bd-61cc-43a1-b735-307321136ffc",
+      "alias": "reset credentials",
+      "description": "Reset credentials for a user if they forgot their 
password or something",
+      "providerId": "basic-flow",
+      "topLevel": true,
+      "builtIn": true,
+      "authenticationExecutions": [
+        {
+          "authenticator": "reset-credentials-choose-user",
+          "requirement": "REQUIRED",
+          "priority": 10,
+          "userSetupAllowed": false,
+          "autheticatorFlow": false
+        },
+        {
+          "authenticator": "reset-credential-email",
+          "requirement": "REQUIRED",
+          "priority": 20,
+          "userSetupAllowed": false,
+          "autheticatorFlow": false
+        },
+        {
+          "authenticator": "reset-password",
+          "requirement": "REQUIRED",
+          "priority": 30,
+          "userSetupAllowed": false,
+          "autheticatorFlow": false
+        },
+        {
+          "authenticator": "reset-otp",
+          "requirement": "OPTIONAL",
+          "priority": 40,
+          "userSetupAllowed": false,
+          "autheticatorFlow": false
+        }
+      ]
+    },
+    {
+      "id": "60a707b1-1ace-4852-ab0f-d755543e5ce5",
+      "alias": "saml ecp",
+      "description": "SAML ECP Profile Authentication Flow",
+      "providerId": "basic-flow",
+      "topLevel": true,
+      "builtIn": true,
+      "authenticationExecutions": [
+        {
+          "authenticator": "http-basic-authenticator",
+          "requirement": "REQUIRED",
+          "priority": 10,
+          "userSetupAllowed": false,
+          "autheticatorFlow": false
+        }
+      ]
+    }
+  ],
+  "authenticatorConfig": [
+    {
+      "id": "bb4eee3a-0624-4a06-8774-b3a2484f30fd",
+      "alias": "create unique user config",
+      "config": {
+        "require.password.update.after.registration": "false"
+      }
+    },
+    {
+      "id": "920d034a-5f7c-47c9-969e-d7f5cd8450dd",
+      "alias": "review profile config",
+      "config": {
+        "update.profile.on.first.login": "missing"
+      }
+    }
+  ],
+  "requiredActions": [
+    {
+      "alias": "CONFIGURE_TOTP",
+      "name": "Configure OTP",
+      "providerId": "CONFIGURE_TOTP",
+      "enabled": true,
+      "defaultAction": false,
+      "priority": 10,
+      "config": {}
+    },
+    {
+      "alias": "terms_and_conditions",
+      "name": "Terms and Conditions",
+      "providerId": "terms_and_conditions",
+      "enabled": false,
+      "defaultAction": false,
+      "priority": 20,
+      "config": {}
+    },
+    {
+      "alias": "UPDATE_PASSWORD",
+      "name": "Update Password",
+      "providerId": "UPDATE_PASSWORD",
+      "enabled": true,
+      "defaultAction": false,
+      "priority": 30,
+      "config": {}
+    },
+    {
+      "alias": "UPDATE_PROFILE",
+      "name": "Update Profile",
+      "providerId": "UPDATE_PROFILE",
+      "enabled": true,
+      "defaultAction": false,
+      "priority": 40,
+      "config": {}
+    },
+    {
+      "alias": "VERIFY_EMAIL",
+      "name": "Verify Email",
+      "providerId": "VERIFY_EMAIL",
+      "enabled": true,
+      "defaultAction": false,
+      "priority": 50,
+      "config": {}
+    }
+  ],
+  "browserFlow": "browser",
+  "registrationFlow": "registration",
+  "directGrantFlow": "direct grant",
+  "resetCredentialsFlow": "reset credentials",
+  "clientAuthenticationFlow": "clients",
+  "dockerAuthenticationFlow": "docker auth",
+  "attributes": {
+    "_browser_header.xXSSProtection": "1; mode=block",
+    "_browser_header.strictTransportSecurity": "max-age=31536000; 
includeSubDomains",
+    "_browser_header.xFrameOptions": "SAMEORIGIN",
+    "quickLoginCheckMilliSeconds": "1000",
+    "permanentLockout": "false",
+    "displayName": "Keycloak",
+    "_browser_header.xRobotsTag": "none",
+    "maxFailureWaitSeconds": "900",
+    "displayNameHtml": "<div 
class=\"kc-logo-text\"><span>Keycloak</span></div>",
+    "minimumQuickLoginWaitSeconds": "60",
+    "failureFactor": "30",
+    "maxDeltaTimeSeconds": "43200",
+    "_browser_header.xContentTypeOptions": "nosniff",
+    "offlineSessionMaxLifespan": "5184000",
+    "_browser_header.contentSecurityPolicyReportOnly": "",
+    "bruteForceProtected": "false",
+    "_browser_header.contentSecurityPolicy": "frame-src 'self'; 
frame-ancestors 'self'; object-src 'none';",
+    "offlineSessionMaxLifespanEnabled": "false",
+    "waitIncrementSeconds": "60"
+  },
+  "keycloakVersion": "6.0.1",
+  "userManagedAccessAllowed": false
+}
\ No newline at end of file
diff --git 
a/fit/enduser-reference/src/test/resources/sso/saml2syncope-console.json 
b/fit/enduser-reference/src/test/resources/sso/saml2syncope-console.json
new file mode 100644
index 0000000..9d4e73d
--- /dev/null
+++ b/fit/enduser-reference/src/test/resources/sso/saml2syncope-console.json
@@ -0,0 +1,131 @@
+{
+    "clientId": "http://localhost:9080/syncope-console/";,
+    "name": "SAML Test",
+    "adminUrl": "http://localhost:8080/auth/realms/master";,
+    "surrogateAuthRequired": false,
+    "enabled": true,
+    "clientAuthenticatorType": "client-secret",
+    "redirectUris": [
+        "http://localhost:9080/*";
+    ],
+    "webOrigins": [
+        "http://localhost:9080";
+    ],
+    "notBefore": 0,
+    "bearerOnly": false,
+    "consentRequired": false,
+    "standardFlowEnabled": true,
+    "implicitFlowEnabled": false,
+    "directAccessGrantsEnabled": false,
+    "serviceAccountsEnabled": false,
+    "publicClient": false,
+    "frontchannelLogout": true,
+    "protocol": "saml",
+    "attributes": {
+        "saml.assertion.signature": "true",
+        "saml_assertion_consumer_url_redirect": 
"http://localhost:9080/syncope-console/saml2sp/assertion-consumer";,
+        "saml.force.post.binding": "true",
+        "saml.multivalued.roles": "false",
+        "saml_single_logout_service_url_post": 
"http://localhost:9080/syncope-console/saml2sp/logout";,
+        "saml.encrypt": "false",
+        "saml_assertion_consumer_url_post": 
"http://localhost:9080/syncope-console/saml2sp/assertion-consumer";,
+        "saml.server.signature": "true",
+        "saml.server.signature.keyinfo.ext": "false",
+        "exclude.session.state.from.auth.response": "false",
+        "saml.signing.certificate": 
"MIIC9TCCAd0CBgFrCC7kezANBgkqhkiG9w0BAQsFADA+MTwwOgYDVQQDDDNodHRwOi8vc3luY29wZS1zYW1sMi10ZXN0LWNvbTo5MDgwL3N5bmNvcGUtZW5kdXNlci8wHhcNMTkwNTMwMDk1ODM5WhcNMjkwNTMwMTAwMDE5WjA+MTwwOgYDVQQDDDNodHRwOi8vc3luY29wZS1zYW1sMi10ZXN0LWNvbTo5MDgwL3N5bmNvcGUtZW5kdXNlci8wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCF4QsiRZGD7BNx0Bglh4rgtACaIr7R/nDQfdGLN9uSA2HkEPygJzBRyluQLiQv9o/LKQMwvmia5fK4Xt99cgJnmrzKXraKo1KsZNz8vpygMpGJzCA2XUMLe065lYg28PV2bjk6hyUcMehlubjKFQ6USAJG5db
 [...]
+        "saml_single_logout_service_url_redirect": 
"http://localhost:9080/syncope-console/saml2sp/logout";,
+        "saml.signature.algorithm": "RSA_SHA256",
+        "saml_force_name_id_format": "false",
+        "saml.client.signature": "false",
+        "tls.client.certificate.bound.access.tokens": "false",
+        "saml.authnstatement": "true",
+        "display.on.consent.screen": "false",
+        "saml.signing.private.key": 
"MIIEowIBAAKCAQEAheELIkWRg+wTcdAYJYeK4LQAmiK+0f5w0H3RizfbkgNh5BD8oCcwUcpbkC4kL/aPyykDML5omuXyuF7ffXICZ5q8yl62iqNSrGTc/L6coDKRicwgNl1DC3tOuZWINvD1dm45OoclHDHoZbm4yhUOlEgCRuXW660s+4ktox0GXMQmQHTzxaWlGaXCTzV1PJ/bPqXkLz3omEbvUFBAf6nv6J70P1iVF8RK8djx5rRvcniECqGnEr6w+q0h8AoMMSYKPrVtdkuG0V4+DcJtoffevT60DvC/HoApBeUS0ntIAWlqmp/R2CEOgf084LBq1DyBsO2QOFluxoC97WaV72WGSwIDAQABAoIBABXnJY0r2Iy+uMesBedN75inmlmdSZ7Ng+N4Uin2r4OJ7iAD73C8OJmJA8Xo5p66NfhE83KsFC0TZcxoKSQ63M3
 [...]
+        "saml_name_id_format": "persistent",
+        "saml.onetimeuse.condition": "false",
+        "saml_signature_canonicalization_method": 
"http://www.w3.org/2001/10/xml-exc-c14n#";
+    },
+    "authenticationFlowBindingOverrides": {},
+    "fullScopeAllowed": true,
+    "nodeReRegistrationTimeout": -1,
+    "protocolMappers": [
+        {
+            "name": "X500 email",
+            "protocol": "saml",
+            "protocolMapper": "saml-user-property-mapper",
+            "consentRequired": false,
+            "config": {
+                "attribute.nameformat": 
"urn:oasis:names:tc:SAML:2.0:attrname-format:uri",
+                "user.attribute": "email",
+                "friendly.name": "email",
+                "attribute.name": "urn:oid:1.2.840.113549.1.9.1"
+            }
+        },
+        {
+            "name": "X500 givenName",
+            "protocol": "saml",
+            "protocolMapper": "saml-user-property-mapper",
+            "consentRequired": false,
+            "config": {
+                "attribute.nameformat": 
"urn:oasis:names:tc:SAML:2.0:attrname-format:uri",
+                "user.attribute": "firstName",
+                "friendly.name": "givenName",
+                "attribute.name": "urn:oid:2.5.4.42"
+            }
+        },
+        {
+            "name": "fullName",
+            "protocol": "saml",
+            "protocolMapper": "saml-user-attribute-mapper",
+            "consentRequired": false,
+            "config": {
+                "attribute.nameformat": "Basic",
+                "user.attribute": "fullName",
+                "friendly.name": "fullName",
+                "attribute.name": "fullName"
+            }
+        },
+        {
+            "name": "X500 surname",
+            "protocol": "saml",
+            "protocolMapper": "saml-user-property-mapper",
+            "consentRequired": false,
+            "config": {
+                "attribute.nameformat": 
"urn:oasis:names:tc:SAML:2.0:attrname-format:uri",
+                "user.attribute": "lastName",
+                "friendly.name": "surname",
+                "attribute.name": "urn:oid:2.5.4.4"
+            }
+        },
+        {
+            "name": "username",
+            "protocol": "saml",
+            "protocolMapper": "saml-user-property-mapper",
+            "consentRequired": false,
+            "config": {
+                "attribute.nameformat": "Basic",
+                "user.attribute": "username",
+                "friendly.name": "username",
+                "attribute.name": "username"
+            }
+        }
+    ],
+    "defaultClientScopes": [
+        "web-origins",
+        "role_list",
+        "profile",
+        "roles",
+        "email"
+    ],
+    "optionalClientScopes": [
+        "address",
+        "phone",
+        "offline_access",
+        "microprofile-jwt"
+    ],
+    "access": {
+        "view": true,
+        "configure": true,
+        "manage": true
+    }
+}
diff --git 
a/fit/enduser-reference/src/test/resources/sso/saml2syncope-enduser.json 
b/fit/enduser-reference/src/test/resources/sso/saml2syncope-enduser.json
new file mode 100644
index 0000000..eec025d
--- /dev/null
+++ b/fit/enduser-reference/src/test/resources/sso/saml2syncope-enduser.json
@@ -0,0 +1,131 @@
+{
+    "clientId": "http://localhost:9080/syncope-enduser/";,
+    "name": "SAML Test",
+    "adminUrl": "http://localhost:8080/auth/realms/master";,
+    "surrogateAuthRequired": false,
+    "enabled": true,
+    "clientAuthenticatorType": "client-secret",
+    "redirectUris": [
+        "http://localhost:9080/*";
+    ],
+    "webOrigins": [
+        "http://localhost:9080";
+    ],
+    "notBefore": 0,
+    "bearerOnly": false,
+    "consentRequired": false,
+    "standardFlowEnabled": true,
+    "implicitFlowEnabled": false,
+    "directAccessGrantsEnabled": false,
+    "serviceAccountsEnabled": false,
+    "publicClient": false,
+    "frontchannelLogout": true,
+    "protocol": "saml",
+    "attributes": {
+        "saml.assertion.signature": "true",
+        "saml_assertion_consumer_url_redirect": 
"http://localhost:9080/syncope-enduser/saml2sp/assertion-consumer";,
+        "saml.force.post.binding": "true",
+        "saml.multivalued.roles": "false",
+        "saml_single_logout_service_url_post": 
"http://localhost:9080/syncope-enduser/saml2sp/logout";,
+        "saml.encrypt": "false",
+        "saml_assertion_consumer_url_post": 
"http://localhost:9080/syncope-enduser/saml2sp/assertion-consumer";,
+        "saml.server.signature": "true",
+        "saml.server.signature.keyinfo.ext": "false",
+        "exclude.session.state.from.auth.response": "false",
+        "saml.signing.certificate": 
"MIIC9TCCAd0CBgFrCC7kezANBgkqhkiG9w0BAQsFADA+MTwwOgYDVQQDDDNodHRwOi8vc3luY29wZS1zYW1sMi10ZXN0LWNvbTo5MDgwL3N5bmNvcGUtZW5kdXNlci8wHhcNMTkwNTMwMDk1ODM5WhcNMjkwNTMwMTAwMDE5WjA+MTwwOgYDVQQDDDNodHRwOi8vc3luY29wZS1zYW1sMi10ZXN0LWNvbTo5MDgwL3N5bmNvcGUtZW5kdXNlci8wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCF4QsiRZGD7BNx0Bglh4rgtACaIr7R/nDQfdGLN9uSA2HkEPygJzBRyluQLiQv9o/LKQMwvmia5fK4Xt99cgJnmrzKXraKo1KsZNz8vpygMpGJzCA2XUMLe065lYg28PV2bjk6hyUcMehlubjKFQ6USAJG5db
 [...]
+        "saml_single_logout_service_url_redirect": 
"http://localhost:9080/syncope-enduser/saml2sp/logout";,
+        "saml.signature.algorithm": "RSA_SHA256",
+        "saml_force_name_id_format": "false",
+        "saml.client.signature": "false",
+        "tls.client.certificate.bound.access.tokens": "false",
+        "saml.authnstatement": "true",
+        "display.on.consent.screen": "false",
+        "saml.signing.private.key": 
"MIIEowIBAAKCAQEAheELIkWRg+wTcdAYJYeK4LQAmiK+0f5w0H3RizfbkgNh5BD8oCcwUcpbkC4kL/aPyykDML5omuXyuF7ffXICZ5q8yl62iqNSrGTc/L6coDKRicwgNl1DC3tOuZWINvD1dm45OoclHDHoZbm4yhUOlEgCRuXW660s+4ktox0GXMQmQHTzxaWlGaXCTzV1PJ/bPqXkLz3omEbvUFBAf6nv6J70P1iVF8RK8djx5rRvcniECqGnEr6w+q0h8AoMMSYKPrVtdkuG0V4+DcJtoffevT60DvC/HoApBeUS0ntIAWlqmp/R2CEOgf084LBq1DyBsO2QOFluxoC97WaV72WGSwIDAQABAoIBABXnJY0r2Iy+uMesBedN75inmlmdSZ7Ng+N4Uin2r4OJ7iAD73C8OJmJA8Xo5p66NfhE83KsFC0TZcxoKSQ63M3
 [...]
+        "saml_name_id_format": "persistent",
+        "saml.onetimeuse.condition": "false",
+        "saml_signature_canonicalization_method": 
"http://www.w3.org/2001/10/xml-exc-c14n#";
+    },
+    "authenticationFlowBindingOverrides": {},
+    "fullScopeAllowed": true,
+    "nodeReRegistrationTimeout": -1,
+    "protocolMappers": [
+        {
+            "name": "X500 email",
+            "protocol": "saml",
+            "protocolMapper": "saml-user-property-mapper",
+            "consentRequired": false,
+            "config": {
+                "attribute.nameformat": 
"urn:oasis:names:tc:SAML:2.0:attrname-format:uri",
+                "user.attribute": "email",
+                "friendly.name": "email",
+                "attribute.name": "urn:oid:1.2.840.113549.1.9.1"
+            }
+        },
+        {
+            "name": "X500 givenName",
+            "protocol": "saml",
+            "protocolMapper": "saml-user-property-mapper",
+            "consentRequired": false,
+            "config": {
+                "attribute.nameformat": 
"urn:oasis:names:tc:SAML:2.0:attrname-format:uri",
+                "user.attribute": "firstName",
+                "friendly.name": "givenName",
+                "attribute.name": "urn:oid:2.5.4.42"
+            }
+        },
+        {
+            "name": "fullName",
+            "protocol": "saml",
+            "protocolMapper": "saml-user-attribute-mapper",
+            "consentRequired": false,
+            "config": {
+                "attribute.nameformat": "Basic",
+                "user.attribute": "fullName",
+                "friendly.name": "fullName",
+                "attribute.name": "fullName"
+            }
+        },
+        {
+            "name": "X500 surname",
+            "protocol": "saml",
+            "protocolMapper": "saml-user-property-mapper",
+            "consentRequired": false,
+            "config": {
+                "attribute.nameformat": 
"urn:oasis:names:tc:SAML:2.0:attrname-format:uri",
+                "user.attribute": "lastName",
+                "friendly.name": "surname",
+                "attribute.name": "urn:oid:2.5.4.4"
+            }
+        },
+        {
+            "name": "username",
+            "protocol": "saml",
+            "protocolMapper": "saml-user-property-mapper",
+            "consentRequired": false,
+            "config": {
+                "attribute.nameformat": "Basic",
+                "user.attribute": "username",
+                "friendly.name": "username",
+                "attribute.name": "username"
+            }
+        }
+    ],
+    "defaultClientScopes": [
+        "web-origins",
+        "role_list",
+        "profile",
+        "roles",
+        "email"
+    ],
+    "optionalClientScopes": [
+        "address",
+        "phone",
+        "offline_access",
+        "microprofile-jwt"
+    ],
+    "access": {
+        "view": true,
+        "configure": true,
+        "manage": true
+    }
+}
\ No newline at end of file

Reply via email to