loading
Preparing LoginRadius developer resources
Mission: Help enterprises accelerate digital transformation with our fully-managed Customer IAM technology.
Skip to main content

IO Script Examples

Three common patterns ready to copy into your IO Script editor.


Example 1: Set a custom field on the identity

Where to place: After Auth → true, before the Success Final node.

What it does: Reads the utm_source query parameter from the initiating URL and writes it to a custom field signupSource on the user's profile.

// Sets a custom field "signupSource" on the user's profile
exports.execute = async (lrObject, hook) => {
const uid = await lrObject.getUid();
if (!uid) {
hook.setError(500, "uid_unavailable", "Could not resolve user identity.");
return;
}

const source = hook.getQueryParam("utm_source") || "direct";
await lrObject.updateProfile(uid, { CustomFields: { signupSource: source } });
};

Example 2: Check an external blocklist before registration

Where to place: After the registration Web Page node, before Create User.

What it does: Calls an external blocklist API with the submitted email. Calls hook.setError() if the email is blocked, routing to the false output and preventing account creation.

// Checks an external blocklist before allowing registration
exports.execute = async (lrObject, hook) => {
const email = hook.getFormField("email");
if (!email) {
hook.setError(400, "missing_email", "Email field is required.");
return;
}

const res = await fetch(
`https://api.example.com/blocklist?email=${encodeURIComponent(email)}`
);
const { blocked } = await res.json();

if (blocked) {
hook.setError(400, "email_blocklisted", "This email address is not permitted.");
return;
}
};

Timeout

If api.example.com is slow, wrap the fetch in a Promise.race with a 4-second timeout to stay within the 5-second script limit.


Example 3: Inspect access token and set session flags

Where to place: After Auth → true, before any downstream MFA or enrichment step.

What it does: Decodes the JWT access token (informational only: no signature verification) and stores the expiry time and issuer in session state for downstream nodes.

// Reads the access token from session and stores expiry info
exports.execute = async (lrObject, hook) => {
const token = lrObject.getAccessToken();
if (!token) {
hook.setError(401, "token_unavailable", "No access token found in session.");
return;
}

// Decode JWT payload: informational only, no signature verification
const [, payload] = token.split(".");
const decoded = JSON.parse(Buffer.from(payload, "base64").toString());
hook.sharedState.set("tokenExp", String(decoded.exp));
hook.sharedState.set("tokenIssuer", decoded.iss);
};

JWT payload is not trusted input

This pattern is useful for logging or routing decisions. Never use the decoded payload as a trust boundary: always verify tokens server-side using your API key secret when making security decisions.


API references