Part 2- How to implement custom Forms Authentication in ASP.NET MVC4 application



Introduction

In this post, I am going to implement custom Membership Provider in Forms authentication in ASP.NET MVC4 application.
In the previous part of this series, we have implemented very simple and easy forms authentication. Now we will see how we can implement our custom Membership Provider.
In ASP.NET default membership provider API The information in the user and role table was predefined and it cannot be customized. It is very complicated to take full control of the database using ASP.NET default membership provider. So, here we will see how to implement our custom membership provider to take full control of the database and forms authentication mechanism (like validate user, create user, update user, delete user, change password and more).
I have split the entire application split into following parts for making things more simple and understandable.

Step-1 : Add a class for extends MembershipProvider class.

Go to solution explorer > Right click on the project name > Add > Class > Enter class name > Add
Here we will extend MembershipProvider class.
for now I have just implemented only the ValidateUser method because this is the only method needed to validate the user credentials. we will see the other features of the membership provider later.
 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Security;

namespace MvcAuthentication
{
    public class MyMembershipProvider : MembershipProvider
    {
        public override string ApplicationName
        {
            get
            {
                throw new NotImplementedException();
            }
            set
            {
                throw new NotImplementedException();
            }
        }

        public override bool ChangePassword(string username, string oldPassword, string newPassword)
        {
            throw new NotImplementedException();
        }

        public override bool ChangePasswordQuestionAndAnswer(string username, string password, string newPasswordQuestion, string newPasswordAnswer)
        {
            throw new NotImplementedException();
        }

        public override MembershipUser CreateUser(string username, string password, string email, string passwordQuestion, string passwordAnswer, bool isApproved, object providerUserKey, out MembershipCreateStatus status)
        {
            throw new NotImplementedException();
        }

        public override bool DeleteUser(string username, bool deleteAllRelatedData)
        {
            throw new NotImplementedException();
        }

        public override bool EnablePasswordReset
        {
            get { throw new NotImplementedException(); }
        }

        public override bool EnablePasswordRetrieval
        {
            get { throw new NotImplementedException(); }
        }

        public override MembershipUserCollection FindUsersByEmail(string emailToMatch, int pageIndex, int pageSize, out int totalRecords)
        {
            throw new NotImplementedException();
        }

        public override MembershipUserCollection FindUsersByName(string usernameToMatch, int pageIndex, int pageSize, out int totalRecords)
        {
            throw new NotImplementedException();
        }

        public override MembershipUserCollection GetAllUsers(int pageIndex, int pageSize, out int totalRecords)
        {
            throw new NotImplementedException();
        }

        public override int GetNumberOfUsersOnline()
        {
            throw new NotImplementedException();
        }

        public override string GetPassword(string username, string answer)
        {
            throw new NotImplementedException();
        }

        public override MembershipUser GetUser(string username, bool userIsOnline)
        {
            throw new NotImplementedException();
        }

        public override MembershipUser GetUser(object providerUserKey, bool userIsOnline)
        {
            throw new NotImplementedException();
        }

        public override string GetUserNameByEmail(string email)
        {
            throw new NotImplementedException();
        }

        public override int MaxInvalidPasswordAttempts
        {
            get { throw new NotImplementedException(); }
        }

        public override int MinRequiredNonAlphanumericCharacters
        {
            get { throw new NotImplementedException(); }
        }

        public override int MinRequiredPasswordLength
        {
            get { throw new NotImplementedException(); }
        }

        public override int PasswordAttemptWindow
        {
            get { throw new NotImplementedException(); }
        }

        public override MembershipPasswordFormat PasswordFormat
        {
            get { throw new NotImplementedException(); }
        }

        public override string PasswordStrengthRegularExpression
        {
            get { throw new NotImplementedException(); }
        }

        public override bool RequiresQuestionAndAnswer
        {
            get { throw new NotImplementedException(); }
        }

        public override bool RequiresUniqueEmail
        {
            get { throw new NotImplementedException(); }
        }

        public override string ResetPassword(string username, string answer)
        {
            throw new NotImplementedException();
        }

        public override bool UnlockUser(string userName)
        {
            throw new NotImplementedException();
        }

        public override void UpdateUser(MembershipUser user)
        {
            throw new NotImplementedException();
        }


        // Here In this example we will use only ValidateUser method, we will see remaining later like create user, 
        //update user change password and more 

        public override bool ValidateUser(string username, string password)
        {
            //Will write code for validate user from our own database 
            using (MyDatabaseEntities dc = new MyDatabaseEntities())
            {
                var user = dc.Users.Where(a => a.Username.Equals(username) && a.Password.Equals(password)).FirstOrDefault();
                if (user != null)
                {
                    return true;
                }
            }
            return false;
        }
    }
}
        

Step-2: Update Login POST Action code of MyAccountController (created in the part 1) .

Here I have replaced the existing code for verify user (used in part 1) for use our own custom membership provider's ValidateUser method
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Login(Login l, string ReturnUrl = "")
{

    // Here we will replace our existing code (what I have used in the previous part) used for clear understanding
    #region Existing Code
    //using (MyDatabaseEntities dc = new MyDatabaseEntities())
    //{
    //    var user = dc.Users.Where(a => a.Username.Equals(l.Username) && a.Password.Equals(l.Password)).FirstOrDefault();
    //    if (user != null)
    //    {
    //        FormsAuthentication.SetAuthCookie(user.Username, l.RememberMe);
    //        if (Url.IsLocalUrl(ReturnUrl))
    //        {
    //            return Redirect(ReturnUrl);
    //        }
    //        else
    //        {
    //            return RedirectToAction("MyProfile", "Home");
    //        }
    //    }
    //}
    #endregion
    //Here I am going to use Membership provider to validate user
    if (ModelState.IsValid)
    {
        var isValidUser = Membership.ValidateUser(l.Username, l.Password);
        if (isValidUser)
        {
            FormsAuthentication.SetAuthCookie(l.Username, l.RememberMe);
            if (Url.IsLocalUrl(ReturnUrl))
            {
                return Redirect(ReturnUrl);
            }
            else
            {
                return RedirectToAction("Index", "Home");
            }
        }
    }
    ModelState.Remove("Password");
    return View();
}

Step-3: Edit web.config for Enable our custom membership provider.

In this example, I have written the following configuration in the web.config file for Enable our custom membership provider
 
<membership defaultProvider="MyMembershipProvider">
    <providers>
    <add name="MyMembershipProvider" type="MvcAuthentication.MyMembershipProvider, MvcAuthentication"/>
    <!--<add name="ClassName" type="NamespaceName.ClassName, assemble (dll) name"/>-->
    </providers>
</membership>
        

Step-4: Run Application.


Hello ! My name is Sourav Mondal. I am a software developer working in Microsoft .NET technologies since 2010.

I like to share my working experience, research and knowledge through my site.

I love developing applications in Microsoft Technologies including Asp.Net webforms, mvc, winforms, c#.net, sql server, entity framework, Ajax, Jquery, web api, web service and more.