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

marat pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-karavan.git

commit 3235f8acd4ae8b6d7a492b081802ff7acef67021
Author: Marat Gubaidullin <[email protected]>
AuthorDate: Thu Sep 8 22:54:47 2022 -0400

    SSO with Keycloak
---
 karavan-app/pom.xml                                |    6 +-
 .../org/apache/camel/karavan/api/AuthResource.java |   18 +-
 .../camel/karavan/api/ComponentResources.java      |    2 +-
 .../camel/karavan/api/ConfigurationResource.java   |    2 +-
 .../org/apache/camel/karavan/api/GitResource.java  |    2 +-
 .../apache/camel/karavan/api/KameletResources.java |    2 +-
 .../camel/karavan/api/KubernetesResource.java      |    2 +-
 .../camel/karavan/api/ProjectFileResource.java     |    2 +-
 .../apache/camel/karavan/api/ProjectResource.java  |    2 +-
 .../apache/camel/karavan/api/StatusResource.java   |    2 +-
 .../apache/camel/karavan/api/UsersResource.java    |   48 +
 .../apache/camel/karavan/service/AuthService.java  |   12 +
 .../src/main/resources/application.properties      |   32 +-
 karavan-app/src/main/webapp/package-lock.json      |   29 +
 karavan-app/src/main/webapp/package.json           |    1 +
 karavan-app/src/main/webapp/public/index.html      |    2 +
 karavan-app/src/main/webapp/src/Main.tsx           |   44 +-
 karavan-app/src/main/webapp/src/MainLogin.tsx      |   45 -
 karavan-app/src/main/webapp/src/api/KaravanApi.tsx |  295 ++-
 karavan-app/src/main/webapp/src/api/SsoApi.tsx     |   20 +
 .../main/webapp/src/projects/CreateFileModal.tsx   |    2 +-
 .../main/webapp/src/projects/ProjectDashboard.tsx  |    2 +-
 .../src/main/webapp/src/projects/ProjectInfo.tsx   |    2 +-
 .../src/{models => projects}/ProjectModels.ts      |    0
 .../src/main/webapp/src/projects/ProjectPage.tsx   |    2 +-
 .../src/main/webapp/src/projects/ProjectsPage.tsx  |    2 +-
 .../main/webapp/src/projects/PropertiesEditor.tsx  |    2 +-
 .../src/main/webapp/src/projects/UploadModal.tsx   |    2 +-
 karavan-builder/karavan-realm.json                 | 2405 ++++++++++++++++++++
 29 files changed, 2777 insertions(+), 210 deletions(-)

diff --git a/karavan-app/pom.xml b/karavan-app/pom.xml
index 0a10d09..ba091c3 100644
--- a/karavan-app/pom.xml
+++ b/karavan-app/pom.xml
@@ -31,7 +31,7 @@
         
<quarkus.platform.group-id>io.quarkus.platform</quarkus.platform.group-id>
         <quarkus.platform.version>2.11.2.Final</quarkus.platform.version>
         <surefire-plugin.version>3.0.0-M5</surefire-plugin.version>
-        <version.camel-kamelet>0.8.1</version.camel-kamelet>
+        <version.camel-kamelet>0.9.0</version.camel-kamelet>
         <version.camel>3.18.1</version.camel>
     </properties>
     <dependencyManagement>
@@ -87,6 +87,10 @@
             <groupId>io.quarkus</groupId>
             <artifactId>quarkus-openshift-client</artifactId>
         </dependency>
+        <dependency>
+            <groupId>io.quarkus</groupId>
+            <artifactId>quarkus-oidc</artifactId>
+        </dependency>
         <dependency>
             <groupId>io.quarkus</groupId>
             <artifactId>quarkus-smallrye-health</artifactId>
diff --git 
a/karavan-app/src/main/java/org/apache/camel/karavan/api/AuthResource.java 
b/karavan-app/src/main/java/org/apache/camel/karavan/api/AuthResource.java
index 759bb72..ce51a63 100644
--- a/karavan-app/src/main/java/org/apache/camel/karavan/api/AuthResource.java
+++ b/karavan-app/src/main/java/org/apache/camel/karavan/api/AuthResource.java
@@ -20,6 +20,7 @@ import org.apache.camel.karavan.service.AuthService;
 
 import javax.inject.Inject;
 import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
 import javax.ws.rs.HeaderParam;
 import javax.ws.rs.POST;
 import javax.ws.rs.Path;
@@ -29,13 +30,14 @@ import javax.ws.rs.core.HttpHeaders;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 
-@Path("/auth")
+@Path("/public")
 public class AuthResource {
 
     @Inject
     AuthService authService;
 
     @POST
+    @Path("/auth")
     @Produces(MediaType.APPLICATION_JSON)
     @Consumes(MediaType.APPLICATION_JSON)
     public Response auth(@HeaderParam("Authorization") String basicAuth, 
@Context HttpHeaders headers) throws Exception {
@@ -45,4 +47,18 @@ public class AuthResource {
             return Response.status(Response.Status.UNAUTHORIZED).build();
         }
     }
+
+    @GET
+    @Path("/sso")
+    @Produces(MediaType.TEXT_PLAIN)
+    public Response sso() throws Exception {
+        return Response.ok(authService.isSSO()).build();
+    }
+
+    @GET
+    @Path("/sso-config")
+    @Produces(MediaType.APPLICATION_JSON)
+    public Response ssoConfig() throws Exception {
+        return Response.ok(authService.getSsoConfig()).build();
+    }
 }
\ No newline at end of file
diff --git 
a/karavan-app/src/main/java/org/apache/camel/karavan/api/ComponentResources.java
 
b/karavan-app/src/main/java/org/apache/camel/karavan/api/ComponentResources.java
index bc89c60..f1d1ea5 100644
--- 
a/karavan-app/src/main/java/org/apache/camel/karavan/api/ComponentResources.java
+++ 
b/karavan-app/src/main/java/org/apache/camel/karavan/api/ComponentResources.java
@@ -27,7 +27,7 @@ import java.io.InputStreamReader;
 import java.util.List;
 import java.util.stream.Collectors;
 
