Skip to content
Scalekit Docs
Talk to an Engineer Dashboard

Roles and permissions

Applications often include many capabilities. Not every user should be able to perform every action (for example, only owners should manage billing or payments). Scalekit helps you restrict access cleanly with roles and permissions so users get only the access they need.

Scalekit’s Full Stack Auth (FSA) lets your users sign in to your app. Once integrated, Scalekit acts as access middleware: it verifies identity and shares the user’s role and permissions with your application so you can allow or restrict actions.

Diagram
  • Role: A convenient bundle of actions. Examples: Admin, Manager, Editor, Viewer. Roles state what a user can and cannot do.
  • Permission: A single allowed action in your system, typically rendered as resource:action (for example, projects:create, tasks:read). Use permissions when you need fine-grained control.

Scalekit automatically assigns default roles when setting up your organization:

  • Organization creator: The first user who creates your Scalekit organization gets the creator role automatically
  • New members: When you invite users to your organization, they’re automatically assigned the member role

These default roles provide a starting point for access control. You can customize what permissions these roles have and change the default role assignments at any time. Additionally, roles can be assigned to anyone who is invited to your organization, regardless of how they joined (email invitation, SSO, social login, etc.). This gives you full control over who gets which role and allows you to modify user roles at any time after they’ve joined.

Design roles that reflect how your users work. For a project management app (similar to Linear), you might define:

RolePermissions
Adminorg:manage, billing:manage, projects:create, projects:write, projects:read, tasks:create, tasks:write, tasks:read, members:manage
Project ownerprojects:create, projects:write, projects:read, tasks:create, tasks:write, tasks:read
Editorprojects:write, projects:read, tasks:create, tasks:write, tasks:read
Memberprojects:read, tasks:create, tasks:read
Viewerprojects:read, tasks:read

Keep headers short and permissions focused. Expand this table to match your product.

You can register roles and permissions from the Scalekit dashboard:

    • Go to User management → Permissions
    • Create granular permissions like projects:create, tasks:read, billing:manage
    • Think about your app’s resources and actions when defining permissions
    • Use consistent naming patterns: resource:action (e.g., projects:create, projects:read, projects:update, projects:delete)

    • Go to Authorization → Roles
    • Click + Add role and provide:
      • Display name: Human-readable name (e.g., “Project Owner”)
      • Name (key): Machine-friendly identifier (e.g., project_owner)
      • Description: Clear explanation of what users with this role can do
    • Use short, machine-friendly keys for the Name field

  1. Understand role inheritance Optional

    Section titled “Understand role inheritance ”

    Role inheritance lets you build permission hierarchies by having one role inherit all permissions from another role, then adding or removing specific permissions. This approach reduces duplication and makes permission management more maintainable.

    How inheritance works:

    • A role automatically gets all permissions from its base role
    • You can then add new permissions specific to the inheriting role
    • You can also remove specific permissions if needed
    • Changes to the base role automatically propagate to all inheriting roles

    Example hierarchy:

    viewer (base role)
    ├── projects:read
    ├── tasks:read
    └── comments:read
    editor (inherits from viewer)
    ├── [inherits all viewer permissions]
    ├── projects:write
    ├── tasks:create
    └── tasks:write
    project_owner (inherits from editor)
    ├── [inherits all editor permissions]
    ├── projects:create
    └── members:invite
    admin (inherits from project_owner)
    ├── [inherits all project_owner permissions]
    ├── org:manage
    ├── billing:manage
    └── members:manage

    Benefits of inheritance:

    • Easier maintenance: Update permissions in one place and they automatically apply to all inheriting roles
    • Consistent access levels: Ensures users with higher roles always have at least the same access as base roles
    • Reduced duplication: No need to repeatedly assign the same permissions to multiple roles
    • Logical structure: Clear progression from basic access to full administrative capabilities

    • Assign the permissions you created to each role
    • Consider using inheritance to build permission sets efficiently
    • Test your permission model to ensure users have appropriate access levels
    • Document your permission structure for your development team
    • Confirm default role for the environment creator is creator
    • Confirm default role for new members is member
    • You can change these defaults at any time in Authorization → Roles

Organization specific roles allow your organization administrators to create roles that go beyond the roles your application can assign.

For example, an organization administrator wants to create a role that allows users to create and manage projects. While this is covered by the project_owner role, the organization administrator may want to create a role that allows users to create and manage projects and also manage users.

You can go ahead and create organization specific roles from the Scalekit dashboard:

  • Go to Organizations → Select an organization → Roles
  • In Custom Role section, Click + Add role and provide:
    • Display name: Human-readable name (e.g., “Project Owner”)
    • Name (key): Machine-friendly identifier (e.g., project_owner)
    • Description: Clear explanation of what users with this role can do
Create organization role
curl 'https://$SCALEKIT_ENVIRONMENT_URL/api/v1/organizations/{org_id}/roles' \
--request POST \
--header 'Content-Type: application/json' \
--data '{
"description": "Organization Viewer Role will be used only for viewing the objects",
"display_name": "Organization Viewer Role",
"extends": "admin_role",
"name": "org_viewer_role",
"permissions": [
"read:users",
"write:documents"
]
}'

View full API reference

When your app is integrated with Full Stack Auth and a user signs in, Scalekit issues an access token and a refresh token, and creates a session to track access duration.

Token claim availability:

  • Access token: Contains both roles and permissions claims
  • ID token: Contains only the roles claim

The roles claim contains the role name (not the display name). For example, if the role name is editor and the display name is “Content Editor,” the token includes "editor".

The permissions claim contains the permission name (not the description). For example, if the permission name is projects:create and the description is “Create new projects,” the token includes "projects:create".

Here’s an example of decoded tokens containing roles and permissions claims:

idToken.json
{
"amr": ["conn_123456789012345678"],
"aud": ["skc_987654321098765432"],
"azp": "skc_987654321098765432",
"client_id": "skc_987654321098765432",
"email": "john.doe@example.com",
"email_verified": true,
"exp": 1753441845,
"family_name": "Doe",
"given_name": "John",
"iat": 1750849845,
"iss": "http://example.localhost:8889",
"name": "John Doe",
"oid": "org_987654321098765432",
"roles": ["member"],
"sid": "ses_987654321098765432",
"sub": "usr_987654321098765432"
}

With roles and permissions available in tokens, enforce access in your backend and UI. Example checks:

// Example: check role
const isProjectOwner = token.roles?.includes('project_owner');
// Example: check permission
const canCreateProject = token.permissions?.includes('projects:create');