Role-Based Access Control

Roles and Permissions

Descope allows you to assign roles and permissions to the application's end user. Users with Descope admin privileges can define roles and permissions in the Descope console. Permissions and roles are represented as strings in Descope. Your application must do the interpretation and enforcement of the roles and permissions.

Permission Creation

Permissions are used within roles. Within the Permissions tab of the console, under Authorization you can create and manage your permissions. Clicking the + Permission Button at the top right allows you to create the permission. You can also click the three dots to the right of the permission to delete the permission or change it's description.

Descope permissions page shown as an example

Role Creation

Within the Roles tab of the console, under Authorization you can create and manage your roles. Clicking the + Role Button at the top right allows you to create the role. You can also click the three dots to the right of the role to delete the role, change it's description, or add permissions to the role.

Descope roles page shown as an example

Configuring User's Roles

Each user that is created in your application (during sign-up) can be assigned roles and permissions. The user can get more than one role and will include the role's associated permissions. The assignment of roles and permissions can be done manually (not recommended) using the console, using the management SDK (sample code below), or can be automatically mapped if you use SSO (SAML) as the authentication method for your application.

You can edit and add roles to users within the Users page.

Descope editing user roles example

Tenants and Roles

Roles have two main types, Tenant and Project. Every role that's configured in a specific project, will either be specific to a Tenant or the entire Project, depending on this type. When you create roles you have the option to assign them to a specific tenant with the respective Tenant ID, shown in the docs below.

If you are using tenants for user management, then the same user can be assigned different roles and permissions for each tenant (if you so desire). These can be automatically assigned using SSO Configuration too. The Tenant Management section covers the steps to configure roles mapping using SAML.

Descope adding tenants and roles to a user

JWT Example

After successful end-user authentication, the roles and permissions are delivered to your application as part of the JWT token. Below is a sample JWT token that contains roles and permissions with a user logged into a tenant.

{
  "amr": [
    "email"
  ],
  "drn": "DS",
  "exp": 1692304651,
  "iat": 1692304051,
  "iss": "P2RFvFexVaxxNFK6rhP0ePtaGfTK",
  "sub": "U2RG6grrbT3REKYqk5yC4SjkMqzA",
  "tenants": {
    "T2U7vUH1NPy4JzWHruoOVIGyzYlu": {
      "permissions": [
        "AppSecEngineer",
        "Marketing",
        "Support"
      ],
      "roles": [
        "Engineering",
        "Product Manager"
      ]
    },
    "T2U7vVBqyZv6HdGtGLdnkgCbNxrC": {
      "permissions": [
        "AppSecEngineer",
        "Support"
      ],
      "roles": [
        "Support"
      ]
    }
  }
}

Validating Roles and Permissions

Examples of how to validate roles and permissions using the backend SDK are covered in our Session Management articles.

Authorization management using the management SDK

Install SDK

Terminal
npm i --save @descope/node-sdk

Import and initialize Management SDK

import DescopeClient from '@descope/node-sdk';
 
const managementKey = "xxxx"
 
try{
    //  baseUrl="<URL>" // When initializing the Descope clientyou can also configure the baseUrl ex: https://auth.company.com  - this is useful when you utilize CNAME within your Descope project.
    const descopeClient = DescopeClient({ projectId: '__ProjectID__', managementKey: managementKey });
} catch (error) {
    // handle the error
    console.log("failed to initialize: " + error)
}
 
// Note that you can handle async operation failures and capture specific errors to customize errors.
//     An example can be found here: https://github.com/descope/node-sdk?tab=readme-ov-file#error-handling

Load All Permissions

This Descope SDK allows administrators to return all details for permissions configured within the Descope instance. The response includes an array of permissions and the details of each permission.

const resp = await descopeClient.management.permission.loadAll()
if (!resp.ok) {
  console.log("Failed to load permissions.")
  console.log("Status Code: " + resp.code)
  console.log("Error Code: " + resp.error.errorCode)
  console.log("Error Description: " + resp.error.errorDescription)
  console.log("Error Message: " + resp.error.errorMessage)
}
else {
  console.log("Successfully loaded permissions.")
  console.log(resp.data)
}

Create a Permissions

This Descope SDK allows administrators to create a new permission.

// Args:
// 		name (str): permission name.
const name = "Test Permission"
// 		description (str): Optional description to briefly explain what this permission allows.
const description = "My description"
 
const resp = await descopeClient.management.permission.create(name, description)
if (!resp.ok) {
  console.log("Failed to create permission.")
  console.log("Status Code: " + resp.code)
  console.log("Error Code: " + resp.error.errorCode)
  console.log("Error Description: " + resp.error.errorDescription)
  console.log("Error Message: " + resp.error.errorMessage)
}
else {
  console.log("Successfully created permission.")
}

Update a Permissions

This Descope SDK allows administrators to update an existing permission with the given various fields. It is important to note that parameters are used as overrides to the existing permission; empty fields will override populated fields.

// Args:
// 		name (str): permission name.
const name = "Test Permission"
// 		newName (str): permission updated name.
const newName = "Updated Test Permission"
// 		description (str): Optional description to briefly explain what this permission allows.
const description = "My updated description"
 
