Implement Password Expiration Check in ASP.NET MVC

1. Create SkipPasswordExpirationCheckAttribute which represents to skip the Password Expiration Check

using System;

namespace Unfuddle.MvcWebApp.Web.Mvc
{
    [AttributeUsageAttribute(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
    public sealed class SkipPasswordExpirationCheckAttribute : Attribute
    {
    }
}

2. Create PasswordExpirationCheckAttribute attribute which inherited from AuthorizeAttribute

using System;
using System.Security.Principal;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
using System.Web.Security;

namespace Unfuddle.MvcWebApp.Web.Mvc
{
    [AttributeUsageAttribute(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = false)]
    public class PasswordExpirationCheckAttribute : AuthorizeAttribute
    {
        private int _maxPasswordAgeInDay;

        public PasswordExpirationCheckAttribute(int maxPasswordAgeInDay = int.MinValue)
        {
            _maxPasswordAgeInDay = maxPasswordAgeInDay;
        }

        public override void OnAuthorization(AuthorizationContext filterContext)
        {
            if (!filterContext.ActionDescriptor.IsDefined(typeof(SkipPasswordExpirationCheckAttribute), inherit: true)
                && !filterContext.ActionDescriptor.ControllerDescriptor.IsDefined(typeof(SkipPasswordExpirationCheckAttribute), inherit: true))
            {
                if (_maxPasswordAgeInDay != int.MinValue)
                {
                    IPrincipal user = filterContext.HttpContext.User;

                    if (user != null && user.Identity.IsAuthenticated)
                    {
                        MembershipUser membershipUser = Membership.GetUser(user.Identity.Name);

                        if (membershipUser != null)
                        {
                            TimeSpan timeSpan = DateTime.Today - membershipUser.LastPasswordChangedDate.Date;

                            if (timeSpan.Days >= _maxPasswordAgeInDay)
                            {
                                HttpContext httpContext = HttpContext.Current;
                                HttpContextBase httpContextBase = new HttpContextWrapper(httpContext);
                                RouteData routeData = new RouteData();
                                RequestContext requestContext = new RequestContext(httpContextBase, routeData);
                                UrlHelper urlHelper = new UrlHelper(requestContext);

                                filterContext.HttpContext.Response.Redirect(urlHelper.Action("ChangePassword", "Account", new { reason = "passwordExpired" }));
                            }
                        }
                    }
                }
            }

            base.OnAuthorization(filterContext);
        }
    }
}

3. Add a setting MaxPasswordAgeInDay in ~\Properties\Settings.settings

MaxPasswordAgeInDay in Settings
MaxPasswordAgeInDay in Settings

4. Register PasswordExpirationCheckAttribute in ~\App_Start\FilterConfig.cs

filters.Add(new PasswordExpirationCheckAttribute(Settings.Default.MaxPasswordAgeInDay));

5. Register SkipPasswordExpirationCheckAttribute in LogOn and ChangePassword action methods of the AccountController

[AllowAnonymous]
[SkipPasswordExpirationCheck]
public ActionResult LogOn()
{
	......
}

[AllowAnonymous]
[SkipPasswordExpirationCheck]
[HttpPost]
public ActionResult LogOn(LogOnViewModel model, string returnUrl)
{
	......
}

[AllowAnonymous]
[SkipPasswordExpirationCheck]
public ActionResult ChangePassword(string reason = null)
{
	......
}

[AllowAnonymous]
[SkipPasswordExpirationCheck]
[HttpPost]
public ActionResult ChangePassword(ChangePasswordViewModel model)
{
	......
}

References

Advertisements

2 thoughts on “Implement Password Expiration Check in ASP.NET MVC

  1. I am trying to apply this logic to an application but I am stuck in an infinite loop on the redirect. Any ideas what might be causing this?

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s