authorization support?
@Dima Utkin : "Convex currently has an authentication framework which verifies user identities. In the future we plan to add an authorization framework which will allow developers to define what data a user can access."
how far is this on the roadmap? 🙂
13 Replies
So far we've been interested in pushing the limits of user-space solutions to this, rather than trying to build a comprehensive solution baked in. For example, defining functions that take in a user and check that they have permission to the documents retrieved. The upside of doing it in code is total flexibility, and in Convex those functions are running much closer to the DB, so you don't have to force your logic into some obtuse DSL like FaunaDB.
I have a few ideas I'm interested in pursuing (as helpers you can copy for now, then maybe as npm packages if they seem useful in that format), open to your feedback on them:
1. Documenting some best practices for storing and leveraging permissions in tables. Having reference code for doing generic permission checks.
2. A wrapper around functions that wrap the
db
parameter to do checks on reads/ writes, based on a user-defined mapping of table -> { readValidator, writeValidator }. This is similar to the "row-level-permissions" idea. I'm a bit fuzzy on the right way to structure users & the relationships pointing to rows that might not have back-references, but open to ideas.
If you were to get to pick an ideal implementation for your app, what would the interface look like? Any stacks you've been especially happy with?@ian tbh, i have no idea, how this should work "in general", i've never implemented sophisticated enough access controls in any app i've worked on.
what i have in mind as a "perfect" solution from the developer's point of view is smth like
if can(userId, resource, action)...
this is the pattern from permit.io service, which looks awesome, but have a list of downsides(especially, the pricing)
but it also bring up a lot of questions... what if the DB is not the only thing you want to protect with these rules? what about calling other APIs, RPC calls to other parts of your infra, using features, etc.?
My point is that, it might work if the target is feature-parity with Firebase, they do have a nice and straightforward way of declaring access rules for the DB. but is it enough for everyone? is it even a good idea to limit these rules to the DB level? What's a <user> if you don't use Firebase Auth? Lots of question there. I don't know if there is a universal solution 🤷Yup, that's what I'm thinking as well. I have some rough ideas, but I'll update here when I get some time to work on it. Would you mind sharing (here or DM) some specific checks you'd do? I have my own idea of "a user can only modify their own user but can read other users" or "on a doc that is only shared with a few people, only the author or those people can view or edit it". The devil is in the details here, b/c for a relational DB a lot of the info is encoded in other tables, e.g. a "join" or "pivot" table, not just the document being fetched. In firestore they advise more denormalization, so you might have all that data encoded in the document. Which you can do with Convex too, but some folks prefer normalizing data.
again, it's very "what's a <user>?" dependent issue to me.
Right now, i'm working on a multi-tenant app(mostly on FE side), with rules from
casl
lib, and we're both empowered by this lib, but also somewhat limited by it in some of the cases, but in general, in works for us.
i see this authZ system as: authN provider (with optional roles like planned in Clerk) <-> user in Convex with roles -> rules on entities in Convex db <-> optional per-user limits for working with entities in db.
Like RBAC is top-level, and ABAC(?) is a nested, more granular level on top of role-based access rules.
Still, i'm a rookie in this area 🙂That makes sense. And yes, because the user definition (and team/group/role/etc) is not a primitive in Convex, I'd be tempted to outline a pattern for using tables to represent users & roles, and some easily composable functions to define rules for each table, and have different apps define their own schemas and such, rather than start with built-in concepts of users & roles. The challenge is enforcing the application of the rules over every access / write, besides convention. 🤔
hi, any update or thoughts on this?
yeah, we're going to be releasing a "full stack" kit that includes things like auth and initial authz in the next few months. in the mean time, the convex-ents project has some support for "rules" which bake in a methdology for access control: https://labs.convex.dev/convex-ents/schema/rules
Rules - Convex Ents
Relations, default values, unique fields and more for Convex
@faluyiHype There is an example of granular permissions in https://github.com/xixixao/saas-starter
GitHub
GitHub - xixixao/saas-starter: Convex, Clerk, Next.js, Convex Ents
Convex, Clerk, Next.js, Convex Ents. Contribute to xixixao/saas-starter development by creating an account on GitHub.
A little confused by this starter kit, if we're using clerk why are we handling team and org logic?
It's generally a better idea to keep information that you want to be transactional and accessed quickly in your own database. If you use Clerk for team & org logic, you need to copy all of that over to your DB in order to actually use it meaningfully. This is especially apparent when you're trying to figure out the user / team / org information of other users during a request. In a Convex transaction (query/mutation) you cannot make http requests to fetch or change data on Clerk. And with any backend you shouldn't be doing http requests while you hold open a transaction.
Ok makes sense so Clerk is only used for authentication then? Might as well switch to convex auth and save some money 😎
Side note, is there a way to have a pre mutation/query hook for the purpose of fetching some 3rd party api before executing a transaction
not really - you can do a post-mutation http call by transactionally scheduling an action, but other things you'd need to do from the client. If you run into a concrete example / pain point let's open another support thread for it though, unless it's focused on authorization
https://docs.convex.dev/functions/actions this clearly covers it thanks.
Actions | Convex Developer Hub
Actions can call third party services to do things such as processing a payment