Skip to main content
Client to Gateway security
Per-listener configuration with GATEWAY_LISTENER_<NAME>_* variables is available from Gateway 3.20.0. On earlier versions, networking is configured with the global variables described in Legacy network configuration. To move an existing deployment over, see Migrate to listener configuration.
Once you’ve configured a listener, the next step is to choose how clients authenticate against it. This page covers the security protocol and authentication options available for each listener. All open connections in Gateway result in a Principal that represents the authenticated identity of the Kafka client. Configuring listener security involves two key decisions:
  1. Security mode (GATEWAY_SECURITY_MODE): defines where authentication and authorization take place — Gateway or Kafka. This applies globally to all listeners.
  2. Security protocol (GATEWAY_LISTENER_<NAME>_SECURITY_PROTOCOL): defines how clients communicate and authenticate with a given listener. Set this per listener.
For local development and testing, you can skip listener configuration entirely. With no listener or networking variables set, Gateway runs in zero-config mode: it creates a default port-routing listener and infers the security mode and protocol from the backing Kafka cluster (with ACLs disabled). Don’t use it in production.
The examples below configure a single listener named DEFAULT. To expose Gateway through multiple endpoints with different security, see Set up multiple listeners.

Security mode

The GATEWAY_SECURITY_MODE environment variable determines where authentication and authorization take place. Gateway supports two modes:

GATEWAY_MANAGED

Gateway handles authentication and authorization. Use this mode when:
  • You want Gateway to manage clients’ credentials using local service accounts, or external ones from your identity provider (for OIDC) or certificates (for mTLS)
  • You need Gateway to enforce ACLs
  • You want the Gateway to be an abstraction layer that manages its own identities and ACLs
Compatible security protocols: PLAINTEXT, SSL, SASL_PLAINTEXT, SASL_SSL ACL behavior: Set GATEWAY_ACL_ENABLED to control ACL enforcement on the passthrough virtual cluster — typically true for this mode. Example configuration:
GATEWAY_SECURITY_MODE: GATEWAY_MANAGED
GATEWAY_ACL_ENABLED: true
GATEWAY_LISTENER_DEFAULT_SECURITY_PROTOCOL: SASL_SSL
GATEWAY_LISTENER_DEFAULT_ROUTING: sni
GATEWAY_LISTENER_DEFAULT_PORTS: 9092

KAFKA_MANAGED

Kafka handles authentication and authorization. Gateway forwards client credentials to the backing Kafka cluster. Use this mode when:
  • Your backing Kafka cluster manages all credentials
  • You want clients to use their existing Kafka credentials through Gateway
  • You need Gateway to respect Kafka’s ACLs and permissions
Compatible security protocols: SASL_PLAINTEXT, SASL_SSL only
KAFKA_MANAGED mode is incompatible with PLAINTEXT or SSL security protocols because these protocols don’t support credential forwarding to Kafka.
ACL behavior: Gateway doesn’t enforce ACLs on the passthrough virtual cluster in this mode — Kafka manages authorization, so GATEWAY_ACL_ENABLED has to be false. Setting it to true causes a startup error. Example configuration:
GATEWAY_SECURITY_MODE: KAFKA_MANAGED
GATEWAY_ACL_ENABLED: false
GATEWAY_LISTENER_DEFAULT_SECURITY_PROTOCOL: SASL_SSL
GATEWAY_LISTENER_DEFAULT_ROUTING: sni
GATEWAY_LISTENER_DEFAULT_PORTS: 9092

Security protocols

