OAuth Bearer Token Authentication for listeners (Apache Kafka 3.1.0 and above)

CAUTION:

Prior to Apache Kafka version 3.1.0, the native OAuth Bearer Token authentication supported only unsecured JWT tokens which were not suitable for production environments, therefore Streaming Data Manager used its own OAuth implementation instead.

To enable OAuth Bearer Token Authentication for pre 3.1.0 Kafka versions (using the Streaming Data Manager OAuth plugin), see OAuth Bearer Token Authentication for listeners (Apache Kafka pre 3.1.0).

This scenario covers using Kafka ACLs with a third-party identity provider via OAuth 2.0 Bearer Token based authentication. Starting from Apache Kafka version 3.1.0, Streaming Data Manager relies on Apache Kafka’s native OAuth Bearer Token authentication support introduced by KIP-768 for both external listeners and internal listeners.

Since the workload has to provide a valid JWT/Bearer Token for authentication, it is required to be capable of OAuth 2.0.

Note: Since Streaming Data Manager ensures TLS communication via Istio, the OAuth must be configured in PLAINTEXT mode.

Prerequisites

To use Kafka ACLs with Istio mTLS, you need:

  • a Kubernetes cluster (version 1.19 and above), with
  • at least 12 vCPU and 12 GB of memory, and
  • with the capability to provision LoadBalancer Kubernetes services.
  • A Kafka cluster.

External listener

  1. Enable ACLs and configure an external listener using Streaming Data Manager. Complete the following steps:

    1. Verify that your deployed Kafka cluster is up and running:

      supertubes cluster get --namespace <namespace-of-your-cluster> --kafka-cluster <name-of-your-kafka-cluster> --kubeconfig <path-to-kubeconfig-file>
      

      Expected output:

      Namespace  Name   State           Image                               Alerts  Cruise Control Topic Status  Rolling Upgrade Errors  Rolling Upgrade Last Success
      kafka      kafka  ClusterRunning  banzaicloud/kafka:3.1.0  0       CruiseControlTopicReady      0
      
    2. Enable ACLs and configure an external listener. The deployed Kafka cluster has no ACLs, and external access is disabled by default. Enable them by applying the following changes:

      supertubes cluster update --namespace kafka --kafka-cluster kafka --kubeconfig <path-to-kubeconfig-file> -f -<<EOF
      apiVersion: kafka.banzaicloud.io/v1beta1
      kind: KafkaCluster
      spec:
        ingressController: "istioingress"
        istioIngressConfig:
          gatewayConfig:
            mode: PASSTHROUGH
        readOnlyConfig: |   
          auto.create.topics.enable=false
          offsets.topic.replication.factor=2
          authorizer.class.name=kafka.security.authorizer.AclAuthorizer
          allow.everyone.if.no.acl.found=false
      
          security.inter.broker.protocol=PLAINTEXT
      
          # OAUTH
          sasl.enabled.mechanisms=OAUTHBEARER
      
          # OAuth issuer token endpoint URL
          sasl.oauthbearer.token.endpoint.url=https://myidp.example.com/oauth2/default/v1/token
      
          # OAuth issuer's JWK Set endpoint URL from which to retrieve the set of JWKs managed by the provider; this can be a file://-based URL that points to a broker file system-accessible file-based copy of the JWKS data.
          sasl.oauthbearer.jwks.endpoint.url=https://myidp.example.com/oauth2/default/v1/keys
      
          listener.name.external.oauthbearer.sasl.login.callback.handler.class=org.apache.kafka.common.security.oauthbearer.secured.OAuthBearerLoginCallbackHandler
          listener.name.external.oauthbearer.sasl.server.callback.handler.class=org.apache.kafka.common.security.oauthbearer.secured.OAuthBearerValidatorCallbackHandler
          listener.name.external.oauthbearer.sasl.jaas.config=org.apache.kafka.common.security.oauthbearer.OAuthBearerLoginModule required \
            clientSecret="<client-secret>" \
            clientId="oauth-client-id";
      
          listener.name.oauth.oauthbearer.sasl.login.callback.handler.class=org.apache.kafka.common.security.oauthbearer.secured.OAuthBearerLoginCallbackHandler
          listener.name.oauth.oauthbearer.sasl.server.callback.handler.class=org.apache.kafka.common.security.oauthbearer.secured.OAuthBearerValidatorCallbackHandler
          listener.name.oauth.oauthbearer.sasl.jaas.config=org.apache.kafka.common.security.oauthbearer.OAuthBearerLoginModule required \
            clientSecret="<client-secret>" \
            clientId="oauth-client-id";
        listenersConfig:
          externalListeners:
          - type: "sasl_plaintext"
            name: "external"
            externalStartingPort: 19090
            containerPort: 9094
      EOF
      

      For details of the OAuth-related configuration options, see the KIP-768 and the Apache Kafka documentation.

    3. The update in the previous step triggers a rolling upgrade of the Kafka cluster. Verify that this is reflected in the state of the cluster.

      supertubes cluster get --namespace kafka --kafka-cluster kafka --kubeconfig <path-to-kubeconfig-file>
      

      Expected output:

      Namespace  Name   State                    Image                               Alerts  Cruise Control Topic Status  Rolling Upgrade Errors  Rolling Upgrade Last Success
      kafka      kafka  ClusterRollingUpgrading  banzaicloud/kafka:2.13-3.1.0  0       CruiseControlTopicReady      0
      
    4. Wait until the reconfiguration is finished and the cluster is in the ClusterRunning state. This can take a while, as the rolling upgrade applies changes on a broker-by-broker basis.

Internal listener

Perform the steps as described in the external listener part, but adjust the listenersConfig section:

  listenersConfig:
    ...
    internalListeners:
    ...
    - containerPort: 29094
      name: oauth
      type: sasl_plaintext
      usedForInnerBrokerCommunication: false

Try out

The following example uses Keycloak as the Identity Provider which supports OIDC.

