I'm a big fan of the authorization options in ASP.NET Core, especially Resource Based Authorization. I also like to have good test coverage in my applications and when I tried to unit test my resource based authorization handlers it wasn't immediately obvious to me how to do it. So, here's a brief outline on how to do it.

For the purposes of this article I'm going to create an authorisation handler for a victicious resource called Document. Here's my code for the handler:

    public enum DocumentAuthorizationMode {
        Read,
        Update,
        Delete
    }

    public class DocumentRequirement : IAuthorizationRequirement {
        public DocumentAuthorizationMode Mode { get; set; }
    }

    public class DocumentAuthorizationHandler : AuthorizationHandler<DocumentRequirement, Document> {

        protected override Task HandleRequirementAsync(
            AuthorizationHandlerContext context, 
            DocumentRequirement requirement, 
            Document resource
            ) {

            throw new NotImplementedException();

        }

    }

I'm not interested in the implementation of the HandleRequirementAsync method right now, just how to test it.

My first thought was to attempt to call the HandleRequirementAsync method passing in the arguments as shown. Then I realised that the method is protected, so I wouldn't be able to test it directly. So, like any good developer, I turned to Google and looked for "unit testing protected methods". That was no good. Everything there looked like a hack. Back to the drawing board.

Next, I took a look at what I could test on my authorization handler and saw that the only method there is HandleAsync. A quick look at AuthorizationHandler.cs in GitHub showed the following:

        public virtual async Task HandleAsync(AuthorizationHandlerContext context)
        {
            if (context.Resource is TResource)
            {
                foreach (var req in context.Requirements.OfType<TRequirement>())
                {
                    await HandleRequirementAsync(context, req, (TResource)context.Resource);
                }
            }
        }

So, really, it's quite simple. I just construct an Authorization context with the current user, the requirements, and a resource and pass that to HandleAsync. Let's do that:

        public async Task UpdateDocumentFailsForUserWithNoClaims() {

            // ARRANGE ///////////////////////////////////////////////
            // create the requirement
            var requirement = new DocumentRequirement {
                Mode = DocumentAuthorizationMode.Update
            };

            // create the user
            var user = new ClaimsPrincipal(
                new ClaimsIdentity(
                    // no claims added
                    ));

            // create the resource
            var resource = new Document {
                // set any properties here
            };

            // create the context
            var context = new AuthorizationHandlerContext(
                new[] { requirement },
                user,
                resource
                );

            // create the handler
            var handler = new DocumentAuthorizationHandler();

            // ACT ///////////////////////////////////////////////////
            // authorize
            await handler.HandleAsync(context);

            // ASSERT ////////////////////////////////////////////////
            Assert.False(context.HasSucceeded);

        }

There we have it! The right way to unit test your resource based authorization.

Given the potential for highly complex authorization requirements in a system, I strongly recommend that you put unit tests in place for all your handlers. Debugging strange authorization scenarios can be a nightmare.