How to Use Inline Hooks for Custom Authentication Flows in Logto

Logto supports inline hooks—sandboxed JavaScript snippets that execute at predefined points in the authentication pipeline—to extend sign-in flows without deploying separate microservices.

The logto-io/logto repository provides a powerful extension mechanism for customizing authentication behavior through inline hooks. These hooks allow you to inject custom logic directly into the sign-in flow, enabling data enrichment, custom validation, or external system integration without maintaining standalone webhook services. By leveraging the built-in execution engine in packages/core/src/libraries/inline-hook.ts, you can modify user objects or create profiles synchronously during authentication.

Understanding Inline Hook Types

Logto currently supports two distinct hook types that trigger at specific stages of the authentication lifecycle:

  • inlineHook.postFirstFactorVerification: Executes after the user passes the first authentication factor (e.g., password verification) but before the session is created.
  • inlineHook.postSignIn: Runs immediately after a successful sign-in completes, before the response returns to the client.

Each hook receives a typed event payload and must return a structured result object that dictates the next action in the flow.

Post-First-Factor Verification Hook

According to the schema definitions in packages/schemas/src/types/logto-config/inline-hook.ts, the PostFirstFactorVerificationEvent payload contains the interaction identifier, the entered password, and the sign-in event details. Your script must return a PostFirstFactorVerificationResult indicating whether to create a new user, update an existing one, or confirm the password verification status.

Post-Sign-In Hook

The PostSignInEvent provides the signed-in user object to your script. The returned PostSignInResult can modify the user profile before finalizing the session, making this hook ideal for last-minute data augmentation or synchronization tasks.

Hook Execution Model and Result Contracts

When enabled, Logto executes your hook script in a sandboxed VM (or remote isolated runner for Logto Cloud deployments). The runtime logic in packages/core/src/libraries/inline-hook.ts loads the hook configuration, validates the enabled flag, injects environment variables, and applies the returned actions.

Your script must export an async function that accepts the event object and returns a result with an action property:

  • For post-first-factor hooks: action can be 'createUser' or 'updateUser', with passwordVerified: true required to proceed.
  • For post-sign-in hooks: action can be 'updateUser' to modify profile attributes before session finalization.

Error handling follows the onExecutionError policy defined in your hook configuration. If set to block, authentication aborts immediately upon script failure; if allow, errors are logged but the flow continues. User-facing error messages are localized in packages/phrases/src/locales/en/errors/inline-hook.ts.

Managing Inline Hooks via the REST API

The OpenAPI specification in packages/core/src/routes/logto-config/inline-hook.openapi.json documents the CRUD endpoints for hook management under the Logto Config routes.

Registering a New Hook

Create a hook by POSTing to /api/configs/inline-hooks:

POST https://<your-logto-domain>/api/configs/inline-hooks
Content-Type: application/json

{
  "hookType": "inlineHook.postFirstFactorVerification",
  "script": "module.exports = async (event) => {\n  if (!event.identifier.email) {\n    return { action: 'createUser', user: { primaryEmail: event.identifier.email }, passwordVerified: true };\n  }\n  return { action: 'updateUser', user: {}, passwordVerified: true };\n};",
  "environmentVariables": {
    "WELCOME_MESSAGE": "Welcome to MyApp!"
  },
  "enabled": true,
  "onExecutionError": "block"
}

Testing Hooks Locally

Validate your logic before enabling production traffic by using the test endpoint:

POST https://<your-logto-domain>/api/configs/inline-hooks/test
Content-Type: application/json

{
  "hookType": "inlineHook.postFirstFactorVerification",
  "script": "module.exports = async (event) => ({ action: 'updateUser', user: { name: 'Test User' }, passwordVerified: true });",
  "event": {
    "key": "inlineHook.postFirstFactorVerification",
    "interactionEvent": "SignIn",
    "identifier": { "type": "email", "value": "john@example.com" },
    "password": "s3cr3t"
  },
  "environmentVariables": {}
}

The response contains the result object or detailed error information if the script execution failed.

Deleting a Hook

Remove a hook by its type:

DELETE https://<your-logto-domain>/api/configs/inline-hooks/inlineHook.postSignIn

Implementation Examples

Auto-Creating User Profiles After First Factor Verification

This hook automatically provisions a user profile if missing after password verification:

// inlineHook.postFirstFactorVerification
module.exports = async (event) => {
  if (!event.identifier.email) {
    return { 
      action: 'createUser', 
      user: { primaryEmail: event.identifier.email }, 
      passwordVerified: true 
    };
  }
  return { 
    action: 'updateUser', 
    user: {}, 
    passwordVerified: true 
  };
};

Augmenting User Data After Sign-In

Add custom claims or sync data to external systems before the session is finalized:

// inlineHook.postSignIn
module.exports = async (event) => {
  const { user } = event;
  const updated = { 
    ...user, 
    customData: { 
      welcomeMessage: process.env.WELCOME_MESSAGE 
    } 
  };
  return { 
    action: 'updateUser', 
    user: updated 
  };
};

Architecture and Source Code Reference

The inline hook system spans four key components in the Logto codebase:

Summary

  • Logto provides two inline hook types—postFirstFactorVerification and postSignIn—enabling custom logic at critical authentication stages.
  • Hook scripts run in sandboxed environments and must return structured result objects with specific action types (createUser or updateUser).
  • The onExecutionError policy determines whether script failures block authentication (block) or allow it to continue (allow).
  • Manage hooks via the /api/configs/inline-hooks endpoints, with support for local testing using the /test endpoint before deployment.
  • Core implementation files include the schema definitions, execution library, and OpenAPI specifications in the logto-io/logto repository.

Frequently Asked Questions

What is the difference between inline hooks and webhooks in Logto?

Inline hooks execute JavaScript code directly within the Logto authentication process using a sandboxed runtime, while webhooks send HTTP requests to external services. Inline hooks are ideal for synchronous logic that must complete before the authentication flow continues, such as data validation or immediate user profile updates.

Can I use external npm packages in my inline hook scripts?

No, inline hooks run in a restricted sandbox environment without access to external package registries. You must use vanilla JavaScript and the built-in Node.js APIs available in the sandbox. For complex dependencies requiring external libraries, consider using webhooks instead to delegate processing to an external service.

How do I debug an inline hook that is failing in production?

Set the onExecutionError configuration to block during development to ensure failures surface immediately, and use the /api/configs/inline-hooks/test endpoint to validate scripts against sample contexts. Check the Logto Core logs for detailed error messages defined in packages/phrases/src/locales/en/errors/inline-hook.ts, which indicate whether failures stem from syntax errors, timeout issues, or invalid result objects.

What environment variables are available to inline hook scripts?

You define custom environment variables in the hook configuration when creating or updating the hook via the API. These variables are injected into the script's process.env at runtime, allowing you to store sensitive values like API keys or configuration flags without hardcoding them in the script source.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →