You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@kafka.apache.org by Ron Dagostino <rn...@gmail.com> on 2018/05/04 03:55:01 UTC

[VOTE] KIP-255: OAuth Authentication via SASL/OAUTHBEARER

Hi everyone.  I would like to start the vote for KIP-255:
https://cwiki.apache.org/confluence/pages/viewpage.action?pageId=75968876

This KIP proposes to add the following functionality related to
SASL/OAUTHBEARER:

1) Allow clients (both brokers when SASL/OAUTHBEARER is the inter-broker
protocol as well as non-broker clients) to flexibly retrieve an access
token from an OAuth 2 authorization server based on the declaration of a
custom login CallbackHandler implementation and have that access token
transparently and automatically transmitted to a broker for authentication.

2) Allow brokers to flexibly validate provided access tokens when a client
establishes a connection based on the declaration of a custom SASL Server
CallbackHandler implementation.

3) Provide implementations of the above retrieval and validation features
based on an unsecured JSON Web Token that function out-of-the-box with
minimal configuration required (i.e. implementations of the two types of
callback handlers mentioned above will be used by default with no need to
explicitly declare them).

4) Allow clients (both brokers when SASL/OAUTHBEARER is the inter-broker
protocol as well as non-broker clients) to transparently retrieve a new
access token in the background before the existing access token expires in
case the client has to open new connections.

Thanks,

Ron

Re: [VOTE] KIP-255: OAuth Authentication via SASL/OAUTHBEARER

Posted by Ron Dagostino <rn...@gmail.com>.
Thank you, Damian.  This concludes the vote for KIP 255.  The vote passes
with three binding + 1 votes, from Rajini, Jun, and Damian, and three
non-binding +1 votes, from Mickael, Manikumar, and myself.

I have marked the KIP as "Accepted".

The pull request is available at https://github.com/apache/kafka/pull/4994
and is squashed/rebased onto trunk.

Ron

On Mon, May 21, 2018 at 8:25 AM, Damian Guy <da...@gmail.com> wrote:

> +1 (binding)
>
> Thanks
>
> On Mon, 21 May 2018 at 04:59 Ron Dagostino <rn...@gmail.com> wrote:
>
> > Hi Committers.  One more binding affirmative vote is required if KIP 255
> > is to have a chance of being included in the 2.0.0 release.  Please vote
> > today.
> >
> > Ron
> >
> > > On May 18, 2018, at 9:27 PM, Ron Dagostino <rn...@gmail.com> wrote:
> > >
> > > Hi committers.  KIP 255 still needs 1 more binding vote.  Currently
> > there are two binding + 1 votes, from Rajini and Jun, and three
> non-binding
> > +1 votes, from Mickael, Manikumar, and myself.
> > >
> > > Please vote by the Monday deadline.
> > >
> > > Ron
> > >
> > >> On Thu, May 17, 2018 at 10:59 AM, Ron Dagostino <rn...@gmail.com>
> > wrote:
> > >> Hi Jun.  I've updated the KIP to add a new section titled "Summary for
> > Production Use" that includes this information along with a consolidated
> > set of references to the applicable specifications.  Thanks for the
> > questions.
> > >>
> > >> *We still need another binding vote* (currently there are two binding
> +
> > 1 votes, from Rajini and Jun, and three non-binding +1 votes, from
> Mickael,
> > Manikumar, and myself).
> > >>
> > >> Please vote before the May 22nd KIP Freeze deadline so this KIP can be
> > included in the 2.0.0 release.
> > >>
> > >> A pull request is available and includes additional commits reflecting
> > initial review comments: https://github.com/apache/kafka/pull/4994
> > >>
> > >> Ron
> > >>
> > >>> On Wed, May 16, 2018 at 8:09 PM, Jun Rao <ju...@confluent.io> wrote:
> > >>> Hi, Ron,
> > >>>
> > >>> Thanks. I understand now. It may be useful to add a reference to JWT
> > in the
> > >>> KIP.
> > >>>
> > >>> Jun
> > >>>
> > >>> On Tue, May 15, 2018 at 6:51 PM, Ron Dagostino <rn...@gmail.com>
> > wrote:
> > >>>
> > >>> > Hi Jun.  I think you are getting at the fact that OAuth 2 is a
> > flexible
> > >>> > framework that allows different installations to do things
> > differently.  It
> > >>> > is true that the principal name in Kafka could come from any claim
> > in the
> > >>> > token.  Most of the time it would come from the 'sub' claim, but it
> > could
> > >>> > certainly come from another claim, or it could be only indirectly
> > based on
> > >>> > a claim value (maybe certain text would be trimmed or
> > prefixed/suffixed).
> > >>> > The point, which I think you are getting at, is that because the
> > framework
> > >>> > is flexible we need to accommodate that flexibility.  The callback
> > handler
> > >>> > class defined by the listener.name.sasl_ssl.
> oauthbearer.sasl.server.
> > >>> > callback.handler.class configuration value gives us the required
> > >>> > flexibility.  As an example, I have an implementation that
> leverages
> > a
> > >>> > popular open source JOSE library to parse the compact
> serialization,
> > >>> > retrieve the public key if it has not yet been retrieved, verify
> the
> > >>> > digital signature, and map the 'sub' claim to the
> OAuthBearerToken's
> > >>> > principal name (which becomes the SASL authorization ID, which
> > becomes the
> > >>> > Kafka principal name).  I could just as easily have mapped a
> > different
> > >>> > claim to the OAuthBearerToken's principal name, manipulated the
> > 'sub' claim
> > >>> > value in some way, etc.  I write the callback handler code, so I
> > complete
> > >>> > flexibility to do whatever my OAuth 2 installation requires me to
> do.
> > >>> >
> > >>> > Ron
> > >>> >
> > >>> > On Tue, May 15, 2018 at 1:39 PM, Jun Rao <ju...@confluent.io> wrote:
> > >>> >
> > >>> > > Hi, Ron,
> > >>> > >
> > >>> > > Thanks for the reply. I understood your answers to #2 and #3.
> > >>> > >
> > >>> > > For #1, will the server map all clients' principal name to the
> > value
> > >>> > > associated with "sub" claim? How do we support mapping different
> > clients
> > >>> > to
> > >>> > > different principal names?
> > >>> > >
> > >>> > > Jun
> > >>> > >
> > >>> > > On Mon, May 14, 2018 at 7:02 PM, Ron Dagostino <
> rndgstn@gmail.com>
> > >>> > wrote:
> > >>> > >
> > >>> > > > Hi Jun.  Thanks for the +1 vote.
> > >>> > > >
> > >>> > > > Regarding the first question about token claims, yes, you have
> it
> > >>> > correct
> > >>> > > > about translating the OAuth token to a principle name via a
> JAAS
> > module
> > >>> > > > option in the default unsecured case.  Specifically, the OAuth
> > SASL
> > >>> > > Server
> > >>> > > > implementation is responsible for setting the authorization ID,
> > and it
> > >>> > > gets
> > >>> > > > the authorization ID from the OAuthBearerToken's
> principalName()
> > >>> > method.
> > >>> > > > The listener.name.sasl_ssl.oauthbearer.sasl.server.
> > >>> > > callback.handler.class
> > >>> > > > is responsible for handling an instance of
> > OAuthBearerValidatorCallback
> > >>> > > to
> > >>> > > > accept a token compact serialization from the client and return
> > an
> > >>> > > instance
> > >>> > > > of OAuthBearerToken (assuming the compact serialization
> > validates), and
> > >>> > > in
> > >>> > > > the default unsecured case the builtin unsecured validator
> > callback
> > >>> > > handler
> > >>> > > > defines the OAuthBearerToken.principalName() method to return
> the
> > >>> > 'sub'
> > >>> > > > claim value by default (with the actual claim it uses being
> > >>> > configurable
> > >>> > > > via the unsecuredValidatorPrincipalClaimName JAAS module
> > option).  So
> > >>> > > that
> > >>> > > > is how we translate from a token to a principal name in the
> > default
> > >>> > > > unsecured (out-of-the-box) case.
> > >>> > > >
> > >>> > > > For production use cases, the implementation associated with
> > >>> > > >
> > listener.name.sasl_ssl.oauthbearer.sasl.server.callback.handler.class
> > >>> > > can
> > >>> > > > do whatever it wants.  As an example, I have written a class
> that
> > >>> > wraps a
> > >>> > > > com.nimbusds.jwt.SignedJWT instance (see
> > >>> > > > https://connect2id.com/products/nimbus-jose-jwt/) and presents
> > it as
> > >>> > an
> > >>> > > > OAuthBearerToken:
> > >>> > > >
> > >>> > > > public class NimbusSignedJwtOAuthBearerToken implements
> > >>> > > OAuthBearerToken {
> > >>> > > >     private final SignedJWT signedJwt;
> > >>> > > >     private final String principalName;
> > >>> > > >     private final Set<String> scope;
> > >>> > > >     private final Long startTimeMs;
> > >>> > > >     private final long lifetimeMs;
> > >>> > > >
> > >>> > > >     /**
> > >>> > > >      * Constructor
> > >>> > > >      *
> > >>> > > >      * @param signedJwt
> > >>> > > >      *            the mandatory signed JWT
> > >>> > > >      * @param principalClaimName
> > >>> > > >      *            the mandatory claim name identifying the
> claim
> > from
> > >>> > > which
> > >>> > > > the
> > >>> > > >      *            principal name will be extracted. The claim
> > must
> > >>> > exist
> > >>> > > > and must be
> > >>> > > >      *            a String.
> > >>> > > >      * @param optionalScopeClaimName
> > >>> > > >      *            the optional claim name identifying the claim
> > from
> > >>> > > which
> > >>> > > > any scope
> > >>> > > >      *            will be extracted. If specified and the claim
> > exists
> > >>> > > then
> > >>> > > > the
> > >>> > > >      *            value must be either a String or a String
> List.
> > >>> > > >      * @throws ParseException
> > >>> > > >      *             if the principal claim does not exist or is
> > not a
> > >>> > > > String; the
> > >>> > > >      *             scope claim is neither a String nor a String
> > List;
> > >>> > the
> > >>> > > > 'exp'
> > >>> > > >      *             claim does not exist or is not a number; the
> > 'iat'
> > >>> > > claim
> > >>> > > > exists
> > >>> > > >      *             but is not a number; or the 'nbf' claim
> > exists and
> > >>> > is
> > >>> > > > not a
> > >>> > > >      *             number.
> > >>> > > >      */
> > >>> > > >     public NimbusSignedJwtOAuthBearerToken(SignedJWT
> signedJwt,
> > String
> > >>> > > > principalClaimName,
> > >>> > > >             String optionalScopeClaimName) throws
> ParseException
> > {
> > >>> > > >         // etc...
> > >>> > > >     }
> > >>> > > >
> > >>> > > > The callback handler runs the following code if the digital
> > signature
> > >>> > > > validates:
> > >>> > > >
> > >>> > > >     callback.token(new NimbusSignedJwtOAuthBearerToke
> n(signedJwt,
> > >>> > "sub",
> > >>> > > > null));
> > >>> > > >
> > >>> > > > I hope that answers the first question.  If not let me know
> what
> > I
> > >>> > > > missed/misunderstood and I'll be glad to try to address it.
> > >>> > > >
> > >>> > > > Regarding the second question, the classes
> > OAuthBearerTokenCallback and
> > >>> > > > OAuthBearerValidatorCallback implement the Callback interface
> --
> > they
> > >>> > are
> > >>> > > > the callbacks that the AuthenticateCallbackHandler
> > implementations need
> > >>> > > to
> > >>> > > > handle.  Specifically, unless the unsecured functionality is
> > what is
> > >>> > > > desired, the two configuration values [listener.name.sasl_ssl.
> > >>> > > oauthbearer.
> > >>> > > > ]sasl.login.callback.handler.class and
> > >>> > > >
> > listener.name.sasl_ssl.oauthbearer.sasl.server.callback.handler.class
> > >>> > > > define the callback handlers that need to handle
> > >>> > OAuthBearerTokenCallback
> > >>> > > > and OAuthBearerValidatorCallback, respectively.
> > >>> > > >
> > >>> > > > Regarding the third question, yes, I see your point that the
> way
> > the
> > >>> > spec
> > >>> > > > is worded could be taken to imply that the error code is a
> single
> > >>> > > > character: "A single ASCII..." (
> > >>> > > > https://tools.ietf.org/html/rfc6749#section-5.2).  However, it
> > is not
> > >>> > a
> > >>> > > > single character.  See the end of that section 5.2 for an
> > example that
> > >>> > > > shows "error":"invalid_request" as the response.
> > >>> > > >
> > >>> > > > Thanks again for the +1 vote, Jun, and please do let me know if
> > I can
> > >>> > > cover
> > >>> > > > anything else.
> > >>> > > >
> > >>> > > > Ron
> > >>> > > >
> > >>> > > >
> > >>> > > > On Mon, May 14, 2018 at 7:10 PM, Jun Rao <ju...@confluent.io>
> > wrote:
> > >>> > > >
> > >>> > > > > Hi, Ron,
> > >>> > > > >
> > >>> > > > > Thanks for the KIP. +1 from me. Just a few minor comments
> > below.
> > >>> > > > >
> > >>> > > > > 1. It seems that we can translate an OAuth token to a
> > principle name
> > >>> > > > > through the claim name configured in JASS. However, it's not
> > clear to
> > >>> > > me
> > >>> > > > > how an OAuth token is mapped to a claim. Could you clarify
> > that?
> > >>> > > > >
> > >>> > > > > 2. The wiki has the following code. It seems that
> > >>> > > > OAuthBearerTokenCallback
> > >>> > > > > should implement AuthenticateCallbackHandler? Ditto
> > >>> > > > > for OAuthBearerValidatorCallback.
> > >>> > > > >
> > >>> > > > > public class OAuthBearerTokenCallback implements Callback
> > >>> > > > >
> > >>> > > > > 3. In OAuthBearerTokenCallback, we have the following method.
> > The
> > >>> > OAuth
> > >>> > > > > spec says the error code is a single ASCII. So, should we
> > return a
> > >>> > Char
> > >>> > > > or
> > >>> > > > > a String?
> > >>> > > > >
> > >>> > > > > public String errorCode()
> > >>> > > > >
> > >>> > > > > Jun
> > >>> > > > >
> > >>> > > > >
> > >>> > > > > On Thu, May 3, 2018 at 8:55 PM, Ron Dagostino <
> > rndgstn@gmail.com>
> > >>> > > wrote:
> > >>> > > > >
> > >>> > > > > > Hi everyone.  I would like to start the vote for KIP-255:
> > >>> > > > > > https://cwiki.apache.org/confluence/pages/viewpage.
> > >>> > > > > action?pageId=75968876
> > >>> > > > > >
> > >>> > > > > > This KIP proposes to add the following functionality
> related
> > to
> > >>> > > > > > SASL/OAUTHBEARER:
> > >>> > > > > >
> > >>> > > > > > 1) Allow clients (both brokers when SASL/OAUTHBEARER is the
> > >>> > > > inter-broker
> > >>> > > > > > protocol as well as non-broker clients) to flexibly
> retrieve
> > an
> > >>> > > access
> > >>> > > > > > token from an OAuth 2 authorization server based on the
> > declaration
> > >>> > > of
> > >>> > > > a
> > >>> > > > > > custom login CallbackHandler implementation and have that
> > access
> > >>> > > token
> > >>> > > > > > transparently and automatically transmitted to a broker for
> > >>> > > > > authentication.
> > >>> > > > > >
> > >>> > > > > > 2) Allow brokers to flexibly validate provided access
> tokens
> > when a
> > >>> > > > > client
> > >>> > > > > > establishes a connection based on the declaration of a
> > custom SASL
> > >>> > > > Server
> > >>> > > > > > CallbackHandler implementation.
> > >>> > > > > >
> > >>> > > > > > 3) Provide implementations of the above retrieval and
> > validation
> > >>> > > > features
> > >>> > > > > > based on an unsecured JSON Web Token that function
> > out-of-the-box
> > >>> > > with
> > >>> > > > > > minimal configuration required (i.e. implementations of the
> > two
> > >>> > types
> > >>> > > > of
> > >>> > > > > > callback handlers mentioned above will be used by default
> > with no
> > >>> > > need
> > >>> > > > to
> > >>> > > > > > explicitly declare them).
> > >>> > > > > >
> > >>> > > > > > 4) Allow clients (both brokers when SASL/OAUTHBEARER is the
> > >>> > > > inter-broker
> > >>> > > > > > protocol as well as non-broker clients) to transparently
> > retrieve a
> > >>> > > new
> > >>> > > > > > access token in the background before the existing access
> > token
> > >>> > > expires
> > >>> > > > > in
> > >>> > > > > > case the client has to open new connections.
> > >>> > > > > >
> > >>> > > > > > Thanks,
> > >>> > > > > >
> > >>> > > > > > Ron
> > >>> > > > > >
> > >>> > > > >
> > >>> > > >
> > >>> > >
> > >>> >
> > >>
> > >
> >
>

