Hacker News new | ask | show | jobs
by codetrotter 457 days ago
What is the advantage of having the policy checking be an async function? From a brief look (framework itself and one of the examples provided in the examples directory) it seems that you’d typically be doing all I/O operations up front before invoking the policy checker, and that doing the policy check does not itself involve any I/O.

I only looked over the code quickly so I’m probably overlooking something.

It would be neat to get the motivation for each of the functions that are async being async instead of just “normal” functions.

1 comments

The examples just don't show any I/O but you could easily imagine that the actual policy check is done by a different service which lives across an I/O boundary or involves DB lookups to validate if the action on the given resource by the subject within the given context is allowed.
A lot of policies are also about accessing IO in the first place. So I feel like this tracks.
Yeah it makes more sense now.

First I was looking at the Axum integration example https://github.com/thepartly/gatehouse/blob/a3b46bcb37353cb5... where they do the simulated I/O first and then do a policy check that consists only of business logic without any I/O as far as I could tell

https://github.com/thepartly/gatehouse/blob/a3b46bcb37353cb5...

Because there from what I could see, all decisions made by the policies are based on properties read from the user, resource and action objects that were already retrieved in full by the application before it did the call to evaluate access.

So from that and looking over the framework itself I was wondering why evaluating access was an async function, when all of the data I saw it use was retrieved before doing the actual access evaluation itself.

But after reading your comment I then had a look at some of the other examples, and found for example the ReBAC policy example https://github.com/thepartly/gatehouse/blob/a3b46bcb37353cb5... which does seem to be written like it demonstrates I/O such as DB lookups during the access evaluation itself.

It kind of seems to me now then, that the sort of usage of the framework they demonstrate in the Axum integration would typically not do I/O during access evaluation, even for a production grade app. Whereas the kind of usage they demonstrate in the ReBAC example would. And that the reason for involving async is to facilitate the sort of usage they do in the ReBAC example and that it is sort of incidental then that even when you use it in a way that would work for production without I/O during access evaluation, like in the Axum integration example, you still end up with the access evaluation being an async function. Because they are doing a framework that also has to support the ReBAC example kind of usage they have the trait for access evaluation async.

And in turn this probably makes it so that you could start using the framework with the sort of access evaluation that is not doing I/O itself (like in the Axum integration), and then you still have flexibility for later to drop in one that does (like in the ReBAC example) without having to change too much in the parts of your code where you were calling the access evaluation from the beginning.

I could see some value in that. At the same time, assuming my above understanding is correct, it also does seem like in some cases one might end up pulling in a framework that is more flexible than one really needs, if one starts out with using it in the way like in the Axum integration example and then later finds out that one ended up not needing much more beyond what one could do with that.

And because I myself don't yet have advanced needs like in the ReBAC example, I'm not sure if a framework like this would really benefit me. Or if I'd be better off finding a more basic framework for doing authorization in my own server programs.

Of course, I could be misunderstanding the whole thing still :P

You're spot on - we wanted to support some async graph traversal calls similar to the ReBAC example and therefore made the evaluate_access call async. I also wanted to support short circuiting such that somewhat expensive IO calls might be skipped by returning early from a policy that didn't need to make that call.