Customer Authentication
Customer registration, login, token management, password reset, and email verification
Customer Authentication
The SDK provides client.customer for storefront customer authentication — separate from the admin/tenant authentication system.
Customer auth is available on BrowserClient only. For server-side customer data management, use client.from('customers') with ServerClient.
Setup
import { createBrowserClient } from '@01.software/sdk'
export const client = createBrowserClient({
clientKey: process.env.NEXT_PUBLIC_SOFTWARE_CLIENT_KEY!,
customer: { persist: true },
})The persist option automatically saves/restores the token in localStorage (SSR-safe). You can also use a custom storage key:
customer: { persist: 'my-app-token' } // custom localStorage keyFor full control, use token and onTokenChange instead:
customer: {
token: getTokenFromCookie(),
onTokenChange: (token) => setTokenCookie(token),
}| Option | Type | Description |
|---|---|---|
persist | boolean | string | Auto-persist in localStorage. true uses key 'customer-token', string for custom key |
token | string | Initial token (e.g. from SSR cookie). Ignored when persist is set |
onTokenChange | (token: string | null) => void | Called on login/logout. Ignored when persist is set |
Register
const { customer } = await client.customer.register({
name: 'John Doe',
email: 'john@example.com',
password: 'securepassword',
phone: '010-1234-5678', // optional
})Registration does not automatically log in. Call login() after registration.
Login
const { token, customer } = await client.customer.login({
email: 'john@example.com',
password: 'securepassword',
})
// Token is stored internally and onTokenChange is calledThe returned customer object:
{
id: string | number
name: string
email: string
phone?: string
isVerified: boolean
}Profile
const profile = await client.customer.me()
if (!profile) {
// Not authenticated or token expired
}Returns null if not authenticated. Automatically clears the token on 401.
Logout
client.customer.logout()
// Token cleared, onTokenChange called with nullPassword Reset
1. Request reset email
await client.customer.forgotPassword('john@example.com')
// Always succeeds (prevents email enumeration)2. Reset with token
The reset email contains a link with a token. Use it to set a new password:
await client.customer.resetPassword(token, 'newpassword')Change Password
Requires authentication:
await client.customer.changePassword('currentPassword', 'newPassword')Email Verification
await client.customer.verifyEmail(token)Token Management
// Check authentication status
client.customer.isAuthenticated() // boolean
// Get current token
client.customer.getToken() // string | null
// Set token manually (e.g. from SSR)
client.customer.setToken(token)Guest vs Registered
| Guest | Registered | |
|---|---|---|
| Creation | client.from('customers').create({ ... }) via ServerClient | client.customer.register({ ... }) |
| Login | Not possible | client.customer.login() |
| Cart | customer field omitted or linked | Linked to customer ID |
| Order history | Lookup by email/order number | client.customer.me() + scoped queries |
| Address book | Not available | Full CRUD |
Error Handling
import { ApiError } from '@01.software/sdk'
try {
await client.customer.login({ email, password })
} catch (error) {
if (error instanceof ApiError) {
switch (error.status) {
case 401:
// Invalid credentials
break
case 429:
// Rate limited
break
}
}
}