Re: [VOTE] KIP-255: OAuth Authentication via SASL/OAUTHBEARER

Posted by Damian Guy <da...@gmail.com>.
+1 (binding)

Thanks

On Mon, 21 May 2018 at 04:59 Ron Dagostino <rn...@gmail.com> wrote:

> Hi Committers.  One more binding affirmative vote is required if KIP 255
> is to have a chance of being included in the 2.0.0 release.  Please vote
> today.
>
> Ron
>
> > On May 18, 2018, at 9:27 PM, Ron Dagostino <rn...@gmail.com> wrote:
> >
> > Hi committers.  KIP 255 still needs 1 more binding vote.  Currently
> there are two binding + 1 votes, from Rajini and Jun, and three non-binding
> +1 votes, from Mickael, Manikumar, and myself.
> >
> > Please vote by the Monday deadline.
> >
> > Ron
> >
> >> On Thu, May 17, 2018 at 10:59 AM, Ron Dagostino <rn...@gmail.com>
> wrote:
> >> Hi Jun.  I've updated the KIP to add a new section titled "Summary for
> Production Use" that includes this information along with a consolidated
> set of references to the applicable specifications.  Thanks for the
> questions.
> >>
> >> *We still need another binding vote* (currently there are two binding +
> 1 votes, from Rajini and Jun, and three non-binding +1 votes, from Mickael,
> Manikumar, and myself).
> >>
> >> Please vote before the May 22nd KIP Freeze deadline so this KIP can be
> included in the 2.0.0 release.
> >>
> >> A pull request is available and includes additional commits reflecting
> initial review comments: https://github.com/apache/kafka/pull/4994
> >>
> >> Ron
> >>
> >>> On Wed, May 16, 2018 at 8:09 PM, Jun Rao <ju...@confluent.io> wrote:
> >>> Hi, Ron,
> >>>
> >>> Thanks. I understand now. It may be useful to add a reference to JWT
> in the
> >>> KIP.
> >>>
> >>> Jun
> >>>
> >>> On Tue, May 15, 2018 at 6:51 PM, Ron Dagostino <rn...@gmail.com>
> wrote:
> >>>
> >>> > Hi Jun.  I think you are getting at the fact that OAuth 2 is a
> flexible
> >>> > framework that allows different installations to do things
> differently.  It
> >>> > is true that the principal name in Kafka could come from any claim
> in the
> >>> > token.  Most of the time it would come from the 'sub' claim, but it
> could
> >>> > certainly come from another claim, or it could be only indirectly
> based on
> >>> > a claim value (maybe certain text would be trimmed or
> prefixed/suffixed).
> >>> > The point, which I think you are getting at, is that because the
> framework
> >>> > is flexible we need to accommodate that flexibility.  The callback
> handler
> >>> > class defined by the listener.name.sasl_ssl.oauthbearer.sasl.server.
> >>> > callback.handler.class configuration value gives us the required
> >>> > flexibility.  As an example, I have an implementation that leverages
> a
> >>> > popular open source JOSE library to parse the compact serialization,
> >>> > retrieve the public key if it has not yet been retrieved, verify the
> >>> > digital signature, and map the 'sub' claim to the OAuthBearerToken's
> >>> > principal name (which becomes the SASL authorization ID, which
> becomes the
> >>> > Kafka principal name).  I could just as easily have mapped a
> different
> >>> > claim to the OAuthBearerToken's principal name, manipulated the
> 'sub' claim
> >>> > value in some way, etc.  I write the callback handler code, so I
> complete
> >>> > flexibility to do whatever my OAuth 2 installation requires me to do.
> >>> >
> >>> > Ron
> >>> >
> >>> > On Tue, May 15, 2018 at 1:39 PM, Jun Rao <ju...@confluent.io> wrote:
> >>> >
> >>> > > Hi, Ron,
> >>> > >
> >>> > > Thanks for the reply. I understood your answers to #2 and #3.
> >>> > >
> >>> > > For #1, will the server map all clients' principal name to the
> value
> >>> > > associated with "sub" claim? How do we support mapping different
> clients
> >>> > to
> >>> > > different principal names?
> >>> > >
> >>> > > Jun
> >>> > >
> >>> > > On Mon, May 14, 2018 at 7:02 PM, Ron Dagostino <rn...@gmail.com>
> >>> > wrote:
> >>> > >
> >>> > > > Hi Jun.  Thanks for the +1 vote.
> >>> > > >
> >>> > > > Regarding the first question about token claims, yes, you have it
> >>> > correct
> >>> > > > about translating the OAuth token to a principle name via a JAAS
> module
> >>> > > > option in the default unsecured case.  Specifically, the OAuth
> SASL
> >>> > > Server
> >>> > > > implementation is responsible for setting the authorization ID,
> and it
> >>> > > gets
> >>> > > > the authorization ID from the OAuthBearerToken's principalName()
> >>> > method.
> >>> > > > The listener.name.sasl_ssl.oauthbearer.sasl.server.
> >>> > > callback.handler.class
> >>> > > > is responsible for handling an instance of
> OAuthBearerValidatorCallback
> >>> > > to
> >>> > > > accept a token compact serialization from the client and return
> an
> >>> > > instance
> >>> > > > of OAuthBearerToken (assuming the compact serialization
> validates), and
> >>> > > in
> >>> > > > the default unsecured case the builtin unsecured validator
> callback
> >>> > > handler
> >>> > > > defines the OAuthBearerToken.principalName() method to return the
> >>> > 'sub'
> >>> > > > claim value by default (with the actual claim it uses being
> >>> > configurable
> >>> > > > via the unsecuredValidatorPrincipalClaimName JAAS module
> option).  So
> >>> > > that
> >>> > > > is how we translate from a token to a principal name in the
> default
> >>> > > > unsecured (out-of-the-box) case.
> >>> > > >
> >>> > > > For production use cases, the implementation associated with
> >>> > > >
> listener.name.sasl_ssl.oauthbearer.sasl.server.callback.handler.class
> >>> > > can
> >>> > > > do whatever it wants.  As an example, I have written a class that
> >>> > wraps a
> >>> > > > com.nimbusds.jwt.SignedJWT instance (see
> >>> > > > https://connect2id.com/products/nimbus-jose-jwt/) and presents
> it as
> >>> > an
> >>> > > > OAuthBearerToken:
> >>> > > >
> >>> > > > public class NimbusSignedJwtOAuthBearerToken implements
> >>> > > OAuthBearerToken {
> >>> > > >     private final SignedJWT signedJwt;
> >>> > > >     private final String principalName;
> >>> > > >     private final Set<String> scope;
> >>> > > >     private final Long startTimeMs;
> >>> > > >     private final long lifetimeMs;
> >>> > > >
> >>> > > >     /**
> >>> > > >      * Constructor
> >>> > > >      *
> >>> > > >      * @param signedJwt
> >>> > > >      *            the mandatory signed JWT
> >>> > > >      * @param principalClaimName
> >>> > > >      *            the mandatory claim name identifying the claim
> from
> >>> > > which
> >>> > > > the
> >>> > > >      *            principal name will be extracted. The claim
> must
> >>> > exist
> >>> > > > and must be
> >>> > > >      *            a String.
> >>> > > >      * @param optionalScopeClaimName
> >>> > > >      *            the optional claim name identifying the claim
> from
> >>> > > which
> >>> > > > any scope
> >>> > > >      *            will be extracted. If specified and the claim
> exists
> >>> > > then
> >>> > > > the
> >>> > > >      *            value must be either a String or a String List.
> >>> > > >      * @throws ParseException
> >>> > > >      *             if the principal claim does not exist or is
> not a
> >>> > > > String; the
> >>> > > >      *             scope claim is neither a String nor a String
> List;
> >>> > the
> >>> > > > 'exp'
> >>> > > >      *             claim does not exist or is not a number; the
> 'iat'
> >>> > > claim
> >>> > > > exists
> >>> > > >      *             but is not a number; or the 'nbf' claim
> exists and
> >>> > is
> >>> > > > not a
> >>> > > >      *             number.
> >>> > > >      */
> >>> > > >     public NimbusSignedJwtOAuthBearerToken(SignedJWT signedJwt,
> String
> >>> > > > principalClaimName,
> >>> > > >             String optionalScopeClaimName) throws ParseException
> {
> >>> > > >         // etc...
> >>> > > >     }
> >>> > > >
> >>> > > > The callback handler runs the following code if the digital
> signature
> >>> > > > validates:
> >>> > > >
> >>> > > >     callback.token(new NimbusSignedJwtOAuthBearerToken(signedJwt,
> >>> > "sub",
> >>> > > > null));
> >>> > > >
> >>> > > > I hope that answers the first question.  If not let me know what
> I
> >>> > > > missed/misunderstood and I'll be glad to try to address it.
> >>> > > >
> >>> > > > Regarding the second question, the classes
> OAuthBearerTokenCallback and
> >>> > > > OAuthBearerValidatorCallback implement the Callback interface --
> they
> >>> > are
> >>> > > > the callbacks that the AuthenticateCallbackHandler
> implementations need
> >>> > > to
> >>> > > > handle.  Specifically, unless the unsecured functionality is
> what is
> >>> > > > desired, the two configuration values [listener.name.sasl_ssl.
> >>> > > oauthbearer.
> >>> > > > ]sasl.login.callback.handler.class and
> >>> > > >
> listener.name.sasl_ssl.oauthbearer.sasl.server.callback.handler.class
> >>> > > > define the callback handlers that need to handle
> >>> > OAuthBearerTokenCallback
> >>> > > > and OAuthBearerValidatorCallback, respectively.
> >>> > > >
> >>> > > > Regarding the third question, yes, I see your point that the way
> the
> >>> > spec
> >>> > > > is worded could be taken to imply that the error code is a single
> >>> > > > character: "A single ASCII..." (
> >>> > > > https://tools.ietf.org/html/rfc6749#section-5.2).  However, it
> is not
> >>> > a
> >>> > > > single character.  See the end of that section 5.2 for an
> example that
> >>> > > > shows "error":"invalid_request" as the response.
> >>> > > >
> >>> > > > Thanks again for the +1 vote, Jun, and please do let me know if
> I can
> >>> > > cover
> >>> > > > anything else.
> >>> > > >
> >>> > > > Ron
> >>> > > >
> >>> > > >
> >>> > > > On Mon, May 14, 2018 at 7:10 PM, Jun Rao <ju...@confluent.io>
> wrote:
> >>> > > >
> >>> > > > > Hi, Ron,
> >>> > > > >
> >>> > > > > Thanks for the KIP. +1 from me. Just a few minor comments
> below.
> >>> > > > >
> >>> > > > > 1. It seems that we can translate an OAuth token to a
> principle name
> >>> > > > > through the claim name configured in JASS. However, it's not
> clear to
> >>> > > me
> >>> > > > > how an OAuth token is mapped to a claim. Could you clarify
> that?
> >>> > > > >
> >>> > > > > 2. The wiki has the following code. It seems that
> >>> > > > OAuthBearerTokenCallback
> >>> > > > > should implement AuthenticateCallbackHandler? Ditto
> >>> > > > > for OAuthBearerValidatorCallback.
> >>> > > > >
> >>> > > > > public class OAuthBearerTokenCallback implements Callback
> >>> > > > >
> >>> > > > > 3. In OAuthBearerTokenCallback, we have the following method.
> The
> >>> > OAuth
> >>> > > > > spec says the error code is a single ASCII. So, should we
> return a
> >>> > Char
> >>> > > > or
> >>> > > > > a String?
> >>> > > > >
> >>> > > > > public String errorCode()
> >>> > > > >
> >>> > > > > Jun
> >>> > > > >
> >>> > > > >
> >>> > > > > On Thu, May 3, 2018 at 8:55 PM, Ron Dagostino <
> rndgstn@gmail.com>
> >>> > > wrote:
> >>> > > > >
> >>> > > > > > Hi everyone.  I would like to start the vote for KIP-255:
> >>> > > > > > https://cwiki.apache.org/confluence/pages/viewpage.
> >>> > > > > action?pageId=75968876
> >>> > > > > >
> >>> > > > > > This KIP proposes to add the following functionality related
> to
> >>> > > > > > SASL/OAUTHBEARER:
> >>> > > > > >
> >>> > > > > > 1) Allow clients (both brokers when SASL/OAUTHBEARER is the
> >>> > > > inter-broker
> >>> > > > > > protocol as well as non-broker clients) to flexibly retrieve
> an
> >>> > > access
> >>> > > > > > token from an OAuth 2 authorization server based on the
> declaration
> >>> > > of
> >>> > > > a
> >>> > > > > > custom login CallbackHandler implementation and have that
> access
> >>> > > token
> >>> > > > > > transparently and automatically transmitted to a broker for
> >>> > > > > authentication.
> >>> > > > > >
> >>> > > > > > 2) Allow brokers to flexibly validate provided access tokens
> when a
> >>> > > > > client
> >>> > > > > > establishes a connection based on the declaration of a
> custom SASL
> >>> > > > Server
> >>> > > > > > CallbackHandler implementation.
> >>> > > > > >
> >>> > > > > > 3) Provide implementations of the above retrieval and
> validation
> >>> > > > features
> >>> > > > > > based on an unsecured JSON Web Token that function
> out-of-the-box
> >>> > > with
> >>> > > > > > minimal configuration required (i.e. implementations of the
> two
> >>> > types
> >>> > > > of
> >>> > > > > > callback handlers mentioned above will be used by default
> with no
> >>> > > need
> >>> > > > to
> >>> > > > > > explicitly declare them).
> >>> > > > > >
> >>> > > > > > 4) Allow clients (both brokers when SASL/OAUTHBEARER is the
> >>> > > > inter-broker
> >>> > > > > > protocol as well as non-broker clients) to transparently
> retrieve a
> >>> > > new
> >>> > > > > > access token in the background before the existing access
> token
> >>> > > expires
> >>> > > > > in
> >>> > > > > > case the client has to open new connections.
> >>> > > > > >
> >>> > > > > > Thanks,
> >>> > > > > >
> >>> > > > > > Ron
> >>> > > > > >
> >>> > > > >
> >>> > > >
> >>> > >
> >>> >
> >>
> >
>

Re: [VOTE] KIP-255: OAuth Authentication via SASL/OAUTHBEARER

Posted by Ron Dagostino <rn...@gmail.com>.
Hi Committers.  One more binding affirmative vote is required if KIP 255 is to have a chance of being included in the 2.0.0 release.  Please vote today.

Ron

