Skip to content

Authentication

Sesamy uses Auth0-compatible authentication to provide industry-standard, secure API access. You can integrate using any Auth0-compatible SDK.

Authentication Methods

Sesamy supports different authentication flows depending on your use case:

Management API - Client Credentials Flow

For server-to-server authentication to the Management API, use the Client Credentials flow.

Best for: Backend services, administrative tasks, server-side integrations

Learn more about API Keys →

Apps & Websites - Authorization Code Flow

For user-facing applications and websites, use the Authorization Code flow with support for PKCE, cookie sessions, and refresh tokens.

Best for: Web applications, single-page applications, native mobile apps

Learn more about OAuth 2.0 →

For publishers deploying Sesamy on a custom domain (e.g. app.yoursite.com), the API proxy implements the Token Handler pattern. The API proxy acts as the OAuth client — it completes the login flow server-side and stores encrypted tokens in HttpOnly cookies. JavaScript never sees a raw token.

Best for: Custom-domain integrations, high-security paywalls, sites where XSS token theft is unacceptable

Learn more about BFF Authentication →

Quick Examples

Management API - Client Credentials Flow

Get a token for server-to-server authentication:

bash
curl -X POST https://token.sesamy.com/oauth/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=client_credentials" \
  -d "client_id=YOUR_CLIENT_ID" \
  -d "client_secret=YOUR_CLIENT_SECRET" \
  -d "audience=https://api.sesamy.com"

# Use the access token
curl -X GET https://api.sesamy.com/management/v1/... \
  -H "Authorization: Bearer ACCESS_TOKEN"

Apps & Websites - Authorization Code Flow (with PKCE)

For web and mobile applications:

bash
# Step 1: Redirect user to authorization endpoint
https://token.sesamy.com/authorize?
  client_id=YOUR_CLIENT_ID&
  redirect_uri=https://yourapp.com/callback&
  response_type=code&
  scope=openid profile email&
  code_challenge=CHALLENGE&
  code_challenge_method=S256

# Step 2: Exchange code for token
curl -X POST https://token.sesamy.com/oauth/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=authorization_code" \
  -d "client_id=YOUR_CLIENT_ID" \
  -d "code=AUTH_CODE" \
  -d "code_verifier=VERIFIER" \
  -d "redirect_uri=https://yourapp.com/callback"

# Use the access token
curl -X GET https://api.sesamy.com/client/v1/profile \
  -H "Authorization: Bearer ACCESS_TOKEN"

The Sesamy API proxy implements the Token Handler pattern — a BFF (Backend-for-Frontend) approach to authentication where the API acts as the OAuth client and stores tokens in HttpOnly cookies instead of exposing them to JavaScript.

How It Works

The API proxy is the OAuth client. It runs the Authorization Code + PKCE flow server-side and hands the browser only HttpOnly cookies — JavaScript never touches a token. The diagram below traces a full login and one authenticated API call. acme is the vendor ID; api.yoursite.com is your custom domain (same eTLD+1 as the page).

Step by step:

  1. User clicks Login → browser navigates to https://api.yoursite.com/auth/acme/login
  2. API proxy generates PKCE, stores the verifier + CSRF state in the encrypted __Host-auth-state cookie, and redirects to https://token.sesamy.com/authorize with redirect_uri=https://api.yoursite.com/auth/acme/callback. Any login_hint / ui_locales ride along.
  3. User authenticates at the token service
  4. Token service redirects back to https://api.yoursite.com/auth/acme/callback with the auth code
  5. API proxy verifies the CSRF state, exchanges the code for tokens server-side, encrypts them with a per-vendor key, and sets the cookies (see Cookie Architecture below)
  6. Browser is redirected back to your SPA — cookies are set, JS never touched a token
  7. sesamy-js sees the sesamy_is_authenticated hint cookie and calls /auth/userinfo to hydrate the session
  8. All subsequent API calls include cookies automatically (credentials: include); the proxy decrypts at, refreshes via __Host-rt when expired, and forwards Authorization: Bearer <at> upstream

This is the canonical reference for every cookie the BFF sets. The two token cookies (at, __Host-rt) are encrypted with a per-vendor AES-256-GCM key; the rest are plaintext hints.

CookieSet whenHttpOnlySameSiteDomainLifetimePurpose
atcallbackLax.yoursite.comaccess token's expires_in (typ. 1h)Encrypted access token
__Host-rtcallbackStrict— (__Host-)30 daysEncrypted refresh token
sesamy_is_authenticatedcallbackLax.yoursite.com30 daysJS-readable session hint — gates the /auth/userinfo call so an anonymous visitor makes no auth request
sesamy_cidcallbackLax.yoursite.com30 daysVendor/client ID hint — lets the proxy derive the per-vendor decryption key without an upstream lookup
__Host-auth-stateloginLax— (__Host-)10 minEncrypted PKCE verifier + CSRF state + returnTo, consumed at the callback

