...
It is worth noting that these extensions would lack a digital signature and therefore should not be used for critical use-cases where security is a concern.
Public Interfaces
New config option for OAuthBearerLoginModule - `unsecuredLoginExtension_<extensionname>`. This will allow users to add custom extensions
`SaslExtensionsCallback` - generic callback to hold extensions
...
Create a new `SaslExtensions` class that takes most of the generalizable logic from `ScramExtensions`. `ScramExtensions` will extend `SaslExtensions`
Create a new `SaslExtensionsCallback` which will be exactly the same as `ScramExtensionsCallback`. `ScramExtensionsCallback` cannot be deleted since it is a public class - it will extend `SaslExtensionsCallback` to preserve backwards-compatibility.
Pass `SaslExtensionsCallback` to the callback handler of `OAuthBearerLoginModule` so that the handler can parse the extensions from the JAAS config and populate them in the Subject class.
Pass `SaslExtensionsCallback` to the callback handler of `OAuthBearerSaslClient` so that the handler can populate take the extensions from the Subject and populate them in the callback. `OAuthBearerSaslClient` will then attach the populated extensions (if any) to the first client message.
Have `OAuthBearerServer` parse sent extensions and expose them via its `OAuthBearerServer#getNegotiatedProperty()` method. It will use a strict regex, parsing only letters for keys and only ASCII characters for values without commas (","), as they are used for separators in the OAuth message
This will allow custom principals to access them through the `SaslServer` instance in `SaslAuthenticationContext#server()`
Note that the default callback handler `OAuthBearerSaslClientCallbackHandler` will not attach any extensions - it is up to the custom user-defined callback handler to attach the appropriate extensions.
Example
A user would make use of the changes in this KIP in the following way:
Add the extension names to your JAAS configuration in the client
Create a custom LoginCallbackHandlerCode Block KafkaClient { org.apache.kafka.common.security.oauthbearer.OAuthBearerLoginModule Required unsecuredLoginStringClaim_sub="thePrincipalName" unsecuredLoginExtension_traceId="123" unsecuredLoginExtension_logLevel="WARN"; };
This handler should handle the `SaslExtensionsCallback` in his `handle()` method and attach custom extensions to the Subject
TODOCode Block - A custom principal builder can then make use of the new extension
Code Block public class CustomPrincipalBuilder implements KafkaPrincipalBuilder { @Override public KafkaPrincipal build(AuthenticationContext context) { if (context instanceof SaslAuthenticationContext) { SaslServer saslServer = ((SaslAuthenticationContext) context).server(); String traceId = saslServer.getNegotiatedPropery("trace-idtraceId"); return new CustomPrincipal("", saslServer, traceId); } throw new Exception(); } }
...