> On May 18, 2018, at 9:27 PM, Ron Dagostino <rn...@gmail.com> wrote:
> 
> Hi committers.  KIP 255 still needs 1 more binding vote.  Currently there are two binding + 1 votes, from Rajini and Jun, and three non-binding +1 votes, from Mickael, Manikumar, and myself.
> 
> Please vote by the Monday deadline.
> 
> Ron
> 
>> On Thu, May 17, 2018 at 10:59 AM, Ron Dagostino <rn...@gmail.com> wrote:
>> Hi Jun.  I've updated the KIP to add a new section titled "Summary for Production Use" that includes this information along with a consolidated set of references to the applicable specifications.  Thanks for the questions.
>> 
>> *We still need another binding vote* (currently there are two binding + 1 votes, from Rajini and Jun, and three non-binding +1 votes, from Mickael, Manikumar, and myself).
>> 
>> Please vote before the May 22nd KIP Freeze deadline so this KIP can be included in the 2.0.0 release.
>> 
>> A pull request is available and includes additional commits reflecting initial review comments: https://github.com/apache/kafka/pull/4994
>> 
>> Ron
>> 
>>> On Wed, May 16, 2018 at 8:09 PM, Jun Rao <ju...@confluent.io> wrote:
>>> Hi, Ron,
>>> 
>>> Thanks. I understand now. It may be useful to add a reference to JWT in the
>>> KIP.
>>> 
>>> Jun
>>> 
>>> On Tue, May 15, 2018 at 6:51 PM, Ron Dagostino <rn...@gmail.com> wrote:
>>> 
>>> > Hi Jun.  I think you are getting at the fact that OAuth 2 is a flexible
>>> > framework that allows different installations to do things differently.  It
>>> > is true that the principal name in Kafka could come from any claim in the
>>> > token.  Most of the time it would come from the 'sub' claim, but it could
>>> > certainly come from another claim, or it could be only indirectly based on
>>> > a claim value (maybe certain text would be trimmed or prefixed/suffixed).
>>> > The point, which I think you are getting at, is that because the framework
>>> > is flexible we need to accommodate that flexibility.  The callback handler
>>> > class defined by the listener.name.sasl_ssl.oauthbearer.sasl.server.
>>> > callback.handler.class configuration value gives us the required
>>> > flexibility.  As an example, I have an implementation that leverages a
>>> > popular open source JOSE library to parse the compact serialization,
>>> > retrieve the public key if it has not yet been retrieved, verify the
>>> > digital signature, and map the 'sub' claim to the OAuthBearerToken's
>>> > principal name (which becomes the SASL authorization ID, which becomes the
>>> > Kafka principal name).  I could just as easily have mapped a different
>>> > claim to the OAuthBearerToken's principal name, manipulated the 'sub' claim
>>> > value in some way, etc.  I write the callback handler code, so I complete
>>> > flexibility to do whatever my OAuth 2 installation requires me to do.
>>> >
>>> > Ron
>>> >
>>> > On Tue, May 15, 2018 at 1:39 PM, Jun Rao <ju...@confluent.io> wrote:
>>> >
>>> > > Hi, Ron,
>>> > >
>>> > > Thanks for the reply. I understood your answers to #2 and #3.
>>> > >
>>> > > For #1, will the server map all clients' principal name to the value
>>> > > associated with "sub" claim? How do we support mapping different clients
>>> > to
>>> > > different principal names?
>>> > >
>>> > > Jun
>>> > >
>>> > > On Mon, May 14, 2018 at 7:02 PM, Ron Dagostino <rn...@gmail.com>
>>> > wrote:
>>> > >
>>> > > > Hi Jun.  Thanks for the +1 vote.
>>> > > >
>>> > > > Regarding the first question about token claims, yes, you have it
>>> > correct
>>> > > > about translating the OAuth token to a principle name via a JAAS module
>>> > > > option in the default unsecured case.  Specifically, the OAuth SASL
>>> > > Server
>>> > > > implementation is responsible for setting the authorization ID, and it
>>> > > gets
>>> > > > the authorization ID from the OAuthBearerToken's principalName()
>>> > method.
>>> > > > The listener.name.sasl_ssl.oauthbearer.sasl.server.
>>> > > callback.handler.class
>>> > > > is responsible for handling an instance of OAuthBearerValidatorCallback
>>> > > to
>>> > > > accept a token compact serialization from the client and return an
>>> > > instance
>>> > > > of OAuthBearerToken (assuming the compact serialization validates), and
>>> > > in
>>> > > > the default unsecured case the builtin unsecured validator callback
>>> > > handler
>>> > > > defines the OAuthBearerToken.principalName() method to return the
>>> > 'sub'
>>> > > > claim value by default (with the actual claim it uses being
>>> > configurable
>>> > > > via the unsecuredValidatorPrincipalClaimName JAAS module option).  So
>>> > > that
>>> > > > is how we translate from a token to a principal name in the default
>>> > > > unsecured (out-of-the-box) case.
>>> > > >
>>> > > > For production use cases, the implementation associated with
>>> > > > listener.name.sasl_ssl.oauthbearer.sasl.server.callback.handler.class
>>> > > can
>>> > > > do whatever it wants.  As an example, I have written a class that
>>> > wraps a
>>> > > > com.nimbusds.jwt.SignedJWT instance (see
>>> > > > https://connect2id.com/products/nimbus-jose-jwt/) and presents it as
>>> > an
>>> > > > OAuthBearerToken:
>>> > > >
>>> > > > public class NimbusSignedJwtOAuthBearerToken implements
>>> > > OAuthBearerToken {
>>> > > >     private final SignedJWT signedJwt;
>>> > > >     private final String principalName;
>>> > > >     private final Set<String> scope;
>>> > > >     private final Long startTimeMs;
>>> > > >     private final long lifetimeMs;
>>> > > >
>>> > > >     /**
>>> > > >      * Constructor
>>> > > >      *
>>> > > >      * @param signedJwt
>>> > > >      *            the mandatory signed JWT
>>> > > >      * @param principalClaimName
>>> > > >      *            the mandatory claim name identifying the claim from
>>> > > which
>>> > > > the
>>> > > >      *            principal name will be extracted. The claim must
>>> > exist
>>> > > > and must be
>>> > > >      *            a String.
>>> > > >      * @param optionalScopeClaimName
>>> > > >      *            the optional claim name identifying the claim from
>>> > > which
>>> > > > any scope
>>> > > >      *            will be extracted. If specified and the claim exists
>>> > > then
>>> > > > the
>>> > > >      *            value must be either a String or a String List.
>>> > > >      * @throws ParseException
>>> > > >      *             if the principal claim does not exist or is not a
>>> > > > String; the
>>> > > >      *             scope claim is neither a String nor a String List;
>>> > the
>>> > > > 'exp'
>>> > > >      *             claim does not exist or is not a number; the 'iat'
>>> > > claim
>>> > > > exists
>>> > > >      *             but is not a number; or the 'nbf' claim exists and
>>> > is
>>> > > > not a
>>> > > >      *             number.
>>> > > >      */
>>> > > >     public NimbusSignedJwtOAuthBearerToken(SignedJWT signedJwt, String
>>> > > > principalClaimName,
>>> > > >             String optionalScopeClaimName) throws ParseException {
>>> > > >         // etc...
>>> > > >     }
>>> > > >
>>> > > > The callback handler runs the following code if the digital signature
>>> > > > validates:
>>> > > >
>>> > > >     callback.token(new NimbusSignedJwtOAuthBearerToken(signedJwt,
>>> > "sub",
>>> > > > null));
>>> > > >
>>> > > > I hope that answers the first question.  If not let me know what I
>>> > > > missed/misunderstood and I'll be glad to try to address it.
>>> > > >
>>> > > > Regarding the second question, the classes OAuthBearerTokenCallback and
>>> > > > OAuthBearerValidatorCallback implement the Callback interface -- they
>>> > are
>>> > > > the callbacks that the AuthenticateCallbackHandler implementations need
>>> > > to
>>> > > > handle.  Specifically, unless the unsecured functionality is what is
>>> > > > desired, the two configuration values [listener.name.sasl_ssl.
>>> > > oauthbearer.
>>> > > > ]sasl.login.callback.handler.class and
>>> > > > listener.name.sasl_ssl.oauthbearer.sasl.server.callback.handler.class
>>> > > > define the callback handlers that need to handle
>>> > OAuthBearerTokenCallback
>>> > > > and OAuthBearerValidatorCallback, respectively.
>>> > > >
>>> > > > Regarding the third question, yes, I see your point that the way the
>>> > spec
>>> > > > is worded could be taken to imply that the error code is a single
>>> > > > character: "A single ASCII..." (
>>> > > > https://tools.ietf.org/html/rfc6749#section-5.2).  However, it is not
>>> > a
>>> > > > single character.  See the end of that section 5.2 for an example that
>>> > > > shows "error":"invalid_request" as the response.
>>> > > >
>>> > > > Thanks again for the +1 vote, Jun, and please do let me know if I can
>>> > > cover
>>> > > > anything else.
>>> > > >
>>> > > > Ron
>>> > > >
>>> > > >
>>> > > > On Mon, May 14, 2018 at 7:10 PM, Jun Rao <ju...@confluent.io> wrote:
>>> > > >
>>> > > > > Hi, Ron,
>>> > > > >
>>> > > > > Thanks for the KIP. +1 from me. Just a few minor comments below.
>>> > > > >
>>> > > > > 1. It seems that we can translate an OAuth token to a principle name
>>> > > > > through the claim name configured in JASS. However, it's not clear to
>>> > > me
>>> > > > > how an OAuth token is mapped to a claim. Could you clarify that?
>>> > > > >
>>> > > > > 2. The wiki has the following code. It seems that
>>> > > > OAuthBearerTokenCallback
>>> > > > > should implement AuthenticateCallbackHandler? Ditto
>>> > > > > for OAuthBearerValidatorCallback.
>>> > > > >
>>> > > > > public class OAuthBearerTokenCallback implements Callback
>>> > > > >
>>> > > > > 3. In OAuthBearerTokenCallback, we have the following method. The
>>> > OAuth
>>> > > > > spec says the error code is a single ASCII. So, should we return a
>>> > Char
>>> > > > or
>>> > > > > a String?
>>> > > > >
>>> > > > > public String errorCode()
>>> > > > >
>>> > > > > Jun
>>> > > > >
>>> > > > >
>>> > > > > On Thu, May 3, 2018 at 8:55 PM, Ron Dagostino <rn...@gmail.com>
>>> > > wrote:
>>> > > > >
>>> > > > > > Hi everyone.  I would like to start the vote for KIP-255:
>>> > > > > > https://cwiki.apache.org/confluence/pages/viewpage.
>>> > > > > action?pageId=75968876
>>> > > > > >
>>> > > > > > This KIP proposes to add the following functionality related to
>>> > > > > > SASL/OAUTHBEARER:
>>> > > > > >
>>> > > > > > 1) Allow clients (both brokers when SASL/OAUTHBEARER is the
>>> > > > inter-broker
>>> > > > > > protocol as well as non-broker clients) to flexibly retrieve an
>>> > > access
>>> > > > > > token from an OAuth 2 authorization server based on the declaration
>>> > > of
>>> > > > a
>>> > > > > > custom login CallbackHandler implementation and have that access
>>> > > token
>>> > > > > > transparently and automatically transmitted to a broker for
>>> > > > > authentication.
>>> > > > > >
>>> > > > > > 2) Allow brokers to flexibly validate provided access tokens when a
>>> > > > > client
>>> > > > > > establishes a connection based on the declaration of a custom SASL
>>> > > > Server
>>> > > > > > CallbackHandler implementation.
>>> > > > > >
>>> > > > > > 3) Provide implementations of the above retrieval and validation
>>> > > > features
>>> > > > > > based on an unsecured JSON Web Token that function out-of-the-box
>>> > > with
>>> > > > > > minimal configuration required (i.e. implementations of the two
>>> > types
>>> > > > of
>>> > > > > > callback handlers mentioned above will be used by default with no
>>> > > need
>>> > > > to
>>> > > > > > explicitly declare them).
>>> > > > > >
>>> > > > > > 4) Allow clients (both brokers when SASL/OAUTHBEARER is the
>>> > > > inter-broker
>>> > > > > > protocol as well as non-broker clients) to transparently retrieve a
>>> > > new
>>> > > > > > access token in the background before the existing access token
>>> > > expires
>>> > > > > in
>>> > > > > > case the client has to open new connections.
>>> > > > > >
>>> > > > > > Thanks,
>>> > > > > >
>>> > > > > > Ron
>>> > > > > >
>>> > > > >
>>> > > >
>>> > >
>>> >
>> 
> 

Re: [VOTE] KIP-255: OAuth Authentication via SASL/OAUTHBEARER

Posted by Ron Dagostino <rn...@gmail.com>.
Hi committers.  KIP 255 still needs 1 more binding vote.  Currently there
are two binding + 1 votes, from Rajini and Jun, and three non-binding +1
votes, from Mickael, Manikumar, and myself.

Please vote by the Monday deadline.

Ron

On Thu, May 17, 2018 at 10:59 AM, Ron Dagostino <rn...@gmail.com> wrote:

