diff --git a/serverless-workflow-examples/pom.xml b/serverless-workflow-examples/pom.xml
index 962cbd298a..37df8bda43 100644
--- a/serverless-workflow-examples/pom.xml
+++ b/serverless-workflow-examples/pom.xml
@@ -67,6 +67,7 @@
serverless-workflow-loanbroker-showcase
serverless-workflow-newsletter-subscription
serverless-workflow-oauth2-orchestration-quarkus
+ serverless-workflow-oauth2-token-exchange-quarkus
serverless-workflow-order-processing
serverless-workflow-parallel-execution
serverless-workflow-qas-service-showcase
diff --git a/serverless-workflow-examples/serverless-workflow-oauth2-token-exchange-quarkus/README.md b/serverless-workflow-examples/serverless-workflow-oauth2-token-exchange-quarkus/README.md
new file mode 100644
index 0000000000..2cb4fb4c3b
--- /dev/null
+++ b/serverless-workflow-examples/serverless-workflow-oauth2-token-exchange-quarkus/README.md
@@ -0,0 +1,12 @@
+# Serverless Workflow OAuth2 Token Exchange Example
+
+TODO:
+
+- Create the financial application for two users to show distinct statement datas
+- Create the workflow to ask for a loan: grab the statement info and verify if the user is able to receive the loan
+
+## References
+
+- [Running Keycloak in a container](https://www.keycloak.org/server/containers)
+- [Using Keycloak Authorization Services and Policy Enforcer to Protect JAX-RS Applications](https://github.com/quarkusio/quarkus-quickstarts/tree/main/security-keycloak-authorization-quickstart)
+- [Keycloak Docs - Audience Support](https://www.keycloak.org/docs/latest/server_admin/#_audience)
\ No newline at end of file
diff --git a/serverless-workflow-examples/serverless-workflow-oauth2-token-exchange-quarkus/acme-financial-service/.gitignore b/serverless-workflow-examples/serverless-workflow-oauth2-token-exchange-quarkus/acme-financial-service/.gitignore
new file mode 100644
index 0000000000..91a800a186
--- /dev/null
+++ b/serverless-workflow-examples/serverless-workflow-oauth2-token-exchange-quarkus/acme-financial-service/.gitignore
@@ -0,0 +1,45 @@
+#Maven
+target/
+pom.xml.tag
+pom.xml.releaseBackup
+pom.xml.versionsBackup
+release.properties
+.flattened-pom.xml
+
+# Eclipse
+.project
+.classpath
+.settings/
+bin/
+
+# IntelliJ
+.idea
+*.ipr
+*.iml
+*.iws
+
+# NetBeans
+nb-configuration.xml
+
+# Visual Studio Code
+.vscode
+.factorypath
+
+# OSX
+.DS_Store
+
+# Vim
+*.swp
+*.swo
+
+# patch
+*.orig
+*.rej
+
+# Local environment
+.env
+
+# Plugin directory
+/.quarkus/cli/plugins/
+# TLS Certificates
+.certs/
diff --git a/serverless-workflow-examples/serverless-workflow-oauth2-token-exchange-quarkus/acme-financial-service/README.md b/serverless-workflow-examples/serverless-workflow-oauth2-token-exchange-quarkus/acme-financial-service/README.md
new file mode 100644
index 0000000000..2213d1749c
--- /dev/null
+++ b/serverless-workflow-examples/serverless-workflow-oauth2-token-exchange-quarkus/acme-financial-service/README.md
@@ -0,0 +1,19 @@
+# Serverless Workflow OAuth2 Token Exchange Example
+
+```shell
+KEYCLOAK_ADDRESS=http://192.168.106.2:32769
+
+curl -X POST "${KEYCLOAK_ADDRESS}/realms/quarkus/protocol/openid-connect/token" \
+ -H "Content-Type: application/x-www-form-urlencoded" \
+ -d "grant_type=client_credentials" \
+ -d "client_id=quarkus-app" \
+ -d "client_secret=secret"
+```
+
+## References
+
+- [Using OpenID Connect (OIDC) and Keycloak to centralize authorization](https://quarkus.io/guides/security-keycloak-authorization)
+
+## Troubleshooting
+
+Problems with Colima on MacOs: https://github.com/testcontainers/testcontainers-java/issues/6450
\ No newline at end of file
diff --git a/serverless-workflow-examples/serverless-workflow-oauth2-token-exchange-quarkus/acme-financial-service/pom.xml b/serverless-workflow-examples/serverless-workflow-oauth2-token-exchange-quarkus/acme-financial-service/pom.xml
new file mode 100644
index 0000000000..e6a3cef97f
--- /dev/null
+++ b/serverless-workflow-examples/serverless-workflow-oauth2-token-exchange-quarkus/acme-financial-service/pom.xml
@@ -0,0 +1,164 @@
+
+
+ 4.0.0
+ acme-financial-service
+ 1.0.0-SNAPSHOT
+ Kogito Example :: Serverless Workflow Oauth2 Token Exchange Example :: ACME Financial Service
+
+
+ org.acme.workflow.oauth2
+ serverless-workflow-oauth2-token-exchange-quarkus
+ 1.0.0-SNAPSHOT
+
+
+
+ 3.13.0
+ 17
+ UTF-8
+ UTF-8
+ quarkus-bom
+ io.quarkus.platform
+ 3.13.2
+ true
+ 3.2.5
+
+ 3.22.0
+
+
+
+
+
+ ${quarkus.platform.group-id}
+ ${quarkus.platform.artifact-id}
+ ${quarkus.platform.version}
+ pom
+ import
+
+
+
+
+
+
+ org.slf4j
+ slf4j-api
+
+
+ io.quarkus
+ quarkus-arc
+
+
+ io.quarkus
+ quarkus-resteasy
+
+
+ io.quarkus
+ quarkus-resteasy-jackson
+
+
+ io.quarkus
+ quarkus-smallrye-openapi
+
+
+ io.quarkus
+ quarkus-oidc
+
+
+ io.quarkus
+ quarkus-keycloak-authorization
+
+
+
+ io.quarkus
+ quarkus-junit5
+ test
+
+
+ io.rest-assured
+ rest-assured
+ test
+
+
+ org.assertj
+ assertj-core
+ ${version.org.assertj}
+ test
+
+
+ io.quarkus
+ quarkus-test-keycloak-server
+ test
+
+
+
+
+
+
+ ${quarkus.platform.group-id}
+ quarkus-maven-plugin
+ ${quarkus.platform.version}
+ true
+
+
+
+ build
+ generate-code
+ generate-code-tests
+ native-image-agent
+
+
+
+
+
+ maven-compiler-plugin
+ ${compiler-plugin.version}
+
+ true
+
+
+
+ maven-surefire-plugin
+ ${surefire-plugin.version}
+
+
+ org.jboss.logmanager.LogManager
+ ${maven.home}
+
+
+
+
+ maven-failsafe-plugin
+ ${surefire-plugin.version}
+
+
+
+ integration-test
+ verify
+
+
+
+
+
+ ${project.build.directory}/${project.build.finalName}-runner
+ org.jboss.logmanager.LogManager
+ ${maven.home}
+
+
+
+
+
+
+
+
+ native
+
+
+ native
+
+
+
+ false
+ true
+
+
+
+
diff --git a/serverless-workflow-examples/serverless-workflow-oauth2-token-exchange-quarkus/acme-financial-service/src/main/java/org/acme/workflow/financial/service/AcmeFinancialApplication.java b/serverless-workflow-examples/serverless-workflow-oauth2-token-exchange-quarkus/acme-financial-service/src/main/java/org/acme/workflow/financial/service/AcmeFinancialApplication.java
new file mode 100644
index 0000000000..a40847ad69
--- /dev/null
+++ b/serverless-workflow-examples/serverless-workflow-oauth2-token-exchange-quarkus/acme-financial-service/src/main/java/org/acme/workflow/financial/service/AcmeFinancialApplication.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.acme.workflow.financial.service;
+
+import org.eclipse.microprofile.openapi.annotations.Components;
+import org.eclipse.microprofile.openapi.annotations.OpenAPIDefinition;
+import org.eclipse.microprofile.openapi.annotations.enums.SecuritySchemeType;
+import org.eclipse.microprofile.openapi.annotations.info.Info;
+import org.eclipse.microprofile.openapi.annotations.security.OAuthFlow;
+import org.eclipse.microprofile.openapi.annotations.security.OAuthFlows;
+import org.eclipse.microprofile.openapi.annotations.security.SecurityScheme;
+
+/**
+ * Defines OpenAPI configurations for the Quarkus application, for more information you must see
+ * Using OpenAPI and Swagger UI
+ */
+@OpenAPIDefinition(
+ info = @Info(
+ title = "Acme Financial Service API",
+ version = "1.0.0"),
+ components = @Components(
+ securitySchemes = {
+ @SecurityScheme(securitySchemeName = "acme-financial-oauth",
+ type = SecuritySchemeType.OAUTH2,
+ flows = @OAuthFlows(
+ clientCredentials = @OAuthFlow(
+ authorizationUrl = "http://localhost:9090/auth/realms/acme/protocol/openid-connect/auth",
+ tokenUrl = "http://localhost:9090/auth/realms/kogito/acme/openid-connect/token",
+ scopes = {})))
+ }))
+public class AcmeFinancialApplication extends jakarta.ws.rs.core.Application {
+}
diff --git a/serverless-workflow-examples/serverless-workflow-oauth2-token-exchange-quarkus/acme-financial-service/src/main/java/org/acme/workflow/financial/service/AcmeFinancialResource.java b/serverless-workflow-examples/serverless-workflow-oauth2-token-exchange-quarkus/acme-financial-service/src/main/java/org/acme/workflow/financial/service/AcmeFinancialResource.java
new file mode 100644
index 0000000000..1bdd141ad7
--- /dev/null
+++ b/serverless-workflow-examples/serverless-workflow-oauth2-token-exchange-quarkus/acme-financial-service/src/main/java/org/acme/workflow/financial/service/AcmeFinancialResource.java
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.acme.workflow.financial.service;
+
+import io.quarkus.security.identity.SecurityIdentity;
+import jakarta.annotation.security.RolesAllowed;
+import jakarta.inject.Inject;
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.core.MediaType;
+import org.eclipse.microprofile.openapi.annotations.Operation;
+import org.eclipse.microprofile.openapi.annotations.security.SecurityRequirement;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.List;
+
+@Path("financial-service")
+public class AcmeFinancialResource {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(AcmeFinancialResource.class);
+
+ @Inject
+ SecurityIdentity identity;
+
+ @Inject
+ StatementsDB statementsDB;
+
+ @GET
+ @Path("statement")
+ @Produces(MediaType.APPLICATION_JSON)
+ @Operation(operationId = "getStatement")
+ @RolesAllowed("customer")
+ @SecurityRequirement(name = "acme-financial-oauth")
+ public List getStatement() {
+ LOGGER.info("Getting statement for user {}", identity.getPrincipal());
+ return statementsDB.getStatementEntries(identity.getPrincipal().getName());
+ }
+}
diff --git a/serverless-workflow-examples/serverless-workflow-oauth2-token-exchange-quarkus/acme-financial-service/src/main/java/org/acme/workflow/financial/service/CustomersDB.java b/serverless-workflow-examples/serverless-workflow-oauth2-token-exchange-quarkus/acme-financial-service/src/main/java/org/acme/workflow/financial/service/CustomersDB.java
new file mode 100644
index 0000000000..0d6b717cbd
--- /dev/null
+++ b/serverless-workflow-examples/serverless-workflow-oauth2-token-exchange-quarkus/acme-financial-service/src/main/java/org/acme/workflow/financial/service/CustomersDB.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.acme.workflow.financial.service;
+
+import jakarta.annotation.PostConstruct;
+import jakarta.enterprise.context.ApplicationScoped;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+@ApplicationScoped
+public class CustomersDB {
+
+ static final String ALICE = "alice";
+ static final String BOB = "bob";
+
+ private final List userNames = new ArrayList<>();
+
+ @PostConstruct
+ void initialize(){
+ userNames.add(BOB);
+ userNames.add(ALICE);
+ }
+
+ public List getUserNames() {
+ return Collections.unmodifiableList(userNames);
+ }
+
+}
diff --git a/serverless-workflow-examples/serverless-workflow-oauth2-token-exchange-quarkus/acme-financial-service/src/main/java/org/acme/workflow/financial/service/StatementEntry.java b/serverless-workflow-examples/serverless-workflow-oauth2-token-exchange-quarkus/acme-financial-service/src/main/java/org/acme/workflow/financial/service/StatementEntry.java
new file mode 100644
index 0000000000..e0ea1311ac
--- /dev/null
+++ b/serverless-workflow-examples/serverless-workflow-oauth2-token-exchange-quarkus/acme-financial-service/src/main/java/org/acme/workflow/financial/service/StatementEntry.java
@@ -0,0 +1,73 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.acme.workflow.financial.service;
+
+import java.io.Serializable;
+import java.time.LocalDate;
+import java.util.Objects;
+
+public class StatementEntry implements Serializable {
+
+ private double amount;
+ private LocalDate date;
+
+ public StatementEntry() {}
+
+ public StatementEntry(double amount, String date) {
+ this.amount = amount;
+ this.date = LocalDate.parse(date);
+ }
+
+ public LocalDate getDate() {
+ return date;
+ }
+
+ public void setDate(LocalDate date) {
+ this.date = date;
+ }
+
+ public double getAmount() {
+ return amount;
+ }
+
+ public void setAmount(double amount) {
+ this.amount = amount;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ StatementEntry that = (StatementEntry) o;
+ return Double.compare(amount, that.amount) == 0 && Objects.equals(date, that.date);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(amount, date);
+ }
+
+ @Override
+ public String toString() {
+ return "StatementEntry{" +
+ "amount=" + amount +
+ ", date=" + date +
+ '}';
+ }
+}
diff --git a/serverless-workflow-examples/serverless-workflow-oauth2-token-exchange-quarkus/acme-financial-service/src/main/java/org/acme/workflow/financial/service/StatementsDB.java b/serverless-workflow-examples/serverless-workflow-oauth2-token-exchange-quarkus/acme-financial-service/src/main/java/org/acme/workflow/financial/service/StatementsDB.java
new file mode 100644
index 0000000000..7ab549f10a
--- /dev/null
+++ b/serverless-workflow-examples/serverless-workflow-oauth2-token-exchange-quarkus/acme-financial-service/src/main/java/org/acme/workflow/financial/service/StatementsDB.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.acme.workflow.financial.service;
+
+import jakarta.annotation.PostConstruct;
+import jakarta.enterprise.context.ApplicationScoped;
+import jakarta.inject.Inject;
+
+import java.util.*;
+
+@ApplicationScoped
+public class StatementsDB {
+
+ private static final Map> STATEMENT_ENTRY = new HashMap<>();
+
+ @Inject
+ CustomersDB customersDB;
+
+ @PostConstruct
+ void initialize() {
+
+ customersDB.getUserNames().forEach(c -> {
+ List statementEntries = new ArrayList<>();
+
+ if (Objects.equals(c, CustomersDB.ALICE)) {
+ statementEntries.add(new StatementEntry(50.00, "2024-03-17"));
+ statementEntries.add(new StatementEntry(11.00, "2024-03-18"));
+ statementEntries.add(new StatementEntry(12.00, "2024-03-19"));
+ statementEntries.add(new StatementEntry(13.00, "2024-03-20"));
+ statementEntries.add(new StatementEntry(14.00, "2024-03-21"));
+ } else {
+ statementEntries.add(new StatementEntry(1.00, "2024-03-17"));
+ }
+
+
+ STATEMENT_ENTRY.put(c, statementEntries);
+ });
+ }
+
+ public List getStatementEntries(String customerUserName) {
+ return Collections.unmodifiableList(STATEMENT_ENTRY.get(customerUserName));
+ }
+}
diff --git a/serverless-workflow-examples/serverless-workflow-oauth2-token-exchange-quarkus/acme-financial-service/src/main/resources/application.properties b/serverless-workflow-examples/serverless-workflow-oauth2-token-exchange-quarkus/acme-financial-service/src/main/resources/application.properties
new file mode 100644
index 0000000000..20e3be902f
--- /dev/null
+++ b/serverless-workflow-examples/serverless-workflow-oauth2-token-exchange-quarkus/acme-financial-service/src/main/resources/application.properties
@@ -0,0 +1,35 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+quarkus.http.port=8181
+
+# OIDC configuration for this service
+quarkus.oidc.application-type=service
+# In production, you should use Kubernetes Secrets instead
+quarkus.oidc.client-id=financial-service
+quarkus.oidc.credentials.secret=secret
+quarkus.oidc.tls.verification=none
+quarkus.oidc.token.issuer=any
+# External Keycloak docker container running via ./scripts/boot-keycloak.sh
+quarkus.oidc.auth-server-url=http://localhost:9090/realms/acme
+
+quarkus.keycloak.policy-enforcer.lazy-load-paths=false
+
+# Keycloak devservices disabled since we are using an external container
+quarkus.keycloak.devservices.enabled=false
diff --git a/serverless-workflow-examples/serverless-workflow-oauth2-token-exchange-quarkus/keycloak/realm-export.json b/serverless-workflow-examples/serverless-workflow-oauth2-token-exchange-quarkus/keycloak/realm-export.json
new file mode 100644
index 0000000000..aa0c9a4caf
--- /dev/null
+++ b/serverless-workflow-examples/serverless-workflow-oauth2-token-exchange-quarkus/keycloak/realm-export.json
@@ -0,0 +1,2783 @@
+{
+ "id": "5f7076a7-b154-4915-9ea2-7a1d173a2197",
+ "realm": "acme",
+ "notBefore": 0,
+ "defaultSignatureAlgorithm": "RS256",
+ "revokeRefreshToken": false,
+ "refreshTokenMaxReuse": 0,
+ "accessTokenLifespan": 300,
+ "accessTokenLifespanForImplicitFlow": 900,
+ "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,
+ "maxTemporaryLockouts": 0,
+ "maxFailureWaitSeconds": 900,
+ "minimumQuickLoginWaitSeconds": 60,
+ "waitIncrementSeconds": 60,
+ "quickLoginCheckMilliSeconds": 1000,
+ "maxDeltaTimeSeconds": 43200,
+ "failureFactor": 30,
+ "roles": {
+ "realm": [
+ {
+ "id": "f277d4aa-ee9f-4d53-adf0-464c87349a3a",
+ "name": "customer",
+ "description": "",
+ "composite": false,
+ "clientRole": false,
+ "containerId": "5f7076a7-b154-4915-9ea2-7a1d173a2197",
+ "attributes": {}
+ },
+ {
+ "id": "942a2cbb-b185-498d-9017-d5f91ddd396e",
+ "name": "offline_access",
+ "description": "${role_offline-access}",
+ "composite": false,
+ "clientRole": false,
+ "containerId": "5f7076a7-b154-4915-9ea2-7a1d173a2197",
+ "attributes": {}
+ },
+ {
+ "id": "2475b504-7b41-48b9-a826-cfa1e3e46b21",
+ "name": "uma_authorization",
+ "description": "${role_uma_authorization}",
+ "composite": false,
+ "clientRole": false,
+ "containerId": "5f7076a7-b154-4915-9ea2-7a1d173a2197",
+ "attributes": {}
+ },
+ {
+ "id": "f024f7c3-71a2-470f-b10c-3c8ab8ebb95d",
+ "name": "default-roles-acme",
+ "description": "${role_default-roles}",
+ "composite": true,
+ "composites": {
+ "realm": [
+ "offline_access",
+ "uma_authorization"
+ ],
+ "client": {
+ "account": [
+ "view-profile",
+ "manage-account"
+ ]
+ }
+ },
+ "clientRole": false,
+ "containerId": "5f7076a7-b154-4915-9ea2-7a1d173a2197",
+ "attributes": {}
+ }
+ ],
+ "client": {
+ "realm-management": [
+ {
+ "id": "fb674c3c-6c61-4054-adf8-9463b27d3b92",
+ "name": "view-identity-providers",
+ "description": "${role_view-identity-providers}",
+ "composite": false,
+ "clientRole": true,
+ "containerId": "47961cdc-e169-4794-8c2d-c54ea4988fe5",
+ "attributes": {}
+ },
+ {
+ "id": "f416d8e8-a2f4-47b1-a000-46c3be8809b7",
+ "name": "view-authorization",
+ "description": "${role_view-authorization}",
+ "composite": false,
+ "clientRole": true,
+ "containerId": "47961cdc-e169-4794-8c2d-c54ea4988fe5",
+ "attributes": {}
+ },
+ {
+ "id": "b40bc591-c2e2-46ce-9c81-36533c358a2b",
+ "name": "query-clients",
+ "description": "${role_query-clients}",
+ "composite": false,
+ "clientRole": true,
+ "containerId": "47961cdc-e169-4794-8c2d-c54ea4988fe5",
+ "attributes": {}
+ },
+ {
+ "id": "27a678b7-2c0d-4d01-9d6f-bf75d970a161",
+ "name": "query-realms",
+ "description": "${role_query-realms}",
+ "composite": false,
+ "clientRole": true,
+ "containerId": "47961cdc-e169-4794-8c2d-c54ea4988fe5",
+ "attributes": {}
+ },
+ {
+ "id": "e2d55a80-f885-42e2-9172-531330766ad8",
+ "name": "manage-users",
+ "description": "${role_manage-users}",
+ "composite": false,
+ "clientRole": true,
+ "containerId": "47961cdc-e169-4794-8c2d-c54ea4988fe5",
+ "attributes": {}
+ },
+ {
+ "id": "0730f9c7-c662-4b36-8f37-6023dcae5e65",
+ "name": "query-users",
+ "description": "${role_query-users}",
+ "composite": false,
+ "clientRole": true,
+ "containerId": "47961cdc-e169-4794-8c2d-c54ea4988fe5",
+ "attributes": {}
+ },
+ {
+ "id": "ac69c01e-63cc-469b-b486-32f39acb8b30",
+ "name": "create-client",
+ "description": "${role_create-client}",
+ "composite": false,
+ "clientRole": true,
+ "containerId": "47961cdc-e169-4794-8c2d-c54ea4988fe5",
+ "attributes": {}
+ },
+ {
+ "id": "cf56b2e1-7817-4c4c-bc4e-adcad70b1d29",
+ "name": "view-users",
+ "description": "${role_view-users}",
+ "composite": true,
+ "composites": {
+ "client": {
+ "realm-management": [
+ "query-users",
+ "query-groups"
+ ]
+ }
+ },
+ "clientRole": true,
+ "containerId": "47961cdc-e169-4794-8c2d-c54ea4988fe5",
+ "attributes": {}
+ },
+ {
+ "id": "14ab569c-aecd-4121-bd90-4d8d3c5adde5",
+ "name": "manage-identity-providers",
+ "description": "${role_manage-identity-providers}",
+ "composite": false,
+ "clientRole": true,
+ "containerId": "47961cdc-e169-4794-8c2d-c54ea4988fe5",
+ "attributes": {}
+ },
+ {
+ "id": "dbc4fab0-6df2-4250-adb5-2222dc9a467b",
+ "name": "query-groups",
+ "description": "${role_query-groups}",
+ "composite": false,
+ "clientRole": true,
+ "containerId": "47961cdc-e169-4794-8c2d-c54ea4988fe5",
+ "attributes": {}
+ },
+ {
+ "id": "cc0c738c-b984-4108-8a09-d1366506f3fa",
+ "name": "realm-admin",
+ "description": "${role_realm-admin}",
+ "composite": true,
+ "composites": {
+ "client": {
+ "realm-management": [
+ "view-identity-providers",
+ "view-authorization",
+ "query-clients",
+ "query-realms",
+ "query-users",
+ "manage-users",
+ "create-client",
+ "view-users",
+ "manage-identity-providers",
+ "query-groups",
+ "manage-events",
+ "view-events",
+ "impersonation",
+ "view-clients",
+ "view-realm",
+ "manage-authorization",
+ "manage-realm",
+ "manage-clients"
+ ]
+ }
+ },
+ "clientRole": true,
+ "containerId": "47961cdc-e169-4794-8c2d-c54ea4988fe5",
+ "attributes": {}
+ },
+ {
+ "id": "81be853a-4a76-4a12-8661-3dd8b82907ae",
+ "name": "manage-events",
+ "description": "${role_manage-events}",
+ "composite": false,
+ "clientRole": true,
+ "containerId": "47961cdc-e169-4794-8c2d-c54ea4988fe5",
+ "attributes": {}
+ },
+ {
+ "id": "757303c9-034a-4a85-b505-89dd2247a7e7",
+ "name": "view-events",
+ "description": "${role_view-events}",
+ "composite": false,
+ "clientRole": true,
+ "containerId": "47961cdc-e169-4794-8c2d-c54ea4988fe5",
+ "attributes": {}
+ },
+ {
+ "id": "cdb4a902-732b-4906-b1c9-040db4efffff",
+ "name": "uma_protection",
+ "composite": false,
+ "clientRole": true,
+ "containerId": "47961cdc-e169-4794-8c2d-c54ea4988fe5",
+ "attributes": {}
+ },
+ {
+ "id": "a139b498-1421-4987-b49e-24ff66145cce",
+ "name": "impersonation",
+ "description": "${role_impersonation}",
+ "composite": false,
+ "clientRole": true,
+ "containerId": "47961cdc-e169-4794-8c2d-c54ea4988fe5",
+ "attributes": {}
+ },
+ {
+ "id": "a7a14669-5825-4ce2-90a7-80b9193b70c3",
+ "name": "view-clients",
+ "description": "${role_view-clients}",
+ "composite": true,
+ "composites": {
+ "client": {
+ "realm-management": [
+ "query-clients"
+ ]
+ }
+ },
+ "clientRole": true,
+ "containerId": "47961cdc-e169-4794-8c2d-c54ea4988fe5",
+ "attributes": {}
+ },
+ {
+ "id": "c9764434-5964-4d48-9892-02ca3ac70cf0",
+ "name": "view-realm",
+ "description": "${role_view-realm}",
+ "composite": false,
+ "clientRole": true,
+ "containerId": "47961cdc-e169-4794-8c2d-c54ea4988fe5",
+ "attributes": {}
+ },
+ {
+ "id": "d8402b8f-6dc8-4591-a0f7-773e58d73164",
+ "name": "manage-authorization",
+ "description": "${role_manage-authorization}",
+ "composite": false,
+ "clientRole": true,
+ "containerId": "47961cdc-e169-4794-8c2d-c54ea4988fe5",
+ "attributes": {}
+ },
+ {
+ "id": "6349ddb7-af68-4fec-929f-5ce01e264b33",
+ "name": "manage-realm",
+ "description": "${role_manage-realm}",
+ "composite": false,
+ "clientRole": true,
+ "containerId": "47961cdc-e169-4794-8c2d-c54ea4988fe5",
+ "attributes": {}
+ },
+ {
+ "id": "ed9acf9c-9214-4479-a121-4949a39a7ac9",
+ "name": "manage-clients",
+ "description": "${role_manage-clients}",
+ "composite": false,
+ "clientRole": true,
+ "containerId": "47961cdc-e169-4794-8c2d-c54ea4988fe5",
+ "attributes": {}
+ }
+ ],
+ "workflow-app": [],
+ "security-admin-console": [],
+ "admin-cli": [],
+ "financial-service": [],
+ "account-console": [],
+ "broker": [
+ {
+ "id": "d720ea77-4cf9-4b08-ae09-3a985e08d7ff",
+ "name": "read-token",
+ "description": "${role_read-token}",
+ "composite": false,
+ "clientRole": true,
+ "containerId": "371bb08f-ca30-44c9-ad71-b8f536119f6d",
+ "attributes": {}
+ }
+ ],
+ "account": [
+ {
+ "id": "27586e74-c6e0-4729-a793-aca81b47bb57",
+ "name": "manage-account-links",
+ "description": "${role_manage-account-links}",
+ "composite": false,
+ "clientRole": true,
+ "containerId": "515d496a-7eb1-4804-972b-24e9676bf260",
+ "attributes": {}
+ },
+ {
+ "id": "723c4e97-c68c-4798-8365-e06ccb7cf7d5",
+ "name": "delete-account",
+ "description": "${role_delete-account}",
+ "composite": false,
+ "clientRole": true,
+ "containerId": "515d496a-7eb1-4804-972b-24e9676bf260",
+ "attributes": {}
+ },
+ {
+ "id": "0398539d-e686-42d6-98ad-dab4d01fcabf",
+ "name": "view-applications",
+ "description": "${role_view-applications}",
+ "composite": false,
+ "clientRole": true,
+ "containerId": "515d496a-7eb1-4804-972b-24e9676bf260",
+ "attributes": {}
+ },
+ {
+ "id": "faf7f450-3843-4100-bdd7-85ad8b0ab77f",
+ "name": "manage-consent",
+ "description": "${role_manage-consent}",
+ "composite": true,
+ "composites": {
+ "client": {
+ "account": [
+ "view-consent"
+ ]
+ }
+ },
+ "clientRole": true,
+ "containerId": "515d496a-7eb1-4804-972b-24e9676bf260",
+ "attributes": {}
+ },
+ {
+ "id": "da63754b-4899-4af1-8025-76756f1b01de",
+ "name": "view-consent",
+ "description": "${role_view-consent}",
+ "composite": false,
+ "clientRole": true,
+ "containerId": "515d496a-7eb1-4804-972b-24e9676bf260",
+ "attributes": {}
+ },
+ {
+ "id": "6c6c8866-90e2-4b42-8597-60cf8d6e178a",
+ "name": "view-groups",
+ "description": "${role_view-groups}",
+ "composite": false,
+ "clientRole": true,
+ "containerId": "515d496a-7eb1-4804-972b-24e9676bf260",
+ "attributes": {}
+ },
+ {
+ "id": "4ebe7af9-775c-4b1d-9137-3f20b5f9a4e9",
+ "name": "view-profile",
+ "description": "${role_view-profile}",
+ "composite": false,
+ "clientRole": true,
+ "containerId": "515d496a-7eb1-4804-972b-24e9676bf260",
+ "attributes": {}
+ },
+ {
+ "id": "7d37ca78-5259-4c98-843a-eac2da7eb2c2",
+ "name": "manage-account",
+ "description": "${role_manage-account}",
+ "composite": true,
+ "composites": {
+ "client": {
+ "account": [
+ "manage-account-links"
+ ]
+ }
+ },
+ "clientRole": true,
+ "containerId": "515d496a-7eb1-4804-972b-24e9676bf260",
+ "attributes": {}
+ }
+ ]
+ }
+ },
+ "groups": [],
+ "defaultRole": {
+ "id": "f024f7c3-71a2-470f-b10c-3c8ab8ebb95d",
+ "name": "default-roles-acme",
+ "description": "${role_default-roles}",
+ "composite": true,
+ "clientRole": false,
+ "containerId": "5f7076a7-b154-4915-9ea2-7a1d173a2197"
+ },
+ "requiredCredentials": [
+ "password"
+ ],
+ "otpPolicyType": "totp",
+ "otpPolicyAlgorithm": "HmacSHA1",
+ "otpPolicyInitialCounter": 0,
+ "otpPolicyDigits": 6,
+ "otpPolicyLookAheadWindow": 1,
+ "otpPolicyPeriod": 30,
+ "otpPolicyCodeReusable": false,
+ "otpSupportedApplications": [
+ "totpAppFreeOTPName",
+ "totpAppGoogleName",
+ "totpAppMicrosoftAuthenticatorName"
+ ],
+ "localizationTexts": {},
+ "webAuthnPolicyRpEntityName": "keycloak",
+ "webAuthnPolicySignatureAlgorithms": [
+ "ES256"
+ ],
+ "webAuthnPolicyRpId": "",
+ "webAuthnPolicyAttestationConveyancePreference": "not specified",
+ "webAuthnPolicyAuthenticatorAttachment": "not specified",
+ "webAuthnPolicyRequireResidentKey": "not specified",
+ "webAuthnPolicyUserVerificationRequirement": "not specified",
+ "webAuthnPolicyCreateTimeout": 0,
+ "webAuthnPolicyAvoidSameAuthenticatorRegister": false,
+ "webAuthnPolicyAcceptableAaguids": [],
+ "webAuthnPolicyExtraOrigins": [],
+ "webAuthnPolicyPasswordlessRpEntityName": "keycloak",
+ "webAuthnPolicyPasswordlessSignatureAlgorithms": [
+ "ES256"
+ ],
+ "webAuthnPolicyPasswordlessRpId": "",
+ "webAuthnPolicyPasswordlessAttestationConveyancePreference": "not specified",
+ "webAuthnPolicyPasswordlessAuthenticatorAttachment": "not specified",
+ "webAuthnPolicyPasswordlessRequireResidentKey": "not specified",
+ "webAuthnPolicyPasswordlessUserVerificationRequirement": "not specified",
+ "webAuthnPolicyPasswordlessCreateTimeout": 0,
+ "webAuthnPolicyPasswordlessAvoidSameAuthenticatorRegister": false,
+ "webAuthnPolicyPasswordlessAcceptableAaguids": [],
+ "webAuthnPolicyPasswordlessExtraOrigins": [],
+ "users": [
+ {
+ "username": "alice",
+ "enabled": true,
+ "emailVerified": true,
+ "credentials": [
+ {
+ "type": "password",
+ "value": "alice"
+ }
+ ],
+ "realmRoles": [
+ "default-roles-acme",
+ "customer"
+ ]
+ },
+ {
+ "username": "bob",
+ "enabled": true,
+ "emailVerified": true,
+ "credentials": [
+ {
+ "type": "password",
+ "value": "bob"
+ }
+ ],
+ "realmRoles": [
+ "default-roles-acme",
+ "customer"
+ ]
+ },
+ {
+ "id": "a300a11f-4c0d-4d35-a490-aca2978150f8",
+ "username": "service-account-financial-service",
+ "emailVerified": false,
+ "createdTimestamp": 1723808925850,
+ "enabled": true,
+ "totp": false,
+ "serviceAccountClientId": "financial-service",
+ "disableableCredentialTypes": [],
+ "requiredActions": [],
+ "realmRoles": [
+ "default-roles-acme"
+ ],
+ "notBefore": 0,
+ "groups": []
+ },
+ {
+ "id": "8710de5a-bb8b-40c0-ba68-e833ff40bda8",
+ "username": "service-account-realm-management",
+ "emailVerified": false,
+ "createdTimestamp": 1723757213624,
+ "enabled": true,
+ "totp": false,
+ "serviceAccountClientId": "realm-management",
+ "disableableCredentialTypes": [],
+ "requiredActions": [],
+ "realmRoles": [
+ "default-roles-acme"
+ ],
+ "clientRoles": {
+ "realm-management": [
+ "uma_protection"
+ ]
+ },
+ "notBefore": 0,
+ "groups": []
+ },
+ {
+ "id": "19e730ea-3981-4790-bd0d-adb6c84d9b05",
+ "username": "service-account-workflow-app",
+ "emailVerified": false,
+ "createdTimestamp": 1723233154559,
+ "enabled": true,
+ "totp": false,
+ "serviceAccountClientId": "workflow-app",
+ "disableableCredentialTypes": [],
+ "requiredActions": [],
+ "realmRoles": [
+ "default-roles-acme"
+ ],
+ "notBefore": 0,
+ "groups": []
+ }
+ ],
+ "scopeMappings": [
+ {
+ "clientScope": "offline_access",
+ "roles": [
+ "offline_access"
+ ]
+ }
+ ],
+ "clientScopeMappings": {
+ "account": [
+ {
+ "client": "account-console",
+ "roles": [
+ "manage-account",
+ "view-groups"
+ ]
+ }
+ ]
+ },
+ "clients": [
+ {
+ "id": "515d496a-7eb1-4804-972b-24e9676bf260",
+ "clientId": "account",
+ "name": "${client_account}",
+ "rootUrl": "${authBaseUrl}",
+ "baseUrl": "/realms/acme/account/",
+ "surrogateAuthRequired": false,
+ "enabled": true,
+ "alwaysDisplayInConsole": false,
+ "clientAuthenticatorType": "client-secret",
+ "redirectUris": [
+ "/realms/acme/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",
+ "roles",
+ "profile",
+ "basic",
+ "email"
+ ],
+ "optionalClientScopes": [
+ "address",
+ "phone",
+ "offline_access",
+ "microprofile-jwt"
+ ]
+ },
+ {
+ "id": "b7d21691-d143-4a32-bb2e-1973a9cea983",
+ "clientId": "account-console",
+ "name": "${client_account-console}",
+ "rootUrl": "${authBaseUrl}",
+ "baseUrl": "/realms/acme/account/",
+ "surrogateAuthRequired": false,
+ "enabled": true,
+ "alwaysDisplayInConsole": false,
+ "clientAuthenticatorType": "client-secret",
+ "redirectUris": [
+ "/realms/acme/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": "7d13f6df-9d0e-4c8a-b879-96622ab0402d",
+ "name": "audience resolve",
+ "protocol": "openid-connect",
+ "protocolMapper": "oidc-audience-resolve-mapper",
+ "consentRequired": false,
+ "config": {}
+ }
+ ],
+ "defaultClientScopes": [
+ "web-origins",
+ "acr",
+ "roles",
+ "profile",
+ "basic",
+ "email"
+ ],
+ "optionalClientScopes": [
+ "address",
+ "phone",
+ "offline_access",
+ "microprofile-jwt"
+ ]
+ },
+ {
+ "id": "09efb772-505a-40b0-bf62-c84fd2b5ce17",
+ "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": {
+ "post.logout.redirect.uris": "+"
+ },
+ "authenticationFlowBindingOverrides": {},
+ "fullScopeAllowed": false,
+ "nodeReRegistrationTimeout": 0,
+ "defaultClientScopes": [
+ "web-origins",
+ "acr",
+ "roles",
+ "profile",
+ "basic",
+ "email"
+ ],
+ "optionalClientScopes": [
+ "address",
+ "phone",
+ "offline_access",
+ "microprofile-jwt"
+ ]
+ },
+ {
+ "id": "371bb08f-ca30-44c9-ad71-b8f536119f6d",
+ "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": {
+ "post.logout.redirect.uris": "+"
+ },
+ "authenticationFlowBindingOverrides": {},
+ "fullScopeAllowed": false,
+ "nodeReRegistrationTimeout": 0,
+ "defaultClientScopes": [
+ "web-origins",
+ "acr",
+ "roles",
+ "profile",
+ "basic",
+ "email"
+ ],
+ "optionalClientScopes": [
+ "address",
+ "phone",
+ "offline_access",
+ "microprofile-jwt"
+ ]
+ },
+ {
+ "id": "9e7642bf-bc64-4def-bbbe-e2f6afda6bb3",
+ "clientId": "financial-service",
+ "name": "",
+ "description": "",
+ "rootUrl": "",
+ "adminUrl": "",
+ "baseUrl": "",
+ "surrogateAuthRequired": false,
+ "enabled": true,
+ "alwaysDisplayInConsole": false,
+ "clientAuthenticatorType": "client-secret",
+ "secret": "secret",
+ "redirectUris": [
+ "/*"
+ ],
+ "webOrigins": [
+ "/*"
+ ],
+ "notBefore": 0,
+ "bearerOnly": false,
+ "consentRequired": false,
+ "standardFlowEnabled": false,
+ "implicitFlowEnabled": true,
+ "directAccessGrantsEnabled": true,
+ "serviceAccountsEnabled": true,
+ "publicClient": false,
+ "frontchannelLogout": true,
+ "protocol": "openid-connect",
+ "attributes": {
+ "oidc.ciba.grant.enabled": "false",
+ "client.secret.creation.time": "1723808925",
+ "backchannel.logout.session.required": "true",
+ "oauth2.device.authorization.grant.enabled": "false",
+ "backchannel.logout.revoke.offline.tokens": "false"
+ },
+ "authenticationFlowBindingOverrides": {},
+ "fullScopeAllowed": true,
+ "nodeReRegistrationTimeout": -1,
+ "protocolMappers": [
+ {
+ "id": "534a38c9-2e56-44d8-9c19-edad765c0a7f",
+ "name": "Client ID",
+ "protocol": "openid-connect",
+ "protocolMapper": "oidc-usersessionmodel-note-mapper",
+ "consentRequired": false,
+ "config": {
+ "user.session.note": "client_id",
+ "id.token.claim": "true",
+ "introspection.token.claim": "true",
+ "access.token.claim": "true",
+ "claim.name": "client_id",
+ "jsonType.label": "String"
+ }
+ },
+ {
+ "id": "47f9deb3-ded8-48f7-bcf3-1ee30e0cbba4",
+ "name": "Client Host",
+ "protocol": "openid-connect",
+ "protocolMapper": "oidc-usersessionmodel-note-mapper",
+ "consentRequired": false,
+ "config": {
+ "user.session.note": "clientHost",
+ "id.token.claim": "true",
+ "introspection.token.claim": "true",
+ "access.token.claim": "true",
+ "claim.name": "clientHost",
+ "jsonType.label": "String"
+ }
+ },
+ {
+ "id": "6bdaab1d-30d3-45d9-9be5-614a43d7de03",
+ "name": "audience resolve",
+ "protocol": "openid-connect",
+ "protocolMapper": "oidc-audience-resolve-mapper",
+ "consentRequired": false,
+ "config": {
+ "introspection.token.claim": "true",
+ "access.token.claim": "true"
+ }
+ },
+ {
+ "id": "92e05815-0bc8-4c1c-9eca-a517446d510a",
+ "name": "Client IP Address",
+ "protocol": "openid-connect",
+ "protocolMapper": "oidc-usersessionmodel-note-mapper",
+ "consentRequired": false,
+ "config": {
+ "user.session.note": "clientAddress",
+ "id.token.claim": "true",
+ "introspection.token.claim": "true",
+ "access.token.claim": "true",
+ "claim.name": "clientAddress",
+ "jsonType.label": "String"
+ }
+ }
+ ],
+ "defaultClientScopes": [
+ "web-origins",
+ "acr",
+ "workflow-app",
+ "roles",
+ "profile",
+ "basic",
+ "email"
+ ],
+ "optionalClientScopes": [
+ "address",
+ "phone",
+ "offline_access",
+ "microprofile-jwt"
+ ]
+ },
+ {
+ "id": "47961cdc-e169-4794-8c2d-c54ea4988fe5",
+ "clientId": "realm-management",
+ "name": "${client_realm-management}",
+ "surrogateAuthRequired": false,
+ "enabled": true,
+ "alwaysDisplayInConsole": false,
+ "clientAuthenticatorType": "client-secret",
+ "secret": "**********",
+ "redirectUris": [],
+ "webOrigins": [],
+ "notBefore": 0,
+ "bearerOnly": false,
+ "consentRequired": false,
+ "standardFlowEnabled": true,
+ "implicitFlowEnabled": false,
+ "directAccessGrantsEnabled": false,
+ "serviceAccountsEnabled": true,
+ "authorizationServicesEnabled": true,
+ "publicClient": false,
+ "frontchannelLogout": false,
+ "protocol": "openid-connect",
+ "attributes": {
+ "client.secret.creation.time": "1723757677",
+ "post.logout.redirect.uris": "+"
+ },
+ "authenticationFlowBindingOverrides": {},
+ "fullScopeAllowed": false,
+ "nodeReRegistrationTimeout": 0,
+ "protocolMappers": [
+ {
+ "id": "d1a7c94d-4481-4e2b-bda0-dfd8b77414b9",
+ "name": "Client Host",
+ "protocol": "openid-connect",
+ "protocolMapper": "oidc-usersessionmodel-note-mapper",
+ "consentRequired": false,
+ "config": {
+ "user.session.note": "clientHost",
+ "introspection.token.claim": "true",
+ "userinfo.token.claim": "true",
+ "id.token.claim": "true",
+ "access.token.claim": "true",
+ "claim.name": "clientHost",
+ "jsonType.label": "String"
+ }
+ },
+ {
+ "id": "1f66a41a-8883-4767-bd42-6613022af099",
+ "name": "Client ID",
+ "protocol": "openid-connect",
+ "protocolMapper": "oidc-usersessionmodel-note-mapper",
+ "consentRequired": false,
+ "config": {
+ "user.session.note": "client_id",
+ "introspection.token.claim": "true",
+ "userinfo.token.claim": "true",
+ "id.token.claim": "true",
+ "access.token.claim": "true",
+ "claim.name": "client_id",
+ "jsonType.label": "String"
+ }
+ },
+ {
+ "id": "ab2674dd-b80f-4887-b991-b9f84705282a",
+ "name": "Client IP Address",
+ "protocol": "openid-connect",
+ "protocolMapper": "oidc-usersessionmodel-note-mapper",
+ "consentRequired": false,
+ "config": {
+ "user.session.note": "clientAddress",
+ "introspection.token.claim": "true",
+ "userinfo.token.claim": "true",
+ "id.token.claim": "true",
+ "access.token.claim": "true",
+ "claim.name": "clientAddress",
+ "jsonType.label": "String"
+ }
+ }
+ ],
+ "defaultClientScopes": [
+ "web-origins",
+ "acr",
+ "roles",
+ "profile",
+ "basic",
+ "email"
+ ],
+ "optionalClientScopes": [
+ "address",
+ "phone",
+ "offline_access",
+ "microprofile-jwt"
+ ],
+ "authorizationSettings": {
+ "allowRemoteResourceManagement": false,
+ "policyEnforcementMode": "ENFORCING",
+ "resources": [
+ {
+ "name": "client.resource.700132ee-a2fc-4fc6-8194-df6782aa23b7",
+ "type": "Client",
+ "ownerManagedAccess": false,
+ "attributes": {},
+ "uris": [],
+ "scopes": [
+ {
+ "name": "view"
+ },
+ {
+ "name": "map-roles-client-scope"
+ },
+ {
+ "name": "configure"
+ },
+ {
+ "name": "map-roles"
+ },
+ {
+ "name": "manage"
+ },
+ {
+ "name": "token-exchange"
+ },
+ {
+ "name": "map-roles-composite"
+ }
+ ]
+ }
+ ],
+ "policies": [
+ {
+ "name": "workflow-app-policy",
+ "description": "",
+ "type": "client",
+ "logic": "POSITIVE",
+ "decisionStrategy": "UNANIMOUS",
+ "config": {
+ "clients": "[\"workflow-app\"]"
+ }
+ },
+ {
+ "name": "workflow2-exchange",
+ "description": "",
+ "type": "client",
+ "logic": "POSITIVE",
+ "decisionStrategy": "UNANIMOUS",
+ "config": {
+ "clients": "[]"
+ }
+ },
+ {
+ "name": "manage.permission.client.700132ee-a2fc-4fc6-8194-df6782aa23b7",
+ "type": "scope",
+ "logic": "POSITIVE",
+ "decisionStrategy": "UNANIMOUS",
+ "config": {
+ "resources": "[\"client.resource.700132ee-a2fc-4fc6-8194-df6782aa23b7\"]",
+ "scopes": "[\"manage\"]"
+ }
+ },
+ {
+ "name": "configure.permission.client.700132ee-a2fc-4fc6-8194-df6782aa23b7",
+ "type": "scope",
+ "logic": "POSITIVE",
+ "decisionStrategy": "UNANIMOUS",
+ "config": {
+ "resources": "[\"client.resource.700132ee-a2fc-4fc6-8194-df6782aa23b7\"]",
+ "scopes": "[\"configure\"]"
+ }
+ },
+ {
+ "name": "view.permission.client.700132ee-a2fc-4fc6-8194-df6782aa23b7",
+ "type": "scope",
+ "logic": "POSITIVE",
+ "decisionStrategy": "UNANIMOUS",
+ "config": {
+ "resources": "[\"client.resource.700132ee-a2fc-4fc6-8194-df6782aa23b7\"]",
+ "scopes": "[\"view\"]"
+ }
+ },
+ {
+ "name": "map-roles.permission.client.700132ee-a2fc-4fc6-8194-df6782aa23b7",
+ "type": "scope",
+ "logic": "POSITIVE",
+ "decisionStrategy": "UNANIMOUS",
+ "config": {
+ "resources": "[\"client.resource.700132ee-a2fc-4fc6-8194-df6782aa23b7\"]",
+ "scopes": "[\"map-roles\"]"
+ }
+ },
+ {
+ "name": "map-roles-client-scope.permission.client.700132ee-a2fc-4fc6-8194-df6782aa23b7",
+ "type": "scope",
+ "logic": "POSITIVE",
+ "decisionStrategy": "UNANIMOUS",
+ "config": {
+ "resources": "[\"client.resource.700132ee-a2fc-4fc6-8194-df6782aa23b7\"]",
+ "scopes": "[\"map-roles-client-scope\"]"
+ }
+ },
+ {
+ "name": "map-roles-composite.permission.client.700132ee-a2fc-4fc6-8194-df6782aa23b7",
+ "type": "scope",
+ "logic": "POSITIVE",
+ "decisionStrategy": "UNANIMOUS",
+ "config": {
+ "resources": "[\"client.resource.700132ee-a2fc-4fc6-8194-df6782aa23b7\"]",
+ "scopes": "[\"map-roles-composite\"]"
+ }
+ },
+ {
+ "name": "token-exchange.permission.client.700132ee-a2fc-4fc6-8194-df6782aa23b7",
+ "description": "",
+ "type": "scope",
+ "logic": "POSITIVE",
+ "decisionStrategy": "UNANIMOUS",
+ "config": {
+ "resources": "[\"client.resource.700132ee-a2fc-4fc6-8194-df6782aa23b7\"]",
+ "scopes": "[\"token-exchange\"]",
+ "applyPolicies": "[\"workflow-app-policy\"]"
+ }
+ }
+ ],
+ "scopes": [
+ {
+ "name": "manage"
+ },
+ {
+ "name": "view"
+ },
+ {
+ "name": "map-roles"
+ },
+ {
+ "name": "map-roles-client-scope"
+ },
+ {
+ "name": "map-roles-composite"
+ },
+ {
+ "name": "configure"
+ },
+ {
+ "name": "token-exchange"
+ }
+ ],
+ "decisionStrategy": "UNANIMOUS"
+ }
+ },
+ {
+ "id": "e4dac26b-92ea-40a1-bda0-70a984b37b1b",
+ "clientId": "security-admin-console",
+ "name": "${client_security-admin-console}",
+ "rootUrl": "${authAdminUrl}",
+ "baseUrl": "/admin/acme/console/",
+ "surrogateAuthRequired": false,
+ "enabled": true,
+ "alwaysDisplayInConsole": false,
+ "clientAuthenticatorType": "client-secret",
+ "redirectUris": [
+ "/admin/acme/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": "465d69e9-664c-4a43-bf39-e92a24c6f1d4",
+ "name": "locale",
+ "protocol": "openid-connect",
+ "protocolMapper": "oidc-usermodel-attribute-mapper",
+ "consentRequired": false,
+ "config": {
+ "introspection.token.claim": "true",
+ "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",
+ "roles",
+ "profile",
+ "basic",
+ "email"
+ ],
+ "optionalClientScopes": [
+ "address",
+ "phone",
+ "offline_access",
+ "microprofile-jwt"
+ ]
+ },
+ {
+ "id": "700132ee-a2fc-4fc6-8194-df6782aa23b7",
+ "clientId": "workflow-app",
+ "name": "",
+ "description": "",
+ "rootUrl": "",
+ "adminUrl": "",
+ "baseUrl": "",
+ "surrogateAuthRequired": false,
+ "enabled": true,
+ "alwaysDisplayInConsole": false,
+ "clientAuthenticatorType": "client-secret",
+ "secret": "secret",
+ "redirectUris": [
+ "/*"
+ ],
+ "webOrigins": [
+ "/*"
+ ],
+ "notBefore": 0,
+ "bearerOnly": false,
+ "consentRequired": false,
+ "standardFlowEnabled": false,
+ "implicitFlowEnabled": true,
+ "directAccessGrantsEnabled": true,
+ "serviceAccountsEnabled": true,
+ "publicClient": false,
+ "frontchannelLogout": true,
+ "protocol": "openid-connect",
+ "attributes": {
+ "oidc.ciba.grant.enabled": "false",
+ "client.secret.creation.time": "1723757733",
+ "backchannel.logout.session.required": "true",
+ "post.logout.redirect.uris": "+",
+ "oauth2.device.authorization.grant.enabled": "false",
+ "backchannel.logout.revoke.offline.tokens": "false"
+ },
+ "authenticationFlowBindingOverrides": {},
+ "fullScopeAllowed": true,
+ "nodeReRegistrationTimeout": -1,
+ "protocolMappers": [
+ {
+ "id": "d0769785-1e48-4e06-bf41-1b115cf7d5a8",
+ "name": "audience resolve",
+ "protocol": "openid-connect",
+ "protocolMapper": "oidc-audience-resolve-mapper",
+ "consentRequired": false,
+ "config": {
+ "introspection.token.claim": "true",
+ "access.token.claim": "true"
+ }
+ },
+ {
+ "id": "0f46501b-628f-4a49-a847-918d8a21d631",
+ "name": "Client Host",
+ "protocol": "openid-connect",
+ "protocolMapper": "oidc-usersessionmodel-note-mapper",
+ "consentRequired": false,
+ "config": {
+ "user.session.note": "clientHost",
+ "introspection.token.claim": "true",
+ "userinfo.token.claim": "true",
+ "id.token.claim": "true",
+ "access.token.claim": "true",
+ "claim.name": "clientHost",
+ "jsonType.label": "String"
+ }
+ },
+ {
+ "id": "c3bc52e4-c6b8-49fb-a7c1-714c97c26c21",
+ "name": "Client ID",
+ "protocol": "openid-connect",
+ "protocolMapper": "oidc-usersessionmodel-note-mapper",
+ "consentRequired": false,
+ "config": {
+ "user.session.note": "client_id",
+ "introspection.token.claim": "true",
+ "userinfo.token.claim": "true",
+ "id.token.claim": "true",
+ "access.token.claim": "true",
+ "claim.name": "client_id",
+ "jsonType.label": "String"
+ }
+ },
+ {
+ "id": "75381980-7a81-4ec1-9ad2-460a0827b1b3",
+ "name": "Client IP Address",
+ "protocol": "openid-connect",
+ "protocolMapper": "oidc-usersessionmodel-note-mapper",
+ "consentRequired": false,
+ "config": {
+ "user.session.note": "clientAddress",
+ "introspection.token.claim": "true",
+ "userinfo.token.claim": "true",
+ "id.token.claim": "true",
+ "access.token.claim": "true",
+ "claim.name": "clientAddress",
+ "jsonType.label": "String"
+ }
+ }
+ ],
+ "defaultClientScopes": [
+ "web-origins",
+ "acr",
+ "roles",
+ "profile",
+ "basic",
+ "email"
+ ],
+ "optionalClientScopes": [
+ "address",
+ "phone",
+ "offline_access",
+ "microprofile-jwt"
+ ]
+ }
+ ],
+ "clientScopes": [
+ {
+ "id": "5202a7c6-cc7c-44e8-8c87-6d739e321868",
+ "name": "workflow-app",
+ "description": "Scope for the Workflow Application Audience",
+ "protocol": "openid-connect",
+ "attributes": {
+ "include.in.token.scope": "true",
+ "display.on.consent.screen": "false",
+ "gui.order": "",
+ "consent.screen.text": ""
+ },
+ "protocolMappers": [
+ {
+ "id": "5ec19709-1519-43b8-b924-73fe817b427f",
+ "name": "workflow-app",
+ "protocol": "openid-connect",
+ "protocolMapper": "oidc-audience-mapper",
+ "consentRequired": false,
+ "config": {
+ "included.client.audience": "workflow-app",
+ "id.token.claim": "false",
+ "lightweight.claim": "false",
+ "access.token.claim": "true",
+ "introspection.token.claim": "true"
+ }
+ }
+ ]
+ },
+ {
+ "id": "c50188de-867b-496a-b7ba-89abcf4e491d",
+ "name": "address",
+ "description": "OpenID Connect built-in scope: address",
+ "protocol": "openid-connect",
+ "attributes": {
+ "include.in.token.scope": "true",
+ "consent.screen.text": "${addressScopeConsentText}",
+ "display.on.consent.screen": "true"
+ },
+ "protocolMappers": [
+ {
+ "id": "6d5cddac-f5b3-4ba6-bc50-390e7a007be7",
+ "name": "address",
+ "protocol": "openid-connect",
+ "protocolMapper": "oidc-address-mapper",
+ "consentRequired": false,
+ "config": {
+ "user.attribute.formatted": "formatted",
+ "user.attribute.country": "country",
+ "introspection.token.claim": "true",
+ "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": "9fdd2c08-1176-4317-b864-687fe57a66e2",
+ "name": "roles",
+ "description": "OpenID Connect scope for add user roles to the access token",
+ "protocol": "openid-connect",
+ "attributes": {
+ "include.in.token.scope": "false",
+ "consent.screen.text": "${rolesScopeConsentText}",
+ "display.on.consent.screen": "true"
+ },
+ "protocolMappers": [
+ {
+ "id": "5212f083-20ea-4bab-90db-2221eb66e329",
+ "name": "client roles",
+ "protocol": "openid-connect",
+ "protocolMapper": "oidc-usermodel-client-role-mapper",
+ "consentRequired": false,
+ "config": {
+ "user.attribute": "foo",
+ "introspection.token.claim": "true",
+ "access.token.claim": "true",
+ "claim.name": "resource_access.${client_id}.roles",
+ "jsonType.label": "String",
+ "multivalued": "true"
+ }
+ },
+ {
+ "id": "e1dc8eb1-ea9c-4ed2-8a7f-03c50d9ed3ac",
+ "name": "audience resolve",
+ "protocol": "openid-connect",
+ "protocolMapper": "oidc-audience-resolve-mapper",
+ "consentRequired": false,
+ "config": {
+ "introspection.token.claim": "true",
+ "access.token.claim": "true"
+ }
+ },
+ {
+ "id": "06318d41-2045-4984-87d2-c842f0059f81",
+ "name": "realm roles",
+ "protocol": "openid-connect",
+ "protocolMapper": "oidc-usermodel-realm-role-mapper",
+ "consentRequired": false,
+ "config": {
+ "user.attribute": "foo",
+ "introspection.token.claim": "true",
+ "access.token.claim": "true",
+ "claim.name": "realm_access.roles",
+ "jsonType.label": "String",
+ "multivalued": "true"
+ }
+ }
+ ]
+ },
+ {
+ "id": "5233c149-d966-4af4-9e20-a91696730a4e",
+ "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": "6e21b645-d17d-4f76-81d1-4b3854523de1",
+ "name": "acr loa level",
+ "protocol": "openid-connect",
+ "protocolMapper": "oidc-acr-mapper",
+ "consentRequired": false,
+ "config": {
+ "id.token.claim": "true",
+ "introspection.token.claim": "true",
+ "access.token.claim": "true",
+ "userinfo.token.claim": "true"
+ }
+ }
+ ]
+ },
+ {
+ "id": "ccc9f61b-f2a3-44f3-89c9-db872c8059b6",
+ "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": "d9294395-1b20-4959-9359-015c6ecf3a70",
+ "name": "email",
+ "description": "OpenID Connect built-in scope: email",
+ "protocol": "openid-connect",
+ "attributes": {
+ "include.in.token.scope": "true",
+ "consent.screen.text": "${emailScopeConsentText}",
+ "display.on.consent.screen": "true"
+ },
+ "protocolMappers": [
+ {
+ "id": "e2ed1d59-976a-41ea-be65-1616a1d25465",
+ "name": "email verified",
+ "protocol": "openid-connect",
+ "protocolMapper": "oidc-usermodel-property-mapper",
+ "consentRequired": false,
+ "config": {
+ "introspection.token.claim": "true",
+ "userinfo.token.claim": "true",
+ "user.attribute": "emailVerified",
+ "id.token.claim": "true",
+ "access.token.claim": "true",
+ "claim.name": "email_verified",
+ "jsonType.label": "boolean"
+ }
+ },
+ {
+ "id": "d333ae22-9dba-4573-b348-b1efb1ebd208",
+ "name": "email",
+ "protocol": "openid-connect",
+ "protocolMapper": "oidc-usermodel-attribute-mapper",
+ "consentRequired": false,
+ "config": {
+ "introspection.token.claim": "true",
+ "userinfo.token.claim": "true",
+ "user.attribute": "email",
+ "id.token.claim": "true",
+ "access.token.claim": "true",
+ "claim.name": "email",
+ "jsonType.label": "String"
+ }
+ }
+ ]
+ },
+ {
+ "id": "290505cb-e5a4-472a-bdae-2f170132eef3",
+ "name": "role_list",
+ "description": "SAML role list",
+ "protocol": "saml",
+ "attributes": {
+ "consent.screen.text": "${samlRoleListScopeConsentText}",
+ "display.on.consent.screen": "true"
+ },
+ "protocolMappers": [
+ {
+ "id": "e1a63680-5729-4813-a252-c9795ea20518",
+ "name": "role list",
+ "protocol": "saml",
+ "protocolMapper": "saml-role-list-mapper",
+ "consentRequired": false,
+ "config": {
+ "single": "false",
+ "attribute.nameformat": "Basic",
+ "attribute.name": "Role"
+ }
+ }
+ ]
+ },
+ {
+ "id": "bf422afd-dff3-4ba3-9754-c8fe45993a42",
+ "name": "profile",
+ "description": "OpenID Connect built-in scope: profile",
+ "protocol": "openid-connect",
+ "attributes": {
+ "include.in.token.scope": "true",
+ "consent.screen.text": "${profileScopeConsentText}",
+ "display.on.consent.screen": "true"
+ },
+ "protocolMappers": [
+ {
+ "id": "39c6c363-211e-42d0-a4f4-8659f277f0d9",
+ "name": "given name",
+ "protocol": "openid-connect",
+ "protocolMapper": "oidc-usermodel-attribute-mapper",
+ "consentRequired": false,
+ "config": {
+ "introspection.token.claim": "true",
+ "userinfo.token.claim": "true",
+ "user.attribute": "firstName",
+ "id.token.claim": "true",
+ "access.token.claim": "true",
+ "claim.name": "given_name",
+ "jsonType.label": "String"
+ }
+ },
+ {
+ "id": "53dc781a-39e4-4b95-b854-76e87484c128",
+ "name": "gender",
+ "protocol": "openid-connect",
+ "protocolMapper": "oidc-usermodel-attribute-mapper",
+ "consentRequired": false,
+ "config": {
+ "introspection.token.claim": "true",
+ "userinfo.token.claim": "true",
+ "user.attribute": "gender",
+ "id.token.claim": "true",
+ "access.token.claim": "true",
+ "claim.name": "gender",
+ "jsonType.label": "String"
+ }
+ },
+ {
+ "id": "ad06389c-80be-4344-afb4-7835cbf73b6e",
+ "name": "birthdate",
+ "protocol": "openid-connect",
+ "protocolMapper": "oidc-usermodel-attribute-mapper",
+ "consentRequired": false,
+ "config": {
+ "introspection.token.claim": "true",
+ "userinfo.token.claim": "true",
+ "user.attribute": "birthdate",
+ "id.token.claim": "true",
+ "access.token.claim": "true",
+ "claim.name": "birthdate",
+ "jsonType.label": "String"
+ }
+ },
+ {
+ "id": "25e70c0d-ee2b-4c08-a914-3d69e7cc4721",
+ "name": "middle name",
+ "protocol": "openid-connect",
+ "protocolMapper": "oidc-usermodel-attribute-mapper",
+ "consentRequired": false,
+ "config": {
+ "introspection.token.claim": "true",
+ "userinfo.token.claim": "true",
+ "user.attribute": "middleName",
+ "id.token.claim": "true",
+ "access.token.claim": "true",
+ "claim.name": "middle_name",
+ "jsonType.label": "String"
+ }
+ },
+ {
+ "id": "5b650bbb-73e7-4e16-a3b5-fa389275913c",
+ "name": "zoneinfo",
+ "protocol": "openid-connect",
+ "protocolMapper": "oidc-usermodel-attribute-mapper",
+ "consentRequired": false,
+ "config": {
+ "introspection.token.claim": "true",
+ "userinfo.token.claim": "true",
+ "user.attribute": "zoneinfo",
+ "id.token.claim": "true",
+ "access.token.claim": "true",
+ "claim.name": "zoneinfo",
+ "jsonType.label": "String"
+ }
+ },
+ {
+ "id": "eb7c4a36-94fa-41d1-9196-2d619530e6ff",
+ "name": "full name",
+ "protocol": "openid-connect",
+ "protocolMapper": "oidc-full-name-mapper",
+ "consentRequired": false,
+ "config": {
+ "id.token.claim": "true",
+ "introspection.token.claim": "true",
+ "access.token.claim": "true",
+ "userinfo.token.claim": "true"
+ }
+ },
+ {
+ "id": "e8383c1d-95b5-44d1-8a23-e74977aa0f59",
+ "name": "locale",
+ "protocol": "openid-connect",
+ "protocolMapper": "oidc-usermodel-attribute-mapper",
+ "consentRequired": false,
+ "config": {
+ "introspection.token.claim": "true",
+ "userinfo.token.claim": "true",
+ "user.attribute": "locale",
+ "id.token.claim": "true",
+ "access.token.claim": "true",
+ "claim.name": "locale",
+ "jsonType.label": "String"
+ }
+ },
+ {
+ "id": "dababf01-c1a8-42af-8f0f-a375711435a9",
+ "name": "family name",
+ "protocol": "openid-connect",
+ "protocolMapper": "oidc-usermodel-attribute-mapper",
+ "consentRequired": false,
+ "config": {
+ "introspection.token.claim": "true",
+ "userinfo.token.claim": "true",
+ "user.attribute": "lastName",
+ "id.token.claim": "true",
+ "access.token.claim": "true",
+ "claim.name": "family_name",
+ "jsonType.label": "String"
+ }
+ },
+ {
+ "id": "b5ebe645-ca59-47e7-bcdf-5b06231e8948",
+ "name": "profile",
+ "protocol": "openid-connect",
+ "protocolMapper": "oidc-usermodel-attribute-mapper",
+ "consentRequired": false,
+ "config": {
+ "introspection.token.claim": "true",
+ "userinfo.token.claim": "true",
+ "user.attribute": "profile",
+ "id.token.claim": "true",
+ "access.token.claim": "true",
+ "claim.name": "profile",
+ "jsonType.label": "String"
+ }
+ },
+ {
+ "id": "00b6be51-aa65-4116-946c-d6f33fdf076c",
+ "name": "username",
+ "protocol": "openid-connect",
+ "protocolMapper": "oidc-usermodel-attribute-mapper",
+ "consentRequired": false,
+ "config": {
+ "introspection.token.claim": "true",
+ "userinfo.token.claim": "true",
+ "user.attribute": "username",
+ "id.token.claim": "true",
+ "access.token.claim": "true",
+ "claim.name": "preferred_username",
+ "jsonType.label": "String"
+ }
+ },
+ {
+ "id": "abb9c9d4-17c4-45ef-9fe0-889097db0547",
+ "name": "picture",
+ "protocol": "openid-connect",
+ "protocolMapper": "oidc-usermodel-attribute-mapper",
+ "consentRequired": false,
+ "config": {
+ "introspection.token.claim": "true",
+ "userinfo.token.claim": "true",
+ "user.attribute": "picture",
+ "id.token.claim": "true",
+ "access.token.claim": "true",
+ "claim.name": "picture",
+ "jsonType.label": "String"
+ }
+ },
+ {
+ "id": "3ec07ce5-c38c-42e0-a15c-23197552c185",
+ "name": "website",
+ "protocol": "openid-connect",
+ "protocolMapper": "oidc-usermodel-attribute-mapper",
+ "consentRequired": false,
+ "config": {
+ "introspection.token.claim": "true",
+ "userinfo.token.claim": "true",
+ "user.attribute": "website",
+ "id.token.claim": "true",
+ "access.token.claim": "true",
+ "claim.name": "website",
+ "jsonType.label": "String"
+ }
+ },
+ {
+ "id": "e40b32ba-5755-450e-ae6b-51039af5e2db",
+ "name": "nickname",
+ "protocol": "openid-connect",
+ "protocolMapper": "oidc-usermodel-attribute-mapper",
+ "consentRequired": false,
+ "config": {
+ "introspection.token.claim": "true",
+ "userinfo.token.claim": "true",
+ "user.attribute": "nickname",
+ "id.token.claim": "true",
+ "access.token.claim": "true",
+ "claim.name": "nickname",
+ "jsonType.label": "String"
+ }
+ },
+ {
+ "id": "542b446d-b95b-4492-82c2-2249ff99fc12",
+ "name": "updated at",
+ "protocol": "openid-connect",
+ "protocolMapper": "oidc-usermodel-attribute-mapper",
+ "consentRequired": false,
+ "config": {
+ "introspection.token.claim": "true",
+ "userinfo.token.claim": "true",
+ "user.attribute": "updatedAt",
+ "id.token.claim": "true",
+ "access.token.claim": "true",
+ "claim.name": "updated_at",
+ "jsonType.label": "long"
+ }
+ }
+ ]
+ },
+ {
+ "id": "be9061df-44cd-4703-a7ba-114794094a3b",
+ "name": "phone",
+ "description": "OpenID Connect built-in scope: phone",
+ "protocol": "openid-connect",
+ "attributes": {
+ "include.in.token.scope": "true",
+ "consent.screen.text": "${phoneScopeConsentText}",
+ "display.on.consent.screen": "true"
+ },
+ "protocolMappers": [
+ {
+ "id": "896eba18-fe8b-4dd5-bb6a-ae8103b958eb",
+ "name": "phone number",
+ "protocol": "openid-connect",
+ "protocolMapper": "oidc-usermodel-attribute-mapper",
+ "consentRequired": false,
+ "config": {
+ "introspection.token.claim": "true",
+ "userinfo.token.claim": "true",
+ "user.attribute": "phoneNumber",
+ "id.token.claim": "true",
+ "access.token.claim": "true",
+ "claim.name": "phone_number",
+ "jsonType.label": "String"
+ }
+ },
+ {
+ "id": "281787d6-716b-434c-9db8-b5435492c3e9",
+ "name": "phone number verified",
+ "protocol": "openid-connect",
+ "protocolMapper": "oidc-usermodel-attribute-mapper",
+ "consentRequired": false,
+ "config": {
+ "introspection.token.claim": "true",
+ "userinfo.token.claim": "true",
+ "user.attribute": "phoneNumberVerified",
+ "id.token.claim": "true",
+ "access.token.claim": "true",
+ "claim.name": "phone_number_verified",
+ "jsonType.label": "boolean"
+ }
+ }
+ ]
+ },
+ {
+ "id": "feb02166-5e5b-4d2b-a84d-243b3ad9aad3",
+ "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",
+ "consent.screen.text": "",
+ "display.on.consent.screen": "false"
+ },
+ "protocolMappers": [
+ {
+ "id": "4ae95d03-b421-41d3-a611-fca0db575a5c",
+ "name": "allowed web origins",
+ "protocol": "openid-connect",
+ "protocolMapper": "oidc-allowed-origins-mapper",
+ "consentRequired": false,
+ "config": {
+ "introspection.token.claim": "true",
+ "access.token.claim": "true"
+ }
+ }
+ ]
+ },
+ {
+ "id": "7341dbcb-b207-4860-9cdd-fb469f8f61b9",
+ "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": "5a41073c-0a80-4e7b-a397-9bd0da669d08",
+ "name": "groups",
+ "protocol": "openid-connect",
+ "protocolMapper": "oidc-usermodel-realm-role-mapper",
+ "consentRequired": false,
+ "config": {
+ "introspection.token.claim": "true",
+ "multivalued": "true",
+ "userinfo.token.claim": "true",
+ "user.attribute": "foo",
+ "id.token.claim": "true",
+ "access.token.claim": "true",
+ "claim.name": "groups",
+ "jsonType.label": "String"
+ }
+ },
+ {
+ "id": "3b2eb35b-54ea-4ca2-b707-bb010aefe2b9",
+ "name": "upn",
+ "protocol": "openid-connect",
+ "protocolMapper": "oidc-usermodel-attribute-mapper",
+ "consentRequired": false,
+ "config": {
+ "introspection.token.claim": "true",
+ "userinfo.token.claim": "true",
+ "user.attribute": "username",
+ "id.token.claim": "true",
+ "access.token.claim": "true",
+ "claim.name": "upn",
+ "jsonType.label": "String"
+ }
+ }
+ ]
+ },
+ {
+ "id": "4481fd4b-1c22-45c0-babc-52f5d199c389",
+ "name": "basic",
+ "description": "OpenID Connect scope for add all basic claims to the token",
+ "protocol": "openid-connect",
+ "attributes": {
+ "include.in.token.scope": "false",
+ "display.on.consent.screen": "false"
+ },
+ "protocolMappers": [
+ {
+ "id": "2b5dd39b-4099-4e6a-8b37-2c9668a20040",
+ "name": "auth_time",
+ "protocol": "openid-connect",
+ "protocolMapper": "oidc-usersessionmodel-note-mapper",
+ "consentRequired": false,
+ "config": {
+ "user.session.note": "AUTH_TIME",
+ "introspection.token.claim": "true",
+ "userinfo.token.claim": "true",
+ "id.token.claim": "true",
+ "access.token.claim": "true",
+ "claim.name": "auth_time",
+ "jsonType.label": "long"
+ }
+ },
+ {
+ "id": "424a6e95-824f-4ed7-b98f-1c6c52c6507b",
+ "name": "sub",
+ "protocol": "openid-connect",
+ "protocolMapper": "oidc-sub-mapper",
+ "consentRequired": false,
+ "config": {
+ "introspection.token.claim": "true",
+ "access.token.claim": "true"
+ }
+ }
+ ]
+ }
+ ],
+ "defaultDefaultClientScopes": [
+ "role_list",
+ "profile",
+ "email",
+ "roles",
+ "web-origins",
+ "acr",
+ "basic",
+ "workflow-app"
+ ],
+ "defaultOptionalClientScopes": [
+ "offline_access",
+ "address",
+ "phone",
+ "microprofile-jwt"
+ ],
+ "browserSecurityHeaders": {
+ "contentSecurityPolicyReportOnly": "",
+ "xContentTypeOptions": "nosniff",
+ "referrerPolicy": "no-referrer",
+ "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": "5f64958a-2f28-4521-8116-7eb5d919c710",
+ "name": "Trusted Hosts",
+ "providerId": "trusted-hosts",
+ "subType": "anonymous",
+ "subComponents": {},
+ "config": {
+ "host-sending-registration-request-must-match": [
+ "true"
+ ],
+ "client-uris-must-match": [
+ "true"
+ ]
+ }
+ },
+ {
+ "id": "72a76754-15fd-4704-a804-89d09095c8ea",
+ "name": "Consent Required",
+ "providerId": "consent-required",
+ "subType": "anonymous",
+ "subComponents": {},
+ "config": {}
+ },
+ {
+ "id": "8db359e2-1877-4d1c-8e95-fed9e029395b",
+ "name": "Allowed Client Scopes",
+ "providerId": "allowed-client-templates",
+ "subType": "anonymous",
+ "subComponents": {},
+ "config": {
+ "allow-default-scopes": [
+ "true"
+ ]
+ }
+ },
+ {
+ "id": "ec75647f-adbd-491e-ac98-da4bb1ee90bb",
+ "name": "Allowed Client Scopes",
+ "providerId": "allowed-client-templates",
+ "subType": "authenticated",
+ "subComponents": {},
+ "config": {
+ "allow-default-scopes": [
+ "true"
+ ]
+ }
+ },
+ {
+ "id": "00ddef35-16f1-4860-8b67-7b48ee7f6c79",
+ "name": "Allowed Protocol Mapper Types",
+ "providerId": "allowed-protocol-mappers",
+ "subType": "anonymous",
+ "subComponents": {},
+ "config": {
+ "allowed-protocol-mapper-types": [
+ "saml-role-list-mapper",
+ "oidc-usermodel-property-mapper",
+ "oidc-address-mapper",
+ "oidc-sha256-pairwise-sub-mapper",
+ "saml-user-attribute-mapper",
+ "oidc-full-name-mapper",
+ "oidc-usermodel-attribute-mapper",
+ "saml-user-property-mapper"
+ ]
+ }
+ },
+ {
+ "id": "4e67e444-554f-41e8-aef4-6056bd7b0372",
+ "name": "Max Clients Limit",
+ "providerId": "max-clients",
+ "subType": "anonymous",
+ "subComponents": {},
+ "config": {
+ "max-clients": [
+ "200"
+ ]
+ }
+ },
+ {
+ "id": "4246fddd-073d-4450-9615-4d06d687fc8c",
+ "name": "Full Scope Disabled",
+ "providerId": "scope",
+ "subType": "anonymous",
+ "subComponents": {},
+ "config": {}
+ },
+ {
+ "id": "bb80bd95-77f8-4b93-b217-81c4a998228d",
+ "name": "Allowed Protocol Mapper Types",
+ "providerId": "allowed-protocol-mappers",
+ "subType": "authenticated",
+ "subComponents": {},
+ "config": {
+ "allowed-protocol-mapper-types": [
+ "oidc-address-mapper",
+ "oidc-usermodel-attribute-mapper",
+ "oidc-full-name-mapper",
+ "oidc-sha256-pairwise-sub-mapper",
+ "saml-user-property-mapper",
+ "oidc-usermodel-property-mapper",
+ "saml-user-attribute-mapper",
+ "saml-role-list-mapper"
+ ]
+ }
+ }
+ ],
+ "org.keycloak.keys.KeyProvider": [
+ {
+ "id": "08072e73-6ef2-4aaa-b998-75bc912b01a1",
+ "name": "rsa-enc-generated",
+ "providerId": "rsa-enc-generated",
+ "subComponents": {},
+ "config": {
+ "priority": [
+ "100"
+ ],
+ "algorithm": [
+ "RSA-OAEP"
+ ]
+ }
+ },
+ {
+ "id": "71ee3a07-fceb-45f3-b65a-fb27b80f3b5e",
+ "name": "hmac-generated-hs512",
+ "providerId": "hmac-generated",
+ "subComponents": {},
+ "config": {
+ "priority": [
+ "100"
+ ],
+ "algorithm": [
+ "HS512"
+ ]
+ }
+ },
+ {
+ "id": "946b2828-e958-458d-a1c4-16fdcefdf4f5",
+ "name": "aes-generated",
+ "providerId": "aes-generated",
+ "subComponents": {},
+ "config": {
+ "priority": [
+ "100"
+ ]
+ }
+ },
+ {
+ "id": "f3e3b1bf-61b3-4748-b2a0-4cd49e3b9f1c",
+ "name": "rsa-generated",
+ "providerId": "rsa-generated",
+ "subComponents": {},
+ "config": {
+ "priority": [
+ "100"
+ ]
+ }
+ }
+ ]
+ },
+ "internationalizationEnabled": false,
+ "supportedLocales": [],
+ "authenticationFlows": [
+ {
+ "id": "fefe2bc0-d9df-42db-8961-6974d6298483",
+ "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": "e72b2e68-4e7e-460b-9393-93a9fbac8fa1",
+ "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": "60aa840b-8ba0-4968-a45e-2fe104282633",
+ "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": "91e6d753-0230-4f79-ac40-15b46f2701f3",
+ "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": "8cfb2a8b-75c3-4d06-9d65-54fc2932b849",
+ "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": "b6985d26-2bff-4f33-8538-1cd63e2196c0",
+ "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": "c15d8ec7-6cae-4d7d-b920-36fecf592152",
+ "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": "fe2ea76c-bb68-40b0-9017-417a7fe9cfbc",
+ "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": "b2f72af1-7f5f-48fb-adbb-7b237db779cc",
+ "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": "e758e76f-25c0-4db8-b3da-ecf20b0a9c57",
+ "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": "9eb5331d-dc19-4f31-9bcd-d19dec2c31b9",
+ "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": "b0b5d76f-e67b-4eef-b5df-ba2023a7f060",
+ "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": "582a48a2-8fa8-4dda-9b63-758b32ba4ac8",
+ "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": "ed4d909d-7aea-4710-b08e-e03177a4ca75",
+ "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": "119c4260-74cd-4a60-91cf-c8d91f1112f6",
+ "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": "3450fa36-da36-4f06-be15-c68bb5f358de",
+ "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-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
+ },
+ {
+ "authenticator": "registration-terms-and-conditions",
+ "authenticatorFlow": false,
+ "requirement": "DISABLED",
+ "priority": 70,
+ "autheticatorFlow": false,
+ "userSetupAllowed": false
+ }
+ ]
+ },
+ {
+ "id": "f847a9e5-bcbc-4b06-a818-d62755bcb86d",
+ "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": "5b0ec71c-a9f1-4609-9377-2fbd7b3cdffe",
+ "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": "4819e841-dfdc-4db8-a6f4-0af222e95418",
+ "alias": "create unique user config",
+ "config": {
+ "require.password.update.after.registration": "false"
+ }
+ },
+ {
+ "id": "f297ddde-2005-43d2-860b-7e466c62b22d",
+ "alias": "review profile config",
+ "config": {
+ "update.profile.on.first.login": "missing"
+ }
+ }
+ ],
+ "requiredActions": [
+ {
+ "alias": "CONFIGURE_TOTP",
+ "name": "Configure OTP",
+ "providerId": "CONFIGURE_TOTP",
+ "enabled": false,
+ "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": false,
+ "defaultAction": false,
+ "priority": 30,
+ "config": {}
+ },
+ {
+ "alias": "UPDATE_PROFILE",
+ "name": "Update Profile",
+ "providerId": "UPDATE_PROFILE",
+ "enabled": false,
+ "defaultAction": false,
+ "priority": 40,
+ "config": {}
+ },
+ {
+ "alias": "VERIFY_EMAIL",
+ "name": "Verify Email",
+ "providerId": "VERIFY_EMAIL",
+ "enabled": false,
+ "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": false,
+ "defaultAction": false,
+ "priority": 70,
+ "config": {}
+ },
+ {
+ "alias": "webauthn-register-passwordless",
+ "name": "Webauthn Register Passwordless",
+ "providerId": "webauthn-register-passwordless",
+ "enabled": false,
+ "defaultAction": false,
+ "priority": 80,
+ "config": {}
+ },
+ {
+ "alias": "VERIFY_PROFILE",
+ "name": "Verify Profile",
+ "providerId": "VERIFY_PROFILE",
+ "enabled": false,
+ "defaultAction": false,
+ "priority": 90,
+ "config": {}
+ },
+ {
+ "alias": "delete_credential",
+ "name": "Delete Credential",
+ "providerId": "delete_credential",
+ "enabled": true,
+ "defaultAction": false,
+ "priority": 100,
+ "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",
+ "firstBrokerLoginFlow": "first broker login",
+ "attributes": {
+ "cibaBackchannelTokenDeliveryMode": "poll",
+ "cibaAuthRequestedUserHint": "login_hint",
+ "clientOfflineSessionMaxLifespan": "0",
+ "oauth2DevicePollingInterval": "5",
+ "clientSessionIdleTimeout": "0",
+ "clientOfflineSessionIdleTimeout": "0",
+ "cibaInterval": "5",
+ "realmReusableOtpCode": "false",
+ "cibaExpiresIn": "120",
+ "oauth2DeviceCodeLifespan": "600",
+ "parRequestUriLifespan": "60",
+ "clientSessionMaxLifespan": "0",
+ "organizationsEnabled": "false"
+ },
+ "keycloakVersion": "25.0.2",
+ "userManagedAccessAllowed": false,
+ "organizationsEnabled": false,
+ "clientProfiles": {
+ "profiles": []
+ },
+ "clientPolicies": {
+ "policies": []
+ }
+}
\ No newline at end of file
diff --git a/serverless-workflow-examples/serverless-workflow-oauth2-token-exchange-quarkus/loan-workflow/pom.xml b/serverless-workflow-examples/serverless-workflow-oauth2-token-exchange-quarkus/loan-workflow/pom.xml
new file mode 100644
index 0000000000..abd416504d
--- /dev/null
+++ b/serverless-workflow-examples/serverless-workflow-oauth2-token-exchange-quarkus/loan-workflow/pom.xml
@@ -0,0 +1,186 @@
+
+
+ 4.0.0
+ 1.0.0-SNAPSHOT
+ Kogito Example :: Serverless Workflow Oauth2 Token Exchange Example :: Acme Loan Workflow
+ loan-workflow
+
+
+ org.acme.workflow.oauth2
+ serverless-workflow-oauth2-token-exchange-quarkus
+ 1.0.0-SNAPSHOT
+
+
+
+ 3.8.4
+ quarkus-bom
+ io.quarkus
+ 3.8.4
+ org.kie.kogito
+ kogito-bom
+ 999-SNAPSHOT
+ 3.8.1
+ 17
+
+ 3.2.5
+ 3.8.1
+ 17
+ 3.0.0-M7
+ 3.22.0
+
+ true
+
+
+
+
+
+ ${quarkus.platform.group-id}
+ ${quarkus.platform.artifact-id}
+ ${quarkus.platform.version}
+ pom
+ import
+
+
+ ${kogito.bom.group-id}
+ ${kogito.bom.artifact-id}
+ ${kogito.bom.version}
+ pom
+ import
+
+
+
+
+
+ io.quarkus
+ quarkus-arc
+
+
+ io.quarkus
+ quarkus-resteasy
+
+
+ io.quarkus
+ quarkus-resteasy-jackson
+
+
+ io.quarkus
+ quarkus-smallrye-openapi
+
+
+ io.quarkus
+ quarkus-oidc-client-filter
+
+
+ io.quarkus
+ quarkus-oidc-token-propagation
+
+
+ io.quarkus
+ quarkus-cache
+
+
+ io.quarkus
+ quarkus-smallrye-jwt
+
+
+ org.apache.kie.sonataflow
+ sonataflow-quarkus
+
+
+ org.kie
+ kie-addons-quarkus-source-files
+
+
+ io.quarkus
+ quarkus-junit5
+ test
+
+
+
+
+
+ ${quarkus.platform.group-id}
+ quarkus-maven-plugin
+ ${quarkus-plugin.version}
+ true
+
+
+
+ build
+ generate-code
+ generate-code-tests
+
+
+
+
+
+ maven-compiler-plugin
+ ${version.compiler.plugin}
+
+ ${maven.compiler.release}
+
+
+
+ maven-surefire-plugin
+ ${surefire-plugin.version}
+
+
+ org.jboss.logmanager.LogManager
+ ${maven.home}
+
+
+
+
+ maven-failsafe-plugin
+ ${surefire-plugin.version}
+
+
+
+ integration-test
+ verify
+
+
+
+
+
+ ${project.build.directory}/${project.build.finalName}-runner
+ org.jboss.logmanager.LogManager
+ ${maven.home}
+
+
+
+
+
+
+
+ container
+
+
+ container
+
+
+
+ container
+
+
+
+ io.quarkus
+ quarkus-container-image-jib
+
+
+
+
+ native
+
+
+ native
+
+
+
+ native
+
+
+
+
\ No newline at end of file
diff --git a/serverless-workflow-examples/serverless-workflow-oauth2-token-exchange-quarkus/loan-workflow/src/main/java/org/acme/workflow/auth/JWTParserHelper.java b/serverless-workflow-examples/serverless-workflow-oauth2-token-exchange-quarkus/loan-workflow/src/main/java/org/acme/workflow/auth/JWTParserHelper.java
new file mode 100644
index 0000000000..1b3595ed75
--- /dev/null
+++ b/serverless-workflow-examples/serverless-workflow-oauth2-token-exchange-quarkus/loan-workflow/src/main/java/org/acme/workflow/auth/JWTParserHelper.java
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.acme.workflow.auth;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import io.smallrye.jwt.auth.principal.JWTParser;
+import jakarta.enterprise.context.ApplicationScoped;
+import jakarta.inject.Inject;
+import org.jose4j.jwt.JwtClaims;
+import org.jose4j.jwt.consumer.InvalidJwtException;
+
+import java.util.Base64;
+
+/**
+ * Used in the workflow to parse the JWT Token and retrieve user's info from the custom header.
+ *
+ * @see Parse and Verify JsonWebToken with JWTParser
+ * @see Decode JWT Token and Verify in Plain Java
+ */
+@ApplicationScoped
+public class JWTParserHelper {
+
+ @Inject
+ JWTParser jwtParser;
+
+ ObjectMapper objectMapper = new ObjectMapper();
+
+ public JsonNode extractUser(String token) throws InvalidJwtException, JsonProcessingException {
+ final String[] tokenParts = token.split("\\.");
+ if (tokenParts.length != 3) {
+ throw new IllegalArgumentException("Invalid JWT token");
+ }
+
+ return objectMapper.readTree(
+ JwtClaims.parse(
+ new String(Base64.getUrlDecoder().decode(tokenParts[1]))).getRawJson());
+ }
+
+}
diff --git a/serverless-workflow-examples/serverless-workflow-oauth2-token-exchange-quarkus/loan-workflow/src/main/java/org/acme/workflow/auth/WorkflowTokenRequestFilter.java b/serverless-workflow-examples/serverless-workflow-oauth2-token-exchange-quarkus/loan-workflow/src/main/java/org/acme/workflow/auth/WorkflowTokenRequestFilter.java
new file mode 100644
index 0000000000..ba6f3951d0
--- /dev/null
+++ b/serverless-workflow-examples/serverless-workflow-oauth2-token-exchange-quarkus/loan-workflow/src/main/java/org/acme/workflow/auth/WorkflowTokenRequestFilter.java
@@ -0,0 +1,120 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.acme.workflow.auth;
+
+import io.quarkus.arc.Arc;
+import io.quarkus.cache.Cache;
+import io.quarkus.cache.CacheName;
+import io.quarkus.cache.CaffeineCache;
+import io.quarkus.oidc.client.*;
+import io.quarkus.oidc.token.propagation.AccessTokenRequestFilter;
+import io.quarkus.runtime.configuration.ConfigurationException;
+import io.quarkus.security.credential.TokenCredential;
+import jakarta.annotation.PostConstruct;
+import jakarta.enterprise.inject.Instance;
+import jakarta.inject.Inject;
+import jakarta.ws.rs.client.ClientRequestContext;
+import jakarta.ws.rs.core.MultivaluedMap;
+import org.eclipse.microprofile.config.ConfigProvider;
+import org.jboss.resteasy.microprofile.client.impl.MpClientInvocation;
+
+import java.io.IOException;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.CompletableFuture;
+
+public class WorkflowTokenRequestFilter extends AccessTokenRequestFilter {
+
+ @Inject
+ Instance accessToken;
+
+ @CacheName("my-cache")
+ Cache refreshTokensCache;
+
+ OidcClient exchangeTokenClient;
+ String exchangeTokenProperty;
+
+ @PostConstruct
+ public void initExchangeTokenClient() {
+ if (isExchangeToken()) {
+ OidcClients clients = Arc.container().instance(OidcClients.class).get();
+ String clientName = getClientName();
+ exchangeTokenClient = clientName != null ? clients.getClient(clientName) : clients.getClient();
+ OidcClientConfig.Grant.Type exchangeTokenGrantType = ConfigProvider.getConfig().getValue("quarkus.oidc-client." + (clientName != null ? clientName + "." : "") + "grant.type", OidcClientConfig.Grant.Type.class);
+ if (exchangeTokenGrantType == OidcClientConfig.Grant.Type.EXCHANGE) {
+ exchangeTokenProperty = "subject_token";
+ } else if (exchangeTokenGrantType == OidcClientConfig.Grant.Type.JWT) {
+ exchangeTokenProperty = "assertion";
+ } else {
+ throw new ConfigurationException("Token exchange is required but OIDC client is configured " + "to use the " + exchangeTokenGrantType.getGrantType() + " grantType");
+ }
+ }
+ }
+
+ @Override
+ public void filter(ClientRequestContext requestContext) throws IOException {
+ final String authTokenFromCtx = acquireTokenCredentialFromCtx(requestContext);
+ if (authTokenFromCtx.isEmpty()) {
+ if (verifyTokenInstance(requestContext, accessToken)) {
+ propagateToken(requestContext, exchangeTokenIfNeeded(accessToken.get().getToken()));
+ }
+ } else {
+ propagateToken(requestContext, exchangeTokenIfNeeded(authTokenFromCtx));
+ }
+ }
+
+ private String exchangeTokenIfNeeded(String token) {
+ if (exchangeTokenClient != null) {
+ Tokens tokens;
+ try {
+ // more dynamic parameters can be configured if required
+ // cache exchangedTokens to avoid roundtrips, for this to work we have to introspect the token and verify if it's valid or expired
+ // see https://quarkus.io/guides/security-oidc-bearer-token-authentication#accessing-jwt-claims
+ tokens = exchangeTokenClient.getTokens(Collections.singletonMap(exchangeTokenProperty, token)).await().indefinitely();
+ // Lame implementation
+ refreshTokensCache.as(CaffeineCache.class).put(token, CompletableFuture.completedFuture(tokens.getRefreshToken()));
+ return tokens.getAccessToken();
+ } catch (OidcClientException e) {
+ // no refresh tokens, nothing to do.
+ if (refreshTokensCache.get(token, k -> null).await().indefinitely() == null) {
+ throw e;
+ }
+ // catch, if invalid token try refreshing
+ final String refreshToken = (String) refreshTokensCache.get(token, k -> null).await().indefinitely();
+ tokens = exchangeTokenClient.refreshTokens(refreshToken).await().indefinitely();
+ // Lame implementation
+ refreshTokensCache.as(CaffeineCache.class).put(token, CompletableFuture.completedFuture(tokens.getRefreshToken()));
+ return tokens.getAccessToken();
+ }
+ }
+ return token;
+ }
+
+ private String acquireTokenCredentialFromCtx(ClientRequestContext requestContext) {
+ MultivaluedMap containerHeaders = (MultivaluedMap) requestContext.getProperty(MpClientInvocation.CONTAINER_HEADERS);
+ if (containerHeaders != null) {
+ final List authorizationHeader = containerHeaders.get("X-Authorization-acme_financial_auth");
+ if (authorizationHeader != null && !authorizationHeader.isEmpty()) {
+ return authorizationHeader.get(0).replace("Bearer ", "").trim();
+ }
+ }
+ return "";
+ }
+
+}
diff --git a/serverless-workflow-examples/serverless-workflow-oauth2-token-exchange-quarkus/loan-workflow/src/main/resources/application.properties b/serverless-workflow-examples/serverless-workflow-oauth2-token-exchange-quarkus/loan-workflow/src/main/resources/application.properties
new file mode 100644
index 0000000000..c0da81729c
--- /dev/null
+++ b/serverless-workflow-examples/serverless-workflow-oauth2-token-exchange-quarkus/loan-workflow/src/main/resources/application.properties
@@ -0,0 +1,57 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+quarkus.log.category."org.acme".level=DEBUG
+quarkus.swagger-ui.always-include=true
+
+quarkus.kogito.devservices.enabled=false
+
+# Service we will call is in the module acme-financial-service generated by the OpenAPI Generator
+# It's based on the openapi file in the specs dir
+# acme_financial_service_yaml is the name of the openapi file used here as the key to configure the service connection
+quarkus.rest-client.acme_financial_service_yaml.url=http://localhost:8181
+
+quarkus.openapi-generator.codegen.spec.acme_financial_service_yml.base-package=com.acme
+# We disabled the security codegen because it's not supporting token exchange at the moment
+quarkus.openapi-generator.codegen.spec.acme_financial_service_yaml.enable-security-generation=false
+# This is a custom register provider that does the token exchange based on our custom header X-Authentication-
+quarkus.openapi-generator.codegen.spec.acme_financial_service_yaml.additional-api-type-annotations=@org.eclipse.microprofile.rest.client.annotation.RegisterProvider(org.acme.workflow.auth.WorkflowTokenRequestFilter.class)
+
+# The token propagation from the OpenAPI Generator is also disabled since we don't have the generated security beans
+//quarkus.openapi-generator.acme_financial_service_yaml.auth.acme_financial_oauth.token-propagation=true
+
+# Information about this Keycloak instance can be found at ./scripts/boot-keycloak.sh and ./keycloak/realm-export.json
+# acme_financial_oauth is the sanitized name of the SecurityScheme in the openapi spec file
+
+quarkus.oidc-client.acme_financial_oauth.discovery-enabled=false
+# Here's the openid discovery endpoint: http://localhost:9090/realms/acme/.well-known/openid-configuration
+quarkus.oidc-client.acme_financial_oauth.auth-server-url=http://localhost:9090/realms/acme/protocol/openid-connect/auth
+quarkus.oidc-client.acme_financial_oauth.token-path=http://localhost:9090/realms/acme/protocol/openid-connect/token
+quarkus.oidc-client.acme_financial_oauth.client-id=workflow-app
+quarkus.oidc-client.acme_financial_oauth.credentials.secret=secret
+quarkus.oidc-client.acme_financial_oauth.grant.type=exchange
+quarkus.oidc-client.acme_financial_oauth.credentials.client-secret.method=basic
+quarkus.oidc-client.acme_financial_oauth.grant-options.exchange.subject_token_type=urn:ietf:params:oauth:token-type:access_token
+
+quarkus.oidc-token-propagation.client-name=acme_financial_oauth
+quarkus.oidc-token-propagation.exchange-token=true
+quarkus.oidc-token-propagation.enabled=true
+
+# Debug
+quarkus.log.category."io.quarkus.oidc.client.runtime".level=TRACE
diff --git a/serverless-workflow-examples/serverless-workflow-oauth2-token-exchange-quarkus/loan-workflow/src/main/resources/loan-workflow.sw.yaml b/serverless-workflow-examples/serverless-workflow-oauth2-token-exchange-quarkus/loan-workflow/src/main/resources/loan-workflow.sw.yaml
new file mode 100644
index 0000000000..c462a179cf
--- /dev/null
+++ b/serverless-workflow-examples/serverless-workflow-oauth2-token-exchange-quarkus/loan-workflow/src/main/resources/loan-workflow.sw.yaml
@@ -0,0 +1,84 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+id: loan-workflow
+version: "1.0"
+name: Acme Loan Workflow
+start: extractUserName
+functions:
+ - name: extractUser
+ type: custom
+ operation: "service:org.acme.workflow.auth.JWTParserHelper::extractUser"
+ - name: getStatement
+ type: rest
+ operation: specs/acme-financial-service.yaml#getStatement
+ - name: calcBalance
+ type: expression
+ operation: "${ .statements | map(.amount) | add }"
+states:
+ - name: extractUserName
+ type: operation
+ actions:
+ - name: extractUserAction
+ functionRef:
+ # we use a custom java function to extract the token from the custom auth header propagated to the target service
+ refName: extractUser
+ arguments:
+ token: "${ $WORKFLOW.headers.\"X-Authorization-acme_financial_auth\" }"
+ stateDataFilter:
+ output: "${ { user: .preferred_username } }"
+ transition: checkBalance
+ - name: checkBalance
+ type: operation
+ actions:
+ - name: getStatementAction
+ functionRef:
+ # The input for this function is the access token that contains info about the authenticated user in the financial service
+ refName: getStatement
+ actionDataFilter:
+ results: "${ { statements: . } }"
+ - name: calcBalanceAction
+ functionRef:
+ refName: calcBalance
+ actionDataFilter:
+ results: "${ { balance: . } }"
+ transition: checkLoan
+ - name: checkLoan
+ type: switch
+ dataConditions:
+ - condition: "${ .balance >= 30.00 }"
+ transition:
+ nextState: loanApproved
+ - condition: "${ .balance < 30.00 }"
+ transition:
+ nextState: loanDenied
+ - name: loanApproved
+ type: inject
+ data:
+ loanApproved: true
+ stateDataFilter:
+ output: "${ { message: \"Congrats \\(.user)! Your loan has been approved!\", loanApproved } }"
+ end: true
+ - name: loanDenied
+ type: inject
+ data:
+ loanApproved: false
+ stateDataFilter:
+ output: "${ { message: \"Sorry \\(.user). Your loan has been denied.\", loanApproved } }"
+ end: true
diff --git a/serverless-workflow-examples/serverless-workflow-oauth2-token-exchange-quarkus/loan-workflow/src/main/resources/specs/acme-financial-service.yaml b/serverless-workflow-examples/serverless-workflow-oauth2-token-exchange-quarkus/loan-workflow/src/main/resources/specs/acme-financial-service.yaml
new file mode 100644
index 0000000000..1a35c5c799
--- /dev/null
+++ b/serverless-workflow-examples/serverless-workflow-oauth2-token-exchange-quarkus/loan-workflow/src/main/resources/specs/acme-financial-service.yaml
@@ -0,0 +1,45 @@
+---
+openapi: 3.0.3
+info:
+ title: Acme Financial Service API
+ version: 1.0.0
+paths:
+ /financial-service/statement:
+ get:
+ tags:
+ - Acme Financial Resource
+ operationId: getStatement
+ responses:
+ "200":
+ description: OK
+ content:
+ application/json:
+ schema:
+ type: array
+ items:
+ $ref: "#/components/schemas/StatementEntry"
+ security:
+ - acme-financial-oauth:
+ - customer
+components:
+ schemas:
+ LocalDate:
+ format: date
+ type: string
+ example: 2022-03-10
+ StatementEntry:
+ type: object
+ properties:
+ amount:
+ format: double
+ type: number
+ date:
+ $ref: "#/components/schemas/LocalDate"
+ securitySchemes:
+ acme-financial-oauth:
+ type: oauth2
+ flows:
+ clientCredentials:
+ authorizationUrl: http://localhost:9090/auth/realms/acme/protocol/openid-connect/auth
+ tokenUrl: http://localhost:9090/auth/realms/kogito/acme/openid-connect/token
+ scopes: {}
diff --git a/serverless-workflow-examples/serverless-workflow-oauth2-token-exchange-quarkus/pom.xml b/serverless-workflow-examples/serverless-workflow-oauth2-token-exchange-quarkus/pom.xml
new file mode 100644
index 0000000000..24bf57ec95
--- /dev/null
+++ b/serverless-workflow-examples/serverless-workflow-oauth2-token-exchange-quarkus/pom.xml
@@ -0,0 +1,43 @@
+
+
+
+ 4.0.0
+
+
+ org.kie.kogito.examples
+ serverless-workflow-examples-parent
+ 999-SNAPSHOT
+ ../serverless-workflow-examples-parent/pom.xml
+
+
+ org.acme.workflow.oauth2
+ serverless-workflow-oauth2-token-exchange-quarkus
+ 1.0.0-SNAPSHOT
+ pom
+ Kogito Example :: Serverless Workflow Oauth2 Token Exchange (RFC 8693) Example
+
+
+ acme-financial-service
+ loan-workflow
+
+
diff --git a/serverless-workflow-examples/serverless-workflow-oauth2-token-exchange-quarkus/postman/Token Exchange.postman_collection.json b/serverless-workflow-examples/serverless-workflow-oauth2-token-exchange-quarkus/postman/Token Exchange.postman_collection.json
new file mode 100644
index 0000000000..8c1f7dfd65
--- /dev/null
+++ b/serverless-workflow-examples/serverless-workflow-oauth2-token-exchange-quarkus/postman/Token Exchange.postman_collection.json
@@ -0,0 +1,281 @@
+{
+ "info": {
+ "_postman_id": "345054ed-fe34-4117-9435-466b21d97bfd",
+ "name": "Token Exchange",
+ "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json",
+ "_exporter_id": "1268158"
+ },
+ "item": [
+ {
+ "name": "Acme Financial Service",
+ "item": [
+ {
+ "name": "Request Access Token Acme Financial Service",
+ "request": {
+ "auth": {
+ "type": "basic",
+ "basic": [
+ {
+ "key": "password",
+ "value": "secret",
+ "type": "string"
+ },
+ {
+ "key": "username",
+ "value": "financial-service",
+ "type": "string"
+ }
+ ]
+ },
+ "method": "POST",
+ "header": [],
+ "body": {
+ "mode": "urlencoded",
+ "urlencoded": [
+ {
+ "key": "username",
+ "value": "bob",
+ "type": "text"
+ },
+ {
+ "key": "password",
+ "value": "bob",
+ "type": "text"
+ },
+ {
+ "key": "grant_type",
+ "value": "password",
+ "type": "text"
+ },
+ {
+ "key": "scope",
+ "value": "workflow-app",
+ "type": "text",
+ "disabled": true
+ }
+ ]
+ },
+ "url": {
+ "raw": "{{keycloak_url}}/realms/acme/protocol/openid-connect/token",
+ "host": [
+ "{{keycloak_url}}"
+ ],
+ "path": [
+ "realms",
+ "acme",
+ "protocol",
+ "openid-connect",
+ "token"
+ ]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "Get Statement",
+ "request": {
+ "auth": {
+ "type": "bearer",
+ "bearer": [
+ {
+ "key": "token",
+ "value": "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJEWjZlaWwwME12MTE1eDNwQ0hfTy1lQWpKQVIxTW5mRE1pN3YybkdrRjI0In0.eyJleHAiOjE3MjQzMzczMjgsImlhdCI6MTcyNDMzNzAyOCwianRpIjoiMmE0ZDRiNWEtMzBmZi00NTQ1LWJmYzktNWY2N2QxMThhZWE4IiwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo5MDkwL3JlYWxtcy9hY21lIiwiYXVkIjpbIndvcmtmbG93LWFwcCIsImFjY291bnQiXSwic3ViIjoiMDdhN2E5MGQtOGQ2Mi00NmYxLWE5ZDItMzJmYTEzM2RhYzBiIiwidHlwIjoiQmVhcmVyIiwiYXpwIjoiZmluYW5jaWFsLXNlcnZpY2UiLCJzaWQiOiIxMDkxNGQ2Ni02MDI0LTQ1ZjItODIxMy00Yzc1MDZiMTExOGMiLCJhY3IiOiIxIiwiYWxsb3dlZC1vcmlnaW5zIjpbIi8qIl0sInJlYWxtX2FjY2VzcyI6eyJyb2xlcyI6WyJkZWZhdWx0LXJvbGVzLWFjbWUiLCJvZmZsaW5lX2FjY2VzcyIsInVtYV9hdXRob3JpemF0aW9uIiwiY3VzdG9tZXIiXX0sInJlc291cmNlX2FjY2VzcyI6eyJhY2NvdW50Ijp7InJvbGVzIjpbIm1hbmFnZS1hY2NvdW50IiwibWFuYWdlLWFjY291bnQtbGlua3MiLCJ2aWV3LXByb2ZpbGUiXX19LCJzY29wZSI6IndvcmtmbG93LWFwcCBlbWFpbCBwcm9maWxlIiwiZW1haWxfdmVyaWZpZWQiOnRydWUsInByZWZlcnJlZF91c2VybmFtZSI6ImFsaWNlIn0.iV-lHdl_RyLZPFAGyJ0zxVFq_IVTf9Ct-hGKvB507S73md2npTfZ-4KMcEYUfWQg_CcE0lGUghpV_9BFrzAWO-TWvLPEc_RJ6GpQqPhgJGM3LUges1WeubevFqEAmj91DR8RjGiZ3OitLmbtdALonbjvZXMjuGoteJbQFVwL7l1NqShkSM8cyy4XUpsyvBh8G0b2nY_bjp08r1ZH0g-awhpWTfyj61CYPcuB1ImMXLvhckooSOoEUmutUcEvnEZ8r_kZaP9tKTvpIDV9-IIH9DSBUPIdHpOaWkLEkUshK8xO6uqYVR34-39azssbfJ38HNMzewPV15IP7EZRsdwXoQ",
+ "type": "string"
+ }
+ ]
+ },
+ "method": "GET",
+ "header": [],
+ "url": {
+ "raw": "{{financial_service_url}}/financial-service/statement",
+ "host": [
+ "{{financial_service_url}}"
+ ],
+ "path": [
+ "financial-service",
+ "statement"
+ ]
+ }
+ },
+ "response": []
+ }
+ ]
+ },
+ {
+ "name": "Keycloak",
+ "item": [
+ {
+ "name": "Workflow App Get Access Token",
+ "request": {
+ "auth": {
+ "type": "basic",
+ "basic": [
+ {
+ "key": "password",
+ "value": "secret",
+ "type": "string"
+ },
+ {
+ "key": "username",
+ "value": "workflow-app",
+ "type": "string"
+ }
+ ]
+ },
+ "method": "POST",
+ "header": [],
+ "body": {
+ "mode": "urlencoded",
+ "urlencoded": [
+ {
+ "key": "grant_type",
+ "value": "urn:ietf:params:oauth:grant-type:token-exchange",
+ "type": "text"
+ }
+ ]
+ },
+ "url": {
+ "raw": "{{keycloak_url}}/realms/acme/protocol/openid-connect/token",
+ "host": [
+ "{{keycloak_url}}"
+ ],
+ "path": [
+ "realms",
+ "acme",
+ "protocol",
+ "openid-connect",
+ "token"
+ ]
+ }
+ },
+ "response": []
+ },
+ {
+ "name": "Workflow App Token Exchange Request",
+ "request": {
+ "method": "POST",
+ "header": [],
+ "body": {
+ "mode": "urlencoded",
+ "urlencoded": [
+ {
+ "key": "grant_type",
+ "value": "urn:ietf:params:oauth:grant-type:token-exchange",
+ "type": "text"
+ },
+ {
+ "key": "client_id",
+ "value": "workflow-app",
+ "type": "text"
+ },
+ {
+ "key": "client_secret",
+ "value": "secret",
+ "type": "text"
+ },
+ {
+ "key": "subject_token",
+ "value": "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJEWjZlaWwwME12MTE1eDNwQ0hfTy1lQWpKQVIxTW5mRE1pN3YybkdrRjI0In0.eyJleHAiOjE3MjQyNTgyMjMsImlhdCI6MTcyNDI1NzkyMywianRpIjoiODg0ZGIyZDMtMDQwYy00YTE3LWJkZTYtYWE1NjU3ODBiYjU1IiwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo5MDkwL3JlYWxtcy9hY21lIiwiYXVkIjpbIndvcmtmbG93LWFwcCIsImFjY291bnQiXSwic3ViIjoiZmI5NWNlYTctYzcwYy00MTlmLWEyMzktNjg1OWI5NWZlNzA2IiwidHlwIjoiQmVhcmVyIiwiYXpwIjoiZmluYW5jaWFsLXNlcnZpY2UiLCJzaWQiOiJhNjNjOGI4MC0wMTQyLTRlMzUtOThmMS0wZDg0YTk1NDg4MjgiLCJhY3IiOiIxIiwiYWxsb3dlZC1vcmlnaW5zIjpbIi8qIl0sInJlYWxtX2FjY2VzcyI6eyJyb2xlcyI6WyJkZWZhdWx0LXJvbGVzLWFjbWUiLCJvZmZsaW5lX2FjY2VzcyIsInVtYV9hdXRob3JpemF0aW9uIiwiY3VzdG9tZXIiXX0sInJlc291cmNlX2FjY2VzcyI6eyJhY2NvdW50Ijp7InJvbGVzIjpbIm1hbmFnZS1hY2NvdW50IiwibWFuYWdlLWFjY291bnQtbGlua3MiLCJ2aWV3LXByb2ZpbGUiXX19LCJzY29wZSI6IndvcmtmbG93LWFwcCBlbWFpbCBwcm9maWxlIiwiZW1haWxfdmVyaWZpZWQiOnRydWUsInByZWZlcnJlZF91c2VybmFtZSI6ImJvYiJ9.LYPYXDjkpx2S8aPUQriC8JC344yHh9AJr3wSfWIfJnN0fx4cjDbr8Uhq45gWopUJ6URQqy0fa3u-Bu1V8EwIgCF5-om9rbDbeBgicHwfgogjrpbQL6YN5ScwOgk5wcNkOTJsr9O_UeFGqDvd-3cVQtBquAs1a5I-65a3lRJGeu06N51sFh87fs_E6XCWNrz6UMrQwPpTiN80omz04w0scPCIKQpp27fy495ZyHgZaNUJWKw40iNLMyNFHBRrlCREbYeVHeqPALO1c2cdW4BkXFCSgXbBPLV6VFI-D4p-rdrqCYZmaDP4c4DxWT_kenQvHPaqzDIWXdbbWZC73Z54WA",
+ "type": "text"
+ },
+ {
+ "key": "subject_token_type",
+ "value": "urn:ietf:params:oauth:token-type:access_token",
+ "type": "text"
+ }
+ ]
+ },
+ "url": {
+ "raw": "{{keycloak_url}}/realms/acme/protocol/openid-connect/token",
+ "host": [
+ "{{keycloak_url}}"
+ ],
+ "path": [
+ "realms",
+ "acme",
+ "protocol",
+ "openid-connect",
+ "token"
+ ]
+ }
+ },
+ "response": []
+ }
+ ]
+ },
+ {
+ "name": "Start Workflow",
+ "request": {
+ "auth": {
+ "type": "noauth"
+ },
+ "method": "POST",
+ "header": [
+ {
+ "key": "X-Authorization-acme_financial_auth",
+ "value": "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJEWjZlaWwwME12MTE1eDNwQ0hfTy1lQWpKQVIxTW5mRE1pN3YybkdrRjI0In0.eyJleHAiOjE3MjQzNDEzODIsImlhdCI6MTcyNDM0MTA4MiwianRpIjoiMDE2MGVhMDEtNTFhMi00NDJjLWEyNTAtYTVmZmY1N2IyOTI2IiwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo5MDkwL3JlYWxtcy9hY21lIiwiYXVkIjpbIndvcmtmbG93LWFwcCIsImFjY291bnQiXSwic3ViIjoiZmI5NWNlYTctYzcwYy00MTlmLWEyMzktNjg1OWI5NWZlNzA2IiwidHlwIjoiQmVhcmVyIiwiYXpwIjoiZmluYW5jaWFsLXNlcnZpY2UiLCJzaWQiOiIxNmFmYTRjZC1iMTEyLTQyNTktYWE3Yi01OTQzODBiZWU3MzUiLCJhY3IiOiIxIiwiYWxsb3dlZC1vcmlnaW5zIjpbIi8qIl0sInJlYWxtX2FjY2VzcyI6eyJyb2xlcyI6WyJkZWZhdWx0LXJvbGVzLWFjbWUiLCJvZmZsaW5lX2FjY2VzcyIsInVtYV9hdXRob3JpemF0aW9uIiwiY3VzdG9tZXIiXX0sInJlc291cmNlX2FjY2VzcyI6eyJhY2NvdW50Ijp7InJvbGVzIjpbIm1hbmFnZS1hY2NvdW50IiwibWFuYWdlLWFjY291bnQtbGlua3MiLCJ2aWV3LXByb2ZpbGUiXX19LCJzY29wZSI6IndvcmtmbG93LWFwcCBlbWFpbCBwcm9maWxlIiwiZW1haWxfdmVyaWZpZWQiOnRydWUsInByZWZlcnJlZF91c2VybmFtZSI6ImJvYiJ9.p0pb9S1X8d4nfgscXgaG2R6BpR6LG9YXC07j2__HApFN7Wx3qqDoQ2gBJRjrhdWQiqp6bVeouy3DPZM4E5cn2UQI5eww4orE3lg9Dy9rbpDcYXwTxLlwNoibfpIBCEDkwIqNeJ9NNxNBpTnBaipYM-t4BXs9bFPgRAZK6ql5KF3qmWGoXD31ZWp8UJ_nnFzvg7DWlsqxH2-FHTj-VuZ7iMNJ0PuxGgKdZR1HHajYzbs2WGKYlQ4jIRdJax1BqpJAHKjEF4U1FKY3XCF-GZqmwq4exUuxYz-K4WW2iOdPeO8IlDzGVsxB9pBKth7eBqLCPvryuBxx9dZK9H1nijXPUQ",
+ "type": "text"
+ }
+ ],
+ "body": {
+ "mode": "raw",
+ "raw": "{}",
+ "options": {
+ "raw": {
+ "language": "json"
+ }
+ }
+ },
+ "url": {
+ "raw": "{{workflow_url}}/loan-workflow",
+ "host": [
+ "{{workflow_url}}"
+ ],
+ "path": [
+ "loan-workflow"
+ ]
+ }
+ },
+ "response": []
+ }
+ ],
+ "event": [
+ {
+ "listen": "prerequest",
+ "script": {
+ "type": "text/javascript",
+ "packages": {},
+ "exec": [
+ ""
+ ]
+ }
+ },
+ {
+ "listen": "test",
+ "script": {
+ "type": "text/javascript",
+ "packages": {},
+ "exec": [
+ ""
+ ]
+ }
+ }
+ ],
+ "variable": [
+ {
+ "key": "keycloak_url",
+ "value": "http://localhost:9090/",
+ "type": "string"
+ },
+ {
+ "key": "financial_service_url",
+ "value": "http://localhost:8181/",
+ "type": "string"
+ },
+ {
+ "key": "workflow_url",
+ "value": "http://localhost:8080/",
+ "type": "string"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/serverless-workflow-examples/serverless-workflow-oauth2-token-exchange-quarkus/scripts/boot-keycloak.sh b/serverless-workflow-examples/serverless-workflow-oauth2-token-exchange-quarkus/scripts/boot-keycloak.sh
new file mode 100755
index 0000000000..ab392bfab6
--- /dev/null
+++ b/serverless-workflow-examples/serverless-workflow-oauth2-token-exchange-quarkus/scripts/boot-keycloak.sh
@@ -0,0 +1,35 @@
+#!/bin/bash
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+user="admin"
+password="admin"
+java_opts="-Dkeycloak.profile.feature.token_exchange=enabled -Dkeycloak.profile.feature.admin_fine_grained_authz=enabled -Dkeycloak.profile.feature.impersonation=enabled"
+realm_path="$(pwd)/keycloak"
+
+if ! test "${realm_path}"; then
+ echo "--> Realm import file '${realm_path}' does not exist. Check your path and try again."
+ exit 1
+fi
+
+# Start Keycloak in devmode, see: https://www.keycloak.org/server/containers
+docker run -p 9090:8080 -e KEYCLOAK_ADMIN="${user}" -e KEYCLOAK_ADMIN_PASSWORD="${password}" -e JAVA_OPTS_APPEND="${java_opts}" \
+ -v "${realm_path}":/opt/keycloak/data/import \
+ quay.io/keycloak/keycloak:latest \
+ start-dev --import-realm