An open API service indexing awesome lists of open source software.

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.

Awesome Lists containing this project

README

        

# ![Logo](https://raw.githubusercontent.com/RobThree/AutoRefreshTokenHttpMessageHandler/main/icon.png) AutoRefreshTokenHttpMessageHandler

![Build Status](https://img.shields.io/github/actions/workflow/status/RobThree/AutoRefreshTokenHttpMessageHandler/test.yml?branch=main&style=flat-square) [![Nuget version](https://img.shields.io/nuget/v/AutoRefreshTokenHttpMessageHandler.svg?style=flat-square)](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)