> Hi Jun.  I've updated the KIP to add a new section titled "Summary for
> Production Use" that includes this information along with a consolidated
> set of references to the applicable specifications.  Thanks for the
> questions.
>
> *We still need another binding vote* (currently there are two binding + 1
> votes, from Rajini and Jun, and three non-binding +1 votes, from Mickael,
> Manikumar, and myself).
>
> Please vote before the May 22nd KIP Freeze deadline so this KIP can be
> included in the 2.0.0 release.
>
> A pull request is available and includes additional commits reflecting
> initial review comments: https://github.com/apache/kafka/pull/4994
>
> Ron
>
> On Wed, May 16, 2018 at 8:09 PM, Jun Rao <ju...@confluent.io> wrote:
>
>> Hi, Ron,
>>
>> Thanks. I understand now. It may be useful to add a reference to JWT in
>> the
>> KIP.
>>
>> Jun
>>
>> On Tue, May 15, 2018 at 6:51 PM, Ron Dagostino <rn...@gmail.com> wrote:
>>
>> > Hi Jun.  I think you are getting at the fact that OAuth 2 is a flexible
>> > framework that allows different installations to do things
>> differently.  It
>> > is true that the principal name in Kafka could come from any claim in
>> the
>> > token.  Most of the time it would come from the 'sub' claim, but it
>> could
>> > certainly come from another claim, or it could be only indirectly based
>> on
>> > a claim value (maybe certain text would be trimmed or
>> prefixed/suffixed).
>> > The point, which I think you are getting at, is that because the
>> framework
>> > is flexible we need to accommodate that flexibility.  The callback
>> handler
>> > class defined by the listener.name.sasl_ssl.oauthbearer.sasl.server.
>> > callback.handler.class configuration value gives us the required
>> > flexibility.  As an example, I have an implementation that leverages a
>> > popular open source JOSE library to parse the compact serialization,
>> > retrieve the public key if it has not yet been retrieved, verify the
>> > digital signature, and map the 'sub' claim to the OAuthBearerToken's
>> > principal name (which becomes the SASL authorization ID, which becomes
>> the
>> > Kafka principal name).  I could just as easily have mapped a different
>> > claim to the OAuthBearerToken's principal name, manipulated the 'sub'
>> claim
>> > value in some way, etc.  I write the callback handler code, so I
>> complete
>> > flexibility to do whatever my OAuth 2 installation requires me to do.
>> >
>> > Ron
>> >
>> > On Tue, May 15, 2018 at 1:39 PM, Jun Rao <ju...@confluent.io> wrote:
>> >
>> > > Hi, Ron,
>> > >
>> > > Thanks for the reply. I understood your answers to #2 and #3.
>> > >
>> > > For #1, will the server map all clients' principal name to the value
>> > > associated with "sub" claim? How do we support mapping different
>> clients
>> > to
>> > > different principal names?
>> > >
>> > > Jun
>> > >
>> > > On Mon, May 14, 2018 at 7:02 PM, Ron Dagostino <rn...@gmail.com>
>> > wrote:
>> > >
>> > > > Hi Jun.  Thanks for the +1 vote.
>> > > >
>> > > > Regarding the first question about token claims, yes, you have it
>> > correct
>> > > > about translating the OAuth token to a principle name via a JAAS
>> module
>> > > > option in the default unsecured case.  Specifically, the OAuth SASL
>> > > Server
>> > > > implementation is responsible for setting the authorization ID, and
>> it
>> > > gets
>> > > > the authorization ID from the OAuthBearerToken's principalName()
>> > method.
>> > > > The listener.name.sasl_ssl.oauthbearer.sasl.server.
>> > > callback.handler.class
>> > > > is responsible for handling an instance of
>> OAuthBearerValidatorCallback
>> > > to
>> > > > accept a token compact serialization from the client and return an
>> > > instance
>> > > > of OAuthBearerToken (assuming the compact serialization validates),
>> and
>> > > in
>> > > > the default unsecured case the builtin unsecured validator callback
>> > > handler
>> > > > defines the OAuthBearerToken.principalName() method to return the
>> > 'sub'
>> > > > claim value by default (with the actual claim it uses being
>> > configurable
>> > > > via the unsecuredValidatorPrincipalClaimName JAAS module option).
>> So
>> > > that
>> > > > is how we translate from a token to a principal name in the default
>> > > > unsecured (out-of-the-box) case.
>> > > >
>> > > > For production use cases, the implementation associated with
>> > > > listener.name.sasl_ssl.oauthbearer.sasl.server.callback.
>> handler.class
>> > > can
>> > > > do whatever it wants.  As an example, I have written a class that
>> > wraps a
>> > > > com.nimbusds.jwt.SignedJWT instance (see
>> > > > https://connect2id.com/products/nimbus-jose-jwt/) and presents it
>> as
>> > an
>> > > > OAuthBearerToken:
>> > > >
>> > > > public class NimbusSignedJwtOAuthBearerToken implements
>> > > OAuthBearerToken {
>> > > >     private final SignedJWT signedJwt;
>> > > >     private final String principalName;
>> > > >     private final Set<String> scope;
>> > > >     private final Long startTimeMs;
>> > > >     private final long lifetimeMs;
>> > > >
>> > > >     /**
>> > > >      * Constructor
>> > > >      *
>> > > >      * @param signedJwt
>> > > >      *            the mandatory signed JWT
>> > > >      * @param principalClaimName
>> > > >      *            the mandatory claim name identifying the claim
>> from
>> > > which
>> > > > the
>> > > >      *            principal name will be extracted. The claim must
>> > exist
>> > > > and must be
>> > > >      *            a String.
>> > > >      * @param optionalScopeClaimName
>> > > >      *            the optional claim name identifying the claim from
>> > > which
>> > > > any scope
>> > > >      *            will be extracted. If specified and the claim
>> exists
>> > > then
>> > > > the
>> > > >      *            value must be either a String or a String List.
>> > > >      * @throws ParseException
>> > > >      *             if the principal claim does not exist or is not a
>> > > > String; the
>> > > >      *             scope claim is neither a String nor a String
>> List;
>> > the
>> > > > 'exp'
>> > > >      *             claim does not exist or is not a number; the
>> 'iat'
>> > > claim
>> > > > exists
>> > > >      *             but is not a number; or the 'nbf' claim exists
>> and
>> > is
>> > > > not a
>> > > >      *             number.
>> > > >      */
>> > > >     public NimbusSignedJwtOAuthBearerToken(SignedJWT signedJwt,
>> String
>> > > > principalClaimName,
>> > > >             String optionalScopeClaimName) throws ParseException {
>> > > >         // etc...
>> > > >     }
>> > > >
>> > > > The callback handler runs the following code if the digital
>> signature
>> > > > validates:
>> > > >
>> > > >     callback.token(new NimbusSignedJwtOAuthBearerToken(signedJwt,
>> > "sub",
>> > > > null));
>> > > >
>> > > > I hope that answers the first question.  If not let me know what I
>> > > > missed/misunderstood and I'll be glad to try to address it.
>> > > >
>> > > > Regarding the second question, the classes OAuthBearerTokenCallback
>> and
>> > > > OAuthBearerValidatorCallback implement the Callback interface --
>> they
>> > are
>> > > > the callbacks that the AuthenticateCallbackHandler implementations
>> need
>> > > to
>> > > > handle.  Specifically, unless the unsecured functionality is what is
>> > > > desired, the two configuration values [listener.name.sasl_ssl.
>> > > oauthbearer.
>> > > > ]sasl.login.callback.handler.class and
>> > > > listener.name.sasl_ssl.oauthbearer.sasl.server.callback.
>> handler.class
>> > > > define the callback handlers that need to handle
>> > OAuthBearerTokenCallback
>> > > > and OAuthBearerValidatorCallback, respectively.
>> > > >
>> > > > Regarding the third question, yes, I see your point that the way the
>> > spec
>> > > > is worded could be taken to imply that the error code is a single
>> > > > character: "A single ASCII..." (
>> > > > https://tools.ietf.org/html/rfc6749#section-5.2).  However, it is
>> not
>> > a
>> > > > single character.  See the end of that section 5.2 for an example
>> that
>> > > > shows "error":"invalid_request" as the response.
>> > > >
>> > > > Thanks again for the +1 vote, Jun, and please do let me know if I
>> can
>> > > cover
>> > > > anything else.
>> > > >
>> > > > Ron
>> > > >
>> > > >
>> > > > On Mon, May 14, 2018 at 7:10 PM, Jun Rao <ju...@confluent.io> wrote:
>> > > >
>> > > > > Hi, Ron,
>> > > > >
>> > > > > Thanks for the KIP. +1 from me. Just a few minor comments below.
>> > > > >
>> > > > > 1. It seems that we can translate an OAuth token to a principle
>> name
>> > > > > through the claim name configured in JASS. However, it's not
>> clear to
>> > > me
>> > > > > how an OAuth token is mapped to a claim. Could you clarify that?
>> > > > >
>> > > > > 2. The wiki has the following code. It seems that
>> > > > OAuthBearerTokenCallback
>> > > > > should implement AuthenticateCallbackHandler? Ditto
>> > > > > for OAuthBearerValidatorCallback.
>> > > > >
>> > > > > public class OAuthBearerTokenCallback implements Callback
>> > > > >
>> > > > > 3. In OAuthBearerTokenCallback, we have the following method. The
>> > OAuth
>> > > > > spec says the error code is a single ASCII. So, should we return a
>> > Char
>> > > > or
>> > > > > a String?
>> > > > >
>> > > > > public String errorCode()
>> > > > >
>> > > > > Jun
>> > > > >
>> > > > >
>> > > > > On Thu, May 3, 2018 at 8:55 PM, Ron Dagostino <rn...@gmail.com>
>> > > wrote:
>> > > > >
>> > > > > > Hi everyone.  I would like to start the vote for KIP-255:
>> > > > > > https://cwiki.apache.org/confluence/pages/viewpage.
>> > > > > action?pageId=75968876
>> > > > > >
>> > > > > > This KIP proposes to add the following functionality related to
>> > > > > > SASL/OAUTHBEARER:
>> > > > > >
>> > > > > > 1) Allow clients (both brokers when SASL/OAUTHBEARER is the
>> > > > inter-broker
>> > > > > > protocol as well as non-broker clients) to flexibly retrieve an
>> > > access
>> > > > > > token from an OAuth 2 authorization server based on the
>> declaration
>> > > of
>> > > > a
>> > > > > > custom login CallbackHandler implementation and have that access
>> > > token
>> > > > > > transparently and automatically transmitted to a broker for
>> > > > > authentication.
>> > > > > >
>> > > > > > 2) Allow brokers to flexibly validate provided access tokens
>> when a
>> > > > > client
>> > > > > > establishes a connection based on the declaration of a custom
>> SASL
>> > > > Server
>> > > > > > CallbackHandler implementation.
>> > > > > >
>> > > > > > 3) Provide implementations of the above retrieval and validation
>> > > > features
>> > > > > > based on an unsecured JSON Web Token that function
>> out-of-the-box
>> > > with
>> > > > > > minimal configuration required (i.e. implementations of the two
>> > types
>> > > > of
>> > > > > > callback handlers mentioned above will be used by default with
>> no
>> > > need
>> > > > to
>> > > > > > explicitly declare them).
>> > > > > >
>> > > > > > 4) Allow clients (both brokers when SASL/OAUTHBEARER is the
>> > > > inter-broker
>> > > > > > protocol as well as non-broker clients) to transparently
>> retrieve a
>> > > new
>> > > > > > access token in the background before the existing access token
>> > > expires
>> > > > > in
>> > > > > > case the client has to open new connections.
>> > > > > >
>> > > > > > Thanks,
>> > > > > >
>> > > > > > Ron
>> > > > > >
>> > > > >
>> > > >
>> > >
>> >
>>
>
>

Re: [VOTE] KIP-255: OAuth Authentication via SASL/OAUTHBEARER

Posted by Ron Dagostino <rn...@gmail.com>.
Hi Jun.  I've updated the KIP to add a new section titled "Summary for
Production Use" that includes this information along with a consolidated
set of references to the applicable specifications.  Thanks for the
questions.

*We still need another binding vote* (currently there are two binding + 1
votes, from Rajini and Jun, and three non-binding +1 votes, from Mickael,
Manikumar, and myself).

Please vote before the May 22nd KIP Freeze deadline so this KIP can be
included in the 2.0.0 release.

A pull request is available and includes additional commits reflecting
initial review comments: https://github.com/apache/kafka/pull/4994

Ron

On Wed, May 16, 2018 at 8:09 PM, Jun Rao <ju...@confluent.io> wrote:

> Hi, Ron,
>
> Thanks. I understand now. It may be useful to add a reference to JWT in the
> KIP.
>
> Jun
>
> On Tue, May 15, 2018 at 6:51 PM, Ron Dagostino <rn...@gmail.com> wrote:
>
> > Hi Jun.  I think you are getting at the fact that OAuth 2 is a flexible
> > framework that allows different installations to do things differently.
> It
> > is true that the principal name in Kafka could come from any claim in the
> > token.  Most of the time it would come from the 'sub' claim, but it could
> > certainly come from another claim, or it could be only indirectly based
> on
> > a claim value (maybe certain text would be trimmed or prefixed/suffixed).
> > The point, which I think you are getting at, is that because the
> framework
> > is flexible we need to accommodate that flexibility.  The callback
> handler
> > class defined by the listener.name.sasl_ssl.oauthbearer.sasl.server.
> > callback.handler.class configuration value gives us the required
> > flexibility.  As an example, I have an implementation that leverages a
> > popular open source JOSE library to parse the compact serialization,
> > retrieve the public key if it has not yet been retrieved, verify the
> > digital signature, and map the 'sub' claim to the OAuthBearerToken's
> > principal name (which becomes the SASL authorization ID, which becomes
> the
> > Kafka principal name).  I could just as easily have mapped a different
> > claim to the OAuthBearerToken's principal name, manipulated the 'sub'
> claim
> > value in some way, etc.  I write the callback handler code, so I complete
> > flexibility to do whatever my OAuth 2 installation requires me to do.
> >
> > Ron
> >
> > On Tue, May 15, 2018 at 1:39 PM, Jun Rao <ju...@confluent.io> wrote:
> >
> > > Hi, Ron,
> > >
> > > Thanks for the reply. I understood your answers to #2 and #3.
> > >
> > > For #1, will the server map all clients' principal name to the value
> > > associated with "sub" claim? How do we support mapping different
> clients
> > to
> > > different principal names?
> > >
> > > Jun
> > >
> > > On Mon, May 14, 2018 at 7:02 PM, Ron Dagostino <rn...@gmail.com>
> > wrote:
> > >
> > > > Hi Jun.  Thanks for the +1 vote.
> > > >
> > > > Regarding the first question about token claims, yes, you have it
> > correct
> > > > about translating the OAuth token to a principle name via a JAAS
> module
> > > > option in the default unsecured case.  Specifically, the OAuth SASL
> > > Server
> > > > implementation is responsible for setting the authorization ID, and
> it
> > > gets
> > > > the authorization ID from the OAuthBearerToken's principalName()
> > method.
> > > > The listener.name.sasl_ssl.oauthbearer.sasl.server.
> > > callback.handler.class
> > > > is responsible for handling an instance of
> OAuthBearerValidatorCallback
> > > to
> > > > accept a token compact serialization from the client and return an
> > > instance
> > > > of OAuthBearerToken (assuming the compact serialization validates),
> and
> > > in
> > > > the default unsecured case the builtin unsecured validator callback
> > > handler
> > > > defines the OAuthBearerToken.principalName() method to return the
> > 'sub'
> > > > claim value by default (with the actual claim it uses being
> > configurable
> > > > via the unsecuredValidatorPrincipalClaimName JAAS module option).
> So
> > > that
> > > > is how we translate from a token to a principal name in the default
> > > > unsecured (out-of-the-box) case.
> > > >
> > > > For production use cases, the implementation associated with
> > > > listener.name.sasl_ssl.oauthbearer.sasl.server.
> callback.handler.class
> > > can
> > > > do whatever it wants.  As an example, I have written a class that
> > wraps a
> > > > com.nimbusds.jwt.SignedJWT instance (see
> > > > https://connect2id.com/products/nimbus-jose-jwt/) and presents it as
> > an
> > > > OAuthBearerToken:
> > > >
> > > > public class NimbusSignedJwtOAuthBearerToken implements
> > > OAuthBearerToken {
> > > >     private final SignedJWT signedJwt;
> > > >     private final String principalName;
> > > >     private final Set<String> scope;
> > > >     private final Long startTimeMs;
> > > >     private final long lifetimeMs;
> > > >
> > > >     /**
> > > >      * Constructor
> > > >      *
> > > >      * @param signedJwt
> > > >      *            the mandatory signed JWT
> > > >      * @param principalClaimName
> > > >      *            the mandatory claim name identifying the claim from
> > > which
> > > > the
> > > >      *            principal name will be extracted. The claim must
> > exist
> > > > and must be
> > > >      *            a String.
> > > >      * @param optionalScopeClaimName
> > > >      *            the optional claim name identifying the claim from
> > > which
> > > > any scope
> > > >      *            will be extracted. If specified and the claim
> exists
> > > then
> > > > the
> > > >      *            value must be either a String or a String List.
> > > >      * @throws ParseException
> > > >      *             if the principal claim does not exist or is not a
> > > > String; the
> > > >      *             scope claim is neither a String nor a String List;
> > the
> > > > 'exp'
> > > >      *             claim does not exist or is not a number; the 'iat'
> > > claim
> > > > exists
> > > >      *             but is not a number; or the 'nbf' claim exists and
> > is
> > > > not a
> > > >      *             number.
> > > >      */
> > > >     public NimbusSignedJwtOAuthBearerToken(SignedJWT signedJwt,
> String
> > > > principalClaimName,
> > > >             String optionalScopeClaimName) throws ParseException {
> > > >         // etc...
> > > >     }
> > > >
> > > > The callback handler runs the following code if the digital signature
> > > > validates:
> > > >
> > > >     callback.token(new NimbusSignedJwtOAuthBearerToken(signedJwt,
> > "sub",
> > > > null));
> > > >
> > > > I hope that answers the first question.  If not let me know what I
> > > > missed/misunderstood and I'll be glad to try to address it.
> > > >
> > > > Regarding the second question, the classes OAuthBearerTokenCallback
> and
> > > > OAuthBearerValidatorCallback implement the Callback interface -- they
> > are
> > > > the callbacks that the AuthenticateCallbackHandler implementations
> need
> > > to
> > > > handle.  Specifically, unless the unsecured functionality is what is
> > > > desired, the two configuration values [listener.name.sasl_ssl.
> > > oauthbearer.
> > > > ]sasl.login.callback.handler.class and
> > > > listener.name.sasl_ssl.oauthbearer.sasl.server.
> callback.handler.class
> > > > define the callback handlers that need to handle
> > OAuthBearerTokenCallback
> > > > and OAuthBearerValidatorCallback, respectively.
> > > >
> > > > Regarding the third question, yes, I see your point that the way the
> > spec
> > > > is worded could be taken to imply that the error code is a single
> > > > character: "A single ASCII..." (
> > > > https://tools.ietf.org/html/rfc6749#section-5.2).  However, it is
> not
> > a
> > > > single character.  See the end of that section 5.2 for an example
> that
> > > > shows "error":"invalid_request" as the response.
> > > >
> > > > Thanks again for the +1 vote, Jun, and please do let me know if I can
> > > cover
> > > > anything else.
> > > >
> > > > Ron
> > > >
> > > >
> > > > On Mon, May 14, 2018 at 7:10 PM, Jun Rao <ju...@confluent.io> wrote:
> > > >
> > > > > Hi, Ron,
> > > > >
> > > > > Thanks for the KIP. +1 from me. Just a few minor comments below.
> > > > >
> > > > > 1. It seems that we can translate an OAuth token to a principle
> name
> > > > > through the claim name configured in JASS. However, it's not clear
> to
> > > me
> > > > > how an OAuth token is mapped to a claim. Could you clarify that?
> > > > >
> > > > > 2. The wiki has the following code. It seems that
> > > > OAuthBearerTokenCallback
> > > > > should implement AuthenticateCallbackHandler? Ditto
> > > > > for OAuthBearerValidatorCallback.
> > > > >
> > > > > public class OAuthBearerTokenCallback implements Callback
> > > > >
> > > > > 3. In OAuthBearerTokenCallback, we have the following method. The
> > OAuth
> > > > > spec says the error code is a single ASCII. So, should we return a
> > Char
> > > > or
> > > > > a String?
> > > > >
> > > > > public String errorCode()
> > > > >
> > > > > Jun
> > > > >
> > > > >
> > > > > On Thu, May 3, 2018 at 8:55 PM, Ron Dagostino <rn...@gmail.com>
> > > wrote:
> > > > >
> > > > > > Hi everyone.  I would like to start the vote for KIP-255:
> > > > > > https://cwiki.apache.org/confluence/pages/viewpage.
> > > > > action?pageId=75968876
> > > > > >
> > > > > > This KIP proposes to add the following functionality related to
> > > > > > SASL/OAUTHBEARER:
> > > > > >
> > > > > > 1) Allow clients (both brokers when SASL/OAUTHBEARER is the
> > > > inter-broker
> > > > > > protocol as well as non-broker clients) to flexibly retrieve an
> > > access
> > > > > > token from an OAuth 2 authorization server based on the
> declaration
> > > of
> > > > a
> > > > > > custom login CallbackHandler implementation and have that access
> > > token
> > > > > > transparently and automatically transmitted to a broker for
> > > > > authentication.
> > > > > >
> > > > > > 2) Allow brokers to flexibly validate provided access tokens
> when a
> > > > > client
> > > > > > establishes a connection based on the declaration of a custom
> SASL
> > > > Server
> > > > > > CallbackHandler implementation.
> > > > > >
> > > > > > 3) Provide implementations of the above retrieval and validation
> > > > features
> > > > > > based on an unsecured JSON Web Token that function out-of-the-box
> > > with
> > > > > > minimal configuration required (i.e. implementations of the two
> > types
> > > > of
> > > > > > callback handlers mentioned above will be used by default with no
> > > need
> > > > to
> > > > > > explicitly declare them).
> > > > > >
> > > > > > 4) Allow clients (both brokers when SASL/OAUTHBEARER is the
> > > > inter-broker
> > > > > > protocol as well as non-broker clients) to transparently
> retrieve a
> > > new
> > > > > > access token in the background before the existing access token
> > > expires
> > > > > in
> > > > > > case the client has to open new connections.
> > > > > >
> > > > > > Thanks,
> > > > > >
> > > > > > Ron
> > > > > >
> > > > >
> > > >
> > >
> >
>

