Developing Secure ASP.NET MVC Applications using ASP.NET Identity 2.0

Posted by: Mahesh Sabnis , on 5/28/2014, in Category ASP.NET MVC
Views: 104744
Abstract: The new ASP.NET Identity 2.0 membership system integrates some robust security features in your ASP.NET applications. This article explores some of these features.

Coping up with a variety of business needs and technical and security requirements of different domains like banking, insurance etc. can be a daunting task. In addition to this, we have social networking applications that have millions of users, and it is widely known that any service accessible to the public on the Internet is constantly probed for vulnerabilities. Therefore, it is recommended to build robust security into all of your Web applications and services.

Building a secure Web application is always a challenging task. Although Microsoft back in the old days in ASP.NET 2.0 introduced a powerful provider-based architecture and a membership provider which could be customized; developers have been craving for something 'simpler'. In addition to this, modern websites have become more social and now use social identities for authentication and authorization. Clearly a fresh look into the membership system was needed to cope up with the changes and growing demand.

This article is published from the DotNetCurry .NET Magazine – A Free High Quality Digital Magazine for .NET professionals published once every two months. Subscribe to this eMagazine for Free and get access to hundreds of free tutorials from experts

Note: It’s worth noting that the Simple membership API introduced with WebPages and WebMatrix has become a popular way of managing authentication but it’s not very extensible, not compatible with OWIN and it is challenging to store membership system data using NoSQL databases.

ASP.NET Identity is the new membership system for building ASP.NET web applications, phone, store, or hybrid applications.

ASP.NET Identity

ASP.NET Identity can be used with all ASP.NET frameworks, such as ASP.NET Web Forms , MVC, Web Pages, Web API, and SignalR.

ASP.NET Identity has been developed with some major security features like Two-Factor Authentication, Account Lockout, and Account Confirmation etc. In addition, you can use it to support multiple storage mechanisms like Relational Databases, SharePoint, Azure, NoSQL etc. It is Unit Testable, supports Social Login providers like FaceBook, Twitter, Google etc. and even supports Claim-based authentication. It is fully compliant with OWIN and can be downloaded from the NuGet Package Manager.

Here are the packages we need to download for ASP.NET Identity 2.0.0:

Microsoft.AspNet.Identity.EntityFramework Version 2.0.0 - Contains EF implementations for identity types. These types are used to manage information for identity users, roles, claim login etc.

Microsoft.AspNet.Identity.Core Version 2.0.0 - Contains classes and interfaces for managing users and roles in ASP.NET Identity. It contains classes for User validation, User login information etc.

Microsoft.AspNet.Identity.OWIN -Version 2.0.0 - Contains classes used to manage identities associated with OWIN.

To implement ASP.NET Identity in an empty Web Application, the following samples can be installed using the NuGet Package:

Microsoft.AspNet.Identity.Samples -Version 2.0.0-beta2 –Pre

This will add the necessary classes for ASP.NET Identity 2.0.0 in your application and thus ease the development effort. It also provides freedom of changing the code wherever required by your application.

Implementing ASP.NET Identity

Step 1: Open Visual Studio 2013 and create a new MVC application targeting .NET 4.5. Name it as MVC_Identity. Once the project is created, you will find the references for the ASP.NET Identity 2.0.0 (assuming you installed the NuGet package shown in Step 2)

references

Step 2: To get the basic infrastructure code ready for Identity 2.0.0, we need to install ASP.NET Identity sample. Run the following command:

samples-nuget

This is an important step for getting the Identity infrastructure ready.

Step 3: After installing the sample, the project will have some additional Controller classes. Based on the Controller classes, new Views will be generated in the Views folder.

Step 4: Open the IdentityConfig.cs class file in the App_Start folder. This class file contains the following classes:

  • ApplicationUserManager
  • ApplicationRoleManager
  • EmailService
  • SmsService
  • ApplicationDbInitializer
  • SignInHelper

The SignInStatus enumeration provides the values for SignIn for the user.

So now the question is what are these classes responsible for? Let’s explore them one by one along with the new security features provided in ASP.NET Identity.

