blog by OSO

Apache Kafka Security using OAuth

Sion Smith
Sion Smith 21 August 2023
OSO guide to Kafka OAuth authentication with SASL/OAUTHBEARER and OIDC, white title text on a navy panel with a lime Blogs label.

What is Kafka OAuth authentication?

Apache Kafka supports several ways to prove who a client is: mutual TLS certificates, SASL/SCRAM usernames and passwords, Kerberos (GSSAPI) and SASL/OAUTHBEARER. OAuth is the option that lets Kafka reuse the identity provider your organisation already runs, such as Okta, Microsoft Entra ID, Keycloak or Ping, rather than keeping a separate list of Kafka-only credentials.

OAuth support arrived in two stages:

  • KIP-255 (Kafka 2.0) added the SASL/OAUTHBEARER mechanism defined in RFC 7628. Its default implementation creates and validates unsecured JWTs, so the Kafka documentation says it is only suitable for development and test.
  • KIP-768 (Kafka 3.1) added production-ready OpenID Connect (OIDC) support: clients can request tokens from a standard token endpoint, and brokers can validate signed tokens against the provider’s published keys.

Later releases added more grant types, including the JWT bearer grant (KIP-1139, Kafka 4.1) and client assertion for the client credentials grant (KIP-1258), so a client can sign its own request with a private key instead of sending a shared secret.

If you are still deciding between mechanisms, our guide on how to secure your Apache Kafka cluster compares SASL/SCRAM, mTLS and OAuth side by side. This article focuses on running OAuth well.

How does SASL/OAUTHBEARER work with an OIDC provider?

The flow has four steps, and only one of them involves the broker talking to the identity provider:

  1. The client gets a token. On start-up the client calls the provider’s token endpoint, usually with the OAuth client_credentials grant, and receives a signed JWT access token.
  2. The client presents the token. During the SASL handshake the client sends the token to the broker over a TLS connection.
  3. The broker validates the token locally. It verifies the signature with keys downloaded from the provider’s JWKS endpoint, and checks the expiry, issuer (iss) and audience (aud) claims. The broker caches the keys (refreshed hourly by default), so it does not call the provider for every connection.
  4. Kafka authorises the principal. The token’s subject claim (sub by default) becomes the principal name, so ACLs are written for User:<subject> exactly as they would be for SCRAM users.
ComponentResponsibilityKey setting
Identity providerIssues and signs tokens, publishes signing keysToken and JWKS endpoints
Kafka clientRequests tokens and refreshes them before expirysasl.oauthbearer.token.endpoint.url
Kafka brokerValidates signature, expiry, issuer and audiencesasl.oauthbearer.jwks.endpoint.url
Kafka authoriserApplies ACLs to the token’s subjectsasl.oauthbearer.sub.claim.name

Authentication and authorisation stay separate. OAuth proves the client’s identity; ACLs, managed in Kafka, still decide which topics and consumer groups that identity can use.

How do you configure Kafka brokers for OAuth?

On each broker, enable OAUTHBEARER on a SASL_SSL listener and point the built-in validator at your provider. This example follows the current Apache Kafka documentation:

listeners=SASL_SSL://broker1.example.com:9093
sasl.enabled.mechanisms=OAUTHBEARER
listener.name.sasl_ssl.oauthbearer.sasl.server.callback.handler.class=org.apache.kafka.common.security.oauthbearer.OAuthBearerValidatorCallbackHandler
listener.name.sasl_ssl.oauthbearer.sasl.oauthbearer.jwks.endpoint.url=https://idp.example.com/oauth2/v1/keys
listener.name.sasl_ssl.oauthbearer.sasl.oauthbearer.expected.audience=my-kafka-cluster
listener.name.sasl_ssl.oauthbearer.sasl.oauthbearer.expected.issuer=https://idp.example.com

Points worth getting right:

  • Always set the expected issuer and audience. Without them, a token issued for another application by the same provider could be accepted. From Kafka 4.4 the broker will not start if a JWKS URL is set without both values, unless you explicitly opt out, which the documentation strongly discourages.
  • Allow the provider’s URLs explicitly on Kafka 4.0 and later. After CVE-2025-27817, Kafka added the JVM system property org.apache.kafka.sasl.oauthbearer.allowed.urls. From 4.0 its default is an empty list, so token and JWKS URLs are rejected until you list them. This also stops an untrusted configuration, for example a connector submitted through the Kafka Connect REST API, from reaching arbitrary files or URLs.
  • Mind clock skew. The broker allows 30 seconds of skew between itself and the provider by default (sasl.oauthbearer.clock.skew.seconds). Keep NTP healthy on brokers.
  • Use a different subject claim if needed. Some providers put the service identity in a claim other than sub; set sasl.oauthbearer.sub.claim.name so ACL principals stay readable.

How do you configure Kafka clients for OAuth?

On Kafka 4.x clients, a service using the client credentials grant with a client secret needs only a few properties:

security.protocol=SASL_SSL
sasl.mechanism=OAUTHBEARER
sasl.jaas.config=org.apache.kafka.common.security.oauthbearer.OAuthBearerLoginModule required ;
sasl.oauthbearer.token.endpoint.url=https://idp.example.com/oauth2/v1/token
sasl.oauthbearer.client.credentials.client.id=orders-service
sasl.oauthbearer.client.credentials.client.secret=<from your secrets manager>
sasl.oauthbearer.scope=kafka

On Kafka 3.x clients, the same settings are passed differently: set sasl.login.callback.handler.class to OAuthBearerLoginCallbackHandler and put clientId, clientSecret and scope inside the JAAS configuration, as described in KIP-768.

