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
-
Enable ACLs and configure an external listener using Streaming Data Manager. Complete the following steps:
-
Verify that your deployed Kafka cluster is up and running:
smm sdm 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
-
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:
smm sdm 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.
-
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.
smm sdm 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
-
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
-
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
-
Import the Kafka realm into Keycloak.
-
Run the following command:
kubectl port-forward -n keycloak svc/idp-keycloak 7070:80
-
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 }
-
Open
localhost:7070
in your browser and use the Keycloak UI to import thekafka-realm.json
file.
-
-
Update your Kafka cluster’s
readOnlyConfig
andlistenersConfig
configuration sections with the following OAuth-related properties: -
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
-
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
-
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
-
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
-
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
-
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
-
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 topicforbidden-topic
. -
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 topicforbidden-topic
.