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
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
Configuration Guide
The following configuration is required in the store's advanced settings (/dashboard/settings#advanced > users
):
{
"external_auth": {
"key": "your-secure-32-character-key", // Required: Token signing key
"issuer": "your-unique-identifier", // Required: Platform identifier
"logout_url": "https://platform.example", // Optional: Custom logout URL
"redirect_url": "https://platform.example/error" // Required: Error handling URL
}
}
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",
"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')
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
tip
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
email
in the token, the integration is 100% anonymous - Use base64decode.org for decoding error details