If you're using SSO with your Descope tenants, and you want to develop backend APIs to handle this process, this guide covers what you need to know. These are all of the SDK functions you can use in your backend to manage SSO for your tenants.
If you want to use SSO for your application with multiple IdPs, you must configure SSO for each tenant independently. These settings can be configured either via the Descope Console , our self-service sso provisioning widget , our APIs , or using the SDK as shown 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
You can either set the identity provider details using a metadata URL from the IdP or enter them in the console. The values for each field can be obtained from the admin console of the identity provider.
NodeJS Python Go Java
// Configure SSO setting for a tenant manually. Alternatively, `configure_via_metadata` can be used instead.
// Args:
// tenantId (str): The tenant ID to be configured
const tenantId = "xxxxxx"
// idpURL (str): The URL for the identity provider.
const idpURL = "https://example_idpURL.com"
// entityId (str): The entity ID (in the IDP).
const entityId = "descope"
// idpCert (str): The certificate provided by the IDP.
const idpCert = "xxxxxx"
// redirectURL (str): An Optional Redirect URL after successful authentication.
const redirectURL = "https://example_descope_app.com/saml"
// domain (str): An optional domain used to associate users authenticating via SSO with this tenant
const domain = "example_descope_app.com"
let resp = await descopeClient.management.sso. configureSettings (tenantId, idpURL, idpCert, entityId, redirectURL, domain)
if ( ! resp.ok) {
console. log ( "Unable to configure tenant sso." )
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 configured sso configuration for tenant manually." )
console. log (resp.data)
}
// Configure SSO setting for am IDP metadata URL. Alternatively, `configure` can be used instead.
// Args:
// tenantId (str): The tenant ID to be configured
const tenantId = "xxxxxx"
// idpMetadataURL (str): The URL to fetch SSO settings from.
const idpMetadataURL = "https://example_idpURL.com/api/v1/apps/xxxxxxx/sso/saml/metadata?"
// redirectURL (str): An Optional Redirect URL after successful authentication.
const redirectURL = "https://example_descope_app.com/saml"
// domain (str): An optional domain used to associate users authenticating via SSO with this tenant
const domain = "example_descope_app.com"
let resp = await descopeClient.management.sso. configureMetadata (tenantId, idpMetadataURL, redirectURL, domain)
if ( ! resp.ok) {
console. log ( "Unable to configure tenant sso." )
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 configured sso configuration for tenant via metadata url." )
console. log (resp.data)
}
Descope allows you to delete the SSO config for a specified tenant. Use caution with this SDK call as it will remove the configuration and is irreversible.
NodeJS Python Go Java
// Args:
// tenantId (str): The tenant ID to get the SSO configuration from.
const tenantId = "xxxxxx"
let resp = await descopeClient.management.sso. getSettings (tenantId)
if ( ! resp.ok) {
console. log ( "Unable to receive the sso configuration from 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 received sso configuration from tenant." )
console. log (resp.data)
}
Descope allows you to delete the SSO config for a specified tenant. Use caution with this SDK call as it will remove the configuration and is irreversible.
NodeJS Python Go Java
// Args:
// tenantId (str): The tenant ID to delete the SSO configuration from.
const tenantId = "xxxxxx"
let resp = await descopeClient.management.sso. deleteSettings (tenantId)
if ( ! resp.ok) {
console. log ( "Unable to delete the sso configuration from 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 sso configuration from tenant." )
}
In this section of the console, you can setup mapping for user attributes. After you set up the mapping, each
user that signs into your application will get these attributes assigned from the IdP.
Note
Descope also allows you to map attributes from your IdP to
custom user attributes when configuring your attribute mapping.
In this part of SSO configuration, you can map SSO groups from your IdP to roles defined in Descope service. The group-to-role mapping will automatically populate the user's roles at the time of
sign-in. The roles are included in the session token after successful authentication. It is important to note, this function overrides any previous mapping (even when empty).
NodeJS Python Go Java
// Args:
// tenantId (str): The tenant ID to be configured
const tenantId = "xxxxxx"
// roleMappings (RoleMapping): A mapping between IDP groups and Descope roles.
const roleMapping = { groups: [ 'IDP_ADMIN' ], roleName: 'Tenant Admin' }
// attributeMapping (AttributeMapping): A mapping between IDP user attributes and descope attributes.
const attributeMapping = {name: "IDP_NAME" , phoneNumber: "IDP_PHONE" ,}
let resp = await descopeClient.management.sso. configureMapping (tenantId, roleMapping, attributeMapping)
if ( ! resp.ok) {
console. log ( "Unable to configured sso role and attribute mapping." )
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 configured sso role and attribute mapping." )
}
The Descope SDKs make the SSO Groups available for being loaded. The below covers the available functions.
Descopers can load all groups for a given tenant, the below covers examples of this.
NodeJS Python Go Java
// Args:
// tenantId (str): Tenant ID to load groups from.
const tenantId = "xxxxx"
const resp = await descopeClient.management.group. loadAllGroups (tenantId)
if ( ! resp.ok) {
console. log (resp)
console. log ( "Unable to load all groups." )
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 all groups." )
console. log (resp.data)
}
Descopers can load all groups for members based on login IDs and user IDs, the below covers examples of this.
NodeJS Python Go Java
// Args:
// tenantId (str): Tenant ID to load groups from.
const tenantId = "xxxxx"
// userIDs (List[str]): Optional List of user IDs, with the format of "U2J5ES9S8TkvCgOvcrkpzUgVTEBM" (example), which can be found on the user's JWT.
const userIds = []
// loginIDs (List[str]): Optional List of login IDs, how the users identify when logging in.
const loginIds = []
const resp = await descopeClient.management.group. loadAllGroupsForMembers (tenantId, userIds, loginIds)
if ( ! resp.ok) {
console. log (resp)
console. log ( "Unable to load all groups for members." )
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 all groups for members." )
console. log (resp.data)
}
Descopers can load all groups members based on tenant ID and group ID, the below covers examples of this.
NodeJS Python Go Java
// Args:
// tenantId (str): Tenant ID to load groups from.
const tenantId = "xxxxx"
// groupId (str): Group ID to load members for.
const groupId = "xxxx"
const res = await descopeClient.management.group. loadAllGroupMembers (tenantId, groupId)
if ( ! resp.ok) {
console. log (resp)
console. log ( "Unable to load all group members." )
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 all group members." )
console. log (resp.data)
}