Deploy and configure Keycloak

  1. Deploy Keycloak.

    helm repo add bitnami https://charts.bitnami.com/bitnami
    
    helm install idp bitnami/keycloak --namespace keycloak  --create-namespace --version 7.1.18 -f-<<EOF
    auth:
      adminUser: admin
      adminPassword: mypwd
    service:
      type: ClusterIP
    EOF
    
  2. Import the Kafka realm into Keycloak.

    1. Run the following command:

      kubectl port-forward -n keycloak svc/idp-keycloak 7070:80
      
    2. Download the following JSON file.

      {
          "id": "kafka",
          "realm": "kafka",
          "displayName": "Realm used for Kafka Cluster",
          "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,
          "enabled": true,
          "sslRequired": "external",
          "registrationAllowed": false,
          "registrationEmailAsUsername": false,
          "rememberMe": false,
          "verifyEmail": false,
          "loginWithEmailAllowed": true,
          "duplicateEmailsAllowed": false,
          "resetPasswordAllowed": false,
          "editUsernameAllowed": false,
          "bruteForceProtected": false,
          "permanentLockout": false,
          "maxFailureWaitSeconds": 900,
          "minimumQuickLoginWaitSeconds": 60,
          "waitIncrementSeconds": 60,
          "quickLoginCheckMilliSeconds": 1000,
          "maxDeltaTimeSeconds": 43200,
          "failureFactor": 30,
          "roles": {
            "realm": [
              {
                "id": "c967fdc3-7e02-4ed9-b593-c4ef5eec16f1",
                "name": "uma_authorization",
                "description": "${role_uma_authorization}",
                "composite": false,
                "clientRole": false,
                "containerId": "kafka",
                "attributes": {}
              },
              {
                "id": "5318117e-76ca-479d-a051-c0e380e5ad1f",
                "name": "offline_access",
                "description": "${role_offline-access}",
                "composite": false,
                "clientRole": false,
                "containerId": "kafka",
                "attributes": {}
              }
            ],
            "client": {
              "realm-management": [
                {
                  "id": "cc2c6d65-e59f-4288-9d9a-4ac27fdfb696",
                  "name": "view-users",
                  "description": "${role_view-users}",
                  "composite": true,
                  "composites": {
                    "client": {
                      "realm-management": [
                        "query-users",
                        "query-groups"
                      ]
                    }
                  },
                  "clientRole": true,
                  "containerId": "1ae17554-0a59-4460-a023-af4d0f10c553",
                  "attributes": {}
                },
                {
                  "id": "89fc9614-87d4-41f7-9d44-21637fdd58f9",
                  "name": "impersonation",
                  "description": "${role_impersonation}",
                  "composite": false,
                  "clientRole": true,
                  "containerId": "1ae17554-0a59-4460-a023-af4d0f10c553",
                  "attributes": {}
                },
                {
                  "id": "e4ef1668-13bd-48ad-9e8a-31d1a1ed1725",
                  "name": "query-users",
                  "description": "${role_query-users}",
                  "composite": false,
                  "clientRole": true,
                  "containerId": "1ae17554-0a59-4460-a023-af4d0f10c553",
                  "attributes": {}
                },
                {
                  "id": "206ae497-1cf8-43d0-b91e-eda53baeb47f",
                  "name": "view-clients",
                  "description": "${role_view-clients}",
                  "composite": true,
                  "composites": {
                    "client": {
                      "realm-management": [
                        "query-clients"
                      ]
                    }
                  },
                  "clientRole": true,
                  "containerId": "1ae17554-0a59-4460-a023-af4d0f10c553",
                  "attributes": {}
                },
                {
                  "id": "9f5d6b15-23f6-44c1-8d87-122ebd28e03a",
                  "name": "query-realms",
                  "description": "${role_query-realms}",
                  "composite": false,
                  "clientRole": true,
                  "containerId": "1ae17554-0a59-4460-a023-af4d0f10c553",
                  "attributes": {}
                },
                {
                  "id": "53be567d-a4a7-4354-ba8f-edf9e0eb63a8",
                  "name": "view-events",
                  "description": "${role_view-events}",
                  "composite": false,
                  "clientRole": true,
                  "containerId": "1ae17554-0a59-4460-a023-af4d0f10c553",
                  "attributes": {}
                },
                {
                  "id": "850bcaf8-2c6d-4859-854e-3e9587647311",
                  "name": "manage-realm",
                  "description": "${role_manage-realm}",
                  "composite": false,
                  "clientRole": true,
                  "containerId": "1ae17554-0a59-4460-a023-af4d0f10c553",
                  "attributes": {}
                },
                {
                  "id": "a3a88fc7-02ee-48c9-8826-cf43b08b9eb8",
                  "name": "realm-admin",
                  "description": "${role_realm-admin}",
                  "composite": true,
                  "composites": {
                    "client": {
                      "realm-management": [
                        "view-users",
                        "impersonation",
                        "view-clients",
                        "query-users",
                        "view-events",
                        "query-realms",
                        "manage-realm",
                        "query-clients",
                        "manage-authorization",
                        "manage-identity-providers",
                        "query-groups",
                        "view-identity-providers",
                        "create-client",
                        "manage-clients",
                        "view-realm",
                        "manage-events",
                        "view-authorization",
                        "manage-users"
                      ]
                    }
                  },
                  "clientRole": true,
                  "containerId": "1ae17554-0a59-4460-a023-af4d0f10c553",
                  "attributes": {}
                },
                {
                  "id": "e8f07ab6-23f7-461f-bc36-f9231d861d89",
                  "name": "query-clients",
                  "description": "${role_query-clients}",
                  "composite": false,
                  "clientRole": true,
                  "containerId": "1ae17554-0a59-4460-a023-af4d0f10c553",
                  "attributes": {}
                },
                {
                  "id": "bbd3bdcd-5032-42c4-b518-be93483cd298",
                  "name": "manage-authorization",
                  "description": "${role_manage-authorization}",
                  "composite": false,
                  "clientRole": true,
                  "containerId": "1ae17554-0a59-4460-a023-af4d0f10c553",
                  "attributes": {}
                },
                {
                  "id": "8c5cb8da-43f2-4408-b032-b189b41d9584",
                  "name": "manage-identity-providers",
                  "description": "${role_manage-identity-providers}",
                  "composite": false,
                  "clientRole": true,
                  "containerId": "1ae17554-0a59-4460-a023-af4d0f10c553",
                  "attributes": {}
                },
                {
                  "id": "ba496bdd-c954-43f9-b59b-ace3226c5770",
                  "name": "query-groups",
                  "description": "${role_query-groups}",
                  "composite": false,
                  "clientRole": true,
                  "containerId": "1ae17554-0a59-4460-a023-af4d0f10c553",
                  "attributes": {}
                },
                {
                  "id": "e4a7c6c0-7f53-4717-a301-389dd018d2b2",
                  "name": "create-client",
                  "description": "${role_create-client}",
                  "composite": false,
                  "clientRole": true,
                  "containerId": "1ae17554-0a59-4460-a023-af4d0f10c553",
                  "attributes": {}
                },
                {
                  "id": "f8c08cce-b923-4b3e-aa0b-09d242d1c802",
                  "name": "manage-clients",
                  "description": "${role_manage-clients}",
                  "composite": false,
                  "clientRole": true,
                  "containerId": "1ae17554-0a59-4460-a023-af4d0f10c553",
                  "attributes": {}
                },
                {
                  "id": "665bc1b8-8434-4b3f-a844-e708caa2c2ed",
                  "name": "view-identity-providers",
                  "description": "${role_view-identity-providers}",
                  "composite": false,
                  "clientRole": true,
                  "containerId": "1ae17554-0a59-4460-a023-af4d0f10c553",
                  "attributes": {}
                },
                {
                  "id": "a5f27ec2-6caf-4fc8-91dc-ed0fce9e2e7d",
                  "name": "view-realm",
                  "description": "${role_view-realm}",
                  "composite": false,
                  "clientRole": true,
                  "containerId": "1ae17554-0a59-4460-a023-af4d0f10c553",
                  "attributes": {}
                },
                {
                  "id": "abd6c29b-7d82-4860-b7da-2f4d0527ef95",
                  "name": "manage-events",
                  "description": "${role_manage-events}",
                  "composite": false,
                  "clientRole": true,
                  "containerId": "1ae17554-0a59-4460-a023-af4d0f10c553",
                  "attributes": {}
                },
                {
                  "id": "eb9bc246-7bce-4020-aeb2-7e2500e4e08a",
                  "name": "manage-users",
                  "description": "${role_manage-users}",
                  "composite": false,
                  "clientRole": true,
                  "containerId": "1ae17554-0a59-4460-a023-af4d0f10c553",
                  "attributes": {}
                },
                {
                  "id": "c70caa9e-a1ee-4cb3-8d04-f726917a7965",
                  "name": "view-authorization",
                  "description": "${role_view-authorization}",
                  "composite": false,
                  "clientRole": true,
                  "containerId": "1ae17554-0a59-4460-a023-af4d0f10c553",
                  "attributes": {}
                }
              ],
              "kafka-broker": [],
              "kafka-consumer": [],
              "security-admin-console": [],
              "kafka-producer": [],
              "admin-cli": [],
              "account-console": [],
              "broker": [
                {
                  "id": "37a10e35-8af5-43c1-a42a-07ef12a84074",
                  "name": "read-token",
                  "description": "${role_read-token}",
                  "composite": false,
                  "clientRole": true,
                  "containerId": "e0e804ca-e7fd-4723-9f29-9e6da135e23e",
                  "attributes": {}
                }
              ],
              "account": [
                {
                  "id": "cc4a4f4e-9817-4805-b7c7-c55dd5405677",
                  "name": "manage-account",
                  "description": "${role_manage-account}",
                  "composite": true,
                  "composites": {
                    "client": {
                      "account": [
                        "manage-account-links"
                      ]
                    }
                  },
                  "clientRole": true,
                  "containerId": "cd96446e-2bf8-4ad4-9343-924b7a278edd",
                  "attributes": {}
                },
                {
                  "id": "f5c8f37f-a5e7-41f7-87ce-f787b9f7c943",
                  "name": "view-consent",
                  "description": "${role_view-consent}",
                  "composite": false,
                  "clientRole": true,
                  "containerId": "cd96446e-2bf8-4ad4-9343-924b7a278edd",
                  "attributes": {}
                },
                {
                  "id": "5ba76c76-9ca9-49cd-b8a3-8fe00868003a",
                  "name": "view-applications",
                  "description": "${role_view-applications}",
                  "composite": false,
                  "clientRole": true,
                  "containerId": "cd96446e-2bf8-4ad4-9343-924b7a278edd",
                  "attributes": {}
                },
                {
                  "id": "9fdc221f-114b-41f7-9100-63565d8587ce",
                  "name": "delete-account",
                  "description": "${role_delete-account}",
                  "composite": false,
                  "clientRole": true,
                  "containerId": "cd96446e-2bf8-4ad4-9343-924b7a278edd",
                  "attributes": {}
                },
                {
                  "id": "ece6b86d-a27d-45fa-812a-5617d8d62331",
                  "name": "view-profile",
                  "description": "${role_view-profile}",
                  "composite": false,
                  "clientRole": true,
                  "containerId": "cd96446e-2bf8-4ad4-9343-924b7a278edd",
                  "attributes": {}
                },
                {
                  "id": "1a3a60d7-4208-47c9-b677-0c1667a49858",
                  "name": "manage-account-links",
                  "description": "${role_manage-account-links}",
                  "composite": false,
                  "clientRole": true,
                  "containerId": "cd96446e-2bf8-4ad4-9343-924b7a278edd",
                  "attributes": {}
                },
                {
                  "id": "69def05c-1c03-4919-90c2-8bb7cde12cb9",
                  "name": "manage-consent",
                  "description": "${role_manage-consent}",
                  "composite": true,
                  "composites": {
                    "client": {
                      "account": [
                        "view-consent"
                      ]
                    }
                  },
                  "clientRole": true,
                  "containerId": "cd96446e-2bf8-4ad4-9343-924b7a278edd",
                  "attributes": {}
                }
              ]
            }
          },
          "groups": [],
          "defaultRoles": [
            "uma_authorization",
            "offline_access"
          ],
          "requiredCredentials": [
            "password"
          ],
          "otpPolicyType": "totp",
          "otpPolicyAlgorithm": "HmacSHA1",
          "otpPolicyInitialCounter": 0,
          "otpPolicyDigits": 6,
          "otpPolicyLookAheadWindow": 1,
          "otpPolicyPeriod": 30,
          "otpSupportedApplications": [
            "FreeOTP",
            "Google Authenticator"
          ],
          "webAuthnPolicyRpEntityName": "keycloak",
          "webAuthnPolicySignatureAlgorithms": [
            "ES256"
          ],
          "webAuthnPolicyRpId": "",
          "webAuthnPolicyAttestationConveyancePreference": "not specified",
          "webAuthnPolicyAuthenticatorAttachment": "not specified",
          "webAuthnPolicyRequireResidentKey": "not specified",
          "webAuthnPolicyUserVerificationRequirement": "not specified",
          "webAuthnPolicyCreateTimeout": 0,
          "webAuthnPolicyAvoidSameAuthenticatorRegister": false,
          "webAuthnPolicyAcceptableAaguids": [],
          "webAuthnPolicyPasswordlessRpEntityName": "keycloak",
          "webAuthnPolicyPasswordlessSignatureAlgorithms": [
            "ES256"
          ],
          "webAuthnPolicyPasswordlessRpId": "",
          "webAuthnPolicyPasswordlessAttestationConveyancePreference": "not specified",
          "webAuthnPolicyPasswordlessAuthenticatorAttachment": "not specified",
          "webAuthnPolicyPasswordlessRequireResidentKey": "not specified",
          "webAuthnPolicyPasswordlessUserVerificationRequirement": "not specified",
          "webAuthnPolicyPasswordlessCreateTimeout": 0,
          "webAuthnPolicyPasswordlessAvoidSameAuthenticatorRegister": false,
          "webAuthnPolicyPasswordlessAcceptableAaguids": [],
          "users": [
            {
              "id": "e4ef5a5c-9de6-44b4-b4c6-555fd79ae8e8",
              "createdTimestamp": 1616172318026,
              "username": "service-account-kafka-broker",
              "enabled": true,
              "totp": false,
              "emailVerified": false,
              "serviceAccountClientId": "kafka-broker",
              "disableableCredentialTypes": [],
              "requiredActions": [],
              "realmRoles": [
                "uma_authorization",
                "offline_access"
              ],
              "clientRoles": {
                "account": [
                  "manage-account",
                  "view-profile"
                ]
              },
              "notBefore": 0,
              "groups": []
            },
            {
              "id": "0aa61449-e970-4854-ac2a-f22e664b0110",
              "createdTimestamp": 1616172407739,
              "username": "service-account-kafka-consumer",
              "enabled": true,
              "totp": false,
              "emailVerified": false,
              "serviceAccountClientId": "kafka-consumer",
              "disableableCredentialTypes": [],
              "requiredActions": [],
              "realmRoles": [
                "uma_authorization",
                "offline_access"
              ],
              "clientRoles": {
                "account": [
                  "manage-account",
                  "view-profile"
                ]
              },
              "notBefore": 0,
              "groups": []
            },
            {
              "id": "4c01f71e-f6a8-46e6-99f4-379db03c4362",
              "createdTimestamp": 1616172472795,
              "username": "service-account-kafka-producer",
              "enabled": true,
              "totp": false,
              "emailVerified": false,
              "serviceAccountClientId": "kafka-producer",
              "disableableCredentialTypes": [],
              "requiredActions": [],
              "realmRoles": [
                "uma_authorization",
                "offline_access"
              ],
              "clientRoles": {
                "account": [
                  "manage-account",
                  "view-profile"
                ]
              },
              "notBefore": 0,
              "groups": []
            }
          ],
          "scopeMappings": [
            {
              "clientScope": "offline_access",
              "roles": [
                "offline_access"
              ]
            }
          ],
          "clientScopeMappings": {
            "account": [
              {
                "client": "account-console",
                "roles": [
                  "manage-account"
                ]
              }
            ]
          },
          "clients": [
            {
              "id": "cd96446e-2bf8-4ad4-9343-924b7a278edd",
              "clientId": "account",
              "name": "${client_account}",
              "rootUrl": "${authBaseUrl}",
              "baseUrl": "/realms/kafka/account/",
              "surrogateAuthRequired": false,
              "enabled": true,
              "alwaysDisplayInConsole": false,
              "clientAuthenticatorType": "client-secret",
              "secret": "**********",
              "defaultRoles": [
                "manage-account",
                "view-profile"
              ],
              "redirectUris": [
                "/realms/kafka/account/*"
              ],
              "webOrigins": [],
              "notBefore": 0,
              "bearerOnly": false,
              "consentRequired": false,
              "standardFlowEnabled": true,
              "implicitFlowEnabled": false,
              "directAccessGrantsEnabled": false,
              "serviceAccountsEnabled": false,
              "publicClient": false,
              "frontchannelLogout": false,
              "protocol": "openid-connect",
              "attributes": {},
              "authenticationFlowBindingOverrides": {},
              "fullScopeAllowed": false,
              "nodeReRegistrationTimeout": 0,
              "defaultClientScopes": [
                "web-origins",
                "role_list",
                "roles",
                "profile",
                "email"
              ],
              "optionalClientScopes": [
                "address",
                "phone",
                "offline_access",
                "microprofile-jwt"
              ]
            },
            {
              "id": "c572ea42-9e1f-4a0d-ad8a-f5a407bcd3e1",
              "clientId": "account-console",
              "name": "${client_account-console}",
              "rootUrl": "${authBaseUrl}",
              "baseUrl": "/realms/kafka/account/",
              "surrogateAuthRequired": false,
              "enabled": true,
              "alwaysDisplayInConsole": false,
              "clientAuthenticatorType": "client-secret",
              "secret": "**********",
              "redirectUris": [
                "/realms/kafka/account/*"
              ],
              "webOrigins": [],
              "notBefore": 0,
              "bearerOnly": false,
              "consentRequired": false,
              "standardFlowEnabled": true,
              "implicitFlowEnabled": false,
              "directAccessGrantsEnabled": false,
              "serviceAccountsEnabled": false,
              "publicClient": true,
              "frontchannelLogout": false,
              "protocol": "openid-connect",
              "attributes": {
                "pkce.code.challenge.method": "S256"
              },
              "authenticationFlowBindingOverrides": {},
              "fullScopeAllowed": false,
              "nodeReRegistrationTimeout": 0,
              "protocolMappers": [
                {
                  "id": "333bc21a-d586-426b-aaa0-51ea59deeb3d",
                  "name": "audience resolve",
                  "protocol": "openid-connect",
                  "protocolMapper": "oidc-audience-resolve-mapper",
                  "consentRequired": false,
                  "config": {}
                }
              ],
              "defaultClientScopes": [
                "web-origins",
                "role_list",
                "roles",
                "profile",
                "email"
              ],
              "optionalClientScopes": [
                "address",
                "phone",
                "offline_access",
                "microprofile-jwt"
              ]
            },
            {
              "id": "9ee5a26c-04d1-4694-9aa4-befccf607332",
              "clientId": "admin-cli",
              "name": "${client_admin-cli}",
              "surrogateAuthRequired": false,
              "enabled": true,
              "alwaysDisplayInConsole": false,
              "clientAuthenticatorType": "client-secret",
              "secret": "**********",
              "redirectUris": [],
              "webOrigins": [],
              "notBefore": 0,
              "bearerOnly": false,
              "consentRequired": false,
              "standardFlowEnabled": false,
              "implicitFlowEnabled": false,
              "directAccessGrantsEnabled": true,
              "serviceAccountsEnabled": false,
              "publicClient": true,
              "frontchannelLogout": false,
              "protocol": "openid-connect",
              "attributes": {},
              "authenticationFlowBindingOverrides": {},
              "fullScopeAllowed": false,
              "nodeReRegistrationTimeout": 0,
              "defaultClientScopes": [
                "web-origins",
                "role_list",
                "roles",
                "profile",
                "email"
              ],
              "optionalClientScopes": [
                "address",
                "phone",
                "offline_access",
                "microprofile-jwt"
              ]
            },
            {
              "id": "e0e804ca-e7fd-4723-9f29-9e6da135e23e",
              "clientId": "broker",
              "name": "${client_broker}",
              "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": false,
              "publicClient": false,
              "frontchannelLogout": false,
              "protocol": "openid-connect",
              "attributes": {},
              "authenticationFlowBindingOverrides": {},
              "fullScopeAllowed": false,
              "nodeReRegistrationTimeout": 0,
              "defaultClientScopes": [
                "web-origins",
                "role_list",
                "roles",
                "profile",
                "email"
              ],
              "optionalClientScopes": [
                "address",
                "phone",
                "offline_access",
                "microprofile-jwt"
              ]
            },
            {
              "id": "3725d980-a1bc-4fc2-aa19-b86c5fa79e59",
              "clientId": "kafka-broker",
              "surrogateAuthRequired": false,
              "enabled": true,
              "alwaysDisplayInConsole": false,
              "clientAuthenticatorType": "client-secret",
              "secret": "4d63e29f-3f81-4d69-92b5-f2d7ffa627f9",
              "redirectUris": [],
              "webOrigins": [],
              "notBefore": 0,
              "bearerOnly": false,
              "consentRequired": false,
              "standardFlowEnabled": false,
              "implicitFlowEnabled": false,
              "directAccessGrantsEnabled": true,
              "serviceAccountsEnabled": true,
              "publicClient": false,
              "frontchannelLogout": false,
              "protocol": "openid-connect",
              "attributes": {
                "saml.assertion.signature": "false",
                "access.token.lifespan": "3600",
                "saml.force.post.binding": "false",
                "saml.multivalued.roles": "false",
                "saml.encrypt": "false",
                "backchannel.logout.revoke.offline.tokens": "false",
                "saml.server.signature": "false",
                "saml.server.signature.keyinfo.ext": "false",
                "exclude.session.state.from.auth.response": "false",
                "backchannel.logout.session.required": "true",
                "client_credentials.use_refresh_token": "false",
                "saml_force_name_id_format": "false",
                "saml.client.signature": "false",
                "tls.client.certificate.bound.access.tokens": "false",
                "saml.authnstatement": "false",
                "display.on.consent.screen": "false",
                "saml.onetimeuse.condition": "false"
              },
              "authenticationFlowBindingOverrides": {},
              "fullScopeAllowed": true,
              "nodeReRegistrationTimeout": -1,
              "protocolMappers": [
                {
                  "id": "802c56c4-d1b8-44f2-9d8b-89681d1e35a1",
                  "name": "Client Host",
                  "protocol": "openid-connect",
                  "protocolMapper": "oidc-usersessionmodel-note-mapper",
                  "consentRequired": false,
                  "config": {
                    "user.session.note": "clientHost",
                    "userinfo.token.claim": "true",
                    "id.token.claim": "true",
                    "access.token.claim": "true",
                    "claim.name": "clientHost",
                    "jsonType.label": "String"
                  }
                },
                {
                  "id": "e0c9f0a7-ea5f-415c-934a-b8a79456cb7e",
                  "name": "Client IP Address",
                  "protocol": "openid-connect",
                  "protocolMapper": "oidc-usersessionmodel-note-mapper",
                  "consentRequired": false,
                  "config": {
                    "user.session.note": "clientAddress",
                    "userinfo.token.claim": "true",
                    "id.token.claim": "true",
                    "access.token.claim": "true",
                    "claim.name": "clientAddress",
                    "jsonType.label": "String"
                  }
                },
                {
                  "id": "11a1804d-4dbb-43d9-8ef7-045fcc7e7935",
                  "name": "Client ID",
                  "protocol": "openid-connect",
                  "protocolMapper": "oidc-usersessionmodel-note-mapper",
                  "consentRequired": false,
                  "config": {
                    "user.session.note": "clientId",
                    "userinfo.token.claim": "true",
                    "id.token.claim": "true",
                    "access.token.claim": "true",
                    "claim.name": "clientId",
                    "jsonType.label": "String"
                  }
                }
              ],
              "defaultClientScopes": [
                "web-origins",
                "role_list",
                "kafka:read",
                "roles",
                "profile",
                "email",
                "kafka:write"
              ],
              "optionalClientScopes": [
                "address",
                "phone",
                "offline_access",
                "microprofile-jwt"
              ]
            },
            {
              "id": "a29394c3-c89a-4954-8bbd-effdcd665ba9",
              "clientId": "kafka-consumer",
              "name": "Kafka Consumer",
              "description": "Kafka Consumer",
              "surrogateAuthRequired": false,
              "enabled": true,
              "alwaysDisplayInConsole": false,
              "clientAuthenticatorType": "client-secret",
              "secret": "4090cfea-44c1-470b-a610-3a7b0f4366ae",
              "redirectUris": [],
              "webOrigins": [],
              "notBefore": 0,
              "bearerOnly": false,
              "consentRequired": false,
              "standardFlowEnabled": false,
              "implicitFlowEnabled": false,
              "directAccessGrantsEnabled": true,
              "serviceAccountsEnabled": true,
              "publicClient": false,
              "frontchannelLogout": false,
              "protocol": "openid-connect",
              "attributes": {
                "saml.assertion.signature": "false",
                "access.token.lifespan": "3600",
                "saml.force.post.binding": "false",
                "saml.multivalued.roles": "false",
                "saml.encrypt": "false",
                "backchannel.logout.revoke.offline.tokens": "false",
                "saml.server.signature": "false",
                "saml.server.signature.keyinfo.ext": "false",
                "exclude.session.state.from.auth.response": "false",
                "backchannel.logout.session.required": "true",
                "client_credentials.use_refresh_token": "false",
                "saml_force_name_id_format": "false",
                "saml.client.signature": "false",
                "tls.client.certificate.bound.access.tokens": "false",
                "saml.authnstatement": "false",
                "display.on.consent.screen": "false",
                "saml.onetimeuse.condition": "false"
              },
              "authenticationFlowBindingOverrides": {},
              "fullScopeAllowed": true,
              "nodeReRegistrationTimeout": -1,
              "protocolMappers": [
                {
                  "id": "8befc2af-1762-4239-b98e-2849a675311a",
                  "name": "Client Host",
                  "protocol": "openid-connect",
                  "protocolMapper": "oidc-usersessionmodel-note-mapper",
                  "consentRequired": false,
                  "config": {
                    "user.session.note": "clientHost",
                    "userinfo.token.claim": "true",
                    "id.token.claim": "true",
                    "access.token.claim": "true",
                    "claim.name": "clientHost",
                    "jsonType.label": "String"
                  }
                },
                {
                  "id": "8caee91b-0da7-4a5f-b4e7-39f8babf3600",
                  "name": "Client IP Address",
                  "protocol": "openid-connect",
                  "protocolMapper": "oidc-usersessionmodel-note-mapper",
                  "consentRequired": false,
                  "config": {
                    "user.session.note": "clientAddress",
                    "userinfo.token.claim": "true",
                    "id.token.claim": "true",
                    "access.token.claim": "true",
                    "claim.name": "clientAddress",
                    "jsonType.label": "String"
                  }
                },
                {
                  "id": "1d09a003-b310-430f-8308-65649f71e622",
                  "name": "Client ID",
                  "protocol": "openid-connect",
                  "protocolMapper": "oidc-usersessionmodel-note-mapper",
                  "consentRequired": false,
                  "config": {
                    "user.session.note": "clientId",
                    "userinfo.token.claim": "true",
                    "id.token.claim": "true",
                    "access.token.claim": "true",
                    "claim.name": "clientId",
                    "jsonType.label": "String"
                  }
                }
              ],
              "defaultClientScopes": [
                "web-origins",
                "role_list",
                "roles",
                "profile",
                "email"
              ],
              "optionalClientScopes": [
                "address",
                "kafka:read",
                "phone",
                "offline_access",
                "microprofile-jwt",
                "kafka:write"
              ]
            },
            {
              "id": "64e49ef6-9c1d-4050-95b2-7801cee1a428",
              "clientId": "kafka-producer",
              "name": "Kafka Producer",
              "description": "Kafka Producer",
              "surrogateAuthRequired": false,
              "enabled": true,
              "alwaysDisplayInConsole": false,
              "clientAuthenticatorType": "client-secret",
              "secret": "85cb47f8-6c76-43f0-bbe2-a66f7f86395a",
              "redirectUris": [],
              "webOrigins": [],
              "notBefore": 0,
              "bearerOnly": false,
              "consentRequired": false,
              "standardFlowEnabled": false,
              "implicitFlowEnabled": false,
              "directAccessGrantsEnabled": true,
              "serviceAccountsEnabled": true,
              "publicClient": false,
              "frontchannelLogout": false,
              "protocol": "openid-connect",
              "attributes": {
                "saml.assertion.signature": "false",
                "access.token.lifespan": "3600",
                "saml.force.post.binding": "false",
                "saml.multivalued.roles": "false",
                "saml.encrypt": "false",
                "backchannel.logout.revoke.offline.tokens": "false",
                "saml.server.signature": "false",
                "saml.server.signature.keyinfo.ext": "false",
                "exclude.session.state.from.auth.response": "false",
                "backchannel.logout.session.required": "true",
                "client_credentials.use_refresh_token": "false",
                "saml_force_name_id_format": "false",
                "saml.client.signature": "false",
                "tls.client.certificate.bound.access.tokens": "false",
                "saml.authnstatement": "false",
                "display.on.consent.screen": "false",
                "saml.onetimeuse.condition": "false"
              },
              "authenticationFlowBindingOverrides": {},
              "fullScopeAllowed": true,
              "nodeReRegistrationTimeout": -1,
              "protocolMappers": [
                {
                  "id": "730e4dba-2a95-42a8-94b0-3040c2488c27",
                  "name": "Client IP Address",
                  "protocol": "openid-connect",
                  "protocolMapper": "oidc-usersessionmodel-note-mapper",
                  "consentRequired": false,
                  "config": {
                    "user.session.note": "clientAddress",
                    "userinfo.token.claim": "true",
                    "id.token.claim": "true",
                    "access.token.claim": "true",
                    "claim.name": "clientAddress",
                    "jsonType.label": "String"
                  }
                },
                {
                  "id": "da52bd51-1444-4b90-a941-cf61dfccba26",
                  "name": "Client Host",
                  "protocol": "openid-connect",
                  "protocolMapper": "oidc-usersessionmodel-note-mapper",
                  "consentRequired": false,
                  "config": {
                    "user.session.note": "clientHost",
                    "userinfo.token.claim": "true",
                    "id.token.claim": "true",
                    "access.token.claim": "true",
                    "claim.name": "clientHost",
                    "jsonType.label": "String"
                  }
                },
                {
                  "id": "8040c1f9-ae7d-4fb1-8395-2f6b4dc0dfd7",
                  "name": "Client ID",
                  "protocol": "openid-connect",
                  "protocolMapper": "oidc-usersessionmodel-note-mapper",
                  "consentRequired": false,
                  "config": {
                    "user.session.note": "clientId",
                    "userinfo.token.claim": "true",
                    "id.token.claim": "true",
                    "access.token.claim": "true",
                    "claim.name": "clientId",
                    "jsonType.label": "String"
                  }
                }
              ],
              "defaultClientScopes": [
                "web-origins",
                "role_list",
                "roles",
                "profile",
                "email"
              ],
              "optionalClientScopes": [
                "address",
                "kafka:read",
                "phone",
                "offline_access",
                "microprofile-jwt",
                "kafka:write"
              ]
            },
            {
              "id": "1ae17554-0a59-4460-a023-af4d0f10c553",
              "clientId": "realm-management",
              "name": "${client_realm-management}",
              "surrogateAuthRequired": false,
              "enabled": true,
              "alwaysDisplayInConsole": false,
              "clientAuthenticatorType": "client-secret",
              "secret": "**********",
              "redirectUris": [],
              "webOrigins": [],
              "notBefore": 0,
              "bearerOnly": true,
              "consentRequired": false,
              "standardFlowEnabled": true,
              "implicitFlowEnabled": false,
              "directAccessGrantsEnabled": false,
              "serviceAccountsEnabled": false,
              "publicClient": false,
              "frontchannelLogout": false,
              "protocol": "openid-connect",
              "attributes": {},
              "authenticationFlowBindingOverrides": {},
              "fullScopeAllowed": false,
              "nodeReRegistrationTimeout": 0,
              "defaultClientScopes": [
                "web-origins",
                "role_list",
                "roles",
                "profile",
                "email"
              ],
              "optionalClientScopes": [
                "address",
                "phone",
                "offline_access",
                "microprofile-jwt"
              ]
            },
            {
              "id": "59e2b1b0-ff84-4f4e-87f0-855917b6523e",
              "clientId": "security-admin-console",
              "name": "${client_security-admin-console}",
              "rootUrl": "${authAdminUrl}",
              "baseUrl": "/admin/kafka/console/",
              "surrogateAuthRequired": false,
              "enabled": true,
              "alwaysDisplayInConsole": false,
              "clientAuthenticatorType": "client-secret",
              "secret": "**********",
              "redirectUris": [
                "/admin/kafka/console/*"
              ],
              "webOrigins": [
                "+"
              ],
              "notBefore": 0,
              "bearerOnly": false,
              "consentRequired": false,
              "standardFlowEnabled": true,
              "implicitFlowEnabled": false,
              "directAccessGrantsEnabled": false,
              "serviceAccountsEnabled": false,
              "publicClient": true,
              "frontchannelLogout": false,
              "protocol": "openid-connect",
              "attributes": {
                "pkce.code.challenge.method": "S256"
              },
              "authenticationFlowBindingOverrides": {},
              "fullScopeAllowed": false,
              "nodeReRegistrationTimeout": 0,
              "protocolMappers": [
                {
                  "id": "2eda49fc-2423-49ba-9b86-fe175d6f7403",
                  "name": "locale",
                  "protocol": "openid-connect",
                  "protocolMapper": "oidc-usermodel-attribute-mapper",
                  "consentRequired": false,
                  "config": {
                    "userinfo.token.claim": "true",
                    "user.attribute": "locale",
                    "id.token.claim": "true",
                    "access.token.claim": "true",
                    "claim.name": "locale",
                    "jsonType.label": "String"
                  }
                }
              ],
              "defaultClientScopes": [
                "web-origins",
                "role_list",
                "roles",
                "profile",
                "email"
              ],
              "optionalClientScopes": [
                "address",
                "phone",
                "offline_access",
                "microprofile-jwt"
              ]
            }
          ],
          "clientScopes": [
            {
              "id": "76ab3c2e-eeff-4347-8f9f-4b6e4959f376",
              "name": "address",
              "description": "OpenID Connect built-in scope: address",
              "protocol": "openid-connect",
              "attributes": {
                "include.in.token.scope": "true",
                "display.on.consent.screen": "true",
                "consent.screen.text": "${addressScopeConsentText}"
              },
              "protocolMappers": [
                {
                  "id": "30fba530-155a-457b-9592-8b533c1ff03e",
                  "name": "address",
                  "protocol": "openid-connect",
                  "protocolMapper": "oidc-address-mapper",
                  "consentRequired": false,
                  "config": {
                    "user.attribute.formatted": "formatted",
                    "user.attribute.country": "country",
                    "user.attribute.postal_code": "postal_code",
                    "userinfo.token.claim": "true",
                    "user.attribute.street": "street",
                    "id.token.claim": "true",
                    "user.attribute.region": "region",
                    "access.token.claim": "true",
                    "user.attribute.locality": "locality"
                  }
                }
              ]
            },
            {
              "id": "988a5244-10a1-4360-9a06-a1b30e11cf28",
              "name": "email",
              "description": "OpenID Connect built-in scope: email",
              "protocol": "openid-connect",
              "attributes": {
                "include.in.token.scope": "true",
                "display.on.consent.screen": "true",
                "consent.screen.text": "${emailScopeConsentText}"
              },
              "protocolMappers": [
                {
                  "id": "bf6607d0-1e8f-4328-99b8-eee7bd69d709",
                  "name": "email",
                  "protocol": "openid-connect",
                  "protocolMapper": "oidc-usermodel-property-mapper",
                  "consentRequired": false,
                  "config": {
                    "userinfo.token.claim": "true",
                    "user.attribute": "email",
                    "id.token.claim": "true",
                    "access.token.claim": "true",
                    "claim.name": "email",
                    "jsonType.label": "String"
                  }
                },
                {
                  "id": "38c05289-88db-48b7-b9ac-357030caf9ff",
                  "name": "email verified",
                  "protocol": "openid-connect",
                  "protocolMapper": "oidc-usermodel-property-mapper",
                  "consentRequired": false,
                  "config": {
                    "userinfo.token.claim": "true",
                    "user.attribute": "emailVerified",
                    "id.token.claim": "true",
                    "access.token.claim": "true",
                    "claim.name": "email_verified",
                    "jsonType.label": "boolean"
                  }
                }
              ]
            },
            {
              "id": "a8a8d4cc-1e84-4f39-aa98-c07ddeb3927d",
              "name": "kafka:read",
              "description": "Read access for Kafka Cluster",
              "protocol": "openid-connect",
              "attributes": {
                "include.in.token.scope": "true",
                "display.on.consent.screen": "false"
              }
            },
            {
              "id": "067b2ea5-d956-400a-8754-084ce9bd7b8c",
              "name": "kafka:write",
              "description": "Write access for Kafka Cluster",
              "protocol": "openid-connect",
              "attributes": {
                "include.in.token.scope": "true",
                "display.on.consent.screen": "false"
              }
            },
            {
              "id": "f89ecc64-b226-4fcc-b834-432933bd3158",
              "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": "42505309-ff09-4ae7-abe8-3e8c09e3c47f",
                  "name": "groups",
                  "protocol": "openid-connect",
                  "protocolMapper": "oidc-usermodel-realm-role-mapper",
                  "consentRequired": false,
                  "config": {
                    "multivalued": "true",
                    "userinfo.token.claim": "true",
                    "user.attribute": "foo",
                    "id.token.claim": "true",
                    "access.token.claim": "true",
                    "claim.name": "groups",
                    "jsonType.label": "String"
                  }
                },
                {
                  "id": "ad860625-1255-4418-a338-b1e439ac5ac1",
                  "name": "upn",
                  "protocol": "openid-connect",
                  "protocolMapper": "oidc-usermodel-property-mapper",
                  "consentRequired": false,
                  "config": {
                    "userinfo.token.claim": "true",
                    "user.attribute": "username",
                    "id.token.claim": "true",
                    "access.token.claim": "true",
                    "claim.name": "upn",
                    "jsonType.label": "String"
                  }
                }
              ]
            },
            {
              "id": "038284ce-46c9-47e6-a5ec-e5cc36ab5972",
              "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": "cff79b7b-7c36-4a1f-8e57-bda9ad8ed28f",
              "name": "phone",
              "description": "OpenID Connect built-in scope: phone",
              "protocol": "openid-connect",
              "attributes": {
                "include.in.token.scope": "true",
                "display.on.consent.screen": "true",
                "consent.screen.text": "${phoneScopeConsentText}"
              },
              "protocolMappers": [
                {
                  "id": "dc197102-3e13-4c12-acd7-5b96e64d83f2",
                  "name": "phone number",
                  "protocol": "openid-connect",
                  "protocolMapper": "oidc-usermodel-attribute-mapper",
                  "consentRequired": false,
                  "config": {
                    "userinfo.token.claim": "true",
                    "user.attribute": "phoneNumber",
                    "id.token.claim": "true",
                    "access.token.claim": "true",
                    "claim.name": "phone_number",
                    "jsonType.label": "String"
                  }
                },
                {
                  "id": "09936d17-672d-4884-ab2c-cd31d5d23907",
                  "name": "phone number verified",
                  "protocol": "openid-connect",
                  "protocolMapper": "oidc-usermodel-attribute-mapper",
                  "consentRequired": false,
                  "config": {
                    "userinfo.token.claim": "true",
                    "user.attribute": "phoneNumberVerified",
                    "id.token.claim": "true",
                    "access.token.claim": "true",
                    "claim.name": "phone_number_verified",
                    "jsonType.label": "boolean"
                  }
                }
              ]
            },
            {
              "id": "e506c266-9871-4730-b40c-63b372220c83",
              "name": "profile",
              "description": "OpenID Connect built-in scope: profile",
              "protocol": "openid-connect",
              "attributes": {
                "include.in.token.scope": "true",
                "display.on.consent.screen": "true",
                "consent.screen.text": "${profileScopeConsentText}"
              },
              "protocolMappers": [
                {
                  "id": "bdb33fcf-0835-450a-b473-0e55d113f2d7",
                  "name": "gender",
                  "protocol": "openid-connect",
                  "protocolMapper": "oidc-usermodel-attribute-mapper",
                  "consentRequired": false,
                  "config": {
                    "userinfo.token.claim": "true",
                    "user.attribute": "gender",
                    "id.token.claim": "true",
                    "access.token.claim": "true",
                    "claim.name": "gender",
                    "jsonType.label": "String"
                  }
                },
                {
                  "id": "fc9c45fb-ed45-4295-9afe-d07bd6a38831",
                  "name": "full name",
                  "protocol": "openid-connect",
                  "protocolMapper": "oidc-full-name-mapper",
                  "consentRequired": false,
                  "config": {
                    "id.token.claim": "true",
                    "access.token.claim": "true",
                    "userinfo.token.claim": "true"
                  }
                },
                {
                  "id": "e8941a2c-a1fa-46ab-ace6-bf1f02039099",
                  "name": "zoneinfo",
                  "protocol": "openid-connect",
                  "protocolMapper": "oidc-usermodel-attribute-mapper",
                  "consentRequired": false,
                  "config": {
                    "userinfo.token.claim": "true",
                    "user.attribute": "zoneinfo",
                    "id.token.claim": "true",
                    "access.token.claim": "true",
                    "claim.name": "zoneinfo",
                    "jsonType.label": "String"
                  }
                },
                {
                  "id": "3ebc63cd-5fc5-45a6-b0dc-4a0f95dc42b4",
                  "name": "given name",
                  "protocol": "openid-connect",
                  "protocolMapper": "oidc-usermodel-property-mapper",
                  "consentRequired": false,
                  "config": {
                    "userinfo.token.claim": "true",
                    "user.attribute": "firstName",
                    "id.token.claim": "true",
                    "access.token.claim": "true",
                    "claim.name": "given_name",
                    "jsonType.label": "String"
                  }
                },
                {
                  "id": "118b11f6-b3d6-4b08-9840-960ecadf8388",
                  "name": "username",
                  "protocol": "openid-connect",
                  "protocolMapper": "oidc-usermodel-property-mapper",
                  "consentRequired": false,
                  "config": {
                    "userinfo.token.claim": "true",
                    "user.attribute": "username",
                    "id.token.claim": "true",
                    "access.token.claim": "true",
                    "claim.name": "preferred_username",
                    "jsonType.label": "String"
                  }
                },
                {
                  "id": "ac4ac3dd-24f0-43df-af62-86d08948ad7b",
                  "name": "middle name",
                  "protocol": "openid-connect",
                  "protocolMapper": "oidc-usermodel-attribute-mapper",
                  "consentRequired": false,
                  "config": {
                    "userinfo.token.claim": "true",
                    "user.attribute": "middleName",
                    "id.token.claim": "true",
                    "access.token.claim": "true",
                    "claim.name": "middle_name",
                    "jsonType.label": "String"
                  }
                },
                {
                  "id": "25e01479-a6f4-4b87-b1ba-4401abf56f38",
                  "name": "locale",
                  "protocol": "openid-connect",
                  "protocolMapper": "oidc-usermodel-attribute-mapper",
                  "consentRequired": false,
                  "config": {
                    "userinfo.token.claim": "true",
                    "user.attribute": "locale",
                    "id.token.claim": "true",
                    "access.token.claim": "true",
                    "claim.name": "locale",
                    "jsonType.label": "String"
                  }
                },
                {
                  "id": "153094d7-7c66-41d1-b431-13ef26841729",
                  "name": "picture",
                  "protocol": "openid-connect",
                  "protocolMapper": "oidc-usermodel-attribute-mapper",
                  "consentRequired": false,
                  "config": {
                    "userinfo.token.claim": "true",
                    "user.attribute": "picture",
                    "id.token.claim": "true",
                    "access.token.claim": "true",
                    "claim.name": "picture",
                    "jsonType.label": "String"
                  }
                },
                {
                  "id": "1e217306-9777-44ac-945a-7fdd880d3e74",
                  "name": "website",
                  "protocol": "openid-connect",
                  "protocolMapper": "oidc-usermodel-attribute-mapper",
                  "consentRequired": false,
                  "config": {
                    "userinfo.token.claim": "true",
                    "user.attribute": "website",
                    "id.token.claim": "true",
                    "access.token.claim": "true",
                    "claim.name": "website",
                    "jsonType.label": "String"
                  }
                },
                {
                  "id": "d6b54763-45f2-4361-8de2-bf8d1ac774f4",
                  "name": "nickname",
                  "protocol": "openid-connect",
                  "protocolMapper": "oidc-usermodel-attribute-mapper",
                  "consentRequired": false,
                  "config": {
                    "userinfo.token.claim": "true",
                    "user.attribute": "nickname",
                    "id.token.claim": "true",
                    "access.token.claim": "true",
                    "claim.name": "nickname",
                    "jsonType.label": "String"
                  }
                },
                {
                  "id": "27f03f14-d848-4c29-a43a-fdce2a84643f",
                  "name": "birthdate",
                  "protocol": "openid-connect",
                  "protocolMapper": "oidc-usermodel-attribute-mapper",
                  "consentRequired": false,
                  "config": {
                    "userinfo.token.claim": "true",
                    "user.attribute": "birthdate",
                    "id.token.claim": "true",
                    "access.token.claim": "true",
                    "claim.name": "birthdate",
                    "jsonType.label": "String"
                  }
                },
                {
                  "id": "7596e042-93bd-4ab3-a6c2-512b193cd7fd",
                  "name": "profile",
                  "protocol": "openid-connect",
                  "protocolMapper": "oidc-usermodel-attribute-mapper",
                  "consentRequired": false,
                  "config": {
                    "userinfo.token.claim": "true",
                    "user.attribute": "profile",
                    "id.token.claim": "true",
                    "access.token.claim": "true",
                    "claim.name": "profile",
                    "jsonType.label": "String"
                  }
                },
                {
                  "id": "4e6331b5-75b1-447c-9d8b-c6cf7c1bc7d8",
                  "name": "family name",
                  "protocol": "openid-connect",
                  "protocolMapper": "oidc-usermodel-property-mapper",
                  "consentRequired": false,
                  "config": {
                    "userinfo.token.claim": "true",
                    "user.attribute": "lastName",
                    "id.token.claim": "true",
                    "access.token.claim": "true",
                    "claim.name": "family_name",
                    "jsonType.label": "String"
                  }
                },
                {
                  "id": "c1f68390-eba8-4fbb-b2dc-14cfe1c3f619",
                  "name": "updated at",
                  "protocol": "openid-connect",
                  "protocolMapper": "oidc-usermodel-attribute-mapper",
                  "consentRequired": false,
                  "config": {
                    "userinfo.token.claim": "true",
                    "user.attribute": "updatedAt",
                    "id.token.claim": "true",
                    "access.token.claim": "true",
                    "claim.name": "updated_at",
                    "jsonType.label": "String"
                  }
                }
              ]
            },
            {
              "id": "9f3c2e7d-cc82-4e82-bf6e-ea5b68cef9bd",
              "name": "role_list",
              "description": "SAML role list",
              "protocol": "saml",
              "attributes": {
                "consent.screen.text": "${samlRoleListScopeConsentText}",
                "display.on.consent.screen": "true"
              },
              "protocolMappers": [
                {
                  "id": "2344edf0-fed8-4f72-be57-1dcac4e2bf42",
                  "name": "role list",
                  "protocol": "saml",
                  "protocolMapper": "saml-role-list-mapper",
                  "consentRequired": false,
                  "config": {
                    "single": "false",
                    "attribute.nameformat": "Basic",
                    "attribute.name": "Role"
                  }
                }
              ]
            },
            {
              "id": "ba01c4f0-3491-4719-b150-b942ef5d1559",
              "name": "roles",
              "description": "OpenID Connect scope for add user roles to the access token",
              "protocol": "openid-connect",
              "attributes": {
                "include.in.token.scope": "false",
                "display.on.consent.screen": "true",
                "consent.screen.text": "${rolesScopeConsentText}"
              },
              "protocolMappers": [
                {
                  "id": "152400d1-6233-46a4-89d6-11d6b595c68f",
                  "name": "client roles",
                  "protocol": "openid-connect",
                  "protocolMapper": "oidc-usermodel-client-role-mapper",
                  "consentRequired": false,
                  "config": {
                    "user.attribute": "foo",
                    "access.token.claim": "true",
                    "claim.name": "resource_access.${client_id}.roles",
                    "jsonType.label": "String",
                    "multivalued": "true"
                  }
                },
                {
                  "id": "11a86042-a37e-4778-9d99-b6150901b359",
                  "name": "audience resolve",
                  "protocol": "openid-connect",
                  "protocolMapper": "oidc-audience-resolve-mapper",
                  "consentRequired": false,
                  "config": {}
                },
                {
                  "id": "6d94d303-41cb-4fae-8d73-215839d104c6",
                  "name": "realm roles",
                  "protocol": "openid-connect",
                  "protocolMapper": "oidc-usermodel-realm-role-mapper",
                  "consentRequired": false,
                  "config": {
                    "user.attribute": "foo",
                    "access.token.claim": "true",
                    "claim.name": "realm_access.roles",
                    "jsonType.label": "String",
                    "multivalued": "true"
                  }
                }
              ]
            },
            {
              "id": "dc268ee1-4e51-4811-bc84-92c32ad73704",
              "name": "web-origins",
              "description": "OpenID Connect scope for add allowed web origins to the access token",
              "protocol": "openid-connect",
              "attributes": {
                "include.in.token.scope": "false",
                "display.on.consent.screen": "false",
                "consent.screen.text": ""
              },
              "protocolMappers": [
                {
                  "id": "ff4494d5-2ad1-49d8-adb8-c239df2ababd",
                  "name": "allowed web origins",
                  "protocol": "openid-connect",
                  "protocolMapper": "oidc-allowed-origins-mapper",
                  "consentRequired": false,
                  "config": {}
                }
              ]
            }
          ],
          "defaultDefaultClientScopes": [
            "email",
            "role_list",
            "roles",
            "web-origins",
            "profile"
          ],
          "defaultOptionalClientScopes": [
            "offline_access",
            "address",
            "phone",
            "microprofile-jwt"
          ],
          "browserSecurityHeaders": {
            "contentSecurityPolicyReportOnly": "",
            "xContentTypeOptions": "nosniff",
            "xRobotsTag": "none",
            "xFrameOptions": "SAMEORIGIN",
            "contentSecurityPolicy": "frame-src 'self'; frame-ancestors 'self'; object-src 'none';",
            "xXSSProtection": "1; mode=block",
            "strictTransportSecurity": "max-age=31536000; includeSubDomains"
          },
          "smtpServer": {},
          "eventsEnabled": false,
          "eventsListeners": [
            "jboss-logging"
          ],
          "enabledEventTypes": [],
          "adminEventsEnabled": false,
          "adminEventsDetailsEnabled": false,
          "identityProviders": [],
          "identityProviderMappers": [],
          "components": {
            "org.keycloak.services.clientregistration.policy.ClientRegistrationPolicy": [
              {
                "id": "f98761ef-45ad-4de9-a150-45a35a8eb7d8",
                "name": "Allowed Protocol Mapper Types",
                "providerId": "allowed-protocol-mappers",
                "subType": "authenticated",
                "subComponents": {},
                "config": {
                  "allowed-protocol-mapper-types": [
                    "saml-user-property-mapper",
                    "oidc-usermodel-property-mapper",
                    "saml-user-attribute-mapper",
                    "oidc-full-name-mapper",
                    "saml-role-list-mapper",
                    "oidc-usermodel-attribute-mapper",
                    "oidc-sha256-pairwise-sub-mapper",
                    "oidc-address-mapper"
                  ]
                }
              },
              {
                "id": "e2a8c6b6-cbd8-4aba-a091-081a28042ef2",
                "name": "Max Clients Limit",
                "providerId": "max-clients",
                "subType": "anonymous",
                "subComponents": {},
                "config": {
                  "max-clients": [
                    "200"
                  ]
                }
              },
              {
                "id": "7b08585f-8584-4e9e-8fc7-ac8708cb72af",
                "name": "Allowed Client Scopes",
                "providerId": "allowed-client-templates",
                "subType": "anonymous",
                "subComponents": {},
                "config": {
                  "allow-default-scopes": [
                    "true"
                  ]
                }
              },
              {
                "id": "6a410fa7-c03d-42b7-a26b-96d2addffe00",
                "name": "Full Scope Disabled",
                "providerId": "scope",
                "subType": "anonymous",
                "subComponents": {},
                "config": {}
              },
              {
                "id": "3def5bfc-33d3-44cf-973b-c0eb24611fe6",
                "name": "Consent Required",
                "providerId": "consent-required",
                "subType": "anonymous",
                "subComponents": {},
                "config": {}
              },
              {
                "id": "6b78efc9-a6fe-4a3c-b6e0-7df15e55bd06",
                "name": "Allowed Protocol Mapper Types",
                "providerId": "allowed-protocol-mappers",
                "subType": "anonymous",
                "subComponents": {},
                "config": {
                  "allowed-protocol-mapper-types": [
                    "saml-user-property-mapper",
                    "saml-user-attribute-mapper",
                    "saml-role-list-mapper",
                    "oidc-address-mapper",
                    "oidc-full-name-mapper",
                    "oidc-usermodel-attribute-mapper",
                    "oidc-sha256-pairwise-sub-mapper",
                    "oidc-usermodel-property-mapper"
                  ]
                }
              },
              {
                "id": "61e51b18-7a30-477a-8453-c97003e0b36f",
                "name": "Trusted Hosts",
                "providerId": "trusted-hosts",
                "subType": "anonymous",
                "subComponents": {},
                "config": {
                  "host-sending-registration-request-must-match": [
                    "true"
                  ],
                  "client-uris-must-match": [
                    "true"
                  ]
                }
              },
              {
                "id": "61d1b578-48e5-417a-bd9f-647937d47aa9",
                "name": "Allowed Client Scopes",
                "providerId": "allowed-client-templates",
                "subType": "authenticated",
                "subComponents": {},
                "config": {
                  "allow-default-scopes": [
                    "true"
                  ]
                }
              }
            ],
            "org.keycloak.keys.KeyProvider": [
              {
                "id": "87317b88-d8bf-4f8c-b384-2656966842d3",
                "name": "aes-generated",
                "providerId": "aes-generated",
                "subComponents": {},
                "config": {
                  "priority": [
                    "100"
                  ]
                }
              },
              {
                "id": "d5e1035a-333e-4b74-a8a2-83871da26333",
                "name": "hmac-generated",
                "providerId": "hmac-generated",
                "subComponents": {},
                "config": {
                  "priority": [
                    "100"
                  ],
                  "algorithm": [
                    "HS256"
                  ]
                }
              },
              {
                "id": "811c7189-b7ba-482f-a58f-a8bf92cd1518",
                "name": "rsa-generated",
                "providerId": "rsa-generated",
                "subComponents": {},
                "config": {
                  "priority": [
                    "100"
                  ]
                }
              }
            ]
          },
          "internationalizationEnabled": false,
          "supportedLocales": [],
          "authenticationFlows": [
            {
              "id": "e8e5e3b3-d717-4af8-b2c4-f84a7a942c41",
              "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",
                  "requirement": "ALTERNATIVE",
                  "priority": 10,
                  "userSetupAllowed": false,
                  "autheticatorFlow": false
                },
                {
                  "requirement": "ALTERNATIVE",
                  "priority": 20,
                  "flowAlias": "Verify Existing Account by Re-authentication",
                  "userSetupAllowed": false,
                  "autheticatorFlow": true
                }
              ]
            },
            {
              "id": "9a43224e-173f-4ed3-9988-6df2f653dcc0",
              "alias": "Authentication Options",
              "description": "Authentication options.",
              "providerId": "basic-flow",
              "topLevel": false,
              "builtIn": true,
              "authenticationExecutions": [
                {
                  "authenticator": "basic-auth",
                  "requirement": "REQUIRED",
                  "priority": 10,
                  "userSetupAllowed": false,
                  "autheticatorFlow": false
                },
                {
                  "authenticator": "basic-auth-otp",
                  "requirement": "DISABLED",
                  "priority": 20,
                  "userSetupAllowed": false,
                  "autheticatorFlow": false
                },
                {
                  "authenticator": "auth-spnego",
                  "requirement": "DISABLED",
                  "priority": 30,
                  "userSetupAllowed": false,
                  "autheticatorFlow": false
                }
              ]
            },
            {
              "id": "d0664bd6-8863-4d2c-8f7a-597a210990a0",
              "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",
                  "requirement": "REQUIRED",
                  "priority": 10,
                  "userSetupAllowed": false,
                  "autheticatorFlow": false
                },
                {
                  "authenticator": "auth-otp-form",
                  "requirement": "REQUIRED",
                  "priority": 20,
                  "userSetupAllowed": false,
                  "autheticatorFlow": false
                }
              ]
            },
            {
              "id": "5cfecfc1-80ad-474b-bc13-781868e3dd64",
              "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",
                  "requirement": "REQUIRED",
                  "priority": 10,
                  "userSetupAllowed": false,
                  "autheticatorFlow": false
                },
                {
                  "authenticator": "direct-grant-validate-otp",
                  "requirement": "REQUIRED",
                  "priority": 20,
                  "userSetupAllowed": false,
                  "autheticatorFlow": false
                }
              ]
            },
            {
              "id": "5a83dd3a-f602-49ab-80f3-6eea11ac0236",
              "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",
                  "requirement": "REQUIRED",
                  "priority": 10,
                  "userSetupAllowed": false,
                  "autheticatorFlow": false
                },
                {
                  "authenticator": "auth-otp-form",
                  "requirement": "REQUIRED",
                  "priority": 20,
                  "userSetupAllowed": false,
                  "autheticatorFlow": false
                }
              ]
            },
            {
              "id": "b8f891c3-b7c2-460b-84a6-6034c9f2e7ca",
              "alias": "Handle Existing Account",
              "description": "Handle what to do if there is existing account with same email/username like authenticated identity provider",
              "providerId": "basic-flow",
              "topLevel": false,
              "builtIn": true,
              "authenticationExecutions": [
                {
                  "authenticator": "idp-confirm-link",
                  "requirement": "REQUIRED",
                  "priority": 10,
                  "userSetupAllowed": false,
                  "autheticatorFlow": false
                },
                {
                  "requirement": "REQUIRED",
                  "priority": 20,
                  "flowAlias": "Account verification options",
                  "userSetupAllowed": false,
                  "autheticatorFlow": true
                }
              ]
            },
            {
              "id": "9c80145a-c30c-41a4-a04a-3d546cb170f2",
              "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",
                  "requirement": "REQUIRED",
                  "priority": 10,
                  "userSetupAllowed": false,
                  "autheticatorFlow": false
                },
                {
                  "authenticator": "reset-otp",
                  "requirement": "REQUIRED",
                  "priority": 20,
                  "userSetupAllowed": false,
                  "autheticatorFlow": false
                }
              ]
            },
            {
              "id": "bdb0f769-ea5e-45da-80fb-9cbc49f0d63c",
              "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",
                  "requirement": "ALTERNATIVE",
                  "priority": 10,
                  "userSetupAllowed": false,
                  "autheticatorFlow": false
                },
                {
                  "requirement": "ALTERNATIVE",
                  "priority": 20,
                  "flowAlias": "Handle Existing Account",
                  "userSetupAllowed": false,
                  "autheticatorFlow": true
                }
              ]
            },
            {
              "id": "f5a53683-111c-425a-a2fe-2dc72cb88a51",
              "alias": "Verify Existing Account by Re-authentication",
              "description": "Reauthentication of existing account",
              "providerId": "basic-flow",
              "topLevel": false,
              "builtIn": true,
              "authenticationExecutions": [
                {
                  "authenticator": "idp-username-password-form",
                  "requirement": "REQUIRED",
                  "priority": 10,
                  "userSetupAllowed": false,
                  "autheticatorFlow": false
                },
                {
                  "requirement": "CONDITIONAL",
                  "priority": 20,
                  "flowAlias": "First broker login - Conditional OTP",
                  "userSetupAllowed": false,
                  "autheticatorFlow": true
                }
              ]
            },
            {
              "id": "a614f3aa-b795-4805-b44f-4d8f51f1bd68",
              "alias": "browser",
              "description": "browser based authentication",
              "providerId": "basic-flow",
              "topLevel": true,
              "builtIn": true,
              "authenticationExecutions": [
                {
                  "authenticator": "auth-cookie",
                  "requirement": "ALTERNATIVE",
                  "priority": 10,
                  "userSetupAllowed": false,
                  "autheticatorFlow": false
                },
                {
                  "authenticator": "auth-spnego",
                  "requirement": "DISABLED",
                  "priority": 20,
                  "userSetupAllowed": false,
                  "autheticatorFlow": false
                },
                {
                  "authenticator": "identity-provider-redirector",
                  "requirement": "ALTERNATIVE",
                  "priority": 25,
                  "userSetupAllowed": false,
                  "autheticatorFlow": false
                },
                {
                  "requirement": "ALTERNATIVE",
                  "priority": 30,
                  "flowAlias": "forms",
                  "userSetupAllowed": false,
                  "autheticatorFlow": true
                }
              ]
            },
            {
              "id": "4ac2c0ea-1b12-4d7e-ac1c-9d294a466885",
              "alias": "clients",
              "description": "Base authentication for clients",
              "providerId": "client-flow",
              "topLevel": true,
              "builtIn": true,
              "authenticationExecutions": [
                {
                  "authenticator": "client-secret",
                  "requirement": "ALTERNATIVE",
                  "priority": 10,
                  "userSetupAllowed": false,
                  "autheticatorFlow": false
                },
                {
                  "authenticator": "client-jwt",
                  "requirement": "ALTERNATIVE",
                  "priority": 20,
                  "userSetupAllowed": false,
                  "autheticatorFlow": false
                },
                {
                  "authenticator": "client-secret-jwt",
                  "requirement": "ALTERNATIVE",
                  "priority": 30,
                  "userSetupAllowed": false,
                  "autheticatorFlow": false
                },
                {
                  "authenticator": "client-x509",
                  "requirement": "ALTERNATIVE",
                  "priority": 40,
                  "userSetupAllowed": false,
                  "autheticatorFlow": false
                }
              ]
            },
            {
              "id": "747edd9a-eba4-4d9c-b89d-6c0b61bd09d8",
              "alias": "direct grant",
              "description": "OpenID Connect Resource Owner Grant",
              "providerId": "basic-flow",
              "topLevel": true,
              "builtIn": true,
              "authenticationExecutions": [
                {
                  "authenticator": "direct-grant-validate-username",
                  "requirement": "REQUIRED",
                  "priority": 10,
                  "userSetupAllowed": false,
                  "autheticatorFlow": false
                },
                {
                  "authenticator": "direct-grant-validate-password",
                  "requirement": "REQUIRED",
                  "priority": 20,
                  "userSetupAllowed": false,
                  "autheticatorFlow": false
                },
                {
                  "requirement": "CONDITIONAL",
                  "priority": 30,
                  "flowAlias": "Direct Grant - Conditional OTP",
                  "userSetupAllowed": false,
                  "autheticatorFlow": true
                }
              ]
            },
            {
              "id": "db981ee0-9cef-4532-9fd1-df9ad8fc6bb7",
              "alias": "docker auth",
              "description": "Used by Docker clients to authenticate against the IDP",
              "providerId": "basic-flow",
              "topLevel": true,
              "builtIn": true,
              "authenticationExecutions": [
                {
                  "authenticator": "docker-http-basic-authenticator",
                  "requirement": "REQUIRED",
                  "priority": 10,
                  "userSetupAllowed": false,
                  "autheticatorFlow": false
                }
              ]
            },
            {
              "id": "a7965662-76ec-4a96-941d-8eaab37d63b6",
              "alias": "first broker login",
              "description": "Actions taken after first broker login with identity provider account, which is not yet linked to any Keycloak account",
              "providerId": "basic-flow",
              "topLevel": true,
              "builtIn": true,
              "authenticationExecutions": [
                {
                  "authenticatorConfig": "review profile config",
                  "authenticator": "idp-review-profile",
                  "requirement": "REQUIRED",
                  "priority": 10,
                  "userSetupAllowed": false,
                  "autheticatorFlow": false
                },
                {
                  "requirement": "REQUIRED",
                  "priority": 20,
                  "flowAlias": "User creation or linking",
                  "userSetupAllowed": false,
                  "autheticatorFlow": true
                }
              ]
            },
            {
              "id": "e8852408-7320-40eb-a9df-b2c23f10fb08",
              "alias": "forms",
              "description": "Username, password, otp and other auth forms.",
              "providerId": "basic-flow",
              "topLevel": false,
              "builtIn": true,
              "authenticationExecutions": [
                {
                  "authenticator": "auth-username-password-form",
                  "requirement": "REQUIRED",
                  "priority": 10,
                  "userSetupAllowed": false,
                  "autheticatorFlow": false
                },
                {
                  "requirement": "CONDITIONAL",
                  "priority": 20,
                  "flowAlias": "Browser - Conditional OTP",
                  "userSetupAllowed": false,
                  "autheticatorFlow": true
                }
              ]
            },
            {
              "id": "ad382942-0dc7-4b2a-adc4-d460f68c2cd8",
              "alias": "http challenge",
              "description": "An authentication flow based on challenge-response HTTP Authentication Schemes",
              "providerId": "basic-flow",
              "topLevel": true,
              "builtIn": true,
              "authenticationExecutions": [
                {
                  "authenticator": "no-cookie-redirect",
                  "requirement": "REQUIRED",
                  "priority": 10,
                  "userSetupAllowed": false,
                  "autheticatorFlow": false
                },
                {
                  "requirement": "REQUIRED",
                  "priority": 20,
                  "flowAlias": "Authentication Options",
                  "userSetupAllowed": false,
                  "autheticatorFlow": true
                }
              ]
            },
            {
              "id": "a627e223-62c9-45d4-ac6d-cb529b890beb",
              "alias": "registration",
              "description": "registration flow",
              "providerId": "basic-flow",
              "topLevel": true,
              "builtIn": true,
              "authenticationExecutions": [
                {
                  "authenticator": "registration-page-form",
                  "requirement": "REQUIRED",
                  "priority": 10,
                  "flowAlias": "registration form",
                  "userSetupAllowed": false,
                  "autheticatorFlow": true
                }
              ]
            },
            {
              "id": "7b55e051-7eda-49ec-b55c-d8c0b69d8681",
              "alias": "registration form",
              "description": "registration form",
              "providerId": "form-flow",
              "topLevel": false,
              "builtIn": true,
              "authenticationExecutions": [
                {
                  "authenticator": "registration-user-creation",
                  "requirement": "REQUIRED",
                  "priority": 20,
                  "userSetupAllowed": false,
                  "autheticatorFlow": false
                },
                {
                  "authenticator": "registration-profile-action",
                  "requirement": "REQUIRED",
                  "priority": 40,
                  "userSetupAllowed": false,
                  "autheticatorFlow": false
                },
                {
                  "authenticator": "registration-password-action",
                  "requirement": "REQUIRED",
                  "priority": 50,
                  "userSetupAllowed": false,
                  "autheticatorFlow": false
                },
                {
                  "authenticator": "registration-recaptcha-action",
                  "requirement": "DISABLED",
                  "priority": 60,
                  "userSetupAllowed": false,
                  "autheticatorFlow": false
                }
              ]
            },
            {
              "id": "f7169862-113f-4aad-84c8-b56fc08f415e",
              "alias": "reset credentials",
              "description": "Reset credentials for a user if they forgot their password or something",
              "providerId": "basic-flow",
              "topLevel": true,
              "builtIn": true,
              "authenticationExecutions": [
                {
                  "authenticator": "reset-credentials-choose-user",
                  "requirement": "REQUIRED",
                  "priority": 10,
                  "userSetupAllowed": false,
                  "autheticatorFlow": false
                },
                {
                  "authenticator": "reset-credential-email",
                  "requirement": "REQUIRED",
                  "priority": 20,
                  "userSetupAllowed": false,
                  "autheticatorFlow": false
                },
                {
                  "authenticator": "reset-password",
                  "requirement": "REQUIRED",
                  "priority": 30,
                  "userSetupAllowed": false,
                  "autheticatorFlow": false
                },
                {
                  "requirement": "CONDITIONAL",
                  "priority": 40,
                  "flowAlias": "Reset - Conditional OTP",
                  "userSetupAllowed": false,
                  "autheticatorFlow": true
                }
              ]
            },
            {
              "id": "3e08fa1d-9e63-4e04-9b5d-b72c277a2807",
              "alias": "saml ecp",
              "description": "SAML ECP Profile Authentication Flow",
              "providerId": "basic-flow",
              "topLevel": true,
              "builtIn": true,
              "authenticationExecutions": [
                {
                  "authenticator": "http-basic-authenticator",
                  "requirement": "REQUIRED",
                  "priority": 10,
                  "userSetupAllowed": false,
                  "autheticatorFlow": false
                }
              ]
            }
          ],
          "authenticatorConfig": [
            {
              "id": "b84cf6e5-fac7-4638-88c3-94e06c99572a",
              "alias": "create unique user config",
              "config": {
                "require.password.update.after.registration": "false"
              }
            },
            {
              "id": "a2552331-4d23-493b-9d0b-cab01655bef7",
              "alias": "review profile config",
              "config": {
                "update.profile.on.first.login": "missing"
              }
            }
          ],
          "requiredActions": [
            {
              "alias": "CONFIGURE_TOTP",
              "name": "Configure OTP",
              "providerId": "CONFIGURE_TOTP",
              "enabled": true,
              "defaultAction": false,
              "priority": 10,
              "config": {}
            },
            {
              "alias": "terms_and_conditions",
              "name": "Terms and Conditions",
              "providerId": "terms_and_conditions",
              "enabled": false,
              "defaultAction": false,
              "priority": 20,
              "config": {}
            },
            {
              "alias": "UPDATE_PASSWORD",
              "name": "Update Password",
              "providerId": "UPDATE_PASSWORD",
              "enabled": true,
              "defaultAction": false,
              "priority": 30,
              "config": {}
            },
            {
              "alias": "UPDATE_PROFILE",
              "name": "Update Profile",
              "providerId": "UPDATE_PROFILE",
              "enabled": true,
              "defaultAction": false,
              "priority": 40,
              "config": {}
            },
            {
              "alias": "VERIFY_EMAIL",
              "name": "Verify Email",
              "providerId": "VERIFY_EMAIL",
              "enabled": true,
              "defaultAction": false,
              "priority": 50,
              "config": {}
            },
            {
              "alias": "delete_account",
              "name": "Delete Account",
              "providerId": "delete_account",
              "enabled": false,
              "defaultAction": false,
              "priority": 60,
              "config": {}
            },
            {
              "alias": "update_user_locale",
              "name": "Update User Locale",
              "providerId": "update_user_locale",
              "enabled": true,
              "defaultAction": false,
              "priority": 1000,
              "config": {}
            }
          ],
          "browserFlow": "browser",
          "registrationFlow": "registration",
          "directGrantFlow": "direct grant",
          "resetCredentialsFlow": "reset credentials",
          "clientAuthenticationFlow": "clients",
          "dockerAuthenticationFlow": "docker auth",
          "attributes": {
            "clientOfflineSessionMaxLifespan": "0",
            "clientSessionIdleTimeout": "0",
            "clientSessionMaxLifespan": "0",
            "clientOfflineSessionIdleTimeout": "0"
          },
          "keycloakVersion": "12.0.4",
          "userManagedAccessAllowed": false
        }
        
    3. Open localhost:7070 in your browser and use the Keycloak UI to import the kafka-realm.json file.

  3. Update your Kafka cluster’s readOnlyConfig and listenersConfig configuration sections with the following OAuth-related properties:

  4. Test the OIDC authentication.

    Note: OAuthCompatibilityTool is a tool provided by the Kafka community when KIP-768 is added for testing, see: https://cwiki.apache.org/confluence/pages/viewpage.action?pageId=186877575#KIP768:ExtendSASL/OAUTHBEARERwithSupportforOIDC-Testing

    1. To test the OIDC authentication with consumer credentials, run the following command:

      kafka-run-class.sh org.apache.kafka.tools.OAuthCompatibilityTool \
      --clientId kafka-consumer \
      --clientSecret 4090cfea-44c1-470b-a610-3a7b0f4366ae \
      --sasl.oauthbearer.jwks.endpoint.url http://idp-keycloak.keycloak.svc.cluster.local/auth/realms/kafka/protocol/openid-connect/certs \
      --sasl.oauthbearer.token.endpoint.url http://idp-keycloak.keycloak.svc.cluster.local/auth/realms/kafka/protocol/openid-connect/token \
      --sasl.oauthbearer.expected.audience account
      

      Expected result:

      PASSED 1/5: client configuration
      PASSED 2/5: client JWT retrieval
      PASSED 3/5: client JWT validation
      PASSED 4/5: broker configuration
      PASSED 5/5: broker JWT validation
      SUCCESS
      
    2. To test the OIDC authentication with producer credentials, run the following command:

      kafka-run-class.sh org.apache.kafka.tools.OAuthCompatibilityTool \
        --clientId kafka-producer \
        --clientSecret 85cb47f8-6c76-43f0-bbe2-a66f7f86395a \
        --sasl.oauthbearer.jwks.endpoint.url http://idp-keycloak.keycloak.svc.cluster.local/auth/realms/kafka/protocol/openid-connect/certs \
        --sasl.oauthbearer.token.endpoint.url http://idp-keycloak.keycloak.svc.cluster.local/auth/realms/kafka/protocol/openid-connect/token \
        --sasl.oauthbearer.expected.audience account
      

      Expected result:

      PASSED 1/5: client configuration
      PASSED 2/5: client JWT retrieval
      PASSED 3/5: client JWT validation
      PASSED 4/5: broker configuration
      PASSED 5/5: broker JWT validation
      SUCCESS
      

