Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@descope/node-sdk

Package Overview
Dependencies
Maintainers
4
Versions
319
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@descope/node-sdk - npm Package Compare versions

Comparing version 1.0.4-alpha.9 to 1.0.4-alpha.10

2

dist/cjs/index.cjs.js

@@ -1,2 +0,2 @@

"use strict";var e=require("@descope/core-js-sdk"),t=require("jose"),s=require("node-fetch"),o=require("tslib");function n(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var a=n(e),r=n(s);const i=(e,t,s)=>`${e}=${t}; Domain=${(null==s?void 0:s.cookieDomain)||""}; Max-Age=${(null==s?void 0:s.cookieMaxAge)||""}; Path=${(null==s?void 0:s.cookiePath)||"/"}; HttpOnly; SameSite=Strict`,l=e=>async(...t)=>{var s,n,a;const r=await e(...t);if(!r.data)return r;let l=r.data,{sessionJwt:d,refreshJwt:c}=l,p=o.__rest(l,["sessionJwt","refreshJwt"]);const m=[i("DS",d,p)];return c?m.push(i("DSR",c,p)):(null===(s=r.response)||void 0===s?void 0:s.headers.get("set-cookie"))&&(c=((e,t)=>{const s=null==e?void 0:e.match(RegExp(`(?:^|;\\s*)${t}=([^;]*)`));return s?s[1]:null})(null===(n=r.response)||void 0===n?void 0:n.headers.get("set-cookie"),"DSR"),m.push(null===(a=r.response)||void 0===a?void 0:a.headers.get("set-cookie"))),Object.assign(Object.assign({},r),{data:Object.assign(Object.assign({},r.data),{refreshJwt:c,cookies:m})})},d=(e,t,s)=>{if(!e)return;const o="string"==typeof t?t.split("."):t,n=o.shift()||"";if(0===o.length||"*"===n){const t=t=>{if(!t||"function"!=typeof e[t])throw Error(`cannot wrap value at key "${t.toString()}"`);e[t]=s(e[t])};"*"===n?Object.keys(e).forEach(t):t(n)}else d(e[n],o,s)};function c(e,t,s){var o,n;const a=s?null===(n=null===(o=e.token.tenants)||void 0===o?void 0:o[s])||void 0===n?void 0:n[t]:e.token[t];return Array.isArray(a)?a:[]}var p={create:"/v1/mgmt/user/create",update:"/v1/mgmt/user/update",delete:"/v1/mgmt/user/delete",load:"/v1/mgmt/user/load",search:"/v1/mgmt/user/search"},m={create:"/v1/mgmt/tenant/create",update:"/v1/mgmt/tenant/update",delete:"/v1/mgmt/tenant/delete"},u={update:"/v1/mgmt/jwt/update"},h={create:"/v1/mgmt/permission/create",update:"/v1/mgmt/permission/update",delete:"/v1/mgmt/permission/delete",loadAll:"/v1/mgmt/permission/all"},v={create:"/v1/mgmt/role/create",update:"/v1/mgmt/role/update",delete:"/v1/mgmt/role/delete",loadAll:"/v1/mgmt/role/all"};const f=(t,s)=>({create:(o,n,a,r,i,l)=>e.transformResponse(t.httpClient.post(p.create,{identifier:o,email:n,phone:a,displayName:r,roleNames:i,userTenants:l},{token:s}),(e=>e.user)),update:(o,n,a,r,i,l)=>e.transformResponse(t.httpClient.post(p.update,{identifier:o,email:n,phone:a,displayName:r,roleNames:i,userTenants:l},{token:s}),(e=>e.user)),delete:o=>e.transformResponse(t.httpClient.post(p.delete,{identifier:o},{token:s})),load:o=>e.transformResponse(t.httpClient.get(p.load,{queryParams:{identifier:o},token:s}),(e=>e.user)),searchAll:(o,n,a)=>e.transformResponse(t.httpClient.post(p.search,{tenantIds:o,roleNames:n,limit:a},{token:s}),(e=>e.users))}),k=(t,s)=>({create:(o,n)=>e.transformResponse(t.httpClient.post(m.create,{name:o,selfProvisioningDomains:n},{token:s})),createWithId:(o,n,a)=>e.transformResponse(t.httpClient.post(m.create,{tenantId:o,name:n,selfProvisioningDomains:a},{token:s})),update:(o,n,a)=>e.transformResponse(t.httpClient.post(m.update,{tenantId:o,name:n,selfProvisioningDomains:a},{token:s})),delete:o=>e.transformResponse(t.httpClient.post(m.delete,{tenantId:o},{token:s}))}),g=(t,s)=>({update:(o,n)=>e.transformResponse(t.httpClient.post(u.update,{jwt:o,customClaims:n},{token:s}))}),y=(t,s)=>({create:(o,n)=>e.transformResponse(t.httpClient.post(h.create,{name:o,description:n},{token:s})),update:(o,n,a)=>e.transformResponse(t.httpClient.post(h.update,{name:o,newName:n,description:a},{token:s})),delete:o=>e.transformResponse(t.httpClient.post(h.delete,{name:o},{token:s})),loadAll:()=>e.transformResponse(t.httpClient.get(h.loadAll,{token:s}),(e=>e.permissions))}),w=(t,s)=>({create:(o,n,a)=>e.transformResponse(t.httpClient.post(v.create,{name:o,description:n,permissionNames:a},{token:s})),update:(o,n,a,r)=>e.transformResponse(t.httpClient.post(v.update,{name:o,newName:n,description:a,permissionNames:r},{token:s})),delete:o=>e.transformResponse(t.httpClient.post(v.delete,{name:o},{token:s})),loadAll:()=>e.transformResponse(t.httpClient.get(v.loadAll,{token:s}),(e=>e.roles))});globalThis.fetch||(globalThis.fetch=r.default,globalThis.Headers=s.Headers,globalThis.Request=s.Request,globalThis.Response=s.Response);const R=e=>{e.hooks=e.hooks||{};const s=e.hooks.beforeRequest;e.hooks.beforeRequest=e=>{var t;const o=e;return o.headers=Object.assign(Object.assign({},o.headers),{"x-descope-sdk-name":"nodejs","x-descope-sdk-node-version":(null===(t=null===process||void 0===process?void 0:process.versions)||void 0===t?void 0:t.node)||"","x-descope-sdk-version":"1.0.4-alpha.9"}),(null==s?void 0:s(o))||o};const o=a.default(e);var n,r;n=o,r=l,["otp.verify.*","magicLink.verify","enchantedLink.signUp.*","enchantedLink.signIn.*","oauth.exchange","saml.exchange","totp.verify","webauthn.signIn.finish","webauthn.signUp.finish","refresh"].forEach((e=>d(n,e,r)));const{projectId:i,logger:p}=e,m={},u=((e,t)=>({user:f(e,t),tenant:k(e,t),jwt:g(e,t),permission:y(e,t),role:w(e,t)}))(o,e.managementKey),h=Object.assign(Object.assign({},o),{management:u,async getKey(e){if(!(null==e?void 0:e.kid))throw Error("header.kid must not be empty");if(m[e.kid])return m[e.kid];if(Object.assign(m,await(async()=>{const e=(await o.httpClient.get(`v2/keys/${i}`).then((e=>e.json()))).keys;return Array.isArray(e)?(await Promise.all(e.map((async e=>[e.kid,await t.importJWK(e)])))).reduce(((e,[t,s])=>t?Object.assign(Object.assign({},e),{[t.toString()]:s}):e),{}):{}})()),!m[e.kid])throw Error("failed to fetch matching key");return m[e.kid]},async validateJwt(e){var s;const o=(await t.jwtVerify(e,h.getKey,{clockTolerance:5})).payload;if(o&&(o.iss=null===(s=o.iss)||void 0===s?void 0:s.split("/").pop(),o.iss!==i))throw new t.errors.JWTClaimValidationFailed('unexpected "iss" claim value',"iss","check_failed");return{jwt:e,token:o}},async validateSession(e,t){var s,o;if(!e&&!t)throw Error("both refresh token and session token are empty");if(e)try{return await h.validateJwt(e)}catch(e){if(!t)throw null==p||p.error("failed to validate session token and no refresh token provided",e),Error("could not validate tokens")}if(t)try{await h.validateJwt(t);const e=await h.refresh(t);if(e.ok){return await h.validateJwt(null===(s=e.data)||void 0===s?void 0:s.sessionJwt)}throw Error(null===(o=e.error)||void 0===o?void 0:o.message)}catch(e){throw null==p||p.error("failed to validate refresh token",e),Error("could not validate tokens")}throw Error("could not validate token")},async exchangeAccessKey(e){if(!e)throw Error("access key must not be empty");let t;try{t=await h.accessKey.exchange(e)}catch(e){throw null==p||p.error("failed to exchange access key",e),Error("could not exchange access key")}const{sessionJwt:s}=t.data;if(!s)throw null==p||p.error("failed to parse exchange access key response"),Error("could not exchange access key");try{return await h.validateJwt(s)}catch(e){throw null==p||p.error("failed to parse jwt from access key",e),Error("could not exchange access key")}},validatePermissions:(e,t)=>h.validateTenantPermissions(e,null,t),validateTenantPermissions(e,t,s){const o=c(e,"permissions",t);return s.every((e=>o.includes(e)))},validateRoles:(e,t)=>h.validateTenantRoles(e,null,t),validateTenantRoles(e,t,s){const o=c(e,"roles",t);return s.every((e=>o.includes(e)))}});return h};R.DeliveryMethods=a.default.DeliveryMethods,R.RefreshTokenCookieName="DSR",R.SessionTokenCookieName="DS",module.exports=R;
"use strict";var e=require("tslib"),t=require("@descope/core-js-sdk"),s=require("jose"),a=require("node-fetch");function o(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var n=o(t),r=o(a);const i=t=>async(...s)=>{var a,o,n;const r=await t(...s);if(!r.data)return r;let i=r.data,{refreshJwt:l}=i,d=e.__rest(i,["refreshJwt"]);const p=[];var m;return l?p.push(`${"DSR"}=${l}; Domain=${(null==(m=d)?void 0:m.cookieDomain)||""}; Max-Age=${(null==m?void 0:m.cookieMaxAge)||""}; Path=${(null==m?void 0:m.cookiePath)||"/"}; HttpOnly; SameSite=Strict`):(null===(a=r.response)||void 0===a?void 0:a.headers.get("set-cookie"))&&(l=((e,t)=>{const s=null==e?void 0:e.match(RegExp(`(?:^|;\\s*)${t}=([^;]*)`));return s?s[1]:null})(null===(o=r.response)||void 0===o?void 0:o.headers.get("set-cookie"),"DSR"),p.push(null===(n=r.response)||void 0===n?void 0:n.headers.get("set-cookie"))),Object.assign(Object.assign({},r),{data:Object.assign(Object.assign({},r.data),{refreshJwt:l,cookies:p})})};function l(e,t,s){var a,o;const n=s?null===(o=null===(a=e.token.tenants)||void 0===a?void 0:a[s])||void 0===o?void 0:o[t]:e.token[t];return Array.isArray(n)?n:[]}var d={create:"/v1/mgmt/user/create",update:"/v1/mgmt/user/update",delete:"/v1/mgmt/user/delete",load:"/v1/mgmt/user",search:"/v1/mgmt/user/search"},p={create:"/v1/mgmt/accesskey/create",load:"/v1/mgmt/accesskey",search:"/v1/mgmt/accesskey/search",update:"/v1/mgmt/accesskey/update",deactivate:"/v1/mgmt/accesskey/deactivate",activate:"/v1/mgmt/accesskey/activate",delete:"/v1/mgmt/accesskey/delete"},m={create:"/v1/mgmt/tenant/create",update:"/v1/mgmt/tenant/update",delete:"/v1/mgmt/tenant/delete",loadAll:"/v1/mgmt/tenant/all"},c={configure:"mgmt/sso/settings",metadata:"mgmt/sso/metadata",mapping:"mgmt/sso/mapping"},u={update:"/v1/mgmt/jwt/update"},h={create:"/v1/mgmt/permission/create",update:"/v1/mgmt/permission/update",delete:"/v1/mgmt/permission/delete",loadAll:"/v1/mgmt/permission/all"},g={create:"/v1/mgmt/role/create",update:"/v1/mgmt/role/update",delete:"/v1/mgmt/role/delete",loadAll:"/v1/mgmt/role/all"},v={loadAllGroups:"/v1/mgmt/group/all",loadAllGroupsForMember:"/v1/mgmt/group/member/all",loadAllGroupMembers:"/v1/mgmt/group/members"};const f=(e,s)=>({create:(a,o,n,r,i,l)=>t.transformResponse(e.httpClient.post(d.create,{identifier:a,email:o,phone:n,displayName:r,roleNames:i,userTenants:l},{token:s}),(e=>e.user)),update:(a,o,n,r,i,l)=>t.transformResponse(e.httpClient.post(d.update,{identifier:a,email:o,phone:n,displayName:r,roleNames:i,userTenants:l},{token:s}),(e=>e.user)),delete:a=>t.transformResponse(e.httpClient.post(d.delete,{identifier:a},{token:s})),load:a=>t.transformResponse(e.httpClient.get(d.load,{queryParams:{identifier:a},token:s}),(e=>e.user)),loadByJwtSubject:a=>t.transformResponse(e.httpClient.get(d.load,{queryParams:{jwtSubject:a},token:s}),(e=>e.user)),searchAll:(a,o,n)=>t.transformResponse(e.httpClient.post(d.search,{tenantIds:a,roleNames:o,limit:n},{token:s}),(e=>e.users))}),k=(e,s)=>({create:(a,o)=>t.transformResponse(e.httpClient.post(m.create,{name:a,selfProvisioningDomains:o},{token:s})),createWithId:(a,o,n)=>t.transformResponse(e.httpClient.post(m.create,{tenantId:a,name:o,selfProvisioningDomains:n},{token:s})),update:(a,o,n)=>t.transformResponse(e.httpClient.post(m.update,{tenantId:a,name:o,selfProvisioningDomains:n},{token:s})),delete:a=>t.transformResponse(e.httpClient.post(m.delete,{tenantId:a},{token:s})),loadAll:()=>t.transformResponse(e.httpClient.get(m.loadAll,{token:s}),(e=>e.tenants))}),y=(e,s)=>({update:(a,o)=>t.transformResponse(e.httpClient.post(u.update,{jwt:a,customClaims:o},{token:s}))}),w=(e,s)=>({create:(a,o)=>t.transformResponse(e.httpClient.post(h.create,{name:a,description:o},{token:s})),update:(a,o,n)=>t.transformResponse(e.httpClient.post(h.update,{name:a,newName:o,description:n},{token:s})),delete:a=>t.transformResponse(e.httpClient.post(h.delete,{name:a},{token:s})),loadAll:()=>t.transformResponse(e.httpClient.get(h.loadAll,{token:s}),(e=>e.permissions))}),R=(e,s)=>({create:(a,o,n)=>t.transformResponse(e.httpClient.post(g.create,{name:a,description:o,permissionNames:n},{token:s})),update:(a,o,n,r)=>t.transformResponse(e.httpClient.post(g.update,{name:a,newName:o,description:n,permissionNames:r},{token:s})),delete:a=>t.transformResponse(e.httpClient.post(g.delete,{name:a},{token:s})),loadAll:()=>t.transformResponse(e.httpClient.get(g.loadAll,{token:s}),(e=>e.roles))}),C=(e,s)=>({loadAllGroups:a=>t.transformResponse(e.httpClient.post(v.loadAllGroups,{tenantId:a},{token:s})),loadAllGroupsForMember:(a,o,n)=>t.transformResponse(e.httpClient.post(v.loadAllGroupsForMember,{tenantId:a,identifiers:n,jwtSubjects:o},{token:s})),loadAllGroupMembers:(a,o)=>t.transformResponse(e.httpClient.post(v.loadAllGroupMembers,{tenantId:a,groupId:o},{token:s}))}),b=(e,s)=>({configureSettings:(a,o,n,r,i)=>t.transformResponse(e.httpClient.post(c.configure,{tenantId:a,idpURL:o,entityId:r,idpCert:n,redirectURL:i},{token:s})),configureMetadata:(a,o)=>t.transformResponse(e.httpClient.post(c.metadata,{tenantId:a,idpMetadataURL:o},{token:s})),configureMapping:(a,o,n)=>t.transformResponse(e.httpClient.post(c.mapping,{tenantId:a,roleMapping:o,attributeMapping:n},{token:s}))}),j=(e,s)=>({create:(a,o,n,r)=>t.transformResponse(e.httpClient.post(p.create,{name:a,expireTime:o,roleNames:n,keyTenants:r},{token:s})),load:a=>t.transformResponse(e.httpClient.get(p.load,{queryParams:{id:a},token:s}),(e=>e.key)),searchAll:a=>t.transformResponse(e.httpClient.post(p.search,{tenantIds:a},{token:s}),(e=>e.keys)),update:(a,o)=>t.transformResponse(e.httpClient.post(p.update,{id:a,name:o},{token:s}),(e=>e.key)),deactivate:a=>t.transformResponse(e.httpClient.post(p.deactivate,{id:a},{token:s})),activate:a=>t.transformResponse(e.httpClient.post(p.activate,{id:a},{token:s})),delete:a=>t.transformResponse(e.httpClient.post(p.delete,{id:a},{token:s}))});globalThis.fetch||(globalThis.fetch=r.default,globalThis.Headers=a.Headers,globalThis.Request=a.Request,globalThis.Response=a.Response);const A=a=>{var{managementKey:o}=a,r=e.__rest(a,["managementKey"]);const d=n.default(t.addHooksToConfig(r,{beforeRequest:e=>{var t;return e.headers=Object.assign(Object.assign({},e.headers),{"x-descope-sdk-name":"nodejs","x-descope-sdk-node-version":(null===(t=null===process||void 0===process?void 0:process.versions)||void 0===t?void 0:t.node)||"","x-descope-sdk-version":"1.0.4-alpha.10"}),e}})),{projectId:p,logger:m}=r,c={},u=((e,t)=>({user:f(e,t),accessKey:j(e,t),tenant:k(e,t),sso:b(e,t),jwt:y(e,t),permission:w(e,t),role:R(e,t),group:C(e,t)}))(d,o),h=Object.assign(Object.assign({},d),{management:u,async getKey(e){if(!(null==e?void 0:e.kid))throw Error("header.kid must not be empty");if(c[e.kid])return c[e.kid];if(Object.assign(c,await(async()=>{const e=(await d.httpClient.get(`v2/keys/${p}`).then((e=>e.json()))).keys;return Array.isArray(e)?(await Promise.all(e.map((async e=>[e.kid,await s.importJWK(e)])))).reduce(((e,[t,s])=>t?Object.assign(Object.assign({},e),{[t.toString()]:s}):e),{}):{}})()),!c[e.kid])throw Error("failed to fetch matching key");return c[e.kid]},async validateJwt(e){var t;const a=(await s.jwtVerify(e,h.getKey,{clockTolerance:5})).payload;if(a&&(a.iss=null===(t=a.iss)||void 0===t?void 0:t.split("/").pop(),a.iss!==p))throw new s.errors.JWTClaimValidationFailed('unexpected "iss" claim value',"iss","check_failed");return{jwt:e,token:a}},async validateSession(e,t){var s,a;if(!e&&!t)throw Error("both refresh token and session token are empty");if(e)try{return await h.validateJwt(e)}catch(e){if(!t)throw null==m||m.error("failed to validate session token and no refresh token provided",e),Error("could not validate tokens")}if(t)try{await h.validateJwt(t);const e=await h.refresh(t);if(e.ok){return await h.validateJwt(null===(s=e.data)||void 0===s?void 0:s.sessionJwt)}throw Error(null===(a=e.error)||void 0===a?void 0:a.message)}catch(e){throw null==m||m.error("failed to validate refresh token",e),Error("could not validate tokens")}throw Error("could not validate token")},async exchangeAccessKey(e){if(!e)throw Error("access key must not be empty");let t;try{t=await h.accessKey.exchange(e)}catch(e){throw null==m||m.error("failed to exchange access key",e),Error("could not exchange access key")}const{sessionJwt:s}=t.data;if(!s)throw null==m||m.error("failed to parse exchange access key response"),Error("could not exchange access key");try{return await h.validateJwt(s)}catch(e){throw null==m||m.error("failed to parse jwt from access key",e),Error("could not exchange access key")}},validatePermissions:(e,t)=>h.validateTenantPermissions(e,null,t),validateTenantPermissions(e,t,s){const a=l(e,"permissions",t);return s.every((e=>a.includes(e)))},validateRoles:(e,t)=>h.validateTenantRoles(e,null,t),validateTenantRoles(e,t,s){const a=l(e,"roles",t);return s.every((e=>a.includes(e)))}});return t.wrapWith(h,["otp.verify.email","otp.verify.sms","otp.verify.whatsapp","magicLink.verify","enchantedLink.signUp","enchantedLink.signIn","oauth.exchange","saml.exchange","totp.verify","webauthn.signIn.finish","webauthn.signUp.finish","refresh"],i)};A.DeliveryMethods=n.default.DeliveryMethods,A.RefreshTokenCookieName="DSR",A.SessionTokenCookieName="DS",module.exports=A;
//# sourceMappingURL=index.cjs.js.map
import * as _descope_core_js_sdk from '@descope/core-js-sdk';
import _descope_core_js_sdk__default, { SdkResponse, ExchangeAccessKeyResponse } from '@descope/core-js-sdk';
import _descope_core_js_sdk__default, { SdkResponse, ExchangeAccessKeyResponse, RequestConfig } from '@descope/core-js-sdk';
export { DeliveryMethod, OAuthProvider } from '@descope/core-js-sdk';
import { JWTHeaderParameters, KeyLike } from 'jose';
/** Represents a tenant association for a User. The tenantId is required to denote
* which tenant the user belongs to. The roleNames array is an optional list of
* roles for the user in this specific tenant.
/** Represents a tenant association for a User or Access Key. The tenantId is required to denote
* which tenant the user or access key belongs to. The roleNames array is an optional list of
* roles for the user or access key in this specific tenant.
*/
declare type UserTenant = {
declare type AssociatedTenant = {
tenantId: string;

@@ -18,2 +18,31 @@ roleNames: string[];

};
/** An access key that can be used to access descope */
declare type AccessKey = {
id: string;
name: string;
expiredTime: number;
roleNames: string[];
keyTenants?: AssociatedTenant[];
status: string;
createdTime: number;
expiresTime: number;
createdBy: string;
};
/** Access Key extended details including created key cleartext */
declare type CreatedAccessKeyResponse = {
key: AccessKey;
cleartext: string;
};
/** Represents a mapping between a set of groups of users and a role that will be assigned to them */
declare type RoleMapping = {
groups: string[];
role: string;
};
/** Represents a mapping between Descope and IDP user attributes */
declare type AttributeMapping = {
name?: string;
email?: string;
phoneNumber?: string;
group?: string;
};
/** UpdateJWT response with a new JWT value with the added custom claims */

@@ -23,2 +52,10 @@ declare type UpdateJWTResponse = {

};
/** Represents a tenant in a project. It has an id, a name and an array of
* self provisioning domains used to associate users with that tenant.
*/
declare type Tenant = {
id: string;
name: string;
selfProvisioningDomains: string[];
};
/** Represents a permission in a project. It has a name and optionally a description.

@@ -40,3 +77,20 @@ * It also has a flag indicating whether it is system default or not.

};
/** Represents a group in a project. It has an id and display name and a list of group members. */
declare type Group = {
id: string;
display: string;
members?: GroupMember[];
};
/** Represents a group member. It has identifier, jwtSubject and display. */
declare type GroupMember = {
identifier: string;
jwtSubject: string;
display: string;
};
/** Refresh JWT cookie name */
declare const refreshTokenCookieName = "DSR";
/** Session JWT cookie name */
declare const sessionTokenCookieName = "DS";
/** Parsed JWT token */

@@ -56,7 +110,2 @@ interface Token {

/** Refresh JWT cookie name */
declare const refreshTokenCookieName = "DSR";
/** Session JWT cookie name */
declare const sessionTokenCookieName = "DS";
/** Configuration arguments which include the Descope core SDK args and an optional management key */

@@ -82,16 +131,21 @@ declare type NodeSdkArgs = Parameters<typeof _descope_core_js_sdk__default>[0] & {

*/
declare const sdkWithAttributes: ((args: NodeSdkArgs) => {
/**
* Provides various APIs for managing a Descope project programmatically. A management key must
* be provided as an argument when initializing the SDK to use these APIs. Management keys can be
* generated in the Descope console.
*/
declare const sdkWithAttributes: (({ managementKey, ...config }: NodeSdkArgs) => {
management: {
user: {
create: (identifier: string, email?: string, phone?: string, displayName?: string, roleNames?: string[], userTenants?: UserTenant[]) => Promise<SdkResponse<_descope_core_js_sdk.UserResponse>>;
update: (identifier: string, email?: string, phone?: string, displayName?: string, roleNames?: string[], userTenants?: UserTenant[]) => Promise<SdkResponse<_descope_core_js_sdk.UserResponse>>;
create: (identifier: string, email?: string, phone?: string, displayName?: string, roles?: string[], userTenants?: AssociatedTenant[]) => Promise<SdkResponse<_descope_core_js_sdk.UserResponse>>;
update: (identifier: string, email?: string, phone?: string, displayName?: string, roles?: string[], userTenants?: AssociatedTenant[]) => Promise<SdkResponse<_descope_core_js_sdk.UserResponse>>;
delete: (identifier: string) => Promise<SdkResponse<never>>;
load: (identifier: string) => Promise<SdkResponse<_descope_core_js_sdk.UserResponse>>;
searchAll: (tenantIds?: string[], roleNames?: string[], limit?: number) => Promise<SdkResponse<_descope_core_js_sdk.UserResponse[]>>;
loadByJwtSubject: (jwtSubject: string) => Promise<SdkResponse<_descope_core_js_sdk.UserResponse>>;
searchAll: (tenantIds?: string[], roles?: string[], limit?: number) => Promise<SdkResponse<_descope_core_js_sdk.UserResponse[]>>;
};
accessKey: {
create: (name: string, expireTime: number, roles?: string[], keyTenants?: AssociatedTenant[]) => Promise<SdkResponse<CreatedAccessKeyResponse>>;
load: (id: string) => Promise<SdkResponse<AccessKey>>;
searchAll: (tenantIds?: string[]) => Promise<SdkResponse<AccessKey[]>>;
update: (id: string, name: string) => Promise<SdkResponse<AccessKey>>;
deactivate: (id: string) => Promise<SdkResponse<never>>;
activate: (id: string) => Promise<SdkResponse<never>>;
delete: (id: string) => Promise<SdkResponse<never>>;
};
tenant: {

@@ -102,3 +156,9 @@ create: (name: string, selfProvisioningDomains?: string[]) => Promise<SdkResponse<CreateTenantResponse>>;

delete: (tenantId: string) => Promise<SdkResponse<never>>;
loadAll: () => Promise<SdkResponse<Tenant[]>>;
};
sso: {
configureSettings: (tenantId: string, idpURL: string, idpCert: string, entityId: string, redirectURL?: string) => Promise<SdkResponse<never>>;
configureMetadata: (tenantId: string, idpMetadataURL: string) => Promise<SdkResponse<never>>;
configureMapping: (tenantId: string, roleMapping?: RoleMapping, attributeMapping?: AttributeMapping) => Promise<SdkResponse<never>>;
};
jwt: {

@@ -119,53 +179,16 @@ update: (jwt: string, customClaims?: Record<string, any>) => Promise<SdkResponse<UpdateJWTResponse>>;

};
group: {
loadAllGroups: (tenantId: string) => Promise<SdkResponse<Group[]>>;
loadAllGroupsForMember: (tenantId: string, jwtSubjects: string[], identifiers: string[]) => Promise<SdkResponse<Group[]>>;
loadAllGroupMembers: (tenantId: string, groupId: string) => Promise<SdkResponse<Group[]>>;
};
};
/** Get the key that can validate the given JWT KID in the header. Can retrieve the public key from local cache or from Descope. */
getKey(header: JWTHeaderParameters): Promise<KeyLike | Uint8Array>;
/**
* Validate the given JWT with the right key and make sure the issuer is correct
* @param jwt the JWT string to parse and validate
* @returns AuthenticationInfo with the parsed token and JWT. Will throw an error if validation fails.
*/
validateJwt(jwt: string): Promise<AuthenticationInfo>;
/**
* Validate session based on at least one of session and refresh JWTs. You must provide at least one of them.
*
* @param sessionToken session JWT
* @param refreshToken refresh JWT
* @returns AuthenticationInfo promise or throws Error if there is an issue with JWTs
*/
validateSession(sessionToken?: string, refreshToken?: string): Promise<AuthenticationInfo>;
/**
* Exchange API key (access key) for a session key
* @param accessKey access key to exchange for a session JWT
* @returns AuthneticationInfo with session JWT data
*/
exchangeAccessKey(accessKey: string): Promise<AuthenticationInfo>;
/**
* Make sure that all given permissions exist on the parsed JWT top level claims
* @param authInfo JWT parsed info
* @param permissions list of permissions to make sure they exist on te JWT claims
* @returns true if all permissions exist, false otherwise
*/
validatePermissions(authInfo: AuthenticationInfo, permissions: string[]): boolean;
/**
* Make sure that all given permissions exist on the parsed JWT tenant claims
* @param authInfo JWT parsed info
* @param permissions list of permissions to make sure they exist on te JWT claims
* @returns true if all permissions exist, false otherwise
*/
validateTenantPermissions(authInfo: AuthenticationInfo, tenant: string, permissions: string[]): boolean;
/**
* Make sure that all given roles exist on the parsed JWT top level claims
* @param authInfo JWT parsed info
* @param roles list of roles to make sure they exist on te JWT claims
* @returns true if all roles exist, false otherwise
*/
validateRoles(authInfo: AuthenticationInfo, roles: string[]): boolean;
/**
* Make sure that all given roles exist on the parsed JWT tenant claims
* @param authInfo JWT parsed info
* @param roles list of roles to make sure they exist on te JWT claims
* @returns true if all roles exist, false otherwise
*/
validateTenantRoles(authInfo: AuthenticationInfo, tenant: string, roles: string[]): boolean;
getKey: (header: JWTHeaderParameters) => Promise<KeyLike | Uint8Array>;
validateJwt: (jwt: string) => Promise<AuthenticationInfo>;
validateSession: (sessionToken?: string, refreshToken?: string) => Promise<AuthenticationInfo>;
exchangeAccessKey: (accessKey: string) => Promise<AuthenticationInfo>;
validatePermissions: (authInfo: AuthenticationInfo, permissions: string[]) => boolean;
validateTenantPermissions: (authInfo: AuthenticationInfo, tenant: string, permissions: string[]) => boolean;
validateRoles: (authInfo: AuthenticationInfo, roles: string[]) => boolean;
validateTenantRoles: (authInfo: AuthenticationInfo, tenant: string, roles: string[]) => boolean;
accessKey: {

@@ -176,5 +199,5 @@ exchange: (accessKey: string) => Promise<SdkResponse<ExchangeAccessKeyResponse>>;

verify: {
email: (identifier: string, code: string) => Promise<SdkResponse<_descope_core_js_sdk.JWTResponse>>;
sms: (identifier: string, code: string) => Promise<SdkResponse<_descope_core_js_sdk.JWTResponse>>;
whatsapp: (identifier: string, code: string) => Promise<SdkResponse<_descope_core_js_sdk.JWTResponse>>;
email: (...args: never) => Promise<SdkResponse<never>>;
sms: (...args: never) => Promise<SdkResponse<never>>;
whatsapp: (...args: never) => Promise<SdkResponse<never>>;
};

@@ -214,12 +237,10 @@ signIn: {

whatsapp: (identifier: string, phone: string) => Promise<SdkResponse<never>>;
}; /**
* Make sure that all given roles exist on the parsed JWT top level claims
* @param authInfo JWT parsed info
* @param roles list of roles to make sure they exist on te JWT claims
* @returns true if all roles exist, false otherwise
*/
};
};
};
magicLink: {
verify: (token: string) => Promise<SdkResponse<_descope_core_js_sdk.JWTResponse>>;
verify: (token: string) => Promise<SdkResponse<_descope_core_js_sdk.JWTResponse & {
refreshJwt?: string;
cookies?: string[];
}>>;
signIn: {

@@ -259,12 +280,10 @@ email: (identifier: string, uri: string) => Promise<SdkResponse<never>>;

};
}; /**
* Make sure that all given roles exist on the parsed JWT tenant claims
* @param authInfo JWT parsed info
* @param roles list of roles to make sure they exist on te JWT claims
* @returns true if all roles exist, false otherwise
*/
};
};
enchantedLink: {
verify: (token: string) => Promise<SdkResponse<never>>;
signIn: (identifier: string, uri: string) => Promise<SdkResponse<_descope_core_js_sdk.EnchantedLinkResponse>>;
signIn: (identifier: string, uri: string) => Promise<SdkResponse<_descope_core_js_sdk.EnchantedLinkResponse & {
refreshJwt?: string;
cookies?: string[];
}>>;
signUpOrIn: (identifier: string, uri: string) => Promise<SdkResponse<_descope_core_js_sdk.EnchantedLinkResponse>>;

@@ -275,3 +294,6 @@ signUp: (identifier: string, uri: string, user?: {

phone?: string;
}) => Promise<SdkResponse<_descope_core_js_sdk.EnchantedLinkResponse>>;
}) => Promise<SdkResponse<_descope_core_js_sdk.EnchantedLinkResponse & {
refreshJwt?: string;
cookies?: string[];
}>>;
waitForSession: (pendingRef: string, config?: {

@@ -318,3 +340,6 @@ pollingIntervalMs: number;

};
exchange: (code: string) => Promise<SdkResponse<_descope_core_js_sdk.JWTResponse>>;
exchange: (code: string) => Promise<SdkResponse<_descope_core_js_sdk.JWTResponse & {
refreshJwt?: string;
cookies?: string[];
}>>;
};

@@ -327,3 +352,6 @@ saml: {

} ? undefined : SdkResponse<_descope_core_js_sdk.URLResponse>>;
exchange: (code: string) => Promise<SdkResponse<_descope_core_js_sdk.JWTResponse>>;
exchange: (code: string) => Promise<SdkResponse<_descope_core_js_sdk.JWTResponse & {
refreshJwt?: string;
cookies?: string[];
}>>;
};

@@ -340,3 +368,6 @@ totp: {

customClaims?: Record<string, any>;
}, token?: string) => Promise<SdkResponse<_descope_core_js_sdk.JWTResponse>>;
}, token?: string) => Promise<SdkResponse<_descope_core_js_sdk.JWTResponse & {
refreshJwt?: string;
cookies?: string[];
}>>;
update: (identifier: string, token?: string) => Promise<SdkResponse<_descope_core_js_sdk.TOTPResponse>>;

@@ -351,3 +382,6 @@ };

}>>;
finish: (transactionId: string, response: string) => Promise<SdkResponse<_descope_core_js_sdk.JWTResponse>>;
finish: (transactionId: string, response: string) => Promise<SdkResponse<_descope_core_js_sdk.JWTResponse & {
refreshJwt?: string;
cookies?: string[];
}>>;
};

@@ -364,3 +398,6 @@ signIn: {

}>>;
finish: (transactionId: string, response: string) => Promise<SdkResponse<_descope_core_js_sdk.JWTResponse>>;
finish: (transactionId: string, response: string) => Promise<SdkResponse<_descope_core_js_sdk.JWTResponse & {
refreshJwt?: string;
cookies?: string[];
}>>;
};

@@ -384,3 +421,3 @@ signUpOrIn: {

flow: {
start: (flowId: string, interactionId?: string, input?: Record<string, FormDataEntryValue>, options?: {
start: (flowId: string, options?: {
redirectUrl?: string;

@@ -392,10 +429,13 @@ tenant?: string;

lastUser?: {
authMethod?: "otp" | "totp" | "webauthn" | "magiclink" | "social" | "sso";
authMethod?: "otp" | "totp" | "webauthn" | "sso" | "magiclink" | "social";
oauthProvider?: string;
externalId?: string;
};
}) => Promise<SdkResponse<_descope_core_js_sdk.FlowResponse>>;
}, interactionId?: string, input?: Record<string, FormDataEntryValue>) => Promise<SdkResponse<_descope_core_js_sdk.FlowResponse>>;
next: (executionId: string, stepId: string, interactionId: string, input?: Record<string, FormDataEntryValue>) => Promise<SdkResponse<_descope_core_js_sdk.FlowResponse>>;
};
refresh: (token?: string) => Promise<SdkResponse<_descope_core_js_sdk.JWTResponse>>;
refresh: (token?: string) => Promise<SdkResponse<_descope_core_js_sdk.JWTResponse & {
refreshJwt?: string;
cookies?: string[];
}>>;
logout: (token?: string) => Promise<SdkResponse<never>>;

@@ -436,2 +476,6 @@ logoutAll: (token?: string) => Promise<SdkResponse<never>>;

}) => Promise<globalThis.Response>;
hooks?: {
beforeRequest?: (config: RequestConfig) => RequestConfig;
afterRequest?: (req: RequestConfig, res: globalThis.Response) => void;
};
};

