...
There are several configuration options for this callback handler:
...
. Sensitive configuration options and SASL extensions appear under the JAAS configuration (sasl.jaas.config
) while the rest are top-level configuration.
The JAAS configuration options are:
clientId
: supports OAuthclientcredentials
grant typeclientSecret
: supports OAuth'sclientcredentials
grantscope
: optional scope to reference in the call to the OAuth server
The top-level configuration options for the client login callback handler are:
sasl.login.token.endpoint.uri
: OAuth issuer token endpoint URIsasl.login.scope.claim.name
: optional override name of the scope claimscopeClaimName
: optional override name of the scope claim; defaults toscope
subClaimName
sasl.login.sub.claim.name
: optional override name of the sub claim; defaults tosub
loginConnectTimeoutMs
sasl.login.connect.timeout.ms
: optional value in milliseconds for HTTPS connect timeout; defaults to10000
loginReadTimeoutMs
sasl.login.read.timeout.ms
: optional value in milliseconds for HTTPS read timeout; defaults to10000
loginAttempts
sasl.login.attempts
: optional number of attempts to make to connect to the OAuth/OIDC identity provider; defaults to3
loginRetryWaitMs
sasl.login.retry.wait.ms
: optional value in milliseconds for the amount of time to wait between HTTPS call attempts; defaults to 250loginRetryMaxWaitMs
sasl.login.retry.max.wait.ms
: optional value in milliseconds for the maximum wait between HTTPS call attempts (as described above); defaults to10000
...
sasl.login.callback.handler.class=...OAuthBearerLoginCallbackHandlersasl.
jaaslogin.
config=token.
..OAuthBearerLoginModule required \
tokenEndpointUri="endpoint.uri=https://myidp.example.com/oauth2/default/v1/token
"
sasl.jaas.config=...OAuthBearerLoginModule required \
clientId="abc123" \
clientSecret="S3cr3t!" \
scope="sales-pipeline" \
extension_supportFeatureX="true" \
extension_organizationId="sales-emea" ;
In the above example, only the OAuth provider’s tokenEndpointUri
to retrieve an access token provider’s sasl.login.token.endpoint.uri
has been specified. The values for clientId
and clientSecret
as provided by the OAuth provider for an “API” or “machine-to-machine” account are required. The optional scope
value will allow the inclusion of a scope
parameter when requesting the token.
...
Once the login has occurred for this client, the returned access token can be reused by other connections from this client. While these additional connections will not issue the token retrieval HTTP call on the client, the broker will still validate the token repeatedly once for each time it is receivedsent by each client connection.
Per KIP-368, the OAuth token re-authentication logic from the existing implementation is automatically "inherited" by this implementation, so no additional work is needed to support that feature.
...
It may be that the names of the claims used by the OAuth provider differ from what is expected. For example, the security principal for which the token is valid is usually contained in the sub
(subject) JWT claim. There may be cases where the value of that claim may not be valid or usable, and instead the value will need to be extracted from, for example, the email
claim.
There are a handful of several configuration options for this callback handler:. Since there are no sensitive configuration options, they are all in the top-level configuration:
listener.name.<listener name>.oauthbearer.sasl.jwks.endpoint.uri
jwksEndpointUri
: OAuth issuer's JWK Set endpoint URI from which to retrieve the set of JWKs managed managed by the provider; mutually exclusive withjwksFile
jwksEndpointRefreshIntervalMs
: optional value in milliseconds for how often to refresh the JWKS from the URL pointed to byjwksEndpointUri
. Only used when usingjwksEndpointUri
. Defaults to3600000
(1 hour)jwksFile
: specifies a locally-accessible file name that holds a filethis can be a
OIDC provider; mutually exclusive withfile://
-based URL that points to a broker file system-accessible file-based copy of the JWKS data. This allows the JWKS data to be updated on the file system and refreshed on the broker when the file is updated, thus avoiding any HTTP communication with the OAuth/jwksEndpointUri
OIDC provider
listener.name.<listener name>.oauthbearer.sasl.jwks.refresh.interval.ms
: optional value in milliseconds for how often to refresh the JWKS from the URL pointed to bylistener.name.<listener name>.oauthbearer.sasl.jwks.endpoint.uri
. Only used when using an HTTP or HTTPS-based URI forlistener.name.<listener name>.oauthbearer.sasl.jwks.endpoint.uri
. Defaults to3600000
(1 hour)listener.name.<listener name>.oauthbearer.sasl.sub.claim.name
subClaimName
: name of the scope from which to extract the subject claim from the JWT; defaults tosub
scopeClaimName
listener.name.<listener name>.oauthbearer.sasl.scope.claim.name
: name of the scope from which to extract the scope claim from the JWT; defaults toscope
scope
listener.name.<listener name>.oauthbearer.sasl.clock.skew.seconds
clockSkew
: optional value in seconds for the clock skew between the OAuththe OAuth/OIDC provider and the broker. Only used when usingjwksEndpointUri
an HTTP or HTTPS-based URI forlistener.name.<listener name>.oauthbearer.sasl.jwks.endpoint.uri
. Defaults to30
expectedAudience
listener.name.<listener name>.oauthbearer.sasl.expected.audience
: The (optional) comma-delimited setting for the broker to use to verify that the JWT was issued for one of the expected audiences. The JWT will be inspected for the standard OAuthaud
claim and if this configuration option is set, the broker will match the value from JWT'saud
claim to see if there is an exact match. If there is no match, the broker will reject the JWT and authentication will fail.expectedIssuer
listener.name.<listener name>.oauthbearer.sasl.expected.issuer
: Optional setting for the broker to use to verify that the JWT was created by the expected issuer. The JWT will be inspected for the standard OAuthiss
claim and if this configuration option is set, the broker will match the value from JWT'siss
claim to see if there is an exact match. If there is no match, the broker will reject the JWT and authentication will fail.
Here's an example of the configuration as a part of a Java properties file:
listener.name.<listener name>.oauthbearer.sasl.login.callback.handler.class=o.a.k...OAuthBearerValidatorCallbackHandler
sasllistener.
jaas.config=o.a.k...OAuthBearerLoginModule required \
jwksEndpointUri="name.<listener name>.oauthbearer.sasl.jwks.endpoint.uri=https://myidp.example.com/oauth2/default/v1/keys
"
listener.name.<listener name>.oauthbearer.sasl.jaas.config=o.a.k...OAuthBearerLoginModule required \
scopeClaimName="scp" ;
In the above configuration the broker points to the appropriate OAuth provider jwksEndpointUri
provider listener.name.<listener name>.oauthbearer.sasl.jwks.endpoint.uri
to retrieve a the set of JWKs for validation. In this example, a non-default value for scopeClaimName
has been provided because the provider uses scp
for the name of the scope claim in the JWT it produces.
...
Providing a JWKS URL. In this mode, the JWKS data will be retrieved from the OAuth provider via the configured URL on broker startup. All then-current keys will be cached on the broker (per the ‘max age’; the jose4j library has a means to keep these-up-to-date when they age out) for incoming requests. If an authentication request is received for a JWT that includes a
kid
that isn’t yet in the cache, the JWKS endpoint will be queried again on demand. However, we prefer polling via a background thread to hopefully pre-populate the cache with any forthcoming keys before any JWT requests that include them are received.Providing a JWKS file. On startup, the broker will load the JWKS file from a the configured location and will watch the file for updates, allowing for dynamic configuration updates. Any updates to the file will require a restart of the broker. The means by which the JWKS file is updated is left to the cluster administrator. In the event that an that an unknown JWT key is encountered, this implementation will simply issue an error and validation will fail.
...
The use of OAuth credentials for broker-to-broker communication will continue to be supported. As with the existing implementation, users can specify the protocols and implementations to use for broker-based communication. This would require providing the appropriate configuration for both client login and broker validation.
Testing
In addition to unit and integration tests, there will be a standalone tool in the tools directory/module: org.apache.kafka.tools.OAuthCompatibilityTest
. This test can be run via the existing bin/kafka-run-class.sh
script thusly:
...