Single Sign-On Deep Link
This guide explains how to integrate External Auth SSO into your whitelabel project. Your backend requests a one-time magic login link from our API using a signed payload. When the user is redirected to that link, they are instantly authenticated and sent to your chosen destination page. The document covers required setup, request/response formats, signature generation, common errors, testing steps, and a ready-to-use Postman collection.
1. Before You Start — Required PBO Settings
Enable SSO in your PBO dashboard:
- Go to Configuration
- Enable Customer Login
- Enable SSO
- Add your SSO Redirect URL (this is the fallback page for expired or invalid magic links)
Your SSO flow will not work without these settings.
2. How the SSO Flow Works
The flow is simple:
- Your system requests a magic login link from our API.
- We return the link.
- You redirect the user to it.
- The user is automatically logged in and sent to your chosen page.
3. Step-by-Step Workflow for Integration
Step 1 — Your backend calls our API
POST https://{wl.domain.com}/v1/guest/auth/external-auth
Request Body Example
{
"email": "[email protected]",
"firstName": "First",
"lastName": "Last",
"externalUserId": "CLIENT-123",
"timestamp": 1763466236,
"signature": "HMAC_SIGNATURE_HERE",
"redirectUrl": "https://project-domain.example/hotels"
}
Required Headers
Content-Type: application/json
X-Liteapi-Key: <your LiteAPI key>
Signature Creation
payload = email + ":" + timestamp + ":" + externalUserId
signature = HMAC_SHA256(liteApiKey, payload)
- The timestamp must be within ±5 minutes of current time.
Step 2 — We return a Magic Login URL
Example response:
{
"loginUrl": "https://project-domain.example/auth/magic-login?token=ABC123&redirectUrl=https%3A%2F%2Fproject-domain.example%2Fhotels"
}
The magic link:
- Logs the user in immediately
- Is valid once only
- Expires in ~30 minutes
- Contains all necessary session context
Step 3 — Redirect the User to loginUrl
loginUrlPerform a standard 302 redirect:
302 → https://project-domain.example/auth/magic-login?token=ABC123...
Do not modify the URL.
Step 4 — User Logs In and Gets Forwarded
After opening the magic link:
- Token is validated
- User is created or logged in
- User is forwarded to your original redirect URL
Successful Redirect Example
https://project-domain.example/hotels?token=<session>&magicLogin=true
Invalid / Used Token Redirect Example
https://your-site.example/sso-error?error=TOKEN_ALREADY_USED&magicLogin=true
4. Complete Example (Start → End)
Your Request
{
"email": "[email protected]",
"firstName": "Sarah",
"lastName": "Smith",
"externalUserId": "USER-001",
"timestamp": 1763466236,
"signature": "ab28fd91c0...",
"redirectUrl": "https://travel-brand.example/hotels"
}
Our Response
{
"loginUrl": "https://travel-brand.example/auth/magic-login?token=Zxcv098765..."
}
Browser Redirect
https://travel-brand.example/auth/magic-login?token=Zxcv098765...
Final Landing Page
https://travel-brand.example/hotels?token=<session>&magicLogin=true
5. Common Errors
| Error | Meaning | Fix |
|---|---|---|
| INVALID_SIGNATURE | Signature doesn’t match | Ensure payload is exactly email:timestamp:externalUserId |
| EXPIRED_REQUEST | Timestamp older than 5 min | Create new timestamp + signature |
| INVALID_INPUT | Missing or invalid values | Check spelling and required fields |
| TOKEN_ALREADY_USED | Magic link opened twice | Generate a fresh link |
| Missing SSO settings | SSO disabled or fallback missing | Confirm PBO settings |
6. Magic Login Link Behavior
When visiting loginUrl:
- Token is validated
- User logs into the whitelabel project
- User is redirected to:
{redirectUrl}?token=<session>&magicLogin=true
If token is invalid or reused, user is redirected to:
{ssoReturnUrl}?error=...&magicLogin=true
ssoReturnUrl must be an HTTPS URL that you control.
7. Setup Checklist
- LiteAPI key (used in header + HMAC secret)
- Enable SSO
- Set Fallback redirect URL (e.g.,
https://your-site.example/sso-error) - Allowed domains configured
- HTTPS used everywhere
8. Testing Tips
Shell Example
ts=$(date +%s)
payload="[email protected]:${ts}:CLIENT-123"
signature=$(printf '%s' "$payload" | openssl dgst -sha256 -hmac "$LITEAPI_KEY" | awk '{print $2}')
curl -X POST "https://{wl.domain.com}/v1/guest/auth/external-auth" \
-H "Content-Type: application/json" \
-H "X-Liteapi-Key: $LITEAPI_KEY" \
-d "{\"email\":\"[email protected]\",\"firstName\":\"First\",\"lastName\":\"Last\",\"externalUserId\":\"CLIENT-123\",\"timestamp\":${ts},\"signature\":\"${signature}\",\"redirectUrl\":\"https://project-domain.example/hotels\"}"
Open the loginUrl returned in the response.
To test an error:
Open the same link twice → should redirect with TOKEN_ALREADY_USED.
9. Troubleshooting
-
JSON response instead of redirect
Likely accessing the magic link at the API host instead of project domain.
Also ensureisSsoActive+ssoReturnUrlare set. -
Signature mismatch
Remove stray spaces; ensure email casing and timestamp match the signature generation. -
Token already used
Request a new magic link.
For help, contact integrations support with:
- timestamp
- project domain
10. Postman Collection
JSON
{
"info": {
"_postman_id": "2858d35b-3368-4c81-8c8c-33f282a6a2e1",
"name": "External Auth SSO",
"description": "Sample requests for the /v1/guest/auth/external-auth flow.",
"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json",
"_exporter_id": "31030075"
},
"item": [
{
"name": "Create Magic Login Link",
"request": {
"method": "POST",
"header": [
{ "key": "Content-Type", "value": "application/json" },
{ "key": "X-Liteapi-Key", "value": "{{liteApiKey}}" }
],
"body": {
"mode": "raw",
"raw": "{\n \"email\": \"{{email}}\",\n \"firstName\": \"{{firstName}}\",\n \"lastName\": \"{{lastName}}\",\n \"externalUserId\": \"{{externalUserId}}\",\n \"timestamp\": {{timestamp}},\n \"signature\": \"{{signature}}\",\n \"redirectUrl\": \"{{redirectUrl}}\"\n}"
},
"url": {
"raw": "{{apiBaseUrl}}/v1/guest/auth/external-auth",
"host": ["{{apiBaseUrl}}"],
"path": ["v1", "guest", "auth", "external-auth"]
},
"description": "Calls the external-auth endpoint to obtain a magic-login URL."
},
"response": []
}
],
"event": [
{
"listen": "prerequest",
"script": {
"type": "text/javascript",
"exec": [
"const email = pm.collectionVariables.get('email');",
"const timestamp = Math.floor(Date.now() / 1000);",
"const externalUserId = pm.collectionVariables.get('externalUserId');",
"const liteApiKey = pm.collectionVariables.get('liteApiKey');",
"",
"const payload = `${email.toLowerCase()}:${timestamp}:${externalUserId}`;",
"",
"const signature = CryptoJS.HmacSHA256(payload, liteApiKey).toString();",
"pm.collectionVariables.set('timestamp', timestamp);",
"pm.collectionVariables.set('signature', signature);"
]
}
},
{ "listen": "test", "script": { "type": "text/javascript", "exec": [""] } }
],
"variable": [
{ "key": "apiBaseUrl", "value": "http://site.wlbl.local/v1" },
{ "key": "liteApiKey", "value": "" },
{ "key": "email", "value": "[email protected]" },
{ "key": "firstName", "value": "First" },
{ "key": "lastName", "value": "Last" },
{ "key": "externalUserId", "value": "CLIENT-123" },
{ "key": "timestamp", "value": "1763466236" },
{ "key": "signature", "value": "" },
{ "key": "redirectUrl", "value": "https://project-domain.example/hotels" }
]
}
How to Use the Collection
Step 1 — Save
Save the JSON as:
external-auth-sso.postman_collection.json
Step 2 — Import
- Open Postman
- Click Import
- Select the file
It will appear as External Auth SSO.
Step 3 — Update Required Variables
| Variable | Description |
|---|---|
| apiBaseUrl | Your API base (e.g., https://wl.domain.com/v1) |
| liteApiKey | Your LiteAPI key |
| User email | |
| firstName | User first name |
| lastName | User last name |
| externalUserId | Your internal user ID |
| redirectUrl | User destination after login |
Do not update:
timestampsignature
These are auto-generated.
Step 4 — How the Pre-Request Script Works
const email = pm.collectionVariables.get('email');
const timestamp = Math.floor(Date.now() / 1000);
const externalUserId = pm.collectionVariables.get('externalUserId');
const liteApiKey = pm.collectionVariables.get('liteApiKey');
const payload = `${email.toLowerCase()}:${timestamp}:${externalUserId}`;
const signature = CryptoJS.HmacSHA256(payload, liteApiKey).toString();
pm.collectionVariables.set('timestamp', timestamp);
pm.collectionVariables.set('signature', signature);
It:
- Creates a new timestamp
- Builds the payload
- Generates the HMAC signature
- Stores both automatically
Step 5 — Send the Request
Open Create Magic Login Link → click Send.
Look for the field:
loginUrl
Step 6 — Test Login Link
Open the loginUrl in a browser → should auto-log in.
To test an error:
Open the link again → you should see:
TOKEN_ALREADY_USED
Updated about 16 hours ago