The User Flow v2 system provides a flexible, step-by-step process for user authentication, registration, account management and other user-related workflows. The system is designed to be used by client applications (web or mobile) that communicate with the API, with the client responsible for rendering the UI components returned by the API.
- The client application initiates a flow by calling the API endpoint with an action parameter
- The server responds with UI elements that should be rendered by the client
- The client renders these elements and collects user input
- The client sends the input back to the server along with the session token
- This process repeats until the flow is complete (indicated by
complete: truein the response)
The API returns a JSON object with the following structure:
{
"complete": false, // Whether the flow is complete
"initial": true, // Whether this is the first step
"email": "user@example.com", // Email if available
"req": ["field1", "field2"], // Required fields that must be submitted
"fields": [], // UI elements to render (see below)
"message": "Login", // Message to display (was flow_action_login token)
"session": "encrypted_session_token", // Session token to pass back
"realm_flags": ["flag1", "flag2"], // Realm flags
"user": {} // User object if available
}When the flow is complete, the response will be:
{
"complete": true, // Flow is complete
"user": {}, // User object
"Redirect": "/destination", // URL to redirect to
"Token": "oauth_token" // OAuth token if applicable
}If a redirection is needed (oauth2, etc), the response will look as follows:
{
"complete": false,
"url": "https://...", // URL to redirect to
}The fields array contains UI elements that should be rendered by the client. Each element has a specific structure based on its type:
{
"cat": "label",
"type": "label",
"label": "Please provide your email in order to login",
"style": "error", // Optional - can be "error" for error messages
"link": "url_or_action" // Optional - makes the label clickable with a URL or action
}Actions can be triggered using the @action syntax in the link field:
{
"cat": "label",
"type": "label",
"label": "Forgot your password?",
"link": "@action=reset_password"
}When the user clicks on a label with an @action link, the client should:
- Reset the current session data
- Initiate a new flow with the specified action
- Stay on the same UI view
- Send a request to the API with the new action but no session token
The server will respond with the initial step of the new flow action. This allows for seamless transitions between different flows (e.g., from login to password reset) without redirecting the user.
{
"cat": "input",
"name": "email",
"type": "email", // Can be: text, email, password, phone
"label": "Email",
"format": "AAAA-AAAA", // Optional format hint
"attributes": {"autocomplete": "off"} // Optional HTML attributes
}If checked the value true (or 1 if sending as url encoded or MIME POST data) must be passed into the form.
{
"cat": "input",
"name": "agree_terms",
"type": "checkbox",
"label": "I agree to the Terms of Service",
}{
"cat": "input",
"type": "select",
"name": "country",
"label": "Select your country",
"values": [
{
"value": "us",
"display": "United States"
},
{
"value": "ca",
"display": "Canada"
}
],
"default": "us"
}For select inputs that need to fetch options dynamically from an API:
{
"cat": "input",
"type": "select",
"name": "country",
"label": "Select your country",
"source": {
"api": "Country",
"label_field": "Name",
"key_field": "Country__"
},
"default": "US"
}When a select field has a source property:
- The API specified in
apimust be called to retrieve the select options label_fieldspecifies the field name to use for display text of each optionkey_fieldspecifies the field name to use for the value of each option- If a value is already set for this field, it should be pre-selected
- If no value is set but
defaultis provided, that value should be pre-selected
{
"type": "oauth2",
"id": "provider_id",
"info": {}, // Provider information
"button": { // Button style
"text": "Sign in with Google",
"color": "#4285F4",
"textColor": "#ffffff",
"icon": "google_icon.svg"
}
}{
"cat": "special",
"name": "profile_pic",
"type": "image",
"target": "User/@/Profile:addImage",
"param": {"purpose": "main"}
}Input fields can include a validation property to enforce specific validation rules on the client side.
| Type | Description |
|---|---|
equal_other_field |
Validates that the field value matches another field's value |
Used to validate that one field's value matches another field. Common use case is password confirmation:
{
"cat": "input",
"name": "password2",
"type": "password",
"label": "Confirm Password",
"validation": {
"type": "equal_other_field",
"field": "password"
}
}When a field has this validation:
- The client should validate that the value entered matches the value of the field specified in
field - Validation should occur before form submission
- If validation fails, display an appropriate error message (e.g., "Passwords do not match")
The system supports various flow actions:
login: User authenticationregister: New user registrationrecover_account: Account recoverydelete_account: Account deletionreset_password: Password resetchange_email: Email changeswitch: Switch between accounts (e.g., parent/child)
-
Start Flow:
- Call the API with the desired action (e.g.,
login) - Receive initial fields to render
- Call the API with the desired action (e.g.,
-
Render UI:
- Render the UI elements from the
fieldsarray - Display any messages from the
messageobject - Mark required fields based on the
reqarray
- Render the UI elements from the
-
Submit Data:
- When user inputs data and submits, send the form data to the API
- Always include the
sessiontoken in subsequent requests
-
Continue Flow:
- Process the response and render new fields if provided
- Check the
completeflag to know when the flow is finished - When
completeis true, follow any redirect or use the provided token
-
Handle Errors:
- If the API returns an error, display it to the user
- Fields with errors may have a
style: "error"attribute
-
Handle Flow Transitions:
- Labels with
linkcontaining "@action=..." indicate flow navigation options - When a user clicks on an @action link, the client should reset the session and start a new flow with the specified action
- This keeps the user on the same UI while changing the logical flow (e.g., switching from login to password reset)
- Labels with
When the flow presents an OAuth2 button, you need to handle the OAuth2 authentication flow:
-
OAuth2 Button Handling:
- When an OAuth2 button appears in the
fieldsarray, render it with the styling information provided - The button should be associated with the provider's ID from the
idfield
- When an OAuth2 button appears in the
-
Starting the OAuth2 Flow:
- When the user clicks an OAuth2 button, send a request to the flow API with:
{ "oauth2": "[provider_id]", "session": "[current_session_token]" }
- When the user clicks an OAuth2 button, send a request to the flow API with:
-
Redirect to Provider:
- The API will respond with a JSON object containing a URL:
{ "complete": false, "url": "https://provider.com/auth?params..." } - Redirect the user to this URL to authenticate with the provider
- The API will respond with a JSON object containing a URL:
-
Handling the Callback:
- The provider will redirect back to your application with query parameters including:
?session=[updated_session_token] - Extract the updated
sessionparameter from the URL
- The provider will redirect back to your application with query parameters including:
-
Continuing the Flow:
- Send a request to the flow API with only the updated session token:
{ "session": "[updated_session_token_from_callback]" } - The API will continue the flow
- Send a request to the flow API with only the updated session token:
-
Completion:
- The API will respond with
"complete": trueand tokens or user data - Use the returned tokens for API access or follow any provided redirect
- The API will respond with
- The session token is encrypted and has a 30-minute expiration
- Sensitive flows require OTP verification
- Password inputs should use proper security measures (autocomplete, etc.)
- OAuth flows include proper validation of redirect URIs
- Client initiates login flow
- Server returns email input field
- User enters email, client submits
- Server returns password field
- User enters password, client submits
- If OTP is enabled, server returns OTP input
- User enters OTP, client submits
- Server returns
complete: truewith user data - Client redirects to the designated page or application
- Client initiates registration flow
- Server returns registration form fields (name, email, password, etc.)
- User fills out form, client submits
- If email verification is required, server sends email and returns code input
- User enters verification code, client submits
- Server returns
complete: truewith user data - Client redirects to the designated page or application
- Client initiates login flow
- Server returns login options including OAuth2 provider buttons
- User clicks an OAuth2 provider button (e.g., Google)
- Client sends request with
oauth2: "google"and current session - Client receives URL and redirects user to Google's auth page
- User authenticates with Google
- Google redirects back to the application with code and updated session
- Client extracts the updated session from the URL
- Client sends request with only the updated session token
- Server completes the flow and returns user data and tokens
- Client uses the provided tokens for API access