We have a permissions/roles use case we’d like to implement, but are not clear how to design using Auth0. Let me outline the use case:
We have a front end application that connects to a back end via APIs.
We have multiple features in the application; those features each require their own set of permission. For example: Read/Write Inventory, Read/Write Orders.
We have multiple customers, each with their own set of data. Its not quite multi-tenant, but in general, the tenants data are separate from each other.
We have user logins, and each user can be assigned a role/group. Permissions can roll up to various roles and roles can roll up into groups.
When a user logs in, login is delegated to Auth0, which assigns a JWT token. The token may contain the roles, and the back end can determine permissions via Auth0 from the roles. The permissions can then drive what APIs are permitted for the user login.
This is all pretty standard RBAC and OAuth.
Here is where things gets interesting. A user may have permissions over only some of the customer data. For example, User 1 might have some access to Customer A only. While User 2 might have access to Customer A, And Customer B.
Even more complicated, User 3 may have Read permissions for inventory to Customer A and write permissions to orders for Customer B.
That is, there may be all sorts of permutations for permission access to different Customers.
How could we design this in Auth0? We do not want to create permissions for every single permutation of Customer and possible permission. That does not seem scalable nor practical. We had a couple of thoughts:
Store Customer Ids that the user has access to in the user meta-data. This is somewhat helpful, however, this would not provide flexibility to provide different fine grained permissions for difference Customers.
Rules seem promising for this. Our thought is to maybe store additional data about the different customer access in an outside DB which is read by the rule and final permissions determined by the rule.
It is the responsibility of the Resource Server (API) to provide access control. This is particularly important when it comes to fine-grained access control for the reasons you have pointed out, this can get pretty gnarly to try to do in the Authorization Service (your Auth0 tenant) itself for the concerns you already mentioned.
That said, there are things that your Authorization Service can help with, but you need to consider a couple of things when deciding how much data to put in the user’s app_metadata:
How often is this data going to change?
If this data is going to change frequently, and you want instant updates to the information (as in, someone logs into the app and gives permission for another user to access their data, how soon do you want that to take effect?), then you would want to store that in the API’s data store rather than in the Access token which only changes when it expires.
You also need to consider rate limits on your Management API. If you will be making a lot of calls to adjust this fine grained information, you need to make sure that isn’t going to push you over rate limits.
Is this permission information needed outside of the API itself?
Are there multiple APIs that all share this data, and no one API owns it? If so, then put the information in the access token, if not, then let the API own the data itself.
How large is this data?
Just from a practical perspective, there are limits to the size of an access token and the size of your user metadata. If this could expand to a lot of combinations, then it could get unruly to expect all of the data to be in the access token.
You can certainly use rules to grab information from app_metadata and create custom claims, and the metadata is open ended (it is just JSON), so you could store some of this information in app_metadata and use a rule to put it in the token. But you need to consider the impacts of that and whether that is the right approach. Once you start talking about individual users having N-type access to M-number of users, that can get to be a complex and large enough matrix that Auth0 metadata may not be fit to address.