Tokens and rate limits
Verify access tokens, read their claims, handle expiry and sign-out, and stay within the Auth API rate limits
Access tokens
Access tokens are JWTs signed with RS256.
| Item | Value |
|---|---|
| Public keys (JWKS) | <AUTH_SERVER>/.well-known/jwks.json |
Issuer (iss) | <AUTH_SERVER> |
| Lifetime | 9 hours |
The JWKS can contain more than one key. Select the key by the kid header. Standard JWT libraries do this for you.
Verify a token on your server
Verify the signature, the issuer, and the expiry before you trust a claim. Example with the jose library:
import { createRemoteJWKSet, jwtVerify } from 'jose'
const jwks = createRemoteJWKSet(new URL(`${process.env.AUTH_SERVER}/.well-known/jwks.json`))
export async function verifyAccessToken(token: string) {
const { payload } = await jwtVerify(token, jwks, { issuer: process.env.AUTH_SERVER })
return payload
}Customer token claims
Claims of a token with scope: "CUSTOMER":
| Claim | Type | Meaning |
|---|---|---|
iss | string | Auth API base URL |
sub | string | Customer ID, as a string |
iat, exp | number | Issue time and expiry time, in seconds |
scope | string | CUSTOMER |
type | string | customer |
operator-id | number | ID of your organisation (the manufacturer) |
operator-name | string | Your store name |
customer-id | number | Customer ID |
customer-principal | string | Sign-in identifier (the email address, in lower case) |
customer-organisation-id | number | ID of the customer's organisation |
client-id | string | Client ID of the storefront credentials |
first-name, last-name | string | Customer name |
language | string | Customer language, in lower case (default en) |
notification-preference | string | Default EMAIL |
has-custom-pricing | boolean | The customer has custom pricing |
is-approved | boolean | Always true (customers who are not approved get no token) |
Claims are read at sign-in. A change to the customer profile shows in the token after the next sign-in.
Guest token claims
Claims of a token with scope: "ANONYMOUS": iss, sub (a random ID for this guest), iat, exp, scope (ANONYMOUS), type (anonymous), operator-id, operator-name, client-id.
Lifetime, refresh, and sign-out
- A token is valid for 9 hours. There is no refresh token.
- When a customer token expires, the customer must sign in again.
- When a guest token expires, get a new guest token.
- There is no sign-out endpoint. To sign a customer out, delete the token that your storefront holds.
- A token stays valid until it expires. Store tokens carefully. An
HttpOnly,Securecookie set by your server is a good choice.
Rate limits
When you exceed a limit, the API returns 429. Some 429 responses have a Retry-After header (seconds). Wait, then try again.
Limits for each set of storefront credentials
| Limit | Value |
|---|---|
All /customer/* calls | 600 in 1 minute |
Guest sessions (/customer/anonymous) | 1200 in 15 minutes |
Sign-in codes sent (/customer/otp/send) | 600 in 15 minutes |
Sign-up codes sent (/customer/signup/otp/send) | 600 in 15 minutes |
Pre-auth calls (/customer/login/pre-auth) | 1800 in 15 minutes |
Limits for each end customer
These limits apply to one email address at your store.
| Limit | Value |
|---|---|
| Sign-in codes sent | 5 in 15 minutes |
| Sign-up codes sent | 5 in 15 minutes |
| Incorrect codes | 10 in 15 minutes |
| Incorrect passwords | 10 in 15 minutes |
After a customer uses up the incorrect-code or incorrect-password limit, the correct value also gives 429 until the 15 minutes end. A new sign-in code resets the incorrect-code limit.
Guidance
- Do not get a new guest token on each page load. Get one for each visitor and keep it.
- Show a clear "try again later" message on
429.
Last updated on