Re: [VOTE] KIP-255: OAuth Authentication via SASL/OAUTHBEARER

Posted by Jun Rao <ju...@confluent.io>.
Hi, Ron,

Thanks. I understand now. It may be useful to add a reference to JWT in the
KIP.

Jun

On Tue, May 15, 2018 at 6:51 PM, Ron Dagostino <rn...@gmail.com> wrote:

> Hi Jun.  I think you are getting at the fact that OAuth 2 is a flexible
> framework that allows different installations to do things differently.  It
> is true that the principal name in Kafka could come from any claim in the
> token.  Most of the time it would come from the 'sub' claim, but it could
> certainly come from another claim, or it could be only indirectly based on
> a claim value (maybe certain text would be trimmed or prefixed/suffixed).
> The point, which I think you are getting at, is that because the framework
> is flexible we need to accommodate that flexibility.  The callback handler
> class defined by the listener.name.sasl_ssl.oauthbearer.sasl.server.
> callback.handler.class configuration value gives us the required
> flexibility.  As an example, I have an implementation that leverages a
> popular open source JOSE library to parse the compact serialization,
> retrieve the public key if it has not yet been retrieved, verify the
> digital signature, and map the 'sub' claim to the OAuthBearerToken's
> principal name (which becomes the SASL authorization ID, which becomes the
> Kafka principal name).  I could just as easily have mapped a different
> claim to the OAuthBearerToken's principal name, manipulated the 'sub' claim
> value in some way, etc.  I write the callback handler code, so I complete
> flexibility to do whatever my OAuth 2 installation requires me to do.
>
> Ron
>
> On Tue, May 15, 2018 at 1:39 PM, Jun Rao <ju...@confluent.io> wrote:
>
> > Hi, Ron,
> >
> > Thanks for the reply. I understood your answers to #2 and #3.
> >
> > For #1, will the server map all clients' principal name to the value
> > associated with "sub" claim? How do we support mapping different clients
> to
> > different principal names?
> >
> > Jun
> >
> > On Mon, May 14, 2018 at 7:02 PM, Ron Dagostino <rn...@gmail.com>
> wrote:
> >
> > > Hi Jun.  Thanks for the +1 vote.
> > >
> > > Regarding the first question about token claims, yes, you have it
> correct
> > > about translating the OAuth token to a principle name via a JAAS module
> > > option in the default unsecured case.  Specifically, the OAuth SASL
> > Server
> > > implementation is responsible for setting the authorization ID, and it
> > gets
> > > the authorization ID from the OAuthBearerToken's principalName()
> method.
> > > The listener.name.sasl_ssl.oauthbearer.sasl.server.
> > callback.handler.class
> > > is responsible for handling an instance of OAuthBearerValidatorCallback
> > to
> > > accept a token compact serialization from the client and return an
> > instance
> > > of OAuthBearerToken (assuming the compact serialization validates), and
> > in
> > > the default unsecured case the builtin unsecured validator callback
> > handler
> > > defines the OAuthBearerToken.principalName() method to return the
> 'sub'
> > > claim value by default (with the actual claim it uses being
> configurable
> > > via the unsecuredValidatorPrincipalClaimName JAAS module option).  So
> > that
> > > is how we translate from a token to a principal name in the default
> > > unsecured (out-of-the-box) case.
> > >
> > > For production use cases, the implementation associated with
> > > listener.name.sasl_ssl.oauthbearer.sasl.server.callback.handler.class
> > can
> > > do whatever it wants.  As an example, I have written a class that
> wraps a
> > > com.nimbusds.jwt.SignedJWT instance (see
> > > https://connect2id.com/products/nimbus-jose-jwt/) and presents it as
> an
> > > OAuthBearerToken:
> > >
> > > public class NimbusSignedJwtOAuthBearerToken implements
> > OAuthBearerToken {
> > >     private final SignedJWT signedJwt;
> > >     private final String principalName;
> > >     private final Set<String> scope;
> > >     private final Long startTimeMs;
> > >     private final long lifetimeMs;
> > >
> > >     /**
> > >      * Constructor
> > >      *
> > >      * @param signedJwt
> > >      *            the mandatory signed JWT
> > >      * @param principalClaimName
> > >      *            the mandatory claim name identifying the claim from
> > which
> > > the
> > >      *            principal name will be extracted. The claim must
> exist
> > > and must be
> > >      *            a String.
> > >      * @param optionalScopeClaimName
> > >      *            the optional claim name identifying the claim from
> > which
> > > any scope
> > >      *            will be extracted. If specified and the claim exists
> > then
> > > the
> > >      *            value must be either a String or a String List.
> > >      * @throws ParseException
> > >      *             if the principal claim does not exist or is not a
> > > String; the
> > >      *             scope claim is neither a String nor a String List;
> the
> > > 'exp'
> > >      *             claim does not exist or is not a number; the 'iat'
> > claim
> > > exists
> > >      *             but is not a number; or the 'nbf' claim exists and
> is
> > > not a
> > >      *             number.
> > >      */
> > >     public NimbusSignedJwtOAuthBearerToken(SignedJWT signedJwt, String
> > > principalClaimName,
> > >             String optionalScopeClaimName) throws ParseException {
> > >         // etc...
> > >     }
> > >
> > > The callback handler runs the following code if the digital signature
> > > validates:
> > >
> > >     callback.token(new NimbusSignedJwtOAuthBearerToken(signedJwt,
> "sub",
> > > null));
> > >
> > > I hope that answers the first question.  If not let me know what I
> > > missed/misunderstood and I'll be glad to try to address it.
> > >
> > > Regarding the second question, the classes OAuthBearerTokenCallback and
> > > OAuthBearerValidatorCallback implement the Callback interface -- they
> are
> > > the callbacks that the AuthenticateCallbackHandler implementations need
> > to
> > > handle.  Specifically, unless the unsecured functionality is what is
> > > desired, the two configuration values [listener.name.sasl_ssl.
> > oauthbearer.
> > > ]sasl.login.callback.handler.class and
> > > listener.name.sasl_ssl.oauthbearer.sasl.server.callback.handler.class
> > > define the callback handlers that need to handle
> OAuthBearerTokenCallback
> > > and OAuthBearerValidatorCallback, respectively.
> > >
> > > Regarding the third question, yes, I see your point that the way the
> spec
> > > is worded could be taken to imply that the error code is a single
> > > character: "A single ASCII..." (
> > > https://tools.ietf.org/html/rfc6749#section-5.2).  However, it is not
> a
> > > single character.  See the end of that section 5.2 for an example that
> > > shows "error":"invalid_request" as the response.
> > >
> > > Thanks again for the +1 vote, Jun, and please do let me know if I can
> > cover
> > > anything else.
> > >
> > > Ron
> > >
> > >
> > > On Mon, May 14, 2018 at 7:10 PM, Jun Rao <ju...@confluent.io> wrote:
> > >
> > > > Hi, Ron,
> > > >
> > > > Thanks for the KIP. +1 from me. Just a few minor comments below.
> > > >
> > > > 1. It seems that we can translate an OAuth token to a principle name
> > > > through the claim name configured in JASS. However, it's not clear to
> > me
> > > > how an OAuth token is mapped to a claim. Could you clarify that?
> > > >
> > > > 2. The wiki has the following code. It seems that
> > > OAuthBearerTokenCallback
> > > > should implement AuthenticateCallbackHandler? Ditto
> > > > for OAuthBearerValidatorCallback.
> > > >
> > > > public class OAuthBearerTokenCallback implements Callback
> > > >
> > > > 3. In OAuthBearerTokenCallback, we have the following method. The
> OAuth
> > > > spec says the error code is a single ASCII. So, should we return a
> Char
> > > or
> > > > a String?
> > > >
> > > > public String errorCode()
> > > >
> > > > Jun
> > > >
> > > >
> > > > On Thu, May 3, 2018 at 8:55 PM, Ron Dagostino <rn...@gmail.com>
> > wrote:
> > > >
> > > > > Hi everyone.  I would like to start the vote for KIP-255:
> > > > > https://cwiki.apache.org/confluence/pages/viewpage.
> > > > action?pageId=75968876
> > > > >
> > > > > This KIP proposes to add the following functionality related to
> > > > > SASL/OAUTHBEARER:
> > > > >
> > > > > 1) Allow clients (both brokers when SASL/OAUTHBEARER is the
> > > inter-broker
> > > > > protocol as well as non-broker clients) to flexibly retrieve an
> > access
> > > > > token from an OAuth 2 authorization server based on the declaration
> > of
> > > a
> > > > > custom login CallbackHandler implementation and have that access
> > token
> > > > > transparently and automatically transmitted to a broker for
> > > > authentication.
> > > > >
> > > > > 2) Allow brokers to flexibly validate provided access tokens when a
> > > > client
> > > > > establishes a connection based on the declaration of a custom SASL
> > > Server
> > > > > CallbackHandler implementation.
> > > > >
> > > > > 3) Provide implementations of the above retrieval and validation
> > > features
> > > > > based on an unsecured JSON Web Token that function out-of-the-box
> > with
> > > > > minimal configuration required (i.e. implementations of the two
> types
> > > of
> > > > > callback handlers mentioned above will be used by default with no
> > need
> > > to
> > > > > explicitly declare them).
> > > > >
> > > > > 4) Allow clients (both brokers when SASL/OAUTHBEARER is the
> > > inter-broker
> > > > > protocol as well as non-broker clients) to transparently retrieve a
> > new
> > > > > access token in the background before the existing access token
> > expires
> > > > in
> > > > > case the client has to open new connections.
> > > > >
> > > > > Thanks,
> > > > >
> > > > > Ron
> > > > >
> > > >
> > >
> >
>

Re: [VOTE] KIP-255: OAuth Authentication via SASL/OAUTHBEARER

Posted by Manikumar <ma...@gmail.com>.
+1 (non-binding)

Thanks for the detailed KIP.

On Wed, May 16, 2018 at 5:59 PM, Mickael Maison <mi...@gmail.com>
wrote:

> Thanks for the KIP,
> +1 (non binding)
>
> On Wed, May 16, 2018 at 2:51 AM, Ron Dagostino <rn...@gmail.com> wrote:
> > Hi Jun.  I think you are getting at the fact that OAuth 2 is a flexible
> > framework that allows different installations to do things differently.
> It
> > is true that the principal name in Kafka could come from any claim in the
> > token.  Most of the time it would come from the 'sub' claim, but it could
> > certainly come from another claim, or it could be only indirectly based
> on
> > a claim value (maybe certain text would be trimmed or prefixed/suffixed).
> > The point, which I think you are getting at, is that because the
> framework
> > is flexible we need to accommodate that flexibility.  The callback
> handler
> > class defined by the listener.name.sasl_ssl.oauthbearer.sasl.server.
> > callback.handler.class configuration value gives us the required
> > flexibility.  As an example, I have an implementation that leverages a
> > popular open source JOSE library to parse the compact serialization,
> > retrieve the public key if it has not yet been retrieved, verify the
> > digital signature, and map the 'sub' claim to the OAuthBearerToken's
> > principal name (which becomes the SASL authorization ID, which becomes
> the
> > Kafka principal name).  I could just as easily have mapped a different
> > claim to the OAuthBearerToken's principal name, manipulated the 'sub'
> claim
> > value in some way, etc.  I write the callback handler code, so I complete
> > flexibility to do whatever my OAuth 2 installation requires me to do.
> >
> > Ron
> >
> > On Tue, May 15, 2018 at 1:39 PM, Jun Rao <ju...@confluent.io> wrote:
> >
> >> Hi, Ron,
> >>
> >> Thanks for the reply. I understood your answers to #2 and #3.
> >>
> >> For #1, will the server map all clients' principal name to the value
> >> associated with "sub" claim? How do we support mapping different
> clients to
> >> different principal names?
> >>
> >> Jun
> >>
> >> On Mon, May 14, 2018 at 7:02 PM, Ron Dagostino <rn...@gmail.com>
> wrote:
> >>
> >> > Hi Jun.  Thanks for the +1 vote.
> >> >
> >> > Regarding the first question about token claims, yes, you have it
> correct
> >> > about translating the OAuth token to a principle name via a JAAS
> module
> >> > option in the default unsecured case.  Specifically, the OAuth SASL
> >> Server
> >> > implementation is responsible for setting the authorization ID, and it
> >> gets
> >> > the authorization ID from the OAuthBearerToken's principalName()
> method.
> >> > The listener.name.sasl_ssl.oauthbearer.sasl.server.
> >> callback.handler.class
> >> > is responsible for handling an instance of
> OAuthBearerValidatorCallback
> >> to
> >> > accept a token compact serialization from the client and return an
> >> instance
> >> > of OAuthBearerToken (assuming the compact serialization validates),
> and
> >> in
> >> > the default unsecured case the builtin unsecured validator callback
> >> handler
> >> > defines the OAuthBearerToken.principalName() method to return the
> 'sub'
> >> > claim value by default (with the actual claim it uses being
> configurable
> >> > via the unsecuredValidatorPrincipalClaimName JAAS module option).  So
> >> that
> >> > is how we translate from a token to a principal name in the default
> >> > unsecured (out-of-the-box) case.
> >> >
> >> > For production use cases, the implementation associated with
> >> > listener.name.sasl_ssl.oauthbearer.sasl.server.callback.handler.class
> >> can
> >> > do whatever it wants.  As an example, I have written a class that
> wraps a
> >> > com.nimbusds.jwt.SignedJWT instance (see
> >> > https://connect2id.com/products/nimbus-jose-jwt/) and presents it as
> an
> >> > OAuthBearerToken:
> >> >
> >> > public class NimbusSignedJwtOAuthBearerToken implements
> >> OAuthBearerToken {
> >> >     private final SignedJWT signedJwt;
> >> >     private final String principalName;
> >> >     private final Set<String> scope;
> >> >     private final Long startTimeMs;
> >> >     private final long lifetimeMs;
> >> >
> >> >     /**
> >> >      * Constructor
> >> >      *
> >> >      * @param signedJwt
> >> >      *            the mandatory signed JWT
> >> >      * @param principalClaimName
> >> >      *            the mandatory claim name identifying the claim from
> >> which
> >> > the
> >> >      *            principal name will be extracted. The claim must
> exist
> >> > and must be
> >> >      *            a String.
> >> >      * @param optionalScopeClaimName
> >> >      *            the optional claim name identifying the claim from
> >> which
> >> > any scope
> >> >      *            will be extracted. If specified and the claim exists
> >> then
> >> > the
> >> >      *            value must be either a String or a String List.
> >> >      * @throws ParseException
> >> >      *             if the principal claim does not exist or is not a
> >> > String; the
> >> >      *             scope claim is neither a String nor a String List;
> the
> >> > 'exp'
> >> >      *             claim does not exist or is not a number; the 'iat'
> >> claim
> >> > exists
> >> >      *             but is not a number; or the 'nbf' claim exists and
> is
> >> > not a
> >> >      *             number.
> >> >      */
> >> >     public NimbusSignedJwtOAuthBearerToken(SignedJWT signedJwt,
> String
> >> > principalClaimName,
> >> >             String optionalScopeClaimName) throws ParseException {
> >> >         // etc...
> >> >     }
> >> >
> >> > The callback handler runs the following code if the digital signature
> >> > validates:
> >> >
> >> >     callback.token(new NimbusSignedJwtOAuthBearerToken(signedJwt,
> "sub",
> >> > null));
> >> >
> >> > I hope that answers the first question.  If not let me know what I
> >> > missed/misunderstood and I'll be glad to try to address it.
> >> >
> >> > Regarding the second question, the classes OAuthBearerTokenCallback
> and
> >> > OAuthBearerValidatorCallback implement the Callback interface -- they
> are
> >> > the callbacks that the AuthenticateCallbackHandler implementations
> need
> >> to
> >> > handle.  Specifically, unless the unsecured functionality is what is
> >> > desired, the two configuration values [listener.name.sasl_ssl.
> >> oauthbearer.
> >> > ]sasl.login.callback.handler.class and
> >> > listener.name.sasl_ssl.oauthbearer.sasl.server.callback.handler.class
> >> > define the callback handlers that need to handle
> OAuthBearerTokenCallback
> >> > and OAuthBearerValidatorCallback, respectively.
> >> >
> >> > Regarding the third question, yes, I see your point that the way the
> spec
> >> > is worded could be taken to imply that the error code is a single
> >> > character: "A single ASCII..." (
> >> > https://tools.ietf.org/html/rfc6749#section-5.2).  However, it is
> not a
> >> > single character.  See the end of that section 5.2 for an example that
> >> > shows "error":"invalid_request" as the response.
> >> >
> >> > Thanks again for the +1 vote, Jun, and please do let me know if I can
> >> cover
> >> > anything else.
> >> >
> >> > Ron
> >> >
> >> >
> >> > On Mon, May 14, 2018 at 7:10 PM, Jun Rao <ju...@confluent.io> wrote:
> >> >
> >> > > Hi, Ron,
> >> > >
> >> > > Thanks for the KIP. +1 from me. Just a few minor comments below.
> >> > >
> >> > > 1. It seems that we can translate an OAuth token to a principle name
> >> > > through the claim name configured in JASS. However, it's not clear
> to
> >> me
> >> > > how an OAuth token is mapped to a claim. Could you clarify that?
> >> > >
> >> > > 2. The wiki has the following code. It seems that
> >> > OAuthBearerTokenCallback
> >> > > should implement AuthenticateCallbackHandler? Ditto
> >> > > for OAuthBearerValidatorCallback.
> >> > >
> >> > > public class OAuthBearerTokenCallback implements Callback
> >> > >
> >> > > 3. In OAuthBearerTokenCallback, we have the following method. The
> OAuth
> >> > > spec says the error code is a single ASCII. So, should we return a
> Char
> >> > or
> >> > > a String?
> >> > >
> >> > > public String errorCode()
> >> > >
> >> > > Jun
> >> > >
> >> > >
> >> > > On Thu, May 3, 2018 at 8:55 PM, Ron Dagostino <rn...@gmail.com>
> >> wrote:
> >> > >
> >> > > > Hi everyone.  I would like to start the vote for KIP-255:
> >> > > > https://cwiki.apache.org/confluence/pages/viewpage.
> >> > > action?pageId=75968876
> >> > > >
> >> > > > This KIP proposes to add the following functionality related to
> >> > > > SASL/OAUTHBEARER:
> >> > > >
> >> > > > 1) Allow clients (both brokers when SASL/OAUTHBEARER is the
> >> > inter-broker
> >> > > > protocol as well as non-broker clients) to flexibly retrieve an
> >> access
> >> > > > token from an OAuth 2 authorization server based on the
> declaration
> >> of
> >> > a
> >> > > > custom login CallbackHandler implementation and have that access
> >> token
> >> > > > transparently and automatically transmitted to a broker for
> >> > > authentication.
> >> > > >
> >> > > > 2) Allow brokers to flexibly validate provided access tokens when
> a
> >> > > client
> >> > > > establishes a connection based on the declaration of a custom SASL
> >> > Server
> >> > > > CallbackHandler implementation.
> >> > > >
> >> > > > 3) Provide implementations of the above retrieval and validation
> >> > features
> >> > > > based on an unsecured JSON Web Token that function out-of-the-box
> >> with
> >> > > > minimal configuration required (i.e. implementations of the two
> types
> >> > of
> >> > > > callback handlers mentioned above will be used by default with no
> >> need
> >> > to
> >> > > > explicitly declare them).
> >> > > >
> >> > > > 4) Allow clients (both brokers when SASL/OAUTHBEARER is the
> >> > inter-broker
> >> > > > protocol as well as non-broker clients) to transparently retrieve
> a
> >> new
> >> > > > access token in the background before the existing access token
> >> expires
> >> > > in
> >> > > > case the client has to open new connections.
> >> > > >
> >> > > > Thanks,
> >> > > >
> >> > > > Ron
> >> > > >
> >> > >
> >> >
> >>
>

Re: [VOTE] KIP-255: OAuth Authentication via SASL/OAUTHBEARER

Posted by Mickael Maison <mi...@gmail.com>.
Thanks for the KIP,
+1 (non binding)

On Wed, May 16, 2018 at 2:51 AM, Ron Dagostino <rn...@gmail.com> wrote:
> Hi Jun.  I think you are getting at the fact that OAuth 2 is a flexible
> framework that allows different installations to do things differently.  It
> is true that the principal name in Kafka could come from any claim in the
> token.  Most of the time it would come from the 'sub' claim, but it could
> certainly come from another claim, or it could be only indirectly based on
> a claim value (maybe certain text would be trimmed or prefixed/suffixed).
> The point, which I think you are getting at, is that because the framework
> is flexible we need to accommodate that flexibility.  The callback handler
> class defined by the listener.name.sasl_ssl.oauthbearer.sasl.server.
> callback.handler.class configuration value gives us the required
> flexibility.  As an example, I have an implementation that leverages a
> popular open source JOSE library to parse the compact serialization,
> retrieve the public key if it has not yet been retrieved, verify the
> digital signature, and map the 'sub' claim to the OAuthBearerToken's
> principal name (which becomes the SASL authorization ID, which becomes the
> Kafka principal name).  I could just as easily have mapped a different
> claim to the OAuthBearerToken's principal name, manipulated the 'sub' claim
> value in some way, etc.  I write the callback handler code, so I complete
> flexibility to do whatever my OAuth 2 installation requires me to do.
>
> Ron
>
> On Tue, May 15, 2018 at 1:39 PM, Jun Rao <ju...@confluent.io> wrote:
>
>> Hi, Ron,
>>
>> Thanks for the reply. I understood your answers to #2 and #3.
>>
>> For #1, will the server map all clients' principal name to the value
>> associated with "sub" claim? How do we support mapping different clients to
>> different principal names?
>>
>> Jun
>>
>> On Mon, May 14, 2018 at 7:02 PM, Ron Dagostino <rn...@gmail.com> wrote:
>>
>> > Hi Jun.  Thanks for the +1 vote.
>> >
>> > Regarding the first question about token claims, yes, you have it correct
>> > about translating the OAuth token to a principle name via a JAAS module
>> > option in the default unsecured case.  Specifically, the OAuth SASL
>> Server
>> > implementation is responsible for setting the authorization ID, and it
>> gets
>> > the authorization ID from the OAuthBearerToken's principalName() method.
>> > The listener.name.sasl_ssl.oauthbearer.sasl.server.
>> callback.handler.class
>> > is responsible for handling an instance of OAuthBearerValidatorCallback
>> to
>> > accept a token compact serialization from the client and return an
>> instance
>> > of OAuthBearerToken (assuming the compact serialization validates), and
>> in
>> > the default unsecured case the builtin unsecured validator callback
>> handler
>> > defines the OAuthBearerToken.principalName() method to return the 'sub'
>> > claim value by default (with the actual claim it uses being configurable
>> > via the unsecuredValidatorPrincipalClaimName JAAS module option).  So
>> that
>> > is how we translate from a token to a principal name in the default
>> > unsecured (out-of-the-box) case.
>> >
>> > For production use cases, the implementation associated with
>> > listener.name.sasl_ssl.oauthbearer.sasl.server.callback.handler.class
>> can
>> > do whatever it wants.  As an example, I have written a class that wraps a
>> > com.nimbusds.jwt.SignedJWT instance (see
>> > https://connect2id.com/products/nimbus-jose-jwt/) and presents it as an
>> > OAuthBearerToken:
>> >
>> > public class NimbusSignedJwtOAuthBearerToken implements
>> OAuthBearerToken {
>> >     private final SignedJWT signedJwt;
>> >     private final String principalName;
>> >     private final Set<String> scope;
>> >     private final Long startTimeMs;
>> >     private final long lifetimeMs;
>> >
>> >     /**
>> >      * Constructor
>> >      *
>> >      * @param signedJwt
>> >      *            the mandatory signed JWT
>> >      * @param principalClaimName
>> >      *            the mandatory claim name identifying the claim from
>> which
>> > the
>> >      *            principal name will be extracted. The claim must exist
>> > and must be
>> >      *            a String.
>> >      * @param optionalScopeClaimName
>> >      *            the optional claim name identifying the claim from
>> which
>> > any scope
>> >      *            will be extracted. If specified and the claim exists
>> then
>> > the
>> >      *            value must be either a String or a String List.
>> >      * @throws ParseException
>> >      *             if the principal claim does not exist or is not a
>> > String; the
>> >      *             scope claim is neither a String nor a String List; the
>> > 'exp'
>> >      *             claim does not exist or is not a number; the 'iat'
>> claim
>> > exists
>> >      *             but is not a number; or the 'nbf' claim exists and is
>> > not a
>> >      *             number.
>> >      */
>> >     public NimbusSignedJwtOAuthBearerToken(SignedJWT signedJwt, String
>> > principalClaimName,
>> >             String optionalScopeClaimName) throws ParseException {
>> >         // etc...
>> >     }
>> >
>> > The callback handler runs the following code if the digital signature
>> > validates:
>> >
>> >     callback.token(new NimbusSignedJwtOAuthBearerToken(signedJwt, "sub",
>> > null));
>> >
>> > I hope that answers the first question.  If not let me know what I
>> > missed/misunderstood and I'll be glad to try to address it.
>> >
>> > Regarding the second question, the classes OAuthBearerTokenCallback and
>> > OAuthBearerValidatorCallback implement the Callback interface -- they are
>> > the callbacks that the AuthenticateCallbackHandler implementations need
>> to
>> > handle.  Specifically, unless the unsecured functionality is what is
>> > desired, the two configuration values [listener.name.sasl_ssl.
>> oauthbearer.
>> > ]sasl.login.callback.handler.class and
>> > listener.name.sasl_ssl.oauthbearer.sasl.server.callback.handler.class
>> > define the callback handlers that need to handle OAuthBearerTokenCallback
>> > and OAuthBearerValidatorCallback, respectively.
>> >
>> > Regarding the third question, yes, I see your point that the way the spec
>> > is worded could be taken to imply that the error code is a single
>> > character: "A single ASCII..." (
>> > https://tools.ietf.org/html/rfc6749#section-5.2).  However, it is not a
>> > single character.  See the end of that section 5.2 for an example that
>> > shows "error":"invalid_request" as the response.
>> >
>> > Thanks again for the +1 vote, Jun, and please do let me know if I can
>> cover
>> > anything else.
>> >
>> > Ron
>> >
>> >
>> > On Mon, May 14, 2018 at 7:10 PM, Jun Rao <ju...@confluent.io> wrote:
>> >
>> > > Hi, Ron,
>> > >
>> > > Thanks for the KIP. +1 from me. Just a few minor comments below.
>> > >
>> > > 1. It seems that we can translate an OAuth token to a principle name
>> > > through the claim name configured in JASS. However, it's not clear to
>> me
>> > > how an OAuth token is mapped to a claim. Could you clarify that?
>> > >
>> > > 2. The wiki has the following code. It seems that
>> > OAuthBearerTokenCallback
>> > > should implement AuthenticateCallbackHandler? Ditto
>> > > for OAuthBearerValidatorCallback.
>> > >
>> > > public class OAuthBearerTokenCallback implements Callback
>> > >
>> > > 3. In OAuthBearerTokenCallback, we have the following method. The OAuth
>> > > spec says the error code is a single ASCII. So, should we return a Char
>> > or
>> > > a String?
>> > >
>> > > public String errorCode()
>> > >
>> > > Jun
>> > >
>> > >
>> > > On Thu, May 3, 2018 at 8:55 PM, Ron Dagostino <rn...@gmail.com>
>> wrote:
>> > >
>> > > > Hi everyone.  I would like to start the vote for KIP-255:
>> > > > https://cwiki.apache.org/confluence/pages/viewpage.
>> > > action?pageId=75968876
>> > > >
>> > > > This KIP proposes to add the following functionality related to
>> > > > SASL/OAUTHBEARER:
>> > > >
>> > > > 1) Allow clients (both brokers when SASL/OAUTHBEARER is the
>> > inter-broker
>> > > > protocol as well as non-broker clients) to flexibly retrieve an
>> access
>> > > > token from an OAuth 2 authorization server based on the declaration
>> of
>> > a
>> > > > custom login CallbackHandler implementation and have that access
>> token
>> > > > transparently and automatically transmitted to a broker for
>> > > authentication.
>> > > >
>> > > > 2) Allow brokers to flexibly validate provided access tokens when a
>> > > client
>> > > > establishes a connection based on the declaration of a custom SASL
>> > Server
>> > > > CallbackHandler implementation.
>> > > >
>> > > > 3) Provide implementations of the above retrieval and validation
>> > features
>> > > > based on an unsecured JSON Web Token that function out-of-the-box
>> with
>> > > > minimal configuration required (i.e. implementations of the two types
>> > of
>> > > > callback handlers mentioned above will be used by default with no
>> need
>> > to
>> > > > explicitly declare them).
>> > > >
>> > > > 4) Allow clients (both brokers when SASL/OAUTHBEARER is the
>> > inter-broker
>> > > > protocol as well as non-broker clients) to transparently retrieve a
>> new
>> > > > access token in the background before the existing access token
>> expires
>> > > in
>> > > > case the client has to open new connections.
>> > > >
>> > > > Thanks,
>> > > >
>> > > > Ron
>> > > >
>> > >
>> >
>>

