Search code examples
cachingasp.net-coreasp.net-core-mvcasp.net-authorization

How to persist policy authorization results for users in ASP.NET Core, MVC 6?


Currently I have a simple custom policy handler that looks like so:

protected override void Handle(AuthorizationContext context, UserPolicyRequirement requirement)
{
    // authorize user against policy requirements
    if (_authorizationTask.AuthorizeUserAgainstPolicy(context.User, requirement))
    {
        // User passed policy req's 
        context.Succeed(requirement);
    }
}

Problem is, this authorization step takes a long time to execute, but this is required in many different areas of the website. Is there any readily available mechanisms to save/cache the results of this policy authorization so that I only need to do this once per session?

I am currently using Windows Authentication, if that helps.


Solution

  • If per session way does not cause any problem, you can use Session to store user data. Simple implementation is something like below:

    First you need a service to get user data from any store

    public interface IGetUserDataService
    {
        <type> GetUserData();
    }
    

    I assume that there is Session configuration(see) and IGetUserDataService implementation.

    Then you need to create a middleware to handle Session

    public class SessionMiddleware
    {
        private readonly RequestDelegate _next;
        private readonly IGetUserDataService _getUserDataService;
    
        public SessionMiddleware(RequestDelegate next, IGetUserDataService getUserDataService)
        {
            _next = next;
            _getUserDataService = getUserDataService;
        }
    
        public async Task Invoke(HttpContext context)
        {
            //user data is obtained only once  then is stored in Session
            if (context.Session.Get("UserData") == null)
            {
                context.Session.Set("UserData", getUserDataService.GetData());
            }
            await _next.Invoke(context);
        }
    }
    
    //In Startup.cs
    app.UseMiddleware<SessionMiddleware>();
    

    Finally get and use session data in handler

    public class YourHandler : AuthorizationHandler<YourRequirement>
    {
        private readonly IHttpContextAccessor _accessor;
        public YourHandler(IHttpContextAccessor accessor)
        {
            _accessor = accessor;
        }
        protected override void Handle(AuthorizationContext context, PermissionRequirement requirement)
        {
            var userData =(<type>)_accessor.HttpContext.Session.Get("UserData");
            // check
        }
    }