rabbitmq / rabbitmq-server

Open source RabbitMQ: core server and tier 1 (built-in) plugins
https://www.rabbitmq.com/
Other
11.83k stars 3.9k forks source link

Support AMQP Claims-based Security in AMQP 1.0 #9259

Open MarcialRosales opened 10 months ago

MarcialRosales commented 10 months ago

Is your feature request related to a problem? Please describe.

In order to fully support OAuth2 authentication in AMQP 1.0 protocol, it should be possible to refresh a token before it expires. Today we use PLAIN SASL authentication mechanism to pass the token in the password field. SASL handle-shake only occurs during the connection establishment phase. Which means, we cannot replace the first token with a new one.

Describe the solution you'd like

In order to fully support token refresh it seems the spec extension, called AMQP Claims-based Security is the way to go. Without having this feature, today our users have to wait until the token expires to reconnect with a new token.

The first course of action is to implement the SASL AMQPCBS Mechanism which is a SASL mechanism meant to transfer one or many, potentially large, tokens to the SASL/AMPQ server. The AMQP 1.0 frame size should be small, e.g. 512 bytes, except for transferring tokens which is allowed to go up to 8192 bytes and send more than one frame until all tokens are transferred.

The second course of action is to handle token refresh. For that, the AMQP client sends set-token messages over a link to a CBS node which holds all the tokens on a connection-basis.

Question 1: According to the spec, a client may send multiple tokens, however RabbitMQ, at least until today, only works with one token, not with many. For instance, if a client refreshes a token on an AMQP 0.9.1 connection via the command update_secret, RabbitMQ drops the old token and use the new one. In AMQP 0.9.1, RabbitMQ supports oauth2 authentication via the SASL PLAIN mechanism. The password field carries the token and the username field is ignored.

Question 2: Is it worth implementing an RFC like SASL AMQPCBS if there are no brokers currently implementing it? All investigated brokers and client libraries (see table below) have adopted what is called as XOAUTH2 which is essentially what RabbitMQ does which is tunneling the token in the password field. Solace mentions that for MQTT connections, the tokens must be less than 4Kbytes. Azure says that to support oauth2 tokens, the maxframesize must be increased. This is what RabbitMQ does at the moment. IBM MQ does not support yet JWT tokens for AMQP 1.0 clients however it does support it over its proprietary API and it does also tunnel the JWT token over the password field. Channels must be configured, like RabbitMQ, to take a token rather than a password, in the password field.

Question 3: Despite being XOAUTH2 the adopted mechanism, it does not address token refresh without reconnecting. Therefore, XOAUTH2 by itself does not give us much because we were looking for a standardized mechanism to refresh tokens and obviously a better protocol support for tokens which allowed for large tokens which could extend beyond the max frame size.

Conclusion: SASL AMQPCBS Mechanism plus AMQP Claim-Based-security (cbs) seem like an ideal solution to handle large tokens and refresh them however there is no evidence that these specifications have been adopted yet. Thus, for now, we have to live with what we have today which tunnelling the token over the password field and wait until the token expires to reconnect with a new obtained token.

Describe alternatives you've considered

In the stream protocol we allowed the exchange of the SASL frame after the connection was established. But I do not think we can do that in AMQP 1.0 protocol unless we want to support it in RabbitMQ. In that case, we would have to modify the amqp10_client too which would only work with RabbitMQ amqp1.0 plugin.

Additional context

https://learn.microsoft.com/en-us/azure/service-bus-messaging/service-bus-amqp-protocol-guide#claims-based-authorization

Other Considerations

AMQP 1.0 client libraries should be able to use this new SASL mechanism for OAuth2. Up until today, tokens have been tunneled via SASL PLAIN mechanism. Clients currently using this SASL PLAIN mechanism for oauth2 authentication have to change in order to continue authenticating with OAuth2 tokens and this mechanism must be readily available in the AMQP 1.0 client library.

Library OAuth2 support
Qpid Proton Supports a different mechanism called XOAUTH2
Qpid JMS Supports XOAuth2
Go AMQP (from Azure) Supports XOAUTH2
Solace Supports XOAUTH2
Javascript rhea XOAUTH2 SASL Mechanism
RabbitMQ.Client for .Net It currently uses PLAIN mechanism. We would need to implement a new mechanism. Either SASLCBS or XOAUTH2
Kafka(broker) Supports XOAUTHBEARER. I have read that this is the new name for XOAUTH2. I need to confirm it. This is the RFC
.Net amqpnetlite It only supports PLAIN, External and Anonymous. There is an opened issue asking for oauth2 support
ansd commented 3 months ago

Which clients implement AMQP Claims-based Security today?

MarcialRosales commented 3 months ago

@ansd so far i have not found any