I'm using IdentityModel.AspNetCore Package to access a protected API using client credential flow.
In my startup, I have the following configuration
services.AddAccessTokenManagement(options =>
{
options.Client.Clients.Add("oauth", new ClientCredentialsTokenRequest
{
Address = Configuration.GetValue<string>("Endpoint"),
ClientId = Configuration.GetValue<string>("ClientId"),
ClientSecret = Configuration.GetValue<string>("ClientSecret"),
Scope = Configuration.GetValue<string>("Scope")
});
});
services.AddClientAccessTokenClient("client", configureClient: client =>
{
client.BaseAddress = new Uri(Configuration.GetValue<string>("ApiBaseUrl"));
});
In my service I'm getting a client instance using IHttpClientFactory
var client = clientFactory.CreateClient("client");
This code is working fine, and I can access the API.
My question is, when I expand the client instance I get from clientFactory, the Authorization header in there is null.
So I'm very confused how this is working.
I expected that it'll have Authorization header value set with the bearer token details.
So how is this working? How is the bearer token set by IdentityModel?
(API is correctly authorizing it seems as if I change the client secret it'll give a 401)
.NET allows you to attach
DelegatingHandlers to anHttpClientto intercept and modify the requests & responses. After you send a request, it goes through a stack of handlers before actually being sent through the network.IdentityModel library works the same way. It intercepts the request, and adds the
Authorizationhandler before sending it. Then it checks the response forHTTP 401errors, and refreshes the token and repeats the request.Here's how it works (source):
As for the actual
Authorizationheader that seems to be missing, you can find it insideHttpResponseMessage.RequestMessageproperty.From the docs (emphasis mine):
Further references: