Descope SDK for Node.js
The Descope SDK for Node.js provides convenient access to the Descope user management and authentication API
for a backend written in Node.js. You can read more on the Descope Website.
Requirements
The SDK supports Node version 14 and above.
Installing the SDK
Install the package with:
npm i --save @descope/node-sdk
Authentication Functions
Setup
Before you can use authentication functions listed below, you must initialize descopeClient
to use all of the built-in SDK functions.
You'll need your Descope Project ID
to create this, and you can find it on the project page in the Descope Console.
import DescopeClient from '@descope/node-sdk';
const descopeClient = DescopeClient({ projectId: 'my-project-ID' });
Once you've created a descopeClient
, you can use that to work with the following functions:
- OTP Authentication
- Magic Link
- Enchanted Link
- OAuth
- SSO/SAML
- TOTP Authentication
- Passwords
- Session Validation
- Roles & Permission Validation
- Logging Out
Management Functions
Setup
Before you can use management functions listed below, you must initialize descopeClient
.
If you wish to also use management functions, you will need to initialize a new version of your descopeClient
, but this time with a ManagementKey
as well as your Project ID
. Create a management key in the Descope Console.
import DescopeClient from '@descope/node-sdk';
const descopeClient = DescopeClient({
projectId: 'my-project-ID',
managementKey: 'management-key',
});
Then, you can use that to work with the following functions:
- Manage Tenants
- Manage Users
- Manage Access Keys
- Manage SSO Setting
- Manage Permissions
- Manage Roles
- Query SSO Groups
- Manage Flows
- Manage JWTs
- Impersonate
- Embedded Links
- Audit
- Manage FGA (Fine-grained Authorization)
- Manage Project
- Manage SSO applications
If you wish to run any of our code samples and play with them, check out our Code Examples section.
If you're performing end-to-end testing, check out the Utils for your end to end (e2e) tests and integration tests section. You will need to use the descopeClient
you created under the setup of Management Functions.
Error Handling
Every async
operation may fail. In case it does, there will be information regarding what happened on the response object.
A typical case of error handling might look something like:
import { SdkResponse, descopeErrors } from '@descope/node-sdk';
try {
const resp = await sdk.otp.signIn.email(loginId);
if (resp.error) {
switch (resp.error.errorCode) {
case descopeErrors.userNotFound:
break;
default:
}
}
} catch (e) {
}
OTP Authentication
Send a user a one-time password (OTP) using your preferred delivery method (Email / SMS / Voice call / WhatsApp). An email address or phone number must be provided accordingly.
The user can either sign up
, sign in
or sign up or in
const loginId = 'desmond@descope.com';
const user = {
name: 'Desmond Copland',
phone: '212-555-1234',
email: loginId,
};
await descopeClient.otp.signUp['email'](loginId, user);
The user will receive a code using the selected delivery method. Verify that code using:
const jwtResponse = await descopeClient.otp.verify['email'](loginId, 'code');
The session and refresh JWTs should be returned to the caller, and passed with every request in the session. Read more on session validation
Magic Link
Send a user a Magic Link using your preferred delivery method (email / SMS).
The Magic Link will redirect the user to page where the its token needs to be verified.
This redirection can be configured in code, or globally in the Descope Console
The user can either sign up
, sign in
or sign up or in
const URI = 'http://myapp.com/verify-magic-link';
await descopeClient.magicLink.signUpOrIn['email']('desmond@descope.com', URI);
To verify a magic link, your redirect page must call the validation function on the token (t
) parameter (https://your-redirect-address.com/verify?t=<token>
):
const jwtResponse = await descopeClient.magicLink.verify('token');
The session and refresh JWTs should be returned to the caller, and passed with every request in the session. Read more on session validation
Enchanted Link
Using the Enchanted Link APIs enables users to sign in by clicking a link
delivered to their email address. The email will include 3 different links,
and the user will have to click the right one, based on the 2-digit number that is
displayed when initiating the authentication process.
This method is similar to Magic Link but differs in two major ways:
- The user must choose the correct link out of the three, instead of having just one
single link.
- This supports cross-device clicking, meaning the user can try to log in on one device,
like a computer, while clicking the link on another device, for instance a mobile phone.
The Enchanted Link will redirect the user to page where the its token needs to be verified.
This redirection can be configured in code per request, or set globally in the Descope Console.
The user can either sign up
, sign in
or sign up or in
const URI = 'http://myapp.com/verify-enchanted-link';
const enchantedLinkRes = await descopeClient.enchantedLink.signIn('desmond@descope.com', URI);
enchantedLinkRes.data.linkId;
enchantedLinkRes.data.pendingRef;
After sending the link, you must poll to receive a valid session using the pendingRef
from
the previous step. A valid session will be returned only after the user clicks the right link.
const jwtResponse = await descopeClient.enchantedLink.waitForSession(
enchantedLinkRes.data.pendingRef,
);
To verify an enchanted link, your redirect page must call the validation function on the token (t
) parameter (https://your-redirect-address.com/verify?t=<token>
). Once the token is verified, the session polling will receive a valid response.
try {
await descopeClient.enchantedLink.verify('token');
} catch (error) {
}
The session and refresh JWTs should be returned to the caller, and passed with every request in the session. Read more on session validation
OAuth
Users can authenticate using their social logins, via the OAuth protocol. Configure your OAuth settings on the Descope console. To start an OAuth flow call:
const urlRes = await descopeClient.oauth.start['google'](redirectUrl);
urlRes.data.url;
The user will authenticate with the authentication provider, and will be redirected back to the redirect URL, with an appended code
HTTP URL parameter. Exchange it to validate the user:
const jwtResponse = await descopeClient.oauth.exchange('token');
The session and refresh JWTs should be returned to the caller, and passed with every request in the session. Read more on session validation
SSO/SAML
Users can authenticate to a specific tenant using SAML or Single Sign On. Configure your SSO/SAML settings on the Descope console. To start a flow call:
const redirectUrl = 'https://my-app.com/handle-saml';
const urlRes = await descopeClient.saml.start('tenant');
urlRes.data.url;
The user will authenticate with the authentication provider configured for that tenant, and will be redirected back to the redirect URL, with an appended code
HTTP URL parameter. Exchange it to validate the user:
const jwtResponse = await descopeClient.saml.exchange('token');
The session and refresh JWTs should be returned to the caller, and passed with every request in the session. Read more on session validation
TOTP Authentication
The user can authenticate using an authenticator app, such as Google Authenticator.
Sign up like you would using any other authentication method. The sign up response
will then contain a QR code image
that can be displayed to the user to scan using
their mobile device camera app, or the user can enter the key
manually or click
on the link provided by the provisioningURL
.
Existing users can add TOTP using the update
function.
const loginId = 'desmond@descope.com';
const user = {
name: 'Desmond Copland',
phone: '212-555-1234',
email: loginId,
};
const totpRes = await descopeClient.totp.signUp(loginId, user);
totpRes.data.provisioningURL;
totpRes.data.image;
totpRes.data.key;
There are 3 different ways to allow the user to save their credentials in
their authenticator app - either by clicking the provisioning URL, scanning the QR
image or inserting the key manually. After that, signing in is done using the code
the app produces.
const jwtResponse = await descopeClient.totp.verify(loginId, 'code');
The session and refresh JWTs should be returned to the caller, and passed with every request in the session. Read more on session validation
Passwords
The user can also authenticate with a password, though it's recommended to
prefer passwordless authentication methods if possible. Sign up requires the
caller to provide a valid password that meets all the requirements configured
for the password authentication method in the Descope console.
const loginId = 'desmond@descope.com';
const password = 'qYlvi65KaX';
const user = {
name: 'Desmond Copeland',
email: loginId,
};
const jwtResponse = await descopeClient.password.signUp(loginId, password, user);
The user can later sign in using the same loginId and password.
const jwtResponse = await descopeClient.password.signIn(loginId, password);
The session and refresh JWTs should be returned to the caller, and passed with every request in the session. Read more on session validation
In case the user needs to update their password, one of two methods are available: Resetting their password or replacing their password
Changing Passwords
NOTE: sendReset will only work if the user has a validated email address. Otherwise password reset prompts cannot be sent.
In the password authentication method in the Descope console, it is possible to define which alternative authentication method can be used in order to authenticate the user, in order to reset and update their password.
const loginId = 'desmond@descope.com';
const redirectURL = 'https://myapp.com/password-reset';
const passwordResetResponse = await descopeClient.password.sendReset(loginId, redirectURL);
The magic link, in this case, must then be verified like any other magic link (see the magic link section for more details). However, after verifying the user, it is expected
to allow them to provide a new password instead of the old one. Since the user is now authenticated, this is possible via:
await descopeClient.password.update(loginId, newPassword, token);
update()
can always be called when the user is authenticated and has a valid session.
Alternatively, it is also possible to replace an existing active password with a new one.
const jwtResponse = await descopeClient.password.replace(loginId, oldPassword, newPassword);
Session Validation
Every secure request performed between your client and server needs to be validated. The client sends
the session and refresh tokens with every request, and they are validated using one of the following:
const authInfo = await descopeClient.validateSession('sessionToken');
const authInfo = await descopeClient.refreshSession('refreshToken');
const authInfo = await descopeClient.validateAndRefreshSession('sessionToken', 'refreshToken');
Choose the right session validation and refresh combination that suits your needs.
Refreshed sessions return the same response as is returned when users first sign up / log in,
containing the session and refresh tokens, as well as all of the JWT claims.
Make sure to return the session token from the response to the client if tokens are validated directly.
Usually, the tokens can be passed in and out via HTTP headers or via a cookie.
The implementation can defer according to your implementation. See our examples for a few examples.
If Roles & Permissions are used, validate them immediately after validating the session. See the next section
for more information.
Session Validation Using Middleware
Alternatively, you can create a simple middleware function that internally uses the validateSession
function.
This middleware will automatically parse the cookies from the request.
On failure, it will respond with 401 Unauthorized
.
const authMiddleware = async (req: Request, res: Response, next: NextFunction) => {
try {
const cookies = parseCookies(req);
const out = await clientAuth.auth.validateSession(
cookies[DescopeClient.SessionTokenCookieName],
cookies[DescopeClient.RefreshTokenCookieName],
);
if (out?.cookies) {
res.set('Set-Cookie', out.cookies);
}
next();
} catch (e) {
res.status(401).json({
error: 'Unauthorized!',
});
}
};
Roles & Permission Validation
When using Roles & Permission, it's important to validate the user has the required
authorization immediately after making sure the session is valid. Taking the AuthenticationInfo
received by the session validation, call the following functions:
For multi-tenant uses:
const validTenantPermissions = descopeClient.validateTenantPermissions(authInfo, 'my-tenant-ID', [
'Permission to validate',
]);
if (!validTenantPermissions) {
}
const validTenantRoles = descopeClient.validateTenantRoles(authInfo, 'my-tenant-ID', [
'Role to validate',
]);
if (!validTenantRoles) {
}
const matchedTenantRoles = descopeClient.getMatchedTenantRoles(authInfo, 'my-tenant-ID', [
'Role to validate',
'Another role to validate',
]);
const matchedTenantPermissions = descopeClient.getMatchedTenantPermissions(
authInfo,
'my-tenant-ID',
['Permission to validate', 'Another permission to validate'],
);
When not using tenants use:
const validPermissions = descopeClient.validatePermissions(authInfo, ['Permission to validate']);
if (!validPermissions) {
}
const validRoles = descopeClient.validateRoles(authInfo, ['Role to validate']);
if (!validRoles) {
}
const matchedRoles = descopeClient.getMatchedRoles(authInfo, [
'Role to validate',
'Another role to validate',
]);
const matchedPermissions = descopeClient.getMatchedPermissions(authInfo, [
'Permission to validate',
'Another permission to validate',
]);
Logging Out
You can log out a user from an active session by providing their refreshToken
for that session.
After calling this function, you must invalidate or remove any cookies you have created.
await descopeClient.logout(refreshToken);
It is also possible to sign the user out of all the devices they are currently signed-in with. Calling logoutAll
will
invalidate all user's refresh tokens. After calling this function, you must invalidate or remove any cookies you have created.
await descopeClient.logoutAll(refreshToken);
Management Functions
It is very common for some form of management or automation to be required. These can be performed
using the management functions. Please note that these actions are more sensitive as they are administrative
in nature. Please use responsibly.
Setup
To use the management API you'll need a Management Key
along with your Project ID
.
Create one in the Descope Console.
import DescopeClient from '@descope/node-sdk';
const descopeClient = DescopeClient({
projectId: 'my-project-ID',
managementKey: 'management-key',
});
Manage Tenants
You can create, update, delete or load tenants, as well as read and update tenant settings:
await descopeClient.management.tenant.create('My Tenant', ['domain.com'], {
customAttributeName: 'val',
});
await descopeClient.management.tenant.createWithId('my-custom-id', 'My Tenant', ['domain.com'], {
customAttributeName: 'val',
});
await descopeClient.management.tenant.update(
'my-custom-id',
'My Tenant',
['domain.com', 'another-domain.com'],
{ customAttributeName: 'val' },
);
await descopeClient.management.tenant.delete('my-custom-id', false);
const tenant = await descopeClient.management.tenant.load('my-custom-id');
const tenantsRes = await descopeClient.management.tenant.loadAll();
tenantsRes.data.forEach((tenant) => {
});
const searchRes = await descopeClient.management.tenant.searchAll(['id']);
searchRes.data.forEach((tenant) => {
});
const tenantSettings = await descopeClient.management.tenant.getSettings('my-tenant-id');
await descopeClient.management.tenant.configureSettings('my-tenant-id', {
domains: ['domain1.com'],
selfProvisioningDomains: ['domain1.com'],
sessionSettingsEnabled: true,
refreshTokenExpiration: 12,
refreshTokenExpirationUnit: 'days',
sessionTokenExpiration: 10,
sessionTokenExpirationUnit: 'minutes',
enableInactivity: true,
JITDisabled: false,
InactivityTime: 10,
InactivityTimeUnit: 'minutes',
});
const res = await descopeClient.management.tenant.generateSSOConfigurationLink(
'my-tenant-id',
60 * 60 * 24,
);
console.log(res.adminSSOConfigurationLink);
Manage Password
You can read and update any tenant password settings and policy:
const passwordSettings = await descopeClient.management.password.getSettings('my-tenant-id');
await descopeClient.management.password.configureSettings('my-tenant-id', {
enabled: true,
minLength: 8,
expiration: true,
expirationWeeks: 4,
lock: true,
lockAttempts: 5,
reuse: true,
reuseAmount: 6,
lowercase: true,
uppercase: false,
number: true,
nonAlphaNumeric: false,
});
Manage SSO applications
You can create, update, delete or load SSO applications:
await descopeClient.management.ssoApplication.createOidcApplication({
name: 'My OIDC app name',
loginPageUrl: 'http://dummy.com/login',
});
await descopeClient.management.ssoApplication.createSamlApplication({
name: 'My SAML app name',
loginPageUrl: 'http://dummy.com/login',
useMetadataInfo: true,
metadataUrl: 'http://dummy.com/metadata',
});
await descopeClient.management.ssoApplication.updateOidcApplication({
id: 'my-app-id',
name: 'My OIDC app name',
loginPageUrl: 'http://dummy.com/login',
});
await descopeClient.management.ssoApplication.updateSamlApplication({
id: 'my-app-id',
name: 'My SAML app name',
loginPageUrl: 'http://dummy.com/login',
enabled: true,
useMetadataInfo: false,
entityId: 'entity1234',
aceUrl: 'http://dummy.com/acs',
certificate: 'certificate',
});
await descopeClient.management.ssoApplication.delete('my-app-id');
const app = await descopeClient.management.ssoApplication.load('my-app-id');
const appsRes = await descopeClient.management.ssoApplication.loadAll();
appsRes.data.forEach((app) => {
});
Manage Users
You can create, update, delete or load users, as well as search according to filters:
await descopeClient.management.user.create('desmond@descope.com', {
email: 'desmond@descope.com',
displayName: 'Desmond Copeland',
userTenants: [{ tenantId: 'tenant-ID1', roleNames: ['role-name1'] }],
});
await descopeClient.management.user.invite('desmond@descope.com', {
email: 'desmond@descope.com',
displayName: 'Desmond Copeland',
userTenants: [{ tenantId: 'tenant-ID1', roleNames: ['role-name1'] }],
templateOptions: { k1: 'v1', k2: 'v2' },
});
await descopeClient.management.user.inviteBatch(
[
{
loginId: 'desmond@descope.com',
email: 'desmond@descope.com',
phone: '+123456789123',
displayName: 'Desmond Copeland',
userTenants: [{ tenantId: 'tenant-ID1', roleNames: ['role-name1'] }],
hashedPassword: {
bcrypt: {
hash: '$2a$...',
},
},
},
],
'<invite_url>',
true,
false,
);
await descopeClient.management.user.update('desmond@descope.com', {
email: 'desmond@descope.com',
displayName: 'Desmond Copeland',
userTenants: [{ tenantId: 'tenant-ID1', roleNames: ['role-name1'] }],
});
await descopeClient.management.user.updatePhone('desmond@descope.com', '+18005551234', true);
await descopeClient.management.user.updateLoginId('desmond@descope.com', 'bane@descope.com');
await descopeClient.management.user.removeTenantRoles(
'desmond@descope.com',
'tenant-ID1',
'role-name2',
);
const options: PatchUserOptions = { displayName: 'Desmond Copeland Jr.' };
await descopeClient.management.user.patch('desmond@descope.com', options);
await descopeClient.management.user.delete('desmond@descope.com');
const userRes = await descopeClient.management.user.load('desmond@descope.com');
const userRes = await descopeClient.management.user.loadByUserId('<user-ID>');
const usersRes = await descopeClient.management.user.search({ tenantIds: ['tenant-ID'] });
usersRes.data.forEach((user) => {
});
await descopeClient.management.user.logoutUser('my-custom-id');
await descopeClient.management.user.logoutUserByUserId('<user-ID>');
const userIds = ['user-id-1', 'user-id-2'];
const usersHistoryRes = await descopeClient.management.user.history(userIds);
usersHistoryRes.forEach((userHistory) => {
});
Set or Expire User Password
You can set a new active password for a user that they can sign in with.
You can also set a temporary password that they user will be forced to change on the next login.
For a user that already has an active password, you can expire their current password, effectively requiring them to change it on the next login.
await descopeClient.management.user.setTemporaryPassword('<login-ID>', '<some-password>');
await descopeClient.management.user.setActivePassword('<login-ID>', '<some-password>');
await descopeClient.management.user.expirePassword('<login-ID>');
Manage Project
You can update project name and tags, as well as clone the current project to a new one:
await descopeClient.management.project.updateName('new-project-name');
await descopeClient.management.project.updateTags(['tag1!', 'new']);
const cloneRes = await descopeClient.management.project.clone('new-project-name');
With using a company management key you can get a list of all the projects in the company:
const projects = await descopeClient.management.project.listProjects();
You can manage your project's settings and configurations by exporting a snapshot:
const exportRes = await descopeClient.management.project.exportSnapshot();
You can also import previously exported snapshots into the same project or a different one:
const validateReq = {
files: exportRes.files,
};
const validateRes = await descopeClient.management.project.import(files);
if (!validateRes.ok) {
}
const importReq = {
files: exportRes.files,
};
await descopeClient.management.project.importSnapshot(files);
Manage Access Keys
You can create, update, delete or load access keys, as well as search according to filters:
await descopeClient.management.accessKey.create(
'key-name',
123456789,
null,
[{ tenantId: 'tenant-ID1', roleNames: ['role-name1'] }],
);
const accessKeyRes = await descopeClient.management.accessKey.load('key-id');
const accessKeysRes = await descopeClient.management.accessKey.searchAll(['tenant-ID']);
accessKeysRes.data.forEach((accessKey) => {
});
await descopeClient.management.accessKey.update('key-id', 'new-key-name', 'new-description');
await descopeClient.management.accessKey.deactivate('key-id');
await descopeClient.management.accessKey.activate('key-id');
await descopeClient.management.accessKey.delete('key-id');
Manage SSO Setting
You can manage SSO settings and map SSO group roles and user attributes.
const ssoSettings = await descopeClient.management.sso.loadSettings("tenant-id")
const tenantId = 'tenant-id'
const idpURL = 'https://idp.com'
const entityID = 'my-idp-entity-id'
const idpCert = '<your-cert-here>'
const redirectURL = 'https://my-app.com/handle-sso'
const domains = ['tenant-users.com']
await descopeClient.management.sso.configureSAMLSettings(tenantID, {idpURL, entityID, idpCert}, redirectURL, domains)
await descopeClient.management.sso.configureSAMLByMetadata(tenantID, {idpMetadataUrl: 'https://idp.com/my-idp-metadata'}, redirectURL, domains)
const name = 'some-name';
const clientId = 'client id of OIDC';
const clientSecret = 'client secret';
await descopeClient.management.sso.configureOIDCSettings(tenantID, {name, clientId, clientSecret, redirectUrl}, domains)
await descopeClient.management.sso.configureMapping(
tenantId,
[{ groups: ['IDP_ADMIN'], roleName: 'Tenant Admin'}]
{ name: 'IDP_NAME', phoneNumber: 'IDP_PHONE'},
)
Note: Certificates should have a similar structure to:
-----BEGIN CERTIFICATE-----
Certifcate contents
-----END CERTIFICATE-----
// You can delete SSO settings for a specific tenant ID
await descopeClient.management.sso.deleteSettings("tenant-id")
Manage Permissions
You can create, update, delete or load permissions:
const name = 'My Permission';
let description = 'Optional description to briefly explain what this permission allows.';
await descopeClient.management.permission.create(name, description);
const newName = 'My Updated Permission';
description = 'A revised description';
await descopeClient.management.permission.update(name, newName, description);
await descopeClient.management.permission.delete(newName);
const permissionsRes = await descopeClient.management.permission.loadAll();
permissionsRes.data.forEach((permission) => {
});
Manage Roles
You can create, update, delete or load roles:
const name = 'My Role';
const tenantId = '<tenant id>';
let description = 'Optional description to briefly explain what this role allows.';
const permissionNames = ['My Updated Permission'];
descopeClient.management.role.create(name, description, permissionNames, tenantId);
const newName = 'My Updated Role';
description = 'A revised description';
permissionNames.push('Another Permission');
descopeClient.management.role.update(name, newName, description, permissionNames, tenantId);
descopeClient.management.role.delete(newName, tenantId);
const rolesRes = await descopeClient.management.role.loadAll();
rolesRes.data.forEach((role) => {
});
const rolesRes = await descopeClient.management.role.search({
tenantIds: ['t1', 't2'],
roleNames: ['role1'],
});
rolesRes.data.forEach((role) => {
});
Query SSO Groups
You can query SSO groups:
const groupsRes = descopeClient.management.group.loadAllGroups('tenant-id');
const groupsRes = descopeClient.management.group.loadAllGroupsForMember('tenant-id', [
'user-id-1',
'user-id-2',
]);
const groupsRes = descopeClient.management.group.loadAllGroupsForMember(
'tenant-id',
[],
['login-id-1', 'login-id-2'],
);
const groupsRes = descopeClient.management.group.loadAllGroupMembers('tenant-id', 'group-id');
groupsRes.data.forEach((group) => {
});
Manage Flows
You can list your flows and also import and export flows and screens, or the project theme:
const res = await descopeClient.management.flow.list();
console.log('found total flows', res.total);
res.flows.forEach((flowMetadata) => {
});
await descopeClient.management.flow.delete(['flow-1', 'flow-2']);
const res = await descopeClient.management.flow.export('sign-up');
console.log('found flow', res.data.flow);
res.data.screens.forEach((screen) => {
});
const { flow, screens } = res.data;
const updatedRes = descopeClient.management.flow.import('sign-up', flow, screens);
console.log('updated flow', updatedRes.data.flow);
updatedRes.data.screens.forEach((screen) => {
});
const res = descopeClient.management.theme.export();
console.log(res.data.theme);
const updatedRes = descopeClient.management.theme.import(theme);
console.log(updatedRes.data.theme);
Manage JWTs
You can add custom claims to a valid JWT.
const updatedJWTRes = await descopeClient.management.jwt.update('original-jwt', {
customKey1: 'custom-value1',
customKey2: 'custom-value2',
});
Impersonate
You can impersonate to another user
The impersonator user must have the impersonation
permission in order for this request to work.
The response would be a refresh JWT of the impersonated user
const updatedJWTRes = await descopeClient.management.jwt.impersonate(
'impersonator-id',
'login-id',
true,
{ k1: 'v1' },
't1',
);
Note 1: The generate code/link functions, work only for test users, will not work for regular users.
Note 2: In case of testing sign-in / sign-up operations with test users, need to make sure to generate the code prior calling the sign-in / sign-up operations.
Embedded Links
Embedded links can be created to directly receive a verifiable token without sending it.
This token can then be verified using the magic link 'verify' function, either directly or through a flow.
const { token } = await descopeClient.management.user.generateEmbeddedLink('desmond@descope.com', {
key1: 'value1',
});
Audit
You can perform an audit search for either specific values or full-text across the fields. Audit search is limited to the last 30 days.
const audits = await descopeClient.management.audit.search({
from: Date.now() - 10 * 24 * 60 * 60 * 1000,
text: 'some-text',
});
console.log(audits);
const audits = await descopeClient.management.audit.search({ actions: ['LoginSucceed'] });
console.log(audits);
You can also create audit event with data
await descopeClient.management.audit.createEvent({
action: 'pencil.created',
type: 'info',
actorId: 'UXXX',
tenantId: 'tenant-id',
data: {
some: 'data',
},
});
Manage FGA (Fine-grained Authorization)
Descope supports full relation based access control (ReBAC) using a zanzibar like schema and operations.
A schema is comprised of types (entities like documents, folders, orgs, etc.) and each type has relation definitions and permission to define relations to other types.
A simple example for a file system like schema would be:
model AuthZ 1.0
type user
type org
relation member: user
relation parent: org
type folder
relation parent: folder
relation owner: user | org#member
relation editor: user
relation viewer: user
permission can_create: owner | parent.owner
permission can_edit: editor | can_create
permission can_view: viewer | can_edit
type doc
relation parent: folder
relation owner: user | org#member
relation editor: user
relation viewer: user
permission can_create: owner | parent.owner
permission can_edit: editor | can_create
permission can_view: viewer | can_edit
Descope SDK allows you to fully manage the schema and relations as well as perform simple (and not so simple) checks regarding the existence of relations.
const descopeClient = require('@descope/node-sdk');
await descopeClient.management.fga.saveSchema(schema);
await descopeClient.management.fga.createRelations([
{
resource: 'some-doc',
resourceType: 'doc',
relation: 'owner',
target: 'u1',
targetType: 'user',
},
]);
const relations = await descopeClient.management.fga.check([
{
resource: 'some-doc',
resourceType: 'doc',
relation: 'can_view',
target: 'u1',
targetType: 'user',
},
]);
Utils for your end to end (e2e) tests and integration tests
To ease your e2e tests, we exposed dedicated management methods,
that way, you don't need to use 3rd party messaging services in order to receive sign-in/up Email, SMS, Voice call or WhatsApp, and avoid the need of parsing the code and token from them.
await descopeClient.management.user.createTestUser('desmond@descope.com', {
email: 'desmond@descope.com',
displayName: 'Desmond Copeland',
userTenants: [{ tenantId: 'tenant-ID1', roleNames: ['role-name1'] }],
});
const searchRes = await descopeClient.management.user.searchTestUsers(['id']);
searchRes.data.forEach((user) => {
});
await descopeClient.management.user.deleteAllTestUsers();
const { code } = await descopeClient.management.user.generateOTPForTestUser(
'sms',
'desmond@descope.com',
);
const { link } = await descopeClient.management.user.generateMagicLinkForTestUser(
'email',
'desmond@descope.com',
'',
);
const { link, pendingRef } = await descopeClient.management.user.generateEnchantedLinkForTestUser(
'desmond@descope.com',
'',
);
Code Examples
You can find various usage examples in the examples folder.
Setup
To run the examples, set your Project ID
by setting the DESCOPE_PROJECT_ID
env var or directly
in the sample code.
Find your Project ID in the Descope console.
export DESCOPE_PROJECT_ID=<ProjectID>
Run an example
Run the following commands in the root of the project to build and run the examples with a local build
of the SDK.
-
Run this to start the ES6 typescript module example
npm i && \
npm run build && \
cd examples/es6 && \
npm i && \
npm run generateCerts && \
npm start
-
Run this to start the commonjs example
npm i && \
npm run build && \
cd examples/commonjs && \
npm i && \
npm run generateCerts && \
npm start
Providing Custom Public Key
By default, the SDK will download the public key from Descope's servers. You can also provide your own public key. This is useful when the server you are running the SDK on does not have access to the internet.
You can find your public key in the https://api.descope.com/v2/keys/<project-id>
endpoint. For further information, please see the Descope Documentation and API reference page.
To provide your own public key, you can do so by providing the publicKey
option when initializing the SDK:
import DescopeClient from '@descope/node-sdk';
const descopeClient = DescopeClient({
projectId: 'my-project-ID',
publicKey: '{"alg":"RS256", ... }',
});
const sessionJWt = '<session-jwt>';
await descopeClient.validateJwt(sessionJWt);
Learn More
To learn more please see the Descope Documentation and API reference page.
Contact Us
If you need help you can email Descope Support
License
The Descope SDK for Node.js is licensed for use under the terms and conditions of the MIT license Agreement.