Tag Archives: Policy

Asp.Net Policy Authorization Based on a DB Field on the User Table

If you read this, you’ll learn how to create authorisation, based on a policy. Specifically, they use the example of the user’s age, and create a restriction to say that only users over the age of 21 can access a resource.

The age was something that they got from a claim, stored against the user. But what if your requirement is a little more complex? For example, what if you have a situation, such as a popular question and answer site that you may recognise, where you are trying to restrict access to a resource based on something that can change during the user session. In this post, I’m covering how you can follow the same policy structure, but force the program to go back to the DB to get details about the user, each time they try to access the restricted resource.

As a background, the particular use case here is that a user of my site can approve something, but only where they have a sufficient rating.

Basic Set-up

The first thing that you’ll need is a custom Authorization Handler. For my project, I’ve created a sub directory called Authorization (I’ve even spelled it wrong to be consistent):

The Authorization Handler inherits from an abstract class, which forces you to override a single method: HandleRequirementAsync. Essentially, you tell the handler about your requirement (we’ll come to the requirement next), and then it passes this back to you in the method; let’s have a look at some code:

    public class ApproverAuthHandler : AuthorizationHandler<ApproverAuthRequirement>
    {
        protected override Task HandleRequirementAsync(
            AuthorizationHandlerContext context, 
            ApproverAuthRequirement requirement)
        {

The Requirement is just a class to hold the relevant data that you need. In our example, the requirement would hold the user’s rating; here’s the requirement code:

    public class ApproverAuthRequirement : IAuthorizationRequirement
    {
        public int UserRating { get; set; }

        public ApproverAuthRequirement(int userRating)
        {
            UserRating = userRating;
        }
    }

IAuthorizationRequirment is what is known as a marker interface. To be honest, I hadn’t come across the term before, but I have used the pattern before. Essentially, this is an empty interface: its purpose it to allow you to pass the class type as a strongly typed interface; but in reality, the class can me anything.

Anyway, let’s get back to the Authorization Handler. Inside HandlerRequirementAsync, you can do anything you choose; should your check be successful, you call context.Succeed(requirement), otherwise, do nothing. In the above linked code, they check a claim against the requirement; we’re going to just get some information from the DB, and check that against the requirement:

        protected override Task HandleRequirementAsync(
            AuthorizationHandlerContext context, 
            ApproverAuthRequirement requirement)
        {
            int? userRating = _userService.GetSubjectRating(context.User);            
            if (!userRating.HasValue)
            {
                return Task.CompletedTask;
            }

            if (userRating >= requirement.UserRating)
            {
                context.Succeed(requirement);
            }

            return Task.CompletedTask;
        }

User service is simply a service that calls into a repository, and returns the user rating.

Unit Testing

All well and good, and this looks eminently testable. In fact, it is: you simply mock out the service, and the test looks like this:

            // Arrange
            var requirements = new[] { new ApproverAuthRequirement(100) };            
            var user = new ClaimsPrincipal(
                        new ClaimsIdentity(
                            new Claim[] { },
                            "Basic")
                        );

            var userService = Substitute.For<IUserService>();
            userService.GetSubjectRating(Arg.Any<IPrincipal>()).Returns(100);

            var context = new AuthorizationHandlerContext(requirements, user, null);
            var sut = new ApproverAuthHandler(userService);

            // Act
            await sut.HandleAsync(context);

            // Assert
            Assert.True(context.HasSucceeded);

No doubt, you could check for the exact service principal under test, although you’re testing the Authorization Handler, so I think this is sufficient.

Resource Based Handler

In this article, there is a similar process discussed; it warrants some further investigation on my part, but I don’t currently see any real difference between my implementation, and this abstraction (although, admittedly, this version looks easier to test).

References

https://docs.microsoft.com/en-us/aspnet/core/security/authorization/policies?view=aspnetcore-3.1

https://stackoverflow.com/questions/51272610/unit-test-authorizationhandler

https://docs.microsoft.com/en-us/aspnet/core/security/authorization/resourcebased?view=aspnetcore-3.1

Fault Resilience in Web Calls Using Polly

Some time ago, I was working on a project using WCF RPC calls. We discovered that of the calls that we made, around 10 – 20% were failing. Once we discovered this, I implemented a retry policy to try and cope with the flaky network. I didn’t realise at the time (or maybe it didn’t exist at the time) that there’s a library out there that does that for you: Polly.

To test this out, let’s create a bog standard API Web Project; from Powershell create a directory; e.g.:

mkdir PollyDemo

Then create a Web API project:

dotnet new webapi -n UnreliableApi

Let’s add a client project console app:

    static async Task Main(string[] args)
    {

        HttpClient httpClient = new HttpClient()
        {
            BaseAddress = new Uri("https://localhost:44368")
        };

        var result = await httpClient.GetAsync("weatherforecast");
        if (result.IsSuccessStatusCode)
        {
            var output = await result.Content.ReadAsStringAsync();
            Console.WriteLine(output);
        }
    }

This should call the API fine (using the default API project you get a weather forecaster). Let’s now introduce a level of entropy into the system. In the server, let’s add the following code:

        static Random _rnd = new Random();

        [HttpGet]
        public IEnumerable<WeatherForecast> Get()
        {
            // 1 in 3 chance of an error
            if (_rnd.Next(3) == 1)
            {
                throw new Exception("Bad stuff happened here");
            }

            var rng = new Random();
            return Enumerable.Range(1, 5).Select(index => new WeatherForecast
            {
                Date = DateTime.Now.AddDays(index),
                TemperatureC = rng.Next(-20, 55),
                Summary = Summaries[rng.Next(Summaries.Length)]
            })
            .ToArray();
        }

Now, if you run the client a few times, you’ll see that it’s occasionally failing (actually, from this screenshot, all you can really see if that it didn’t succeed):

We know that this error is transient – just needs an F5, so we can put some code into the client to handle this:

for (int i = 1; i <= 3; i++)
{
    var result = await httpClient.GetAsync("weatherforecast");
    if (result.IsSuccessStatusCode)
    {
        var output = await result.Content.ReadAsStringAsync();
        Console.WriteLine(output);
        break;
    }
    else
    {
        Console.WriteLine("Bad things happened... ");
    }
}

Console.WriteLine("If we get here, we either succeeded or gave up ");

And we’re back in business:

The only problem here is that our code is suddenly a little cumbersome; we have a foreach loop around the code, and we’re risking each person implementing this doesn’t introduce a bug by not breaking when successful or whatever.

Before we introduce Polly as the solution, it’s probably worth mentioning that, whilst some errors can legitimately be fixed by simply trying again, in other cases this can be incredibly harmful. You should ensure that your code is idempotent. Imagine you’re creating a sales order on this call, and it fails after writing something to the database – you risk creating multiple sales orders!

Polly

Polly is basically a library built around this concept. It’s a NuGet package, so import it from here into your client. Let’s start by refactoring our code to call the service:

        private static async Task<bool> GetTheWeather(HttpClient httpClient)
        {
            var result = await httpClient.GetAsync("weatherforecast");
            if (result.IsSuccessStatusCode)
            {
                var output = await result.Content.ReadAsStringAsync();
                Console.WriteLine(output);
                return true;
            }
            else
            {
                Console.WriteLine("Bad things happened... ");
                return false;
            }
        }

Now let’s call that using Polly:

        static async Task Main(string[] args)
        {

            //https://localhost:44368/weatherforecast

            HttpClient httpClient = new HttpClient()
            {
                BaseAddress = new Uri("https://localhost:44368")
            };

            var retryPolicy = Policy
                .HandleResult<bool>(false)               
                .RetryAsync(3, (response, retryCount) =>
                  {
                      Console.WriteLine($"Received a response of {response.Result}, retrying {retryCount}.");
                  });

            var result = await retryPolicy.ExecuteAsync(() => GetTheWeather(httpClient));            

            Console.WriteLine("If we get here, we either succeeded or gave up ");
        }

All we’re doing here is telling Polly that we want a policy that acts on a return value of False (in theory, I imagine you could set this to something like .HandleResult(“Aardvark”) and have it retry while the method returned a value of Aardvark). RetryAsync sounds pretty obvious, but the Async part is very important, otherwise, you won’t be able to use ExecuteAsync… and you’ll spend a while wondering why (so I hear)!

ExecuteAsync is awaitable, so it will wrap the retry logic in this single line.

The advantage here is that you can define a retry policy for your application, or several retry policies for your application.

References

https://github.com/App-vNext/Polly

https://github.com/bryanjhogan/trydotnet-polly