29

I'm trying to use an HttpClient for a third-party service that requires basic HTTP authentication. I am using the AuthenticationHeaderValue. Here is what I've come up with so far:

HttpRequestMessage<RequestType> request = 
    new HttpRequestMessage<RequestType>(
        new RequestType("third-party-vendor-action"),
        MediaTypeHeaderValue.Parse("application/xml"));
request.Headers.Authorization = new AuthenticationHeaderValue(
    "Basic", Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(
        string.Format("{0}:{1}", "username", "password"))));

var task = client.PostAsync(Uri, request.Content);
ResponseType response = task.ContinueWith(
    t =>
    {
        return t.Result.Content.ReadAsAsync<ResponseType>();
    }).Unwrap().Result;

It looks like the POST action works fine, but I don't get back the data I expect. Through some trial and error, and ultimately using Fiddler to sniff the raw traffic, I discovered the authorization header isn't being sent.

I've seen this, but I think I've got the authentication scheme specified as a part of the AuthenticationHeaderValue constructor.

Is there something I've missed?

5 Answers 5

41

Your code looks like it should work - I remember running into a similar problem setting the Authorization headers and solved by doing a Headers.Add() instead of setting it:

request.Headers.Add("Authorization", "Basic " + Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(string.Format("{0}:{1}", "username", "password"))));

UPDATE: It looks like when you do a request.Content, not all headers are being reflected in the content object. You can see this by inspecting request.Headers vs request.Content.Headers. One thing you might want to try is to use SendAsync instead of PostAsync. For example:

HttpRequestMessage<RequestType> request = 
     new HttpRequestMessage<RequestType>(
         new RequestType("third-party-vendor-action"),
         MediaTypeHeaderValue.Parse("application/xml"));

request.Headers.Authorization = 
    new AuthenticationHeaderValue(
        "Basic", 
        Convert.ToBase64String(
            System.Text.ASCIIEncoding.ASCII.GetBytes(
                string.Format("{0}:{1}", "username", "password"))));

 request.Method = HttpMethod.Post;
 request.RequestUri = Uri;
 var task = client.SendAsync(request);

 ResponseType response = task.ContinueWith(
     t => 
         { return t.Result.Content.ReadAsAsync<ResponseType>(); })
         .Unwrap().Result;
Sign up to request clarification or add additional context in comments.

3 Comments

I tried that and something similar with request.Headers.Authorization with the same results. It's left me with a bit of a head-scratcher as I'm not entirely sure what to try next. I know the MVC4 beta and 4.5 preview are directly incompatible for some things - I wonder if that has something to do with it?
Your update seems to at least send the authorization header. I'm not yet able to retrieve data from the third party service yet (probably something else wrong in the request body I've missed), but at least the correct headers are going over the wire. It's a start. Thank you!
21

This would also work and you wouldn't have to deal with the base64 string conversions:

var handler = new HttpClientHandler();
handler.Credentials = new System.Net.NetworkCredential("username", "password");
var client = new HttpClient(handler);
...

1 Comment

much cleaner solution than encoding the UID:PWD combination.
18

Try setting the header on the client:

DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(Encoding.ASCII.GetBytes(String.Format("{0}:{1}", userName, password))));

This works for me.

2 Comments

This would probably work, but it would set the authorization headers for all requests, would it not? That's not desirable.
For all requests made with that instance of a client, yes. Are you using the same client to access endpoints with different authentication schemes? I.e., are you setting the BaseAddress on the client instance or not?
12

Also, consider that Redirect-Handler will clear the Authorization header if your request gets redirected.
So if you call an HTTP endpoint and it redirected to the HTTPS one, you will lose your authorization header.

request.Headers.Authorization = null;

Framework: .NET v6.0

Comments

10

Actually your problem is with PostAsync- you should use SendAsync. In your code - client.PostAsync(Uri, request.Content); sends only the content the request message headers are not included. The proper way is:

HttpRequestMessage message = new HttpRequestMessage(HttpMethod.Post, url)
{
    Content = content
};
message.Headers.Authorization = new AuthenticationHeaderValue("Basic", credentials);
httpClient.SendAsync(message);

2 Comments

A thousand times thank you. I've spent hours trying to attach headers to the HttpClient and using GetAsync and PostAsync etc, and in general am finding WebAPI a pain (give me ServiceStack!!)
A thousand time more thank you! Exactly what I was missing.

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.