External Authentication Token Integration
Overview
The External Authentication Token integration enables secure and seamless single sign-on (SSO) between external platforms and Publica.la stores. This feature streamlines the authentication process, allowing automatic user authentication and account creation, eliminating the need for manual login forms while maintaining enterprise-grade security standards.
Authentication Flow
View Authentication Flow Diagram
The authentication process follows these steps:
- The external system generates a JWT token containing user information
- The system redirects the user to our authentication endpoint
- We validate the token and authenticate the user
- The user receives access to their intended destination
Authentication Endpoint
After generating the JWT token, redirect users to the authentication endpoint:
https://{your-store-domain}/auth/token
Supported HTTP Methods
- GET - For browser redirects
- POST - For programmatic authentication
Passing the Token
The token can be provided in two ways:
-
HTTP Header (recommended for API calls)
external-auth-token: {JWT_TOKEN} -
Query Parameter (recommended for browser redirects)
https://{your-store-domain}/auth/token?external-auth-token={JWT_TOKEN}
Query Parameters:
- ⚠️ Tokens appear in browser history and server logs
- ⚠️ May be exposed in HTTP referrer headers
- ⚠️ Visible in browser's address bar
- ✅ Simple to implement for browser redirects
- Mitigation: Use short expiration times (60 seconds recommended)
HTTP Headers:
- ✅ Not logged in browser history
- ✅ Not visible to users
- ✅ Recommended for programmatic/API authentication
- ⚠️ Requires JavaScript or server-side implementation
Response Behavior
Both GET and POST requests to /auth/token follow the same response pattern:
Success Flow:
- Validates the JWT token
- Creates or updates the user account
- Sets a session cookie for authentication
- Returns
302 redirectto theintended_urlfrom the token (or tenant's home URL if not specified)
Error Flow:
- Returns
302 redirectto the configuredredirect_urlwith error parameters - Error details provided via query string parameters (see Troubleshooting section)
Response Details:
| Scenario | HTTP Status | Action | Session Created |
|---|---|---|---|
| Valid token | 302 | Redirect to intended_url or home URL | Yes |
| Invalid/expired token | 302 | Redirect to redirect_url with error params | No |
| Invalid user data | 302 | Redirect to redirect_url with error params | No |
| Missing config | 422 | JSON error response | No |
Fallback Behaviors
The authentication endpoint handles missing or invalid optional parameters gracefully:
Redirect URL Fallbacks:
| Parameter | When Missing/Invalid | Fallback Behavior |
|---|---|---|
intended_url (in token) | Not provided or invalid URL format | Redirects to tenant's library/home page |
reader_exit_url (in token) | Not provided or invalid URL format | Uses tenant's default reader exit behavior |
redirect_url (in config) | Not configured in tenant settings | Returns 422 error (prevents authentication) |
logout_url (in config) | Not configured | Uses tenant's default logout URL |
Note: JWT tokens are URL-safe by design, so no additional encoding is needed when passing them in query parameters.
Configuration Guide
- Open a support ticket asking for the External Auth Token setup for your store.
- Include these values in the request so Support can add them on your behalf:
key– a 32-character secret your platform will use to sign JWTs (Publica.la verifies the signature).issuer– a unique identifier for your platform (e.g.,platform-name).redirect_url– the URL we should use to redirect users if an error occurs.logout_url(optional) – where users should land after they sign out.
- Wait for Support to confirm the configuration is live.
JWT Signing Requirements
Algorithm: Only HS256 (HMAC-SHA256) is supported for token signing.
Key Management:
- Your platform generates and signs the JWT using the shared secret key
- Publica.la validates the signature using the same key
- The key must be stored securely on both sides
Tokens signed with algorithms other than HS256 will be rejected during validation.
Required Claims
| Claim | Value | Description |
|---|---|---|
iss | Platform ID | Must match the configured issuer |
aud | "farfalla" | Fixed value for Publica.la authentication |
sub | "user" | Fixed value identifying token type |
jti | UUID v4 | Unique token identifier for security |
exp | Timestamp | Token expiration time (60-3600 seconds) |
user.uuid | String | Unique identifier for the user |
Optional Claims
| Claim | Description |
|---|---|
user.email | User's email address for identification |
user.picture_url | Profile picture URL for user avatar |
intended_url | Custom redirect URL after successful login |
reader_exit_url | Custom URL for reader exit action |
user.accept_terms_and_policies | Automatically accept terms and conditions |
Example Token Payload
{
"iss": "platform-name",
"aud": "farfalla",
"sub": "user",
"jti": "550e8400-e29b-41d4-a716-446655440000",
"iat": 1614553200,
"exp": 1614556800,
"user": {
"uuid": "user-123",
"email": "[email protected]",
"picture_url": "https://example.com/avatar.jpg",
"accept_terms_and_policies": true
},
"intended_url": "https://{store_final_domain}/reader/product-name",
"reader_exit_url": "https://platform.example/custom_exit_url/"
}
Implementation Examples
- PHP
- Node.js
- Python
use Lcobucci\JWT\Builder;
use Ramsey\Uuid\Uuid;
use Lcobucci\JWT\Signer\Hmac\Sha256;
$token = (new Builder())
->setIssuer('platform-name')
->setAudience('farfalla')
->setId(Uuid::uuid4())
->setIssuedAt(time())
->setExpiration(time() + 60)
->set('sub', 'user')
->set('user', [
'uuid' => 'user-123',
'email' => '[email protected]',
'picture_url' => 'https://example.com/avatar.jpg',
'accept_terms_and_policies' => true
])
->sign(new Sha256(), $_ENV['TOKEN_SECRET'])
->getToken();
const jwt = require('jsonwebtoken');
const { v4: uuidv4 } = require('uuid');
const token = jwt.sign({
iss: 'platform-name',
aud: 'farfalla',
sub: 'user',
jti: uuidv4(),
exp: Math.floor(Date.now() / 1000) + 60,
user: {
uuid: 'user-123',
email: '[email protected]',
picture_url: 'https://example.com/avatar.jpg',
accept_terms_and_policies: true
},
intended_url: 'https://store.example/reader/product-name',
reader_exit_url: 'https://platform.example/custom_exit_url/'
}, process.env.TOKEN_SECRET, {
algorithm: 'HS256'
});
import jwt
import os
from uuid import uuid4
from time import time
token = jwt.encode({
'iss': 'platform-name',
'aud': 'farfalla',
'sub': 'user',
'jti': str(uuid4()),
'exp': int(time()) + 60,
'user': {
'uuid': 'user-123',
'email': '[email protected]',
'picture_url': 'https://example.com/avatar.jpg',
'accept_terms_and_policies': True
},
'intended_url': 'https://store.example/reader/product-name',
'reader_exit_url': 'https://platform.example/custom_exit_url/'
}, os.environ.get('TOKEN_SECRET'), algorithm='HS256')
Interactive JWT Generator
Need a quick way to create a valid token for testing? Paste your payload JSON and secret key below, then click Generate JWT to produce a signed HS256 token.
Security Best Practices
-
Token Security
- Set short token expiration times (60 seconds recommended)
- Store signing keys securely using environment variables
- Use HTTPS for all API endpoints
- Implement regular key rotation schedules
-
Error Handling
- Configure secure error redirect URLs
- Monitor authentication failures
- Implement comprehensive logging
- Set up alerts for security events
Troubleshooting
Common Error Codes
-
invalid-token
- Token expiration time issues
- Signing key validity problems
- Incorrect issuer and audience values
- Token format and structure errors
Example error response:
https://your-library-url.com?external-auth-token-error=invalid-token&external-auth-token-error-details=eyJ0b2tlbiI6eyJleHAiOiJUb2tlbiBlcyBleHBpcmVkIG9yIGBleHBgIGF0dHJpYnV0ZSBub3QgcHJlc2VudC4ifX0= -
invalid-user
- Data format issues
- Missing required fields
- UUID uniqueness problems
Example error response:
https://your-library-url.com?external-auth-token-error=invalid-user&external-auth-token-error-details=eyJlbWFpbCI6WyJUaGUgZW1haWwgbXVzdCBiZSBhIHZhbGlkIGVtYWlsIGFkZHJlc3MuIl19
Debugging Tips
- Use jwt.io for token inspection and validation
- Enable detailed logging with
force_debug_log=true - Verify store configuration settings
- Confirm all required claims are present
Tips for Integrators
- When sending the token in the query string, you don't need to URL encode it as JWT is already URL safe
- If you don't include the
emailin the token, the integration is 100% anonymous - Use base64decode.org for decoding error details