Understanding, Using and Customizing ASP.NET Identity System for Authentication and Authorization

downloadIn this article we will look into ASP.NET Identity System which comes as the default authentication and authorization mechanism with ASP.NET MVC 5 internet application template. We will try to understand the ASP.NET Identity system and compare it with the ASP.NET simple membership providor and the classic ASP.NET roles and membership provider API.

Background

Let us start the discussion by looking at what authentication and authorization is. Authentication means validating users. In this step, we verify user credentials to check whether the person tying to log in is the right one or not. Authorization on the other hand is keeping track of what the current user is allowed to see and what should be hidden from him. It is more like keeping a register to what to show and what not to show to the user.

Whenever a user logs in, he will have to authenticate himself with his credentials. Once he is authenticated, he will be authorized to see resources/pages of the website. Mostly these two concepts go together.

ASP.NET supports two basic types of authentication:

  1. Windows authentication: Based on Windows accounts and access control lists (not very practical for web scenario)
  2. Forms authentication: In this mode the application will use its own username and password to authenticate the user. Once a user is authentication, an authentication cookie will be created. On subsequent requests, this cookie is checked. If it is a valid, the request is served. otherwise, the user is redirected to a login page.

To ease the process of forms authentication ASP.NET provides ASP.NET membership APIs. With the release of ASP.NET 2.0, came the Roles and membership APIs in ASP.NET framework which provided all the required boilerplate code and database schema that is needed to address the issue of authentication and authorization. Implementing authentication and authorization was just a matter of pluging in the ASP.NET membership API and the membership provider gave us the authentication and authorization functionality out of the box. To know more on this please refer: Understanding ASP.NET Roles and Membership – A Beginner’s Tutorial[^]

In ASP.NET membership provider API The information in the user and role table was predefined and it cannot be customized. User profile information is also stored in the same database. It was not very easy and straight forward to take full control of the database using ASP.NET membership provider. and this some applications still found themselves a need to implement their mechanism of authentication and authorization using their own database for tracking users and their roles. Some reasons for having such a requirements could be:

  • We have an existing database and we are trying to implement an application using that.
  • The Roles and Membership functionality is overkill for our application.
  • The Roles and Membership functionality is not sufficient for our applications and we need custom data.

It was possible to using the custom authentication and authorization mechanism with ASP.NET. This technique was known as custom forms authentication mechanism. To know more on custom forms authentication, please refer:

With ASP.NET MVC 4, the simple membership provider API has been provided by Microsoft. Compared to the ASP.NET membership provider, the major benefit of the simple membership API is more simple, mature and relatively straight forward to take full control of. Another major benefit of the simple membership provider is that is persistence ignorant. Meaning it provides us a set of models to work with to achieve the authentication and authorization and uses the code first approach. It is up to the application developers to decide where and how these models should get persisted. (supported by Entity framework code first).

The simple membership provider gave a simpler database and an easy way to create custom schema for the user and roles but it had few problems. The first problem was that it was not possible to store the membership data in a non relational database. sure it was persistent ignorant but as long as the database we are choosing is a relational database. The second problem was that it doesn’t work with classic ASP.NET membership provider. So if I have an enterprise application using ASP.NET membership API and i want to implement a new module using simple membership provider, it get a little tricky to get the application to work. We might have to put in some workaroundish bridges to get this to work. Finally the simple membership provider does not work with OWIN forms authentication.

To solve all the above problems, ASP.NET identity system has been created. The main idea behind having the ASP.NET identity system is to get the best of both/all worlds. ASP.NET one identity system provides all the benefits of one simple membership provider and also overcomes its limitations.

Using the code

Let us try to create a simple ASP.NET MVC5 internet application and observe the simple membership provider in action. When we create the ASP.NET MVC 5 internet application template, the project structure will look like:

templateSnap

Understanding the default template

The template gives a following out of the box:

  • ApplicationUser: A model which contains all the profile information for the user. We can add custom profile data for the user by adding more properties to this ApplicationUser class(Models/IdentityModels.cs).
  • ApplicationDbContext: Context class which is responsible for performing the CRUD operations on the Identity tables(Models/IdentityModels.cs).
  • RegisterViewModel: A view model to help in new user registration(Models/AccountViewModels.cs).
  • LoginViewModel: A view model to help in user login(Models/AccountViewModels.cs).
  • ManageUserViewModel: A view model to help in user profile management. By default it supports password change functionality but it can be customized as per needs(Models/AccountViewModels.cs).

Understanding the details under the hood

The next thing to notice is the  AccountController. We will not be discussing the complete class here but this class contains all the CRUD operations on our user profile in such a way that it is wrapped in form of “Register”, “Login”, “Manage” functions. The important thing to notice is that this class uses UserManager<T> to perform all the user management activities. This class has been instantiated to use the  UserStore<ApplicationUser> which uses the  ApplicationUser class as the user profile class and  ApplicationDbContext to perform the CRUD operations.

Now this use of  UserStore can be visualized as using a façade to access a complex set of classes that deals with authentication and authorization. The most important thing to note in the controller is that the controller uses  UserManager class and the  UserStore is injected into the class. Which would mean that we can have custom classes(implementing  IUSerStore) for all the authentication and authorization logic and they they can be injected into the Controller easily. Another important thing to notice is that the  UserStore also uses the  ApplicationDbContext that was injected into it, that would mean that we can have other contexts injected into it too. Which makes make the Identity system fully extensible and unit testable.

Now when we run the application, we can perform all the operations like “Register”, “Login” and “Manage” using the One identity provider.

register

login

Manage

Adding custom fields in user model – the easy part

Having custom fields in the user model is fairly straightforward when we are using the ASP.NET identity system. Just add more fields to the  ApplicationUser model and they will be ready to use. We will not be discussing this in details here.

Customizing everything – from User model to storage location

Now just to understand the possibility of easy customization when it comes to storage of user data, let us try to write our own version of account controller. this controller will use our custom class for authenticating the user. This custom class will use an in memory collection to validate the user credentials.

Let us start by creating a custom user model that we will be using. lets call it  DummyUser.

Next thing we need is the Context class that will save this user information. Since our plan is to save the user details in memory, lets create a simple class that will hold a list of dummy users.

Note: We will only be implementing the register and login functionality and thus this class looks very contrived. Also, the purpose of this article is to demonstrate the possibility of customization. I am compromising on many best practices by creating statics just to keep the sample code simple.

Next we need to implement a  CustomUserStore which will use our  DummyModel and this  InMemoryUserContext.

Note: Since we are going to implement only register and login, I have left a few functions unimplemented.

Finally, lets create the  DummyAccountController which will use our custom user model and store class.

Now we can run the application, register a new user using our  DummyAccountController. the authentication and authorization mechanism of ASP.NET identity system will use our in memory user list.

Note: Please check the sample application to understand the code in details.

Point of interest

In this article we have looked at the ASP.NET identity system. We saw how the identity system is an improvement over simple membership provider. We looked at the details of the default template and customized the default template to use ASP.NET identity system as per our needs. This has been written from a beginner’s perspective. I hope this has been informative.

Download sample code for this article: ASPNETIdentityDemo