https://github.com/robthree/autorefreshtokenhttpmessagehandler
A thread-safe implementation of a DelegatingHandler that automatically refreshes the access token when the access token expires whilst **not** serializing all requests.
https://github.com/robthree/autorefreshtokenhttpmessagehandler
accesstoken c-sharp c-sharp-8 c-sharp-library refreshtoken
Last synced: about 1 month ago
JSON representation
A thread-safe implementation of a DelegatingHandler that automatically refreshes the access token when the access token expires whilst **not** serializing all requests.
- Host: GitHub
- URL: https://github.com/robthree/autorefreshtokenhttpmessagehandler
- Owner: RobThree
- License: mit
- Created: 2024-02-19T12:30:43.000Z (over 1 year ago)
- Default Branch: main
- Last Pushed: 2024-10-09T20:02:33.000Z (8 months ago)
- Last Synced: 2024-10-09T20:16:21.694Z (8 months ago)
- Topics: accesstoken, c-sharp, c-sharp-8, c-sharp-library, refreshtoken
- Language: C#
- Homepage:
- Size: 27.3 KB
- Stars: 4
- Watchers: 2
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Funding: .github/FUNDING.yml
- License: LICENSE
Awesome Lists containing this project
README
#  AutoRefreshTokenHttpMessageHandler
 [](https://www.nuget.org/packages/AutoRefreshTokenHttpMessageHandler/)
This is a thread-safe implementation of a `DelegatingHandler`, available as [Nuget package](https://www.nuget.org/packages/AutoRefreshTokenHttpMessageHandler/), that automatically refreshes the access token when the access token expires whilst **not** serializing all requests. Most implementations use a lock internally which essentially makes all async actions synchronous again. This implementation only blocks during the actual refresh. Inspired by Bryan Helms' [Thread-Safe Auth Token Store Using ConcurrentDictionary and AsyncLazy](https://bryanhelms.com/2021/03/29/thread-safe-auth-token-store-using-concurrentdictionary-and-asynclazy.html).
## Quickstart
```c#
var builder = WebApplication.CreateBuilder(args);builder.Services.Configure(configuration.GetRequiredSection("MyClient"))
.AddTransient()
.AddHttpClient()
.ConfigureHttpClient(c => c.BaseAddress = new Uri("http://auth.myservice.com")).Services
```## Custom service:
```c#
builder.Services.AddHttpClient()
.ConfigureHttpClient(c => c.BaseAddress = new Uri("http://myservice.com"))
.AddHttpMessageHandler();public class MyService(HttpClient client)
{
public Task> GetFoos() => client.GetFromJsonAsync>("/api/v1/foos");
}
```## ...or using [Refit](https://github.com/reactiveui/refit):
```c#
// ...or Refit:
builder.Services.AddRefitClient()
.ConfigureHttpClient(c => c.BaseAddress = new Uri("http://myservice.com"))
.AddHttpMessageHandler();public interface IMyService
{
[Get("/api/v1/foos")]
Task> GetFooss();
}
```## Adding [Polly](https://www.thepollyproject.org/) to the mix:
```c#
builder.Services.AddHttpClient()
.ConfigureHttpClient(c => c.BaseAddress = new Uri("http://myservice.com"))
.AddHttpMessageHandler();
.AddPolicyHandler(HttpPolicyExtensions
.HandleTransientHttpError()
.WaitAndRetryAsync(Backoff.DecorrelatedJitterBackoffV2(TimeSpan.FromSeconds(1), 3))
).Services
```
## Add options to appsettings:### Client credentials:
```json
{
"MyClient": {
"ClientId": "myclient",
"ClientSecret": "clientsecretclientsecretclientsecret",
"TokenEndpoint": "http://auth.myservice.com/realms/myapi/protocol/openid-connect/token"
}
}
```### ...or using username/password:
```json
{
"MyClient": {
"ClientId": "myclient",
"ClientSecret": "clientsecretclientsecretclientsecret",
"Username": "admin",
"Password": "mysup3rs4f3p455w0rd",
"TokenEndpoint": "http://auth.myservice.com/realms/myapi/protocol/openid-connect/token"
}
}
```## Attribution
Icon by [Freepik](https://www.freepik.com/icon/key_908229)