Initial Setup
Learn how to initialize and configure user roles with SuperTokens.
Add roles, permissions, and protected routes.
Add SuperTokens roles and permissions to this application. Inspect the existing backend, frontend, session configuration, and tenant model first. Define roles and permissions that match the application’s resources, initialize the UserRoles recipe, assign roles to users, and protect backend and frontend routes. Check whether role data should be included in access tokens, preserve existing authorization conventions, and validate authorized, unauthorized, and cross-tenant access.
Overview
When you work with the UserRoles recipe you should follow these steps:
Create a role and assign permissions to it
Assign roles to users
Protect frontend and backend routes by verifying that the user has the correct role and permissions
The next sections show you the actual instructions on how to achieve this.
Before you start
Steps
1. Initialize the recipe
import SuperTokens from "supertokens-node";
import UserRoles from "supertokens-node/recipe/userroles";
SuperTokens.init({
supertokens: {
connectionURI: "...",
},
appInfo: {
apiDomain: "...",
appName: "...",
websiteDomain: "...",
},
recipeList: [UserRoles.init()],
});import (
"github.com/supertokens/supertokens-golang/recipe/userroles"
"github.com/supertokens/supertokens-golang/supertokens"
)
func main() {
supertokens.Init(supertokens.TypeInput{
RecipeList: []supertokens.Recipe{
userroles.Init(nil),
},
})
}from supertokens_python import InputAppInfo, init
from supertokens_python.recipe import userroles
init(
app_info=InputAppInfo(
api_domain="...", app_name="...", website_domain="..."
),
framework='...',
recipe_list=[
# Initialize other recipes as seen in the quick setup guide
userroles.init()
]
)By default, the user roles recipe adds the roles and permission information into a user’s session (if they have assigned roles & permissions). If you do not want roles or permissions information in the session, or want to manually add it yourself, you can provide the following input configs to the UserRoles.init function:
import UserRoles from "supertokens-node/recipe/userroles";
UserRoles.init({
skipAddingRolesToAccessToken: true,
skipAddingPermissionsToAccessToken: true,
});import (
"github.com/supertokens/supertokens-golang/recipe/userroles"
"github.com/supertokens/supertokens-golang/recipe/userroles/userrolesmodels"
"github.com/supertokens/supertokens-golang/supertokens"
)
func main() {
supertokens.Init(supertokens.TypeInput{
AppInfo: supertokens.AppInfo{ /*...*/ },
RecipeList: []supertokens.Recipe{
userroles.Init(&userrolesmodels.TypeInput{
SkipAddingRolesToAccessToken: true,
SkipAddingPermissionsToAccessToken: true,
}),
},
})
}from supertokens_python import InputAppInfo, init
from supertokens_python.recipe import userroles
init(
app_info=InputAppInfo(
api_domain="...", app_name="...", website_domain="..."
),
framework='...',
recipe_list=[
userroles.init(skip_adding_roles_to_access_token=True,
skip_adding_permissions_to_access_token=True)
]
)2. Create roles and permissions
Roles and permissions are simple string values. They should represent entities and actions that are relevant to your business logic. To create them use the next code snippet as a reference. When you create a role you can also include the permissions that the role should have.