Test OIDC authentication with console consumer and console producer

  1. Create an example-topic:

    kubectl apply -n kafka -f- <<EOF
    apiVersion: kafka.banzaicloud.io/v1alpha1
    kind: KafkaTopic
    metadata:
      name: example-topic
      namespace: kafka
    spec:
      clusterRef:
        name: kafka
      name: example-topic
      partitions: 3
      replicationFactor: 2
      config:
        "retention.ms": "604800000"
        "cleanup.policy": "delete"
    EOF
    
  2. Grant access to the identities defined in Keycloak to the example-topic topic with Kafka ACLs:

    kubectl apply -n kafka -f- <<EOF
    ---
    apiVersion: kafka.banzaicloud.io/v1beta1
    kind: KafkaResourceSelector
    metadata:
      name: selector-of-example-topic
      namespace: kafka
    spec:
      type: topic
      name: example-topic
      pattern: literal
    ---
    apiVersion: kafka.banzaicloud.io/v1beta1
    kind: KafkaResourceSelector
    metadata:
      name: all-groups
      namespace: kafka
    spec:
      type: group
      name: '*'
      pattern: literal
    ---
    apiVersion: kafka.banzaicloud.io/v1beta1
    kind: KafkaACL
    metadata:
      name: consumer-kafkaacl
      namespace: kafka
    spec:
      kind: User
      name: 0aa61449-e970-4854-ac2a-f22e664b0110
      clusterRef:
        name: kafka
        namespace: kafka
      roles:
        - name: consumer
          resourceSelectors:
            - name: selector-of-example-topic
              namespace: kafka
            - name: all-groups
              namespace: kafka   
    ---
    apiVersion: kafka.banzaicloud.io/v1beta1
    kind: KafkaACL
    metadata:
      name: producer-kafkaacl
      namespace: kafka
    spec:
      kind: User
      name: 4c01f71e-f6a8-46e6-99f4-379db03c4362
      clusterRef:
        name: kafka
        namespace: kafka
      roles:
        - name: producer
          resourceSelectors:
            - name: selector-of-example-topic
              namespace: kafka
    EOF
    
  3. Create another topic (called forbidden-topic in the following example) that none of the identities defined in Keycloak has access to:

    kubectl apply -n kafka -f- <<EOF
    apiVersion: kafka.banzaicloud.io/v1alpha1
    kind: KafkaTopic
    metadata:
      name: forbidden-topic
      namespace: kafka
    spec:
      clusterRef:
        name: kafka
      name: forbidden-topic
      partitions: 3
      replicationFactor: 2
      config:
        "retention.ms": "604800000"
        "cleanup.policy": "delete"
    EOF
    
  4. Configure the producer configuration. Use the following producer configuration with the kafka-console-producer.sh tool (shipped with Kafka) for consuming and producing messages. Set the producer properties like this in a properties file:

    sasl.mechanism=OAUTHBEARER
    security.protocol=SASL_PLAINTEXT
    sasl.login.callback.handler.class=org.apache.kafka.common.security.oauthbearer.secured.OAuthBearerLoginCallbackHandler
    sasl.oauthbearer.token.endpoint.url=http://idp-keycloak.keycloak.svc.cluster.local/auth/realms/kafka/protocol/openid-connect/token
    sasl.jaas.config=org.apache.kafka.common.security.oauthbearer.OAuthBearerLoginModule required \
        clientId="kafka-producer" \
        clientSecret="85cb47f8-6c76-43f0-bbe2-a66f7f86395a" \
        scope="kafka:write";
    

    Note: You can produce messages only messages to the example-topic, because the producer user has no access to the topic forbidden-topic.

  5. Configure the consumer. Use the following consumer configuration with kafka-console-producer.sh tool (shipped with Kafka) for consuming and producing messages. Set the consumer properties like this in a properties file:

    group.id=consumer-1
    group.instance.id=consumer-1-instance-1
    client.id=consumer-1-instance-1
    sasl.mechanism=OAUTHBEARER
    security.protocol=SASL_PLAINTEXT
    sasl.login.callback.handler.class=org.apache.kafka.common.security.oauthbearer.secured.OAuthBearerLoginCallbackHandler
    sasl.oauthbearer.token.endpoint.url=http://idp-keycloak.keycloak.svc.cluster.local/auth/realms/kafka/protocol/openid-connect/token
    sasl.jaas.config=org.apache.kafka.common.security.oauthbearer.OAuthBearerLoginModule required \
        clientId="kafka-consumer" \
        clientSecret="4090cfea-44c1-470b-a610-3a7b0f4366ae" \
        scope="kafka:read" ;
    

    Note: Only messages from the example-topic can be consumed, because the consumer user has no access to the topic forbidden-topic.