Re: [VOTE] KIP-255: OAuth Authentication via SASL/OAUTHBEARER

Posted by Ron Dagostino <rn...@gmail.com>.
Hi Jun.  I think you are getting at the fact that OAuth 2 is a flexible
framework that allows different installations to do things differently.  It
is true that the principal name in Kafka could come from any claim in the
token.  Most of the time it would come from the 'sub' claim, but it could
certainly come from another claim, or it could be only indirectly based on
a claim value (maybe certain text would be trimmed or prefixed/suffixed).
The point, which I think you are getting at, is that because the framework
is flexible we need to accommodate that flexibility.  The callback handler
class defined by the listener.name.sasl_ssl.oauthbearer.sasl.server.
callback.handler.class configuration value gives us the required
flexibility.  As an example, I have an implementation that leverages a
popular open source JOSE library to parse the compact serialization,
retrieve the public key if it has not yet been retrieved, verify the
digital signature, and map the 'sub' claim to the OAuthBearerToken's
principal name (which becomes the SASL authorization ID, which becomes the
Kafka principal name).  I could just as easily have mapped a different
claim to the OAuthBearerToken's principal name, manipulated the 'sub' claim
value in some way, etc.  I write the callback handler code, so I complete
flexibility to do whatever my OAuth 2 installation requires me to do.

Ron

On Tue, May 15, 2018 at 1:39 PM, Jun Rao <ju...@confluent.io> wrote:

> Hi, Ron,
>
> Thanks for the reply. I understood your answers to #2 and #3.
>
> For #1, will the server map all clients' principal name to the value
> associated with "sub" claim? How do we support mapping different clients to
> different principal names?
>
> Jun
>
> On Mon, May 14, 2018 at 7:02 PM, Ron Dagostino <rn...@gmail.com> wrote:
>
> > Hi Jun.  Thanks for the +1 vote.
> >
> > Regarding the first question about token claims, yes, you have it correct
> > about translating the OAuth token to a principle name via a JAAS module
> > option in the default unsecured case.  Specifically, the OAuth SASL
> Server
> > implementation is responsible for setting the authorization ID, and it
> gets
> > the authorization ID from the OAuthBearerToken's principalName() method.
> > The listener.name.sasl_ssl.oauthbearer.sasl.server.
> callback.handler.class
> > is responsible for handling an instance of OAuthBearerValidatorCallback
> to
> > accept a token compact serialization from the client and return an
> instance
> > of OAuthBearerToken (assuming the compact serialization validates), and
> in
> > the default unsecured case the builtin unsecured validator callback
> handler
> > defines the OAuthBearerToken.principalName() method to return the 'sub'
> > claim value by default (with the actual claim it uses being configurable
> > via the unsecuredValidatorPrincipalClaimName JAAS module option).  So
> that
> > is how we translate from a token to a principal name in the default
> > unsecured (out-of-the-box) case.
> >
> > For production use cases, the implementation associated with
> > listener.name.sasl_ssl.oauthbearer.sasl.server.callback.handler.class
> can
> > do whatever it wants.  As an example, I have written a class that wraps a
> > com.nimbusds.jwt.SignedJWT instance (see
> > https://connect2id.com/products/nimbus-jose-jwt/) and presents it as an
> > OAuthBearerToken:
> >
> > public class NimbusSignedJwtOAuthBearerToken implements
> OAuthBearerToken {
> >     private final SignedJWT signedJwt;
> >     private final String principalName;
> >     private final Set<String> scope;
> >     private final Long startTimeMs;
> >     private final long lifetimeMs;
> >
> >     /**
> >      * Constructor
> >      *
> >      * @param signedJwt
> >      *            the mandatory signed JWT
> >      * @param principalClaimName
> >      *            the mandatory claim name identifying the claim from
> which
> > the
> >      *            principal name will be extracted. The claim must exist
> > and must be
> >      *            a String.
> >      * @param optionalScopeClaimName
> >      *            the optional claim name identifying the claim from
> which
> > any scope
> >      *            will be extracted. If specified and the claim exists
> then
> > the
> >      *            value must be either a String or a String List.
> >      * @throws ParseException
> >      *             if the principal claim does not exist or is not a
> > String; the
> >      *             scope claim is neither a String nor a String List; the
> > 'exp'
> >      *             claim does not exist or is not a number; the 'iat'
> claim
> > exists
> >      *             but is not a number; or the 'nbf' claim exists and is
> > not a
> >      *             number.
> >      */
> >     public NimbusSignedJwtOAuthBearerToken(SignedJWT signedJwt, String
> > principalClaimName,
> >             String optionalScopeClaimName) throws ParseException {
> >         // etc...
> >     }
> >
> > The callback handler runs the following code if the digital signature
> > validates:
> >
> >     callback.token(new NimbusSignedJwtOAuthBearerToken(signedJwt, "sub",
> > null));
> >
> > I hope that answers the first question.  If not let me know what I
> > missed/misunderstood and I'll be glad to try to address it.
> >
> > Regarding the second question, the classes OAuthBearerTokenCallback and
> > OAuthBearerValidatorCallback implement the Callback interface -- they are
> > the callbacks that the AuthenticateCallbackHandler implementations need
> to
> > handle.  Specifically, unless the unsecured functionality is what is
> > desired, the two configuration values [listener.name.sasl_ssl.
> oauthbearer.
> > ]sasl.login.callback.handler.class and
> > listener.name.sasl_ssl.oauthbearer.sasl.server.callback.handler.class
> > define the callback handlers that need to handle OAuthBearerTokenCallback
> > and OAuthBearerValidatorCallback, respectively.
> >
> > Regarding the third question, yes, I see your point that the way the spec
> > is worded could be taken to imply that the error code is a single
> > character: "A single ASCII..." (
> > https://tools.ietf.org/html/rfc6749#section-5.2).  However, it is not a
> > single character.  See the end of that section 5.2 for an example that
> > shows "error":"invalid_request" as the response.
> >
> > Thanks again for the +1 vote, Jun, and please do let me know if I can
> cover
> > anything else.
> >
> > Ron
> >
> >
> > On Mon, May 14, 2018 at 7:10 PM, Jun Rao <ju...@confluent.io> wrote:
> >
> > > Hi, Ron,
> > >
> > > Thanks for the KIP. +1 from me. Just a few minor comments below.
> > >
> > > 1. It seems that we can translate an OAuth token to a principle name
> > > through the claim name configured in JASS. However, it's not clear to
> me
> > > how an OAuth token is mapped to a claim. Could you clarify that?
> > >
> > > 2. The wiki has the following code. It seems that
> > OAuthBearerTokenCallback
> > > should implement AuthenticateCallbackHandler? Ditto
> > > for OAuthBearerValidatorCallback.
> > >
> > > public class OAuthBearerTokenCallback implements Callback
> > >
> > > 3. In OAuthBearerTokenCallback, we have the following method. The OAuth
> > > spec says the error code is a single ASCII. So, should we return a Char
> > or
> > > a String?
> > >
> > > public String errorCode()
> > >
> > > Jun
> > >
> > >
> > > On Thu, May 3, 2018 at 8:55 PM, Ron Dagostino <rn...@gmail.com>
> wrote:
> > >
> > > > Hi everyone.  I would like to start the vote for KIP-255:
> > > > https://cwiki.apache.org/confluence/pages/viewpage.
> > > action?pageId=75968876
> > > >
> > > > This KIP proposes to add the following functionality related to
> > > > SASL/OAUTHBEARER:
> > > >
> > > > 1) Allow clients (both brokers when SASL/OAUTHBEARER is the
> > inter-broker
> > > > protocol as well as non-broker clients) to flexibly retrieve an
> access
> > > > token from an OAuth 2 authorization server based on the declaration
> of
> > a
> > > > custom login CallbackHandler implementation and have that access
> token
> > > > transparently and automatically transmitted to a broker for
> > > authentication.
> > > >
> > > > 2) Allow brokers to flexibly validate provided access tokens when a
> > > client
> > > > establishes a connection based on the declaration of a custom SASL
> > Server
> > > > CallbackHandler implementation.
> > > >
> > > > 3) Provide implementations of the above retrieval and validation
> > features
> > > > based on an unsecured JSON Web Token that function out-of-the-box
> with
> > > > minimal configuration required (i.e. implementations of the two types
> > of
> > > > callback handlers mentioned above will be used by default with no
> need
> > to
> > > > explicitly declare them).
> > > >
> > > > 4) Allow clients (both brokers when SASL/OAUTHBEARER is the
> > inter-broker
> > > > protocol as well as non-broker clients) to transparently retrieve a
> new
> > > > access token in the background before the existing access token
> expires
> > > in
> > > > case the client has to open new connections.
> > > >
> > > > Thanks,
> > > >
> > > > Ron
> > > >
> > >
> >
>

Re: [VOTE] KIP-255: OAuth Authentication via SASL/OAUTHBEARER

Posted by Jun Rao <ju...@confluent.io>.
Hi, Ron,

Thanks for the reply. I understood your answers to #2 and #3.

For #1, will the server map all clients' principal name to the value
associated with "sub" claim? How do we support mapping different clients to
different principal names?

Jun

On Mon, May 14, 2018 at 7:02 PM, Ron Dagostino <rn...@gmail.com> wrote:

> Hi Jun.  Thanks for the +1 vote.
>
> Regarding the first question about token claims, yes, you have it correct
> about translating the OAuth token to a principle name via a JAAS module
> option in the default unsecured case.  Specifically, the OAuth SASL Server
> implementation is responsible for setting the authorization ID, and it gets
> the authorization ID from the OAuthBearerToken's principalName() method.
> The listener.name.sasl_ssl.oauthbearer.sasl.server.callback.handler.class
> is responsible for handling an instance of OAuthBearerValidatorCallback to
> accept a token compact serialization from the client and return an instance
> of OAuthBearerToken (assuming the compact serialization validates), and in
> the default unsecured case the builtin unsecured validator callback handler
> defines the OAuthBearerToken.principalName() method to return the 'sub'
> claim value by default (with the actual claim it uses being configurable
> via the unsecuredValidatorPrincipalClaimName JAAS module option).  So that
> is how we translate from a token to a principal name in the default
> unsecured (out-of-the-box) case.
>
> For production use cases, the implementation associated with
> listener.name.sasl_ssl.oauthbearer.sasl.server.callback.handler.class can
> do whatever it wants.  As an example, I have written a class that wraps a
> com.nimbusds.jwt.SignedJWT instance (see
> https://connect2id.com/products/nimbus-jose-jwt/) and presents it as an
> OAuthBearerToken:
>
> public class NimbusSignedJwtOAuthBearerToken implements OAuthBearerToken {
>     private final SignedJWT signedJwt;
>     private final String principalName;
>     private final Set<String> scope;
>     private final Long startTimeMs;
>     private final long lifetimeMs;
>
>     /**
>      * Constructor
>      *
>      * @param signedJwt
>      *            the mandatory signed JWT
>      * @param principalClaimName
>      *            the mandatory claim name identifying the claim from which
> the
>      *            principal name will be extracted. The claim must exist
> and must be
>      *            a String.
>      * @param optionalScopeClaimName
>      *            the optional claim name identifying the claim from which
> any scope
>      *            will be extracted. If specified and the claim exists then
> the
>      *            value must be either a String or a String List.
>      * @throws ParseException
>      *             if the principal claim does not exist or is not a
> String; the
>      *             scope claim is neither a String nor a String List; the
> 'exp'
>      *             claim does not exist or is not a number; the 'iat' claim
> exists
>      *             but is not a number; or the 'nbf' claim exists and is
> not a
>      *             number.
>      */
>     public NimbusSignedJwtOAuthBearerToken(SignedJWT signedJwt, String
> principalClaimName,
>             String optionalScopeClaimName) throws ParseException {
>         // etc...
>     }
>
> The callback handler runs the following code if the digital signature
> validates:
>
>     callback.token(new NimbusSignedJwtOAuthBearerToken(signedJwt, "sub",
> null));
>
> I hope that answers the first question.  If not let me know what I
> missed/misunderstood and I'll be glad to try to address it.
>
> Regarding the second question, the classes OAuthBearerTokenCallback and
> OAuthBearerValidatorCallback implement the Callback interface -- they are
> the callbacks that the AuthenticateCallbackHandler implementations need to
> handle.  Specifically, unless the unsecured functionality is what is
> desired, the two configuration values [listener.name.sasl_ssl.oauthbearer.
> ]sasl.login.callback.handler.class and
> listener.name.sasl_ssl.oauthbearer.sasl.server.callback.handler.class
> define the callback handlers that need to handle OAuthBearerTokenCallback
> and OAuthBearerValidatorCallback, respectively.
>
> Regarding the third question, yes, I see your point that the way the spec
> is worded could be taken to imply that the error code is a single
> character: "A single ASCII..." (
> https://tools.ietf.org/html/rfc6749#section-5.2).  However, it is not a
> single character.  See the end of that section 5.2 for an example that
> shows "error":"invalid_request" as the response.
>
> Thanks again for the +1 vote, Jun, and please do let me know if I can cover
> anything else.
>
> Ron
>
>
> On Mon, May 14, 2018 at 7:10 PM, Jun Rao <ju...@confluent.io> wrote:
>
> > Hi, Ron,
> >
> > Thanks for the KIP. +1 from me. Just a few minor comments below.
> >
> > 1. It seems that we can translate an OAuth token to a principle name
> > through the claim name configured in JASS. However, it's not clear to me
> > how an OAuth token is mapped to a claim. Could you clarify that?
> >
> > 2. The wiki has the following code. It seems that
> OAuthBearerTokenCallback
> > should implement AuthenticateCallbackHandler? Ditto
> > for OAuthBearerValidatorCallback.
> >
> > public class OAuthBearerTokenCallback implements Callback
> >
> > 3. In OAuthBearerTokenCallback, we have the following method. The OAuth
> > spec says the error code is a single ASCII. So, should we return a Char
> or
> > a String?
> >
> > public String errorCode()
> >
> > Jun
> >
> >
> > On Thu, May 3, 2018 at 8:55 PM, Ron Dagostino <rn...@gmail.com> wrote:
> >
> > > Hi everyone.  I would like to start the vote for KIP-255:
> > > https://cwiki.apache.org/confluence/pages/viewpage.
> > action?pageId=75968876
> > >
> > > This KIP proposes to add the following functionality related to
> > > SASL/OAUTHBEARER:
> > >
> > > 1) Allow clients (both brokers when SASL/OAUTHBEARER is the
> inter-broker
> > > protocol as well as non-broker clients) to flexibly retrieve an access
> > > token from an OAuth 2 authorization server based on the declaration of
> a
> > > custom login CallbackHandler implementation and have that access token
> > > transparently and automatically transmitted to a broker for
> > authentication.
> > >
> > > 2) Allow brokers to flexibly validate provided access tokens when a
> > client
> > > establishes a connection based on the declaration of a custom SASL
> Server
> > > CallbackHandler implementation.
> > >
> > > 3) Provide implementations of the above retrieval and validation
> features
> > > based on an unsecured JSON Web Token that function out-of-the-box with
> > > minimal configuration required (i.e. implementations of the two types
> of
> > > callback handlers mentioned above will be used by default with no need
> to
> > > explicitly declare them).
> > >
> > > 4) Allow clients (both brokers when SASL/OAUTHBEARER is the
> inter-broker
> > > protocol as well as non-broker clients) to transparently retrieve a new
> > > access token in the background before the existing access token expires
> > in
> > > case the client has to open new connections.
> > >
> > > Thanks,
> > >
> > > Ron
> > >
> >
>

