Overview
Most LatentGEO API endpoints require JWT (JSON Web Token) bearer authentication. The API validates tokens using Auth0 RS256 signatures in production, with an internal HS256 fallback for test environments.JWT Bearer Authentication
Include your JWT token in theAuthorization header of each request:
Bearer token for authentication. Format:
Bearer <token>Required JWT Claims
The LatentGEO backend expects the following claims in your JWT:Subject claim containing the internal user ID. This is the primary identifier for the authenticated user.
User’s email address. Can also be provided as
user_email. Used for ownership checks and audit trails. Automatically normalized to lowercase.Issuer claim. Must match the configured Auth0 domain/issuer URL in production.
Audience claim. Must match the configured Auth0 API audience in production.
Expiration timestamp (Unix epoch). Tokens past this time are rejected.
Production Token Validation
In production environments, the API performs strict RS256 validation:- Issuer verification - Token
issclaim must match your Auth0 domain - Audience verification - Token
audclaim must match the configured API audience - Signature verification - Token must be signed by Auth0 using RS256
- JWKS validation - Public key is fetched from Auth0’s JWKS endpoint and cached
- Expiration check - Token
expclaim must be in the future - Required claims - Token must contain
sub,iss,aud, andexpclaims
AUTH0_EXPECTED_CLIENT_ID is configured, the token’s azp or client_id claim must match.
Test Environment Compatibility
In test environments, the API accepts internal HS256 tokens for unit testing stability. This mode is enabled when:ENVIRONMENT=test, orPYTEST_CURRENT_TESTenvironment variable is set, orALLOW_INTERNAL_TEST_JWT=trueis set
Ownership and Access Control
Resource Ownership
GitHub and HubSpot connections are user-owned resources identified by:owner_user_id- Matches the JWTsubclaimowner_email- Matches the JWTemailoruser_emailclaim
403 Forbidden response.
Legacy Policy
In debug mode (DEBUG=true), the first authenticated user to access an ownerless legacy connection automatically claims ownership. In production mode (DEBUG=false), ownerless connections are blocked with a 403 Forbidden response.
OAuth Security Contract
GitHub and HubSpot OAuth flows require an authenticated user for both initialization and callback.OAuth Initialization
Request an OAuth authorization URL:state token is:
- Signed using HS256 with your backend secret
- Time-limited (default: 10 minutes)
- User-bound to the authenticated user’s
subclaim
url to begin the OAuth flow.
OAuth Callback
After the user authorizes, handle the OAuth callback:- Bearer token must be present and valid
- State token must be valid and not expired
- State token’s embedded user ID must match the bearer token’s
subclaim
400 Bad Request- Invalid or expired state token401 Unauthorized- User mismatch between state and bearer token403 Forbidden- Ownership violation
Authentication Errors
Authentication failures return401 Unauthorized with a custom header:
missing_token- No Authorization header providedexpired_token- JWT has expiredinvalid_signature- Token signature verification failedinvalid_issuer- Issuer claim doesn’t match expected Auth0 domaininvalid_audience- Audience claim doesn’t match API audiencemissing_sub- Token missing requiredsubclaimjwks_unavailable- Unable to fetch or validate JWKS from Auth0invalid_client- Client ID doesn’t match expected value
Example: Complete OAuth Flow
Step 1: Initialize OAuth
Step 2: Redirect User
Redirect the user to theurl returned in step 1.
Step 3: Handle Callback
After user authorization, GitHub redirects back withcode and state:
Step 4: Use Connection
JWKS Caching
The API caches Auth0’s JWKS (JSON Web Key Set) to improve performance:- Cache TTL: Configurable via
AUTH0_JWKS_CACHE_TTL_SECONDS(default: varies by deployment) - Fetch timeout: Configurable via
AUTH0_JWKS_FETCH_TIMEOUT_MS(default: varies by deployment) - Key rotation: On unknown
kid(key ID), the cache automatically refreshes to support Auth0 key rotation
Best Practices
- Token storage - Store tokens securely (e.g., httpOnly cookies, secure storage)
- Token refresh - Implement token refresh logic before expiration
- Error handling - Check
X-Auth-Error-Codeheader for specific failure reasons - State validation - Always validate OAuth state tokens in callbacks
- HTTPS only - Use HTTPS in production to prevent token interception