Gateway supports the following security protocols for client connections: In the table below, “security protocol” refers to the per-listener GATEWAY_LISTENER_<NAME>_SECURITY_PROTOCOL setting.
Clients ⟶ GW transit in plaintextClients ⟶ GW transit is encrypted
Anonymous access onlySecurity mode: GATEWAY_MANAGED
Security protocol: PLAINTEXT
Authentication mechanism: None
Security mode: GATEWAY_MANAGED
Security protocol: SSL
Authentication mechanism: None
Credentials managed by GatewaySecurity mode: GATEWAY_MANAGED
Security protocol: SASL_PLAINTEXT
Authentication mechanism: PLAIN
Security mode: GATEWAY_MANAGED
Security protocol: SASL_SSL
Authentication mechanism: PLAIN
Gateway configured with OAuthSecurity mode: GATEWAY_MANAGED
Security protocol: SASL_PLAINTEXT
Authentication mechanism: OAUTHBEARER
Security mode: GATEWAY_MANAGED
Security protocol: SASL_SSL
Authentication mechanism: OAUTHBEARER
Clients are identified by certificates (mTLS)Not possible (mTLS requires encryption)Security mode: GATEWAY_MANAGED
Security protocol: SSL
Authentication mechanism: MTLS
Credentials managed by KafkaSecurity mode: KAFKA_MANAGED
Security protocol: SASL_PLAINTEXT
Authentication mechanism: PLAIN, SCRAM-SHA-256, SCRAM-SHA-512, OAUTHBEARER or AWS_MSK_IAM
Security mode: KAFKA_MANAGED
Security protocol: SASL_SSL
Authentication mechanism: PLAIN, SCRAM-SHA-256, SCRAM-SHA-512, OAUTHBEARER or AWS_MSK_IAM

Configure security protocol

The GATEWAY_LISTENER_<NAME>_SECURITY_PROTOCOL environment variable defines how clients communicate with a given Gateway listener. In the examples below, the listener is named DEFAULT.
The global GATEWAY_SECURITY_PROTOCOL is deprecated in favor of the per-listener GATEWAY_LISTENER_<NAME>_SECURITY_PROTOCOL. If your deployment still sets it, see Legacy network configuration.
Gateway supports all standard Kafka security protocols. The following sections show configuration examples for each protocol with both security modes where applicable.

PLAINTEXT

There is no client authentication to Gateway and all communication is exchanged without any network security. Security mode: GATEWAY_MANAGED only Gateway configuration:
GATEWAY_SECURITY_MODE: GATEWAY_MANAGED
GATEWAY_ACL_ENABLED: true
GATEWAY_LISTENER_DEFAULT_SECURITY_PROTOCOL: PLAINTEXT
GATEWAY_LISTENER_DEFAULT_ROUTING: port
GATEWAY_LISTENER_DEFAULT_PORTS: 9092-9095
Client configuration:
bootstrap.servers=your.gateway.hostname:9092
security.protocol=PLAINTEXT

SSL

With SSL only, there is no client authentication, but communication between the client and Gateway broker will be encrypted. Security mode: GATEWAY_MANAGED only Gateway configuration:
GATEWAY_SECURITY_MODE: GATEWAY_MANAGED
GATEWAY_ACL_ENABLED: true
GATEWAY_LISTENER_DEFAULT_SECURITY_PROTOCOL: SSL
GATEWAY_LISTENER_DEFAULT_ROUTING: port
GATEWAY_LISTENER_DEFAULT_PORTS: 9092-9095
GATEWAY_SSL_KEY_STORE_PATH: /path/to/your/keystore.jks
GATEWAY_SSL_KEY_STORE_PASSWORD: yourKeystorePassword
GATEWAY_SSL_KEY_PASSWORD: yourKeyPassword
Client configuration:
bootstrap.servers=your.gateway.hostname:9092
security.protocol=SSL
ssl.truststore.location=/path/to/your/truststore.jks
ssl.truststore.password=yourTruststorePassword
ssl.protocol=TLSv1.3
The truststore contains certificates from trusted Certificate Authorities (CAs) used to verify Gateway’s TLS certificate, which is stored in the keystore. Find out more about JKS truststores.

mTLS