Re: [VOTE] KIP-255: OAuth Authentication via SASL/OAUTHBEARER

Posted by Ron Dagostino <rn...@gmail.com>.
Hi Jun.  Thanks for the +1 vote.

Regarding the first question about token claims, yes, you have it correct
about translating the OAuth token to a principle name via a JAAS module
option in the default unsecured case.  Specifically, the OAuth SASL Server
implementation is responsible for setting the authorization ID, and it gets
the authorization ID from the OAuthBearerToken's principalName() method.
The listener.name.sasl_ssl.oauthbearer.sasl.server.callback.handler.class
is responsible for handling an instance of OAuthBearerValidatorCallback to
accept a token compact serialization from the client and return an instance
of OAuthBearerToken (assuming the compact serialization validates), and in
the default unsecured case the builtin unsecured validator callback handler
defines the OAuthBearerToken.principalName() method to return the 'sub'
claim value by default (with the actual claim it uses being configurable
via the unsecuredValidatorPrincipalClaimName JAAS module option).  So that
is how we translate from a token to a principal name in the default
unsecured (out-of-the-box) case.

For production use cases, the implementation associated with
listener.name.sasl_ssl.oauthbearer.sasl.server.callback.handler.class can
do whatever it wants.  As an example, I have written a class that wraps a
com.nimbusds.jwt.SignedJWT instance (see
https://connect2id.com/products/nimbus-jose-jwt/) and presents it as an
OAuthBearerToken:

public class NimbusSignedJwtOAuthBearerToken implements OAuthBearerToken {
    private final SignedJWT signedJwt;
    private final String principalName;
    private final Set<String> scope;
    private final Long startTimeMs;
    private final long lifetimeMs;

    /**
     * Constructor
     *
     * @param signedJwt
     *            the mandatory signed JWT
     * @param principalClaimName
     *            the mandatory claim name identifying the claim from which
the
     *            principal name will be extracted. The claim must exist
and must be
     *            a String.
     * @param optionalScopeClaimName
     *            the optional claim name identifying the claim from which
any scope
     *            will be extracted. If specified and the claim exists then
the
     *            value must be either a String or a String List.
     * @throws ParseException
     *             if the principal claim does not exist or is not a
String; the
     *             scope claim is neither a String nor a String List; the
'exp'
     *             claim does not exist or is not a number; the 'iat' claim
exists
     *             but is not a number; or the 'nbf' claim exists and is
not a
     *             number.
     */
    public NimbusSignedJwtOAuthBearerToken(SignedJWT signedJwt, String
principalClaimName,
            String optionalScopeClaimName) throws ParseException {
        // etc...
    }

The callback handler runs the following code if the digital signature
validates:

    callback.token(new NimbusSignedJwtOAuthBearerToken(signedJwt, "sub",
null));

I hope that answers the first question.  If not let me know what I
missed/misunderstood and I'll be glad to try to address it.

Regarding the second question, the classes OAuthBearerTokenCallback and
OAuthBearerValidatorCallback implement the Callback interface -- they are
the callbacks that the AuthenticateCallbackHandler implementations need to
handle.  Specifically, unless the unsecured functionality is what is
desired, the two configuration values [listener.name.sasl_ssl.oauthbearer.
]sasl.login.callback.handler.class and
listener.name.sasl_ssl.oauthbearer.sasl.server.callback.handler.class
define the callback handlers that need to handle OAuthBearerTokenCallback
and OAuthBearerValidatorCallback, respectively.

Regarding the third question, yes, I see your point that the way the spec
is worded could be taken to imply that the error code is a single
character: "A single ASCII..." (
https://tools.ietf.org/html/rfc6749#section-5.2).  However, it is not a
single character.  See the end of that section 5.2 for an example that
shows "error":"invalid_request" as the response.

Thanks again for the +1 vote, Jun, and please do let me know if I can cover
anything else.

Ron


On Mon, May 14, 2018 at 7:10 PM, Jun Rao <ju...@confluent.io> wrote:

> Hi, Ron,
>
> Thanks for the KIP. +1 from me. Just a few minor comments below.
>
> 1. It seems that we can translate an OAuth token to a principle name
> through the claim name configured in JASS. However, it's not clear to me
> how an OAuth token is mapped to a claim. Could you clarify that?
>
> 2. The wiki has the following code. It seems that OAuthBearerTokenCallback
> should implement AuthenticateCallbackHandler? Ditto
> for OAuthBearerValidatorCallback.
>
> public class OAuthBearerTokenCallback implements Callback
>
> 3. In OAuthBearerTokenCallback, we have the following method. The OAuth
> spec says the error code is a single ASCII. So, should we return a Char or
> a String?
>
> public String errorCode()
>
> Jun
>
>
> On Thu, May 3, 2018 at 8:55 PM, Ron Dagostino <rn...@gmail.com> wrote:
>
> > Hi everyone.  I would like to start the vote for KIP-255:
> > https://cwiki.apache.org/confluence/pages/viewpage.
> action?pageId=75968876
> >
> > This KIP proposes to add the following functionality related to
> > SASL/OAUTHBEARER:
> >
> > 1) Allow clients (both brokers when SASL/OAUTHBEARER is the inter-broker
> > protocol as well as non-broker clients) to flexibly retrieve an access
> > token from an OAuth 2 authorization server based on the declaration of a
> > custom login CallbackHandler implementation and have that access token
> > transparently and automatically transmitted to a broker for
> authentication.
> >
> > 2) Allow brokers to flexibly validate provided access tokens when a
> client
> > establishes a connection based on the declaration of a custom SASL Server
> > CallbackHandler implementation.
> >
> > 3) Provide implementations of the above retrieval and validation features
> > based on an unsecured JSON Web Token that function out-of-the-box with
> > minimal configuration required (i.e. implementations of the two types of
> > callback handlers mentioned above will be used by default with no need to
> > explicitly declare them).
> >
> > 4) Allow clients (both brokers when SASL/OAUTHBEARER is the inter-broker
> > protocol as well as non-broker clients) to transparently retrieve a new
> > access token in the background before the existing access token expires
> in
> > case the client has to open new connections.
> >
> > Thanks,
> >
> > Ron
> >
>

Re: [VOTE] KIP-255: OAuth Authentication via SASL/OAUTHBEARER

Posted by Jun Rao <ju...@confluent.io>.
Hi, Ron,

Thanks for the KIP. +1 from me. Just a few minor comments below.

1. It seems that we can translate an OAuth token to a principle name
through the claim name configured in JASS. However, it's not clear to me
how an OAuth token is mapped to a claim. Could you clarify that?

2. The wiki has the following code. It seems that OAuthBearerTokenCallback
should implement AuthenticateCallbackHandler? Ditto
for OAuthBearerValidatorCallback.

public class OAuthBearerTokenCallback implements Callback

3. In OAuthBearerTokenCallback, we have the following method. The OAuth
spec says the error code is a single ASCII. So, should we return a Char or
a String?

public String errorCode()

Jun


On Thu, May 3, 2018 at 8:55 PM, Ron Dagostino <rn...@gmail.com> wrote:

> Hi everyone.  I would like to start the vote for KIP-255:
> https://cwiki.apache.org/confluence/pages/viewpage.action?pageId=75968876
>
> This KIP proposes to add the following functionality related to
> SASL/OAUTHBEARER:
>
> 1) Allow clients (both brokers when SASL/OAUTHBEARER is the inter-broker
> protocol as well as non-broker clients) to flexibly retrieve an access
> token from an OAuth 2 authorization server based on the declaration of a
> custom login CallbackHandler implementation and have that access token
> transparently and automatically transmitted to a broker for authentication.
>
> 2) Allow brokers to flexibly validate provided access tokens when a client
> establishes a connection based on the declaration of a custom SASL Server
> CallbackHandler implementation.
>
> 3) Provide implementations of the above retrieval and validation features
> based on an unsecured JSON Web Token that function out-of-the-box with
> minimal configuration required (i.e. implementations of the two types of
> callback handlers mentioned above will be used by default with no need to
> explicitly declare them).
>
> 4) Allow clients (both brokers when SASL/OAUTHBEARER is the inter-broker
> protocol as well as non-broker clients) to transparently retrieve a new
> access token in the background before the existing access token expires in
> case the client has to open new connections.
>
> Thanks,
>
> Ron
>

Re: [VOTE] KIP-255: OAuth Authentication via SASL/OAUTHBEARER

Posted by Ron Dagostino <rn...@gmail.com>.
HI again, everyone.  Still looking for 2 more binding votes.  PR is now
available at https://github.com/apache/kafka/pull/4994.

Ron

On Tue, May 8, 2018 at 9:45 AM, Ron Dagostino <rn...@gmail.com> wrote:

> HI everyone.  Can we get 2 more binding votes on this KIP (and non-binding
> votes, too)?
>
> Ron
>
> On Fri, May 4, 2018 at 11:53 AM, Rajini Sivaram <ra...@gmail.com>
> wrote:
>
>> Hi Ron,
>>
>> +1 (binding)
>>
>> Thanks for the KIP!
>>
>> Regards,
>>
>> Rajini
>>
>> On Fri, May 4, 2018 at 4:55 AM, Ron Dagostino <rn...@gmail.com> wrote:
>>
>> > Hi everyone.  I would like to start the vote for KIP-255:
>> > https://cwiki.apache.org/confluence/pages/viewpage.action?
>> pageId=75968876
>> >
>> > This KIP proposes to add the following functionality related to
>> > SASL/OAUTHBEARER:
>> >
>> > 1) Allow clients (both brokers when SASL/OAUTHBEARER is the inter-broker
>> > protocol as well as non-broker clients) to flexibly retrieve an access
>> > token from an OAuth 2 authorization server based on the declaration of a
>> > custom login CallbackHandler implementation and have that access token
>> > transparently and automatically transmitted to a broker for
>> authentication.
>> >
>> > 2) Allow brokers to flexibly validate provided access tokens when a
>> client
>> > establishes a connection based on the declaration of a custom SASL
>> Server
>> > CallbackHandler implementation.
>> >
>> > 3) Provide implementations of the above retrieval and validation
>> features
>> > based on an unsecured JSON Web Token that function out-of-the-box with
>> > minimal configuration required (i.e. implementations of the two types of
>> > callback handlers mentioned above will be used by default with no need
>> to
>> > explicitly declare them).
>> >
>> > 4) Allow clients (both brokers when SASL/OAUTHBEARER is the inter-broker
>> > protocol as well as non-broker clients) to transparently retrieve a new
>> > access token in the background before the existing access token expires
>> in
>> > case the client has to open new connections.
>> >
>> > Thanks,
>> >
>> > Ron
>> >
>>
>
>

Re: [VOTE] KIP-255: OAuth Authentication via SASL/OAUTHBEARER

Posted by Ron Dagostino <rn...@gmail.com>.
HI everyone.  Can we get 2 more binding votes on this KIP (and non-binding
votes, too)?

Ron

On Fri, May 4, 2018 at 11:53 AM, Rajini Sivaram <ra...@gmail.com>
wrote:

> Hi Ron,
>
> +1 (binding)
>
> Thanks for the KIP!
>
> Regards,
>
> Rajini
>
> On Fri, May 4, 2018 at 4:55 AM, Ron Dagostino <rn...@gmail.com> wrote:
>
> > Hi everyone.  I would like to start the vote for KIP-255:
> > https://cwiki.apache.org/confluence/pages/viewpage.
> action?pageId=75968876
> >
> > This KIP proposes to add the following functionality related to
> > SASL/OAUTHBEARER:
> >
> > 1) Allow clients (both brokers when SASL/OAUTHBEARER is the inter-broker
> > protocol as well as non-broker clients) to flexibly retrieve an access
> > token from an OAuth 2 authorization server based on the declaration of a
> > custom login CallbackHandler implementation and have that access token
> > transparently and automatically transmitted to a broker for
> authentication.
> >
> > 2) Allow brokers to flexibly validate provided access tokens when a
> client
> > establishes a connection based on the declaration of a custom SASL Server
> > CallbackHandler implementation.
> >
> > 3) Provide implementations of the above retrieval and validation features
> > based on an unsecured JSON Web Token that function out-of-the-box with
> > minimal configuration required (i.e. implementations of the two types of
> > callback handlers mentioned above will be used by default with no need to
> > explicitly declare them).
> >
> > 4) Allow clients (both brokers when SASL/OAUTHBEARER is the inter-broker
> > protocol as well as non-broker clients) to transparently retrieve a new
> > access token in the background before the existing access token expires
> in
> > case the client has to open new connections.
> >
> > Thanks,
> >
> > Ron
> >
>

Re: [VOTE] KIP-255: OAuth Authentication via SASL/OAUTHBEARER

Posted by Rajini Sivaram <ra...@gmail.com>.
Hi Ron,

+1 (binding)

Thanks for the KIP!

Regards,

Rajini

On Fri, May 4, 2018 at 4:55 AM, Ron Dagostino <rn...@gmail.com> wrote:

> Hi everyone.  I would like to start the vote for KIP-255:
> https://cwiki.apache.org/confluence/pages/viewpage.action?pageId=75968876
>
> This KIP proposes to add the following functionality related to
> SASL/OAUTHBEARER:
>
> 1) Allow clients (both brokers when SASL/OAUTHBEARER is the inter-broker
> protocol as well as non-broker clients) to flexibly retrieve an access
> token from an OAuth 2 authorization server based on the declaration of a
> custom login CallbackHandler implementation and have that access token
> transparently and automatically transmitted to a broker for authentication.
>
> 2) Allow brokers to flexibly validate provided access tokens when a client
> establishes a connection based on the declaration of a custom SASL Server
> CallbackHandler implementation.
>
> 3) Provide implementations of the above retrieval and validation features
> based on an unsecured JSON Web Token that function out-of-the-box with
> minimal configuration required (i.e. implementations of the two types of
> callback handlers mentioned above will be used by default with no need to
> explicitly declare them).
>
> 4) Allow clients (both brokers when SASL/OAUTHBEARER is the inter-broker
> protocol as well as non-broker clients) to transparently retrieve a new
> access token in the background before the existing access token expires in
> case the client has to open new connections.
>
> Thanks,
>
> Ron
>