Search code examples
authenticationasp.net-coreurl-routingchange-password

Force user change password when loading any webpage


I am using ASP.net core 2.0. I added a flag column called IsChangePassword to my AspNetUsers table and to my ApplicationUser class. The idea is to force the user to change their password. There is always a chance that they might enter a url to bypass being forced to change their password. I want to have it check that property every time a webpage is being loaded and redirect to ChangePassword if that flag is true.


Solution

  • You need a resource filter, which you'll need to inject with both UserManager<TUser> and IUrlHelperFactory. The former will obviously be used to check the value of IsChangePassword, while the latter will be necessary to check the current URL against your chosen redirect URL, to prevent an endless redirect loop. Simply:

    public class ChangePasswordResourceFilter : IAsyncResourceFilter
    {
        private readonly UserManager<ApplicationUser> _userManager;
        private readonly IUrlHelperFactory _urlHelperFactory;
    
        public ChangePasswordResourceFilter(UserManager<ApplicationUser> userManager, IUrlHelperFactory urlHelperFactory)
        {
            _userManager = userManager;
            _urlHelperFactory = urlHelperFactory;
        }
    
        public async Task OnResourceExecutionAsync(ResourceExecutingContext context, ResourceExecutionDelegate next)
        {
            var urlHelper = _urlHelperFactory.GetUrlHelper(context);
            var redirectUrl = urlHelper.Page("~/PasswordChange");
            var currentUrl = context.HttpContext.Request.Path;
    
            if (redirectUrl != currentUrl)
            {
                var user = await _userManager.GetUserAsync(context.HttpContext.User);
                if (user?.IsChangePassword ?? false)
                {
                    context.Result = new RedirectResult(redirectUrl);
                }
            }
    
            await next();
        }
    }
    

    Then, in Startup.ConfigureServices:

    services.AddScoped<ChangePasswordResourceFilter>();
    
    ...
    
    services.AddMvc(o =>
    {
        o.Filters.Add(typeof(ChangePasswordResourceFilter));
    });