Skip to content

Flows in AuthHero ​

Flows in AuthHero provide a powerful way to orchestrate complex authentication and user management workflows. Unlike forms which focus on UI presentation, flows handle the business logic and actions that need to be performed during authentication processes.

Overview ​

A flow consists of a sequence of actions that are executed in order. Flows can be triggered through:

  • Post-login hooks
  • Post-registration hooks
  • Manual API calls
  • Form node navigation

Flow Structure ​

A basic flow has the following structure:

json
{
  "id": "flow_abc123",
  "name": "Email Verification Flow",
  "actions": [
    {
      "id": "verify_email",
      "type": "EMAIL",
      "action": "VERIFY_EMAIL",
      "params": {
        "email": "{{user.email}}",
        "rules": {
          "require_mx_record": true,
          "block_disposable_emails": true
        }
      },
      "allow_failure": false,
      "mask_output": false
    }
  ],
  "created_at": "2024-12-21T10:00:00.000Z",
  "updated_at": "2024-12-21T10:00:00.000Z"
}

Action Types ​

Flows support multiple action types for different purposes:

AUTH0 Actions ​

Auth0-compatible actions for user management:

UPDATE_USER ​

Updates user attributes:

json
{
  "id": "update_metadata",
  "type": "AUTH0",
  "action": "UPDATE_USER",
  "params": {
    "user_id": "{{user.user_id}}",
    "changes": {
      "app_metadata": {
        "onboarded": true
      }
    }
  }
}

CREATE_USER ​

Creates a new user (typically used in migration scenarios):

json
{
  "id": "create_user",
  "type": "AUTH0",
  "action": "CREATE_USER",
  "params": {
    "email": "[email protected]",
    "password": "secure_password",
    "connection_id": "con_123"
  }
}

GET_USER ​

Retrieves user information:

json
{
  "id": "get_user",
  "type": "AUTH0",
  "action": "GET_USER",
  "params": {
    "user_id": "auth0|123456"
  }
}

SEND_EMAIL ​

Sends an email to the user:

json
{
  "id": "send_welcome_email",
  "type": "AUTH0",
  "action": "SEND_EMAIL",
  "params": {
    "to": "{{user.email}}",
    "subject": "Welcome!",
    "template": "welcome_email"
  }
}

EMAIL Actions ​

Email-specific validation and verification:

VERIFY_EMAIL ​

Validates email addresses with configurable rules:

json
{
  "id": "verify_email",
  "type": "EMAIL",
  "action": "VERIFY_EMAIL",
  "params": {
    "email": "{{user.email}}",
    "rules": {
      "require_mx_record": true,
      "block_aliases": false,
      "block_free_emails": false,
      "block_disposable_emails": true,
      "blocklist": ["spam.com", "test.com"],
      "allowlist": ["company.com"]
    }
  }
}

Validation Rules:

  • require_mx_record: Verify the domain has valid MX records
  • block_aliases: Block email addresses with + aliases (e.g., [email protected])
  • block_free_emails: Block common free email providers (Gmail, Yahoo, etc.)
  • block_disposable_emails: Block temporary/disposable email services
  • blocklist: Array of domains to block
  • allowlist: Array of domains to explicitly allow (overrides other rules)

REDIRECT Actions ​

AuthHero-specific feature for redirecting users during authentication flows:

REDIRECT_USER ​

Redirects the user to a predefined or custom URL while maintaining the authentication session state:

json
{
  "id": "redirect_to_email_change",
  "type": "REDIRECT",
  "action": "REDIRECT_USER",
  "params": {
    "target": "change-email"
  }
}

Pre-defined Targets:

  • change-email: Redirects to /u/account/change-email?state=...
  • account: Redirects to /u/account?state=...
  • custom: Redirects to a custom URL (requires custom_url parameter)

Custom URL Example:

json
{
  "id": "redirect_to_onboarding",
  "type": "REDIRECT",
  "action": "REDIRECT_USER",
  "params": {
    "target": "custom",
    "custom_url": "/onboarding/welcome"
  }
}

State Preservation:

The redirect action automatically appends the authentication state to the redirect URL, ensuring the user can continue their authentication flow after completing the redirected action. For example:

  • Pre-defined targets automatically include ?state={loginSessionId}
  • Custom URLs get the state appended: /onboarding/welcome?state={loginSessionId}

This is particularly useful for:

  • Forcing email changes for users with invalid email patterns
  • Requiring profile completion before authentication
  • Conditional onboarding based on user attributes
  • Custom consent flows

Action Parameters ​

Common Parameters ​

All actions support these common parameters:

  • id (required): Unique identifier for the action step
  • alias (optional): Human-readable name for the action (max 100 characters)
  • type (required): The action type (AUTH0, EMAIL, or REDIRECT)
  • action (required): The specific action to perform
  • allow_failure (optional): If true, the flow continues even if this action fails
  • mask_output (optional): If true, the action output is not logged (useful for sensitive data)

Template Variables ​

Many action parameters support template variables using the syntax:

  • {{user.email}}: User's email address
  • {{user.user_id}}: User's unique ID
  • {{user.name}}: User's display name
  • {{user.app_metadata.field}}: Custom app metadata fields
  • {{user.user_metadata.field}}: Custom user metadata fields

Flow Execution ​

Execution Order ​

Actions are executed sequentially in the order they appear in the actions array. Each action must complete before the next one starts.

Error Handling ​

By default, if an action fails, the entire flow stops and returns an error. You can change this behavior with:

json
{
  "id": "optional_action",
  "type": "EMAIL",
  "action": "VERIFY_EMAIL",
  "allow_failure": true,
  "params": { ... }
}

When allow_failure: true, the flow continues to the next action even if this one fails.

