Forms authentication is a common feature in many C# MVC .NET web applications. There are a variety of methods for implementing forms authentication in MVC .NET. A key part for each, is the process of storing user specific details that are carried throughout the web application. User details such as Id, Username, Address, and Age may be obtained through various methods, such as by querying the database upon every request or as needed, loading from cache, context, or even loading from Session.
In this tutorial, we’ll walk through the steps of implementing forms authentication in C# MVC .NET, specifically with MVC4. We’ll use a custom MembershipProvider class, along with a custom Principal object. The Principal will hold our custom user details, encrypted within the forms authentication ticket cookie, and allow us to access this data anywhere within the web application.
The first step for implementing MVC4 .NET forms authentication is to configure the web.config with the associated tags. We’ll need a configuration for the authentication type and another for the membership provider, as shown below.
In the above configuration, we’re setting the forms authentication tag and providing the membership provider details. We’ve included the name of our custom MembershipProvider, as well as the type property, which combines the assembly and class name. The membership provider class is an important part of forms authentication, as it allows us to easily authenticate a user that is logging in. It also assists us in configuring the HttpContext.User.Identity property.
Before beginning the code setup for C# MVC .NET forms authentication, we’ll need some basic types to handle maintaining the user details after logging in.
public class User
The User class will hold details read from the database. We’ll store a copy of the User class within the forms authentication ticket, so it’s important to omit sensitive information from this class. Any sensitive or frequently-changing data should be read on-demand, when an action is initiated.
The MyPrincipal class is a custom Principal object that will be used with the HttpContext.User.Identity to allow us to load the forms authentication custom user data. We’ll be serializing the User class as a JSON string and storing it in the forms authentication ticket.
We can create our initial controller method for the Login call with a basic MVC4 .NET controller method, as shown below:
In the above controller method, we authenticate the user with our custom membership provider and create the forms authentication ticket. The above method is using an ajax form submission, and therefore, returns a JsonResult string, rather than an actual MVC .NET view.
The login controller calls our ValidateUser helper method, which in turn, calls the custom membership provider to authenticate the user. The .NET membership provider framework will call our custom MyMembershipProvider class and execute our AuthenticateUser() method.
If the membership provider call succeeds, we can create the forms authentication cookie. The membership provider will store the resulting User object within HttpContext.Current.Items. This collection is valid only for the current request, which is just enough time for us to grab it and save it in the cookie. It’s important to note that Session is not yet available in this call.
We’ll first serialize the returned User object as a JSON string. We’ll then create the forms authentication ticket and provide the JSON string as our custom user data. The entire ticket will be encrypted and stored as the C# MVC4 .NET forms authentication cookie, which we can later retrieve and decrypt to access its contents.
public static bool ValidateUser(Logon logon, HttpResponseBase response)
As part of the login process, our Controller method has called ValidateUser(), which in turn, calls the custom membership provider’s ValidateUser() method. We can define the custom membership provider by inheriting from the MembershipProvider base class. Since we’ll only need two of the methods, defined by the base class, we can implement our custom MembershipProvider in C# MVC4 .NET as follows:
public class MyMembershipProvider : MembershipProvider
In the above code, we’ve provided the methods for ValidateUser() and GetUser(). Our ValidateUser method first calls our own user authentication method to check the user’s username and password. If the check succeeds, we are returned a User object. We’ll need to store this User object in the forms authentication ticket. However, since Session will not be available in the Application_AuthenticateRequest() method, we’ll need a way to temporarily store the User object for the current request. We can take advantage of HttpContext.Current.Items for this, as this object holds values for the duration of the request. This will give us enough time to read the User and store it in the forms authentication ticket custom data.
The helper method for actually authenticating the user (ie., calling the database or web service), is shown below:
public static User AuthenticateUser(string username, string password)
The AuthenticateUser method would typically call the database or web server to verify the user details. In this example, we simply check against a hard-coded account and return a sample User. The series of calls is finally returned back to the ValidateUser() helper method, where we can continue by encrypting the forms authentication ticket and saving the cookie. The user is now successfully logged in.
Once the user is logged in, we’ll often need to retrieve his data. For example, we’ll probably need to show his name, address, and other information. Some of this data will probably be regularly used throughout the C# MVC4 web application. Since we’ve stored this data in the forms authentication ticket, we’ve greatly enhanced our web application by not having to query the database or web service to retrieve these details. Instead, we can query the HttpContext.Current.Items of the current request, which contains our decrypted User object from the forms authentication ticket.
To begin, we need to implement the Application_AuthenticateRequest() in the Global.asax.cs file. This method is called on each request in the web application, so you’ll want to keep it lightweight, in nature. While this example includes the below code for every request, you could also create a custom MVC4 filter to obtain the data only on specific web application actions. Our AuthenticateRequest call appears as follows:
protected void Application_AuthenticateRequest(object sender, EventArgs e)
In the above code, we first check if a forms authentication ticket cookie exists for the currently connected user. If the cookie exists, we read it and attempt to decrypt it. With the decrypted cookie, we create the custom Principal object and provide it with the decrypted user details from the cookie. This will allow us to access the user details from the standard HttpContext.Current.User property in the .NET MVC web application.
Since our AuthenticateRequest method has created the User.Identity and included our custom User data within it, we simply need to cast the Context.User object to our custom User type. We’ll then be able to easily access the user details from anywhere within our MVC .NET web application. We can create a helper method for making this more convenient, as shown below:
public static User User
We’ll use the above helper method for logging the user in (as shown above in the ValidateUser helper method), as well as accessing the user’s details after he’s already logged in.
The above User helper method first checks if the user is already authenticated. If he is, we simply cast the HttpContext.Current.User object to our custom principal object, MyPrincipal, and then return the User property. Remember, this object was created in the AuthenticateRequest() method, as part of the MVC ASP .NET framework.
If the user is not yet logged in, we’ll check the HttpContext.Current.Items for the User object. This is stored as part of the custom membership provider (since we don’t have access to Session at the time of logging in, we use the HttpContext to store the data temporarily for the current request).
Finally, our framework is complete. The user has been authenticated, logged in, and is now available in our application by accessing the HttpContext.Current.User or our helper User class. We can access the user in the MVC Razor view, as shown below:
The above MVC Razor view checks if the user is authenticated. If he is, we access the User helper object (obtained via the forms authentication cookie and associated encrypted data). If the user is not yet logged in, we show the login form.
When the user is ready to log out, we’ll simply need to abandon the session, sign out of the forms authentication, and clear any remaining forms authentication cookie by allowing it to expire. We can do this with a helper method, as shown below:
public static void Logoff(HttpSessionStateBase session, HttpResponseBase response)
The above method may be called from your Logoff controller method.
You can download the project source code on GitHub by visiting the MVC4 Forms Authentication example project.