Mutual TLS leverages client side certificates to authenticate a Kafka client. Principal for an mTLS connection can be detected from the subject of the certificate using the same feature as Apache Kafka, the SSL principal mapping. Security mode: GATEWAY_MANAGED only Gateway configuration:
GATEWAY_SECURITY_MODE: GATEWAY_MANAGED
GATEWAY_ACL_ENABLED: true
GATEWAY_LISTENER_DEFAULT_SECURITY_PROTOCOL: SSL
GATEWAY_LISTENER_DEFAULT_ROUTING: port
GATEWAY_LISTENER_DEFAULT_PORTS: 9092-9095
GATEWAY_LISTENER_DEFAULT_SSL_CLIENT_AUTH: REQUIRE
GATEWAY_SSL_KEY_STORE_PATH: /path/to/your/keystore.jks
GATEWAY_SSL_KEY_STORE_PASSWORD: yourKeystorePassword
GATEWAY_SSL_KEY_PASSWORD: yourKeyPassword
GATEWAY_SSL_TRUST_STORE_PATH: /path/to/your/truststore.jks
GATEWAY_SSL_TRUST_STORE_PASSWORD: yourTrustStorePassword
Client configuration:
bootstrap.servers=your.gateway.hostname:9093
security.protocol=SSL
ssl.keystore.type=PEM
ssl.keystore.key=/path/to/your/client.key
ssl.keystore.certificate.chain=/path/to/your/client.crt
ssl.truststore.type=PEM
ssl.truststore.certificates=/path/to/your/ca.crt
ssl.protocol=TLSv1.3
ssl.client.auth=required
The server CA certificate here is provided as a PEM file as well as the client’s certificates (ssl.keystore.xx keys). Jks could also be used for both client and server side authentication.

SASL_PLAINTEXT

Authentication from the client is mandatory but all communications are exchanged without any network security. Security mode: GATEWAY_MANAGED or KAFKA_MANAGED
You don’t set GATEWAY_SASL_MECHANISM — this environment variable does not exist. Gateway automatically detects the authentication mechanism based on how the client presents itself. For example, if a client uses OAUTHBEARER, Gateway uses the OAuth configuration. If a client uses PLAIN, Gateway validates credentials based on the security mode.

Gateway-managed (PLAIN mechanism)

Plain mechanism uses username/password credentials to authenticate against Gateway. Credentials take the form of a JWT token managed in Gateway using the Admin (HTTP) API. Gateway configuration:
GATEWAY_SECURITY_MODE: GATEWAY_MANAGED
GATEWAY_ACL_ENABLED: true
GATEWAY_LISTENER_DEFAULT_SECURITY_PROTOCOL: SASL_PLAINTEXT
GATEWAY_LISTENER_DEFAULT_ROUTING: port
GATEWAY_LISTENER_DEFAULT_PORTS: 9092-9095
GATEWAY_USER_POOL_SECRET_KEY: yourRandom256bitKeyUsedToSignTokens
The GATEWAY_USER_POOL_SECRET_KEY has to be set to a random base64-encoded value of 256 bits to ensure that tokens aren’t forged. For example: openssl rand -base64 32. This value is required — Gateway has no default. Client configuration:
bootstrap.servers=your.gateway.hostname:9092
security.protocol=SASL_PLAINTEXT
sasl.mechanism=PLAIN
sasl.jaas.config=org.apache.kafka.common.security.plain.PlainLoginModule required \
  username="yourUsername" \
  password="yourToken";
It has to be a token that’s obtained by a Gateway admin via the Admin (HTTP) API, as follows:
  1. Create the service account, the username
Request:
curl \
  --request PUT \
  --url 'http://localhost:8888/gateway/v2/service-account' \
  --user admin:conduktor \
  --header 'Content-Type: application/json' \
  --data-raw '{
    "kind" : "GatewayServiceAccount",
    "apiVersion" : "gateway/v2",
    "metadata" : {
      "name" : "jdoe",
      "vCluster" : "passthrough"
    },
    "spec" : { "type" : "LOCAL" }'
