Aelio
Chat Widget

Widget Authentication

Secure the chat widget with magic link session tokens.

Three separate secrets

SecretWho issuesPurpose
AELIO_SDK_SECRETYou configureSDK ↔ Server WebSocket + protected HTTP routes
LLM API keysProviderServer ↔ LLM provider
Session tokenAelio serverWidget ↔ Server WebSocket (per-user, short-lived)

Never put AELIO_SDK_SECRET in frontend code.

curl -X POST https://your-aelio-server.com/auth/magic-link \
  -H "Authorization: Bearer $AELIO_SDK_SECRET" \
  -H "Content-Type: application/json" \
  -d '{"email": "user@example.com", "externalId": "user_abc123"}'

Requires Bearer AELIO_SDK_SECRET. Returns a magic link URL.

GET /auth/verify?token=...

Returns:

{
  "customerId": "user_abc123",
  "externalId": "user_abc123",
  "email": "user@example.com",
  "sessionToken": "eyJ..."
}

3. Widget uses the session token

mountAelioChat({
  serverUrl: 'https://your-aelio-server.com',
  customerId: 'user_abc123',
  authToken: sessionToken,  // from step 2
  email: 'user@example.com',
});

Session tokens are HMAC-SHA256 signed, TTL default 60 minutes. The server verifies the token matches customerId to prevent spoofing.

Anonymous mode (development only)

Set in config.yaml:

identity:
  allow_anonymous: true

Allows widget init without a token. Not recommended for production.

Development without auth

For local dev, you can pass just customerId and email:

<script
  src="http://localhost:3010/widget.js"
  data-server-url="http://localhost:3010"
  data-customer-id="demo-shopper"
  data-email="user@example.com"
></script>

Error codes

CodeMeaning
auth_requiredToken required but not provided
identity_mismatchToken doesn't match customerId
origin_not_allowedPage origin not in allowlist

On this page