skip to content

When would you choose SASL/PLAIN vs SASL/SCRAM (vs mTLS or OAUTHBEARER) for a production Kafka cluster, and what are the operational trade-offs?

level: principalimportance: should knowfreq 35%

answer

  1. mechanism choice = identity ownership + rotation
  2. SCRAM = self-managed user/pass, live kafka-configs
  3. PLAIN only with custom callback (LDAP/secrets) -> raw cred on wire
  4. OAUTHBEARER = OIDC tokens; mTLS = cert identity, no passwords
  5. always SASL_SSL; ACLs separate from authentication

basics

~20 s

Use SCRAM for self-managed username/password auth with live user management. Use PLAIN only when an external system (e.g. LDAP via a custom callback) validates credentials. Prefer OAUTHBEARER/mTLS for identity-provider or certificate-based auth. Always wrap in TLS.

solid answer

~50 s

Choice depends on who owns identities and how you rotate them. SASL/SCRAM is the default for clusters that manage their own username/password users: credentials live hashed in ZK/KRaft, you add/rotate/delete users live with kafka-configs, and the password never crosses the wire — good operational and security posture. SASL/PLAIN is mainly attractive when you delegate validation to an external store via a custom AuthenticateCallbackHandler (LDAP, a secrets service): PLAIN carries the raw credential which your handler checks. Its downside is static JAAS user lists and broker restarts to change them, plus full reliance on TLS. For enterprise SSO, OAUTHBEARER integrates with an OIDC provider (short-lived tokens, central revocation). For strong service identity, mutual TLS (SSL security protocol with client certs) ties identity to certificates and needs no passwords at all. All SASL options must run over SASL_SSL. A common production pattern: mTLS or SCRAM internally, OAUTHBEARER for external/human clients, never PLAIN without a custom backing store.

go deeper

for a junior

Know SCRAM is generally preferred over PLAIN and that all SASL needs TLS.

for a middle

Contrast SCRAM's live user management with PLAIN's static restart-to-add model.

for a senior

Weigh SCRAM vs PLAIN-with-callback vs OAUTHBEARER vs mTLS and use per-listener mechanisms.

for a principal

Design a cluster-wide identity strategy tying mechanism choice to IdP/PKI ownership, rotation, blast radius, and the separate ACL layer.

## The real question: who owns identity and how do you rotate it? Mechanism choice is an identity-management decision, not just a crypto one. ## SASL/SCRAM — the self-managed default - **Use when**: you want Kafka itself to be the credential store for username/password users. - **Pros**: passwords never on the wire; credentials stored salted in ZK/KRaft; add/rotate/delete live via `kafka-configs` (no restart); two strengths (SHA-256/512). - **Cons**: Kafka becomes a password store (you own rotation, complexity policy); no central SSO; client config still holds a cleartext password locally; stolen StoredKey is a cluster-scoped verifier. - **Best fit**: small-to-mid platforms, internal services, environments without an enterprise IdP. ## SASL/PLAIN — only with a custom backend - **Out of the box**: static `user_<name>` entries in broker JAAS → restart to add a user → poor at scale. Avoid this in production. - **The legitimate use**: implement a custom `AuthenticateCallbackHandler` (`sasl.server.callback.handler.class`) so PLAIN credentials are validated against **LDAP / a secrets manager / a DB**. PLAIN's wire format (raw username/password) is exactly what such a backend needs. - **Cons**: raw credential on the wire → absolute dependence on TLS; any proxy that terminates TLS sees passwords; no built-in rotation. ## OAUTHBEARER — enterprise SSO - **Use when**: you have an OIDC/OAuth2 identity provider (Keycloak, Okta, Azure AD). - **Pros**: short-lived bearer tokens, central issuance/revocation, no long-lived passwords in client config, group/scope claims usable for authorization. - **Cons**: needs token infra and a JWT-validation callback; clock/expiry handling; more moving parts. ## Mutual TLS (SSL) — certificate identity - **Use when**: you want strong, password-less service identity. - **Pros**: identity = client certificate (principal from the cert DN); no shared secrets; works well with a service mesh/PKI; encryption and auth in one layer. - **Cons**: certificate lifecycle/rotation, revocation (CRL/OCSP), PKI ops burden; principal mapping rules (`ssl.principal.mapping.rules`). ## Cross-cutting rules - **Always TLS**: every SASL mechanism (including SCRAM) should run over `SASL_SSL`. SASL authenticates; it does not encrypt data. - **Per-listener mechanisms**: use `listener.name.<l>.<mech>.sasl.jaas.config` to run internal SCRAM/mTLS and external OAUTHBEARER simultaneously. - **Authorization is separate**: the mechanism establishes the *principal*; ACLs (`AclAuthorizer`/`StandardAuthorizer`) decide what it can do. SCRAM/PLAIN/OAUTH/mTLS all feed the same ACL layer. ## A pragmatic production blueprint - Internal broker-to-broker and service clients: **mTLS** or **SCRAM-SHA-512**. - Human/external clients with corporate SSO: **OAUTHBEARER**. - **PLAIN**: only behind a custom LDAP/secrets callback, always over TLS; otherwise avoid. ## Decision cues - Have an IdP? → OAUTHBEARER. - Have a PKI/mesh? → mTLS. - Need self-contained username/password with live management? → SCRAM. - Must validate against an existing password store? → PLAIN + custom callback.

  • Is plain SASL/PLAIN with static JAAS users ever acceptable in production?
    Generally no — it requires editing broker JAAS and restarting to add/rotate users, and puts raw credentials on the wire. The one defensible PLAIN use is with a custom AuthenticateCallbackHandler that validates credentials against LDAP or a secrets store, always over TLS.
  • How does the authentication mechanism relate to Kafka authorization (ACLs)?
    Authentication only establishes the principal (e.g. User:alice or a cert DN). Authorization is a separate layer: the StandardAuthorizer/AclAuthorizer checks ACLs for that principal on each operation. SCRAM, PLAIN, OAUTHBEARER, and mTLS all feed into the same ACL evaluation.
  • You need internal services on SCRAM but external partners on SSO tokens. How?
    Define separate listeners and use per-listener config: an internal SASL_SSL listener with SCRAM-SHA-512 and an external SASL_SSL listener with OAUTHBEARER, each via listener.name.<l>.<mech>.sasl.jaas.config, with sasl.enabled.mechanisms set per listener.

saying these in an interview costs you the question

  • Recommending SASL/PLAIN with static JAAS users for a large production cluster
  • Treating the auth mechanism as if it also handles authorization
  • Saying any SASL mechanism removes the need for TLS
  • Picking SCRAM when the org already has an enterprise IdP that OAUTHBEARER would serve better

context