Authorization Header Is Lost on Redirect

Authorization header is lost on redirect

The reason you are experiencing this behavior is that it is by design.

Most HTTP clients (by default) strip out authorization headers when following a redirect.

One reason is security. The client could be redirected to an untrusted third party server, one that you would not want to disclose your authorization token to.

What you can do is detect that the redirect has occurred and reissue the request directly to the correct location.

Your API is returning 401 Unauthorized to indicate that the authorization header is missing (or incomplete). I will assume that the same API returns 403 Forbidden if the authorization information is present in the request but is simply incorrect (wrong username / password).

If this is the case, you can detect the 'redirect / missing authorization header' combination and resend the request.


Here is the code from the question rewritten to do this:

[Test]
public void RedirectTest()
{
// These lines are not relevant to the problem, but are included for completeness.
HttpResponseMessage response;
var client = new HttpClient();
using (var authString = new StringContent(@"{username: ""theUser"", password: ""password""}", Encoding.UTF8, "application/json"))
{
response = client.PostAsync("http://host/api/authenticate", authString).Result;
}

string result = response.Content.ReadAsStringAsync().Result;
var authorization = JsonConvert.DeserializeObject<CustomAutorization>(result);

// Relevant from this point on.
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(authorization.Scheme, authorization.Token);
client.DefaultRequestHeaders.Add("Accept", "application/vnd.host+json;version=1");

var requestUri = new Uri("http://host/api/getSomething");
response = client.GetAsync(requestUri).Result;

if (response.StatusCode == HttpStatusCode.Unauthorized)
{
// Authorization header has been set, but the server reports that it is missing.
// It was probably stripped out due to a redirect.

var finalRequestUri = response.RequestMessage.RequestUri; // contains the final location after following the redirect.

if (finalRequestUri != requestUri) // detect that a redirect actually did occur.
{
if (IsHostTrusted(finalRequestUri)) // check that we can trust the host we were redirected to.
{
response = client.GetAsync(finalRequestUri).Result; // Reissue the request. The DefaultRequestHeaders configured on the client will be used, so we don't have to set them again.
}
}
}

Assert.True(response.StatusCode == HttpStatusCode.OK);
}

private bool IsHostTrusted(Uri uri)
{
// Do whatever checks you need to do here
// to make sure that the host
// is trusted and you are happy to send it
// your authorization token.

if (uri.Host == "host")
{
return true;
}

return false;
}

Note that you could save the value of finalRequestUri and use it for future requests to avoid the extra request involved in the retry. However as this is a temporary redirect you should probably issue the request to the original location each time.

Nginx redirection to Phoenix loses authorization header

This is a feature in curl. If a request gets redirected to a different hostname, then any Authorization header is going to be removed in the second request in order not to leak credentials to an unrelated server. (You're making a request to localhost:80, but the redirect location is 0.0.0.0:4000, so that counts as a different hostname.)

You can get curl to forward the Authorization header by using the --location-trusted option instead of -L.

(Though it's odd that you're seeing this with curl 7.54.0 - according to this security advisory, curl 7.54.0 should behave as you expect it to, and only 7.58.0 and higher have this protection feature.)

NodeJS: header authorization missing from redirect using res.writeHead

Headers like auth headers and other custom headers are NOT preserved by the browser when you do a redirect. The browser forms a new request to the location you specified in the redirect response and builds that new request with default headers, not with the headers from your redirect response. It is as if the user typed the redirected URL into the browser URL bar and the browser created a new, default request to that new URL.

You will need to pass information to the redirected request either via the URL path, via query parameters or via a cookie. Query parameters and the URL path will always be present on the redirected request and cookies will be present if the cookie is set on the domain of the redirected target.

When the "new" request arrives to the other NodeJS server, the authorization header is missing

Headers are not preserved when redirecting the browser. The browser creates a new request with default headers to the location specified in the redirect. Any information you want to communicate to the new target must be either in the redirect URL (path or query parameters) or in a cookie that is set on the target domain.

How to prevent Safari from dropping the Authorization header when following a same-origin redirect?

Safari 15.4+ (iOS 15.4, macOS 12.3) users will no longer experience this Authorization drop.

Details: A fix for this was actually merged into the WebKit/Safari code back in October 2021 but per comments at https://bugs.webkit.org/show_bug.cgi?id=230935#c18 didn’t end up shipping until mid-March 2022 in Safari 15.4.

So, this problem will continue to happen for any users of Safari versions prior to to 15.4 — users not upgraded to iOS 15.4 or macOS 12.3 yet — but not for users with current Safari/iOS/macOS.

NSURLRequest lost HTTP header “Authorization” while redirecting the request

'Authorization' header is one from the 'special' headers that are advised not to be modified. This is from Apple's documentation (LINK):

The NSURLConnection class and NSURLSession classes are designed to handle various aspects >of the HTTP protocol for you. As a result, you should not modify the following headers:

  • Authorization
  • Connection
  • Host
  • WWW-Authenticate

Passing Authorization Header in multiple redirects of HttpClient

I was missing the delegation handler, which will handle the redirects.
https://stackoverflow.com/a/19493338/3459965
this link helps me

Updated Code is:

 static async Task CallWebAPIAsync()
{
HttpClientHandler clientHandler = new HttpClientHandler();
WebRequestHandler webRequestHandler = new WebRequestHandler();
webRequestHandler.UseDefaultCredentials = true;
webRequestHandler.AllowPipelining = true;
webRequestHandler.AllowAutoRedirect = false;
webRequestHandler.Credentials = CredentialCache.DefaultCredentials;

GlobalRedirectHandler globalRedirectHandler = new GlobalRedirectHandler() { InnerHandler = webRequestHandler };

using (var client = new HttpClient(globalRedirectHandler))
{
client.BaseAddress = new Uri("https://apitest");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", token);

client.Timeout = TimeSpan.FromSeconds(30000);
//GET Method
var response = await client.GetAsync("user").ConfigureAwait(false);
if (response.IsSuccessStatusCode)
{
var responseresult = await response.Content.ReadAsStringAsync();
Console.WriteLine("Id:{0}\tName:{1}", responseresult);
}
else
{
Console.WriteLine("Internal server Error");
}

}
}

C# HttpClient authorization header removed after send to server

I find out the problem. It's really Ridiculous.
When I use URL like www.abc.com/api/something the request gets 301 error and postman sends another request like www.abc.com/api/something/. The difference is just / at the end of request.
I tried new URL in postman and first request got ok.
Also I tried URL in my C# code and again its ok.
But i could not understand why.

Thanks a lot dear @pharaz-fadaei



Related Topics



Leave a reply



Submit