16.2. Using OAuth 2.0 token-based authentication
Streams for Apache Kafka supports the use of OAuth 2.0 for token-based authentication. An OAuth 2.0 authorization server handles the granting of access and inquiries about access. Kafka clients authenticate to Kafka brokers. Brokers and clients communicate with the authorization server, as necessary, to obtain or validate access tokens.
For a deployment of Streams for Apache Kafka, OAuth 2.0 integration provides the following support:
- Server-side OAuth 2.0 authentication for Kafka brokers
- Client-side OAuth 2.0 authentication for Kafka MirrorMaker, Kafka Connect, and the Kafka Bridge
To secure Kafka brokers with OAuth 2.0 authentication, configure a listener in the Kafka resource to use OAUth 2.0 authentication and a client authentication mechanism, and add further configuration depending on the authentication mechanism and type of token validation used in the authentication.
Configuring listeners to use oauth authentication
Specify a listener in the Kafka resource with an oauth authentication type. You can configure internal and external listeners. We recommend using OAuth 2.0 authentication together with TLS encryption (tls: true). Without encryption, the connection is vulnerable to network eavesdropping and unauthorized access through token theft.
Example listener configuration with OAuth 2.0 authentication
apiVersion: kafka.strimzi.io/v1beta2
kind: Kafka
spec:
kafka:
# ...
listeners:
- name: tls
port: 9093
type: internal
tls: true
authentication:
type: oauth
- name: external3
port: 9094
type: loadbalancer
tls: true
authentication:
type: oauth
#...
Enabling SASL authentication mechanisms
Use one or both of the following SASL mechanisms for clients to exchange credentials and establish authenticated sessions with Kafka.
OAUTHBEARERUsing the
OAUTHBEARERauthentication mechanism, credentials exchange uses a bearer token provided by an OAuth callback handler. Token provision can be configured to use the following methods:- Client ID and secret (using the OAuth 2.0 client credentials mechanism)
- Client ID and client assertion
- Long-lived access token or Service account token
- Long-lived refresh token obtained manually
OAUTHBEARERis recommended as it provides a higher level of security thanPLAIN, though it can only be used by Kafka clients that support theOAUTHBEARERmechanism at the protocol level. Client credentials are never shared with Kafka.PLAINPLAINis a simple authentication mechanism used by all Kafka client tools. Consider usingPLAINonly with Kafka clients that do not supportOAUTHBEARER. Using thePLAINauthentication mechanism, credentials exchange can be configured to use the following methods:- Client ID and secret (using the OAuth 2.0 client credentials mechanism)
-
Long-lived access token
Regardless of the method used, the client must provideusernameandpasswordproperties to Kafka.
Credentials are handled centrally behind a compliant authorization server, similar to how
OAUTHBEARERauthentication is used. The username extraction process depends on the authorization server configuration.
OAUTHBEARER is automatically enabled in the oauth listener configuration for the Kafka broker. To use the PLAIN mechanism, you must set the enablePlain property to true.
In the following example, the PLAIN mechanism is enabled, and the OAUTHBEARER mechanism is disabled on a listener using the enableOauthBearer property.
Example listener configuration for the PLAIN mechanism
apiVersion: kafka.strimzi.io/v1beta2
kind: Kafka
spec:
kafka:
# ...
listeners:
- name: tls
port: 9093
type: internal
tls: true
authentication:
type: oauth
- name: external3
port: 9094
type: loadbalancer
tls: true
authentication:
type: oauth
enablePlain: true
enableOauthBearer: false
#...
When you have defined the type of authentication as OAuth 2.0, you add configuration based on the type of validation, either as fast local JWT validation or token validation using an introspection endpoint.
Configuring fast local JWT token validation
Fast local JWT token validation involves checking a JWT token signature locally to ensure that the token meets the following criteria:
-
Contains a
typ(type) ortoken_typeheader claim value ofBearerto indicate it is an access token - Is currently valid and not expired
-
Has an issuer that matches a
validIssuerURI
You specify a validIssuerURI attribute when you configure the listener, so that any tokens not issued by the authorization server are rejected.
The authorization server does not need to be contacted during fast local JWT token validation. You activate fast local JWT token validation by specifying a jwksEndpointUri attribute, the endpoint exposed by the OAuth 2.0 authorization server. The endpoint contains the public keys used to validate signed JWT tokens, which are sent as credentials by Kafka clients.
All communication with the authorization server should be performed using TLS encryption. You can configure a certificate truststore as an OpenShift Secret in your Streams for Apache Kafka project namespace, and use the tlsTrustedCertificates property to point to the OpenShift secret containing the truststore file.
You might want to configure a userNameClaim to properly extract a username from the JWT token. If required, you can use a JsonPath expression like "['user.info'].['user.id']" to retrieve the username from nested JSON attributes within a token.
If you want to use Kafka ACL authorization, identify the user by their username during authentication. (The sub claim in JWT tokens is typically a unique ID, not a username.)
Example configuration for fast local JWT token validation
#...
- name: external3
port: 9094
type: loadbalancer
tls: true
authentication:
type: oauth
validIssuerUri: https://<auth_server_address>/<issuer-context>
jwksEndpointUri: https://<auth_server_address>/<path_to_jwks_endpoint>
userNameClaim: preferred_username
maxSecondsWithoutReauthentication: 3600
tlsTrustedCertificates:
- secretName: oauth-server-cert
pattern: "*.crt"
disableTlsHostnameVerification: true
jwksExpirySeconds: 360
jwksRefreshSeconds: 300
jwksMinRefreshPauseSeconds: 1
- 1
- Listener type set to
oauth. - 2
- URI of the token issuer used for authentication.
- 3
- URI of the JWKS certificate endpoint used for local JWT validation.
- 4
- The token claim (or key) that contains the actual username used to identify the user. Its value depends on the authorization server. If necessary, a JsonPath expression like
"['user.info'].['user.id']"can be used to retrieve the username from nested JSON attributes within a token. - 5
- (Optional) Activates the Kafka re-authentication mechanism that enforces session expiry to the same length of time as the access token. If the specified value is less than the time left for the access token to expire, then the client will have to re-authenticate before the actual token expiry. By default, the session does not expire when the access token expires, and the client does not attempt re-authentication.
- 6
- (Optional) Certificates stored in X.509 format within the specified secrets for TLS connection to the authorization server.
- 7
- (Optional) Disable TLS hostname verification. Default is
false. - 8
- The duration the JWKS certificates are considered valid before they expire. Default is
360seconds. If you specify a longer time, consider the risk of allowing access to revoked certificates. - 9
- The period between refreshes of JWKS certificates. The interval must be at least 60 seconds shorter than the expiry interval. Default is
300seconds. - 10
- The minimum pause in seconds between consecutive attempts to refresh JWKS public keys. When an unknown signing key is encountered, the JWKS keys refresh is scheduled outside the regular periodic schedule with at least the specified pause since the last refresh attempt. The refreshing of keys follows the rule of exponential backoff, retrying on unsuccessful refreshes with ever increasing pause, until it reaches
jwksRefreshSeconds. The default value is 1.
Configuring fast local JWT token validation with OpenShift service accounts
To configure the listener for OpenShift service accounts, the Kubernetes API server must be used as the authorization server.
Example configuration for fast local JWT token validation using Kubernetes API server as authorization server
#...
- name: external3
port: 9094
type: loadbalancer
tls: true
authentication:
type: oauth
validIssuerUri: https://kubernetes.default.svc.cluster.local
jwksEndpointUri: https://kubernetes.default.svc.cluster.local/openid/v1/jwks
serverBearerTokenLocation: /var/run/secrets/kubernetes.io/serviceaccount/token
checkAccessTokenType: false
includeAcceptHeader: false
tlsTrustedCertificates:
- secretName: oauth-server-cert
pattern: "*.crt"
maxSecondsWithoutReauthentication: 3600
customClaimCheck: "@.['kubernetes.io'] && @.['kubernetes.io'].['namespace'] in ['myproject']"
- 1
- URI of the token issuer used for authentication. Must use FQDN, including the
.cluster.localextension, which may vary based on the OpenShift cluster configuration. - 2
- URI of the JWKS certificate endpoint used for local JWT validation. Must use FQDN, including the
.cluster.localextension, which may vary based on the OpenShift cluster configuration. - 3
- Location to the access token used by the Kafka broker to authenticate to the Kubernetes API server in order to access the
jwksEndpointUri. - 4
- Skip the access token type check, as the claim for this is not present in service account tokens.
- 5
- Skip sending
Acceptheader in HTTP requests to the JWKS endpoint, as the Kubernetes API server does not support it. - 6
- Trusted certificates to connect to authorization server. This should point to a manually created Secret that contains the Kubernetes API server public certificate, which is mounted to the running pods under
/var/run/secrets/kubernetes.io/serviceaccount/ca.crt. You can use the following command to create the Secret:oc get cm kube-root-ca.crt -o jsonpath="{['data']['ca\.crt']}" > /tmp/ca.crt oc create secret generic oauth-server-cert --from-file=ca.crt=/tmp/ca.crt - 7
- (Optional) Additional constraints that JWT token has to fulfill in order to be accepted, expressed as JsonPath filter query. In this example the service account has to belong to
myprojectnamespace in order to be allowed to authenticate.
The above configuration uses the sub claim from the service account JWT token as the user ID. For example, the default service account for pods deployed in the myproject namespace has the username: system:serviceaccount:myproject:default.
When configuring ACLs the general form of how to refer to the ServiceAccount user should in that case be: User:system:serviceaccount:<Namespace>:<ServiceAccount-name>
Configuring token validation using an introspection endpoint
Token validation using an OAuth 2.0 introspection endpoint treats a received access token as opaque. The Kafka broker sends an access token to the introspection endpoint, which responds with the token information necessary for validation. Importantly, it returns up-to-date information if the specific access token is valid, and also information about when the token expires.
To configure OAuth 2.0 introspection-based validation, you specify an introspectionEndpointUri attribute rather than the jwksEndpointUri attribute specified for fast local JWT token validation. Depending on the authorization server, you typically have to specify a clientId and clientSecret, because the introspection endpoint is usually protected.
Example token validation configuration using an introspection endpoint
- name: external3
port: 9094
type: loadbalancer
tls: true
authentication:
type: oauth
validIssuerUri: https://<auth_server_address>/<issuer-context>
introspectionEndpointUri: https://<auth_server_address>/<path_to_introspection_endpoint>
clientId: kafka-broker
clientSecret:
secretName: my-cluster-oauth
key: clientSecret
userNameClaim: preferred_username
maxSecondsWithoutReauthentication: 3600
tlsTrustedCertificates:
- secretName: oauth-server-cert
pattern: "*.crt"
- 1
- URI of the token introspection endpoint.
- 2
- Client ID to identify the client.
- 3
- Client Secret and client ID is used for authentication.
- 4
- The token claim (or key) that contains the actual username used to identify the user. Its value depends on the authorization server. If necessary, a JsonPath expression like
"['user.info'].['user.id']"can be used to retrieve the username from nested JSON attributes within a token. - 5
- (Optional) Activates the Kafka re-authentication mechanism that enforces session expiry to the same length of time as the access token. If the specified value is less than the time left for the access token to expire, then the client will have to re-authenticate before the actual token expiry. By default, the session does not expire when the access token expires, and the client does not attempt re-authentication.
Authenticating brokers to the authorization server protected endpoints
Usually, the certificates endpoint of the authorization server (jwksEndpointUri) is publicly accessible, while the introspection endpoint (introspectionEndpointUri) is protected. However, this may vary depending on the authorization server configuration.
The Kafka broker can authenticate to the authorization server’s protected endpoints in one of two ways using HTTP authentication schemes:
- HTTP Basic authentication uses a client ID and secret.
- HTTP Bearer authentication uses a bearer token.
To configure HTTP Basic authentication, set the following properties:
-
clientId -
clientSecret
For HTTP Bearer authentication, set the following property:
-
serverBearerTokenLocationto specify the file path on disk containing the bearer token.
Including additional configuration options
Specify additional settings depending on the authentication requirements and the authorization server you are using. Some of these properties apply only to certain authentication mechanisms or when used in combination with other properties.
For example, when using OAUth over PLAIN, access tokens are passed as password property values with or without an $accessToken: prefix.
-
If you configure a token endpoint (
tokenEndpointUri) in the listener configuration, you need the prefix. - If you don’t configure a token endpoint in the listener configuration, you don’t need the prefix. The Kafka broker interprets the password as a raw access token.
If the password is set as the access token, the username must be set to the same principal name that the Kafka broker obtains from the access token. You can specify username extraction options in your listener using the userNameClaim, usernamePrefix, fallbackUserNameClaim, fallbackUsernamePrefix, and userInfoEndpointUri properties. The username extraction process also depends on your authorization server; in particular, how it maps client IDs to account names.
The PLAIN mechanism does not support password grant authentication. Use either client credentials (client ID + secret) or an access token for authentication.
Example optional configuration settings
# ...
authentication:
type: oauth
# ...
checkIssuer: false
checkAudience: true
usernamePrefix: user-
fallbackUserNameClaim: client_id
fallbackUserNamePrefix: client-account-
serverBearerTokenLocation: path/to/access/token
validTokenType: bearer
userInfoEndpointUri: https://<auth_server_address>/<path_to_userinfo_endpoint>
enableOauthBearer: false
enablePlain: true
tokenEndpointUri: https://<auth_server_address>/<path_to_token_endpoint>
customClaimCheck: "@.custom == 'custom-value'"
clientAudience: audience
clientScope: scope
connectTimeoutSeconds: 60
readTimeoutSeconds: 60
httpRetries: 2
httpRetryPauseMs: 300
groupsClaim: "$.groups"
groupsClaimDelimiter: ","
includeAcceptHeader: false
- 1
- If your authorization server does not provide an
issclaim, it is not possible to perform an issuer check. In this situation, setcheckIssuertofalseand do not specify avalidIssuerUri. Default istrue. - 2
- If your authorization server provides an
aud(audience) claim, and you want to enforce an audience check, setcheckAudiencetotrue. Audience checks identify the intended recipients of tokens. As a result, the Kafka broker will reject tokens that do not have itsclientIdin theiraudclaim. Default isfalse. - 3
- The prefix used when constructing the user ID. This only takes effect if
userNameClaimis configured. - 4
- An authorization server may not provide a single attribute to identify both regular users and clients. When a client authenticates in its own name, the server might provide a client ID. When a user authenticates using a username and password to obtain a refresh token or an access token, the server might provide a username attribute in addition to a client ID. Use this fallback option to specify the username claim (attribute) to use if a primary user ID attribute is not available. If necessary, a JsonPath expression like
"['client.info'].['client.id']"can be used to retrieve the fallback username to retrieve the username from nested JSON attributes within a token. - 5
- In situations where
fallbackUserNameClaimis applicable, it may also be necessary to prevent name collisions between the values of the username claim, and those of the fallback username claim. Consider a situation where a client calledproducerexists, but also a regular user calledproducerexists. In order to differentiate between the two, you can use this property to add a prefix to the user ID of the client. - 6
- The location of the access token used by the Kafka broker to authenticate to the Kubernetes API server for accessing protected endpoints. The authorization server must support
OAUTHBEARERauthentication. This is an alternative to specifyingclientIdandclientSecret, which usesPLAINauthentication. - 7
- (Only applicable when using
introspectionEndpointUri) Depending on the authorization server you are using, the introspection endpoint may or may not return the token type attribute, or it may contain different values. You can specify a valid token type value that the response from the introspection endpoint has to contain. - 8
- (Only applicable when using
introspectionEndpointUri) The authorization server may be configured or implemented in such a way to not provide any identifiable information in an introspection endpoint response. In order to obtain the user ID, you can configure the URI of theuserinfoendpoint as a fallback. TheuserNameClaim,fallbackUserNameClaim, andfallbackUserNamePrefixsettings are applied to the response ofuserinfoendpoint. - 9
- Set this to
falseto disable theOAUTHBEARERmechanism on the listener. At least one ofPLAINorOAUTHBEARERhas to be enabled. Default istrue. - 10
- Set to
trueto enablePLAINauthentication on the listener, which is supported for clients on all platforms. - 11
- Additional configuration for the
PLAINmechanism. If specified, clients can authenticate overPLAINby passing an access token as thepasswordusing an$accessToken:prefix. For production, always usehttps://urls. - 12
- Additional custom rules can be imposed on the JWT access token during validation by setting this to a JsonPath filter query. If the access token does not contain the necessary data, it is rejected. When using the
introspectionEndpointUri, the custom check is applied to the introspection endpoint response JSON. - 13
- An
audienceparameter passed to the token endpoint. An audience is used when obtaining an access token for inter-broker authentication. It is also used in the name of a client for OAuth 2.0 overPLAINclient authentication using aclientIdandsecret. This only affects the ability to obtain the token, and the content of the token, depending on the authorization server. It does not affect token validation rules by the listener. - 14
- A
scopeparameter passed to the token endpoint. A scope is used when obtaining an access token for inter-broker authentication. It is also used in the name of a client for OAuth 2.0 overPLAINclient authentication using aclientIdandsecret. This only affects the ability to obtain the token, and the content of the token, depending on the authorization server. It does not affect token validation rules by the listener. - 15
- The connect timeout in seconds when connecting to the authorization server. The default value is 60.
- 16
- The read timeout in seconds when connecting to the authorization server. The default value is 60.
- 17
- The maximum number of times to retry a failed HTTP request to the authorization server. The default value is
0, meaning that no retries are performed. To use this option effectively, consider reducing the timeout times for theconnectTimeoutSecondsandreadTimeoutSecondsoptions. However, note that retries may prevent the current worker thread from being available to other requests, and if too many requests stall, it could make the Kafka broker unresponsive. - 18
- The time to wait before attempting another retry of a failed HTTP request to the authorization server. By default, this time is set to zero, meaning that no pause is applied. This is because many issues that cause failed requests are per-request network glitches or proxy issues that can be resolved quickly. However, if your authorization server is under stress or experiencing high traffic, you may want to set this option to a value of 100 ms or more to reduce the load on the server and increase the likelihood of successful retries.
- 19
- A JsonPath query that is used to extract groups information from either the JWT token or the introspection endpoint response. This option is not set by default. By configuring this option, a custom authorizer can make authorization decisions based on user groups.
- 20
- A delimiter used to parse groups information when it is returned as a single delimited string. The default value is ',' (comma).
- 21
- Some authorization servers have issues with client sending
Accept: application/jsonheader. By settingincludeAcceptHeader: falsethe header will not be sent. Default istrue.
16.2.2. Configuring OAuth 2.0 on client applications 复制链接链接已复制到粘贴板!
To configure OAuth 2.0 on client applications, you must specify the following:
- SASL (Simple Authentication and Security Layer) security protocols
- SASL mechanisms
- A JAAS (Java Authentication and Authorization Service) module
- Authentication properties to access the authorization server
Configuring SASL protocols
Specify SASL protocols in the client configuration:
-
SASL_SSLfor authentication over TLS encrypted connections -
SASL_PLAINTEXTfor authentication over unencrypted connections
Use SASL_SSL for production and SASL_PLAINTEXT for local development only.
When using SASL_SSL, additional ssl.truststore configuration is needed. The truststore configuration is required for secure connection (https://) to the OAuth 2.0 authorization server. To verify the OAuth 2.0 authorization server, add the CA certificate for the authorization server to the truststore in your client configuration. You can configure a truststore in PEM or PKCS #12 format.
Configuring SASL authentication mechanisms
Specify SASL mechanisms in the client configuration:
-
OAUTHBEARERfor credentials exchange using a bearer token -
PLAINto pass client credentials (clientId + secret) or an access token
Configuring a JAAS module
Specify a JAAS module that implements the SASL authentication mechanism as a sasl.jaas.config property value:
-
org.apache.kafka.common.security.oauthbearer.OAuthBearerLoginModuleimplements theOAUTHBEARERmechanism -
org.apache.kafka.common.security.plain.PlainLoginModuleimplements thePLAINmechanism
For the OAUTHBEARER mechanism, Streams for Apache Kafka provides a callback handler for clients that use Kafka Client Java libraries to enable credentials exchange. For clients in other languages, custom code may be required to obtain the access token. For the PLAIN mechanism, Streams for Apache Kafka provides server-side callbacks to enable credentials exchange.
To be able to use the OAUTHBEARER mechanism, you must also add the custom io.strimzi.kafka.oauth.client.JaasClientOauthLoginCallbackHandler class as the callback handler. JaasClientOauthLoginCallbackHandler handles OAuth callbacks to the authorization server for access tokens during client login. This enables automatic token renewal, ensuring continuous authentication without user intervention. Additionally, it handles login credentials for clients using the OAuth 2.0 password grant method.
Configuring authentication properties
Configure the client to use credentials or access tokens for OAuth 2.0 authentication.
- Using client credentials
- Using client credentials involves configuring the client with the necessary credentials (client ID and secret, or client ID and client assertion) to obtain a valid access token from an authorization server. This is the simplest mechanism.
- Using access tokens
- Using access tokens, the client is configured with a valid long-lived access token or refresh token obtained from an authorization server. Using access tokens adds more complexity because there is an additional dependency on authorization server tools. If you are using long-lived access tokens, you may need to configure the client in the authorization server to increase the maximum lifetime of the token.
The only information ever sent to Kafka is the access token. The credentials used to obtain the token are never sent to Kafka. When a client obtains an access token, no further communication with the authorization server is needed.
SASL authentication properties support the following authentication methods:
- OAuth 2.0 client credentials
- Access token or Service account token
- Refresh token
- OAuth 2.0 password grant (deprecated)
Add the authentication properties as JAAS configuration (sasl.jaas.config and sasl.login.callback.handler.class).
If the client application is not configured with an access token directly, the client exchanges one of the following sets of credentials for an access token during Kafka session initiation:
- Client ID and secret
- Client ID and client assertion
- Client ID, refresh token, and (optionally) a secret
- Username and password, with client ID and (optionally) a secret
You can also specify authentication properties as environment variables, or as Java system properties. For Java system properties, you can set them using setProperty and pass them on the command line using the -D option.
Example client credentials configuration using the client secret
security.protocol=SASL_SSL
sasl.mechanism=OAUTHBEARER
ssl.truststore.location=/tmp/truststore.p12
ssl.truststore.password=$STOREPASS
ssl.truststore.type=PKCS12
sasl.jaas.config=org.apache.kafka.common.security.oauthbearer.OAuthBearerLoginModule required \
oauth.token.endpoint.uri="<token_endpoint_url>" \
oauth.client.id="<client_id>" \
oauth.client.secret="<client_secret>" \
oauth.ssl.truststore.location="/tmp/oauth-truststore.p12" \
oauth.ssl.truststore.password="$STOREPASS" \
oauth.ssl.truststore.type="PKCS12" \
oauth.scope="<scope>" \
oauth.audience="<audience>" ;
sasl.login.callback.handler.class=io.strimzi.kafka.oauth.client.JaasClientOauthLoginCallbackHandler
- 1
SASL_SSLsecurity protocol for TLS-encrypted connections. UseSASL_PLAINTEXTover unencrypted connections for local development only.- 2
- The SASL mechanism specified as
OAUTHBEARERorPLAIN. - 3
- The truststore configuration for secure access to the Kafka cluster.
- 4
- URI of the authorization server token endpoint.
- 5
- Client ID, which is the name used when creating the client in the authorization server.
- 6
- Client secret created when creating the client in the authorization server.
- 7
- The location contains the public key certificate (
truststore.p12) for the authorization server. - 8
- The password for accessing the truststore.
- 9
- The truststore type.
- 10
- (Optional) The
scopefor requesting the token from the token endpoint. An authorization server may require a client to specify the scope. - 11
- (Optional) The
audiencefor requesting the token from the token endpoint. An authorization server may require a client to specify the audience.
Example client credentials configuration using the client assertion
security.protocol=SASL_SSL
sasl.mechanism=OAUTHBEARER
ssl.truststore.location=/tmp/truststore.p12
ssl.truststore.password=$STOREPASS
ssl.truststore.type=PKCS12
sasl.jaas.config=org.apache.kafka.common.security.oauthbearer.OAuthBearerLoginModule required \
oauth.token.endpoint.uri="<token_endpoint_url>" \
oauth.client.id="<client_id>" \
oauth.client.assertion.location="<path_to_client_assertion_token_file>" \
oauth.client.assertion.type="urn:ietf:params:oauth:client-assertion-type:jwt-bearer" \
oauth.ssl.truststore.location="/tmp/oauth-truststore.p12" \
oauth.ssl.truststore.password="$STOREPASS" \
oauth.ssl.truststore.type="PKCS12" \
oauth.scope="<scope>" \
oauth.audience="<audience>" ;
sasl.login.callback.handler.class=io.strimzi.kafka.oauth.client.JaasClientOauthLoginCallbackHandler
- 1
- Path to the client assertion file used for authenticating the client. This file is a private key file as an alternative to the client secret. Alternatively, use the
oauth.client.assertionoption to specify the client assertion value in clear text. - 2
- (Optional) Sometimes you may need to specify the client assertion type. In not specified, the default value is
urn:ietf:params:oauth:client-assertion-type:jwt-bearer.
Example password grants configuration
security.protocol=SASL_SSL
sasl.mechanism=OAUTHBEARER
ssl.truststore.location=/tmp/truststore.p12
ssl.truststore.password=$STOREPASS
ssl.truststore.type=PKCS12
sasl.jaas.config=org.apache.kafka.common.security.oauthbearer.OAuthBearerLoginModule required \
oauth.token.endpoint.uri="<token_endpoint_url>" \
oauth.client.id="<client_id>" \
oauth.client.secret="<client_secret>" \
oauth.password.grant.username="<username>" \
oauth.password.grant.password="<password>" \
oauth.ssl.truststore.location="/tmp/oauth-truststore.p12" \
oauth.ssl.truststore.password="$STOREPASS" \
oauth.ssl.truststore.type="PKCS12" \
oauth.scope="<scope>" \
oauth.audience="<audience>" ;
sasl.login.callback.handler.class=io.strimzi.kafka.oauth.client.JaasClientOauthLoginCallbackHandler
- 1
- Client ID, which is the name used when creating the client in the authorization server.
- 2
- (Optional) Client secret created when creating the client in the authorization server.
- 3
- Username for password grant authentication. OAuth password grant configuration (username and password) uses the OAuth 2.0 password grant method. To use password grants, create a user account for a client on your authorization server with limited permissions. The account should act like a service account. Use in environments where user accounts are required for authentication, but consider using a refresh token first.
- 4
- Password for password grant authentication.注意
SASL
PLAINdoes not support passing a username and password (password grants) using the OAuth 2.0 password grant method.
Example access token configuration
security.protocol=SASL_SSL
sasl.mechanism=OAUTHBEARER
ssl.truststore.location=/tmp/truststore.p12
ssl.truststore.password=$STOREPASS
ssl.truststore.type=PKCS12
sasl.jaas.config=org.apache.kafka.common.security.oauthbearer.OAuthBearerLoginModule required \
oauth.access.token="<access_token>" ;
sasl.login.callback.handler.class=io.strimzi.kafka.oauth.client.JaasClientOauthLoginCallbackHandler
- 1
- Long-lived access token for Kafka clients. Alternatively,
oauth.access.token.locationcan be used to specify the file that contains the access token.
Example OpenShift service account token configuration
security.protocol=SASL_SSL
sasl.mechanism=OAUTHBEARER
ssl.truststore.location=/tmp/truststore.p12
ssl.truststore.password=$STOREPASS
ssl.truststore.type=PKCS12
sasl.jaas.config=org.apache.kafka.common.security.oauthbearer.OAuthBearerLoginModule required \
oauth.access.token.location="/var/run/secrets/kubernetes.io/serviceaccount/token";
sasl.login.callback.handler.class=io.strimzi.kafka.oauth.client.JaasClientOauthLoginCallbackHandler
- 1
- Location to the service account token on the filesystem (assuming that the client is deployed as an OpenShift pod)
Example refresh token configuration
security.protocol=SASL_SSL
sasl.mechanism=OAUTHBEARER
ssl.truststore.location=/tmp/truststore.p12
ssl.truststore.password=$STOREPASS
ssl.truststore.type=PKCS12
sasl.jaas.config=org.apache.kafka.common.security.oauthbearer.OAuthBearerLoginModule required \
oauth.token.endpoint.uri="<token_endpoint_url>" \
oauth.client.id="<client_id>" \
oauth.client.secret="<client_secret>" \
oauth.refresh.token="<refresh_token>" \
oauth.ssl.truststore.location="/tmp/oauth-truststore.p12" \
oauth.ssl.truststore.password="$STOREPASS" \
oauth.ssl.truststore.type="PKCS12" ;
sasl.login.callback.handler.class=io.strimzi.kafka.oauth.client.JaasClientOauthLoginCallbackHandler
16.2.3. OAuth 2.0 client authentication flows 复制链接链接已复制到粘贴板!
OAuth 2.0 authentication flows depend on the underlying Kafka client and Kafka broker configuration. The flows must also be supported by the authorization server used.
The Kafka broker listener configuration determines how clients authenticate using an access token. The client can pass a client ID and secret to request an access token.
If a listener is configured to use PLAIN authentication, the client can authenticate with a client ID and secret or username and access token. These values are passed as the username and password properties of the PLAIN mechanism.
Listener configuration supports the following token validation options:
- You can use fast local token validation based on JWT signature checking and local token introspection, without contacting an authorization server. The authorization server provides a JWKS endpoint with public certificates that are used to validate signatures on the tokens.
- You can use a call to a token introspection endpoint provided by an authorization server. Each time a new Kafka broker connection is established, the broker passes the access token received from the client to the authorization server. The Kafka broker checks the response to confirm whether the token is valid.
An authorization server might only allow the use of opaque access tokens, which means that local token validation is not possible.
Kafka client credentials can also be configured for the following types of authentication:
- Direct local access using a previously generated long-lived access token
- Contact with the authorization server for a new access token to be issued (using a client ID and credentials, or a refresh token, or a username and a password)
You can use the following communication flows for Kafka authentication using the SASL OAUTHBEARER mechanism.
Client using client ID and credentials, with broker delegating validation to authorization server
- The Kafka client requests an access token from the authorization server using a client ID and credentials, and optionally a refresh token. Alternatively, the client may authenticate using a username and a password.
- The authorization server generates a new access token.
-
The Kafka client authenticates with the Kafka broker using the SASL
OAUTHBEARERmechanism to pass the access token. - The Kafka broker validates the access token by calling a token introspection endpoint on the authorization server using its own client ID and secret.
- A Kafka client session is established if the token is valid.
Client using client ID and credentials, with broker performing fast local token validation
- The Kafka client authenticates with the authorization server from the token endpoint, using a client ID and credentials, and optionally a refresh token. Alternatively, the client may authenticate using a username and a password.
- The authorization server generates a new access token.
-
The Kafka client authenticates with the Kafka broker using the SASL
OAUTHBEARERmechanism to pass the access token. - The Kafka broker validates the access token locally using a JWT token signature check, and local token introspection.
Client using long-lived access token, with broker delegating validation to authorization server
-
The Kafka client authenticates with the Kafka broker using the SASL
OAUTHBEARERmechanism to pass the long-lived access token. - The Kafka broker validates the access token by calling a token introspection endpoint on the authorization server, using its own client ID and secret.
- A Kafka client session is established if the token is valid.
Client using long-lived access token, with broker performing fast local validation
-
The Kafka client authenticates with the Kafka broker using the SASL
OAUTHBEARERmechanism to pass the long-lived access token. - The Kafka broker validates the access token locally using a JWT token signature check and local token introspection.
Fast local JWT token signature validation is suitable only for short-lived tokens as there is no check with the authorization server if a token has been revoked. Token expiration is written into the token, but revocation can happen at any time, so cannot be accounted for without contacting the authorization server. Any issued token would be considered valid until it expires.
You can use the following communication flows for Kafka authentication using the OAuth PLAIN mechanism.
Client using a client ID and secret, with the broker obtaining the access token for the client
-
The Kafka client passes a
clientIdas a username and asecretas a password. -
The Kafka broker uses a token endpoint to pass the
clientIdandsecretto the authorization server. - The authorization server returns a fresh access token or an error if the client credentials are not valid.
The Kafka broker validates the token in one of the following ways:
- If a token introspection endpoint is specified, the Kafka broker validates the access token by calling the endpoint on the authorization server. A session is established if the token validation is successful.
- If local token introspection is used, a request is not made to the authorization server. The Kafka broker validates the access token locally using a JWT token signature check.
Client using a long-lived access token without a client ID and secret
- The Kafka client passes a username and password. The password provides the value of an access token that was obtained manually and configured before running the client.
The password is passed with or without an
$accessToken:string prefix depending on whether or not the Kafka broker listener is configured with a token endpoint for authentication.-
If the token endpoint is configured, the password should be prefixed by
$accessToken:to let the broker know that the password parameter contains an access token rather than a client secret. The Kafka broker interprets the username as the account username. -
If the token endpoint is not configured on the Kafka broker listener (enforcing a
no-client-credentials mode), the password should provide the access token without the prefix. The Kafka broker interprets the username as the account username. In this mode, the client doesn’t use a client ID and secret, and thepasswordparameter is always interpreted as a raw access token.
-
If the token endpoint is configured, the password should be prefixed by
The Kafka broker validates the token in one of the following ways:
- If a token introspection endpoint is specified, the Kafka broker validates the access token by calling the endpoint on the authorization server. A session is established if token validation is successful.
- If local token introspection is used, there is no request made to the authorization server. Kafka broker validates the access token locally using a JWT token signature check.
16.2.4. Re-authenticating sessions 复制链接链接已复制到粘贴板!
Configure oauth listeners to use Kafka session re-authentication for OAuth 2.0 sessions between Kafka clients and Kafka. This mechanism enforces the expiry of an authenticated session between the client and the broker after a defined period of time. When a session expires, the client immediately starts a new session by reusing the existing connection rather than dropping it.
Session re-authentication is disabled by default. To enable it, you set a time value for maxSecondsWithoutReauthentication in the oauth listener configuration. The same property is used to configure session re-authentication for OAUTHBEARER and PLAIN authentication. For an example configuration, see 第 16.2.1 节 “Configuring OAuth 2.0 authentication on listeners”.
Session re-authentication must be supported by the Kafka client libraries used by the client.
Session re-authentication can be used with fast local JWT or introspection endpoint token validation.
Client re-authentication
When the broker’s authenticated session expires, the client must re-authenticate to the existing session by sending a new, valid access token to the broker, without dropping the connection.
If token validation is successful, a new client session is started using the existing connection. If the client fails to re-authenticate, the broker will close the connection if further attempts are made to send or receive messages. Java clients that use Kafka client library 2.2 or later automatically re-authenticate if the re-authentication mechanism is enabled on the broker.
Session re-authentication also applies to refresh tokens, if used. When the session expires, the client refreshes the access token by using its refresh token. The client then uses the new access token to re-authenticate to the existing session.
Session expiry
When session re-authentication is configured, session expiry works differently for OAUTHBEARER and PLAIN authentication.
For OAUTHBEARER and PLAIN, using the client ID and secret method:
-
The broker’s authenticated session will expire at the configured
maxSecondsWithoutReauthentication. - The session will expire earlier if the access token expires before the configured time.
For PLAIN using the long-lived access token method:
-
The broker’s authenticated session will expire at the configured
maxSecondsWithoutReauthentication. -
Re-authentication will fail if the access token expires before the configured time. Although session re-authentication is attempted,
PLAINhas no mechanism for refreshing tokens.
If maxSecondsWithoutReauthentication is not configured, OAUTHBEARER and PLAIN clients can remain connected to brokers indefinitely, without needing to re-authenticate. Authenticated sessions do not end with access token expiry. However, this can be considered when configuring authorization, for example, by using keycloak authorization or installing a custom authorizer.
16.2.5. Example: Enabling OAuth 2.0 authentication 复制链接链接已复制到粘贴板!
This example shows how to configure client access to a Kafka cluster using OAUth 2.0 authentication. The procedures describe the configuration required to set up OAuth 2.0 authentication on Kafka listeners, Kafka Java clients, and Kafka components.
Configure Kafka listeners so that they are enabled to use OAuth 2.0 authentication using an authorization server.
We advise using OAuth 2.0 over an encrypted interface through through a listener with tls: true. Plain listeners are not recommended.
If the authorization server is using certificates signed by the trusted CA and matching the OAuth 2.0 server hostname, TLS connection works using the default settings. Otherwise, you may need to configure the truststore with proper certificates or disable the certificate hostname validation.
For more information on the configuration of OAuth 2.0 authentication for Kafka broker listeners, see the KafkaListenerAuthenticationOAuth schema reference.
Prerequisites
- Streams for Apache Kafka and Kafka are running
- An OAuth 2.0 authorization server is deployed
Procedure
Specify a listener in the
Kafkaresource with anoauthauthentication type.Example listener configuration with OAuth 2.0 authentication
apiVersion: kafka.strimzi.io/v1beta2 kind: Kafka spec: kafka: # ... listeners: - name: tls port: 9093 type: internal tls: true authentication: type: oauth - name: external3 port: 9094 type: loadbalancer tls: true authentication: type: oauth #...Configure the OAuth listener depending on the authorization server and validation type:
-
Apply the changes to the
Kafkaconfiguration. Check the update in the logs or by watching the pod state transitions:
oc logs -f ${POD_NAME} -c ${CONTAINER_NAME} oc get pod -wThe rolling update configures the brokers to use OAuth 2.0 authentication.
What to do next
16.2.5.2. Setting up OAuth 2.0 on Kafka Java clients 复制链接链接已复制到粘贴板!
Configure Kafka producer and consumer APIs to use OAuth 2.0 for interaction with Kafka brokers. Add a callback plugin to your client pom.xml file, then configure your client for OAuth 2.0.
How you configure the authentication properties depends on the authentication method you are using to access the OAuth 2.0 authorization server. In this procedure, the properties are specified in a properties file, then loaded into the client configuration.
Prerequisites
- Streams for Apache Kafka and Kafka are running
- An OAuth 2.0 authorization server is deployed and configured for OAuth access to Kafka brokers
- Kafka brokers are configured for OAuth 2.0
Procedure
Add the client library with OAuth 2.0 support to the
pom.xmlfile for the Kafka client:<dependency> <groupId>io.strimzi</groupId> <artifactId>kafka-oauth-client</artifactId> <version>0.15.0.redhat-00010</version> </dependency>Configure the client depending on the OAuth 2.0 authentication method:
For example, specify the properties for the authentication method in a
client.propertiesfile.Input the client properties for OAUTH 2.0 authentication into the Java client code.
Example showing input of client properties
Properties props = new Properties(); try (FileReader reader = new FileReader("client.properties", StandardCharsets.UTF_8)) { props.load(reader); }- Verify that the Kafka client can access the Kafka brokers.
16.2.5.3. Setting up OAuth 2.0 on Kafka components 复制链接链接已复制到粘贴板!
This procedure describes how to set up Kafka components to use OAuth 2.0 authentication using an authorization server.
You can configure OAuth 2.0 authentication for the following components:
- Kafka Connect
- Kafka MirrorMaker
- Kafka Bridge
In this scenario, the Kafka component and the authorization server are running in the same cluster.
Before you start
For more information on the configuration of OAuth 2.0 authentication for Kafka components, see the KafkaClientAuthenticationOAuth schema reference. The schema reference includes examples of configuration options.
Prerequisites
- Streams for Apache Kafka and Kafka are running
- An OAuth 2.0 authorization server is deployed and configured for OAuth access to Kafka brokers
- Kafka brokers are configured for OAuth 2.0
Procedure
Create a client secret and mount it to the component as an environment variable.
For example, here we are creating a client
Secretfor the Kafka Bridge:apiVersion: kafka.strimzi.io/v1beta2 kind: Secret metadata: name: my-bridge-oauth type: Opaque data: clientSecret: MGQ1OTRmMzYtZTllZS00MDY2LWI5OGEtMTM5MzM2NjdlZjQw1 - 1
- The
clientSecretkey must be in base64 format.
Create or edit the resource for the Kafka component so that OAuth 2.0 authentication is configured for the authentication property.
For OAuth 2.0 authentication, you can use the following options:
- Client ID and secret
- Client ID and client assertion
- Client ID and refresh token
- Access token
- Username and password
- TLS
For example, here OAuth 2.0 is assigned to the Kafka Bridge client using a client ID and secret, and TLS:
Example OAuth 2.0 authentication configuration using the client secret
apiVersion: kafka.strimzi.io/v1beta2 kind: KafkaBridge metadata: name: my-bridge spec: # ... authentication: type: oauth1 tokenEndpointUri: https://<auth_server_address>/<path_to_token_endpoint>2 clientId: kafka-bridge clientSecret: secretName: my-bridge-oauth key: clientSecret tlsTrustedCertificates:3 - secretName: oauth-server-cert pattern: "*.crt"In this example, OAuth 2.0 is assigned to the Kafka Bridge client using a client ID and the location of a client assertion file, with TLS to connect to the authorization server:
Example OAuth 2.0 authentication configuration using client assertion
apiVersion: kafka.strimzi.io/v1beta2 kind: KafkaBridge metadata: name: my-bridge spec: # ... authentication: type: oauth tokenEndpointUri: https://<auth_server_address>/<path_to_token_endpoint> clientId: kafka-bridge clientAssertionLocation: /var/run/secrets/sso/assertion1 tlsTrustedCertificates: - secretName: oauth-server-cert pattern: "*.crt"- 1
- Filesystem path to the client assertion file used for authenticating the client. This file is typically added to the deployed pod by an external operator service. Alternatively, use
clientAssertionto refer to a secret containing the client assertion value.
Here, OAuth 2.0 is assigned to the Kafka Bridge client using a service account token:
Example OAuth 2.0 authentication configuration using the service account token
apiVersion: kafka.strimzi.io/v1beta2 kind: KafkaBridge metadata: name: my-bridge spec: # ... authentication: type: oauth accessTokenLocation: /var/run/secrets/kubernetes.io/serviceaccount/token1 - 1
- Path to the service account token file location.
Depending on how you apply OAuth 2.0 authentication, and the type of authorization server, there are additional configuration options you can use:
Additional configuration options
# ... spec: # ... authentication: # ... disableTlsHostnameVerification: true1 accessTokenIsJwt: false2 scope: any3 audience: kafka4 connectTimeoutSeconds: 605 readTimeoutSeconds: 606 httpRetries: 27 httpRetryPauseMs: 3008 includeAcceptHeader: false9 - 1
- (Optional) Disable TLS hostname verification. Default is
false. - 2
- If you are using opaque tokens, you can apply
accessTokenIsJwt: falseso that access tokens are not treated as JWT tokens. - 3
- (Optional) The
scopefor requesting the token from the token endpoint. An authorization server may require a client to specify the scope. In this case it isany. - 4
- (Optional) The
audiencefor requesting the token from the token endpoint. An authorization server may require a client to specify the audience. In this case it iskafka. - 5
- (Optional) The connect timeout in seconds when connecting to the authorization server. The default value is 60.
- 6
- (Optional) The read timeout in seconds when connecting to the authorization server. The default value is 60.
- 7
- (Optional) The maximum number of times to retry a failed HTTP request to the authorization server. The default value is
0, meaning that no retries are performed. To use this option effectively, consider reducing the timeout times for theconnectTimeoutSecondsandreadTimeoutSecondsoptions. However, note that retries may prevent the current worker thread from being available to other requests, and if too many requests stall, it could make the Kafka broker unresponsive. - 8
- (Optional) The time to wait before attempting another retry of a failed HTTP request to the authorization server. By default, this time is set to zero, meaning that no pause is applied. This is because many issues that cause failed requests are per-request network glitches or proxy issues that can be resolved quickly. However, if your authorization server is under stress or experiencing high traffic, you may want to set this option to a value of 100 ms or more to reduce the load on the server and increase the likelihood of successful retries.
- 9
- (Optional) Some authorization servers have issues with client sending
Accept: application/jsonheader. By settingincludeAcceptHeader: falsethe header will not be sent. Default istrue.
- Apply the changes to the resource configuration of the component.
Check the update in the logs or by watching the pod state transitions:
oc logs -f ${POD_NAME} -c ${CONTAINER_NAME} oc get pod -wThe rolling updates configure the component for interaction with Kafka brokers using OAuth 2.0 authentication.