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