Permissions & RBAC

Control what each user can do and access with the permission system

Team Permissions

Team permissions control what a user can do within each team. You can create and assign permissions to team members from the Stack dashboard. These permissions could include actions like create_post or read_secret_info, or roles like admin or moderator. Within your app, you can verify if a user has a specific permission within a team.

Permissions can be nested to create a hierarchical structure. For example, an admin permission can include both moderator and user permissions. We provide tools to help you verify whether a user has a permission directly or indirectly.

Creating a Permission

To create a new permission, navigate to the Team Permissions section of the Stack dashboard. You can select the permissions that the new permission will contain. Any permissions included within these selected permissions will also be recursively included.

System Permissions

Stack comes with a few predefined team permissions known as system permissions. These permissions start with a dollar sign ($). While you can assign these permissions to members or include them within other permissions, you cannot modify them as they are integral to the Stack backend system.

Checking if a User has a Permission

To check whether a user has a specific permission, use the getPermission method or the usePermission hook on the User object. This returns the Permission object if the user has it; otherwise, it returns null. Always perform permission checks on the server side for business logic, as client-side checks can be bypassed. Here’s an example:

Check user permission on the client
1"use client";
2import { useUser } from "@stackframe/stack";
3
4export function CheckUserPermission() {
5 const user = useUser({ or: 'redirect' });
6 const permission = user.usePermission('read');
7
8 // Don't rely on client-side permission checks for business logic.
9 return (
10 <div>
11 {permission ? 'You have the read permission' : 'You shall not pass'}
12 </div>
13 );
14}

Listing All Permissions of a User

To get a list of all permissions a user has, use the listPermissions method or the usePermissions hook on the User object. This method retrieves both direct and indirect permissions. Here is an example:

List user permissions on the client
1"use client";
2import { useUser } from "@stackframe/stack";
3
4export function DisplayUserPermissions() {
5 const user = useUser({ or: 'redirect' });
6 const permissions = user.usePermissions();
7
8 return (
9 <div>
10 {permissions.map(permission => (
11 <div key={permission.id}>{permission.id}</div>
12 ))}
13 </div>
14 );
15}

Granting a Permission to a User

To grant a permission to a user, use the grantPermission method on the ServerUser. Here’s an example:

1const team = await stackServerApp.getTeam('teamId');
2const user = await stackServerApp.getUser();
3await user.grantPermission(team, 'read');

Revoking a Permission from a User

To revoke a permission from a user, use the revokePermission method on the ServerUser. Here’s an example:

1const team = await stackServerApp.getTeam('teamId');
2const user = await stackServerApp.getUser();
3await user.revokePermission(team, 'read');

By following these guidelines, you can efficiently manage and verify team permissions within your application.