Scriptlets

Flows are built from screens, actions, conditions, and connectors. Those steps are customizable, but their outputs are fixed shapes that Descope writes into the flow context.

When you need something more flexible — hashing, date math, string transforms, or other small logic that does not fit a built-in action — use the Scriptlet action. It runs custom JavaScript in the flow and writes the values you return back into context.

Scriptlet action in the flow editor

Using Scriptlets

Add a Scriptlet action from the flow editor, then configure arguments, code, the result context key, and optional overrides.

Arguments

Arguments pass values into the script. Each argument has a name (used as a variable in your code) and a source:

TypeDescription
DynamicValue read from flow context at runtime (for example form.displayName)
String / Boolean / Number / TimeStatic value you set in the action, validated by type

Scriptlet arguments

In the example above, the Scriptlet builds a greeting string. If form.displayName is empty, it falls back to a static default such as John.

Available Libraries

The Scriptlet runtime includes:

  • Lodash — iteration, object helpers, and similar utilities
  • CryptoJS — hashing and related crypto helpers

Use them directly in your script (for example Lodash collection helpers or CryptoJS hash functions).

Note

Secure random number generation (for example CryptoJS.lib.WordArray.random()) is not supported in Scriptlets.

For non-cryptographic random values, use Math.random() instead.

Context Key

The object your script returns is stored under the context key you configure (default paths look like scripts.scriptletResult).

Scriptlet context key

Example output shape:

{
  "scripts": {
    "scriptletResult": {
      "greeting": "Hello, John!"
    }
  }
}

Later actions and conditions can read those keys from context (for example scripts.scriptletResult.greeting).

Overrides

Use Overrides to copy Scriptlet results onto existing flow context keys such as form.displayName, form.email, or form.customAttributes.*.

Scriptlet overrides

For example, strip + subaddresses from an email in the Scriptlet, return { email: result }, then override form.email with scripts.scriptletResult.email:

let result = email;
const domainIndex = email.lastIndexOf('@');
if (domainIndex > -1) {
  // Treat '+' after the first character as a subaddress separator
  const aliasIndex = email.substring(1).indexOf('+') + 1;
  if (aliasIndex > 0) {
    result = email.substring(0, aliasIndex) + email.substring(domainIndex);
  }
}

return {
  email: result,
};

Mapping a Scriptlet result onto form.email

If you override a custom screen input, define that field's context key on the screen component first.

Custom input component context key

Overriding the Tenant

To switch tenants in an existing session without running another flow, use selectTenant on the client SDKs.

If a Scriptlet overrides tenant-related context keys, Descope includes the dct (Descope Current Tenant) claim in the resulting JWT, updates JWT structure as needed, and applies tenant-specific roles and permissions.

Logging and Debugging

Scriptlets support the standard console methods - console.log(), console.warn(), console.error(), and console.debug().

Anything you log is written to the Flow Runner messages when you run the flow from the Descope console. This lets you inspect intermediate values while the flow executes, without having to return them into flow context just to see them.

console.log(`Incoming email: ${email}`);

const domainIndex = email.lastIndexOf('@');

if (domainIndex === -1) {
  console.error(`Email is missing a domain: ${email}`);
  return {};
}

const domain = email.substring(domainIndex + 1);
console.debug(`Extracted domain: ${domain}`);

return {
  domain: domain,
};

Scriptlet console output in the Flow Runner messages panel

To view the output, run your flow from Flows in the Descope console and check the Runner messages panel below your flows.

Testing Scriptlets

Use Test in the Scriptlet editor before you rely on the action in a live flow.

The test panel lists the Arguments you defined above. For each Dynamic argument, you can override the value that would normally come from flow context — enter any sample input you want to try. Static arguments keep the values you already set on the action.

Run the test to see the object the Scriptlet would return (and therefore what lands under your context key). That makes it easy to confirm hashing, date math, or string transforms without stepping through the full flow.

Scriptlet test panel

Examples

Here are some examples of how to use Scriptlets in Flows.

Hash an Email Domain for a Tenant ID

Create a tenant for a new user and derive a stable tenant ID from the user's email domain (for example with CryptoJS hashing), then pass that value into Create Tenant.

Flow that creates a tenant for a new user

Scriptlet that hashes the email domain

Create Tenant action using the Scriptlet result

Time-Based MFA Condition

Prompt for MFA when the user has not authenticated in the last 30 days.

Flow that branches into MFA

Compare last authentication time to the current time in a Scriptlet:

Scriptlet comparing last auth time to now

Use the boolean (or age) output in a Condition step:

Condition using the Scriptlet output

Was this helpful?

On this page