import UserRoles from "supertokens-node/recipe/userroles";
async function createRole() {
const response = await UserRoles.createNewRoleOrAddPermissions("user", ["read"]);
if (response.createdNewRole === false) {
// The role already exists
}
}import (
"github.com/supertokens/supertokens-golang/recipe/userroles"
)
func createRole() {
resp, err := userroles.CreateNewRoleOrAddPermissions("user", []string{
"read",
}, nil)
if err != nil {
// TODO: Handle error
return
}
if resp.OK.CreatedNewRole == false {
// The role already exists
}
}from supertokens_python.recipe.userroles.asyncio import create_new_role_or_add_permissions
async def create_role():
res = await create_new_role_or_add_permissions("user", ["read"])
if not res.created_new_role:
# The role already existed
passfrom supertokens_python.recipe.userroles.syncio import create_new_role_or_add_permissions
def create_role():
res = create_new_role_or_add_permissions("user", ["read"])
if not res.created_new_role:
# The role already existed
passcurl --location --request PUT '<CORE_API_ENDPOINT>/recipe/role' \
--header 'api-key: <YOUR_API_KEY>' \
--header 'Content-Type: application/json; charset=utf-8' \
--data-raw '{
"role": "user",
"permissions": [
"read"
]
}'3. Assign roles to users
After you create a user account, you can assign roles to them.
You can do this by overriding the authentication recipes with a function that calls the UserRoles API after a successful sign up.
The next code snippet shows you what function to call to connect a user to a role.
To figure out where to call that function, check the documentation for the authentication method that you use: passwordless, email-password or third-party.
import UserRoles from "supertokens-node/recipe/userroles";
async function addRoleToUser(userId: string) {
const response = await UserRoles.addRoleToUser("public", userId, "user");
if (response.status === "UNKNOWN_ROLE_ERROR") {
// No such role exists
return;
}
if (response.didUserAlreadyHaveRole === true) {
// The user already had the role
}
}import (
"github.com/supertokens/supertokens-golang/recipe/userroles"
)
func addRoleToUser(userId string) {
response, err := userroles.AddRoleToUser("public", userId, "user", nil)
if err != nil {
// TODO: Handle error
return
}
if response.UnknownRoleError != nil {
// No such role exists
return
}
if response.OK.DidUserAlreadyHaveRole {
// The user already had the role
}
}from supertokens_python.recipe.userroles.asyncio import add_role_to_user
from supertokens_python.recipe.userroles.interfaces import UnknownRoleError
async def add_role_to_user_func(user_id: str):
role = "user"
res = await add_role_to_user("public", user_id, role)
if isinstance(res, UnknownRoleError):
# No such role exists
return
if res.did_user_already_have_role:
# User already had this role
passfrom supertokens_python.recipe.userroles.syncio import add_role_to_user
from supertokens_python.recipe.userroles.interfaces import UnknownRoleError
def add_role_to_user_func(user_id: str):
role = "user"
res = add_role_to_user("public", user_id, role)
if isinstance(res, UnknownRoleError):
# No such role exists
return
if res.did_user_already_have_role:
# User already had this role
passcurl --location --request PUT 'http://localhost:3567/recipe/user/role' \
--header 'api-key: <YOUR_API_KEY>' \
--header 'Content-Type: application/json; charset=utf-8' \
--data-raw '{
"userId": "fa7a0841-b533-4478-95533-0fde890c3483",
"role": "user"
}'Assign roles to a session
If you want to associate a role to a user after you create a session, you can do this by manually calling the function described in the next code snippet.
For information on how to access the session object that you need to pass to the function, check either the Verify Session or the Get Session documentation.
import { UserRoleClaim, PermissionClaim } from "supertokens-node/recipe/userroles";
import { SessionContainer } from "supertokens-node/recipe/session";
async function addRolesAndPermissionsToSession(session: SessionContainer) {
// we add the user's roles to the user's session
await session.fetchAndSetClaim(UserRoleClaim);
// we add the permissions of a user to the user's session
await session.fetchAndSetClaim(PermissionClaim);
}import (
"github.com/supertokens/supertokens-golang/recipe/session/sessmodels"
"github.com/supertokens/supertokens-golang/recipe/userroles/userrolesclaims"
)
func addRolesAndPermissionsToSession(session sessmodels.SessionContainer) error {
// we add the user's roles to the user's session
err := session.FetchAndSetClaim(userrolesclaims.UserRoleClaim)
if err != nil {
return err
}
// we add the user's permissions to the user's session
err = session.FetchAndSetClaim(userrolesclaims.PermissionClaim)
if err != nil {
return err
}
return nil
}from supertokens_python.recipe.session import SessionContainer
from supertokens_python.recipe.userroles import UserRoleClaim, PermissionClaim
async def add_roles_and_permissions_to_session(session: SessionContainer):
# we add the user's roles to the user's session
await session.fetch_and_set_claim(UserRoleClaim)
# we add the user's permissions to the user's session
await session.fetch_and_set_claim(PermissionClaim)from supertokens_python.recipe.session import SessionContainer
from supertokens_python.recipe.userroles import UserRoleClaim, PermissionClaim
def add_roles_and_permissions_to_session(session: SessionContainer):
# we add the user's roles to the user's session
session.sync_fetch_and_set_claim(UserRoleClaim)
# we add the user's permissions to the user's session
session.sync_fetch_and_set_claim(PermissionClaim)