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

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 ApplicationUserManageris inherited from the UserManager base class. This is a generic class with the type ApplicationUserparameter. 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<ApplicationUser>(context.Get <ApplicationDbContext>()));
// Configure validation logic for usernames
manager.UserValidator = new UserValidator<ApplicationUser>(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<ApplicationUser>
{
  MessageFormat = "Your security code is: {0}"
});
manager.RegisterTwoFactorProvider("EmailCode", new EmailTokenProvider<ApplicationUser>
{
      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 TopSecurityStampBasedTokenProviderThis 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:
<system.net>
<mailSettings>
<smtp deliveryMethod="SpecifiedPickupDirectory">
<specifiedPickupDirectory pickupDirectoryLocation="C:\mailDrop"/>
</smtp>
</mailSettings>
</system.net>
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:
<add name="DefaultConnection"
connectionString="Data Source=(LocalDb)\v11.0;
Initial Catalog=MVC_Identity-1-14;Integrated Security=SSPI" 
providerName="System.Data.SqlClient" /></connectionStrings>
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<ActionResult> 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: <a href=\"" + callbackUrl + "\">link</a>");
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 theDefaultAccountLockoutTimeSpan 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<SignInStatus> 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

Comments

  1. I like your blog, I read this blog please update more content on hacking,
    Nice post,and good information Thanks for sharing
    further check it once at .NET Online Course

    ReplyDelete
  2. Pretty article! I found some useful information in your blog, it was awesome to read, thanks for sharing this great content to my vision, keep sharing.



    Dot Net Training in Chennai | Dot Net Training in anna nagar | Dot Net Training in omr | Dot Net Training in porur | Dot Net Training in tambaram | Dot Net Training in velachery




    ReplyDelete

Post a Comment