|
One of the things the Silverlight Networking stack lacks is the support for credentials. Where we have things like the below in the full CLR, Silverlight doesn’t have any support.
httpWebRequest.Credentials = new NetworkCredential(username, password);
Investigation
So what about some investigation of the use of credentials. I remembered something about the usage of request headers for sending credentials. After a few minutes googleing I got support from a page on Oreilly about HTTP Headers. I found out the headername is "Authorization" and the value consist of authorization scheme and the credentials base64 encoded.
Tryout in full CLR
I tried to get it to work within the full CLR. I made two extension methods, one to set the RequestHeader and the other to convert a string to base64 encoding. As you can see the username and password will be divided by a colon before encoding the string to base64.
This code seemed to work on the CLR. So I thought very nice, on to the limited Silverlight CLR.
1 internal static class Extensions
2 {
3 public static void SetCredentials(this WebRequest request, string username, string password)
4 {
5 request.Headers["Authorization"] = string.Format("Basic {0}",
6 string.Format("{0}:{1}",username, password).EncodeTo64());
7 }
8
9 public static string EncodeTo64(this string toEncode)
10 {
11 byte[] toEncodeAsBytes
12 = Encoding.ASCII.GetBytes(toEncode);
13
14 string returnValue
15 = Convert.ToBase64String(toEncodeAsBytes);
16 return returnValue;
17 }
18 }
Trying to get it to work with the Silverlight CLR
The first thing I had to do was to change the Encoding to use Encoding.Unicode, the ASCII character set isn’t available as it seems. After this all the compilation errors were gone. But something very frustrating came around: "Error: This header must be modified using the appropriate property." Was I doing something wrong? It worked on the full CLR, why not within Silverlight?
After an investigation with Reflector I found out about a line of code that checks if a header is supported. A few clicks further and there was the list of not allowed headers.
And this list sadly also contains the headername "Authorization". I also found out that the list of allowed headers has a length of 12 headers. But also new custom headers are supported. The lists below are read from doing some inspection with Reflector.
List of unsupported headers: Allow, Accept, Authorization, Accept-Charset, Accept-Encoding, Accept-Language, Cookie, Connection, Content-Type, Content-Range, Content-Length, Content-Location, Date, Expect, Host, Keep-Alive, Last-Modified, Max-Forwards, Proxy-Authorization, Range, Referer, TE, Trailer, Transfer-Encoding, Upgrade, User-Agent, Via, Warning, Allowed, Connect, Content-Transfer-Encoding, Delete, Get, Head, Options, Post, Proxy-Connection, Public, Put, Request-Range, Trace, Uri, X-Flash-Version, Accept-Ranges, Age, ETag, Location, Proxy-Authenticate, Retry-After, Server, Vary, WWW-Authenticate.
List of supported headers: Cache-Control, Content-Encoding, Content-Language, Content-MD5, Expires, From, If-Match, If-Range, If-None-Match, If-Modified-Since, If-Unmodified-Since, Pragma. Besides this also custom headers are supported.
I hope we get support for using credentials within requests as soon as possible. Almost all services on the web use some form of credentials don’t they?
|
July 16th, 2008 at 04:23
Silverlight Cream for July 15, 2008 — #325
Mark Monster on SL Networking (2), Andy Beaulieu on finding XAML elements, chrishayuk with SL2 Wee Mee
July 16th, 2008 at 04:51
Hi there,
I’ve also been looking for support of basic authentication in Silverlight, which seems to be missing from this current release. Hopefully, they’ll add it in RC. I suppose the only way to go about this right now is to write a service that SL communicates with. Btw, which part of the assemblies did you find the restriction on the headers?
Nice work on the code above
July 16th, 2008 at 05:28
System.Net.HeaderInfoTable
static HeaderInfoTable()
{
HeaderInfo[] infoArray = new HeaderInfo[] {
new HeaderInfo(”Allow”, true, true), new HeaderInfo(”Accept”, true, true), new HeaderInfo(”Authorization”, true, true), new HeaderInfo(”Accept-Charset”, true, true), new HeaderInfo(”Accept-Encoding”, true, true), new HeaderInfo(”Accept-Language”, true, true), new HeaderInfo(”Cookie”, true, true), new HeaderInfo(”Connection”, true, true), new HeaderInfo(”Content-MD5″, false, false), new HeaderInfo(”Content-Type”, true, false), new HeaderInfo(”Cache-Control”, false, true), new HeaderInfo(”Content-Range”, true, false), new HeaderInfo(”Content-Length”, true, false), new HeaderInfo(”Content-Encoding”, false, true), new HeaderInfo(”Content-Language”, false, true), new HeaderInfo(”Content-Location”, true, false),
new HeaderInfo(”Date”, true, false), new HeaderInfo(”Expect”, true, true), new HeaderInfo(”Expires”, false, false), new HeaderInfo(”From”, false, false), new HeaderInfo(”Host”, true, false), new HeaderInfo(”If-Match”, false, true), new HeaderInfo(”If-Range”, false, false), new HeaderInfo(”If-None-Match”, false, true), new HeaderInfo(”If-Modified-Since”, false, false), new HeaderInfo(”If-Unmodified-Since”, false, false), new HeaderInfo(”Keep-Alive”, true, false), new HeaderInfo(”Last-Modified”, true, false), new HeaderInfo(”Max-Forwards”, true, false), new HeaderInfo(”Pragma”, false, true), new HeaderInfo(”Proxy-Authorization”, true, true), new HeaderInfo(”Range”, true, true),
new HeaderInfo(”Referer”, true, false), new HeaderInfo(”TE”, true, true), new HeaderInfo(”Trailer”, true, true), new HeaderInfo(”Transfer-Encoding”, true, true), new HeaderInfo(”Upgrade”, true, true), new HeaderInfo(”User-Agent”, true, false), new HeaderInfo(”Via”, true, true), new HeaderInfo(”Warning”, true, true), new HeaderInfo(”Allowed”, true, false), new HeaderInfo(”Connect”, true, false), new HeaderInfo(”Content-Transfer-Encoding”, true, false), new HeaderInfo(”Delete”, true, false), new HeaderInfo(”Get”, true, false), new HeaderInfo(”Head”, true, false), new HeaderInfo(”Options”, true, false), new HeaderInfo(”Post”, true, false),
new HeaderInfo(”Proxy-Connection”, true, false), new HeaderInfo(”Public”, true, false), new HeaderInfo(”Put”, true, false), new HeaderInfo(”Request-Range”, true, false), new HeaderInfo(”Trace”, true, false), new HeaderInfo(”Uri”, true, false), new HeaderInfo(”X-Flash-Version”, true, false), new HeaderInfo(”Accept-Ranges”, true, false), new HeaderInfo(”Age”, true, false), new HeaderInfo(”ETag”, true, false), new HeaderInfo(”Location”, true, false), new HeaderInfo(”Proxy-Authenticate”, true, false), new HeaderInfo(”Retry-After”, true, false), new HeaderInfo(”Server”, true, false), new HeaderInfo(”Vary”, true, false), new HeaderInfo(”WWW-Authenticate”, true, false)
};
HeaderHashTable = new Dictionary(infoArray.Length * 2, CaseInsensitiveAscii.StaticInstance);
for (int i = 0; i
July 18th, 2008 at 21:48
[...] few days ago I blogged about the trouble of getting Credentials to work in Silverlight Networking. The troubles still exists sadly. I’ve been thinking about creating a simple [...]
July 23rd, 2008 at 20:03
[...] Silverlight Networking - Getting credentials to work, unsuccessful. [...]
July 28th, 2008 at 17:31
[...] Silverlight Networking - Getting credentials to work, unsuccessful. [...]
July 29th, 2008 at 12:00
[...] Silverlight Networking - Getting credentials to work, unsuccessful. [...]
July 11th, 2009 at 20:31
[...] the past I also tried to add the Authorization header manually. I won’t go into the details but, the implementation of the Credentials property would mean that [...]