The proxy generated by NSWAG for C# when calling an API is correctly getting a 401 when the token has expired. Is it possible to have it handle refreshing the token, or should be handled higher up the chain in my APP ? I am using MSAL
Asked
Active
Viewed 129 times
1 Answers
0
I use NSwag also to generate the API Clients in VS (using the VS extension REST API Code Generator for VS).
My approach was to override SendAsync using DelegatingHandler. In this handle is possible to catch the response of SendAsync and then manage to refresh the token. I found a kind of implementation in the docs, but in this answer you can find the source of my approach to implement the handle:
public partial class CustomDelegatingHandler : DelegatingHandler
{
private static SemaphoreSlim sem = new SemaphoreSlim(1);
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
var response = await base.SendAsync(request, cancellationToken);
// check status unauthorized && header authorization is not empty && refresh token exists
if (response.StatusCode == HttpStatusCode.Unauthorized &&
!string.IsNullOrEmpty(request.Headers.Authorization.Parameter) &&
!string.IsNullOrEmpty(Globals.tokenData.RefreshToken))
{
//going to request refresh token: enter or start wait
await sem.WaitAsync();
// refresh token
var tokenService = new AuthClient(Globals.tokenData.AuthURL);
var newTokenData = await tokenService.RestClient.TokenPUTAsync(new RESTClients.AuthAPI.RefreshTokenRequestData()
{
RefreshToken = Globals.tokenData.RefreshToken
}, cancellationToken);
// reset header token
request.Headers.Authorization = new
System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", newTokenData.Token.TokenID);
//headers are set, so release:
sem.Release();
//retry actual request with new tokens
response = await base.SendAsync(request, cancellationToken);
}
return response;
}
}
I used a global/static variable to store the refresh tokens and other authentication data required.
In my case I had no chance to use dependency injection (DI) as the answer I linked before. Then, before using the service, I create a HttpClient and I assign the CustomDelegatingHandler to this HttpClient.
System.Net.Http.HttpClient httpClient =
new System.Net.Http.HttpClient(new CustomDelegatingHandler());
var RestClient = new NSWagerAPIClient(httpClient);

SpicyCatGames
- 863
- 7
- 25

Ruekov
- 16
- 6