Response:
{
  "resource" : {
    "kind" : "GatewayServiceAccount",
    "apiVersion" : "gateway/v2",
    "metadata" : {
      "name" : "jdoe",
      "vCluster" : "passthrough"
    },
    "spec" : {
      "type" : "LOCAL"
    }
  },
  "upsertResult" : "CREATED"
}
  1. Generate a token for the service account, the password
Request:
curl \
  --silent \
  --request POST \
  --url 'http://localhost:8888/gateway/v2/token' \
  --header 'Authorization: Basic YWRtaW46Y29uZHVrdG9y' \
  --header 'Content-Type: application/json' \
  --data-raw '{
    "username": "jdoe",
    "vCluster": "passthrough",
    "lifeTimeSeconds": 3600000
  }'
{"token":"eyJhbGciOiJIUzI1NiJ9.eyJ1c2VybmFtZSI6Impkb2UiLCJ2Y2x1c3RlciI6InBhc3N0aHJvdWdoIiwiZXhwIjoxNzQ1MzY1OTcxfQ.zPPiD17MiRnXyHJw07Cx4SKPySDi_ErJrXmi5BycR04"}
The token conforms to the JWT token specification. The JWT payload contains the username, the vCluster and the expiration date:
jwt decode eyJhbGciOiJIUzI1NiJ9.eyJ1c2VybmFtZSI6Impkb2UiLCJ2Y2x1c3RlciI6InBhc3N0aHJvdWdoIiwiZXhwIjoxNzQ1MzY1OTcxfQ.zPPiD17MiRnXyHJw07Cx4SKPySDi_ErJrXmi5BycR04

Token claims
------------
{
  "exp": 1745365971,
  "username": "jdoe",
  "vcluster": "passthrough"
}

Gateway-managed (OAUTHBEARER mechanism)

OAuthbearer uses an OAuth2/OIDC security provider to authenticate a token in Gateway. The OAuth credentials base is managed in the configured provider. This mechanism also allows you to verify claims from your OIDC provider (audience and issuer). Gateway configuration:
GATEWAY_SECURITY_MODE: GATEWAY_MANAGED
GATEWAY_ACL_ENABLED: true
GATEWAY_LISTENER_DEFAULT_SECURITY_PROTOCOL: SASL_PLAINTEXT
GATEWAY_LISTENER_DEFAULT_ROUTING: port
GATEWAY_LISTENER_DEFAULT_PORTS: 9092-9095
GATEWAY_OAUTH_JWKS_URL: https://login.microsoftonline.com/common/discovery/keys
GATEWAY_OAUTH_EXPECTED_ISSUER: https://sts.windows.net/xxxxxxxx-df00-48cd-805b-1ebe914e8b11/
GATEWAY_OAUTH_EXPECTED_AUDIENCES: "[00000002-0000-0000-c000-000000000000]"
Client configuration:
bootstrap.servers=your.gateway.hostname:9092
security.protocol=SASL_PLAINTEXT
sasl.mechanism=OAUTHBEARER
sasl.login.callback.handler.class=org.apache.kafka.common.security.oauthbearer.secured.OAuthBearerLoginCallbackHandler
sasl.oauthbearer.token.endpoint.url=https://login.microsoftonline.com/xxxxxxxx-df00-48cd-805b-1ebe914e8b11/oauth2/token
sasl.jaas.config=org.apache.kafka.common.security.oauthbearer.OAuthBearerLoginModule required \
 clientId="yourClientID" \
  clientSecret="yourClientSecret" \
  scope=".default";

Kafka-managed

Gateway forwards client credentials to the backing Kafka cluster for authentication. Credentials are managed by your backing Kafka cluster. Supported SASL mechanisms: PLAIN, SCRAM-SHA-256, SCRAM-SHA-512, OAUTHBEARER, AWS_MSK_IAM Gateway configuration:
GATEWAY_SECURITY_MODE: KAFKA_MANAGED
GATEWAY_ACL_ENABLED: false
GATEWAY_LISTENER_DEFAULT_SECURITY_PROTOCOL: SASL_PLAINTEXT
GATEWAY_LISTENER_DEFAULT_ROUTING: port
GATEWAY_LISTENER_DEFAULT_PORTS: 9092-9095
Client configuration (using PLAIN mechanism as an example):
bootstrap.servers=your.gateway.hostname:9092
security.protocol=SASL_PLAINTEXT
sasl.mechanism=PLAIN
sasl.jaas.config=org.apache.kafka.common.security.plain.PlainLoginModule required username="yourKafkaUser" password="yourKafkaPassword";