Key points:

  • __Host- prefix (__Host-rt, __Host-auth-state) forces Secure, Path=/, and no Domain — the browser will only send these back to the API proxy itself, never to a sibling subdomain. On localhost (insecure) the proxy falls back to a plain rt / auth-state cookie because __Host- requires HTTPS.
  • at is scoped to the top-level domain (Domain=.yoursite.com) so it rides along on same-site API calls; the refresh token deliberately is not.
  • Only sesamy_is_authenticated and sesamy_cid are readable by JS — and neither is a token. They are hints that let sesamy-js skip needless network calls.

Enabling BFF Mode in sesamy-js

Set auth.useHttpCookies: true in your configuration. No @auth0/auth0-spa-js script is needed:

html
<script type="application/json" id="sesamy-js">
  {
    "clientId": "your-vendor-id",
    "vendorId": "your-vendor-id",
    "auth": {
      "useHttpCookies": true
    },
    "api": {
      "namespace": "sesamy",
      "endpoint": ""
    }
  }
</script>

Setting api.endpoint to "" makes sesamy-js use relative URLs (/entitlements, /contracts, etc.) so all requests stay on the same origin and flow through your reverse proxy or Vite dev server — ensuring cookies are scoped correctly.

Prerequisites

The Token Handler is configured per-vendor via the management API (PUT /management/vendors/:vendorId/token-handler). The entry requires:

  • clientId — your Sesamy vendor/client ID
  • authHostname — optional, used only for federated logout redirect

Because the vendor ID is embedded in the login and callback URLs, no hostname scanning is required — the proxy resolves vendor settings directly from the path.

Auth0 callback URL

You must add https://api.yoursite.com/auth/<vendorId>/callback to the Allowed Callback URLs list in your Auth0 application settings. For local development add http://localhost:8787/auth/<vendorId>/callback.

Security Properties

PropertyValue
Token exposure to JS✅ None — HttpOnly cookies only
XSS token theft✅ Immune
CSRF✅ Mitigated by SameSite=Lax/Strict
Token storageAES-256-GCM encrypted, server-side per-vendor key
Session refreshAutomatic — refresh token rotated on each use
Cross-domain SSO❌ Not supported (session is domain-bound)

Safari's Intelligent Tracking Prevention (ITP) caps the lifetime of cookies set by cross-site responses to 7 days. This means:

  • Custom domain (api.yoursite.com + yoursite.com): both are on the same eTLD+1, so cookies are classified as first-party. The 7-day cap does not apply, and refresh tokens survive for their full 30-day lifetime.
  • No custom domain (api2.sesamy.com + yoursite.com): the API is on a different domain, so Safari classifies the Set-Cookie response as cross-site. Cookies are capped at 7 days, causing users to be logged out weekly.

This is the primary reason the BFF pattern requires a custom domain on the same eTLD+1 as your site. If you cannot use a custom domain, use the standard Authorization Code + PKCE flow with refresh tokens instead.

Session Management

If you're using a custom domain with the BFF pattern, sessions are managed entirely via HttpOnly cookies. No client-side token storage is needed.

Token Refresh (All Domains)

If you're not using custom domains, use refresh tokens to maintain user sessions:

bash
curl -X POST https://token.sesamy.com/oauth/token \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=refresh_token" \
  -d "client_id=YOUR_CLIENT_ID" \
  -d "refresh_token=REFRESH_TOKEN"

Security Best Practices

Important

Never expose your client secrets in client-side code or public repositories. Always use PKCE for public clients (SPAs, native apps).

  1. Store secrets securely: Use environment variables or secure vaults for sensitive credentials
  2. Use HTTPS: Always use HTTPS for all authentication endpoints
  3. Enable PKCE: Use PKCE for all public clients (SPAs, native apps) to prevent authorization code interception
  4. Validate tokens: Verify token signatures and expiration on your backend
  5. Rotate secrets: Regularly rotate client secrets in your dashboard
  6. Use appropriate scopes: Request only the scopes your application needs

Auth0-Compatible SDKs

Since Sesamy uses Auth0-compatible authentication, you can use any Auth0-compatible SDK:

Next Steps

  • API Keys - Management API credentials and setup
  • OAuth 2.0 - Complete authorization flow guide
  • JWT Tokens - Understanding and validating tokens

Released under the MIT License.