Reputation: 599
I am validating JWT token using authorization filters in order to check user are authorised to access the API endpoint.
It's working fine. However, I am not sure how to unit test that Authorization filter (ASP.NET Core Web API):
public class AuthFilter : IAuthorizationFilter
{
// code ......
}
Upvotes: 3
Views: 1953
Reputation: 71
To unit test your AuthFilter
you want to test that the method, that I assume you've implemented, OnAuthorization(AuthorizationFilterContext context)
, results in the expected state of the context
given some JWT token. That is, you have an authenticated user represented by the token, and now you want to verify with AuthFilter
that they're authorized or have permission to request the resource they're attempting to request. If this is not the case, please have a look at the Microsoft .NET documentation which explains how authorization requires authentication.
To do this, I also assume that you have some method, service or class that does this authorization check for you. If it just is a method in the AuthFilter
, I would recommend extracting it into an interface like this:
public interface IAuthorizationChecker {
public bool HasPermission(string token);
}
which you then inject into your AuthFilter
:
public class AuthFilter : IAuthorizationFilter {
private readonly IAuthorizationChecker _authChecker;
public AuthFilter(IAuthorizationChecker authChecker) {
_authChecker = authChecker;
}
public void OnAuthorization(AuthorizationFilterContext context) {
...
var token = context.HttpContext.Request.Headers["Authorization"].split(' ')[1];
var hasAccess = _authChecker.HasPermission(token);
if (!hasAccess) {
filterContext.Result = new StatusCodeResult(403);
return;
}
...
}
You can then create a mock implementation of this interface like so:
public class MockAuthorizationChecker : AuthorizationChecker {
private readonly bool _hasAccess;
public MockAuthorizationChecker(bool hasAccess) {
_hasAccess = hasAccess;
}
public bool HasPermission(string token) {
return _hasAccess;
}
}
And finally, you have isolated all parts allowing you to unit test the functionality of the OnAuthorization()
method. A simple test would be something like the following (here with NUnit, but the same applies for other frameworks):
[Test]
public async Task TestAuthorizationFilterReturnsExpected() {
// Arrange
var expected = 403; // Forbidden; Or whatever you do expect here
// This token may be valid or invalid, depending on what you expect the result from the OnAuthorization() method to be
var token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...";
var httpContext = new DefaultHttpContext();
httpContext.Request.Headers["Authorization"] = $"Bearer {token}";
var hasAccess = false;
var mockAuthChecker = new MockAuthorizationChecker(hasAccess);
var authFilter = new AuthFilter(mockAuthChecker); // Mock and inject any other dependencies that your filter might require here
var filters = new List<IFilterMetadata> { authFilter };
var routeData = new RouteData(); // Unused, required to create context
var actionDescriptor = new ActionDescriptor(); // Unused, required to create context
var actionContext = new ActionContext(httpContext, routeData, actionDescriptor);
var authorizationFilterContext = new AuthorizationFilterContext(actionContext, filters);
// Act
await authFilter.OnAuthorizationAsync(authorizationFilterContext);
// Assert
var actual = authorizationFilterContext.Result as StatusCodeResult;
Assert.That(actual, Is.Not.Null);
Assert.That(actual.StatusCode, Is.EqualTo(expected), "Context Result");
}
As stated in the code example, you might have other dependencies which you need to mock to isolate the AuthFilter from the dependencies.
Upvotes: 7