refit icon indicating copy to clipboard operation
refit copied to clipboard

Authorization header not being set when provided as [HeaderCollection]

Open DrLeh opened this issue 3 years ago • 8 comments

My issue stated here: https://stackoverflow.com/questions/72172657/c-sharp-refit-client-is-not-sending-authorization-header

I'm using a C# client to have my services talk to one another via http.

I'm trying to send a Bearer token through the Authorization header, but according to the error message, it's not setting the AZ header in the request (see bottom). I've tried setting it through providing all headers, and using the [Authorize] attribute, and all the other methods as described in the readme.

Here is my Refit client api call definition:

[Post(PresentationsBasePath + "/{presentationId}/cart")]
Task AddItemToCartAsync(long presentationId, ShoppingCartItemView item, [HeaderCollection] IDictionary<string, string> headers);

private Dictionary<string, string> GetTokenHeader(long presentationId, string token) => new()
{
    ["pres_id"] = presentationId.ToString(),
    [HeaderNames.Authorization] = $"Bearer {token}",
};

var header = GetTokenHeader(presentationId, token);
await _api.AddItemToCartAsync(presentationId, item, header);

However, I'm getting a 401, and looking at the Refit.ApiException that's thrown, the RequestMessage.Headers does not contain the Authorization header. When I debug the receiving server, i'm seeing that there is indeed no Authorization header set on the incoming request.

Here's how I'm registering my refit api IPresentationsApi. I'm not doing anything relating to auth in the DI configuration

var refitSettings = GetRefitSettings();

void Configure<T>() where T : class => services
    .AddRefitClient<T>()
    .ConfigureHttpClient(ConfigureHttpClient);

Configure<IMarsPresentationApi>();
//other apis configured below

    
    private static void ConfigureHttpClient(IServiceProvider sp, HttpClient client)
    {
        var config = sp.GetRequiredService<IMarsConfiguration>();
        if (config.BaseUrl == null)
            throw new InvalidOperationException("Mars:BaseUrl must be configured");
        client.BaseAddress = new Uri(config.BaseUrl);
    }

Error shown here- you can see I get 401 because the AZ header is not set in the request as expected, even though the pres_id value is:

image

And on the server-side I can also verify that there's no AZ header set image

What am I doing wrong? How do I get it to send the AZ header?

Environment

  • Refit Version: 6.3.2

DrLeh avatar Jun 09 '22 17:06 DrLeh

From your code sample it doesn't look like you're doing anything wrong, so it's surprising you say it's not working. I had a go at doing a reproduction of this and wrote some tests including one for this specific scenario but all the tests pass and when I inspect it via the debugger it works perfectly.

https://github.com/reactiveui/refit/pull/1385

james-s-tayler avatar Jul 19 '22 11:07 james-s-tayler

Im having the same issue, except I have narrowed down mine to adding it to refit Settings

using Microsoft.Net.Http.Headers;
using Refit;

var header = "<insert>";
var refitSettings = new RefitSettings()
{
    AuthorizationHeaderValueGetter = async () => await Task.FromResult(header)
};

var client = RestService.For<IGraphQLApi>("https://thegraphqlendpoint", refitSettings);
var result = await client.SendQuery("Doesnt matter");
Console.WriteLine(result.StatusCode);
Console.ReadKey();

public interface IGraphQLApi
{
    // for testing locally
    [Post("/GraphQL")]
    public Task<HttpResponseMessage> SendQuery([Body] string query);
}

I have used this same code, slightly changed in the past, and it has worked, but this time it is not working. However, DrLeh way works for me. Could be that Task.FromResult, but again it has worked in the past. This is a .net core console application.

refit

EDIT: Added the async/await to the Header Task and still didnt see the headers in the client or the request

supermitsuba avatar Jul 28 '22 20:07 supermitsuba

I had the same problem and searching for a solution I stumbled over several posts, saying that Authorization header gets stripped, when a redirect happens. https://docs.microsoft.com/en-us/dotnet/api/system.net.http.httpclienthandler.allowautoredirect?view=net-6.0#remarks I changed my code to:

services.AddHeaderPropagation(options => options.Headers.Add("Authorization"));
services.AddRefitClient<IIdentityApi>(settings)
                .ConfigurePrimaryHttpMessageHandler(() => new HttpClientHandler() { AllowAutoRedirect = false })
                .ConfigureHttpClient(client =>
                {
                    client.BaseAddress = new Uri(url);
                })
                .AddHeaderPropagation() // Enable on this specific client
                ;

With that I got an exception thrown, that a redirect happened. Might be worth checking if it is the same for you.

Gets or sets a value that indicates whether the handler should follow redirection responses.

Edit: fixed code formatting

b1ubb0r avatar Aug 12 '22 06:08 b1ubb0r

Same problem happening here

osnipezzini avatar Sep 14 '22 18:09 osnipezzini

I hit this same issue and discovered that I was receiving redirects from my target API thanks to @b1ubb0r 's comment above ☝🏻.

I wanted to add that in my case I was being returned a 301-Moved Permanently because I had configured my endpoint to be /{presentationId}/cart and this particular API was being a bit fussy and redirecting me to /{presentationId}/cart/ 🙄

simonneedham avatar Feb 17 '23 09:02 simonneedham