33

I'm trying to use HTTPWebRequest to access a REST service, and am having problems passing credentials in, see code below. I've read that NetworkCredential doesn't support SSL, and I'm hitting an HTTPS site. Does anyone know of a class similar to NetworkCredential that does support SSL?

Uri requestUri = null;
Uri.TryCreate("https://mywebserver/webpage", UriKind.Absolute, out requestUri);
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(requestUri);
NetworkCredential nc = new NetworkCredential("user", "password");
request.Credentials = nc;
request.Method = WebRequestMethods.Http.Get;
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
Asbjørn Ulsberg
  • 8,721
  • 3
  • 45
  • 61
Russ Clark
  • 13,260
  • 16
  • 56
  • 81

4 Answers4

49

See if it shows up when you use the old-fashioned method:

string credentials = Convert.ToBase64String(ASCIIEncoding.ASCII.GetBytes("user"+ ":" + "password"));
request.Headers.Add("Authorization", "Basic " + credentials);
Ed Power
  • 8,310
  • 3
  • 36
  • 42
28

What kind of authentication mechanism is protecting the web service? The credentials set on HttpWebRequest will only be passed through HTTP's Authorization header via Basic, Digest or NTLM. So, if your web service is protected with WS-Security, the NetworkCredentials will probably not be passed on to the authentication scheme at all, because WS-Security doesn't operate at the HTTP level.

What you should do is create a Web Service client proxy for the web service through the command line tool wsdl.exe or something similar. That will give you access to Web Service aware authentication schemes.

Update after comments:

It seems like HttpWebRequest needs to receive the WWW-Authenticate challenge with a 401 Unauthorized before it can authenticate properly over SSL. I guess there's two separate code paths in HttpWebRequests handling regular HTTP traffic and encrypted HTTPS traffic. Anyway, what you should try, is:

  1. Execute an unauthenticated HttpWebRequest to the https://.../ URI.
  2. Receive the 401 Unauthorized response.
  3. Execute the same request, now with both Credentials set (not sure if PreAuthenticate should be true or false; test both).
  4. You should now get 200 OK or whatever it is your Web Service responds with.

Another option is to build the Authorization header yourself on the initial request:

string credentials = String.Format("{0}:{1}", username, password);
byte[] bytes = Encoding.ASCII.GetBytes(credentials);
string base64 = Convert.ToBase64String(bytes);
string authorization = String.Concat("Basic ", base64);
request.Headers.Add("Authorization", authorization);
Asbjørn Ulsberg
  • 8,721
  • 3
  • 45
  • 61
  • Sorry, I didn't realize until now that it is a REST Service I'm calling, so there is now wsdl file. Also, I'm able to walk the code in the debugger, and I can see it build up the NetworkCredentials object properly, but it just doesn't seem to be getting passed in with the HttpWebRequest. One more thing - I can successully call the REST service by typing it in to my browser address bar, so it must be using my credentials that way. – Russ Clark Nov 09 '09 at 19:01
  • 1
    You haven't written what authentication scheme you're using and where you have your credentials from. Plus, if this is a REST service, it shouldn't have a WSDL file. A Web Service with a WSDL file is usually a SOAP Web Service which is the direct opposite of a REST Web Service. Being able to access the Web Service with a browser (without typing in any credentials?) sounds like it's protected with HTTP authentication, possibly NTLM. Is this true? – Asbjørn Ulsberg Nov 10 '09 at 07:48
  • Also, what is the response you get? Is it a `401 Unauthorized`, `403 Forbidden` or something else? – Asbjørn Ulsberg Nov 10 '09 at 07:52
  • It's an https site, so the authentication mechanism is SSL - the MSDN online documentation for the NetworkCredential class says it doesn't suport SSL, so I'm thinking that is the problem. The error I'm getting back is 401 Unauthorized. – Russ Clark Nov 10 '09 at 13:53
  • SSL is not an authentication mechanism, it's a cryptographic protocol that provide end-to-end security between the browser and the server. Authentication is orthogonal to SSL and can be done in a number of ways regardless of whether you use SSL or not. Do you need to enter a username and password when visiting this web service in a browser? – Asbjørn Ulsberg Nov 11 '09 at 12:35
  • Thanks for the clarification, I'm clearly not an expert at this. I've found out that we are using Basic authentication. The message I get back when I try to use the NetworkCredential class directly is 401 Unauthorized. If I try to create a CredentialCache object and add the NetworkCredential object to that, then assign it to the HttpWebRequest.Credentials, then I get a 403 Forbidden error message. If I hit the service directly in the browser I'm not prompted for credentials, it just works, so I assume the browser is passing my credentials in for me. – Russ Clark Nov 11 '09 at 13:13
  • 1
    Are your credentials cached in the browser? Which browser are you using? I'm only familiar with one authentication scheme that doesn't actually challenge the user for the credentials like you explain, and that's NTLM, because it can use pre authentication invisibly by sending your Windows credentials to the server. I believe Internet Explorer does this automatically, for instance. – Asbjørn Ulsberg Nov 12 '09 at 16:21
  • Just a small comment on this one: I struggled quite a bit getting this example to work, as it has a lowercase "b" in "basic". My server would not authenticate me unless the header contained "Basic" instead of "basic", even though both username and password was correct. Wikipedia also lists this header with a capital "B", so I would advice you to edit your response :) – Bendik Apr 18 '12 at 07:24
  • I guess this pass the pain text password. Is it possible to encrypt the header? – CharithJ May 15 '17 at 11:37
  • @CharithJ, then you should use another authentication scheme than `Basic`, such as `Digest` (RFC 7616) or `Mutual` (RFC 8120). – Asbjørn Ulsberg May 22 '17 at 19:55
21

If your server uses NTLM authentication you may try this:

CredentialCache cc = new CredentialCache();
cc.Add(
    new Uri("https://mywebserver/webpage"), 
    "NTLM", 
    new NetworkCredential("user", "password"));
request.Credentials = cc;
Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
3

Try setting request.PreAuthenticate to true.

David
  • 34,223
  • 3
  • 62
  • 80
  • 2
    According to [this](http://weblog.west-wind.com/posts/2010/Feb/18/NET-WebRequestPreAuthenticate-not-quite-what-it-sounds-like) it won't work. Still require some work – chaZm Jun 03 '14 at 06:56