13

I have a BasicAuthenticationAttribute that inspects the Authorisation header in the request but despite it being present, it still believes the Authorisation header is null:

public class BasicAuthenticationAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(HttpActionContext actionContext)
    {
        if (actionContext.Request.Headers.Authorization == null)
        {
            actionContext.Response = new HttpResponseMessage(HttpStatusCode.Unauthorized);
        }

        ...

If I inspect actionContext.Request.Headers I can see Authorization listed:

{Connection: Keep-Alive
Accept: */*
Accept-Encoding: gzip, deflate
Accept-Language: en-gb
Authorization: REDACTED_BUT_PRESENT==
Host: localhost:44300
Referer: https://localhost:44300/
User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; InfoPath.3; .NET4.0E)
}

Update

I have just inspected the full request headers and they look like this... I can see an Authorization header in the first section, but the Authorization header in the second section is clearly null.

request.Headers

{Connection: Keep-Alive
Accept: */*
Accept-Encoding: gzip, deflate
Accept-Language: en-gb
Authorization: REDACTED_BUT_PRESENT==
Host: localhost:1734
Referer: http://localhost:1734/
User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; InfoPath.3; .NET4.0E)
}
    base {System.Net.Http.Headers.HttpHeaders}: {Connection: Keep-Alive
Accept: */*
Accept-Encoding: gzip, deflate
Accept-Language: en-gb
Authorization: VXNlcjpQYXNzd29yZA==
Host: localhost:1734
Referer: http://localhost:1734/
User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; InfoPath.3; .NET4.0E)
}
    Accept: {*/*}
    AcceptCharset: {}
    AcceptEncoding: {gzip, deflate}
    AcceptLanguage: {en-gb}
    Authorization: null
    CacheControl: null
    ... removed for brevity ...
    Warning: {}
4
  • are you trying Basic authentication. Commented Oct 11, 2012 at 12:52
  • @satish - yes - so I'm setting the Authorisation header and inspecting it using my Action Filter. Commented Oct 11, 2012 at 13:44
  • I have made a Message handler and it seems to work fine. I will try with action filter also. Can you check if this helps gist.github.com/3872727 -Handler ,gist.github.com/3872715 - Unit Test Commented Oct 11, 2012 at 14:26
  • This essentially is the same for me - I can see the Authorization header just as posted, but in the Message Handler it thinks that request.Headers.Authorization is null. Let me inspect the headers generated by the unit tests and see if it looks different. Commented Oct 11, 2012 at 15:15

5 Answers 5

14

If you get stuck on this, you can get the header using:

var header = request.Headers.FirstOrDefault(h => h.Key.Equals("Authorization"));

But not via

var header = request.Headers.Authorization;
Sign up to request clarification or add additional context in comments.

5 Comments

Why is that? That seems bizarre.
I believe because it is a Key/Value structure like a dictionary.
Seriously, why is this though? A library that I'm using checks the Authorization property, not the headers collection...
@Fenton, in Web API2 Controller, we can using Request.Headers.Authorization.Parameter will give the actual token.
Why just not request.Headers["Authorization"] ?!
10

I noticed myself that if the Authorization-header only contained the key/token, the request.Headers.Authorization wouldn't be initiated properly because it's looking for a scheme as well in the format <Scheme> <key/token>, i.e. Authorization: Token VXNlcjpQYXNzd29yZA==, then the Authorization wouldn't be null anymore and contain request.Headers.Authorization.Scheme = "Token" and request.Headers.Authorization.Parameter = "VXNlcjpQYXNzd29yZA=="

Comments

5

I've posted my own example of a Basic Authentication Attribute. Maybe this gives you some hints.

I use:

HttpContext.Current.Request.Headers["Authorization"];

And here is the link to the complete solution:

http://remy.supertext.ch/2012/04/basic-http-authorization-for-web-api-in-mvc-4-beta/

1 Comment

Be aware though that in case of Web API, the HttpContext.Current can be null at times for older versions of .NET or for projects upgraded from an older version: stackoverflow.com/questions/24956178/….
1

Though, this thread is very old but it might help others if I share how did I resolve it in my case:

Request should contain

Authorization: Basic VXNlcjpQYXNzd29yZA==

instead of:

Authorization: VXNlcjpQYXNzd29yZA==

so following change in request may solve the problem:

client.Headers.Add("Authorization", "Basic VXNlcjpQYXNzd29yZA==");

Comments

0

Adding more information to @finstas's answer.

Authorization is null because well defined HTTP headers like Accept, Authorization and many more are parsed when creating the HttpRequestHeaders class. Hence if the request comes in with a format different from what .NET accepts for that header then that specific property will be null.

Below is the decompiled code from the AuthenticationHeaderValue class responsible for parsing the Authorization header. Similarly there are other classes for the different HTTP headers which do the same.

Hope this sheds more info into why there needs to be a space between Token and the value.

internal static int GetAuthenticationLength(string input, int startIndex, out object parsedValue)
{
  parsedValue = (object) null;
  if (string.IsNullOrEmpty(input) || startIndex >= input.Length)
    return 0;
  int tokenLength = HttpRuleParser.GetTokenLength(input, startIndex);
  if (tokenLength == 0)
    return 0;
  AuthenticationHeaderValue authenticationHeaderValue = new AuthenticationHeaderValue();
  authenticationHeaderValue.scheme = input.Substring(startIndex, tokenLength);
  int startIndex1 = startIndex + tokenLength;
  int whitespaceLength = HttpRuleParser.GetWhitespaceLength(input, startIndex1);
  int index = startIndex1 + whitespaceLength;
  if (index == input.Length || (int) input[index] == 44)
  {
    parsedValue = (object) authenticationHeaderValue;
    return index - startIndex;
  }
  if (whitespaceLength == 0)
    return 0;
  int startIndex2 = index;
  int parameterEndIndex = index;
  if (!AuthenticationHeaderValue.TrySkipFirstBlob(input, ref index, ref parameterEndIndex) || index < input.Length && !AuthenticationHeaderValue.TryGetParametersEndIndex(input, ref index, ref parameterEndIndex))
    return 0;
  authenticationHeaderValue.parameter = input.Substring(startIndex2, parameterEndIndex - startIndex2 + 1);
  parsedValue = (object) authenticationHeaderValue;
  return index - startIndex;
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.