Skip to content

Choose a permission model

Choose the model that describes how your application grants access. Every model stores permission data and provides check and list functions you can call from your backend. You can use more than one model in the same database. RLS is optional and independent of this choice.

Your rule Start with Example
A role grants access across the application App-wide RBAC Editors can edit documents.
A role grants access within an organization Tenant-scoped RBAC Alice edits documents in Acme and reads documents in Globex.
Access depends on a relationship to one object OpenFGA Bob views a document shared with his team.
A relationship depends on expiry or another attribute OpenFGA conditions A document share lasts for 30 days.
Access depends on attributes of the user or resource Cedar Owners edit their own documents unless they are confidential.
A backend check needs trusted request facts Cedar request context Approving a document requires MFA.
A deny must override grants from several models Combine model decisions Block a suspended user even if a role or share grants access.
You want rules as policy text that people can review Cedar A security team reviews a policy file.

RBAC is the shortest path when roles describe your access rules. Use permissions.rbac to manage roles, permissions, and assignments. A user can hold a role app-wide or in one scope. Those assignments are separate: an app-wide role does not automatically apply within a tenant.

Use permissions.fga to manage authorization models and relationship tuples. Use it for individual shares, nested teams, and access inherited from folders. Conditions are part of this model and use a CEL expression on a tuple.

Use permissions.cedar to manage policies and entities. Policies permit or forbid actions on resources, with conditions on attributes or trusted request context. Use it for rules expressed as policy text, including attribute checks, nested groups and explicit denies. A Cedar forbid overrides every matching permit in Cedar.

Request context is available to the admin check. The current-subject functions accept no request context; they use stored entities and can receive resource attributes from your backend or an RLS policy. See Check access.

The three models have separate data and APIs. A role does not create a relationship, a relationship does not assign a role, and a Cedar policy does not read either. Your backend can combine their results into one decision. For example, allow a role or a share to grant access, while requiring a suspension check to pass.

To add sharing to an existing RBAC application, keep the roles and add OpenFGA tuples and checks. If you enforce table access with RLS, Combine models with RLS shows separate policies for each model and a restrictive policy for a deny across them. Keeping those grant policies separate can improve query performance.

RBAC OpenFGA Cedar
You write Roles, permissions, assignments An authorization model, and tuples Policies, and entities
A rule is A role has a permission in a scope A relationship between a user and an object A permit or a forbid with conditions
Attributes No On a relationship, with CEL conditions On entities, on the resource and in the context
Deny behavior No explicit deny; a missing grant returns false but not excludes access through that relation forbid overrides Cedar permits
Groups Role inheritance Teams and nested teams Any hierarchy of entities
JavaScript check for the current user rbac.hasPermission() fga.check() cedar.isAuthorized()
List accessible scopes or resources rbac.scopesWithPermission() fga.listObjects() cedar.listResources()
How you represent a share A role assignment in an object scope A tuple Entity data used by a policy, or a template link

Denies within OpenFGA or Cedar do not automatically override another model’s answer. Apply a deny across models in your backend’s combined decision, or use a restrictive policy if you choose RLS.

Check access in your application covers backend enforcement with SQL or JavaScript. Use it to authorize API requests, server functions or other operations. The backend handles the result before carrying out the operation.

RLS policies are an optional way to enforce access on database rows. They can call the model functions and add conditions on row columns, such as allowing only editors to see drafts. A Cedar policy defines a rule in the Cedar language; it works with either enforcement approach and does not require an RLS policy.

ABAC describes a category of authorization rules. Use Cedar for attributes of the user, the resource and the request, and OpenFGA conditions for attributes on a relationship. Your backend can supply trusted resource attributes; an RLS policy can supply them from a row. CEL support here is part of OpenFGA conditions, not a separate authorization model.