How to work with multiple MessageHandlers #2060
-
|
Hello! Delegation for endpoints and ClientCredentials for Machine to machine communication. Is it possible to register both MessageHandlers and is the code smart enough to figure out when to use which (no http context use client credentials for example?) |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment
-
|
Refit does not auto-pick a handler based on whether an HttpContext is present. Each Refit client is bound to one HttpClient with one handler chain, so you decide which auth applies by which client you resolve. Two common patterns:
// User-delegated (needs HttpContext)
services.AddKeyedRefitClient<IMyApi>("delegated")
.ConfigureHttpClient(c => c.BaseAddress = baseUri)
.AddHttpMessageHandler<DelegatedAuthHandler>();
// Machine-to-machine (client credentials, no HttpContext)
services.AddKeyedRefitClient<IMyApi>("clientcreds")
.ConfigureHttpClient(c => c.BaseAddress = baseUri)
.AddHttpMessageHandler<ClientCredentialsAuthHandler>();Resolve with [FromKeyedServices("delegated")] / GetRequiredKeyedService("clientcreds") depending on the call path. This is the cleanest design because intent is explicit.
public sealed class AuthHandler(IHttpContextAccessor accessor, ITokenService tokens)
: DelegatingHandler
{
protected override async Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request, CancellationToken ct)
{
var token = accessor.HttpContext?.User?.Identity?.IsAuthenticated == true
? await tokens.GetDelegatedTokenAsync(accessor.HttpContext, ct)
: await tokens.GetClientCredentialsTokenAsync(ct);
request.Headers.Authorization = new("Bearer", token);
return await base.SendAsync(request, ct);
}
}Recommendation: prefer option 1 (two keyed clients). It avoids the fragile "is there an HttpContext" heuristic and makes the two flows independently configurable and testable. |
Beta Was this translation helpful? Give feedback.
Refit does not auto-pick a handler based on whether an HttpContext is present. Each Refit client is bound to one HttpClient with one handler chain, so you decide which auth applies by which client you resolve. Two common patterns:
Register the same interface twice as keyed clients (Refit supports AddKeyedRefitClient), each with its own DelegatingHandler: