0

I have created my custom AuthorizationHandler.

public class VdsAuthorizationHandler : IAuthorizationHandler
    {
        private readonly IConfiguration _configuration;
        private readonly IHttpContextAccessor _httpContext;
        private readonly IHttpClientFactory _clientFactory;
        public VdsAuthorizationHandler(IConfiguration configuration, IHttpContextAccessor httpContextAccessor, IHttpClientFactory clientFactory)
        {
            _configuration = configuration;
            _httpContext = httpContextAccessor;
            _clientFactory = clientFactory;
        }

        public Task HandleAsync(AuthorizationHandlerContext context)
        {
            UserRightsDefinition appUserRights = null;
            var authRequirement = context.PendingRequirements.Where(x => x is DenyAnonymousAuthorizationRequirement).FirstOrDefault();
            if (authRequirement != null)
            {
                if(_httpContext.HttpContext.User.Identity.IsAuthenticated)
                {
                    context.Succeed(authRequirement);
                } else
                {
                    context.Fail();
                    return Task.CompletedTask;
                }
            }
            var skipRequirement = context.PendingRequirements.Where(x => x is VdsSkipRequirement).FirstOrDefault();
            if (skipRequirement != null)
            {
                context.Succeed(skipRequirement);
            }
            else
            {
                var req = _clientFactory.CreateClient("Auth");
                var reqMessage = new HttpRequestMessage(HttpMethod.Get, "Auth/userrights");
                reqMessage.Content = new StringContent("", Encoding.UTF8, "application/json");
                var response = req.SendAsync(reqMessage);
                if (response.Result.IsSuccessStatusCode)
                {
                    var userRights = JsonConvert.DeserializeObject<Dictionary<string, UserRightsDefinition>>(response.Result.Content.ReadAsStringAsync().Result);
                    userRights.TryGetValue(_configuration.GetValue<string>("AppSettings:AppCode"), out appUserRights);
                }
                else
                {
                    throw new Vds404NotFoundException();
                }
            }

            if (appUserRights != null)
            {
                var pendingRequirements = context.PendingRequirements.ToList();
                foreach (var requirement in pendingRequirements)
                {
                    if (requirement is VdsPermissionsRequirement)
                    {
                        if (((VdsPermissionsRequirement)requirement).Permissions.Intersect(appUserRights.Permissions).Any())
                        {
                            context.Succeed(requirement);
                        }
                    }
                    else if (requirement is VdsGroupsRequirement)
                    {
                        if (((VdsGroupsRequirement)requirement).Groups.Intersect(appUserRights.Groups).Any())
                        {
                            context.Succeed(requirement);
                        }
                    }
                }
            }

            return Task.CompletedTask;
        }
    }
}

It does what it has to do, except in one case : If I access a non-existing endpoint (ex. /api/fakeendpoint), HandleAsync is still called. So I need to be able to do one of these 2 things :

  • Either evaluate if the requested endpoint is valid or;
  • Avoid calling HandleAsync if the endpoint is invalid

How can I do that?

EDIT:

I might have found an answer, if anyone can confirm :

if(_httpContext.HttpContext.GetRouteData().Values.Count == 0)
{
    context.Fail();
    return Task.CompletedTask;
}
  • You can register handler after registering a "routing" middleware, middleware handlers will be executed in the same order they are registered in `Configure` method of `Startup.cs`. Or you can skip your logic and give it to be handled by routing handler further in middleware pipeline. – Fabio Oct 27 '19 at 22:08
  • Currently, UseRouting() and UseAuthorization() are called in this order. So I don't think this changes anything, unless I need to specify some configuration. Do you have an example for your RoutingHandler? – Simon Lapointe Oct 27 '19 at 22:41
  • I think I found a way to do so, I added the code to the question, if anyone could confirm this is a way to go. – Simon Lapointe Oct 28 '19 at 00:15

0 Answers0