ASP.NET http authentication header rewrites

I were recently a victim of asp.net's browser detection and on the fly content change.

The story is:

I work for a company called ZYB, and for a new feature we are developing we have created some HttpModules, which basically provides means of authenticating our users against their usual ZYB account using either Bacic Authentication or Digest Authentication.

This is all fine, and since both Basic Authentication and Digest Authentication are pretty straightforward to implement we were done in a few days.

We tested the modules, simply by invoking the urls that were protected by the web.config sections:

<authorization>
<deny users="?" />
</authorization>
<authentication mode="None" />

Please note that when developing your own authentication modules, you have to allow Anonymous users in IIS, and remove all other authentication options, and in the web.config, you have to set the

<authentication mode="None" />

Otherwise your modules wont kick in.

But back on track, this is not the reason why I am writing this blog post, its simply because we suddenly discovered that for some user agents, asp.net was modifying the HTTP 401 Unauthorized status code to 200 OK, but still sent the WWW-Authenticate header anyway.

This does seem like a bug, and I traveled many paths before finding out that it was the user-agent header that triggered the Status rewrite.

I am pretty sure asp.net should never rewrite the status codes, at least not for authentication, since it pretty much screws up authentication.

Since changing the User-Agent was not an option, I tried to change the Request headers, but microsoft have made that impossible with a recent fix to .NET.

So I was getting desperate, and I tried to use some of the .browser files you can place in the App_Browsers directory, but I could not find any options for "Do not fuck up my status http headers", so no luck there.

In a desperate measure, I looked at the clientTarget xml elements you can put into the web.config, but no luck there as well, so my last try before rewriting the entire feature, to use in place authentication within the http body, was the

browserCaps section in system.web in the web.config.

I found that if I added the following section:

    <browserCaps>
      <result type="System.Web.HttpBrowserCapabilities"/>
      <use var="HTTP_USER_AGENT"/>
    </browserCaps>

asp.net stopped fucking up my headers, and returned the proper 401 status code.

The user agent that fucked everything up, was more or less any mobile device out there, and ZYB being a mobile company, its damn hard to just ignore that.

So this blog post is hopefully a help for people stuck in the same situation.

 

Extension methods

As promised way back in 2007 I will try to show some of the coolness of extension methods.

Extension methods are simply said, methods that can extend existing classes whether or not you have access to the original code.

You cannot access private member variables etc, but from all other views and use it will look as it was a method that was created originally in the class it self.

To use an extension method, you have to import the namespace that contains the class with the method, and have a variable of the type the method works on.

Lets say you always wanted a Reverse() method on a string because you always use that nice feature in some obscure project you are the maintainer of.

No sweat.

The principles of extension methods are simple. Just create a static class, put a static method in that class, with a special signature, and voilá you can access that method in your other class as it was natively written for that.

Let me give you an example with the Reverse() method on string.

    /// <summary>
    /// Class with useful extensions to System.String
    /// </summary>
    public static class StringExtensions
    {
        /// <summary>
        /// Reverses the specified string
        /// </summary>
        /// <param name="s">The s.</param>
        /// <returns></returns>
        public static string Reverse(this string s)
        {
            StringBuilder sb = new StringBuilder(s.Length);
            char[] chars = s.ToCharArray();
            for (int x = chars.Length - 1; x > -1; x--)
            {
                sb.Append(chars[x]);
            }
            return sb.ToString();
        }
    }
Please note the use of this in the method signature, the this signifies that its should be interpreted as an extension method, and then you just use the parameter as it was a normal method.

To use the method above, just create a string variable and call Reverse() on it. Just as easy as:

string s = "OMG";
Console.WriteLine(s.Reverse());
And its really as simple as that.

Another example could be System.DateTime which sometimes can be a bitch to get to know the different string formats for outputting. Why not just create an extension method with your favorite format:

 /// <summary>
 /// Class with useful extensions to System.DateTime
 /// </summary>
 public static class DateTimeExtensions
 {
     /// <summary>
     /// Returns an ISO8601 string representation of the date time object
     /// as used in e.g. VEVENT
     /// </summary>
     /// <param name="dt">The dt.</param>
     /// <returns></returns>
     public static string ToISO8601String(this DateTime dt)
     {
         if (dt.Kind == DateTimeKind.Utc)
         {
             return dt.ToString("yyyyMMddThhmmssZ");
         }
         else
         {
             return dt.ToString("yyyyMMddThhmmss");
         }
     }
Which in turn is used as easily as:

DateTime dt = DateTime.Now;
Console.WriteLine(dt.ToISO8601String());
See how easy it is :-)

Extension methods can naturally have parameters just like normal methods, and its as simple as creating normal parameters, the only rule is to have the class that the method should be an extension to as the first parameter, i.e. public static bool MatchModulus(this int x, int modulus).

A more elaborate example could be another string extention method called Slice:

        /// <summary>
        /// Slices the specified string into the specified number of parts
        /// </summary>
        /// <param name="s">The string to slice into parts</param>
        /// <param name="parts">The number of parts</param>
        /// <returns></returns>
        public static string[] Slice(this string s, int parts)
        {
            if (string.IsNullOrEmpty(s))
            {
                throw new ArgumentException("String to be sliced cannot be null or empty");
            }
            if (parts < 1)
            {
                throw new ArgumentException("Number of parts to slice into must be greater than 0");
            }
            string[] slices = new string[parts];
            int charsInSlice = (int)s.Length / parts;
            int charsRemoved = 0;
            for (int x = 0; x < parts; x++)
            {
                slices[x] = s.Substring(charsRemoved, charsInSlice);
                charsRemoved += charsInSlice;
            }
            if (charsRemoved != s.Length)
            {
                slices[parts - 1] += s.Substring(charsRemoved);
            }
            return slices;
        }
Which in this example slices the string into the specified number of parts. The example is not a perfect method, because if you specify more parts than characters in the string it will return a string array with only the last element of the string array containing the entire string. Feel free to rewrite the method, its very simple to change :-p.

I hope this gave a little insight into extension methods and that they can in fact be useful.