Output Masking ​

Sensitive data can be masked from logs:

json
{
  "id": "sensitive_update",
  "type": "AUTH0",
  "action": "UPDATE_USER",
  "mask_output": true,
  "params": { ... }
}

This prevents the action's output from appearing in execution logs.

Using Flows with Forms ​

Flows can be integrated with forms through ACTION nodes. This allows forms to trigger redirects or other actions based on conditional routing:

json
{
  "nodes": [
    {
      "id": "check_email",
      "type": "ROUTER",
      "config": {
        "rules": [
          {
            "id": "invalid_email_rule",
            "condition": {
              "operator": "ends_with",
              "field": "{{context.user.email}}",
              "value": "@oldcompany.com"
            },
            "next_node": "redirect_to_change_email"
          }
        ],
        "fallback": "continue_flow"
      }
    },
    {
      "id": "redirect_to_change_email",
      "type": "ACTION",
      "config": {
        "action_type": "REDIRECT",
        "target": "change-email",
        "next_node": "$ending"
      }
    }
  ]
}

In this example:

  1. A ROUTER node checks the user's email
  2. If it ends with @oldcompany.com, it routes to an ACTION node
  3. The ACTION node redirects the user to the change-email page
  4. The state is preserved, allowing the user to continue after changing their email

API Endpoints ​

Flows can be managed through the Management API:

List Flows ​

http
GET /api/v2/flows
Authorization: Bearer {access_token}

Get Flow ​

http
GET /api/v2/flows/{flow_id}
Authorization: Bearer {access_token}

Create Flow ​

http
POST /api/v2/flows
Authorization: Bearer {access_token}
Content-Type: application/json

{
  "name": "My Flow",
  "actions": [...]
}

Update Flow ​

http
PATCH /api/v2/flows/{flow_id}
Authorization: Bearer {access_token}
Content-Type: application/json

{
  "name": "Updated Flow Name",
  "actions": [...]
}

Delete Flow ​

http
DELETE /api/v2/flows/{flow_id}
Authorization: Bearer {access_token}

Best Practices ​

1. Use Descriptive Names and Aliases ​

json
{
  "name": "Post-Login Email Verification",
  "actions": [
    {
      "id": "verify_email_step",
      "alias": "Verify user email is valid",
      "type": "EMAIL",
      "action": "VERIFY_EMAIL"
    }
  ]
}

2. Handle Failures Gracefully ​

Consider which actions are critical and which can fail:

json
{
  "actions": [
    {
      "id": "verify_email",
      "type": "EMAIL",
      "action": "VERIFY_EMAIL",
      "allow_failure": false // Critical
    },
    {
      "id": "send_analytics",
      "type": "AUTH0",
      "action": "SEND_REQUEST",
      "allow_failure": true // Non-critical
    }
  ]
}

3. Mask Sensitive Data ​

Always mask sensitive information in action outputs:

json
{
  "id": "update_password",
  "type": "AUTH0",
  "action": "UPDATE_USER",
  "mask_output": true,
  "params": {
    "user_id": "{{user.user_id}}",
    "changes": {
      "password": "new_password"
    }
  }
}

4. Use Template Variables ​

Leverage template variables for dynamic values:

json
{
  "params": {
    "email": "{{user.email}}",
    "name": "{{user.name}}",
    "custom_field": "{{user.app_metadata.custom_field}}"
  }
}

5. Keep Flows Focused ​

Create separate flows for different purposes rather than one large flow:

  • ✅ "Email Verification Flow"
  • ✅ "User Onboarding Flow"
  • ✅ "Profile Update Flow"
  • ❌ "Everything Flow"

Comparison with Auth0 Actions ​

FeatureAuth0 ActionsAuthHero Flows
ConfigurationCode-based (Node.js)JSON configuration
ExecutionServerless functionsBuilt-in execution engine
Email ValidationCustom implementationBuilt-in EMAIL actions
RedirectsLimitedFull REDIRECT action support
Template VariablesLimitedExtensive support
TestingComplex (separate deployment)Simple (API-based)

Examples ​

Example 1: Email Validation Flow ​

json
{
  "name": "Validate Corporate Email",
  "actions": [
    {
      "id": "verify_email",
      "alias": "Ensure email is from company domain",
      "type": "EMAIL",
      "action": "VERIFY_EMAIL",
      "params": {
        "email": "{{user.email}}",
        "rules": {
          "allowlist": ["company.com"],
          "require_mx_record": true
        }
      },
      "allow_failure": false
    }
  ]
}

Example 2: Conditional Redirect Flow ​

json
{
  "name": "Force Email Update for Legacy Users",
  "actions": [
    {
      "id": "redirect_legacy_users",
      "alias": "Redirect users with old email pattern",
      "type": "REDIRECT",
      "action": "REDIRECT_USER",
      "params": {
        "target": "change-email"
      }
    }
  ]
}

This flow would typically be used with a form ROUTER that checks email patterns first.

Example 3: User Onboarding Flow ​

json
{
  "name": "New User Onboarding",
  "actions": [
    {
      "id": "set_metadata",
      "alias": "Mark user as new",
      "type": "AUTH0",
      "action": "UPDATE_USER",
      "params": {
        "user_id": "{{user.user_id}}",
        "changes": {
          "app_metadata": {
            "onboarded": false,
            "created_at": "{{timestamp}}"
          }
        }
      }
    },
    {
      "id": "redirect_onboarding",
      "alias": "Send to onboarding",
      "type": "REDIRECT",
      "action": "REDIRECT_USER",
      "params": {
        "target": "custom",
        "custom_url": "/onboarding"
      }
    }
  ]
}

See Also ​

Dual-licensed: AGPL-3.0-only or commercial license.