# Add customer accounts Add customer accounts without confusing project access with buyer identity. A required Storefront token authorizes the project's Storefront surface. A customer bearer token identifies the signed-in buyer. ## Before you begin Use a server-side session boundary and a Storefront connection. Configure the email workflow required for account activation and password recovery. The [Next.js example](/guides/storefront/nextjs) integrates `@thor-commerce/better-auth-thor` in `src/lib/auth.ts` and account UI under `src/features/account`. Use those files as an integration example, with your own session and deployment configuration. ## 1. Register and activate [customerRegister](/api/storefront-graphql/mutations/customer-register) starts registration with the buyer's email. Your configured email integration delivers the activation instructions. [customerActivate](/api/storefront-graphql/mutations/customer-activate) uses the activation token and required account details. Verify delivery and activation in a test account before presenting registration as complete. Do not assume that accepting the registration mutation means an email provider has delivered a message. Treat activation and password-reset tokens as secrets. ## 2. Sign in Storefront API ```graphql mutation SignIn($input: CustomerAccessTokenCreateInput!) { customerAccessTokenCreate(input: $input) { customerAccessToken { accessToken refreshToken expiresIn } errors { __typename ... on UserError { message } } } } ``` Variables ```json { "input": { "email": "buyer@example.com", "password": "" } } ``` Check the payload before establishing a local session. Store the tokens through your server-side session mechanism, and send the access token as a bearer token for authenticated requests. Keep the project Storefront header as well when required. Use [customer](/api/storefront-graphql/queries/customer) to retrieve the authenticated profile. ## 3. Refresh and sign out Use [customerAccessTokenRefresh](/api/storefront-graphql/mutations/customer-access-token-refresh) and replace both stored tokens with the returned pair. Coordinate concurrent refreshes for one session. If refresh fails, clear the session and provide a sign-in path. Never keep retrying an expired credential indefinitely. On sign-out, clear customer-sensitive UI and cached account data. Reconcile the current cart before continuing with an anonymous buyer. ## 4. Reconcile the cart after sign-in Attach the authenticated customer through the supported cart workflow and refresh commercial data. Customer-group prices can differ from anonymous prices. The example storefront explicitly handles customer association and cart replication when repricing is needed; this is application behavior you should verify for your own flow. Do not infer that a changed browser cookie has already repriced an existing cart. ## 5. Add recovery Use [customerPasswordResetToken](/api/storefront-graphql/mutations/customer-password-reset-token), your email workflow, and [customerPasswordReset](/api/storefront-graphql/mutations/customer-password-reset). Use neutral confirmation copy that does not disclose account existence. Test activation, incorrect password, expired session, concurrent refresh, password recovery, sign-out, and group-sensitive prices. Keep all account responses out of shared public caches.