@@ -438,0 +482,0 @@ }) & {

@@ -1,2 +0,2 @@

import e,{transformResponse as t}from"@descope/core-js-sdk";import{jwtVerify as o,errors as s,importJWK as a}from"jose";import n,{Headers as r,Request as i,Response as l}from"node-fetch";import{__rest as d}from"tslib";const c=(e,t,o)=>`${e}=${t}; Domain=${(null==o?void 0:o.cookieDomain)||""}; Max-Age=${(null==o?void 0:o.cookieMaxAge)||""}; Path=${(null==o?void 0:o.cookiePath)||"/"}; HttpOnly; SameSite=Strict`,p=e=>async(...t)=>{var o,s,a;const n=await e(...t);if(!n.data)return n;let r=n.data,{sessionJwt:i,refreshJwt:l}=r,p=d(r,["sessionJwt","refreshJwt"]);const m=[c("DS",i,p)];return l?m.push(c("DSR",l,p)):(null===(o=n.response)||void 0===o?void 0:o.headers.get("set-cookie"))&&(l=((e,t)=>{const o=null==e?void 0:e.match(RegExp(`(?:^|;\\s*)${t}=([^;]*)`));return o?o[1]:null})(null===(s=n.response)||void 0===s?void 0:s.headers.get("set-cookie"),"DSR"),m.push(null===(a=n.response)||void 0===a?void 0:a.headers.get("set-cookie"))),Object.assign(Object.assign({},n),{data:Object.assign(Object.assign({},n.data),{refreshJwt:l,cookies:m})})},m=(e,t,o)=>{if(!e)return;const s="string"==typeof t?t.split("."):t,a=s.shift()||"";if(0===s.length||"*"===a){const t=t=>{if(!t||"function"!=typeof e[t])throw Error(`cannot wrap value at key "${t.toString()}"`);e[t]=o(e[t])};"*"===a?Object.keys(e).forEach(t):t(a)}else m(e[a],s,o)};function h(e,t,o){var s,a;const n=o?null===(a=null===(s=e.token.tenants)||void 0===s?void 0:s[o])||void 0===a?void 0:a[t]:e.token[t];return Array.isArray(n)?n:[]}var u={create:"/v1/mgmt/user/create",update:"/v1/mgmt/user/update",delete:"/v1/mgmt/user/delete",load:"/v1/mgmt/user/load",search:"/v1/mgmt/user/search"},v={create:"/v1/mgmt/tenant/create",update:"/v1/mgmt/tenant/update",delete:"/v1/mgmt/tenant/delete"},k={update:"/v1/mgmt/jwt/update"},g={create:"/v1/mgmt/permission/create",update:"/v1/mgmt/permission/update",delete:"/v1/mgmt/permission/delete",loadAll:"/v1/mgmt/permission/all"},f={create:"/v1/mgmt/role/create",update:"/v1/mgmt/role/update",delete:"/v1/mgmt/role/delete",loadAll:"/v1/mgmt/role/all"};const y=(e,o)=>({create:(s,a,n,r,i,l)=>t(e.httpClient.post(u.create,{identifier:s,email:a,phone:n,displayName:r,roleNames:i,userTenants:l},{token:o}),(e=>e.user)),update:(s,a,n,r,i,l)=>t(e.httpClient.post(u.update,{identifier:s,email:a,phone:n,displayName:r,roleNames:i,userTenants:l},{token:o}),(e=>e.user)),delete:s=>t(e.httpClient.post(u.delete,{identifier:s},{token:o})),load:s=>t(e.httpClient.get(u.load,{queryParams:{identifier:s},token:o}),(e=>e.user)),searchAll:(s,a,n)=>t(e.httpClient.post(u.search,{tenantIds:s,roleNames:a,limit:n},{token:o}),(e=>e.users))}),w=(e,o)=>({create:(s,a)=>t(e.httpClient.post(v.create,{name:s,selfProvisioningDomains:a},{token:o})),createWithId:(s,a,n)=>t(e.httpClient.post(v.create,{tenantId:s,name:a,selfProvisioningDomains:n},{token:o})),update:(s,a,n)=>t(e.httpClient.post(v.update,{tenantId:s,name:a,selfProvisioningDomains:n},{token:o})),delete:s=>t(e.httpClient.post(v.delete,{tenantId:s},{token:o}))}),b=(e,o)=>({update:(s,a)=>t(e.httpClient.post(k.update,{jwt:s,customClaims:a},{token:o}))}),C=(e,o)=>({create:(s,a)=>t(e.httpClient.post(g.create,{name:s,description:a},{token:o})),update:(s,a,n)=>t(e.httpClient.post(g.update,{name:s,newName:a,description:n},{token:o})),delete:s=>t(e.httpClient.post(g.delete,{name:s},{token:o})),loadAll:()=>t(e.httpClient.get(g.loadAll,{token:o}),(e=>e.permissions))}),j=(e,o)=>({create:(s,a,n)=>t(e.httpClient.post(f.create,{name:s,description:a,permissionNames:n},{token:o})),update:(s,a,n,r)=>t(e.httpClient.post(f.update,{name:s,newName:a,description:n,permissionNames:r},{token:o})),delete:s=>t(e.httpClient.post(f.delete,{name:s},{token:o})),loadAll:()=>t(e.httpClient.get(f.loadAll,{token:o}),(e=>e.roles))});globalThis.fetch||(globalThis.fetch=n,globalThis.Headers=r,globalThis.Request=i,globalThis.Response=l);const x=t=>{t.hooks=t.hooks||{};const n=t.hooks.beforeRequest;t.hooks.beforeRequest=e=>{var t;const o=e;return o.headers=Object.assign(Object.assign({},o.headers),{"x-descope-sdk-name":"nodejs","x-descope-sdk-node-version":(null===(t=null===process||void 0===process?void 0:process.versions)||void 0===t?void 0:t.node)||"","x-descope-sdk-version":"1.0.4-alpha.9"}),(null==n?void 0:n(o))||o};const r=e(t);var i,l;i=r,l=p,["otp.verify.*","magicLink.verify","enchantedLink.signUp.*","enchantedLink.signIn.*","oauth.exchange","saml.exchange","totp.verify","webauthn.signIn.finish","webauthn.signUp.finish","refresh"].forEach((e=>m(i,e,l)));const{projectId:d,logger:c}=t,u={},v=((e,t)=>({user:y(e,t),tenant:w(e,t),jwt:b(e,t),permission:C(e,t),role:j(e,t)}))(r,t.managementKey),k=Object.assign(Object.assign({},r),{management:v,async getKey(e){if(!(null==e?void 0:e.kid))throw Error("header.kid must not be empty");if(u[e.kid])return u[e.kid];if(Object.assign(u,await(async()=>{const e=(await r.httpClient.get(`v2/keys/${d}`).then((e=>e.json()))).keys;return Array.isArray(e)?(await Promise.all(e.map((async e=>[e.kid,await a(e)])))).reduce(((e,[t,o])=>t?Object.assign(Object.assign({},e),{[t.toString()]:o}):e),{}):{}})()),!u[e.kid])throw Error("failed to fetch matching key");return u[e.kid]},async validateJwt(e){var t;const a=(await o(e,k.getKey,{clockTolerance:5})).payload;if(a&&(a.iss=null===(t=a.iss)||void 0===t?void 0:t.split("/").pop(),a.iss!==d))throw new s.JWTClaimValidationFailed('unexpected "iss" claim value',"iss","check_failed");return{jwt:e,token:a}},async validateSession(e,t){var o,s;if(!e&&!t)throw Error("both refresh token and session token are empty");if(e)try{return await k.validateJwt(e)}catch(e){if(!t)throw null==c||c.error("failed to validate session token and no refresh token provided",e),Error("could not validate tokens")}if(t)try{await k.validateJwt(t);const e=await k.refresh(t);if(e.ok){return await k.validateJwt(null===(o=e.data)||void 0===o?void 0:o.sessionJwt)}throw Error(null===(s=e.error)||void 0===s?void 0:s.message)}catch(e){throw null==c||c.error("failed to validate refresh token",e),Error("could not validate tokens")}throw Error("could not validate token")},async exchangeAccessKey(e){if(!e)throw Error("access key must not be empty");let t;try{t=await k.accessKey.exchange(e)}catch(e){throw null==c||c.error("failed to exchange access key",e),Error("could not exchange access key")}const{sessionJwt:o}=t.data;if(!o)throw null==c||c.error("failed to parse exchange access key response"),Error("could not exchange access key");try{return await k.validateJwt(o)}catch(e){throw null==c||c.error("failed to parse jwt from access key",e),Error("could not exchange access key")}},validatePermissions:(e,t)=>k.validateTenantPermissions(e,null,t),validateTenantPermissions(e,t,o){const s=h(e,"permissions",t);return o.every((e=>s.includes(e)))},validateRoles:(e,t)=>k.validateTenantRoles(e,null,t),validateTenantRoles(e,t,o){const s=h(e,"roles",t);return o.every((e=>s.includes(e)))}});return k};x.DeliveryMethods=e.DeliveryMethods,x.RefreshTokenCookieName="DSR",x.SessionTokenCookieName="DS";export{x as default};
import{__rest as e}from"tslib";import t,{transformResponse as a,addHooksToConfig as o,wrapWith as n}from"@descope/core-js-sdk";import{jwtVerify as s,errors as r,importJWK as i}from"jose";import l,{Headers as d,Request as c,Response as p}from"node-fetch";const m=t=>async(...a)=>{var o,n,s;const r=await t(...a);if(!r.data)return r;let i=r.data,{refreshJwt:l}=i,d=e(i,["refreshJwt"]);const c=[];var p;return l?c.push(`${"DSR"}=${l}; Domain=${(null==(p=d)?void 0:p.cookieDomain)||""}; Max-Age=${(null==p?void 0:p.cookieMaxAge)||""}; Path=${(null==p?void 0:p.cookiePath)||"/"}; HttpOnly; SameSite=Strict`):(null===(o=r.response)||void 0===o?void 0:o.headers.get("set-cookie"))&&(l=((e,t)=>{const a=null==e?void 0:e.match(RegExp(`(?:^|;\\s*)${t}=([^;]*)`));return a?a[1]:null})(null===(n=r.response)||void 0===n?void 0:n.headers.get("set-cookie"),"DSR"),c.push(null===(s=r.response)||void 0===s?void 0:s.headers.get("set-cookie"))),Object.assign(Object.assign({},r),{data:Object.assign(Object.assign({},r.data),{refreshJwt:l,cookies:c})})};function u(e,t,a){var o,n;const s=a?null===(n=null===(o=e.token.tenants)||void 0===o?void 0:o[a])||void 0===n?void 0:n[t]:e.token[t];return Array.isArray(s)?s:[]}var h={create:"/v1/mgmt/user/create",update:"/v1/mgmt/user/update",delete:"/v1/mgmt/user/delete",load:"/v1/mgmt/user",search:"/v1/mgmt/user/search"},g={create:"/v1/mgmt/accesskey/create",load:"/v1/mgmt/accesskey",search:"/v1/mgmt/accesskey/search",update:"/v1/mgmt/accesskey/update",deactivate:"/v1/mgmt/accesskey/deactivate",activate:"/v1/mgmt/accesskey/activate",delete:"/v1/mgmt/accesskey/delete"},v={create:"/v1/mgmt/tenant/create",update:"/v1/mgmt/tenant/update",delete:"/v1/mgmt/tenant/delete",loadAll:"/v1/mgmt/tenant/all"},k={configure:"mgmt/sso/settings",metadata:"mgmt/sso/metadata",mapping:"mgmt/sso/mapping"},y={update:"/v1/mgmt/jwt/update"},f={create:"/v1/mgmt/permission/create",update:"/v1/mgmt/permission/update",delete:"/v1/mgmt/permission/delete",loadAll:"/v1/mgmt/permission/all"},w={create:"/v1/mgmt/role/create",update:"/v1/mgmt/role/update",delete:"/v1/mgmt/role/delete",loadAll:"/v1/mgmt/role/all"},C={loadAllGroups:"/v1/mgmt/group/all",loadAllGroupsForMember:"/v1/mgmt/group/member/all",loadAllGroupMembers:"/v1/mgmt/group/members"};const b=(e,t)=>({create:(o,n,s,r,i,l)=>a(e.httpClient.post(h.create,{identifier:o,email:n,phone:s,displayName:r,roleNames:i,userTenants:l},{token:t}),(e=>e.user)),update:(o,n,s,r,i,l)=>a(e.httpClient.post(h.update,{identifier:o,email:n,phone:s,displayName:r,roleNames:i,userTenants:l},{token:t}),(e=>e.user)),delete:o=>a(e.httpClient.post(h.delete,{identifier:o},{token:t})),load:o=>a(e.httpClient.get(h.load,{queryParams:{identifier:o},token:t}),(e=>e.user)),loadByJwtSubject:o=>a(e.httpClient.get(h.load,{queryParams:{jwtSubject:o},token:t}),(e=>e.user)),searchAll:(o,n,s)=>a(e.httpClient.post(h.search,{tenantIds:o,roleNames:n,limit:s},{token:t}),(e=>e.users))}),A=(e,t)=>({create:(o,n)=>a(e.httpClient.post(v.create,{name:o,selfProvisioningDomains:n},{token:t})),createWithId:(o,n,s)=>a(e.httpClient.post(v.create,{tenantId:o,name:n,selfProvisioningDomains:s},{token:t})),update:(o,n,s)=>a(e.httpClient.post(v.update,{tenantId:o,name:n,selfProvisioningDomains:s},{token:t})),delete:o=>a(e.httpClient.post(v.delete,{tenantId:o},{token:t})),loadAll:()=>a(e.httpClient.get(v.loadAll,{token:t}),(e=>e.tenants))}),j=(e,t)=>({update:(o,n)=>a(e.httpClient.post(y.update,{jwt:o,customClaims:n},{token:t}))}),x=(e,t)=>({create:(o,n)=>a(e.httpClient.post(f.create,{name:o,description:n},{token:t})),update:(o,n,s)=>a(e.httpClient.post(f.update,{name:o,newName:n,description:s},{token:t})),delete:o=>a(e.httpClient.post(f.delete,{name:o},{token:t})),loadAll:()=>a(e.httpClient.get(f.loadAll,{token:t}),(e=>e.permissions))}),I=(e,t)=>({create:(o,n,s)=>a(e.httpClient.post(w.create,{name:o,description:n,permissionNames:s},{token:t})),update:(o,n,s,r)=>a(e.httpClient.post(w.update,{name:o,newName:n,description:s,permissionNames:r},{token:t})),delete:o=>a(e.httpClient.post(w.delete,{name:o},{token:t})),loadAll:()=>a(e.httpClient.get(w.loadAll,{token:t}),(e=>e.roles))}),T=(e,t)=>({loadAllGroups:o=>a(e.httpClient.post(C.loadAllGroups,{tenantId:o},{token:t})),loadAllGroupsForMember:(o,n,s)=>a(e.httpClient.post(C.loadAllGroupsForMember,{tenantId:o,identifiers:s,jwtSubjects:n},{token:t})),loadAllGroupMembers:(o,n)=>a(e.httpClient.post(C.loadAllGroupMembers,{tenantId:o,groupId:n},{token:t}))}),M=(e,t)=>({configureSettings:(o,n,s,r,i)=>a(e.httpClient.post(k.configure,{tenantId:o,idpURL:n,entityId:r,idpCert:s,redirectURL:i},{token:t})),configureMetadata:(o,n)=>a(e.httpClient.post(k.metadata,{tenantId:o,idpMetadataURL:n},{token:t})),configureMapping:(o,n,s)=>a(e.httpClient.post(k.mapping,{tenantId:o,roleMapping:n,attributeMapping:s},{token:t}))}),R=(e,t)=>({create:(o,n,s,r)=>a(e.httpClient.post(g.create,{name:o,expireTime:n,roleNames:s,keyTenants:r},{token:t})),load:o=>a(e.httpClient.get(g.load,{queryParams:{id:o},token:t}),(e=>e.key)),searchAll:o=>a(e.httpClient.post(g.search,{tenantIds:o},{token:t}),(e=>e.keys)),update:(o,n)=>a(e.httpClient.post(g.update,{id:o,name:n},{token:t}),(e=>e.key)),deactivate:o=>a(e.httpClient.post(g.deactivate,{id:o},{token:t})),activate:o=>a(e.httpClient.post(g.activate,{id:o},{token:t})),delete:o=>a(e.httpClient.post(g.delete,{id:o},{token:t}))});globalThis.fetch||(globalThis.fetch=l,globalThis.Headers=d,globalThis.Request=c,globalThis.Response=p);const S=a=>{var{managementKey:l}=a,d=e(a,["managementKey"]);const c=t(o(d,{beforeRequest:e=>{var t;return e.headers=Object.assign(Object.assign({},e.headers),{"x-descope-sdk-name":"nodejs","x-descope-sdk-node-version":(null===(t=null===process||void 0===process?void 0:process.versions)||void 0===t?void 0:t.node)||"","x-descope-sdk-version":"1.0.4-alpha.10"}),e}})),{projectId:p,logger:h}=d,g={},v=((e,t)=>({user:b(e,t),accessKey:R(e,t),tenant:A(e,t),sso:M(e,t),jwt:j(e,t),permission:x(e,t),role:I(e,t),group:T(e,t)}))(c,l),k=Object.assign(Object.assign({},c),{management:v,async getKey(e){if(!(null==e?void 0:e.kid))throw Error("header.kid must not be empty");if(g[e.kid])return g[e.kid];if(Object.assign(g,await(async()=>{const e=(await c.httpClient.get(`v2/keys/${p}`).then((e=>e.json()))).keys;return Array.isArray(e)?(await Promise.all(e.map((async e=>[e.kid,await i(e)])))).reduce(((e,[t,a])=>t?Object.assign(Object.assign({},e),{[t.toString()]:a}):e),{}):{}})()),!g[e.kid])throw Error("failed to fetch matching key");return g[e.kid]},async validateJwt(e){var t;const a=(await s(e,k.getKey,{clockTolerance:5})).payload;if(a&&(a.iss=null===(t=a.iss)||void 0===t?void 0:t.split("/").pop(),a.iss!==p))throw new r.JWTClaimValidationFailed('unexpected "iss" claim value',"iss","check_failed");return{jwt:e,token:a}},async validateSession(e,t){var a,o;if(!e&&!t)throw Error("both refresh token and session token are empty");if(e)try{return await k.validateJwt(e)}catch(e){if(!t)throw null==h||h.error("failed to validate session token and no refresh token provided",e),Error("could not validate tokens")}if(t)try{await k.validateJwt(t);const e=await k.refresh(t);if(e.ok){return await k.validateJwt(null===(a=e.data)||void 0===a?void 0:a.sessionJwt)}throw Error(null===(o=e.error)||void 0===o?void 0:o.message)}catch(e){throw null==h||h.error("failed to validate refresh token",e),Error("could not validate tokens")}throw Error("could not validate token")},async exchangeAccessKey(e){if(!e)throw Error("access key must not be empty");let t;try{t=await k.accessKey.exchange(e)}catch(e){throw null==h||h.error("failed to exchange access key",e),Error("could not exchange access key")}const{sessionJwt:a}=t.data;if(!a)throw null==h||h.error("failed to parse exchange access key response"),Error("could not exchange access key");try{return await k.validateJwt(a)}catch(e){throw null==h||h.error("failed to parse jwt from access key",e),Error("could not exchange access key")}},validatePermissions:(e,t)=>k.validateTenantPermissions(e,null,t),validateTenantPermissions(e,t,a){const o=u(e,"permissions",t);return a.every((e=>o.includes(e)))},validateRoles:(e,t)=>k.validateTenantRoles(e,null,t),validateTenantRoles(e,t,a){const o=u(e,"roles",t);return a.every((e=>o.includes(e)))}});return n(k,["otp.verify.email","otp.verify.sms","otp.verify.whatsapp","magicLink.verify","enchantedLink.signUp","enchantedLink.signIn","oauth.exchange","saml.exchange","totp.verify","webauthn.signIn.finish","webauthn.signUp.finish","refresh"],m)};S.DeliveryMethods=t.DeliveryMethods,S.RefreshTokenCookieName="DSR",S.SessionTokenCookieName="DS";export{S as default};
//# sourceMappingURL=index.esm.js.map
{
"name": "@descope/node-sdk",
"version": "1.0.4-alpha.9",
"version": "1.0.4-alpha.10",
"description": "Node.js library used to integrate with Descope",

@@ -98,3 +98,3 @@ "typings": "./dist/index.d.ts",

"dependencies": {
"@descope/core-js-sdk": "0.0.41-alpha.33",
"@descope/core-js-sdk": "0.0.41-alpha.38",
"jose": "4.11.1",

@@ -101,0 +101,0 @@ "node-fetch": "2.6.7"

@@ -1,11 +0,14 @@

# Descope Node.js SDK
# Descope SDK for Node.js
Use the Descope NodeJS SDK for NodeJS/Express to quickly and easily add user authentication to your application or website.
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](https://descope.com).
## Requirements
The SDK supports Node version 14 and above.
## Installing the SDK
Replace any instance of `<ProjectID>` in the code below with your company's Project ID, which can be found in the [Descope console](https://app.descope.com).
Install the package with:
Run the following code in your project. These commands will add the Descope SDK for Node as a project dependency, and set the `DESCOPE_PROJECT_ID` variable to a valid \<ProjectID\>.
```bash

@@ -15,22 +18,564 @@ npm i --save @descope/node-sdk

## What do you want to implement?
## Setup
Click one of the following links to open the documentation for that specific functionality.
A Descope `Project ID` is required to initialize the SDK. Find it on the
[project page in the Descope Console](https://app.descope.com/settings/project).
- [x] [One time passwords (OTP)](./docs/otp.md)
- [x] [Magic Links](./docs/magiclink.md)
- [x] [OAuth/Social](./docs/oauth.md)
```typescript
import DescopeClient from '@descope/node-sdk';
## Run the Examples
const descopeClient = DescopeClient({ projectId: 'my-project-ID' });
```
Instantly run the end-to-end ExpresSDK for NodeJS examples, as shown below. The source code for these examples are in the folder [GitHub node-sdk/examples folder](https://github.com/descope/node-sdk/blob/main/examples).
## Usage
### Prerequisites
Here are some examples how to manage and authenticate users:
Run the following commands in your project. Replace any instance of `<ProjectID>` in the code below with your company's Project ID, which can be found in the [Descope console](https://app.descope.com).
### OTP Authentication
This commands will add the Descope NodeJS SDK as a project dependency, clone the SDK repository locally, and set the `DESCOPE_PROJECT_ID`.
Send a user a one-time password (OTP) using your preferred delivery method (_email / SMS_). An email address or phone number must be provided accordingly.
```code bash
git clone github.com/descope/node-sdk
The user can either `sign up`, `sign in` or `sign up or in`
```typescript
// Every user must have an identifier. All other user information is optional
const identifier = 'desmond@descope.com';
const user = {
name: 'Desmond Copland',
phone: '212-555-1234',
email: identifier,
};
await descopeClient.otp.signUp['email'](identifier, user);
```
The user will receive a code using the selected delivery method. Verify that code using:
```typescript
const jwtResponse = await descopeClient.otp.verify['email'](identifier, 'code');
// jwtResponse.data.sessionJwt
// jwtResponse.data.refreshJwt
```
The session and refresh JWTs should be returned to the caller, and passed with every request in the session. Read more on [session validation](#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](https://app.descope.com/settings/authentication/magiclink)
The user can either `sign up`, `sign in` or `sign up or in`
```typescript
// If configured globally, the redirect URI is optional. If provided however, it will be used
// instead of any global configuration
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>`):
```typescript
const jwtResponse = await descopeClient.magicLink.verify('token');
// jwtResponse.data.sessionJwt;
// jwtResponse.data.refreshJwt;
```
The session and refresh JWTs should be returned to the caller, and passed with every request in the session. Read more on [session validation](#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](#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](https://app.descope.com/settings/authentication/enchantedlink).
The user can either `sign up`, `sign in` or `sign up or in`
```typescript
// If configured globally, the redirect URI is optional. If provided however, it will be used
// instead of any global configuration.
const URI = 'http://myapp.com/verify-enchanted-link';
const enchantedLinkRes = await descopeClient.enchantedLink.signIn('desmond@descope.com', URI);
enchantedLinkRes.data.linkId; // Should be displayed to the user so they can click the corresponding link in the email
enchantedLinkRes.data.pendingRef; // Used to poll for a valid session
```
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.
```typescript
// Poll for a certain number of tries / time frame. You can control the polling interval and time frame
// with the optional WaitForSessionConfig
const jwtResponse = await descopeClient.enchantedLink.waitForSession(
enchantedLinkRes.data.pendingRef,
);
// jwtResponse.data.sessionJwt;
// jwtResponse.data.refreshJwt;
```
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.
```typescript
try {
await descopeClient.enchantedLink.verify('token');
// token is invalid
} catch (error) {
// token is valid
}
```
The session and refresh JWTs should be returned to the caller, and passed with every request in the session. Read more on [session validation](#session-validation)
### OAuth
Users can authenticate using their social logins, via the OAuth protocol. Configure your OAuth settings on the [Descope console](https://app.descope.com/settings/authentication/social). To start an OAuth flow call:
```typescript
// Choose an oauth provider out of the supported providers
// If configured globally, the return URL is optional. If provided however, it will be used
// instead of any global configuration.
const urlRes = await descopeClient.oauth.start['google'](redirectUrl);
urlRes.data.url; // Redirect the user to the returned URL to start the OAuth redirect chain
```
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:
```typescript
const jwtResponse = await descopeClient.oauth.exchange('token');
// jwtResponse.data.sessionJwt;
// jwtResponse.data.refreshJwt;
```
The session and refresh JWTs should be returned to the caller, and passed with every request in the session. Read more on [session validation](#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](https://app.descope.com/settings/authentication/sso). To start a flow call:
```typescript
// If configured globally, the return URL is optional. If provided however, it will be used
// instead of any global configuration.
const redirectUrl = 'https://my-app.com/handle-saml';
const urlRes = await descopeClient.saml.start('tenant'); // Choose which tenant to log into. An email can also be provided here and the domain will be extracted from it
urlRes.data.url; // Redirect the user to the given returned URL to start the SSO/SAML redirect chain
```
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:
```typescript
const jwtResponse = await descopeClient.saml.exchange('token');
// jwtResponse.data.sessionJwt;
// jwtResponse.data.refreshJwt;
```
The session and refresh JWTs should be returned to the caller, and passed with every request in the session. Read more on [session validation](#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.
```typescript
// Every user must have an identifier. All other user information is optional
const identifier = 'desmond@descope.com';
const user = {
name: 'Desmond Copland',
phone: '212-555-1234',
email: identifier,
};
const totpRes = await descopeClient.totp.signUp(identifier, user);
// Use one of the provided options to have the user add their credentials to the authenticator
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.
```typescript
const jwtResponse = await descopeClient.totp.verify(identifier, 'code');
// jwtResponse.data.sessionJwt;
// jwtResponse.data.refreshJwt;
```
The session and refresh JWTs should be returned to the caller, and passed with every request in the session. Read more on [session validation](#session-validation)
### 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:
```typescript
// The response will contain all token information including the raw JWT, parsed JWT and cookies
const authInfo = await descopeClient.validateSession('sessionToken', 'refreshToken');
```
These function will validate the session and also refresh it in the event it has expired.
It returns the given session token if it's still valid, or a new one if it was refreshed.
Make sure to return the session token from the response to the client if tokens are validated directly.
The `refreshToken` is optional here to validate a session, but is required to refresh the session in the event it has expired.
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](#code-examples) for a few examples.
If Roles & Permissions are used, validate them immediately after validating the session. See the [next section](#roles--permission-validation)
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`.
```typescript
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: new 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](#session-validation), call the following functions:
For multi-tenant uses:
```typescript
// You can validate specific permissions
const validTenantPermissions = await descopeClient.validateTenantPermissions(
authInfo,
'my-tenant-ID',
['Permission to validate'],
);
if (!validTenantPermissions) {
// Deny access
}
// Or validate roles directly
const validTenantRoles = await descopeClient.validateTenantRoles(authInfo, 'my-tenant-ID', [
'Role to validate',
]);
if (!validTenantRoles) {
// Deny access
}
```
When not using tenants use:
```typescript
// You can validate specific permissions
const validPermissions = await descopeClient.validatePermissions(authInfo, [
'Permission to validate',
]);
if (!validPermissions) {
// Deny access
}
// Or validate roles directly
const validRoles = await descopeClient.validateRoles(authInfo, ['Role to validate']);
if (!validRoles) {
// Deny access
}
```
## Management API
It is very common for some form of management or automation to be required. These can be performed
using the management API. 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](https://app.descope.com/settings/company/managementkeys).
```typescript
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:
```typescript
// The self provisioning domains or optional. If given they'll be used to associate
// Users logging in to this tenant
await descopeClient.management.tenant.create('My Tenant', ['domain.com']);
// You can optionally set your own ID when creating a tenant
await descopeClient.management.tenant.createWithId('my-custom-id', 'My Tenant', ['domain.com']);
// Update will override all fields as is. Use carefully.
await descopeClient.management.tenant.update('my-custom-id', 'My Tenant', [
'domain.com',
'another-domain.com',
]);
// Tenant deletion cannot be undone. Use carefully.
await descopeClient.management.tenant.delete('my-custom-id');
// Load all tenants
const tenantsRes = await descopeClient.management.tenant.loadAll();
tenantsRes.data.forEach((tenant) => {
// do something
});
```
### Manage Users
You can create, update, delete or load users, as well as search according to filters:
```typescript
// A user must have an identifier, other fields are optional.
// Roles should be set directly if no tenants exist, otherwise set
// on a per-tenant basis.
await descopeClient.management.user.create(
'desmond@descope.com',
'desmond@descope.com',
null,
'Desmond Copeland',
null,
[{ tenantId: 'tenant-ID1', roleNames: ['role-name1'] }],
);
// Update will override all fields as is. Use carefully.
await descopeClient.management.user.update(
'desmond@descope.com',
'desmond@descope.com',
null,
'Desmond Copeland',
null,
[{ tenantId: 'tenant-ID1', roleNames: ['role-name1', 'role-name2'] }],
);
// User deletion cannot be undone. Use carefully.
await descopeClient.management.user.delete('desmond@descope.com');
// Load specific user
const userRes = await descopeClient.management.user.load('desmond@descope.com');
// If needed, users can be loaded using the JWT subject as well
const userRes = await descopeClient.management.user.loadByJwtSubject('<jwt-subject>');
// Search all users, optionally according to tenant and/or role filter
const usersRes = await descopeClient.management.user.searchAll(['tenant-ID']);
usersRes.data.forEach((user) => {
// do something
});
```
### Manage Access Keys
You can create, update, delete or load access keys, as well as search according to filters:
```typescript
// An access key must have a name and expiration, other fields are optional.
// Roles should be set directly if no tenants exist, otherwise set
// on a per-tenant basis.
await descopeClient.management.accessKey.create(
'key-name',
123456789, // expiration time
null,
[{ tenantId: 'tenant-ID1', roleNames: ['role-name1'] }],
);
// Load specific user
const accessKeyRes = await descopeClient.management.accessKey.load('key-id');
// Search all users, optionally according to tenant and/or role filter
const accessKeysRes = await descopeClient.management.accessKey.searchAll(['tenant-ID']);
accessKeysRes.data.forEach((accessKey) => {
// do something
});
// Update will override all fields as is. Use carefully.
await descopeClient.management.accessKey.update('key-id', 'new-key-name');
// Access keys can be deactivated to prevent usage. This can be undone using "activate".
await descopeClient.management.accessKey.deactivate('key-id');
// Disabled access keys can be activated once again.
await descopeClient.management.accessKey.activate('key-id');
// Access key deletion cannot be undone. Use carefully.
await descopeClient.management.accessKey.delete('key-id');
```
### Manage SSO Setting
You can manage SSO settings and map SSO group roles and user attributes.
```typescript
// You can configure SSO settings manually by setting the required fields directly
const tenantId = 'tenant-id' // Which tenant this configuration is for
const idpURL = 'https://idp.com'
const entityID = 'my-idp-entity-id'
const idpCert = '<your-cert-here>'
const redirectURL = 'https://my-app.com/handle-saml' // Global redirect URL for SSO/SAML
await descopeClient.management.sso.configureSettings(tenantID, idpURL, entityID, idpCert, redirectURL)
// Alternatively, configure using an SSO metadata URL
await descopeClient.management.sso.configureMetadata(tenantID, 'https://idp.com/my-idp-metadata')
// Map IDP groups to Descope roles, or map user attributes.
// This function overrides any previous mapping (even when empty). Use carefully.
await descopeClient.management.sso.configureMapping(
tenantId,
{ groups: ['IDP_ADMIN'], role: 'Tenant Admin'}
{ name: 'IDP_NAME', phoneNumber: 'IDP_PHONE'},
)
```
Note: Certificates should have a similar structure to:
```
-----BEGIN CERTIFICATE-----
Certifcate contents
-----END CERTIFICATE-----
```
### Manage Permissions
You can create, update, delete or load permissions:
```typescript
// You can optionally set a description for a permission.
const name = 'My Permission';
let description = 'Optional description to briefly explain what this permission allows.';
await descopeClient.management.permission.create(name, description);
// Update will override all fields as is. Use carefully.
const newName = 'My Updated Permission';
description = 'A revised description';
await descopeClient.management.permission.update(name, newName, description);
// Permission deletion cannot be undone. Use carefully.
await descopeClient.management.permission.delete(newName);
// Load all permissions
const permissionsRes = await descopeClient.management.permission.loadAll();
permissionsRes.data.forEach((permission) => {
// do something
});
```
### Manage Roles
You can create, update, delete or load roles:
```typescript
// You can optionally set a description and associated permission for a roles.
const name = 'My Role';
let description = 'Optional description to briefly explain what this role allows.';
const permissionNames = ['My Updated Permission'];
descopeClient.management.role.create(name, description, permissionNames);
// Update will override all fields as is. Use carefully.
const newName = 'My Updated Role';
description = 'A revised description';
permissionNames.push('Another Permission');
descopeClient.management.role.update(name, newName, description, permissionNames);
// Role deletion cannot be undone. Use carefully.
descopeClient.management.role.delete(newName);
// Load all roles
const rolesRes = await descopeClient.management.role.loadAll();
rolesRes.data.forEach((role) => {
// do something
});
```
### ### Query SSO Groups
You can query SSO groups:
```typescript
// Load all groups for a given tenant id
const groupsRes = descopeClient.management.group.loadAllGroups('tenant-id');
// Load all groups for the given user's jwt subjects (can be found in the user's JWT)
const groupsRes = descopeClient.management.group.loadAllGroupsForMember('tenant-id', [
'jwt-subject-1',
'jwt-subject-2',
]);
// Load all groups for the given user's identifiers (used for sign-in)
const groupsRes = descopeClient.management.group.loadAllGroupsForMember(
'tenant-id',
[],
['identifier-1', 'identifier-2'],
);
// Load all group's members by the given group id
const groupsRes = descopeClient.management.group.loadAllGroupMembers('tenant-id', 'group-id');
groupsRes.data.forEach((group) => {
// do something
});
```
### Manage JWTs
You can add custom claims to a valid JWT.
```typescript
const updatedJWTRes = await descopeClient.management.jwt.update('original-jwt', {
customKey1: 'custom-value1',
customKey2: 'custom-value2',
});
```
## Code Examples
You can find various usage examples in the [examples folder](https://github.com/descope/node-sdk/blob/main/examples).
### 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](https://app.descope.com/settings/project).
```bash
export DESCOPE_PROJECT_ID=<ProjectID>

@@ -41,9 +586,8 @@ ```

**TL;DR**: Run `npm run quick`
Run the following commands in the root of the project to build and run the examples with a local build
of the SDK.
Run the following commands in the root of the project to build and run the examples.
1. Run this to start the ES6 typescript module example
```code bash
```bash
npm i && \

@@ -59,3 +603,3 @@ npm run build && \

```code bash
```bash
npm i && \

@@ -69,4 +613,12 @@ npm run build && \

## Learn More
To learn more please see the [Descope Documentation and API reference page](https://docs.descope.com/).
## Contact Us
If you need help you can email [Descope Support](mailto:support@descope.com)
## License
The Descope ExpresSDK for Node is licensed for use under the terms and conditions of the [MIT license Agreement](https://github.com/descope/node-sdk/blob/main/LICENSE).
The Descope SDK for Node.js is licensed for use under the terms and conditions of the [MIT license Agreement](https://github.com/descope/node-sdk/blob/main/LICENSE).

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc