Role-Based Access Control overview
Stytch's Role-Based Access Control (RBAC) solution is an authorization model that manages access to resources within your application. Our RBAC model streamlines the management and enforcement of permissions with a flexible interface that's designed for a multi-tenant auth system.
In this overview, we'll cover the core concepts of how our RBAC model works.
The RBAC Policy
Every Stytch Project has a governing document called the RBAC Policy that stores all access controls. It is the canonical source for all RBAC authorizations within a Stytch Project.
The RBAC Policy can be updated through the Dashboard. You can view its data structure in the API Reference. To retrieve the document, you would call the Get RBAC Policy endpoint.
The RBAC Policy is collectively made up of three core concepts:
- Resources
- Roles
- Actions
The relationship between them is what serves as the foundation for Stytch's RBAC permissioning model. To understand how they all fit into the RBAC Policy, we'll first define them individually.
Resources & actions
A Resource represents an abstract entity that your application interacts with. It is identified by resource_id, a unique, user-inputted string that allows you to freely name a Resource after almost anything.
Typically, Resources are modeled after data objects your application regularly creates or manages. For example, Resources in the Stytch API context might be Organizations, Members, and SAML Connections. In your application's context, Resources might be "documents", "images", "invoices", "products", "employees", or "credit-cards".
In addition to resource_id, a Resource is associated with a list of actions. The list enumerates all the valid operations that can be performed upon the given Resource. Any action not explicitly included in the list is considered invalid and unauthorized.
Stored as free-text strings, actions can represent standard CRUD operations like "create", "read", "update", and "delete" or more application-specific tasks like "share", "invite", "block", and "export".
Once the resource_id and actions fields, along with an optional description, are defined, the Resource object has all its necessary components. The final state should look similar to this example:
{
"resource_id": "documents",
"actions": [
"create",
"read",
"write",
"delete",
"share",
"export"
],
"description": "Documents are text files that can be shared for collaboration."
}
The above JSON can be interpreted as "The documents resource supports create, read, write, delete, share, and export operations."
Resources are created and managed in the Dashboard where updates will propagate to the RBAC Policy. We recommend always setting both the resource_id and actions to be human-readable strings.
Check out the Resource object in the API reference for more details.
Roles & permissions
A Role is a named collection of permissions. Identified by role_id, a unique, user-inputted string, Roles are usually named in a way to represent meaningful personas such as "admin", "accountant", or "analyst".
Depending on the use case, a Role can have one or more permissions. For example, an "admin" role would have many if not all permissions, while a "reader" role would only have read permissions.
A Role's permission is a tuple that links actions to a resource_id. Actions are scoped to a specific Resource — so if the "document" and "image" Resources both have a "view" Action, the permission to "view" "documents" and the permission to "view" "images" are two distinct permissions that you could grant individually to a Role.
Note that a permission's actions are a subset of the Resource's. In other words, a permission can only include an action that the corresponding Resource object has already specified within its own actions list.
Here is an example of a Role:
{
"role_id": "reader",
"permissions": [
{
"actions": [
"read"
],
"resource_id": "documents"
},
{
"actions": [
"read"
],
"resource_id": "images"
}
],
"description": "Members with the reader role can view documents and images."
}
The above JSON can be interpreted as "The reader role is authorized to perform read operations on documents and images."
Stytch also supports the use of a wildcard permission “*” to authorize all possible actions for a given Resource. Assigning the wildcard permission “*” for a Resource to a Role will grant authorization for all current and future actions associated with that Resource. This is useful for situations like an "admin" Role where you would always want to grant all available permissions.
{
"role": "admin",
"permissions": [
{
"actions": [
"*"
],
"resource_id": "documents"
},
{
"actions": [
"*"
],
"resource_id": "images"
}
],
"description": "The admin role is authorized to perform all operations on documents and images."
}
When assigned to a Member, the Role grants them the permissions within the context of their Organizations.
Roles are created and managed in the Dashboard where updates will propagate to the RBAC Policy. We recommend always setting the role_id to be a human-readable string.
Check out the Role object in the API reference for more details.
Putting them all together
To summarize:
- Resources represent entities like documents, users, videos, or settings.
Resources have actions, which are lists that enumerate all valid operations.
- Roles represent personas like admin, analyst, editor, or reader.
Roles have permissions that link specific actions to a Resource.
The RBAC Policy puts them all together and serves as the centralized repository. It stores all Resources and Roles, along with their updates. Always refer to the RBAC Policy to review the defined Resources and Roles within your Project's RBAC model.
Here is a complete example of an RBAC Policy:
{
"policy": {
"resources": [
{
"actions": [
"create",
"read",
"write",
"delete"
],
"description": "Documents are text files that can be shared for collaboration.",
"resource_id": "documents"
},
{
"actions": [
"create",
"read",
"delete"
],
"description": "Images are media files for sharing.",
"resource_id": "images"
},
{
"actions": [
"update.info.name",
"update.info.slug",
"update.info.logo-url",
"update.settings.allowed-auth-methods",
"update.settings.allowed-mfa-methods",
"update.settings.email-jit-provisioning",
"update.settings.email-invites",
"update.settings.allowed-domains",
"update.settings.default-sso-connection",
"update.settings.sso-jit-provisioning",
"update.settings.mfa-policy",
"update.settings.implicit-roles",
"delete"
],
"description": "Built-in resource for Stytch organization objects",
"resource_id": "stytch.organization"
},
{
"actions": [
"create",
"update.info.name",
"update.info.untrusted-metadata",
"update.info.mfa-phone",
"update.info.delete.mfa-phone",
"update.info.delete.password",
"update.settings.is-breakglass",
"update.settings.mfa-enrolled",
"update.settings.roles",
"search",
"delete"
],
"description": "Built-in resource for Stytch member objects",
"resource_id": "stytch.member"
},
],
"roles": [
{
"description": "",
"permissions": [
{
"actions": [
"*"
],
"resource_id": "documents"
},
{
"actions": [
"*"
],
"resource_id": "images"
}
],
"role_id": "organization_admin"
},
{
"description": "",
"permissions": [
{
"actions": [
"read",
"write"
],
"resource_id": "documents"
},
{
"actions": [
"read",
"share",
"export"
],
"resource_id": "images"
}
],
"role_id": "editor"
},
{
"description": "",
"permissions": [
{
"actions": [
"read"
],
"resource_id": "documents"
},
{
"actions": [
"read"
],
"resource_id": "images"
}
],
"role_id": "reader"
}
]
}
}
What's next
Check out our integration guide to start enforcing authorization with Stytch.