...
Finally, note that the implementation of flexible, substitution-aware configuration that was originally proposed in an early draft of this KIP was at first deemed more generally useful and was separated out into its own KIP-269: Substitution Within Configuration Values, but that KIP is likely to be rejected/moved to the inactive list and is not required fort this for this KIP (see Rejected Alternatives: Substitution Within Configuration Values).
...
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
package org.apache.kafka.common.security.oauthbearer; /** * The <code>b64token</code> value as defined in * <a href="https://tools.ietf.org/html/rfc6750#section-2.1">RFC 6750 Section * 2.1</a> along with the token's specific scope and lifetime and principal * name. * <p> * A network request would be required to re-hydrate an opaque token, and that * could result in (for example) an {@code IOException}, but retrievers for * various attributes ({@link #scope()}, {@link #lifetime#lifetimeMs()}, etc.) declare no * exceptions. Therefore, if a network request is required for any of these * retriever methods, that request could be performed at construction time so * that the various attributes can be reliably provided thereafter. For example, * a constructor might declare {@code throws IOException} in such a case. * Alternatively, the retrievers could throw unchecked exceptions. * * @see <a href="https://tools.ietf.org/html/rfc6749#section-1.4">RFC 6749 * Section 1.4</a> and * <a href="https://tools.ietf.org/html/rfc6750#section-2.1">RFC 6750 * Section 2.1</a> */ public interface OAuthBearerToken { /** * The <code>b64token</code> value as defined in * <a href="https://tools.ietf.org/html/rfc6750#section-2.1">RFC 6750 Section * 2.1</a> * * @return <code>b64token</code> value as defined in * <a href="https://tools.ietf.org/html/rfc6750#section-2.1">RFC 6750 * Section 2.1</a> */ String value(); /** * The token's scope of access, as per * <a href="https://tools.ietf.org/html/rfc6749#section-1.4">RFC 6749 Section * 1.4</a> * * @return the token's (always non-null but potentially empty) scope of access, * as per <a href="https://tools.ietf.org/html/rfc6749#section-1.4">RFC * 6749 Section 1.4</a>. Note that all values in the returned set will * be trimmed of preceding and trailing whitespace, and the result will * never contain the empty string. */ Set<String> scope(); /** * The token's lifetime, expressed as the number of milliseconds since the * epoch, as per <a href="https://tools.ietf.org/html/rfc6749#section-1.4">RFC * 6749 Section 1.4</a> * * @return the token'slifetime, expressed as the number of milliseconds since * the epoch, as per * <a href="https://tools.ietf.org/html/rfc6749#section-1.4">RFC 6749 * Section 1.4</a>. */ long lifetimeMs(); /** * The name of the principal to which this credential applies * * @return the always non-null/non-empty principal name */ String principalName(); /** * When the credential became valid, in terms of the number of milliseconds * since the epoch, if known, otherwise null. An expiring credential may not * necessarily indicate when it was created -- just when it expires -- so we * need to support a null return value here. * * @return the time when the credential became valid, in terms of the number of * milliseconds since the epoch, if known, otherwise null */ Long startTimeMs(); } |
Code Block | ||||||
---|---|---|---|---|---|---|
| ||||||
package org.apache.kafka.common.security.oauthbearer; /** * The {@code LoginModule} for the SASL/OAUTHBEARER mechanism. When a client * (whether a non-broker client or a broker when SASL/OAUTHBEARER is the * inter-broker protocol) connects to Kafka the {@link@code OAuthBearerLoginModule} * instance asks its configured {@link AuthenticateCallbackHandler} * implementation to handle an instance of {@link OAuthBearerTokenCallback} and * return an instance of {@link OAuthBearerToken}. A default, builtin * {@link AuthenticateCallbackHandler} implementation creates an unsecured token * as defined by these JAAS module options: * <table> * <tr> * <th>JAAS Module Option for Unsecured Token Retrieval</th> * <th>Documentation</th> * </tr> * <tr> * <td>{@code unsecuredLoginStringClaim_<claimname>="value"}</td> * <td>Creates a {@code String} claim with the given name and value. Any valid * claim name can be specified except '{@code iat}' and '{@code exp}' (these are * automatically generated).</td> * </tr> * <tr> * <td>{@code unsecuredLoginNumberClaim_<claimname>="value"}</td> * <td>Creates a {@code Number} claim with the given name and value. Any valid * claim name can be specified except '{@code iat}' and '{@code exp}' (these are * automatically generated).</td> * </tr> * <tr> * <td>{@code unsecuredLoginListClaim_<claimname>="value"}</td> * <td>Creates a {@code String List} claim with the given name and values parsed * from the given value where the first character is taken as the delimiter. For * example: {@code unsecuredLoginListClaim_fubar="|value1|value2"}. Any valid * claim name can be specified except '{@code iat}' and '{@code exp}' (these are * automatically generated).</td> * </tr> * <tr> * <td>{@code unsecuredLoginPrincipalClaimName}</td> * <td>Set to a custom claim name if you wish the name of the String claim * holding the principal name to be something other than '{@code sub}'.</td> * </tr> * <tr> * <td>{@code unsecuredLoginLifetimeSeconds}</td> * <td>Set to an integer value if the token expiration is to be set to something * other than the default value of 3600 seconds (which is 1 hour). The * '{@code exp}' claim will be set to reflect the expiration time.</td> * </tr> * <tr> * <td>{@code unsecuredLoginScopeClaimName}</td> * <td>Set to a custom claim name if you wish the name of the String or String * List claim holding any token scope to be something other than * '{@code scope}'.</td> * </tr> * </table> * Production use cases will require writing an implementation of * {@link AuthenticateCallbackHandler} that can handle an instance of * {@link OAuthBearerTokenCallback} and declaring it via either the * {@code sasl.login.callback.handler.class} configuration option for a * non-broker client or via the * {@code listener.name.sasl_ssl.oauthbearer.sasl.login.callback.handler.class} * configuration option for brokers (when SASL/OAUTHBEARER is the inter-broker * protocol). * <p> * Here is a typical, basic JAAS configuration for a client leveraging unsecured * SASL/OAUTHBEARER authentication: * * <pre> * KafkaClient { * org.apache.kafka.common.security.oauthbearer.OAuthBearerLoginModule Required * unsecuredLoginStringClaim_sub="thePrincipalName"; * }; * </pre> * * An implementation of the {@link Login} interface specific to the * {@code OAUTHBEARER} mechanism is automatically applied; it periodically * refreshes any token before it expires so that the client can continue to make * connections to brokers. The parameters that impact how the refresh algorithm * operates are specified as part of the producer/consumer/broker configuration * are as follows. See the documentation for these properties elsewhere for * details. * <table> * <tr> * <th>Producer/Consumer/Broker Configuration Property</th> * </tr> * <tr> * <td>{@code sasl.login.refresh.window.factor}</td> * </tr> * <tr> * <td>{@code sasl.login.refresh.window.jitter}</td> * </tr> * <tr> * <td>{@code sasl.login.refresh.min.period.seconds}</td> * </tr> * <tr> * <td>{@code sasl.login.refresh.min.buffer.seconds}</td> * </tr> * </table> * When a broker accepts a SASL/OAUTHBEARER connection the instance of the * builtin {@code SaslServer} implementation asks its configured * {@link AuthenticateCallbackHandler} implementation to handle an instance of * {@link OAuthBearerValidatorCallback} constructed with the OAuth 2 Bearer * Token's compact serialization and return an instance of * {@link OAuthBearerToken} if the value validates. A default, builtin * {@link AuthenticateCallbackHandler} implementation validates an unsecured * token as defined by these JAAS module options: * <table> * <tr> * <th>JAAS Module Option for Unsecured Token Validation</th> * <th>Documentation</th> * </tr> * <tr> * <td>{@code unsecuredValidatorPrincipalClaimName="value"}</td> * <td>Set to a non-empty value if you wish a particular String claim holding a principal * principal name to be checked for existence; the default is to performcheck nofor suchthe * checkexistence of the '{@code sub}' claim.</td> * </tr> * <tr> * <td>{@code unsecuredValidatorScopeClaimName="value"}</td> * <td>Set to a custom claim name if you wish the name of the String or String * List claim holding any token scope to be something other than * '{@code scope}'.</td> * </tr> * <tr> * <td>{@code unsecuredValidatorRequiredScope="value"}</td> * <td>Set to a space-delimited list of scope values if you wish the * String/String List claim holding the token scope to be checked to make sure * it contains certain values.</td> * </tr> * <tr> * <td>{@code unsecuredValidatorAllowableClockSkewMs="value"}</td> * <td>Set to a positive integer value if you wish to allow up to some number of * positive milliseconds of clock skew (the default is 0).</td> * </tr> * </table> * Here is a typical, basic JAAS configuration for a broker leveraging unsecured * SASL/OAUTHBEARER validation: * * <pre> * KafkaServer { * org.apache.kafka.common.security.oauthbearer.OAuthBearerLoginModule Required * unsecuredLoginStringClaim_sub="thePrincipalName" * unsecuredValidatorPrincipalClaimName="sub"; * }; * </pre> * * Production use cases will require writing an implementation of * {@link AuthenticateCallbackHandler} that can handle an instance of * {@link OAuthBearerValidatorCallback} and declaring it via the * {@code listener.name.sasl_ssl.oauthbearer.sasl.server.callback.handler.class} * configuration option. * * @see SaslConfigs#SASL_LOGIN_REFRESH_WINDOW_FACTOR_DOC * @see SaslConfigs#SASL_LOGIN_REFRESH_WINDOW_JITTER_DOC * @see SaslConfigs#SASL_LOGIN_REFRESH_MIN_PERIOD_SECONDS_DOC * @see SaslConfigs#SASL_LOGIN_REFRESH_MIN_BUFFER_SECONDS_DOC */ public class OAuthBearerLoginModule implements LoginModule { static { OAuthBearerSaslClientProvider.initialize(); // not part of public API OAuthBearerSaslServerProvider.initialize(); // not part of public API } // etc... } |
...
JAAS Module Option for Unsecured Token Validation | Documentation |
---|---|
unsecuredValidatorPrincipalClaimName="value" | Set to a non-empty value if you wish a particular String claim holding |
unsecuredValidatorScopeClaimName="value" | Set to a custom claim name if you wish the name of the String or String |
unsecuredValidatorRequiredScope="value" | Set to a space-delimited list of scope values if you wish the |
unsecuredValidatorAllowableClockSkewMs="value" | Set to a positive integer value if you wish to allow up to some number of positive milliseconds of clock skew (the default is 0). |
...
KafkaServer {
};
org.apache.kafka.common.security.oauthbearer.OAuthBearerLoginModule Required
unsecuredLoginStringClaim_sub="thePrincipalName"
unsecuredValidatorPrincipalClaimName="sub";
Production use cases will require writing an implementation of AuthenticateCallbackHandler
that can handle an instance of OAuthBearerValidatorCallback
and declaring it via the listener.name.sasl_ssl.oauthbearer.sasl.server.callback.handler.class
configuration option.
...