diff --git a/site/dotnet-api-guide.md b/site/dotnet-api-guide.md index 651f688682..3eae71ca7e 100644 --- a/site/dotnet-api-guide.md +++ b/site/dotnet-api-guide.md @@ -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. @@ -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. + +## OAuth 2 Support + +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. + +### Getting the OAuth 2 Token + +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. + +
+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();
+
+
+ +In production, ensure you use HTTPS for the token endpoint URI and configure +a `HttpClientHandler` appropriately for the `HttpClient` : + +
+...
+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));
+
+ +Note: In case your Authorization server requires extra request parameters beyond what the specification +requires, you can add `` pairs to a `Dictionary` and passing it to the +`OAuth2ClientCredentialsProvider` constructor rather than an `EMPTY` one as shown above. + + +### Refreshing the Token + +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`: + +
+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();
+
+ +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.