SASL_SSL

Authentication from client is mandatory and communication will be encrypted using TLS. Security mode: GATEWAY_MANAGED or KAFKA_MANAGED
You don’t set GATEWAY_SASL_MECHANISM — this environment variable does not exist. Gateway automatically detects the authentication mechanism based on how the client presents itself. For example, if a client uses OAUTHBEARER, Gateway uses the OAuth configuration. If a client uses PLAIN, Gateway validates credentials based on the security mode.

Gateway-managed (PLAIN mechanism)

Plain mechanism uses username/password credentials to authenticate against Gateway. Credentials are managed in Gateway using the HTTP API. Gateway configuration:
GATEWAY_SECURITY_MODE: GATEWAY_MANAGED
GATEWAY_ACL_ENABLED: true
GATEWAY_LISTENER_DEFAULT_SECURITY_PROTOCOL: SASL_SSL
GATEWAY_LISTENER_DEFAULT_ROUTING: port
GATEWAY_LISTENER_DEFAULT_PORTS: 9092-9095
GATEWAY_USER_POOL_SECRET_KEY: yourRandom256bitKeyUsedToSignTokens
GATEWAY_SSL_KEY_STORE_PATH: /path/to/your/keystore.jks
GATEWAY_SSL_KEY_STORE_PASSWORD: yourKeystorePassword
GATEWAY_SSL_KEY_PASSWORD: yourKeyPassword
You have to set GATEWAY_USER_POOL_SECRET_KEY to a random value to ensure that tokens cannot be forged. This value is required — Gateway has no default. Client configuration:
bootstrap.servers=your.gateway.hostname:9093
security.protocol=SASL_SSL
sasl.mechanism=PLAIN
ssl.truststore.location=/path/to/your/truststore.jks
ssl.truststore.password=yourTruststorePassword
sasl.jaas.config=org.apache.kafka.common.security.plain.PlainLoginModule required \
  username="yourUsername" \
  password="yourToken";
See the above section for requirements on how to create tokens using the Admin (HTTP) API.

Gateway-managed (OAUTHBEARER mechanism)

OAuthbearer uses an OAuth2/OIDC security provider to authenticate a token in Gateway. The OAuth credentials base is managed in the configured provider. This mechanism also allows you to verify claims from your OIDC provider (audience and issuer). Gateway configuration:
GATEWAY_SECURITY_MODE: GATEWAY_MANAGED
GATEWAY_ACL_ENABLED: true
GATEWAY_LISTENER_DEFAULT_SECURITY_PROTOCOL: SASL_SSL
GATEWAY_LISTENER_DEFAULT_ROUTING: port
GATEWAY_LISTENER_DEFAULT_PORTS: 9092-9095
GATEWAY_OAUTH_JWKS_URL: https://login.microsoftonline.com/common/discovery/keys
GATEWAY_OAUTH_EXPECTED_ISSUER: https://sts.windows.net/xxxxxxxx-df00-48cd-805b-1ebe914e8b11/
GATEWAY_OAUTH_EXPECTED_AUDIENCES: "[00000002-0000-0000-c000-000000000000]"
GATEWAY_SSL_KEY_STORE_PATH: /path/to/your/keystore.jks
GATEWAY_SSL_KEY_STORE_PASSWORD: yourKeystorePassword
GATEWAY_SSL_KEY_PASSWORD: yourKeyPassword
Client configuration:
bootstrap.servers=your.gateway.hostname:9092
security.protocol=SASL_SSL
sasl.mechanism=OAUTHBEARER
ssl.truststore.location=/path/to/your/truststore.jks
ssl.truststore.password=yourTruststorePassword
sasl.login.callback.handler.class=org.apache.kafka.common.security.oauthbearer.secured.OAuthBearerLoginCallbackHandler
sasl.oauthbearer.token.endpoint.url=https://login.microsoftonline.com/xxxxxxxx-df00-48cd-805b-1ebe914e8b11/oauth2/token
sasl.jaas.config=org.apache.kafka.common.security.oauthbearer.OAuthBearerLoginModule required \
  clientId="yourClientID" \
  clientSecret="yourClientSecret" \
  scope=".default";

