User Access Token Authentication
Why
Some endpoints need to know who is making the request — for example to return user-specific data or to enforce permissions. The Registration Backend verifies JWT access tokens issued by the Statista SSO (Auth0) to identify the calling user.
This is separate from API key authentication (x-api-key), which
authenticates the client application. A request may require both.
How to Protect a Route
Call validateUserAccessToken(request) in any loader or action. It returns
the authenticated user's payload or throws an error response automatically
(401 for bad tokens, 500 if the SSO config can't be fetched):
import { validateUserAccessToken } from "../services/validate-user-access-token.server.js";
export async function loader({ request }: Route.LoaderArgs) {
const user = await validateUserAccessToken(request);
// user.userId — Auth0 user ID (e.g. "auth0|6398304")
// user.legacyUserId — Statista legacy user ID
// user.permissions — Array of granted permissions
return success({ ... });
}
No try/catch needed — auth errors are handled for you.
What the Client Needs to Send
The client must include the JWT access token (not the session blob) in the
x-access-token header:
x-access-token: Bearer eyJhbGciOiJSUzI1Ni...
The token must be issued by the same environment you're targeting
(e.g. a token from https://statista.com won't work against
https://stage.statista.com).
Available User Fields
The most commonly used fields from the decoded token:
| Field | Description |
|---|---|
userId |
Auth0 user ID (e.g. auth0\|6398304) |
legacyUserId |
Statista legacy user ID |
The full schema is defined in app/services/validate-user-access-token.server.ts
as UserPayloadSchema.
Local Development
Set SKIP_USER_AUTH=true in your .env to bypass token verification.
The function will return a mock user payload without contacting the SSO
server, so you don't need a real token during local development.
OpenAPI
When registering a protected route in OpenAPI, add the bearerAuth security
scheme and include the 401 and 500 error responses that
validateUserAccessToken can throw:
import { ErrorResponseSchema } from "../helpers/api-response.js";
registry.registerPath({
method: "get",
path: "/my-endpoint",
security: [{ bearerAuth: [] }],
responses: {
200: { ... },
401: {
description: "Missing, malformed, or invalid access token",
content: {
"application/json": { schema: ErrorResponseSchema },
},
},
500: {
description: "Failed to fetch SSO config",
content: {
"application/json": { schema: ErrorResponseSchema },
},
},
},
});