Skip to main content

Auth Token

Overview

The Auth Token integration enables single sign-on (SSO) between your platform and Publica.la stores. Users authenticated in your system (LMS, e-commerce, CMS, etc.) can access Publica.la content without logging in again.

How it works: Your platform generates a signed JWT containing user information, redirects the user to Publica.la with that token, and we validate it to grant access automatically. New users are created on first authentication; existing users are recognized by their uuid.

Not the right fit? Consider IP Authentication for IP-based access, LTI for LMS integrations, or URL Referrer for domain or URL-based access.


Setup

  1. Generate a secret key — Create a 32-character secret that you'll use to sign JWTs.

  2. Contact support with the following configuration:

    ParameterDescription
    keyThe 32-character secret you generated
    issuerYour platform identifier (e.g., platform-name). Must match iss claim in tokens.
    redirect_urlWhere to send users on auth errors
    logout_urlWhere to send users after logging out
  3. Wait for confirmation before testing your integration.


Token format

Tokens must be signed with HS256 (HMAC-SHA256). Other algorithms are rejected.

Example payload

{
"iss": "platform-name",
"aud": "farfalla",
"sub": "user",
"jti": "550e8400-e29b-41d4-a716-446655440000",
"exp": 1699999960,
"user": {
"uuid": "user-123",
"email": "user@example.com",
"picture_url": "https://example.com/avatar.jpg"
},
"intended_url": "https://store.publica.la/reader/my-ebook"
}

Claims reference

Required JWT claims

ClaimTypeDescription
issstringYour platform identifier. Must match configured issuer.
audstringMust be "farfalla".
substringMust be "user".
jtistringUnique token ID. Use UUID v4 to prevent replay.
expnumberExpiration timestamp (Unix time). We recommend 60 seconds for real-time redirects.

User object (user claim)

FieldRequiredTypeDescription
uuidYesstringUnique identifier for the user in your system. 1-200 characters. Stored as external_id in Publica.la.
emailNostringUser's email address. Must be valid format if provided. Updated on each login if changed.
picture_urlNostringProfile picture URL. Max 200 characters. Only set on first login, not updated afterwards.
accept_terms_and_policiesNobooleanIf true, automatically accepts terms on first login.

Optional claims

ClaimTypeDescription
intended_urlstringWhere to redirect after successful login. Must be a valid URL. Defaults to /library.
reader_exit_urlstringCustom URL for the reader's exit button. Stored in session for the reader to use.

Endpoint

URL

https://{store-domain}/auth/token

Methods

Both GET and POST are supported.

Passing the token

The token can be provided in two ways:

https://{store-domain}/auth/token?external-auth-token={JWT}

Recommended for browser redirects. JWT tokens are URL-safe, no encoding needed.

Security consideration

Tokens in URLs appear in browser history, server logs, and may leak via Referrer headers. Use short expiration times (60 seconds) to mitigate risk.

Response behavior

ScenarioHTTP ResponseDestination
Valid token302 Redirectintended_url from token, or /library if not specified
Invalid token302 Redirectredirect_url with error query params
Invalid user data302 Redirectredirect_url with error query params
Missing store configuration422 JSONError message returned

User management

View detailed authentication flow

New users

When a user authenticates for the first time (no existing user with that uuid):

  1. A new user account is created with the provided uuid as external_id
  2. email and picture_url are set if provided in the token
  3. If accept_terms_and_policies: true, terms are automatically accepted
  4. User is logged in and redirected to their destination

Returning users

When a user with an existing uuid authenticates:

  1. User is found by their external_id (your uuid)
  2. email is updated if the token contains a different value
  3. picture_url is not updated (only set on creation)
  4. User is logged in and redirected

Email uniqueness

Each email address can only be associated with one uuid. If you send an email that already belongs to a different user, authentication will fail with an invalid-user error.


Code examples

use Lcobucci\JWT\Configuration;
use Lcobucci\JWT\Signer\Hmac\Sha256;
use Lcobucci\JWT\Signer\Key\InMemory;
use DateTimeImmutable;

$config = Configuration::forSymmetricSigner(
new Sha256(),
InMemory::plainText($_ENV['JWT_SECRET'])
);

$now = new DateTimeImmutable();

$token = $config->builder()
->issuedBy('platform-name') // iss - must match configured issuer
->permittedFor('farfalla') // aud - always "farfalla"
->relatedTo('user') // sub - always "user"
->identifiedBy(bin2hex(random_bytes(16))) // jti - unique token ID
->expiresAt($now->modify('+60 seconds')) // exp - short expiration for security
->withClaim('user', [
'uuid' => $userId,
'email' => $userEmail,
'picture_url' => $userAvatar,
])
->withClaim('intended_url', 'https://store.publica.la/reader/my-ebook')
->getToken($config->signer(), $config->signingKey());

$jwt = $token->toString();

// Redirect user to Publica.la
header('Location: https://store.publica.la/auth/token?external-auth-token=' . $jwt);
exit;

Error handling

When authentication fails, users are redirected to your configured redirect_url with error information in query parameters:

https://your-redirect-url.com?external-auth-token-error={code}&external-auth-token-error-details={base64-json}

Error codes

CodeDescription
invalid-tokenToken validation failed (expired, bad signature, wrong issuer/audience/subject)
invalid-userUser data validation failed (invalid email format, missing uuid, uuid too long)

Decoding error details

The external-auth-token-error-details parameter contains Base64-encoded JSON with specific error messages:

const details = JSON.parse(atob(errorDetails));
console.log(details);

Example error responses

Token validation error:

{
"token": {
"exp": "Token is expired or `exp` attribute not present."
}
}

User validation error:

{
"email": ["The email must be a valid email address."]
}

Email conflict error:

{
"uuid": ["This email is already attached to UUID abc-123."]
}

Troubleshooting

ProblemCauseSolution
"Token is expired"exp timestamp is in the pastEnsure server clock is synchronized (NTP). Use 60-second expiration.
"Invalid signature"Signing key doesn't matchVerify key matches exactly what was configured in setup.
"Invalid issuer"iss claim mismatchEnsure iss matches the configured issuer exactly (case-sensitive).
"Invalid audience"aud claim wrongMust be exactly "farfalla".
"Email already attached to UUID"Email registered to different userUse the correct uuid for that email, or use a different email.
422 errorStore not configuredContact support to complete Auth Token setup.

Debugging tips

  1. Inspect your token — Paste it at jwt.io to see decoded header and payload
  2. Check expiration — Ensure exp is in the future when the request reaches Publica.la
  3. Verify fixed valuesaud must be "farfalla", sub must be "user"
  4. Decode errors — Use base64decode.org to read error details

JWT Generator

Generate test tokens to verify your integration:


Security best practices

  1. Use short expiration times — 60 seconds is recommended for tokens passed in URLs
  2. Store secrets securely — Use environment variables, never commit keys to version control
  3. Use HTTPS only — Never transmit tokens over unencrypted connections
  4. Prefer headers when possible — HTTP headers don't appear in browser history or server logs
  5. Generate unique jti values — Use UUID v4 for each token to enable replay detection
  6. Rotate keys periodically — Contact support to update your signing key

Tips for integrators

  • Anonymous users — Omit email to create anonymous user accounts
  • Direct content access — Use intended_url to send users directly to a specific book or page
  • Custom reader exit — Use reader_exit_url to control where users go when closing the reader
  • No URL encoding needed — JWT tokens are URL-safe by design
  • Email updates — Users are matched by uuid, so if an email changes in your system, just send the new email and it will be updated automatically
X

Graph View