-@Path("/component")
+@Path("/api/component")
 public class ComponentResources {
 
     @GET
diff --git 
a/karavan-app/src/main/java/org/apache/camel/karavan/api/ConfigurationResource.java
 
b/karavan-app/src/main/java/org/apache/camel/karavan/api/ConfigurationResource.java
index 8568bba..9d0b9ed 100644
--- 
a/karavan-app/src/main/java/org/apache/camel/karavan/api/ConfigurationResource.java
+++ 
b/karavan-app/src/main/java/org/apache/camel/karavan/api/ConfigurationResource.java
@@ -28,7 +28,7 @@ import javax.ws.rs.core.Response;
 import java.util.Map;
 import java.util.stream.Collectors;
 
-@Path("/configuration")
+@Path("/api/configuration")
 public class ConfigurationResource {
 
     @ConfigProperty(name = "karavan.version")
diff --git 
a/karavan-app/src/main/java/org/apache/camel/karavan/api/GitResource.java 
b/karavan-app/src/main/java/org/apache/camel/karavan/api/GitResource.java
index 713d09b..217e40e 100644
--- a/karavan-app/src/main/java/org/apache/camel/karavan/api/GitResource.java
+++ b/karavan-app/src/main/java/org/apache/camel/karavan/api/GitResource.java
@@ -31,7 +31,7 @@ import javax.ws.rs.Produces;
 import javax.ws.rs.core.MediaType;
 import java.util.List;
 
-@Path("/git")
+@Path("/api/git")
 public class GitResource {
 
     @Inject
diff --git 
a/karavan-app/src/main/java/org/apache/camel/karavan/api/KameletResources.java 
b/karavan-app/src/main/java/org/apache/camel/karavan/api/KameletResources.java
index 7c6ebbf..840df37 100644
--- 
a/karavan-app/src/main/java/org/apache/camel/karavan/api/KameletResources.java
+++ 
b/karavan-app/src/main/java/org/apache/camel/karavan/api/KameletResources.java
@@ -36,7 +36,7 @@ import java.util.List;
 import java.util.regex.Pattern;
 import java.util.stream.Collectors;
 
-@Path("/kamelet")
+@Path("/api/kamelet")
 public class KameletResources {
 
     @Inject
diff --git 
a/karavan-app/src/main/java/org/apache/camel/karavan/api/KubernetesResource.java
 
b/karavan-app/src/main/java/org/apache/camel/karavan/api/KubernetesResource.java
index 2e8c183..162310c 100644
--- 
a/karavan-app/src/main/java/org/apache/camel/karavan/api/KubernetesResource.java
+++ 
b/karavan-app/src/main/java/org/apache/camel/karavan/api/KubernetesResource.java
@@ -39,7 +39,7 @@ import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 import java.util.Optional;
 
-@Path("/kubernetes")
+@Path("/api/kubernetes")
 public class KubernetesResource {
 
     @Inject
diff --git 
a/karavan-app/src/main/java/org/apache/camel/karavan/api/ProjectFileResource.java
 
b/karavan-app/src/main/java/org/apache/camel/karavan/api/ProjectFileResource.java
index 0495efe..5b4bbf9 100644
--- 
a/karavan-app/src/main/java/org/apache/camel/karavan/api/ProjectFileResource.java
+++ 
b/karavan-app/src/main/java/org/apache/camel/karavan/api/ProjectFileResource.java
@@ -34,7 +34,7 @@ import java.net.URLDecoder;
 import java.nio.charset.StandardCharsets;
 import java.util.List;
 
-@Path("/file")
+@Path("/api/file")
 public class ProjectFileResource {
 
     @Inject
diff --git 
a/karavan-app/src/main/java/org/apache/camel/karavan/api/ProjectResource.java 
b/karavan-app/src/main/java/org/apache/camel/karavan/api/ProjectResource.java
index 9ebdc44..253f46d 100644
--- 
a/karavan-app/src/main/java/org/apache/camel/karavan/api/ProjectResource.java
+++ 
b/karavan-app/src/main/java/org/apache/camel/karavan/api/ProjectResource.java
@@ -38,7 +38,7 @@ import java.util.List;
 import java.util.Map;
 import java.util.stream.Collectors;
 
-@Path("/project")
+@Path("/api/project")
 public class ProjectResource {
 
     @Inject
diff --git 
a/karavan-app/src/main/java/org/apache/camel/karavan/api/StatusResource.java 
b/karavan-app/src/main/java/org/apache/camel/karavan/api/StatusResource.java
index 054730a..b33cac1 100644
--- a/karavan-app/src/main/java/org/apache/camel/karavan/api/StatusResource.java
+++ b/karavan-app/src/main/java/org/apache/camel/karavan/api/StatusResource.java
@@ -35,7 +35,7 @@ import java.util.HashMap;
 import java.util.Map;
 import java.util.stream.Collectors;
 
-@Path("/status")
+@Path("/api/status")
 public class StatusResource {
 
     private static final Logger LOGGER = 
Logger.getLogger(StatusResource.class.getName());
diff --git 
a/karavan-app/src/main/java/org/apache/camel/karavan/api/UsersResource.java 
b/karavan-app/src/main/java/org/apache/camel/karavan/api/UsersResource.java
new file mode 100644
index 0000000..a3d3e95
--- /dev/null
+++ b/karavan-app/src/main/java/org/apache/camel/karavan/api/UsersResource.java
@@ -0,0 +1,48 @@
+package org.apache.camel.karavan.api;
+
+import javax.inject.Inject;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+
+import io.quarkus.oidc.IdToken;
+import org.eclipse.microprofile.jwt.JsonWebToken;
+import org.jboss.resteasy.reactive.NoCache;
+import io.quarkus.security.identity.SecurityIdentity;
+
+import java.util.Set;
+
+@Path("/api/users")
+@Produces(MediaType.APPLICATION_JSON)
+public class UsersResource {
+
+    @Inject
+    SecurityIdentity securityIdentity;
+
+    @GET
+    @Path("/me")
+    @NoCache
+    public User me() {
+        return new User(securityIdentity);
+    }
+
+    public static class User {
+
+        private final String userName;
+        private final java.util.Set<java.lang.String> roles;
+
+        User(SecurityIdentity securityIdentity) {
+            this.userName = securityIdentity.getPrincipal().getName();
+            this.roles = securityIdentity.getRoles();
+        }
+
+        public String getUserName() {
+            return userName;
+        }
+
+        public Set<String> getRoles() {
+            return roles;
+        }
+    }
+}
\ No newline at end of file
diff --git 
a/karavan-app/src/main/java/org/apache/camel/karavan/service/AuthService.java 
b/karavan-app/src/main/java/org/apache/camel/karavan/service/AuthService.java
index 8cd82b6..fb01c99 100644
--- 
a/karavan-app/src/main/java/org/apache/camel/karavan/service/AuthService.java
+++ 
b/karavan-app/src/main/java/org/apache/camel/karavan/service/AuthService.java
@@ -25,8 +25,11 @@ import org.jboss.logging.Logger;
 
 import javax.enterprise.context.ApplicationScoped;
 import javax.inject.Inject;
+import java.net.MalformedURLException;
+import java.net.URL;
 import java.nio.charset.StandardCharsets;
 import java.util.Base64;
+import java.util.Map;
 
 @ApplicationScoped
 public class AuthService {
@@ -58,4 +61,13 @@ public class AuthService {
         String auth = "Basic " + secretToken;
         return auth.equals(basicAuth);
     }
+
+    public boolean isSSO() {
+        return ConfigProvider.getConfig().getValue("quarkus.oidc.enabled", 
Boolean.class);
+    }
+
+    public Map<String, String> getSsoConfig() throws MalformedURLException {
+        URL netUrl = new 
URL(ConfigProvider.getConfig().getValue("quarkus.oidc.auth-server-url", 
String.class));
+        return Map.of("url", netUrl.getProtocol() + "://" + 
netUrl.getAuthority() + "/");
+    }
 }
diff --git a/karavan-app/src/main/resources/application.properties 
b/karavan-app/src/main/resources/application.properties
index 4efe8c2..53eb9ee 100644
--- a/karavan-app/src/main/resources/application.properties
+++ b/karavan-app/src/main/resources/application.properties
@@ -1,4 +1,5 @@
-karavan.version=${project.version}
+#karavan.version=${project.version}
+karavan.version=3.18.3
 
 karavan.master-username=admin
 karavan.master-password=karavan
@@ -59,13 +60,22 @@ quarkus.infinispan-client.auth-password=password
 quarkus.infinispan-client.client-intelligence=BASIC
 
 # SSO
-#quarkus.oidc.auth-server-url=http://localhost:8081/realms/karavan
-#quarkus.oidc.client-id=karavan
-#quarkus.oidc.credentials.secret=vWh7ZQf3jhCd1jkZwGIaSqeLKIvYCbPM
-#quarkus.oidc.application-type=web-app
-#quarkus.oidc.tls.verification=none
-#quarkus.http.auth.permission.authenticated.paths=/*
-#quarkus.http.auth.permission.authenticated.policy=authenticated
+quarkus.oidc.enabled=true
+quarkus.oidc.auth-server-url=http://localhost:8081/realms/karavan
+quarkus.oidc.client-id=karavan-backend
+quarkus.oidc.credentials.secret=AYiPVbEh2be8vWpV6QRIx3jwPPrGspNJ
+quarkus.oidc.application-type=service
+quarkus.oidc.tls.verification=none
+quarkus.oidc.roles.source=accesstoken
+
+quarkus.keycloak.devservices.enabled=false
+
+quarkus.http.auth.permission.authenticated.paths=/api/*
+quarkus.http.auth.permission.authenticated.policy=authenticated
+
+quarkus.http.auth.permission.public.paths=/public/*,/static/*,/*.map,/*.css,/*.js,/*.png,/*.html,/*.woff2,/*.ico,/robots.txt
+quarkus.http.auth.permission.public.policy=permit
+quarkus.http.auth.permission.public.methods=GET,HEAD,POST
 
 # Quarkus configuration
 quarkus.log.level=INFO
@@ -76,7 +86,7 @@ 
quarkus.docker.dockerfile-jvm-path=src/main/docker/Dockerfile.distroless
 
 quarkus.container-image.group=apache
 quarkus.container-image.name=camel-karavan
-quarkus.container-image.tag=${project.version}
+#quarkus.container-image.tag=${project.version}
 
 quarkus.container-image.builder=docker
 
@@ -87,7 +97,3 @@ quarkus.container-image.builder=docker
 
 quarkus.kubernetes-client.connection-timeout=2000
 quarkus.kubernetes-client.request-timeout=10000
-
-quarkus.openshift.route.expose=true
-quarkus.openshift.name=karavan
-quarkus.openshift.namespace=karavan
diff --git a/karavan-app/src/main/webapp/package-lock.json 
b/karavan-app/src/main/webapp/package-lock.json
index 9c98cc2..43fcfb8 100644
--- a/karavan-app/src/main/webapp/package-lock.json
+++ b/karavan-app/src/main/webapp/package-lock.json
@@ -21,6 +21,7 @@
         "dagre": "^0.8.5",
         "file-saver": "^2.0.5",
         "karavan-core": "file:../../../../karavan-core",
+        "keycloak-js": "^19.0.1",
         "localforage": "^1.10.0",
         "react": "17.0.2",
         "react-dom": "17.0.2",
@@ -11048,6 +11049,11 @@
         "url": "https://github.com/chalk/supports-color?sponsor=1";
       }
     },
+    "node_modules/js-sha256": {
+      "version": "0.9.0",
+      "resolved": "https://registry.npmjs.org/js-sha256/-/js-sha256-0.9.0.tgz";,
+      "integrity": 
"sha512-sga3MHh9sgQN2+pJ9VYZ+1LPwXOxuBJBA5nrR5/ofPfuiJBE2hnjsaN8se8JznOmGLN2p49Pe5U/ttafcs/apA=="
+    },
     "node_modules/js-tokens": {
       "version": "4.0.0",
       "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz";,
@@ -11200,6 +11206,15 @@
       "resolved": "../../../../karavan-core",
       "link": true
     },
+    "node_modules/keycloak-js": {
+      "version": "19.0.1",
+      "resolved": 
"https://registry.npmjs.org/keycloak-js/-/keycloak-js-19.0.1.tgz";,
+      "integrity": 
"sha512-/GNJcgCb4OsMW+pI2EEQU8PWd4tkXCABqLHkVHbfU+r7XaU9E+zFkD960TItIEarCR0JP6iD8fhKchgxkV+W8w==",
+      "dependencies": {
+        "base64-js": "^1.5.1",
+        "js-sha256": "^0.9.0"
+      }
+    },
     "node_modules/kind-of": {
       "version": "6.0.3",
       "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz";,
@@ -24978,6 +24993,11 @@
         }
       }
     },
+    "js-sha256": {
+      "version": "0.9.0",
+      "resolved": "https://registry.npmjs.org/js-sha256/-/js-sha256-0.9.0.tgz";,
+      "integrity": 
"sha512-sga3MHh9sgQN2+pJ9VYZ+1LPwXOxuBJBA5nrR5/ofPfuiJBE2hnjsaN8se8JznOmGLN2p49Pe5U/ttafcs/apA=="
+    },
     "js-tokens": {
       "version": "4.0.0",
       "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz";,
@@ -25111,6 +25131,15 @@
         "uuid": "8.3.2"
       }
     },
+    "keycloak-js": {
+      "version": "19.0.1",
+      "resolved": 
"https://registry.npmjs.org/keycloak-js/-/keycloak-js-19.0.1.tgz";,
+      "integrity": 
"sha512-/GNJcgCb4OsMW+pI2EEQU8PWd4tkXCABqLHkVHbfU+r7XaU9E+zFkD960TItIEarCR0JP6iD8fhKchgxkV+W8w==",
+      "requires": {
+        "base64-js": "^1.5.1",
+        "js-sha256": "^0.9.0"
+      }
+    },
     "kind-of": {
       "version": "6.0.3",
       "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz";,
diff --git a/karavan-app/src/main/webapp/package.json 
b/karavan-app/src/main/webapp/package.json
index f3e2f86..24363be 100644
--- a/karavan-app/src/main/webapp/package.json
+++ b/karavan-app/src/main/webapp/package.json
@@ -40,6 +40,7 @@
     "dagre": "^0.8.5",
     "file-saver": "^2.0.5",
     "karavan-core": "file:../../../../karavan-core",
+    "keycloak-js": "^19.0.1",
     "localforage": "^1.10.0",
     "react": "17.0.2",
     "react-dom": "17.0.2",
diff --git a/karavan-app/src/main/webapp/public/index.html 
b/karavan-app/src/main/webapp/public/index.html
index 5f0c9eb..a9882bc 100644
--- a/karavan-app/src/main/webapp/public/index.html
+++ b/karavan-app/src/main/webapp/public/index.html
@@ -4,6 +4,8 @@
 <head>
   <meta charset="utf-8" />
   <meta name="viewport" content="width=device-width, initial-scale=1" />
+  <meta http-equiv="Pragma" content="no-cache" />
+  <meta http-equiv="Expires" content="0" />
   <title>Karavan</title>
 </head>
 
diff --git a/karavan-app/src/main/webapp/src/Main.tsx 
b/karavan-app/src/main/webapp/src/Main.tsx
index b535726..7ac92a4 100644
--- a/karavan-app/src/main/webapp/src/Main.tsx
+++ b/karavan-app/src/main/webapp/src/Main.tsx
@@ -10,9 +10,10 @@ import {
     FlexItem,
     Avatar,
     Tooltip,
-    Divider
+    Divider, Spinner, Bullseye
 } from '@patternfly/react-core';
 import {KaravanApi} from "./api/KaravanApi";
+import {SsoApi} from "./api/SsoApi";
 import {KameletApi} from "karavan-core/lib/api/KameletApi";
 import './designer/karavan.css';
 import {ConfigurationPage} from "./config/ConfigurationPage";
@@ -23,7 +24,7 @@ import Icon from "./Logo";
 import {ComponentsPage} from "./components/ComponentsPage";
 import {EipPage} from "./eip/EipPage";
 import {ProjectsPage} from "./projects/ProjectsPage";
-import {Project} from "./models/ProjectModels";
+import {Project} from "./projects/ProjectModels";
 import {ProjectPage} from "./projects/ProjectPage";
 import UsersIcon from "@patternfly/react-icons/dist/js/icons/users-icon";
 import UserIcon from "@patternfly/react-icons/dist/js/icons/user-icon";
@@ -33,7 +34,6 @@ import EipIcon from 
"@patternfly/react-icons/dist/js/icons/topology-icon";
 import ComponentsIcon from "@patternfly/react-icons/dist/js/icons/module-icon";
 import ConfigurationIcon from 
"@patternfly/react-icons/dist/js/icons/cogs-icon";
 import {MainLogin} from "./MainLogin";
-import {AxiosResponse} from "axios";
 
 class ToastMessage {
     id: string = ''
@@ -77,7 +77,9 @@ interface State {
     request: string,
     filename: string,
     key: string,
-    isAuthorized: boolean
+    isAuthorized: boolean,
+    authType?: 'SSO' | 'Basic',
+    me: any,
 }
 
 export class Main extends React.Component<Props, State> {
@@ -93,23 +95,38 @@ export class Main extends React.Component<Props, State> {
         openapi: '',
         filename: '',
         isAuthorized: false,
-        key: ''
+        key: '',
+        me: {}
     };
 
     designer = React.createRef();
 
     componentDidMount() {
-        KaravanApi.getConfiguration((config: any) => {
-            this.setState({
-                config: config
-            })
+        KaravanApi.isSSO((sso: any) => {
+            const isSSO = (sso === 'true' || sso === true);
+            console.log("isSSO", isSSO);
+            if (isSSO) {
+                SsoApi.auth(() => {
+                    KaravanApi.getMe((user: any) => {
+                        console.log("me", user);
+                        this.setState({authType: 'SSO', me: user, 
isAuthorized: true});
+                        this.getData();
+                    });
+                });
+            } else {
+                this.setState({authType: 'Basic'});
+            }
         });
+        console.log("this.state.isAuthorized", this.state.isAuthorized);
         if (this.state.isAuthorized) {
             this.getData();
         }
     }
 
     getData() {
+        KaravanApi.getConfiguration((config: any) => {
+            this.setState({ config: config })
+        });
         KaravanApi.getKameletNames(names => names.forEach(name => {
             KaravanApi.getKamelet(name, yaml => KameletApi.saveKamelet(yaml))
         }));
@@ -273,11 +290,16 @@ export class Main extends React.Component<Props, State> {
     }
 
     render() {
-        const {isAuthorized} = this.state;
+        const {isAuthorized, authType} = this.state;
         return (
             <Page className="karavan">
+                {authType === undefined && <Bullseye className="loading-page">
+                    <Spinner className="progress-stepper" isSVG 
diameter="80px" aria-label="Loading...">
+                        {Icon()}
+                    </Spinner>
+                </Bullseye>}
                 {isAuthorized && this.getMain()}
-                {!isAuthorized && <MainLogin config={this.state.config} 
onLogin={this.onLogin}/>}
+                {!isAuthorized && authType === 'Basic' && <MainLogin 
config={this.state.config} onLogin={this.onLogin}/>}
                 {this.state.alerts.map((e: ToastMessage) => (
                     <Alert key={e.id} className="main-alert" 
variant={e.variant} title={e.title}
                            timeout={e.variant === "success" ? 1000 : 2000}
diff --git a/karavan-app/src/main/webapp/src/MainLogin.tsx 
b/karavan-app/src/main/webapp/src/MainLogin.tsx
index 1953ee1..90d7db4 100644
--- a/karavan-app/src/main/webapp/src/MainLogin.tsx
+++ b/karavan-app/src/main/webapp/src/MainLogin.tsx
@@ -34,47 +34,6 @@ export class MainLogin extends React.Component<Props, State> 
{
     }
 
     render() {
-        const socialMediaLoginContent = (
-            <React.Fragment>
-                <LoginMainFooterLinksItem href="#" linkComponentProps={{ 
'aria-label': 'Login with Google' }}>
-                    <svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg"; 
viewBox="0 0 488 512">
-                        <path d="M488 261.8C488 403.3 391.1 504 248 504 110.8 
504 0 393.2 0 256S110.8 8 248 8c66.8 0 123 24.5 166.3 64.9l-67.5 64.9C258.5 
52.6 94.3 116.6 94.3 256c0 86.5 69.1 156.6 153.7 156.6 98.2 0 135-70.4 
140.8-106.9H248v-85.3h236.1c2.3 12.7 3.9 24.9 3.9 41.4z" />
-                    </svg>
-                </LoginMainFooterLinksItem>
-                <LoginMainFooterLinksItem href="#" linkComponentProps={{ 
'aria-label': 'Login with Github' }}>
-                    <svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg"; 
viewBox="0 0 496 512">
-                        <path d="M165.9 397.4c0 2-2.3 3.6-5.2 
3.6-3.3.3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 
3.6zm-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 
6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3zm44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 
2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9zM244.8 8C106.1 8 
0 113.3 0 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 
0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 
1.6-15 [...]
-                    </svg>
-                </LoginMainFooterLinksItem>
-                <LoginMainFooterLinksItem href="#" linkComponentProps={{ 
'aria-label': 'Login with Dropbox' }}>
-                    <svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg"; 
viewBox="0 0 528 512">
-                        <path d="M264.4 116.3l-132 84.3 132 84.3-132 84.3L0 
284.1l132.3-84.3L0 116.3 132.3 32l132.1 84.3zM131.6 395.7l132-84.3 132 84.3-132 
84.3-132-84.3zm132.8-111.6l132-84.3-132-83.6L395.7 32 528 116.3l-132.3 84.3L528 
284.8l-132.3 84.3-131.3-85z" />
-                    </svg>
-                </LoginMainFooterLinksItem>
-                <LoginMainFooterLinksItem href="#" linkComponentProps={{ 
'aria-label': 'Login with Facebook' }}>
-                    <svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg"; 
viewBox="0 0 448 512">
-                        <path d="M448 56.7v398.5c0 13.7-11.1 24.7-24.7 
24.7H309.1V306.5h58.2l8.7-67.6h-67v-43.2c0-19.6 5.4-32.9 
33.5-32.9h35.8v-60.5c-6.2-.8-27.4-2.7-52.2-2.7-51.6 0-87 31.5-87 
89.4v49.9h-58.4v67.6h58.4V480H24.7C11.1 480 0 468.9 0 455.3V56.7C0 43.1 11.1 32 
24.7 32h398.5c13.7 0 24.8 11.1 24.8 24.7z" />
-                    </svg>
-                </LoginMainFooterLinksItem>
-                <LoginMainFooterLinksItem href="#" linkComponentProps={{ 
'aria-label': 'Login with Gitlab' }}>
-                    <svg aria-hidden="true" xmlns="http://www.w3.org/2000/svg"; 
viewBox="0 0 512 512">
-                        <path d="M29.782 199.732L256 493.714 8.074 
309.699c-6.856-5.142-9.712-13.996-7.141-21.993l28.849-87.974zm75.405-174.806c-3.142-8.854-15.709-8.854-18.851
 0L29.782 199.732h131.961L105.187 24.926zm56.556 174.806L256 
493.714l94.257-293.982H161.743zm349.324 87.974l-28.849-87.974L256 
493.714l247.926-184.015c6.855-5.142 9.711-13.996 
7.141-21.993zm-85.404-262.78c-3.142-8.854-15.709-8.854-18.851 0l-56.555 
174.806h131.961L425.663 24.926z" />
-                    </svg>
-                </LoginMainFooterLinksItem>
-            </React.Fragment>
-        );
-
-        const signUpForAccountMessage = (
-            <LoginMainFooterBandItem>
-                Need an account? <a href="#">Sign up.</a>
-            </LoginMainFooterBandItem>
-        );
-        const forgotCredentials = (
-            <LoginMainFooterBandItem>
-                <a href="#">Forgot username or password?</a>
-            </LoginMainFooterBandItem>
-        );
-
         return (
             <Bullseye>
                 <Card isFlat isCompact>
@@ -98,10 +57,6 @@ export class MainLogin extends React.Component<Props, State> 
{
                             loginButtonLabel="Log in"
                         />
                     </CardBody>
-                    <CardFooter>
-                        {signUpForAccountMessage}
-                        {forgotCredentials}
-                    </CardFooter>
                 </Card>
             </Bullseye>
         );
diff --git a/karavan-app/src/main/webapp/src/api/KaravanApi.tsx 
b/karavan-app/src/main/webapp/src/api/KaravanApi.tsx
index 09bb9c5..a322662 100644
--- a/karavan-app/src/main/webapp/src/api/KaravanApi.tsx
+++ b/karavan-app/src/main/webapp/src/api/KaravanApi.tsx
@@ -1,12 +1,49 @@
 import axios, {AxiosResponse} from "axios";
-import {Project, ProjectFile, ProjectStatus} from "../models/ProjectModels";
-import { Buffer } from 'buffer';
+import {Project, ProjectFile, ProjectStatus} from "../projects/ProjectModels";
+import {Buffer} from 'buffer';
+import {SsoApi} from "./SsoApi";
 
-export const KaravanApi = {
+axios.defaults.headers.common['Accept'] = 'application/json';
+axios.defaults.headers.common['Content-Type'] = 'application/json';
+const instance = axios.create();
+instance.interceptors.request.use(async config => {
+        config.headers = {
+            'Authorization': 'Bearer ' + SsoApi.keycloak?.token,
+        }
+        return config;
+    },
+    error => {
+        Promise.reject(error)
+    });
+
+instance.interceptors.response.use((response) => {
+    return response
+}, async function (error) {
+    const originalRequest = error.config;
+    if ((error?.response?.status === 403 || error?.response?.status === 401) 
&& !originalRequest._retry) {
+        console.log("error", error)
+        return SsoApi.keycloak?.updateToken(1).then(refreshed => {
+            if (refreshed) {
+                console.log('SsoApi', 'Token was successfully refreshed', 
SsoApi.keycloak?.token);
+            } else {
+                console.log('SsoApi', 'Token is still valid');
+            }
+            originalRequest._retry = true;
+            return instance(originalRequest);
+        }).catch(reason => {
+            console.log('SsoApi', 'Failed to refresh token: ' + reason);
+        });
+    }
+    return Promise.reject(error);
+});
+
+export class KaravanApi {
+
+    static me?: any;
+    static sso: boolean = false;
 
-    getConfiguration: async (after: (config: {}) => void) => {
-        axios.get('/configuration',
-            {headers: {'Accept': 'application/json'}})
+    static async getConfig(after: (config: {}) => void) {
+        axios.get('/public/sso-config', {headers: {'Accept': 
'application/json'}})
             .then(res => {
                 if (res.status === 200) {
                     after(res.data);
@@ -14,35 +51,79 @@ export const KaravanApi = {
             }).catch(err => {
             console.log(err);
         });
-    },
+    }
 
-    getProject: async (projectId: string, after: (project: Project) => void) 
=> {
-        axios.get('/project/' + projectId,
-            {headers: {'Accept': 'application/json', 'username': 'cameleer'}})
+    static async isSSO(after: (config: {}) => void) {
+        axios.get('/public/sso', {headers: {'Accept': 'text/plain'}})
             .then(res => {
                 if (res.status === 200) {
+                    KaravanApi.sso = res.data === 'true' || res.data === true
                     after(res.data);
                 }
             }).catch(err => {
             console.log(err);
         });
-    },
+    }
+
+    static async auth(username: string, password: string, after: (res: any) => 
void) {
+        const token = username + ":" + password;
+        const basicAuth = "Basic " + Buffer.from(token).toString('base64');
+        axios.post('/public/auth/', "",
+            {headers: {Accept: 'application/json', "Content-Type": 
'application/json', Authorization: basicAuth}})
+            .then(res => {
+                after(res);
+            }).catch(err => {
+            after(err.response);
+        });
+    }
 
-    getProjectStatus: async (projectId: string, after: (status: ProjectStatus) 
=> void) => {
-        axios.get('/status/project/' + projectId,
-            {headers: {'Accept': 'application/json', 'username': 'cameleer'}})
+    static async getMe(after: (user: {}) => void) {
+        instance.get('/api/users/me')
             .then(res => {
                 if (res.status === 200) {
+                    KaravanApi.me = res.data;
                     after(res.data);
                 }
             }).catch(err => {
             console.log(err);
         });
-    },
+    }
+
+    static async getConfiguration(after: (config: {}) => void) {
+        instance.get('/api/configuration')
+            .then(res => {
+                if (res.status === 200) {
+                    after(res.data);
+                }
+            }).catch(err => {
+            console.log(err);
+        });
+    }
+
+    static async getProject(projectId: string, after: (project: Project) => 
void) {
+        instance.get('/api/project/' + projectId)
+            .then(res => {
+                if (res.status === 200) {
+                    after(res.data);
+                }
+            }).catch(err => {
+            console.log(err);
+        });
+    }
+
+    static async getProjectStatus(projectId: string, after: (status: 
ProjectStatus) => void) {
+        instance.get('/api/status/project/' + projectId)
+            .then(res => {
+                if (res.status === 200) {
+                    after(res.data);
+                }
+            }).catch(err => {
+            console.log(err);
+        });
+    }
 
-    getProjects: async (after: (projects: Project[]) => void) => {
-        axios.get('/project',
-            {headers: {'Accept': 'application/json', 'username': 'cameleer'}})
+    static async getProjects(after: (projects: Project[]) => void) {
+        instance.get('/api/project')
             .then(res => {
                 if (res.status === 200) {
                     after(res.data.map((p: Partial<Project> | undefined) => 
new Project(p)));
@@ -50,41 +131,38 @@ export const KaravanApi = {
             }).catch(err => {
             console.log(err);
         });
-    },
+    }
 
-    postProject: async (project: Project, after: (res: AxiosResponse<any>) => 
void) => {
-        axios.post('/project', project,
-            {headers: {'Accept': 'application/json', 'Content-Type': 
'application/json', 'username': 'cameleer'}})
+    static async postProject(project: Project, after: (res: 
AxiosResponse<any>) => void) {
+        instance.post('/api/project', project)
             .then(res => {
                 after(res);
             }).catch(err => {
             after(err);
         });
-    },
+    }
 
-    copyProject: async (sourceProject: string, project: Project, after: (res: 
AxiosResponse<any>) => void) => {
-        axios.post('/project/copy/' + sourceProject, project,
-            {headers: {'Accept': 'application/json', 'Content-Type': 
'application/json', 'username': 'cameleer'}})
+    static async copyProject(sourceProject: string, project: Project, after: 
(res: AxiosResponse<any>) => void) {
+        instance.post('/api/project/copy/' + sourceProject, project)
             .then(res => {
                 after(res);
             }).catch(err => {
             after(err);
         });
-    },
+    }
 
-    deleteProject: async (project: Project, after: (res: AxiosResponse<any>) 
=> void) => {
-        axios.delete('/project/' + encodeURI(project.projectId),
-            {headers:{'username': 'cameleer'}})
+    static async deleteProject(project: Project, after: (res: 
AxiosResponse<any>) => void) {
+        instance.delete('/project/' + encodeURI(project.projectId),
+            {headers: {'username': 'cameleer'}})
             .then(res => {
                 after(res);
             }).catch(err => {
             after(err);
         });
-    },
+    }
 
-    getFiles: async (project: string, after: (files: []) => void) => {
-        axios.get('/file/' + project,
-            {headers: {'Accept': 'application/json', 'Content-Type': 
'application/json', 'username': 'cameleer'}})
+    static async getFiles(project: string, after: (files: []) => void) {
+        instance.get('/api/file/' + project)
             .then(res => {
                 if (res.status === 200) {
                     after(res.data);
@@ -92,51 +170,46 @@ export const KaravanApi = {
             }).catch(err => {
             console.log(err);
         });
-    },
+    }
 
-    postProjectFile: async (file: ProjectFile, after: (res: 
AxiosResponse<any>) => void) => {
-        axios.post('/file', file,
-            {headers: {'Accept': 'application/json', 'Content-Type': 
'application/json', 'username': 'cameleer'}})
+    static async postProjectFile(file: ProjectFile, after: (res: 
AxiosResponse<any>) => void) {
+        instance.post('/api/file', file)
             .then(res => {
                 after(res);
             }).catch(err => {
             after(err);
         });
-    },
+    }
 
-    deleteProjectFile: async (file: ProjectFile, after: (res: 
AxiosResponse<any>) => void) => {
-        axios.delete('/file/' + file.projectId + '/' + file.name,
-            {headers:{'username': 'cameleer'}})
+    static async deleteProjectFile(file: ProjectFile, after: (res: 
AxiosResponse<any>) => void) {
+        instance.delete('/api/file/' + file.projectId + '/' + file.name)
             .then(res => {
                 after(res);
             }).catch(err => {
             after(err);
         });
-    },
+    }
 
-    push: async (project: Project, after: (res: AxiosResponse<any>) => void) 
=> {
-        axios.post('/git', project,
-            {headers: {'Accept': 'application/json', 'Content-Type': 
'application/json', 'username': 'cameleer'}})
+    static async push(project: Project, after: (res: AxiosResponse<any>) => 
void) {
+        instance.post('/api/git', project)
             .then(res => {
                 after(res);
             }).catch(err => {
             after(err);
         });
-    },
+    }
 
-    pipelineRun: async (project: Project, environment: string, after: (res: 
AxiosResponse<any>) => void) => {
-        axios.post('/kubernetes/pipeline/' + environment, project,
-            {headers: {'Accept': 'application/json', 'Content-Type': 
'application/json', 'username': 'cameleer'}})
+    static async pipelineRun(project: Project, environment: string, after: 
(res: AxiosResponse<any>) => void) {
+        instance.post('/api/kubernetes/pipeline/' + environment, project)
             .then(res => {
                 after(res);
             }).catch(err => {
             after(err);
         });
-    },
+    }
 
-    getPipelineLog: async (environment: string, pipelineRunName: string, 
after: (res: AxiosResponse<any>) => void) => {
-        axios.get('/kubernetes/pipeline/log/' + environment + "/" + 
pipelineRunName,
-            {headers: {'Accept': 'application/json', 'Content-Type': 
'application/json', 'username': 'cameleer'}})
+    static async getPipelineLog(environment: string, pipelineRunName: string, 
after: (res: AxiosResponse<any>) => void) {
+        instance.get('/api/kubernetes/pipeline/log/' + environment + "/" + 
pipelineRunName)
             .then(res => {
                 if (res.status === 200) {
                     after(res.data);
@@ -144,11 +217,10 @@ export const KaravanApi = {
             }).catch(err => {
             console.log(err);
         });
-    },
+    }
 
-    getContainerLog: async (environment: string, name: string, after: (res: 
AxiosResponse<string>) => void) => {
-        axios.get('/kubernetes/container/log/' + environment + "/" + name,
-            {headers: {'Accept': 'application/json', 'Content-Type': 
'application/json', 'username': 'cameleer'}})
+    static async getContainerLog(environment: string, name: string, after: 
(res: AxiosResponse<string>) => void) {
+        instance.get('/api/kubernetes/container/log/' + environment + "/" + 
name)
             .then(res => {
                 if (res.status === 200) {
                     after(res.data);
@@ -156,41 +228,37 @@ export const KaravanApi = {
             }).catch(err => {
             console.log(err);
         });
-    },
+    }
 
-    rolloutDeployment: async (name: string, environment: string, after: (res: 
AxiosResponse<any>) => void) => {
-        axios.post('/kubernetes/deployment/rollout/' + environment + '/' + 
name, "",
-            {headers: {'Accept': 'application/json', 'Content-Type': 
'application/json', 'username': 'cameleer'}})
+    static async rolloutDeployment(name: string, environment: string, after: 
(res: AxiosResponse<any>) => void) {
+        instance.post('/api/kubernetes/deployment/rollout/' + environment + 
'/' + name, "")
             .then(res => {
                 after(res);
             }).catch(err => {
             after(err);
         });
-    },
+    }
 
-    deleteDeployment: async (environment: string, name: string, after: (res: 
AxiosResponse<any>) => void) => {
-        axios.delete('/kubernetes/deployment/' + environment + '/' + name,
-            {headers: {'Accept': 'application/json', 'Content-Type': 
'application/json', 'username': 'cameleer'}})
+    static async deleteDeployment(environment: string, name: string, after: 
(res: AxiosResponse<any>) => void) {
+        instance.delete('/api/kubernetes/deployment/' + environment + '/' + 
name)
             .then(res => {
                 after(res);
             }).catch(err => {
             after(err);
         });
-    },
+    }
 
-    deletePod: async (environment: string, name: string, after: (res: 
AxiosResponse<any>) => void) => {
-        axios.delete('/kubernetes/pod/' + environment + '/' + name,
-            {headers: {'Accept': 'application/json', 'Content-Type': 
'application/json', 'username': 'cameleer'}})
+    static async deletePod(environment: string, name: string, after: (res: 
AxiosResponse<any>) => void) {
+        instance.delete('/api/kubernetes/pod/' + environment + '/' + name)
             .then(res => {
                 after(res);
             }).catch(err => {
             after(err);
         });
-    },
+    }
 
-    getConfigMaps: async (environment: string, after: (any: []) => void) => {
-        axios.get('/kubernetes/configmap/' + environment,
-            {headers: {'Accept': 'application/json', 'Content-Type': 
'application/json', 'username': 'cameleer'}})
+    static async getConfigMaps(environment: string, after: (any: []) => void) {
+        instance.get('/api/kubernetes/configmap/' + environment)
             .then(res => {
                 if (res.status === 200) {
                     after(res.data);
@@ -198,11 +266,10 @@ export const KaravanApi = {
             }).catch(err => {
             console.log(err);
         });
-    },
+    }
 
-    getSecrets: async (environment: string, after: (any: []) => void) => {
-        axios.get('/kubernetes/secret/' + environment,
-            {headers: {'Accept': 'application/json', 'Content-Type': 
'application/json', 'username': 'cameleer'}})
+    static async getSecrets(environment: string, after: (any: []) => void) {
+        instance.get('/api/kubernetes/secret/' + environment)
             .then(res => {
                 if (res.status === 200) {
                     after(res.data);
@@ -210,11 +277,10 @@ export const KaravanApi = {
             }).catch(err => {
             console.log(err);
         });
-    },
+    }
 
-    getServices: async (environment: string, after: (any: []) => void) => {
-        axios.get('/kubernetes/service/' + environment,
-            {headers: {'Accept': 'application/json', 'Content-Type': 
'application/json', 'username': 'cameleer'}})
+    static async getServices(environment: string, after: (any: []) => void) {
+        instance.get('/api/kubernetes/service/' + environment)
             .then(res => {
                 if (res.status === 200) {
                     after(res.data);
@@ -222,12 +288,11 @@ export const KaravanApi = {
             }).catch(err => {
             console.log(err);
         });
-    },
+    }
 
 
-    getKameletNames: async (after: (names: []) => void) => {
-        axios.get('/kamelet',
-            {headers: {'Accept': 'application/json'}})
+    static async getKameletNames(after: (names: []) => void) {
+        instance.get('/api/kamelet')
             .then(res => {
                 if (res.status === 200) {
                     after(res.data);
@@ -235,11 +300,10 @@ export const KaravanApi = {
             }).catch(err => {
             console.log(err);
         });
-    },
+    }
 
-    getKamelet: async (name: string, after: (yaml: string) => void) => {
-        axios.get('/kamelet/' + name,
-            {headers: {'Accept': 'text/plain'}})
+    static async getKamelet(name: string, after: (yaml: string) => void) {
+        instance.get('/api/kamelet/' + name, {headers: {'Accept': 
'text/plain'}})
             .then(res => {
                 if (res.status === 200) {
                     after(res.data);
@@ -247,11 +311,10 @@ export const KaravanApi = {
             }).catch(err => {
             console.log(err);
         });
-    },
+    }
 
-    getComponentNames: async (after: (names: []) => void) => {
-        axios.get('/component',
-            {headers: {'Accept': 'application/json'}})
+    static async getComponentNames(after: (names: []) => void) {
+        instance.get('/api/component')
             .then(res => {
                 if (res.status === 200) {
                     after(res.data);
@@ -259,11 +322,10 @@ export const KaravanApi = {
             }).catch(err => {
             console.log(err);
         });
-    },
+    }
 
-    getComponent: async (name: string, after: (json: string) => void) => {
-        axios.get('/component/' + name,
-            {headers: {'Accept': 'application/json'}})
+    static async getComponent(name: string, after: (json: string) => void) {
+        instance.get('/api/component/' + name)
             .then(res => {
                 if (res.status === 200) {
                     after(JSON.stringify(res.data));
@@ -271,11 +333,10 @@ export const KaravanApi = {
             }).catch(err => {
             console.log(err);
         });
-    },
+    }
 
-    getOpenApis: async (after: (openapis: []) => void) => {
-        axios.get('/openapi',
-            {headers: {'Accept': 'application/json', 'username': 'cameleer'}})
+    static async getOpenApis(after: (openapis: []) => void) {
+        instance.get('/api/openapi')
             .then(res => {
                 if (res.status === 200) {
                     after(res.data);
@@ -283,38 +344,24 @@ export const KaravanApi = {
             }).catch(err => {
             console.log(err);
         });
-    },
+    }
 
-    getOpenApi: async (name: string, after: (res: AxiosResponse<any>) => void) 
=> {
-        axios.get('/openapi/' + name,
-            {headers: {'Accept': 'text/plain', 'username': 'cameleer'}})
+    static async getOpenApi(name: string, after: (res: AxiosResponse<any>) => 
void) {
+        instance.get('/api/openapi/' + name, {headers: {'Accept': 
'text/plain'}})
             .then(res => {
                 after(res);
             }).catch(err => {
             after(err);
         });
-    },
+    }
 
-    postOpenApi: async (file: ProjectFile, generateRest: boolean, 
generateRoutes: boolean, integrationName: string,  after: (res: 
AxiosResponse<any>) => void) => {
+    static async postOpenApi(file: ProjectFile, generateRest: boolean, 
generateRoutes: boolean, integrationName: string, after: (res: 
AxiosResponse<any>) => void) {
         const uri = 
`/file/openapi/${generateRest}/${generateRoutes}/${integrationName}`;
-        axios.post(encodeURI(uri), file,
-            {headers: {'Accept': 'application/json', 'Content-Type': 
'application/json', 'username': 'cameleer'}})
-            .then(res => {
-                after(res);
-            }).catch(err => {
-                after(err);
-        });
-    },
-
-    auth: async (username: string, password: string, after: (res: any) => 
void) => {
-        const token = username + ":" + password;
-        const basicAuth = "Basic " + Buffer.from(token).toString('base64');
-        axios.post('/auth/', "",
-            {headers: {Accept: 'application/json', "Content-Type": 
'application/json', Authorization: basicAuth }})
+        instance.post(encodeURI(uri), file)
             .then(res => {
                 after(res);
             }).catch(err => {
-                after(err.response);
+            after(err);
         });
-    },
+    }
 }
\ No newline at end of file
diff --git a/karavan-app/src/main/webapp/src/api/SsoApi.tsx 
b/karavan-app/src/main/webapp/src/api/SsoApi.tsx
new file mode 100644
index 0000000..321907f
--- /dev/null
+++ b/karavan-app/src/main/webapp/src/api/SsoApi.tsx
@@ -0,0 +1,20 @@
+import Keycloak from "keycloak-js";
+import {KaravanApi} from "./KaravanApi";
+
+export class SsoApi {
+
+    static keycloak?: Keycloak;
+
+    static auth(after: () => void) {
+        KaravanApi.getConfig((config: any) => {
+            SsoApi.keycloak = new Keycloak({url: config.url, realm: 'karavan', 
clientId: 'karavan-frontend'});
+            SsoApi.keycloak.init({onLoad: 'login-required', flow: 
'hybrid'}).then(value => {
+                console.log('SsoApi', 'User is now authenticated.');
+                after();
+            }).catch(reason => {
+                console.log('SsoApi', 'Error:', reason);
+                window.location.reload();
+            });
+        });
+    }
+}
\ No newline at end of file
diff --git a/karavan-app/src/main/webapp/src/projects/CreateFileModal.tsx 
b/karavan-app/src/main/webapp/src/projects/CreateFileModal.tsx
index aaa5cae..9413dd8 100644
--- a/karavan-app/src/main/webapp/src/projects/CreateFileModal.tsx
+++ b/karavan-app/src/main/webapp/src/projects/CreateFileModal.tsx
@@ -9,7 +9,7 @@ import {
 } from '@patternfly/react-core';
 import '../designer/karavan.css';
 import {KaravanApi} from "../api/KaravanApi";
-import {Project, ProjectFile, ProjectFileTypes} from "../models/ProjectModels";
+import {Project, ProjectFile, ProjectFileTypes} from "./ProjectModels";
 import {CamelUi} from "../designer/utils/CamelUi";
 
 interface Props {
diff --git a/karavan-app/src/main/webapp/src/projects/ProjectDashboard.tsx 
b/karavan-app/src/main/webapp/src/projects/ProjectDashboard.tsx
index 47b5443..c40d1d6 100644
--- a/karavan-app/src/main/webapp/src/projects/ProjectDashboard.tsx
+++ b/karavan-app/src/main/webapp/src/projects/ProjectDashboard.tsx
@@ -7,7 +7,7 @@ import {
 } from '@patternfly/react-core';
 import '../designer/karavan.css';
 import {KaravanApi} from "../api/KaravanApi";
-import {Project, ProjectFileTypes, ProjectStatus} from 
"../models/ProjectModels";
+import {Project, ProjectFileTypes, ProjectStatus} from "./ProjectModels";
 import {ChartDonutThreshold} from "@patternfly/react-charts";
 
 interface Props {
diff --git a/karavan-app/src/main/webapp/src/projects/ProjectInfo.tsx 
b/karavan-app/src/main/webapp/src/projects/ProjectInfo.tsx
index 9bd5022..25e6cf8 100644
--- a/karavan-app/src/main/webapp/src/projects/ProjectInfo.tsx
+++ b/karavan-app/src/main/webapp/src/projects/ProjectInfo.tsx
@@ -11,7 +11,7 @@ import {
 } from '@patternfly/react-core';
 import '../designer/karavan.css';
 import {KaravanApi} from "../api/KaravanApi";
-import {DeploymentStatus, Project, ProjectStatus} from 
"../models/ProjectModels";
+import {DeploymentStatus, Project, ProjectStatus} from "./ProjectModels";
 import BuildIcon from "@patternfly/react-icons/dist/esm/icons/build-icon";
 import RolloutIcon from 
"@patternfly/react-icons/dist/esm/icons/process-automation-icon";
 import PushIcon from "@patternfly/react-icons/dist/esm/icons/code-branch-icon";
diff --git a/karavan-app/src/main/webapp/src/models/ProjectModels.ts 
b/karavan-app/src/main/webapp/src/projects/ProjectModels.ts
similarity index 100%
rename from karavan-app/src/main/webapp/src/models/ProjectModels.ts
rename to karavan-app/src/main/webapp/src/projects/ProjectModels.ts
diff --git a/karavan-app/src/main/webapp/src/projects/ProjectPage.tsx 
b/karavan-app/src/main/webapp/src/projects/ProjectPage.tsx
index 107470c..1c4bd2f 100644
--- a/karavan-app/src/main/webapp/src/projects/ProjectPage.tsx
+++ b/karavan-app/src/main/webapp/src/projects/ProjectPage.tsx
@@ -26,7 +26,7 @@ import {
 import '../designer/karavan.css';
 import {MainToolbar} from "../MainToolbar";
 import {KaravanApi} from "../api/KaravanApi";
-import {Project, ProjectFile, ProjectFileTypes, ProjectStatus} from 
"../models/ProjectModels";
+import {Project, ProjectFile, ProjectFileTypes, ProjectStatus} from 
"./ProjectModels";
 import {CamelUi} from "../designer/utils/CamelUi";
 import UploadIcon from "@patternfly/react-icons/dist/esm/icons/upload-icon";
 import {TableComposable, Tbody, Td, Th, Thead, Tr} from 
"@patternfly/react-table";
diff --git a/karavan-app/src/main/webapp/src/projects/ProjectsPage.tsx 
b/karavan-app/src/main/webapp/src/projects/ProjectsPage.tsx
index 3c32227..cad4f3d 100644
--- a/karavan-app/src/main/webapp/src/projects/ProjectsPage.tsx
+++ b/karavan-app/src/main/webapp/src/projects/ProjectsPage.tsx
@@ -31,7 +31,7 @@ import '../designer/karavan.css';
 import {MainToolbar} from "../MainToolbar";
 import RefreshIcon from '@patternfly/react-icons/dist/esm/icons/sync-alt-icon';
 import PlusIcon from '@patternfly/react-icons/dist/esm/icons/plus-icon';
-import {Project} from "../models/ProjectModels";
+import {Project} from "./ProjectModels";
 import {TableComposable, Tbody, Td, Th, Thead, Tr} from 
"@patternfly/react-table";
 import DeleteIcon from "@patternfly/react-icons/dist/js/icons/times-icon";
 import SearchIcon from '@patternfly/react-icons/dist/esm/icons/search-icon';
diff --git a/karavan-app/src/main/webapp/src/projects/PropertiesEditor.tsx 
b/karavan-app/src/main/webapp/src/projects/PropertiesEditor.tsx
index 4b6ceec..28cbcf4 100644
--- a/karavan-app/src/main/webapp/src/projects/PropertiesEditor.tsx
+++ b/karavan-app/src/main/webapp/src/projects/PropertiesEditor.tsx
@@ -3,7 +3,7 @@ import {
     PageSection,
 } from '@patternfly/react-core';
 import '../designer/karavan.css';
-import {ProjectFile} from "../models/ProjectModels";
+import {ProjectFile} from "./ProjectModels";
 import {PropertiesTable} from "./PropertiesTable";
 import {ProjectModel} from "karavan-core/lib/model/ProjectModel";
 import {ProjectModelApi} from "karavan-core/lib/api/ProjectModelApi";
diff --git a/karavan-app/src/main/webapp/src/projects/UploadModal.tsx 
b/karavan-app/src/main/webapp/src/projects/UploadModal.tsx
index d457c51..b515ca9 100644
--- a/karavan-app/src/main/webapp/src/projects/UploadModal.tsx
+++ b/karavan-app/src/main/webapp/src/projects/UploadModal.tsx
@@ -5,7 +5,7 @@ import {
 } from '@patternfly/react-core';
 import '../designer/karavan.css';
 import {KaravanApi} from "../api/KaravanApi";
-import {ProjectFile} from "../models/ProjectModels";
+import {ProjectFile} from "./ProjectModels";
 
 interface Props {
     projectId: string,
diff --git a/karavan-builder/karavan-realm.json 
b/karavan-builder/karavan-realm.json
new file mode 100644
index 0000000..4037a9e
--- /dev/null
+++ b/karavan-builder/karavan-realm.json
@@ -0,0 +1,2405 @@
+{
+  "id": "6562d57f-3c7a-4566-b8bb-2a38d61cafb5",
+  "realm": "karavan",
+  "displayName": "",
+  "displayNameHtml": "",
+  "notBefore": 0,
+  "defaultSignatureAlgorithm": "RS256",
+  "revokeRefreshToken": false,
+  "refreshTokenMaxReuse": 0,
+  "accessTokenLifespan": 60,
+  "accessTokenLifespanForImplicitFlow": 60,
+  "ssoSessionIdleTimeout": 1800,
+  "ssoSessionMaxLifespan": 36000,
+  "ssoSessionIdleTimeoutRememberMe": 0,
+  "ssoSessionMaxLifespanRememberMe": 0,
+  "offlineSessionIdleTimeout": 2592000,
+  "offlineSessionMaxLifespanEnabled": false,
+  "offlineSessionMaxLifespan": 5184000,
+  "clientSessionIdleTimeout": 0,
+  "clientSessionMaxLifespan": 0,
+  "clientOfflineSessionIdleTimeout": 0,
+  "clientOfflineSessionMaxLifespan": 0,
+  "accessCodeLifespan": 60,
+  "accessCodeLifespanUserAction": 300,
+  "accessCodeLifespanLogin": 1800,
+  "actionTokenGeneratedByAdminLifespan": 43200,
+  "actionTokenGeneratedByUserLifespan": 300,
+  "oauth2DeviceCodeLifespan": 600,
+  "oauth2DevicePollingInterval": 5,
+  "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": "80e65103-f756-43cd-80b1-fca046f94c47",
+        "name": "developer",
+        "description": "",
+        "composite": false,
+        "clientRole": false,
+        "containerId": "6562d57f-3c7a-4566-b8bb-2a38d61cafb5",
+        "attributes": {}
+      },
+      {
+        "id": "ba4d0639-c76e-4a88-99b2-b356d71d968e",
+        "name": "default-roles-karavan",
+        "description": "${role_default-roles}",
+        "composite": true,
+        "composites": {
+          "realm": [
+            "offline_access",
+            "uma_authorization"
+          ],
+          "client": {
+            "account": [
+              "view-profile",
+              "manage-account"
+            ]
+          }
+        },
+        "clientRole": false,
+        "containerId": "6562d57f-3c7a-4566-b8bb-2a38d61cafb5",
+        "attributes": {}
+      },
+      {
+        "id": "cb1ce68b-2413-4b8a-ab21-3265d570df87",
+        "name": "uma_authorization",
+        "description": "${role_uma_authorization}",
+        "composite": false,
+        "clientRole": false,
+        "containerId": "6562d57f-3c7a-4566-b8bb-2a38d61cafb5",
+        "attributes": {}
+      },
+      {
+        "id": "3a5e8a77-30f6-410e-aaf3-360b14fef368",
+        "name": "administrator",
+        "description": "",
+        "composite": false,
+        "clientRole": false,
+        "containerId": "6562d57f-3c7a-4566-b8bb-2a38d61cafb5",
+        "attributes": {}
+      },
+      {
+        "id": "b1892fdc-fccd-4a57-a5b3-6b6c1d9707dc",
+        "name": "viewer",
+        "description": "",
+        "composite": false,
+        "clientRole": false,
+        "containerId": "6562d57f-3c7a-4566-b8bb-2a38d61cafb5",
+        "attributes": {}
+      },
+      {
+        "id": "35f77d32-b2db-4452-b461-5bf110211f3a",
+        "name": "offline_access",
+        "description": "${role_offline-access}",
+        "composite": false,
+        "clientRole": false,
+        "containerId": "6562d57f-3c7a-4566-b8bb-2a38d61cafb5",
+        "attributes": {}
+      }
+    ],
+    "client": {
+      "karavan-frontend": [
+        {
+          "id": "02f9488a-520c-4836-b495-5dc126189c50",
+          "name": "uma_protection",
+          "composite": false,
+          "clientRole": true,
+          "containerId": "8ea85c96-3fbe-4c02-8b00-43a4366f5957",
+          "attributes": {}
+        }
+      ],
+      "realm-management": [
+        {
+          "id": "52b6add0-977e-4d48-bb3f-5655907ef286",
+          "name": "query-realms",
+          "description": "${role_query-realms}",
+          "composite": false,
+          "clientRole": true,
+          "containerId": "0d896239-dee9-4172-a0a5-1950ab32b4ad",
+          "attributes": {}
+        },
+        {
+          "id": "e7fb1fae-f15a-4cfa-9ae2-bf137f4a6082",
+          "name": "manage-clients",
+          "description": "${role_manage-clients}",
+          "composite": false,
+          "clientRole": true,
+          "containerId": "0d896239-dee9-4172-a0a5-1950ab32b4ad",
+          "attributes": {}
+        },
+        {
+          "id": "ffd7fe66-74a4-4312-ad2e-e6e72ac1f449",
+          "name": "view-realm",
+          "description": "${role_view-realm}",
+          "composite": false,
+          "clientRole": true,
+          "containerId": "0d896239-dee9-4172-a0a5-1950ab32b4ad",
+          "attributes": {}
+        },
+        {
+          "id": "259c11f9-ab17-4dff-8160-3a200af8f508",
+          "name": "manage-events",
+          "description": "${role_manage-events}",
+          "composite": false,
+          "clientRole": true,
+          "containerId": "0d896239-dee9-4172-a0a5-1950ab32b4ad",
+          "attributes": {}
+        },
+        {
+          "id": "cc99614f-c4b0-47a1-98e0-4bd8ab7067ab",
+          "name": "manage-users",
+          "description": "${role_manage-users}",
+          "composite": false,
+          "clientRole": true,
+          "containerId": "0d896239-dee9-4172-a0a5-1950ab32b4ad",
+          "attributes": {}
+        },
+        {
+          "id": "08956ca5-35a8-47a5-9fb5-62ed5bab8e01",
+          "name": "query-clients",
+          "description": "${role_query-clients}",
+          "composite": false,
+          "clientRole": true,
+          "containerId": "0d896239-dee9-4172-a0a5-1950ab32b4ad",
+          "attributes": {}
+        },
+        {
+          "id": "0f59a971-8faf-4d82-87b5-665a41e4da08",
+          "name": "manage-realm",
+          "description": "${role_manage-realm}",
+          "composite": false,
+          "clientRole": true,
+          "containerId": "0d896239-dee9-4172-a0a5-1950ab32b4ad",
+          "attributes": {}
+        },
+        {
+          "id": "dd499754-95e2-49a3-89b2-1762e81bd06b",
+          "name": "view-clients",
+          "description": "${role_view-clients}",
+          "composite": true,
+          "composites": {
+            "client": {
+              "realm-management": [
+                "query-clients"
+              ]
+            }
+          },
+          "clientRole": true,
+          "containerId": "0d896239-dee9-4172-a0a5-1950ab32b4ad",
+          "attributes": {}
+        },
+        {
+          "id": "5d141367-4900-406c-a3d7-6486e99b4633",
+          "name": "query-groups",
+          "description": "${role_query-groups}",
+          "composite": false,
+          "clientRole": true,
+          "containerId": "0d896239-dee9-4172-a0a5-1950ab32b4ad",
+          "attributes": {}
+        },
+        {
+          "id": "7d1ed1e2-54bc-4cc5-96b5-8f27e175864d",
+          "name": "view-events",
+          "description": "${role_view-events}",
+          "composite": false,
+          "clientRole": true,
+          "containerId": "0d896239-dee9-4172-a0a5-1950ab32b4ad",
+          "attributes": {}
+        },
+        {
+          "id": "a01dc9ec-f547-4a2a-a0b4-33c842693071",
+          "name": "manage-authorization",
+          "description": "${role_manage-authorization}",
+          "composite": false,
+          "clientRole": true,
+          "containerId": "0d896239-dee9-4172-a0a5-1950ab32b4ad",
+          "attributes": {}
+        },
+        {
+          "id": "e8e9ce47-9fed-4b34-b336-35771c6ae89c",
+          "name": "impersonation",
+          "description": "${role_impersonation}",
+          "composite": false,
+          "clientRole": true,
+          "containerId": "0d896239-dee9-4172-a0a5-1950ab32b4ad",
+          "attributes": {}
+        },
+        {
+          "id": "b3982c35-e635-4fee-ba87-23d973aaf5a7",
+          "name": "view-authorization",
+          "description": "${role_view-authorization}",
+          "composite": false,
+          "clientRole": true,
+          "containerId": "0d896239-dee9-4172-a0a5-1950ab32b4ad",
+          "attributes": {}
+        },
+        {
+          "id": "1bcadccb-cb90-4a77-b220-16ad5e701d7e",
+          "name": "view-identity-providers",
+          "description": "${role_view-identity-providers}",
+          "composite": false,
+          "clientRole": true,
+          "containerId": "0d896239-dee9-4172-a0a5-1950ab32b4ad",
+          "attributes": {}
+        },
+        {
+          "id": "4e0038b6-a8c2-4f1b-bea6-bf2afa4b707e",
+          "name": "realm-admin",
+          "description": "${role_realm-admin}",
+          "composite": true,
+          "composites": {
+            "client": {
+              "realm-management": [
+                "query-realms",
+                "manage-clients",
+                "view-realm",
+                "manage-events",
+                "manage-users",
+                "query-clients",
+                "manage-realm",
+                "view-clients",
+                "query-groups",
+                "view-events",
+                "manage-authorization",
+                "impersonation",
+                "view-identity-providers",
+                "view-authorization",
+                "view-users",
+                "create-client",
+                "query-users",
+                "manage-identity-providers"
+              ]
+            }
+          },
+          "clientRole": true,
+          "containerId": "0d896239-dee9-4172-a0a5-1950ab32b4ad",
+          "attributes": {}
+        },
+        {
+          "id": "c8d748c8-5864-47bd-9141-7f6a23034ac6",
+          "name": "view-users",
+          "description": "${role_view-users}",
+          "composite": true,
+          "composites": {
+            "client": {
+              "realm-management": [
+                "query-users",
+                "query-groups"
+              ]
+            }
+          },
+          "clientRole": true,
+          "containerId": "0d896239-dee9-4172-a0a5-1950ab32b4ad",
+          "attributes": {}
+        },
+        {
+          "id": "ffcab42b-5126-4d8a-b283-1a96338b4a41",
+          "name": "create-client",
+          "description": "${role_create-client}",
+          "composite": false,
+          "clientRole": true,
+          "containerId": "0d896239-dee9-4172-a0a5-1950ab32b4ad",
+          "attributes": {}
+        },
+        {
+          "id": "243d0070-c70d-4084-96d2-ea07541530fe",
+          "name": "query-users",
+          "description": "${role_query-users}",
+          "composite": false,
+          "clientRole": true,
+          "containerId": "0d896239-dee9-4172-a0a5-1950ab32b4ad",
+          "attributes": {}
+        },
+        {
+          "id": "0f5f4fe1-195e-4384-bb60-ed8dd4ced405",
+          "name": "manage-identity-providers",
+          "description": "${role_manage-identity-providers}",
+          "composite": false,
+          "clientRole": true,
+          "containerId": "0d896239-dee9-4172-a0a5-1950ab32b4ad",
+          "attributes": {}
+        }
+      ],
+      "karavan-backend": [],
+      "security-admin-console": [],
+      "admin-cli": [],
+      "account-console": [],
+      "broker": [
+        {
+          "id": "ab741448-d3e6-45a9-ba2d-ac1502b19631",
+          "name": "read-token",
+          "description": "${role_read-token}",
+          "composite": false,
+          "clientRole": true,
+          "containerId": "37133f55-003d-4397-ad82-f5f4b7f56467",
+          "attributes": {}
+        }
+      ],
+      "account": [
+        {
+          "id": "9dc76c56-2c0b-4867-a5f0-5d299d889a77",
+          "name": "manage-consent",
+          "description": "${role_manage-consent}",
+          "composite": true,
+          "composites": {
+            "client": {
+              "account": [
+                "view-consent"
+              ]
+            }
+          },
+          "clientRole": true,
+          "containerId": "c6f5cc82-8ad4-4e91-a71f-6fc2c1b836f0",
+          "attributes": {}
+        },
+        {
+          "id": "8a1a8a57-7d0d-4f48-84c2-12e25070bf8c",
+          "name": "view-profile",
+          "description": "${role_view-profile}",
+          "composite": false,
+          "clientRole": true,
+          "containerId": "c6f5cc82-8ad4-4e91-a71f-6fc2c1b836f0",
+          "attributes": {}
+        },
+        {
+          "id": "2777d407-4e74-431f-b1e7-dc537c4696dd",
+          "name": "view-consent",
+          "description": "${role_view-consent}",
+          "composite": false,
+          "clientRole": true,
+          "containerId": "c6f5cc82-8ad4-4e91-a71f-6fc2c1b836f0",
+          "attributes": {}
+        },
+        {
+          "id": "55484d01-01e2-4579-b434-e6b7992af7d8",
+          "name": "view-applications",
+          "description": "${role_view-applications}",
+          "composite": false,
+          "clientRole": true,
+          "containerId": "c6f5cc82-8ad4-4e91-a71f-6fc2c1b836f0",
+          "attributes": {}
+        },
+        {
+          "id": "88511016-8fe9-46ab-9a00-880e8afcd11e",
+          "name": "delete-account",
+          "description": "${role_delete-account}",
+          "composite": false,
+          "clientRole": true,
+          "containerId": "c6f5cc82-8ad4-4e91-a71f-6fc2c1b836f0",
+          "attributes": {}
+        },
+        {
+          "id": "2bfb99b4-a3bb-44ec-9368-cd743c6e6736",
+          "name": "manage-account",
+          "description": "${role_manage-account}",
+          "composite": true,
+          "composites": {
+            "client": {
+              "account": [
+                "manage-account-links"
+              ]
+            }
+          },
+          "clientRole": true,
+          "containerId": "c6f5cc82-8ad4-4e91-a71f-6fc2c1b836f0",
+          "attributes": {}
+        },
+        {
+          "id": "baa20014-1019-4ea2-9f5a-0aaa9ad387b5",
+          "name": "manage-account-links",
+          "description": "${role_manage-account-links}",
+          "composite": false,
+          "clientRole": true,
+          "containerId": "c6f5cc82-8ad4-4e91-a71f-6fc2c1b836f0",
+          "attributes": {}
+        }
+      ]
+    }
+  },
+  "groups": [
+    {
+      "id": "4d80db18-4945-4128-9b45-27f6f8b1bd09",
+      "name": "administrators",
+      "path": "/administrators",
+      "attributes": {},
+      "realmRoles": [
+        "administrator"
+      ],
+      "clientRoles": {},
+      "subGroups": []
+    },
+    {
+      "id": "c22cf3c5-9bb0-4f50-b5b5-2dceeacbc001",
+      "name": "developers",
+      "path": "/developers",
+      "attributes": {},
+      "realmRoles": [
+        "developer"
+      ],
+      "clientRoles": {},
+      "subGroups": []
+    },
+    {
+      "id": "e657b3af-973b-489e-84b2-43ebd892004f",
+      "name": "viewers",
+      "path": "/viewers",
+      "attributes": {},
+      "realmRoles": [
+        "viewer"
+      ],
+      "clientRoles": {},
+      "subGroups": []
+    }
+  ],
+  "defaultRole": {
+    "id": "ba4d0639-c76e-4a88-99b2-b356d71d968e",
+    "name": "default-roles-karavan",
+    "description": "${role_default-roles}",
+    "composite": true,
+    "clientRole": false,
+    "containerId": "6562d57f-3c7a-4566-b8bb-2a38d61cafb5"
+  },
+  "requiredCredentials": [
+    "password"
+  ],
+  "otpPolicyType": "totp",
+  "otpPolicyAlgorithm": "HmacSHA1",
+  "otpPolicyInitialCounter": 0,
+  "otpPolicyDigits": 6,
+  "otpPolicyLookAheadWindow": 1,
+  "otpPolicyPeriod": 30,
+  "otpSupportedApplications": [
+    "FreeOTP",
+    "Google Authenticator"
+  ],
+  "webAuthnPolicyRpEntityName": "keycloak",
+  "webAuthnPolicySignatureAlgorithms": [
+    "ES256"
+  ],
+  "webAuthnPolicyRpId": "",
+  "webAuthnPolicyAttestationConveyancePreference": "not specified",
+  "webAuthnPolicyAuthenticatorAttachment": "not specified",
+  "webAuthnPolicyRequireResidentKey": "not specified",
+  "webAuthnPolicyUserVerificationRequirement": "not specified",
+  "webAuthnPolicyCreateTimeout": 0,
+  "webAuthnPolicyAvoidSameAuthenticatorRegister": false,
+  "webAuthnPolicyAcceptableAaguids": [],
+  "webAuthnPolicyPasswordlessRpEntityName": "keycloak",
+  "webAuthnPolicyPasswordlessSignatureAlgorithms": [
+    "ES256"
+  ],
+  "webAuthnPolicyPasswordlessRpId": "",
+  "webAuthnPolicyPasswordlessAttestationConveyancePreference": "not specified",
+  "webAuthnPolicyPasswordlessAuthenticatorAttachment": "not specified",
+  "webAuthnPolicyPasswordlessRequireResidentKey": "not specified",
+  "webAuthnPolicyPasswordlessUserVerificationRequirement": "not specified",
+  "webAuthnPolicyPasswordlessCreateTimeout": 0,
+  "webAuthnPolicyPasswordlessAvoidSameAuthenticatorRegister": false,
+  "webAuthnPolicyPasswordlessAcceptableAaguids": [],
+  "scopeMappings": [
+    {
+      "clientScope": "offline_access",
+      "roles": [
+        "offline_access"
+      ]
+    },
+    {
+      "clientScope": "roles",
+      "roles": [
+        "viewer",
+        "administrator",
+        "developer"
+      ]
+    }
+  ],
+  "clientScopeMappings": {
+    "account": [
+      {
+        "client": "account-console",
+        "roles": [
+          "manage-account"
+        ]
+      }
+    ]
+  },
+  "clients": [
+    {
+      "id": "c6f5cc82-8ad4-4e91-a71f-6fc2c1b836f0",
+      "clientId": "account",
+      "name": "${client_account}",
+      "rootUrl": "${authBaseUrl}",
+      "baseUrl": "/realms/karavan/account/",
+      "surrogateAuthRequired": false,
+      "enabled": true,
+      "alwaysDisplayInConsole": false,
+      "clientAuthenticatorType": "client-secret",
+      "redirectUris": [
+        "/realms/karavan/account/*"
+      ],
+      "webOrigins": [],
+      "notBefore": 0,
+      "bearerOnly": false,
+      "consentRequired": false,
+      "standardFlowEnabled": true,
+      "implicitFlowEnabled": false,
+      "directAccessGrantsEnabled": false,
+      "serviceAccountsEnabled": false,
+      "publicClient": true,
+      "frontchannelLogout": false,
+      "protocol": "openid-connect",
+      "attributes": {
+        "post.logout.redirect.uris": "+"
+      },
+      "authenticationFlowBindingOverrides": {},
+      "fullScopeAllowed": false,
+      "nodeReRegistrationTimeout": 0,
+      "defaultClientScopes": [
+        "web-origins",
+        "acr",
+        "profile",
+        "roles",
+        "email"
+      ],
+      "optionalClientScopes": [
+        "address",
+        "phone",
+        "offline_access",
+        "microprofile-jwt"
+      ]
+    },
+    {
+      "id": "0df3fbc3-7bf8-4170-8d77-704956948ccd",
+      "clientId": "account-console",
+      "name": "${client_account-console}",
+      "rootUrl": "${authBaseUrl}",
+      "baseUrl": "/realms/karavan/account/",
+      "surrogateAuthRequired": false,
+      "enabled": true,
+      "alwaysDisplayInConsole": false,
+      "clientAuthenticatorType": "client-secret",
+      "redirectUris": [
+        "/realms/karavan/account/*"
+      ],
+      "webOrigins": [],
+      "notBefore": 0,
+      "bearerOnly": false,
+      "consentRequired": false,
+      "standardFlowEnabled": true,
+      "implicitFlowEnabled": false,
+      "directAccessGrantsEnabled": false,
+      "serviceAccountsEnabled": false,
+      "publicClient": true,
+      "frontchannelLogout": false,
+      "protocol": "openid-connect",
+      "attributes": {
+        "post.logout.redirect.uris": "+",
+        "pkce.code.challenge.method": "S256"
+      },
+      "authenticationFlowBindingOverrides": {},
+      "fullScopeAllowed": false,
+      "nodeReRegistrationTimeout": 0,
+      "protocolMappers": [
+        {
+          "id": "9fa808dc-9d16-44bf-ae2b-3d130e1419d8",
+          "name": "audience resolve",
+          "protocol": "openid-connect",
+          "protocolMapper": "oidc-audience-resolve-mapper",
+          "consentRequired": false,
+          "config": {}
+        }
+      ],
+      "defaultClientScopes": [
+        "web-origins",
+        "acr",
+        "profile",
+        "roles",
+        "email"
+      ],
+      "optionalClientScopes": [
+        "address",
+        "phone",
+        "offline_access",
+        "microprofile-jwt"
+      ]
+    },
+    {
+      "id": "cd5e1900-6a4d-4a18-925b-06860c64f374",
+      "clientId": "admin-cli",
+      "name": "${client_admin-cli}",
+      "surrogateAuthRequired": false,
+      "enabled": true,
+      "alwaysDisplayInConsole": false,
+      "clientAuthenticatorType": "client-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",
+        "acr",
+        "profile",
+        "roles",
+        "email"
+      ],
+      "optionalClientScopes": [
+        "address",
+        "phone",
+        "offline_access",
+        "microprofile-jwt"
+      ]
+    },
+    {
+      "id": "37133f55-003d-4397-ad82-f5f4b7f56467",
+      "clientId": "broker",
+      "name": "${client_broker}",
+      "surrogateAuthRequired": false,
+      "enabled": true,
+      "alwaysDisplayInConsole": false,
+      "clientAuthenticatorType": "client-secret",
+      "redirectUris": [],
+      "webOrigins": [],
+      "notBefore": 0,
+      "bearerOnly": true,
+      "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",
+        "acr",
+        "profile",
+        "roles",
+        "email"
+      ],
+      "optionalClientScopes": [
+        "address",
+        "phone",
+        "offline_access",
+        "microprofile-jwt"
+      ]
+    },
+    {
+      "id": "4a667224-8418-4877-a4e4-d3362b994b6a",
+      "clientId": "karavan-backend",
+      "name": "karavan-backend",
+      "description": "",
+      "rootUrl": "http://localhost:8080";,
+      "adminUrl": "",
+      "baseUrl": "http://localhost:8080";,
+      "surrogateAuthRequired": false,
+      "enabled": true,
+      "alwaysDisplayInConsole": false,
+      "clientAuthenticatorType": "client-secret",
+      "secret": "**********",
+      "redirectUris": [
+        "http://localhost:8080/*";
+      ],
+      "webOrigins": [
+        "*"
+      ],
+      "notBefore": 0,
+      "bearerOnly": false,
+      "consentRequired": false,
+      "standardFlowEnabled": true,
+      "implicitFlowEnabled": false,
+      "directAccessGrantsEnabled": true,
+      "serviceAccountsEnabled": false,
+      "publicClient": false,
+      "frontchannelLogout": true,
+      "protocol": "openid-connect",
+      "attributes": {
+        "oidc.ciba.grant.enabled": "false",
+        "client.secret.creation.time": "1662565636",
+        "backchannel.logout.session.required": "true",
+        "display.on.consent.screen": "false",
+        "oauth2.device.authorization.grant.enabled": "false",
+        "backchannel.logout.revoke.offline.tokens": "false"
+      },
+      "authenticationFlowBindingOverrides": {},
+      "fullScopeAllowed": true,
+      "nodeReRegistrationTimeout": -1,
+      "defaultClientScopes": [
+        "web-origins",
+        "acr",
+        "profile",
+        "roles",
+        "email"
+      ],
+      "optionalClientScopes": [
+        "address",
+        "phone",
+        "offline_access",
+        "microprofile-jwt"
+      ]
+    },
+    {
+      "id": "8ea85c96-3fbe-4c02-8b00-43a4366f5957",
+      "clientId": "karavan-frontend",
+      "name": "karavan-frontend",
+      "description": "",
+      "rootUrl": "http://localhost:8080";,
+      "adminUrl": "",
+      "baseUrl": "http://localhost:8080";,
+      "surrogateAuthRequired": false,
+      "enabled": true,
+      "alwaysDisplayInConsole": true,
+      "clientAuthenticatorType": "client-secret",
+      "redirectUris": [
+        "http://localhost:8080/*";,
+        "http://localhost:8080";
+      ],
+      "webOrigins": [
+        "*"
+      ],
+      "notBefore": 0,
+      "bearerOnly": false,
+      "consentRequired": false,
+      "standardFlowEnabled": true,
+      "implicitFlowEnabled": true,
+      "directAccessGrantsEnabled": true,
+      "serviceAccountsEnabled": false,
+      "publicClient": true,
+      "frontchannelLogout": true,
+      "protocol": "openid-connect",
+      "attributes": {
+        "client.secret.creation.time": "1662491799",
+        "oauth2.device.authorization.grant.enabled": "false",
+        "backchannel.logout.revoke.offline.tokens": "false",
+        "use.refresh.tokens": "true",
+        "tls-client-certificate-bound-access-tokens": "false",
+        "oidc.ciba.grant.enabled": "false",
+        "backchannel.logout.session.required": "true",
+        "client_credentials.use_refresh_token": "false",
+        "acr.loa.map": "{}",
+        "require.pushed.authorization.requests": "false",
+        "display.on.consent.screen": "false",
+        "token.response.type.bearer.lower-case": "false"
+      },
+      "authenticationFlowBindingOverrides": {},
+      "fullScopeAllowed": true,
+      "nodeReRegistrationTimeout": -1,
+      "protocolMappers": [
+        {
+          "id": "7fd86114-d7c8-44f3-85e8-6521f427a8cf",
+          "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": "46199aae-a84d-429f-a3dd-f60a0189f672",
+          "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": "06273632-b6f4-4931-933c-f7f86a5e9e2c",
+          "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",
+        "acr",
+        "profile",
+        "roles",
+        "email"
+      ],
+      "optionalClientScopes": [
+        "address",
+        "phone",
+        "offline_access",
+        "microprofile-jwt"
+      ]
+    },
+    {
+      "id": "0d896239-dee9-4172-a0a5-1950ab32b4ad",
+      "clientId": "realm-management",
+      "name": "${client_realm-management}",
+      "surrogateAuthRequired": false,
+      "enabled": true,
+      "alwaysDisplayInConsole": false,
+      "clientAuthenticatorType": "client-secret",
+      "redirectUris": [],
+      "webOrigins": [],
+      "notBefore": 0,
+      "bearerOnly": true,
+      "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",
+        "acr",
+        "profile",
+        "roles",
+        "email"
+      ],
+      "optionalClientScopes": [
+        "address",
+        "phone",
+        "offline_access",
+        "microprofile-jwt"
+      ]
+    },
+    {
+      "id": "2cb7dddf-ca0b-4d0b-98ea-18085c061206",
+      "clientId": "security-admin-console",
+      "name": "${client_security-admin-console}",
+      "rootUrl": "${authAdminUrl}",
+      "baseUrl": "/admin/karavan/console/",
+      "surrogateAuthRequired": false,
+      "enabled": true,
+      "alwaysDisplayInConsole": false,
+      "clientAuthenticatorType": "client-secret",
+      "redirectUris": [
+        "/admin/karavan/console/*"
+      ],
+      "webOrigins": [
+        "+"
+      ],
+      "notBefore": 0,
+      "bearerOnly": false,
+      "consentRequired": false,
+      "standardFlowEnabled": true,
+      "implicitFlowEnabled": false,
+      "directAccessGrantsEnabled": false,
+      "serviceAccountsEnabled": false,
+      "publicClient": true,
+      "frontchannelLogout": false,
+      "protocol": "openid-connect",
+      "attributes": {
+        "post.logout.redirect.uris": "+",
+        "pkce.code.challenge.method": "S256"
+      },
+      "authenticationFlowBindingOverrides": {},
+      "fullScopeAllowed": false,
+      "nodeReRegistrationTimeout": 0,
+      "protocolMappers": [
+        {
+          "id": "7697e393-836b-4e4c-9c87-0bfafc6d3345",
+          "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",
+        "acr",
+        "profile",
+        "roles",
+        "email"
+      ],
+      "optionalClientScopes": [
+        "address",
+        "phone",
+        "offline_access",
+        "microprofile-jwt"
+      ]
+    }
+  ],
+  "clientScopes": [
+    {
+      "id": "dd806da8-202e-4634-a3d4-51546e23cd03",
+      "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": "44ea8214-88c3-4c01-94a7-449f2b1b5f97",
+          "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": "c7bc8212-7604-485d-a764-57b35d5393ab",
+      "name": "offline_access",
+      "description": "OpenID Connect built-in scope: offline_access",
+      "protocol": "openid-connect",
+      "attributes": {
+        "consent.screen.text": "${offlineAccessScopeConsentText}",
+        "display.on.consent.screen": "true"
+      }
+    },
+    {
+      "id": "dd49f4b3-7a6d-4ddb-83d0-7c1e113596d2",
+      "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": "aea5ed66-c89b-46ce-ae1c-740f23029f11",
+          "name": "allowed web origins",
+          "protocol": "openid-connect",
+          "protocolMapper": "oidc-allowed-origins-mapper",
+          "consentRequired": false,
+          "config": {}
+        }
+      ]
+    },
+    {
+      "id": "ace6f66a-6aec-43ef-92ce-e37a2efafce6",
+      "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": "ddf30129-fd95-49c1-8b6d-436b4fb4eab3",
+          "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": "8df62edc-1000-49b9-99de-47832487443a",
+          "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": "95f701eb-c024-42dd-84d8-023cc48f41ce",
+      "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": "b2c3017f-f732-4a5f-85fb-e00015e318ff",
+          "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": "92399b90-4045-4e08-9cbe-859a888db49f",
+          "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": "65cffabe-4352-454f-b055-8559fdcf5e72",
+          "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": "68636224-a156-42a3-9e59-cf9aa1b25d1d",
+          "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": "13c8c9cb-484e-4f50-a31b-5c76ceb0755a",
+          "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": "long"
+          }
+        },
+        {
+          "id": "4fb5cbc4-caf1-4d04-aeae-d477acd8a9f4",
+          "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": "9c8a587d-000d-4fed-a3f5-674d200fe1d2",
+          "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": "11e05080-517e-4ae7-8a82-40ce6d91cd0f",
+          "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": "50c924ed-a1a9-4dc5-bd89-6299651c63aa",
+          "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": "cbe0f591-d373-4121-a8d4-a9c578002811",
+          "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": "324abe97-3d66-4ed9-b3e2-4f9266d7e88d",
+          "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": "fef27669-7928-4d89-b1c8-87622b60985d",
+          "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": "75a5730e-4f44-4a79-a55c-a19c57ac5ac7",
+          "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": "d9ba2a3c-dcec-4ece-9255-b8f066123dd8",
+          "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": "798cc16d-16a7-410c-b9ba-d8f9ef830612",
+      "name": "role_list",
+      "description": "SAML role list",
+      "protocol": "saml",
+      "attributes": {
+        "consent.screen.text": "${samlRoleListScopeConsentText}",
+        "display.on.consent.screen": "true"
+      },
+      "protocolMappers": [
+        {
+          "id": "127230d4-d4ef-44a9-ab7c-9479c1f033ab",
+          "name": "role list",
+          "protocol": "saml",
+          "protocolMapper": "saml-role-list-mapper",
+          "consentRequired": false,
+          "config": {
+            "single": "false",
+            "attribute.nameformat": "Basic",
+            "attribute.name": "Role"
+          }
+        }
+      ]
+    },
+    {
+      "id": "53ae60a7-bf41-4854-a1bd-b63454a059b6",
+      "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": "17a4dec3-3f19-4b30-8eba-16c2291c433f",
+          "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": "0a846ed5-04e0-4bd5-8477-513f2447e914",
+          "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": "64a778e1-9a72-4bbe-89e1-bef28640f368",
+      "name": "acr",
+      "description": "OpenID Connect scope for add acr (authentication context 
class reference) to the token",
+      "protocol": "openid-connect",
+      "attributes": {
+        "include.in.token.scope": "false",
+        "display.on.consent.screen": "false"
+      },
+      "protocolMappers": [
+        {
+          "id": "d91e3d52-bb5b-4737-9f5b-38385a8580fb",
+          "name": "acr loa level",
+          "protocol": "openid-connect",
+          "protocolMapper": "oidc-acr-mapper",
+          "consentRequired": false,
+          "config": {
+            "id.token.claim": "true",
+            "access.token.claim": "true"
+          }
+        }
+      ]
+    },
+    {
+      "id": "19a4d6fa-f94d-4752-bf26-e1d9a374c87a",
+      "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": "5b29de61-7888-418c-a70c-9934dcc473b6",
+          "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": "36dff379-0b42-46b3-a90e-72ebc7d8a12e",
+          "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": "ccf6db1c-8b37-48be-b752-0517bfa382f7",
+      "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",
+        "gui.order": "",
+        "consent.screen.text": "${rolesScopeConsentText}"
+      },
+      "protocolMappers": [
+        {
+          "id": "9c61b306-60d5-4c39-ae4c-aabca433733e",
+          "name": "realm roles",
+          "protocol": "openid-connect",
+          "protocolMapper": "oidc-usermodel-realm-role-mapper",
+          "consentRequired": false,
+          "config": {
+            "user.attribute": "foo",
+            "access.token.claim": "true",
+            "claim.name": "realm_access.roles",
+            "jsonType.label": "String",
+            "multivalued": "true"
+          }
+        },
+        {
+          "id": "1f5da035-f052-4f52-90a7-fca3f110e4a3",
+          "name": "audience resolve",
+          "protocol": "openid-connect",
+          "protocolMapper": "oidc-audience-resolve-mapper",
+          "consentRequired": false,
+          "config": {}
+        },
+        {
+          "id": "537e969c-747a-4e0e-8a11-0e56fdd0d099",
+          "name": "client roles",
+          "protocol": "openid-connect",
+          "protocolMapper": "oidc-usermodel-client-role-mapper",
+          "consentRequired": false,
+          "config": {
+            "user.attribute": "foo",
+            "access.token.claim": "true",
+            "claim.name": "resource_access.${client_id}.roles",
+            "jsonType.label": "String",
+            "multivalued": "true"
+          }
+        }
+      ]
+    }
+  ],
+  "defaultDefaultClientScopes": [
+    "role_list",
+    "profile",
+    "email",
+    "web-origins",
+    "acr",
+    "roles"
+  ],
+  "defaultOptionalClientScopes": [
+    "offline_access",
+    "address",
+    "phone",
+    "microprofile-jwt"
+  ],
+  "browserSecurityHeaders": {
+    "contentSecurityPolicyReportOnly": "",
+    "xContentTypeOptions": "nosniff",
+    "xRobotsTag": "none",
+    "xFrameOptions": "SAMEORIGIN",
+    "contentSecurityPolicy": "frame-src 'self'; frame-ancestors 'self'; 
object-src 'none';",
+    "xXSSProtection": "1; mode=block",
+    "strictTransportSecurity": "max-age=31536000; includeSubDomains"
+  },
+  "smtpServer": {},
+  "eventsEnabled": false,
+  "eventsListeners": [
+    "jboss-logging"
+  ],
+  "enabledEventTypes": [],
+  "adminEventsEnabled": false,
+  "adminEventsDetailsEnabled": false,
+  "identityProviders": [],
+  "identityProviderMappers": [],
+  "components": {
+    
"org.keycloak.services.clientregistration.policy.ClientRegistrationPolicy": [
+      {
+        "id": "e4748767-37fc-4271-98ca-8b721557daf3",
+        "name": "Full Scope Disabled",
+        "providerId": "scope",
+        "subType": "anonymous",
+        "subComponents": {},
+        "config": {}
+      },
+      {
+        "id": "adacec82-8271-4c5d-aa8c-88e62a371cba",
+        "name": "Max Clients Limit",
+        "providerId": "max-clients",
+        "subType": "anonymous",
+        "subComponents": {},
+        "config": {
+          "max-clients": [
+            "200"
+          ]
+        }
+      },
+      {
+        "id": "fd2ae24c-818d-4638-abd7-2042e4cce269",
+        "name": "Allowed Client Scopes",
+        "providerId": "allowed-client-templates",
+        "subType": "anonymous",
+        "subComponents": {},
+        "config": {
+          "allow-default-scopes": [
+            "true"
+          ]
+        }
+      },
+      {
+        "id": "2591ed13-a8e9-401f-a0cd-59bdc4735adf",
+        "name": "Consent Required",
+        "providerId": "consent-required",
+        "subType": "anonymous",
+        "subComponents": {},
+        "config": {}
+      },
+      {
+        "id": "8eed841e-6201-401e-807b-5044d00a1c04",
+        "name": "Trusted Hosts",
+        "providerId": "trusted-hosts",
+        "subType": "anonymous",
+        "subComponents": {},
+        "config": {
+          "host-sending-registration-request-must-match": [
+            "true"
+          ],
+          "client-uris-must-match": [
+            "true"
+          ]
+        }
+      },
+      {
+        "id": "b27ba27c-6e18-479a-8f40-3c4615e608dc",
+        "name": "Allowed Protocol Mapper Types",
+        "providerId": "allowed-protocol-mappers",
+        "subType": "authenticated",
+        "subComponents": {},
+        "config": {
+          "allowed-protocol-mapper-types": [
+            "oidc-usermodel-attribute-mapper",
+            "saml-user-property-mapper",
+            "oidc-full-name-mapper",
+            "oidc-usermodel-property-mapper",
+            "saml-user-attribute-mapper",
+            "oidc-sha256-pairwise-sub-mapper",
+            "oidc-address-mapper",
+            "saml-role-list-mapper"
+          ]
+        }
+      },
+      {
+        "id": "092df6ca-650c-4469-a839-090bc1b6d22c",
+        "name": "Allowed Protocol Mapper Types",
+        "providerId": "allowed-protocol-mappers",
+        "subType": "anonymous",
+        "subComponents": {},
+        "config": {
+          "allowed-protocol-mapper-types": [
+            "saml-user-property-mapper",
+            "oidc-address-mapper",
+            "oidc-sha256-pairwise-sub-mapper",
+            "oidc-usermodel-attribute-mapper",
+            "oidc-usermodel-property-mapper",
+            "saml-user-attribute-mapper",
+            "oidc-full-name-mapper",
+            "saml-role-list-mapper"
+          ]
+        }
+      },
+      {
+        "id": "56fce54c-5e75-4503-aa7d-925170d82a9d",
+        "name": "Allowed Client Scopes",
+        "providerId": "allowed-client-templates",
+        "subType": "authenticated",
+        "subComponents": {},
+        "config": {
+          "allow-default-scopes": [
+            "true"
+          ]
+        }
+      }
+    ],
+    "org.keycloak.userprofile.UserProfileProvider": [
+      {
+        "id": "f32fdf6d-de24-4478-827c-666f89dbefb8",
+        "providerId": "declarative-user-profile",
+        "subComponents": {},
+        "config": {}
+      }
+    ],
+    "org.keycloak.keys.KeyProvider": [
+      {
+        "id": "f6534d5e-e9c6-4f65-9521-a36d55a13444",
+        "name": "rsa-generated",
+        "providerId": "rsa-generated",
+        "subComponents": {},
+        "config": {
+          "priority": [
+            "100"
+          ]
+        }
+      },
+      {
+        "id": "f635ec76-b78e-4fad-9114-3ca8d39960dd",
+        "name": "hmac-generated",
+        "providerId": "hmac-generated",
+        "subComponents": {},
+        "config": {
+          "priority": [
+            "100"
+          ],
+          "algorithm": [
+            "HS256"
+          ]
+        }
+      },
+      {
+        "id": "8b4bbb8c-8cec-409f-8734-135b94bb92f6",
+        "name": "rsa-enc-generated",
+        "providerId": "rsa-enc-generated",
+        "subComponents": {},
+        "config": {
+          "priority": [
+            "100"
+          ],
+          "algorithm": [
+            "RSA-OAEP"
+          ]
+        }
+      },
+      {
+        "id": "a2d0ccbd-10a1-4200-a781-889b5fc7b74d",
+        "name": "aes-generated",
+        "providerId": "aes-generated",
+        "subComponents": {},
+        "config": {
+          "priority": [
+            "100"
+          ]
+        }
+      }
+    ]
+  },
+  "internationalizationEnabled": false,
+  "supportedLocales": [],
+  "authenticationFlows": [
+    {
+      "id": "2f589b8c-c67c-4344-b77a-73db7e9ff238",
+      "alias": "Account verification options",
+      "description": "Method with which to verity the existing account",
+      "providerId": "basic-flow",
+      "topLevel": false,
+      "builtIn": true,
+      "authenticationExecutions": [
+        {
+          "authenticator": "idp-email-verification",
+          "authenticatorFlow": false,
+          "requirement": "ALTERNATIVE",
+          "priority": 10,
+          "autheticatorFlow": false,
+          "userSetupAllowed": false
+        },
+        {
+          "authenticatorFlow": true,
+          "requirement": "ALTERNATIVE",
+          "priority": 20,
+          "autheticatorFlow": true,
+          "flowAlias": "Verify Existing Account by Re-authentication",
+          "userSetupAllowed": false
+        }
+      ]
+    },
+    {
+      "id": "6a105aef-bffc-420b-8d3e-8829cc84f0b1",
+      "alias": "Authentication Options",
+      "description": "Authentication options.",
+      "providerId": "basic-flow",
+      "topLevel": false,
+      "builtIn": true,
+      "authenticationExecutions": [
+        {
+          "authenticator": "basic-auth",
+          "authenticatorFlow": false,
+          "requirement": "REQUIRED",
+          "priority": 10,
+          "autheticatorFlow": false,
+          "userSetupAllowed": false
+        },
+        {
+          "authenticator": "basic-auth-otp",
+          "authenticatorFlow": false,
+          "requirement": "DISABLED",
+          "priority": 20,
+          "autheticatorFlow": false,
+          "userSetupAllowed": false
+        },
+        {
+          "authenticator": "auth-spnego",
+          "authenticatorFlow": false,
+          "requirement": "DISABLED",
+          "priority": 30,
+          "autheticatorFlow": false,
+          "userSetupAllowed": false
+        }
+      ]
+    },
+    {
+      "id": "9a582f8d-97b2-4717-a60d-ffd1ae1d0611",
+      "alias": "Browser - Conditional OTP",
+      "description": "Flow to determine if the OTP is required for the 
authentication",
+      "providerId": "basic-flow",
+      "topLevel": false,
+      "builtIn": true,
+      "authenticationExecutions": [
+        {
+          "authenticator": "conditional-user-configured",
+          "authenticatorFlow": false,
+          "requirement": "REQUIRED",
+          "priority": 10,
+          "autheticatorFlow": false,
+          "userSetupAllowed": false
+        },
+        {
+          "authenticator": "auth-otp-form",
+          "authenticatorFlow": false,
+          "requirement": "REQUIRED",
+          "priority": 20,
+          "autheticatorFlow": false,
+          "userSetupAllowed": false
+        }
+      ]
+    },
+    {
+      "id": "ae605cd7-cb24-46ef-a34d-706047726f7c",
+      "alias": "Direct Grant - Conditional OTP",
+      "description": "Flow to determine if the OTP is required for the 
authentication",
+      "providerId": "basic-flow",
+      "topLevel": false,
+      "builtIn": true,
+      "authenticationExecutions": [
+        {
+          "authenticator": "conditional-user-configured",
+          "authenticatorFlow": false,
+          "requirement": "REQUIRED",
+          "priority": 10,
+          "autheticatorFlow": false,
+          "userSetupAllowed": false
+        },
+        {
+          "authenticator": "direct-grant-validate-otp",
+          "authenticatorFlow": false,
+          "requirement": "REQUIRED",
+          "priority": 20,
+          "autheticatorFlow": false,
+          "userSetupAllowed": false
+        }
+      ]
+    },
+    {
+      "id": "8a33ed63-0893-44f6-a979-83a5419025d8",
+      "alias": "First broker login - Conditional OTP",
+      "description": "Flow to determine if the OTP is required for the 
authentication",
+      "providerId": "basic-flow",
+      "topLevel": false,
+      "builtIn": true,
+      "authenticationExecutions": [
+        {
+          "authenticator": "conditional-user-configured",
+          "authenticatorFlow": false,
+          "requirement": "REQUIRED",
+          "priority": 10,
+          "autheticatorFlow": false,
+          "userSetupAllowed": false
+        },
+        {
+          "authenticator": "auth-otp-form",
+          "authenticatorFlow": false,
+          "requirement": "REQUIRED",
+          "priority": 20,
+          "autheticatorFlow": false,
+          "userSetupAllowed": false
+        }
+      ]
+    },
+    {
+      "id": "7f25f07c-e1e0-4e65-b1cc-5ff44b844e69",
+      "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",
+          "authenticatorFlow": false,
+          "requirement": "REQUIRED",
+          "priority": 10,
+          "autheticatorFlow": false,
+          "userSetupAllowed": false
+        },
+        {
+          "authenticatorFlow": true,
+          "requirement": "REQUIRED",
+          "priority": 20,
+          "autheticatorFlow": true,
+          "flowAlias": "Account verification options",
+          "userSetupAllowed": false
+        }
+      ]
+    },
+    {
+      "id": "27879743-ec68-461e-b9c6-f47f8ffe7ddd",
+      "alias": "Reset - Conditional OTP",
+      "description": "Flow to determine if the OTP should be reset or not. Set 
to REQUIRED to force.",
+      "providerId": "basic-flow",
+      "topLevel": false,
+      "builtIn": true,
+      "authenticationExecutions": [
+        {
+          "authenticator": "conditional-user-configured",
+          "authenticatorFlow": false,
+          "requirement": "REQUIRED",
+          "priority": 10,
+          "autheticatorFlow": false,
+          "userSetupAllowed": false
+        },
+        {
+          "authenticator": "reset-otp",
+          "authenticatorFlow": false,
+          "requirement": "REQUIRED",
+          "priority": 20,
+          "autheticatorFlow": false,
+          "userSetupAllowed": false
+        }
+      ]
+    },
+    {
+      "id": "c0d5ecf3-64a8-45dd-ad88-5d5a7b4cc39b",
+      "alias": "User creation or linking",
+      "description": "Flow for the existing/non-existing user alternatives",
+      "providerId": "basic-flow",
+      "topLevel": false,
+      "builtIn": true,
+      "authenticationExecutions": [
+        {
+          "authenticatorConfig": "create unique user config",
+          "authenticator": "idp-create-user-if-unique",
+          "authenticatorFlow": false,
+          "requirement": "ALTERNATIVE",
+          "priority": 10,
+          "autheticatorFlow": false,
+          "userSetupAllowed": false
+        },
+        {
+          "authenticatorFlow": true,
+          "requirement": "ALTERNATIVE",
+          "priority": 20,
+          "autheticatorFlow": true,
+          "flowAlias": "Handle Existing Account",
+          "userSetupAllowed": false
+        }
+      ]
+    },
+    {
+      "id": "577a3471-5137-4a28-845d-03e32313bed7",
+      "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",
+          "authenticatorFlow": false,
+          "requirement": "REQUIRED",
+          "priority": 10,
+          "autheticatorFlow": false,
+          "userSetupAllowed": false
+        },
+        {
+          "authenticatorFlow": true,
+          "requirement": "CONDITIONAL",
+          "priority": 20,
+          "autheticatorFlow": true,
+          "flowAlias": "First broker login - Conditional OTP",
+          "userSetupAllowed": false
+        }
+      ]
+    },
+    {
+      "id": "da3c29d0-b25b-4831-81f3-7fc180e9c761",
+      "alias": "browser",
+      "description": "browser based authentication",
+      "providerId": "basic-flow",
+      "topLevel": true,
+      "builtIn": true,
+      "authenticationExecutions": [
+        {
+          "authenticator": "auth-cookie",
+          "authenticatorFlow": false,
+          "requirement": "ALTERNATIVE",
+          "priority": 10,
+          "autheticatorFlow": false,
+          "userSetupAllowed": false
+        },
+        {
+          "authenticator": "auth-spnego",
+          "authenticatorFlow": false,
+          "requirement": "DISABLED",
+          "priority": 20,
+          "autheticatorFlow": false,
+          "userSetupAllowed": false
+        },
+        {
+          "authenticator": "identity-provider-redirector",
+          "authenticatorFlow": false,
+          "requirement": "ALTERNATIVE",
+          "priority": 25,
+          "autheticatorFlow": false,
+          "userSetupAllowed": false
+        },
+        {
+          "authenticatorFlow": true,
+          "requirement": "ALTERNATIVE",
+          "priority": 30,
+          "autheticatorFlow": true,
+          "flowAlias": "forms",
+          "userSetupAllowed": false
+        }
+      ]
+    },
+    {
+      "id": "7206cc64-a893-4dd8-b9af-84038e480ad2",
+      "alias": "clients",
+      "description": "Base authentication for clients",
+      "providerId": "client-flow",
+      "topLevel": true,
+      "builtIn": true,
+      "authenticationExecutions": [
+        {
+          "authenticator": "client-secret",
+          "authenticatorFlow": false,
+          "requirement": "ALTERNATIVE",
+          "priority": 10,
+          "autheticatorFlow": false,
+          "userSetupAllowed": false
+        },
+        {
+          "authenticator": "client-jwt",
+          "authenticatorFlow": false,
+          "requirement": "ALTERNATIVE",
+          "priority": 20,
+          "autheticatorFlow": false,
+          "userSetupAllowed": false
+        },
+        {
+          "authenticator": "client-secret-jwt",
+          "authenticatorFlow": false,
+          "requirement": "ALTERNATIVE",
+          "priority": 30,
+          "autheticatorFlow": false,
+          "userSetupAllowed": false
+        },
+        {
+          "authenticator": "client-x509",
+          "authenticatorFlow": false,
+          "requirement": "ALTERNATIVE",
+          "priority": 40,
+          "autheticatorFlow": false,
+          "userSetupAllowed": false
+        }
+      ]
+    },
+    {
+      "id": "fed14bd1-066f-401d-823c-1253b6c835d2",
+      "alias": "direct grant",
+      "description": "OpenID Connect Resource Owner Grant",
+      "providerId": "basic-flow",
+      "topLevel": true,
+      "builtIn": true,
+      "authenticationExecutions": [
+        {
+          "authenticator": "direct-grant-validate-username",
+          "authenticatorFlow": false,
+          "requirement": "REQUIRED",
+          "priority": 10,
+          "autheticatorFlow": false,
+          "userSetupAllowed": false
+        },
+        {
+          "authenticator": "direct-grant-validate-password",
+          "authenticatorFlow": false,
+          "requirement": "REQUIRED",
+          "priority": 20,
+          "autheticatorFlow": false,
+          "userSetupAllowed": false
+        },
+        {
+          "authenticatorFlow": true,
+          "requirement": "CONDITIONAL",
+          "priority": 30,
+          "autheticatorFlow": true,
+          "flowAlias": "Direct Grant - Conditional OTP",
+          "userSetupAllowed": false
+        }
+      ]
+    },
+    {
+      "id": "0c2b466e-afe2-437b-a5a9-12350fbc9ec4",
+      "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",
+          "authenticatorFlow": false,
+          "requirement": "REQUIRED",
+          "priority": 10,
+          "autheticatorFlow": false,
+          "userSetupAllowed": false
+        }
+      ]
+    },
+    {
+      "id": "c2759deb-95f9-4bde-ba53-5ef3363eafbc",
+      "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",
+          "authenticatorFlow": false,
+          "requirement": "REQUIRED",
+          "priority": 10,
+          "autheticatorFlow": false,
+          "userSetupAllowed": false
+        },
+        {
+          "authenticatorFlow": true,
+          "requirement": "REQUIRED",
+          "priority": 20,
+          "autheticatorFlow": true,
+          "flowAlias": "User creation or linking",
+          "userSetupAllowed": false
+        }
+      ]
+    },
+    {
+      "id": "c0836105-73a6-4c73-9c99-b51cbf0e69d9",
+      "alias": "forms",
+      "description": "Username, password, otp and other auth forms.",
+      "providerId": "basic-flow",
+      "topLevel": false,
+      "builtIn": true,
+      "authenticationExecutions": [
+        {
+          "authenticator": "auth-username-password-form",
+          "authenticatorFlow": false,
+          "requirement": "REQUIRED",
+          "priority": 10,
+          "autheticatorFlow": false,
+          "userSetupAllowed": false
+        },
+        {
+          "authenticatorFlow": true,
+          "requirement": "CONDITIONAL",
+          "priority": 20,
+          "autheticatorFlow": true,
+          "flowAlias": "Browser - Conditional OTP",
+          "userSetupAllowed": false
+        }
+      ]
+    },
+    {
+      "id": "a6546a9f-bb82-432e-a6f4-42df08fd595d",
+      "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",
+          "authenticatorFlow": false,
+          "requirement": "REQUIRED",
+          "priority": 10,
+          "autheticatorFlow": false,
+          "userSetupAllowed": false
+        },
+        {
+          "authenticatorFlow": true,
+          "requirement": "REQUIRED",
+          "priority": 20,
+          "autheticatorFlow": true,
+          "flowAlias": "Authentication Options",
+          "userSetupAllowed": false
+        }
+      ]
+    },
+    {
+      "id": "4ce944ae-cd3e-4ca1-9941-86802378b6f6",
+      "alias": "registration",
+      "description": "registration flow",
+      "providerId": "basic-flow",
+      "topLevel": true,
+      "builtIn": true,
+      "authenticationExecutions": [
+        {
+          "authenticator": "registration-page-form",
+          "authenticatorFlow": true,
+          "requirement": "REQUIRED",
+          "priority": 10,
+          "autheticatorFlow": true,
+          "flowAlias": "registration form",
+          "userSetupAllowed": false
+        }
+      ]
+    },
+    {
+      "id": "d3177967-b70e-46c3-a69b-042e84443387",
+      "alias": "registration form",
+      "description": "registration form",
+      "providerId": "form-flow",
+      "topLevel": false,
+      "builtIn": true,
+      "authenticationExecutions": [
+        {
+          "authenticator": "registration-user-creation",
+          "authenticatorFlow": false,
+          "requirement": "REQUIRED",
+          "priority": 20,
+          "autheticatorFlow": false,
+          "userSetupAllowed": false
+        },
+        {
+          "authenticator": "registration-profile-action",
+          "authenticatorFlow": false,
+          "requirement": "REQUIRED",
+          "priority": 40,
+          "autheticatorFlow": false,
+          "userSetupAllowed": false
+        },
+        {
+          "authenticator": "registration-password-action",
+          "authenticatorFlow": false,
+          "requirement": "REQUIRED",
+          "priority": 50,
+          "autheticatorFlow": false,
+          "userSetupAllowed": false
+        },
+        {
+          "authenticator": "registration-recaptcha-action",
+          "authenticatorFlow": false,
+          "requirement": "DISABLED",
+          "priority": 60,
+          "autheticatorFlow": false,
+          "userSetupAllowed": false
+        }
+      ]
+    },
+    {
+      "id": "e2ca73ce-64cd-4108-8892-adfe28f48143",
+      "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",
+          "authenticatorFlow": false,
+          "requirement": "REQUIRED",
+          "priority": 10,
+          "autheticatorFlow": false,
+          "userSetupAllowed": false
+        },
+        {
+          "authenticator": "reset-credential-email",
+          "authenticatorFlow": false,
+          "requirement": "REQUIRED",
+          "priority": 20,
+          "autheticatorFlow": false,
+          "userSetupAllowed": false
+        },
+        {
+          "authenticator": "reset-password",
+          "authenticatorFlow": false,
+          "requirement": "REQUIRED",
+          "priority": 30,
+          "autheticatorFlow": false,
+          "userSetupAllowed": false
+        },
+        {
+          "authenticatorFlow": true,
+          "requirement": "CONDITIONAL",
+          "priority": 40,
+          "autheticatorFlow": true,
+          "flowAlias": "Reset - Conditional OTP",
+          "userSetupAllowed": false
+        }
+      ]
+    },
+    {
+      "id": "befd4bbf-74b4-45af-8454-aa08765e7344",
+      "alias": "saml ecp",
+      "description": "SAML ECP Profile Authentication Flow",
+      "providerId": "basic-flow",
+      "topLevel": true,
+      "builtIn": true,
+      "authenticationExecutions": [
+        {
+          "authenticator": "http-basic-authenticator",
+          "authenticatorFlow": false,
+          "requirement": "REQUIRED",
+          "priority": 10,
+          "autheticatorFlow": false,
+          "userSetupAllowed": false
+        }
+      ]
+    }
+  ],
+  "authenticatorConfig": [
+    {
+      "id": "c20973c7-5b3a-4eb0-87f6-e795c95f64a3",
+      "alias": "create unique user config",
+      "config": {
+        "require.password.update.after.registration": "false"
+      }
+    },
+    {
+      "id": "f0d504a1-df38-4ccf-9832-a40c10a9bf7a",
+      "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": {}
+    },
+    {
+      "alias": "delete_account",
+      "name": "Delete Account",
+      "providerId": "delete_account",
+      "enabled": false,
+      "defaultAction": false,
+      "priority": 60,
+      "config": {}
+    },
+    {
+      "alias": "webauthn-register",
+      "name": "Webauthn Register",
+      "providerId": "webauthn-register",
+      "enabled": true,
+      "defaultAction": false,
+      "priority": 70,
+      "config": {}
+    },
+    {
+      "alias": "webauthn-register-passwordless",
+      "name": "Webauthn Register Passwordless",
+      "providerId": "webauthn-register-passwordless",
+      "enabled": true,
+      "defaultAction": false,
+      "priority": 80,
+      "config": {}
+    },
+    {
+      "alias": "update_user_locale",
+      "name": "Update User Locale",
+      "providerId": "update_user_locale",
+      "enabled": true,
+      "defaultAction": false,
+      "priority": 1000,
+      "config": {}
+    }
+  ],
+  "browserFlow": "browser",
+  "registrationFlow": "registration",
+  "directGrantFlow": "direct grant",
+  "resetCredentialsFlow": "reset credentials",
+  "clientAuthenticationFlow": "clients",
+  "dockerAuthenticationFlow": "docker auth",
+  "attributes": {
+    "cibaBackchannelTokenDeliveryMode": "poll",
+    "cibaAuthRequestedUserHint": "login_hint",
+    "oauth2DevicePollingInterval": "5",
+    "clientOfflineSessionMaxLifespan": "0",
+    "clientSessionIdleTimeout": "0",
+    "actionTokenGeneratedByUserLifespan-execute-actions": "",
+    "actionTokenGeneratedByUserLifespan-verify-email": "",
+    "clientOfflineSessionIdleTimeout": "0",
+    "actionTokenGeneratedByUserLifespan-reset-credentials": "",
+    "cibaInterval": "5",
+    "cibaExpiresIn": "120",
+    "oauth2DeviceCodeLifespan": "600",
+    "actionTokenGeneratedByUserLifespan-idp-verify-account-via-email": "",
+    "parRequestUriLifespan": "60",
+    "clientSessionMaxLifespan": "0",
+    "frontendUrl": "",
+    "acr.loa.map": "[]"
+  },
+  "keycloakVersion": "19.0.1",
+  "userManagedAccessAllowed": false,
+  "clientProfiles": {
+    "profiles": []
+  },
+  "clientPolicies": {
+    "policies": []
+  }
+}
\ No newline at end of file

Reply via email to