Two-Factor Authentication

Two-Factor Authentication provides an extra security layer for an application’s (web site) user account. This is a protection used in case the password of the user gets compromised. This feature uses the mechanism of sending the security code using SMS on the users phone or alternatively a verification email, if the user is not having access to his/her phone. The class ApplicationUserManager is inherited from the UserManager base class. This is a generic class with the type ApplicationUser parameter. The ApplicationUser class is responsible to work with the users’ identity. The class ApplicationUserManager defines a Create method. This method contains logic for validating user name and password as shown here:

var manager = new ApplicationUserManager(new UserStore(context.Get ()));
// Configure validation logic for usernames
manager.UserValidator = new UserValidator(manager)
{
AllowOnlyAlphanumericUserNames = false,
RequireUniqueEmail = true
            };
// Configure validation logic for passwords
manager.PasswordValidator = new PasswordValidator
            {
RequiredLength = 6,
RequireNonLetterOrDigit = true,
RequireDigit = true,
RequireLowercase = true,
RequireUppercase = true,
};

Account Lockout

Account Lockout is another important feature provided by the ASP.NET Identity 2.0.0. This locks out the user’s account if the user enters a wrong password for a specific number of times. This can be specified by configuring maximum failed attempts and lockout time span as shown here:

manager.UserLockoutEnabledByDefault = true;
manager.DefaultAccountLockoutTimeSpan = TimeSpan.FromMinutes(5);
manager.MaxFailedAccessAttemptsBeforeLockout = 5;

Once the validators and the lockout are set for the account, now the Two-Factor authentication can be set using the code provided here:

manager.RegisterTwoFactorProvider("PhoneCode", new PhoneNumberTokenProvider
{
  MessageFormat = "Your security code is: {0}"
});
manager.RegisterTwoFactorProvider("EmailCode", new EmailTokenProvider
{
      Subject = "SecurityCode",
      BodyFormat = "Your security code is {0}"
});
manager.EmailService = new EmailService();
manager.SmsService = new SmsService();

In the above code, PhoneNumberTokenProvider and EmailTokenProvider classes are used. These classes are inherited from TopSecurityStampBasedTokenProvider. This class is responsible for generating time-based codes using the users security stamp, and sending it to users using the Phone number and Email address with the help of PhoneNumberTokenProvider and EmailTokenProvider respectively. Naturally to send Email or SMS, consent is needed. So to implement the consent service, the following classes are used:

public class EmailService : IIdentityMessageService {
public Task SendAsync(IdentityMessage message)
{
  // Plug in your email service here to send an email.
  returnTask.FromResult(0);
}
}

public class SmsService : IIdentityMessageService
{
public Task SendAsync(IdentityMessage message)
{
// Plug in your sms service here to send a text message.
return Task.FromResult(0);
}
}

This is just a sample. You can change the code here as per your apps requirement.

Using Email Service for Authentication

Step 5: Add the following code in the SendAsync method of the EmailService class.

public Task SendAsync(IdentityMessage message)
{
var mailMessage = new System.Net.Mail.MailMessage("TestAdmin.Admin@MyApplication.com ",
message.Destination,
message.Subject,
message.Body
);

//Send the Message
SmtpClient client = new SmtpClient();
client.SendAsync(mailMessage, null);


return Task.FromResult(true);
}

Here the MailMessage class is used which accepts the following parameters:

  • Senders Email Address
  • Recipients Email address
  • Subject
  • Body

Using the SmtpClient class, a message can be sent. Note that you can use your email server settings here.

Step 6: In the development environment, an email drop folder needs to be configured in the web.config file as shown here:








The above configuration specifies the SMTP for the Email message pickup.

Step 7: The web.config file also adds a new connection string to store the user’s information in SQL Server:

connectionString="Data Source=(LocalDb)\v11.0;
Initial Catalog=MVC_Identity-1-14;Integrated Security=SSPI"
providerName="System.Data.SqlClient" />

Step 8: Open the AccountController.cs and locate the Register method with HttpPost. This contains the required code to send an email for account confirmation:

