Using SimpleMembership With Mobile Applications In ASP.NET MVC 4

Someone recently asked on StackOverflow if you can use the SimpleMembership provider in a mobile application generated by the mobile template for ASP.NET MVC 4.  The shell of the mobile application generated by this template generates basic security, such as logging in, logging out, registration and password reset, but it uses the older ASP.NET membership and role providers.  So I thought this would be a good exercise to see if I could use the open source project SimpleSecurity to switch the mobile application to use the SimpleMembershipProvider.  SimpleSecurity helps decouple SimpleMembership from an MVC application.  It turns out that it was quite easy to add SimpleMembership to an ASP.NET MVC mobile application when using SimpleSecurity.

First add the SimpleSecurity assembly as a reference in your mobile project. You will also need to add WebMatrix.Data and WebMatrix.WebData as references. In the properties for these two assemblies set the property Copy Local to true.

Next modify your web.config to use the SimpleMembership providers.  Replace the settings for the providers in the template generated web.config to the following.

    <roleManager enabled="true" defaultProvider="SimpleRoleProvider">
      <providers>
        <clear/>
        <add name="SimpleRoleProvider" type="WebMatrix.WebData.SimpleRoleProvider, WebMatrix.WebData"/>
      </providers>
    </roleManager>
    <membership defaultProvider="SimpleMembershipProvider">
      <providers>
        <clear/>
        <add name="SimpleMembershipProvider" type="WebMatrix.WebData.SimpleMembershipProvider, WebMatrix.WebData" />
      </providers>
    </membership>

Add the following line to the Application_Start method in the Global.asax to register SimpleSecurity.

    WebSecurity.Register();


Finally we need to modify the actions in the AccountController that were generated by the mobile template. Here are the modifications to the POST Login action.

        [AllowAnonymous]
        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Login(LoginModel model, string returnUrl)
        {
            if (ModelState.IsValid)
            {
                if (WebSecurity.Login(model.UserName, model.Password, model.RememberMe))
                {
                    if (Url.IsLocalUrl(returnUrl))
                    {
                        return Redirect(returnUrl);
                    }
                    else
                    {
                        return RedirectToAction("Index", "Home");
                    }
                }
                else
                {
                    ModelState.AddModelError("", "The user name or password provided is incorrect.");
                }
            }

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


And here are the changes to the LogOff action.

       public ActionResult LogOff()
       {
           WebSecurity.Logout();

           return RedirectToAction("Index", "Home");
       }


You will also need to change the Register action.

        [AllowAnonymous]
        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Register(RegisterModel model)
        {
            if (ModelState.IsValid)
            {
                // Attempt to register the user
                bool createdUser = false;
                string errMessage = string.Empty;
                try
                {
                    WebSecurity.CreateUserAndAccount(model.UserName, model.Password, model.Email);
                    createdUser = true;

                }
                catch (Exception ex)
                {
                    errMessage = ex.Message;
                    createdUser = false; 
                }

                if (createdUser)
                {
                    if (WebSecurity.Login(model.UserName, model.Password))
                        return RedirectToAction("Index", "Home");
                    else
                        ModelState.AddModelError("", "Error logging user in with that username/password.");

                }
                else
                {
                    ModelState.AddModelError("", errMessage);
                }
            }

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


And lets not forget the ChangePassword action.

        [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult ChangePassword(ChangePasswordModel model)
        {
            if (ModelState.IsValid)
            {

                // ChangePassword will throw an exception rather
                // than return false in certain failure scenarios.
                bool changePasswordSucceeded;
                try
                {
                    UserProfile currUser = WebSecurity.GetCurrentUser();
                    changePasswordSucceeded = WebSecurity.ChangePassword(currUser.UserName, model.OldPassword, model.NewPassword);
                }
                catch (Exception)
                {
                    changePasswordSucceeded = false;
                }

                if (changePasswordSucceeded)
                {
                    return RedirectToAction("ChangePasswordSuccess");
                }
                else
                {
                    ModelState.AddModelError("", "The current password is incorrect or the new password is invalid.");
                }
            }


That is it. Your mobile application will now use the SimpleMembership provider instead of the old-style ASP.NET providers. If you would like the source code for this example you can get it here.




Comments

Popular posts from this blog

Using Claims in ASP.NET Identity

Seeding & Customizing ASP.NET MVC SimpleMembership

Customizing Claims for Authorization in ASP.NET Core 2.0