Earlier this year, I was working on an iPhone Application that interacted with a running ASP.NET MVC site and the need arose for the iPhone user to authenticate so that they could access some of the Actions within a Controller decorated with the lovely [Authorize] attribute.

This post will cover how to create a simple “cookie-aware” WebClient class that will authenticate and persist this authentication for the duration of the WebClient to allow access to secure areas of your MVC application without the need for re-authenticating for each request.

The Problem

You are using a very basic ASP.NET MVC application with integrated Forms Authentication and the need arises for you to authenticate and access multiple controller actions, which require authentication, using a single WebClient.

The Solution

Cookies can easily be persisted within a WebClient object to eliminate the need to continually authenticate each request.

In order to handle this issue, we will need to create a custom WebClient class that will persist our authentication token for the duration of our “visit” based on parameters that were passed in. This can be accomplished by creating a class that will inherit from the WebClient class and will have a specific container to house the authentication cookie:

In its current state – this fails to actually do anything except create an extra CookieContainer property that we can’t really do anything with as we will need to determine a way to actually populate the authentication cookie and store it within the WebClient from any of the Requests that are made through the client itself.

This can be handled by adding the following snippet of code within the CookieAwareWebClient class:

The above code will associate the current Request that is being made from the WebClient and add the appropriate cookie to handle any future requests made by the client.

Digging in the Cookie Jar

The following example details how to use the newly created Cookie-Aware WebClient within an MVC environment by allowing the current user (in this instance from an iOS Application built through Xamarin) to authenticate using the standard AccountController available in ASP.NET MVC and then call a method from a Controller that is decorated with the [Authorize] attribute.

Let’s take a look at exactly what we want to access through our iOS call:

As you can see, there isn’t really anything special about the Controller or the Action besides the [Authorize] decoration at the Controller level, which is great because we don’t really want to have to do anything special to handle this functionality.

Now – within your iOS application, we are going to make two calls (the first to authenticate and the second to make the actual call itself) within an instance of the WebClient:

//Create an instance of your new CookieAware Web Client
using (var client = new CookieAwareWebClient())
{
//Authenticate (username and password can be either hard-coded or pulled from a settings area)
var values = new NameValueCollection{{ "UserName", username },{ "Password", password }};
//Perform authentication - after this has been performed the cookie will be stored within the Web Client
client.UploadValues(new Uri("http://www.yourdomain.com/Account/LogOn/"), "POST", values);
//Authentication worked! Access the secure area (you can use a variety of methods here such as UploadFile, UploadValues, etc.)
client.UploadString(new Uri("http://www.yourdomain.com/Secure/YourSecureMethod"), "POST", "Example Message");
}

And that’s really all you need as you could call a multitude of other Controller Actions within the context of your WebClient. It should be noted that your authentication values will only persist during the using statement and any further attempts to access your application outside of it will require additional authentication.

More Chocolate-Chips to Add to the Cookies

This is just one of the many examples of the Web Client being extended to assist with a very simple requirement that previous several redundant calls from being made within a simple Request. Another feature that I found to be incredibly helpful is implementing a Timeout mechanism for your WebClient.

Timing out can be essential when dealing with requests from iOS devices, as most users don’t want to sit there and wait indefinitely for a password that they accidentally left the CAPS LOCK key on to be rejected. For this reason, implementing a timeout can put a stop to a request after a specific amount of time and notify the user that they will need to retry their request.

All you will need to do to handle this will be to add an integer property to the WebClient class:

So after all that, now you would just need to set the property (if you need it) after declaring your WebClient:

using (var client = new CookieAwareWebClient())
{
//Times out after 5 minutes
client.SetTimeout (5 * 60 * 1000);
//I found that on iOS devices that the KeepAlive header can be helpful (but it is likely not completely necessary in most instances)
client.Headers [HttpRequestHeader.KeepAlive] = "true";
//Code
}

Too. Much. Cookie.

If this post made you hungry and you are too overwhelmed or are edging towards a cookie-coma, don’t fret. I won’t make you go through the extended trouble of copy-pasting the entire class above from all of those separate snippets. You can download the class from github below in case the need ever arises that you should require something even remotely like it or you would want to use it to further extend:

Share

About the Author

An experienced Software Developer and Graphic Designer with an extensive knowledge of object-oriented programming, software architecture, design methodologies and database design principles. Specializing in Microsoft Technologies and focused on leveraging a strong technical background and a creative skill-set to create meaningful and successful applications.

Well versed in all aspects of the software development life-cycle and passionate about embracing emerging development technologies and standards, building intuitive interfaces and providing clean, maintainable solutions for even the most complex of problems.