const resp = await descopeClient.management.permission.update(name, newName, description)
if (!resp.ok) {
  console.log("Failed to update permission.")
  console.log("Status Code: " + resp.code)
  console.log("Error Code: " + resp.error.errorCode)
  console.log("Error Description: " + resp.error.errorDescription)
  console.log("Error Message: " + resp.error.errorMessage)
}
else {
  console.log("Successfully updated permission.")
}

Delete a Permissions

This Descope SDK allows administrators to delete an existing permission. It is important to note that this action is irreversible.

// Args:
// 		name (str): The name of the permission to be deleted.
const name = "Updated Test Permission"
 
const resp = await descopeClient.management.permission.delete(name)
if (!resp.ok) {
  console.log("Failed to delete permission.")
  console.log("Status Code: " + resp.code)
  console.log("Error Code: " + resp.error.errorCode)
  console.log("Error Description: " + resp.error.errorDescription)
  console.log("Error Message: " + resp.error.errorMessage)
}
else {
  console.log("Successfully deleted permission.")
}

Load All Roles

This Descope SDK allows administrators to return all details for roles configured within the Descope instance. The response includes an array of roles and the details of each role.

const resp = await descopeClient.management.role.loadAll()
if (!resp.ok) {
  console.log("Failed to load roles.")
  console.log("Status Code: " + resp.code)
  console.log("Error Code: " + resp.error.errorCode)
  console.log("Error Description: " + resp.error.errorDescription)
  console.log("Error Message: " + resp.error.errorMessage)
}
else {
  console.log("Successfully loaded roles.")
  console.log(resp.data)
}

Search for Roles

This Descope SDK allows administrators to return specific roles configured within the Descope instance using several parameters. The response includes an array of roles and the details of each role.

// Args:
//    tenant_ids (List[str]): List of tenant ids to filter by
const tenant_ids = ["Tenant ID"]
//    role_names (List[str]): Only return matching roles to the given names
const role_names = ["Role name"]
//    role_name_like (str): Return roles that contain the given string ignoring case
const role_name_like = "string in role"
//    permission_names (List[str]): Only return roles that have the given permissions
const permission_names = ["TestPermission"]
 
const resp = await descopeClient.management.role.search(tenant_ids, role_names, role_name_like, permission_names)
if (!resp.ok) {
  console.log("Failed to Search for roles.")
  console.log("Status Code: " + resp.code)
  console.log("Error Code: " + resp.error.errorCode)
  console.log("Error Description: " + resp.error.errorDescription)
  console.log("Error Message: " + resp.error.errorMessage)
}
else {
  console.log("Successfully searched for roles.")
  console.log(resp.data)
}

Create a Role

This Descope SDK allows administrators to create a new role.

// Args:
//    name (str): role name.
const name = "My Test Role"
// description (str): Optional description to briefly explain what this role allows.
const description = "My Role Description"
// permissionNames (List[str]): Optional list of names of permissions this role grants.
const permissionNames = ["TestPermission"]
//    tenantId (str): Optional Tenant ID to assign new role to specific tenant
const tenantId = "Tenant ID"
 
const resp = await descopeClient.management.role.create(name, description, permissionNames, tenantId)
if (!resp.ok) {
  console.log("Failed to create role.")
  console.log("Status Code: " + resp.code)
  console.log("Error Code: " + resp.error.errorCode)
  console.log("Error Description: " + resp.error.errorDescription)
  console.log("Error Message: " + resp.error.errorMessage)
}
else {
  console.log("Successfully created role.")
}

Update a Role

This Descope SDK allows administrators to update an existing role with the given various fields. It is important to note that parameters are used as overrides to the existing role; empty fields will override populated fields.

// Args:
//    name (str): role name.
const name = "My Test Role"
//    newName (str): role updated name.
const newName = "My Updated Test Role"
//    description (str): Optional description to briefly explain what this role allows.
const description = "My Updated Role Description"
//    permissionNames (List[str]): Optional list of names of permissions this role grants.
const permissionNames = ["TestPermission", "TestPermission2"]
//    tenantId (str): Optional Tenant ID to assign new role to specific tenant
const tenantId = "Tenant ID"
 
const resp = await descopeClient.management.role.update(name, newName, description, permissionNames, tenantId)
if (!resp.ok) {
  console.log("Failed to update role.")
  console.log("Status Code: " + resp.code)
  console.log("Error Code: " + resp.error.errorCode)
  console.log("Error Description: " + resp.error.errorDescription)
  console.log("Error Message: " + resp.error.errorMessage)
}
else {
  console.log("Successfully updated role.")
}

Delete a Role

This Descope SDK allows administrators to delete an existing role. It is important to note that this action is irreversible.

// Args:
//    name (str): The name of the role to be deleted.
const name = "My Updated Test Role"
//    tenantId (str): Optional Tenant ID to assign new role to specific tenant
const tenantId = "Tenant ID"
 
const resp = await descopeClient.management.role.delete(name, tenantId)
if (!resp.ok) {
  console.log("Failed to delete role.")
  console.log("Status Code: " + resp.code)
  console.log("Error Code: " + resp.error.errorCode)
  console.log("Error Description: " + resp.error.errorDescription)
  console.log("Error Message: " + resp.error.errorMessage)
}
else {
  console.log("Successfully deleted role.")
}
Was this helpful?

On this page