Where your provider supports it, prefer client assertion over a client secret. The client signs a short-lived JWT with its own private key, so no shared secret is sent over the network. The Kafka documentation recommends short assertion lifetimes, such as 300 seconds, and including a unique jti claim to protect against replay.

Key takeaway: Use the built-in OIDC handlers rather than custom code, always validate issuer and audience on the broker, and keep client secrets out of properties files, or replace them with signed client assertions.

How does Kafka refresh OAuth tokens?

Tokens are short-lived on purpose: if one leaks, it is only useful until it expires. Kafka’s login refresh thread renews the token before expiry, so producers and consumers keep running without interruption.

SettingDefaultWhat it controls
sasl.login.refresh.window.factor0.8Refresh when 80% of the token’s lifetime has passed
sasl.login.refresh.window.jitter0.05Up to 5% random jitter, so clients do not all refresh at once
sasl.login.refresh.min.period.seconds60Minimum wait between refreshes
sasl.login.refresh.buffer.seconds300Keep at least five minutes before expiry where possible
connections.max.reauth.ms (broker)0 (off)Forces existing connections to re-authenticate within this time

The last row matters. A refreshed token is used for new connections, but by default an established connection stays authenticated for as long as it is open. Setting connections.max.reauth.ms on the broker (added by KIP-368 in Kafka 2.2) makes clients re-authenticate on long-lived connections. Expired or revoked credentials then stop working within a known time, rather than whenever the client next reconnects.

Why centralise Kafka identity in an identity provider?

Most teams start with SCRAM users or certificates created by hand for each application. That works for a few services, but it becomes hard to manage as the platform grows. A central provider gives you:

  • One place to create and remove identities. Disabling a service account in the provider stops new tokens being issued, with no Kafka-specific clean-up.
  • Shared discovery and audit. Every application uses the same token and key endpoints, and authentication events land in the provider’s audit log alongside your other systems.
  • No long-lived Kafka passwords. Clients hold a client secret or private key for the provider, and Kafka only ever sees short-lived tokens.
  • A consistent model across environments. The same claims and naming conventions work on self-managed Kafka and on managed services that support OAUTHBEARER.

In regulated organisations this is often the deciding factor. Our work with Lloyds Banking Group is an example of designing a secure, auditable Kafka platform where access control has to stand up to scrutiny.

How should you migrate existing Kafka clients to OAuth?

You do not need a big-bang cut-over. Kafka brokers can enable several SASL mechanisms at once, so OAuth can run alongside SCRAM or mTLS while clients move across. A low-risk sequence:

  1. Use standard components. Stick to the built-in OIDC handlers and a mainstream identity provider rather than writing custom callback handlers or running a home-grown OAuth server.
  2. Add an OAuth listener or mechanism next to the existing one, with issuer, audience and allowed URLs set from day one.
  3. Recreate ACLs for the new principals. A service that was User:orders under SCRAM may become User:<client id> under OAuth, so mirror its ACLs before switching it.
  4. Move low-risk clients first, such as reporting and analytics consumers, then work towards business-critical producers.
  5. Watch the provider and the brokers. Track token endpoint latency and errors, failed authentications per listener, and re-authentication rates, so a provider outage is spotted before tokens start to expire.
  6. Remove the old mechanism once no client authenticates with it, and delete the unused credentials.

Treat the identity provider as a production dependency: if clients cannot get new tokens, new connections fail once current tokens expire. Plan for its availability as you would for the brokers. If you are moving clusters at the same time, our guide on how to migrate a Kafka cluster covers sequencing the cut-over.

Need a second pair of eyes on your Kafka security design? OSO’s engineers help teams roll out OAuth, ACLs and encryption through our Kafka consulting services and keep it running with 24/7 Kafka support.

Frequently asked questions

Does Apache Kafka support OAuth?

Yes. Kafka supports OAuth 2.0 through the SASL/OAUTHBEARER mechanism. KIP-255 added the mechanism in Kafka 2.0, and KIP-768 added production-ready OpenID Connect support in Kafka 3.1, so brokers can validate signed tokens from providers such as Okta, Entra ID or Keycloak.

Is the default OAUTHBEARER implementation safe for production?

No. The default implementation creates and validates unsecured JWTs and the Kafka documentation says it is for non-production use only. In production, use the built-in OIDC handlers that validate signed tokens against your provider’s JWKS endpoint, and always run OAUTHBEARER over TLS.

Does OAuth replace Kafka ACLs?

No. OAuth handles authentication, proving who the client is. Kafka still authorises each request with ACLs, using the token’s subject claim as the principal, so you grant topic and group permissions to that User principal just as you would for SCRAM users.

How often does a Kafka client refresh its OAuth token?

By default a Kafka client refreshes its token once 80% of its lifetime has passed, with up to 5% random jitter, a minimum of 60 seconds between refreshes and a five-minute buffer before expiry. These are controlled by the sasl.login.refresh.* settings.

Can I use Kafka OAuth for single sign-on (SSO)?

Partly. OAUTHBEARER is designed for applications and service accounts using machine-to-machine grants, not interactive browser log-ins. Human SSO usually happens in the tools around Kafka, such as admin consoles, which then use their own OAuth identity to talk to the brokers.

Get started with OSO professional services for Apache Kafka

Talk to one of our Kafka experts about securing your clusters with OAuth, ACLs and encryption, and rolling it out without downtime.

CONTACT US
OSO
Privacy Overview

This website uses cookies so that we can provide you with the best user experience possible. Cookie information is stored in your browser and performs functions such as recognising you when you return to our website and helping our team to understand which sections of the website you find most interesting and useful.