Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Better support for OAuth2 authorization backend #1159

Open
kratkyzobak opened this issue Feb 9, 2024 · 0 comments
Open

Better support for OAuth2 authorization backend #1159

kratkyzobak opened this issue Feb 9, 2024 · 0 comments
Labels

Comments

@kratkyzobak
Copy link

RabbitMQ supports OAuth2 authorization, which has some challenges for clients to implement.

** OAuth2 in RabbitMQ **

For login, nothing is changed - OAuth token is passed instead of password with any username (username is read from token), so there is no need to upgrade library at all.

But for long running processes, there is problem. OAuth access tokens has it's expiration. This is usually something about few minutes to one hour, depending on concrete IdP. RabbitMQ developers decided to "unauthorize" connections after token expiration. So long-running workers which are connected to RabbitMQ needs to upgrade access token in connection before expiration.

** How it can be implemented **

First, generally simple step, is to expose any method to support connection.update-secret call for long-running processes.

This would be still very low level support for OAuth2 authorization as library consumer still needs to handle some timer function to upgrade secret.

I believe, there is few possibilities to handle this inside library, but I'm not sure what is "correct" (and would be accepted by maintainers).

Simple part is initial password use. Instead of password, there can be some interface TokenProvider which would have method to return token and it's expiration - this is very common for OAuth2. Configuration and/or connection constructors would accept null|string|TokenProvider $password instead of just nullable strings. For initial connection it's easy - If $password instanceof TokenProvider, just call provideToken and use it as password. For lazy connection / reconnect - if token provider is present in instance, call provideToken before new connection is done. This part is still improvement from current state, as for long-running processes with lazy connections, where "password" can expire even before first connection attempt. (PR soon)

Hard part is when to call update-secret on existing connections. Library can either use some timer function OR enable user to use it's own timer and call library. In this library, there is already PCNTL/SIG handlers of heartbeats so it can be combined into something "better than just heartbeat", but it can also check access token expiration time and update it if possible. Problem is, that pcntl_alarm callback can be only one. So some refactoring would be needed to support both - heartbeats and updating secrets. Also, it would be good to try to support multiple RabbitMQ connections with heartbeats.

Another solution can be on library side, where check if "secret is valid" can be done during generic read/writes (or during heartbeats?).

Either variant, there should be code like:

if ($this->is_connected && $this->current_token->expiration < time() - $fewSeconds)) {
    $this->updatePassword($this->token_provider->provideToken());
}

And problem is where to call this code from. I'm open to provide PR with any strategy, but I need to guidance from maintainers to say which way is acceptable by them.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants