Skip to content

Commit

Permalink
Merge pull request #1652 from rabbitmq/oauth2-support-dotnet-client
Browse files Browse the repository at this point in the history
Oauth2 support section for dotnet client
  • Loading branch information
michaelklishin authored May 24, 2023
2 parents 1da0cfe + daa0565 commit cfea65d
Showing 1 changed file with 80 additions and 0 deletions.
80 changes: 80 additions & 0 deletions site/dotnet-api-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ Key sections of the guide are:
* [Async Consumer Implementations](#consuming-async)
* [Concurrency Considerations and Safety](#concurrency)
* [Automatic Recovery From Network Failures](#recovery)
* [OAuth 2 Support](#oauth2-support)

An [API reference](https://rabbitmq.github.io/rabbitmq-dotnet-client/api/RabbitMQ.Client.html) is available separately.

Expand Down Expand Up @@ -874,3 +875,82 @@ growing between recoveries.
Acknowledgements with stale delivery tags will not be
sent. Applications that use manual acknowledgements and automatic
recovery must be capable of handling redeliveries.

## <a id="oauth2-support" class="anchor" href="#oauth2-support">OAuth 2 Support</a>

The client can authenticate against an OAuth 2 server like [UAA](https://github.com/cloudfoundry/uaa).
The [OAuth 2 plugin](https://github.com/rabbitmq/rabbitmq-server/tree/main/deps/rabbitmq_auth_backend_oauth2)
must be turned on on the server side and configured to use the same OAuth 2 server as the client.

### <a id="oauth2-getting-token" class="anchor" href="#oauth2-getting-token">Getting the OAuth 2 Token</a>

The .Net client provides the `OAuth2ClientCredentialsProvider`
class to get a JWT token using the [OAuth 2 Client Credentials flow](https://tools.ietf.org/html/rfc6749#section-4.4).
The client sends the access token in the password field when opening a connection.
The broker then verifies the access token signature, validity, and permissions
before authorising the connection and granting access to the requested
virtual host.

<pre class="lang-csharp">
using RabbitMQ.Client.Impl.OAuth2;

...

ICredentialsProvider credentialsProvider = new OAuth2ClientCredentialsProvider("prod-uaa-1",
new OAuth2Client("client_id", "client_secret", new Uri("http://somedomain.com/token")));

var connectionFactory = new ConnectionFactory {
CredentialsProvider = credentialsProvider
};
var connection = connectionFactory.CreateConnection();

</pre>

In production, ensure you use HTTPS for the token endpoint URI and configure
a `HttpClientHandler` appropriately for the `HttpClient` :

<pre class="lang-csharp">
...
HttpClientHandler httpClientHandler = buildHttpClientHandlerWithTLSEnabled();

ICredentialsProvider credentialsProvider = new OAuth2ClientCredentialsProvider("prod-uaa-1",
new OAuth2Client("client_id", "client_secret", new Uri("http://somedomain.com/token"),
OAuth2ClientCredentialsProvider.EMPTY, httpClientHandler));
</pre>

Note: In case your Authorization server requires extra request parameters beyond what the specification
requires, you can add `<key, value>` pairs to a `Dictionary` and passing it to the
`OAuth2ClientCredentialsProvider` constructor rather than an `EMPTY` one as shown above.


### <a id="oauth2-refreshing-token" class="anchor" href="#oauth2-refreshing-token">Refreshing the Token</a>

When tokens expire, the broker refuses further operations over the connection. It is possible to call
`ICredentialsProvider#Refresh()` before expiring and send the new
token to the server. This is not convenient for applications so, the .Net client provides
help with the `TimerBasedCredentialRefresher`. This utility
schedules a timer for every token received. When the timer expires, it reports the
connection which in turn calls `ICredentialsProvider#Refresh()`.

The following snippet shows how to create a `TimerBasedCredentialRefresher`
instance and set it up on the `ConnectionFactory`:

<pre class="lang-csharp">
using RabbitMQ.Client.Impl.OAuth2;

...

ICredentialsProvider credentialsProvider = new OAuth2ClientCredentialsProvider("prod-uaa-1",
new OAuth2Client("client_id", "client_secret", new Uri("http://somedomain.com/token")));
ICredentialsRefresher credentialsRefresher = new TimerBasedCredentialRefresher();

var connectionFactory = new ConnectionFactory {
CredentialsProvider = credentialsProvider,
CredentialsRefresher = credentialsRefresher
};
var connection = connectionFactory.CreateConnection();
</pre>

The `TimerBasedCredentialRefresher` schedules a refresh after 2/3
of the token validity time. For example, if the token expires in 60 minutes,
it is refreshed after 40 minutes.

0 comments on commit cfea65d

Please sign in to comment.