Skip to main content
The AuthenticationService (accessed via client.authentication) is the gateway to obtaining customer session tokens. It handles customer registration, login, passwordless flows, password management, and session refresh. Every customer-scoped operation across the SDK — on client.customers, client.cartWishlist, client.giftCards, and client.messaging — requires the access_token minted here to be passed as the xAuthToken header.
Already using your own auth provider? If your storefront authenticates through Auth0, Clerk, Cognito, Firebase, NextAuth, SSO, or any other external identity system, you don’t need this service. Use CustomersService to provision Galactic Core customer records directly from your backend. See Customers and Auth for the decision matrix.

The Customer Session Lifecycle

Access tokens are JWTs valid for 1 hour. Refresh tokens are long-lived but single-use — each refreshToken call returns a brand-new refresh token that supersedes the previous one.

On a marketplace key, the user object returned by register, login, verifyOtp and getCurrentUser also carries email_verified: whether the account has proven control of its email address by verifying a one-time code or a sign-in link. It is false straight after register and true once verifyOtp succeeds. email_confirmed does not answer that question. A marketplace adds purchases made as a guest with an email address to the account only when email_verified is true.

Core Authentication

register

Create a new customer account. On success, returns 201 Created along with session tokens so you can log the user in immediately. The email must be a real, deliverable address. Disposable and placeholder domains (example.com, test.com, known throwaway-mail providers, and similar) are rejected with 400 invalid_email, so a sign-up form that submits a dummy address gets a validation error rather than a dead account. A password must be 8 to 72 characters long, counted as characters, and must not appear on the list of commonly used passwords, which is compared without regard to case. A password that breaks the rule is refused with 400 weak_password; details.rule identifies the rule.
The password rule is evaluated before the email is looked up, so the refusal is identical whether or not the email already has an account, and no error code distinguishes the two. The other 400 codes are invalid_request for a missing email or password and invalid_email for a malformed, disposable or placeholder address. Past the attempt limits below, the call answers 429 rate_limited with a Retry-After header. Pass marketing_consent: true when the sign-up form includes a marketing opt-in box and the customer checked it. It defaults to false (opt-in) — a customer is never subscribed to marketing without affirmative consent. The customer can change this later via updateCustomer.
Response (201)
Response shape:
If an account already exists for this store with the given email, register returns 409 Conflict — distinct from a generic 400 validation error. Surface this to your UI so you can route the user to /login instead.

login

Authenticate an existing customer using their email and password. Returns 200 OK.
Session object:

logout

Invalidate the current session. Revokes both the access and refresh tokens on the server. Returns 200 OK.

Send a passwordless authentication link and a 6-digit OTP code to the customer’s email. Codes are valid for 15 minutes. Returns 200 OK with a hint to check email.

verifyOtp

Verify the 6-digit OTP code emitted by sendMagicLink to complete authentication. Returns 200 OK with the same response shape as login (message, user, customer, session).

Password Management

resetPassword

Trigger a password reset email for a customer who has forgotten their password. Returns 200 OK.

updatePassword

Update the password for the currently authenticated user. Returns 200 OK. The new password follows the password rule that applies to register; a password that breaks it is refused with 400 weak_password and a details.rule of too_short, too_long or common.
xAuthToken is mandatory here and must be the customer’s own session JWT (the access_token returned from login / verifyOtp / register). Server keys cannot stand in — this endpoint mutates the customer’s login credentials and requires per-customer authorization.

Session Utilities

refreshToken

Exchange a refresh token for a fresh access token. Returns 200 OK with a brand-new session object (including a rotated refresh_token).
Schedule the refresh ~60 seconds before expires_at rather than waiting for a 401 on a customer-scoped call. This avoids cart/wishlist write failures during checkout.

getCurrentUser

Retrieve the lightweight identity of the currently authenticated user — useful right after login to confirm “who am I?” Also routed as GET /v1/auth/me. Returns 200 OK with { user, customer }.
xAuthToken is mandatory and must be the customer’s own session JWT. This endpoint resolves “who am I?” from the JWT alone — passing the wrong token returns a different customer’s record (or 401).
Response (200)
Looking for the full customer profile? getCurrentUser returns just enough to identify the customer (id, email, basic fields). For the complete profile — addresses, store metrics, purchase history, status — call CustomersService.getCustomer. The same xAuthToken works there. Profile edits (address change, name change, etc.) also live on CustomersService via updateCustomer.

Full Lifecycle Example

This walks the customer from sign-in, through a cart mutation and checkout, to logout — showing where xAuthToken flows.

Response Codes

Attempt limits

Attempts are limited by where they come from, and an account is never locked by attempts made on it. Every attempt counts, successful or not, and an address with no account is treated identically, so a 429 says nothing about whether an account exists. A refused call returns 429 rate_limited with a Retry-After header giving the seconds to wait. With a secret key (a storefront’s server, whose address is not the shopper’s), each method is limited per store and email address. Past the threshold the account is not refused; it is slowed to one attempt per interval, and Retry-After gives the seconds until the next one is accepted. With a publishable key (a browser), attempts are limited per calling address: 10 per address and email, and 30 per address across all emails, in 15 minutes. Across every store and address, a higher per-email threshold slows an attack spread over many sources: Session calls are limited per session or token: refreshToken 20 per refresh token and updatePassword 5 per session in 15 minutes, getCurrentUser 120 per session per minute.
Token Lifetime: Access tokens are valid for 1 hour. We recommend implementing an interceptor in your application to automatically call refreshToken before the access token expires.