public async Task Register(RegisterViewModel model)
{
if (ModelState.IsValid)
{
var user = new ApplicationUser { UserName = model.Email, Email = model.Email };

var result = awaitUserManager.CreateAsync(user, model.Password);
if (result.Succeeded)
                {
var code = await UserManager.GenerateEmailConfirmationTokenAsync(user.Id);
var callbackUrl = Url.Action("ConfirmEmail", "Account", new { userId = user.Id, code = code }, protocol: Request.Url.Scheme);
await UserManager.SendEmailAsync(user.Id, "Confirm your account", "Please confirm your account by clicking this link: link");
ViewBag.Link = callbackUrl;
return View("DisplayEmail");
}
AddErrors(result);
}

// If we got this far, something failed, redisplay form
return View(model);
}

Step 9: Run the application and click the Register link on the page, the view rendered will be as shown here

register-view

Step 10: Enter your email and other details and click on the register button. You will see a similar view:

confirmation-mail

Step 11: Navigate to the email drop folder configured in the config file. You will find the mail which can then be opened in Outlook or similar:

email

Step 12: Click on the link in the mail

confirmation

Step 13: Now you can login as shown here:

login

Similarly email service can also be used by subscribing to the email provider.

Implementing Account Lockout

Account Lockout as we briefly touched upon in the introduction section is one of the most important aspects of implementing security which is required in most commercial and finance sites.

Step 1: In the Create method of the ApplicationUserManager class, change the DefaultAccountLockoutTimeSpan and MaxFiledAccessAttemptBeforeLockout properties as mentioned here:

manager.UserLockoutEnabledByDefault = true;
manager.DefaultAccountLockoutTimeSpan = TimeSpan.FromMinutes(1);
manager.MaxFailedAccessAttemptsBeforeLockout = 2;

Step 2: To implement the account lockout feature, we need to add the following code in the beginning of the PasswordSignIn method after application user is found by its name: (yellow marked code)

public async Task PasswordSignIn(stringuserName, string password, bool isPersistent, bool shouldLockout)
        {
var user = await UserManager.FindByNameAsync(userName);

await UserManager.IsLockedOutAsync(user.Id);
await UserManager.AccessFailedAsync(user.Id);
await UserManager.SetLockoutEnabledAsync(user.Id, true);

if (user == null)
{
returnSignInStatus.Failure;
}

if (await UserManager.IsLockedOutAsync(user.Id))
{
return SignInStatus.LockedOut;
}

if (awaitUserManager.CheckPasswordAsync(user, password))
{
return await SignInOrTwoFactor(user, isPersistent);
}

if (shouldLockout)
{
// If lockout is requested, increment access failed count which might lock out the user
await UserManager.AccessFailedAsync(user.Id);
if (await UserManager.IsLockedOutAsync(user.Id))
{
   return SignInStatus.LockedOut;
}
}
return SignInStatus.Failure;
}

Here are some important points to note:

await UserManager.IsLockedOutAsync(user.Id) - Returns true if the user is lockout.

await UserManager.AccessFailedAsync(user.Id) - Increments the accessfail count for the user. If the failed access count is greater than or equal to MaxFailedAccessAttemptsBeforeLockout, then the user will be locked for the time span of the lockouttimespan.

await UserManager.SetLockoutEnabledAsync(user.Id, true) – Sets if the lockout is enabled for the user.

Step 3: Run the application and create a user as explained above in the Two-Factor authentication section.

Step 4: Try to login with a wrong password. After two failed attempts, you will get the following message:

lockout

Now wait for the completion of DefaultAccountLockoutTimeSpan and try logging in again with correct password; you will be able to login successfully.

This is an awesome facility provided by the ASP.NET Identity 2.0.0 to protect the user credential information from unauthorized access.

Password Reset

A Password Reset feature is also available in case the user forgets it. As we have seen in the register new user section, the verification mail is send to the users registered email address with a link for resetting the password.

In the project, we have existing methods in the AccountController class which contains logic for ForgetPassword and ResetPassword. This functionality is provided with the sample NuGet with ASP.NET Identity 2.0.0 package that we installed at the beginning of this article.

