Friday, January 15, 2016

Applying c# Extensions for Claims-based Authentication

In My AccountController, I have NewLogin Action:
        [HttpPost]
        [AllowAnonymous]
        [ValidateAntiForgeryToken]
        public ActionResult NewLogin(LocalAccountLoginViewModel model, string returnUrl)
        {
            using (UserService _service = new UserService())
            {
                CFG_Users user = _service.GetUserById(model.UserId);
                if (user == null)
                {
                    DisplayErrorPage("Error", Resources.Account.LoginResources.UserNotExist);
                    return View(model);
                }
                if (!user.Enabled)
                {
                    DisplayErrorPage("Error", Resources.Account.LoginResources.UserNotActive);
                    return View(model);
                }

                if (!_service.ValidateUser(model.UserId, model.Password))
                {
                    DisplayErrorPage("Error", Resources.Account.LoginResources.InvalidUserNamePassword);
                    return View(model);
                }

                var claims = new List<Claim>();

                // create *required* claims
                claims.Add(new Claim(ClaimTypes.NameIdentifier, user.IDUser));
                claims.Add(new Claim(ClaimTypes.Name, _service.GetUserName(user)));
                claims.Add(new Claim("IsAdmin", _service.IsUserAdmin(user).ToString()));
                claims.Add(new Claim("Culture", user.IDLanguage.Trim()));

                IdentitySignin(claims, model.UserId, model.RememberMe);

                if (!string.IsNullOrEmpty(returnUrl))
                    return Redirect(returnUrl);

                return RedirectToAction("Index", "Dashboard", null);
            }
        }
The NewLogin action  applied following helper method to finish the sign in process.
        /// <summary>
        /// Helper method that adds the Identity cookie to the request output
        /// headers. 
        /// </summary>
        /// <param name="claims"></param>
        /// <param name="providerKey"></param>
        /// <param name="isPersistent"></param>
        public void IdentitySignin(List<Claim> claims, string providerKey = null, bool isPersistent = false)
        {
            var identity = new ClaimsIdentity(claims, DefaultAuthenticationTypes.ApplicationCookie);

            // add to user here!
            AuthenticationManager.SignIn(new AuthenticationProperties()
            {
                AllowRefresh = true,
                IsPersistent = isPersistent,
                ExpiresUtc = DateTime.UtcNow.AddDays(1)
            }, identity);

            var userCulture = identity.GetCulture();
            // set lang to the user's language 
            if (RouteData.Values["lang"] != userCulture)
            {
                RouteData.Values["lang"] = userCulture;
                SetThreadCulture(userCulture);
            }
        }

        public void IdentitySignout()
        {
            AuthenticationManager.SignOut(DefaultAuthenticationTypes.ApplicationCookie,
                DefaultAuthenticationTypes.ExternalCookie);
        }

        private IAuthenticationManager AuthenticationManager
        {
            get { return HttpContext.GetOwinContext().Authentication; }
        }
Note I applied C# Extensions so I can easily use GetCulture for my identity. Here is the Claim Identity Extension code:
using System.Collections.Generic;
using System.Security.Claims;
using System.Linq;
namespace MyApp.Extensions
{
    public static class ClaimsIdentityExtensions
    {
        public static bool IsAdmin(this ClaimsIdentity identity)
        {
            var claims = identity.Claims;
            return bool.Parse(GetClaim(claims, "IsAdmin")); 
        }

        public static string GetCulture(this ClaimsIdentity identity)
        {
            var claims = identity.Claims;
            return GetClaim(claims, "Culture"); //todo: replace Culture with a Const
        }

        public static string GetName(this ClaimsIdentity identity)
        {
            var claims = identity.Claims;
            return GetClaim(claims, ClaimTypes.Name); ;
        }

        public static string GetUserId(this ClaimsIdentity identity)
        {
            var claims = identity.Claims;
            return GetClaim(claims, ClaimTypes.NameIdentifier);
        }

        private static string GetClaim(IEnumerable<Claim> claims, string key)
        {
            var claim = claims.ToList().FirstOrDefault(c => c.Type == key);
            if (claim == null)
                return null;
            return claim.Value;
        }
    }
}

Reference:
http://leastprivilege.com/2012/10/08/custom-claims-principals-in-net-4-5/

No comments:

Post a Comment