If you wish to learn more about Tenants in general, visit our section on Tenant Management .
The Descope service supports multi-tenancy architecture natively. Each project can have multiple tenants, and the end-users can be assigned to either the project or can belong to one or many tenants.
The most common use case of tenants is when you are building a B2B application, and each of your customers can have multiple users. You must manage these users and their roles at a tenant level.
Descope admins can create and update tenants either manually in the Descope console or using the tenant management API and sdk from within their application as show below.
NodeJS Python Go Java Ruby
npm i --save @descope/node-sdk
NodeJS Python Go Java Ruby
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
Use the code below to load all existing tenants within the project
NodeJS Python Go Java
let resp = await descopeClient.management.tenant. loadAll ();
if ( ! resp.ok) {
console. log ( "Unable to load tenants." )
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 tenants:" )
console. log (resp.data)
}
This function allows for you to load a specific tenant based on the tenant's ID.
NodeJS Python Go Java
// Args:
// id (String): The ID of the tenant which you want to load
const id = "xxxx"
let resp = await descopeClient.management.tenant. load (id);
if ( ! resp.ok) {
console. log ( "Failed to load tenant." )
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 tenant." )
console. log (resp.data)
}
This function allows for you to search Descope tenants by ID, name, self service provisioning domain,
and custom attributes.
NodeJS Python Go Java
// Args:
// ids (String[]): Array of tenant IDs to search for.
const ids = [ "TestTenant" ]
// names (String[]): Array of tenant names to search for.
const names = [ "TestTenant" ]
// selfProvisioningDomains (String[]): Array of self service provisioning domains to search for.
const selfProvisioningDomains = [ "example.com" , "company.com" ]
// customAttributes (String[]): Array of self service provisioning domains to search for.
const customAttributes = { "mycustomattribute" : "Test" }
// When searching based on one of these items or a few of these items, leave the applicable items you are not searching for to null.
let resp = await descopeClient.management.tenant. searchAll (ids, names, selfProvisioningDomains, customAttributes);
if ( ! resp.ok) {
console. log ( "Failed to search tenants." )
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 tenants." )
resp.data. forEach (( tenant ) => {
console. log (tenant)
});
}
At the time of creation, the tenant must be given a name and a tenant-id. If you don't provide a tenant-id, a tenant-id is automatically generated. The tenant-id is used for sign-up/sign-in and other management
operations later. In addition, you can also set domains for the tenant. The domain is used to automatically assign the end-user to a tenant at the time of sign-up and sign-in. The tenant name must be unique per
project. The tenant ID is generated automatically for the tenant when not provided.
NodeJS Python Go Java
// There are two ways to create a tenant via SDK. createWithId (which will assign the given id) and create (which will automatically generate the id). Examples below:
// createWithId: Create a new tenant with a given name and tenant id.
// ==================================================================
// Args:
// name (str): The tenant's name
var name = "TestTenantCreateWithId"
// id (str): The tenant's id.
var id = "TestConfiguredId"
// selfProvisioningDomains (List[str]): An optional list of domains that are associated with this tenant. Users authenticating from these domains will be associated with this tenant.
var selfProvisioningDomains = [ "TestDomain1.com" , "TestDomain2.com" ]
// customAttributes (dict): Optional, set the different custom attributes values of the keys that were previously configured in Descope console app
const customAttributes = { "attribute1" : "Value 1" , "attribute2" : "Value 2" }
let resp = await descopeClient.management.tenant. createWithId (id, name, selfProvisioningDomains, customAttributes)
if ( ! resp.ok) {
console. log (resp)
console. log ( "Unable to create tenant." )
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 tenant." )
console. log (resp.data)
}
// Create: Create a new tenant with the given name. The id will be automatically generated and returned.
// ==================================================================
// Args:
// name (str): The tenant's name
name = "TestTenantCreateGeneratedId"
// selfProvisioningDomains (List[str]): An optional list of domains that are associated with this tenant. Users authenticating from these domains will be associated with this tenant.
selfProvisioningDomains = [ "TestDomain3.com" , "TestDomain4.com" ]
// customAttributes (dict): Optional, set the different custom attributes values of the keys that were previously configured in Descope console app
const customAttributes = { "attribute1" : "Value 1" , "attribute2" : "Value 2" }
resp = await descopeClient.management.tenant. create (name, selfProvisioningDomains, customAttributes)
if ( ! resp.ok) {
console. log ( "Unable to create tenant." )
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 tenant." )
console. log (resp.data)
}
Use the code below to update an existing tenant with the given name and domains. All parameters are used as overrides to the existing tenant. Empty fields will override populated fields.
NodeJS Python Go Java
// Args:
// id (str): The tenant's id.
var id = "xxxxxx"
// name (str): The tenant's name
var name = "Test Updated Name"
// selfProvisioningDomains (List[str]): An optional list of domains that are associated with this tenant. Users authenticating from these domains will be associated with this tenant. If changed, it will be the new list of self provisioned domains.
var selfProvisioningDomains = [ "TestUpdatedDomain1.com" , "TestUpdatedDomain2.com" ]
// customAttributes (dict): Optional, set the different custom attributes values of the keys that were previously configured in Descope console app
const customAttributes = { "attribute1" : "Value 1" , "attribute2" : "Value 2" }
const resp = await descopeClient.management.tenant. update (id, name, selfProvisioningDomains, customAttributes);
if ( ! resp.ok) {
console. log (resp)
console. log ( "Failed to update tenant." )
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 update tenant." )
console. log (resp.data)
}
Use the code below to delete an existing tenant. Please note that this action is irreversible.
NodeJS Python Go Java
// Args:
// id (str): The tenant's id.
var id = "xxxxxx"
// cascade (boolean): Pass true to cascade value, in case you want to delete all users/keys associated only with this tenant
var cascade = false
let resp = await descopeClient.management.tenant. delete (id, cascade);
if ( ! resp.ok) {
console. log (resp)
console. log ( "Unable to delete tenant." )
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 tenant." )
console. log (resp.data)
}
Use the code below to update password policy for your tenant.
NodeJS Go Ruby
// Args:
//tenantId (str): The tenant Id whose password policy has to be updated.
//enabled (boolean): To enable
//minLength (int) : minimum passwords length
//lowercase (boolean): Requires atleast one lowercase letter
//uppercase (boolean): Requires atleast one uppercase letter
//number (boolean): Requires atleast one number
//nonAlphaNumeric (boolean) : Requies at least one non-alphanumeric character
//expiration (boolean): Enable password expiration
//expirationWeeks (int): Password expiration period in weeks
//reuse (boolean): Enable/Disable prevent password reuse
//reuseAmount (int): Number of passwords to remember
//lock (boolean) : Enable/Disable account locking
//lockAttempts (int) : Lock account after this number of attempts
const tenantId = "xxxx"
const policysetting = {
enabled: true ,
minLength: 8 ,
expiration: true ,
expirationWeeks: 4 ,
lock: true ,
lockAttempts: 5 ,
reuse: true ,
reuseAmount: 6 ,
lowercase: true ,
uppercase: false ,
number: true ,
nonAlphaNumeric: false ,
}
const resp = await descopeClient.management.password. configureSettings (tenantId, policysetting);
if ( ! resp.ok) {
console. log ( "Failed to update access key." )
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 password policy." )
console. log (resp.data)
}