Step 1: Run the application and from the Login View, click on the ‘Forget your password’ link. You will navigate to the ForgotPassword view as shown here:

forgot-password

Step 2: Enter the account email and click on the Email Link button. The following View will be displayed:

reset-forgot

Here the email will appear in the drop folder which we configured a short while ago in the web.config file with the attribute pickupDirectoryLocation. On clicking the link in the email, the following view will be displayed:

reset-password-confirmation

and a new password can now be used to login.

Conclusion

As you might have observed, these new features provided in ASP.NET Identity 2.0.0 provides an enhanced mechanism to manage security of precious credential information in our data stores. A developer instead of customizing a provider from scratch can now instead rely on the extensible API set provided with the new identity features for security.

I hope this article will help you integrate some robust security features in your new applications as well as help migrate your existing apps that use ASP.NET Membership to the new ASP.NET Identity system.

Download the entire source code from our GitHub Repository at bit.ly/dncm12-aspidentity

This article has been editorially reviewed by Suprotim Agarwal.

Absolutely Awesome Book on C# and .NET

C# and .NET have been around for a very long time, but their constant growth means there’s always more to learn.

We at DotNetCurry are very excited to announce the The Absolutely Awesome Book on C# and .NET. This is a 500 pages concise technical eBook available in PDF, ePub (iPad), and Mobi (Kindle).

Organized around concepts, this eBook aims to provide a concise, yet solid foundation in C# and .NET, covering C# 6.0, C# 7.0 and .NET Core, with chapters on .NET Standard and the upcoming C# 8.0 too. Use these concepts to deepen your existing knowledge of C# and .NET, to have a solid grasp of the latest in C# and .NET OR to crack your next .NET Interview.

Click here to Explore the Table of Contents or Download Sample Chapters!

What Others Are Reading!
Was this article worth reading? Share it with fellow developers too. Thanks!
Share on LinkedIn
Share on Google+

Author
Mahesh Sabnis is a DotNetCurry author and Microsoft MVP having over 17 years of experience in IT education and development. He is a Microsoft Certified Trainer (MCT) since 2005 and has conducted various Corporate Training programs for .NET Technologies (all versions). Follow him on twitter @maheshdotnet


Page copy protected against web site content infringement 	by Copyscape




Feedback - Leave us some adulation, criticism and everything in between!
Comment posted by Hemant on Wednesday, May 28, 2014 4:35 PM
So can we assume this will work for MVC 4 and MVC 5?
Comment posted by Suprotim Agarwal on Wednesday, May 28, 2014 11:06 PM
@Hemant: The first thing to remember is to use Identity you need .NET 4.5. Secondly never tried it but I think if you can include the Identity.Core, Identity.Owin and Identity.EF libraries it should work.
Comment posted by WINDSON on Thursday, May 29, 2014 3:42 AM
I'm implementing a web application using ASP.NET, NHibernate as ORM and WEB API. Do I still need to use EntityFramework dll for Identity? Is there any other ready made framework exists to implement Identity using NHibernate
Comment posted by WINDSON on Thursday, May 29, 2014 5:09 AM
I'm implementing a web application using ASP.NET, NHibernate as ORM and WEB API. Do I still need to use EntityFramework dll for Identity? Is there any other ready made framework exists to implement Identity using NHibernate
Comment posted by Mike Jones on Tuesday, June 17, 2014 7:23 AM
Nothing like creating a project with missing assemblies. Total waste of my time.
Comment posted by Ramu on Monday, June 23, 2014 7:15 AM
Hello Sir my Name is Ramu Now Only am Learning In DOT NET.So I Want to know how to implement password recovery Email as well as mobile verification code also.i need full code to learn asp code and c# code and web & window application ramube.19@gmail.com this is my mail id send that sample project for me. Thank you sir..........

Categories

JOIN OUR COMMUNITY

POPULAR ARTICLES

C# .NET BOOK

C# Book for Building Concepts and Interviews

Tags

JQUERY COOKBOOK

jQuery CookBook