Kafka-managed

Gateway forwards client credentials to the backing Kafka cluster for authentication. Credentials are managed by your backing Kafka cluster. Supported SASL mechanisms: PLAIN, SCRAM-SHA-256, SCRAM-SHA-512, OAUTHBEARER, AWS_MSK_IAM Gateway configuration:
GATEWAY_SECURITY_MODE: KAFKA_MANAGED
GATEWAY_ACL_ENABLED: false
GATEWAY_LISTENER_DEFAULT_SECURITY_PROTOCOL: SASL_SSL
GATEWAY_LISTENER_DEFAULT_ROUTING: port
GATEWAY_LISTENER_DEFAULT_PORTS: 9092-9095
GATEWAY_SSL_KEY_STORE_PATH: /path/to/your/keystore.jks
GATEWAY_SSL_KEY_STORE_PASSWORD: yourKeystorePassword
GATEWAY_SSL_KEY_PASSWORD: yourKeyPassword
Client configuration (using PLAIN mechanism as an example):
bootstrap.servers=your.gateway.hostname:9092
security.protocol=SASL_SSL
sasl.mechanism=PLAIN
ssl.truststore.location=/path/to/your/truststore.jks
ssl.truststore.password=yourTruststorePassword
sasl.jaas.config=org.apache.kafka.common.security.plain.PlainLoginModule required username="yourKafkaUser" password="yourKafkaPassword";

Principal resolver

When using Confluent Cloud authentication with Kafka-managed mode, Gateway supports automatically resolving API keys to their associated service account. This feature enhances security and improves usability by working with the service account principals instead of raw API keys. See the principal resolver environment variables. Gateway configuration using environment variables:
GATEWAY_PRINCIPAL_RESOLVER: CONFLUENT_CLOUD
GATEWAY_CONFLUENT_CLOUD_API_KEY: your-api-key
GATEWAY_CONFLUENT_CLOUD_API_SECRET: your-api-secret
GATEWAY_CONFLUENT_CLOUD_CACHE_SIZE: 1000 # default
GATEWAY_CONFLUENT_CLOUD_CACHE_EXPIRY_MS: 86400000 # 1 day default
Gateway configuration using a configuration file
authenticationConfig:
  principalResolver: CONFLUENT_CLOUD
  confluentCloud:
    apiKey: ${GATEWAY_CONFLUENT_CLOUD_API_KEY}
    apiSecret: ${GATEWAY_CONFLUENT_CLOUD_API_SECRET}
    cacheConfig:
      maxSize: ${GATEWAY_CONFLUENT_CLOUD_CACHE_SIZE|1000}
      ttlMs: ${GATEWAY_CONFLUENT_CLOUD_CACHE_EXPIRY_MS|86400000} # 1 day
The value of GATEWAY_CONFLUENT_CLOUD_API_KEY has to be a Confluent Cloud API key because it will be used to access the Confluent Cloud API. Find out more about Confluent Cloud API keys.
When the principal resolver is configured, Gateway will automatically resolve Kafka cluster API keys (like XIGMNERQXOUKXDQU) to their associated owner, which will be either the user (e.g. u-12345) or the service account (e.g. sa-72839j).

Authentication flow

Re-authentication support

We support Apache Kafka re-authentication as Kafka brokers. Find out more about KIP-368.