First time here?

You are looking at the most recent posts. You may also want to check out older archives. Please leave a comment, ask a question and consider subscribing to the latest posts via RSS or email. Thank you for visiting!

A little bit of hidden gem in the Silverlight 4 release is the ability to modify the Authorization header in network calls.  For most, the sheer ability to leverage network credentials in the networking stack will be enough.  But there are times when you may be working with an API that requires something other than basic authentication, but uses the Authorization HTTP header.

The Details

Basically you just set the header value.  How’s that for details :-). 

Seriously though, here’s a snippet of code:

   1: WebClient c = new WebClient();
   2: c.Headers[HttpRequestHeader.Authorization] = "Auth header from same domain-browser stack";
   3: c.DownloadStringCompleted += ((s, args) =>
   4:     {
   5:         if (args.Error != null)
   6:         {
   7:             response.Text = args.Error.Message;
   8:         }
   9:         response.Text = args.Result;
  10:     });
  11: c.DownloadStringAsync(new Uri(http://localhost:4469/handler.ashx));

As you can see in the code is rather simple.  Prior to Silverlight 4 you’d receive an exception that setting the header isn’t possible…but now it is.  If you are using HttpWebRequest instead it would be just as simple:

   1: HttpWebRequest req = (HttpWebRequest)WebRequest.CreateHttp("http://localhost:4469/handler.ashx");
   2: req.Headers[HttpRequestHeader.Authorization] = "Auth header from same domain using HWR";
   3: req.BeginGetResponse((cb) =>
   4:     {
   5:         HttpWebRequest rq = cb.AsyncState as HttpWebRequest;
   6:         HttpWebResponse resp = rq.EndGetResponse(cb) as HttpWebResponse;
   8:         StreamReader rdr = new StreamReader(resp.GetResponseStream());
   9:         string foo = rdr.ReadToEnd();
  10:         Dispatcher.BeginInvoke(() =>
  11:             {
  12:                 response.Text = foo;
  13:             });
  14:         rdr.Close();
  16:     }, req);

That’s it.

The Support Matrix

As such this feature does have some restrictions for security reasons.  Basically the difference has to do with cross-domain calls.  Here’s the feature support matrix in the simplest terms:

Network Stack Used Domain Type Authorization Header Allowed
Browser (default) same domain Yes
ClientHttp same domain Yes
Browser (default) cross-domain Yes with policy
ClientHttp cross-domain Yes with policy

As you can see a cross-domain call of this (i.e., setting an Authorization header on a 3rd party site) would require that a valid clientaccesspolicy.xml be in place.  Here’s an example of a pretty liberal one:

   1: <?xml version="1.0" encoding="utf-8" ?>
   2: <access-policy>
   3:     <cross-domain-access>
   4:         <policy>
   5:             <allow-from http-request-headers="Content-Type,Authorization">
   6:                 <domain uri="*"/>
   7:             </allow-from>
   8:             <grant-to>
   9:                 <resource include-subpaths="true" path="/"/>
  10:             </grant-to>
  11:         </policy>
  12:     </cross-domain-access>
  13: </access-policy>

I should note that when I mean ‘pretty liberal’ this means that the above makes all your resources available to all Silverlight clients.  But pay attention to the http-request-headers section.  Notice the addition of the Authorization header (Content-Type is default always).  By adding this you would be able to have a cross-domain Authorization header writing ability.  Without it you’d see a security exception.  And remember, the policy files exist on the destination endpoint and not in your app.  To demonstrate this, here’s my quick sample application output:

Auth header sample app output

You can download the code for this sample tester application here: Authheaders.zip


Hopefully this is good news to some developers.  Now with Silverlight 4 we have network credentials support and the ability to use the Authorization header when needed for other purposes.  It’s a little hidden gem that frankly could have been better called out in the docs a bit.

Hope this helps!

This work is licensed under a Creative Commons Attribution By license.


The opinions/content expressed on this blog are provided "ASIS" with no warranties and are my own personal opinions/content (unless otherwise noted) and do not represent my employer's view in any way.