Auth
Access via client.auth.
After a successful login or magic link verification the SDK stores the accessToken internally and sends it as Authorization: Bearer on subsequent requests.
Methods
login(params)
Email + password login.
const response = await client.auth.login({
email: 'customer@example.com',
password: 'secret',
})
// response.customer, response.accessToken, response.refreshToken
register(params)
Create a new customer account.
await client.auth.register({
email: 'new@example.com',
password: 'secret',
name: 'Anna Svensson',
})
sendMagicLink(email) / verifyMagicLink(token) / verifyMagicLinkCode({ email, code })
Passwordless flow. The email carries both a link and a six-digit code for the same request; the customer uses either one.
await client.auth.sendMagicLink('customer@example.com')
// On the /auth/verify?token=<token> landing page, from a click handler:
const response = await client.auth.verifyMagicLink(token)
// Or, in the tab where the link was requested:
const response = await client.auth.verifyMagicLinkCode({ email, code })
verifyMagicLink in onMounted hands the one-time session to the scanner and shows the customer "invalid link". Render a "Sign in" button and verify on click. Scanners render pages; they do not click buttons.The code is bound to the email address it was sent to and dies after five wrong attempts. It exists for two cases the link cannot cover: a scanner has already consumed the link, or the customer reads the email on one device and signs in on another. Up to three unused link+code pairs may be outstanding per customer; requesting a new one does not invalidate the previous ones.
methods()
Which sign-in options the store has turned on under Settings → Customer accounts. Render your sign-in page from this instead of hard-coding it.
const methods = await client.auth.methods()
// { password: true, magicLink: true, registration: { b2c: true, b2b: false },
// klarna: { clientId: 'klarna_live_client_…', environment: 'production', scope: 'openid offline_access profile:name profile:email profile:phone' },
// google: { clientId: '…apps.googleusercontent.com', scope: 'openid email profile' },
// microsoft: { clientId: '…', authority: 'https://login.microsoftonline.com/organizations/v2.0', accounts: 'work', scope: 'openid profile email' } }
magicLink is always true: the link confirms the customer's email and is how a customer who forgot their password gets in. password is false when the store chose Magic link only. Each provider is null unless the store has its integration turned on and the provider chosen under Customer accounts.
signInWithProvider(provider, { idToken })
Sign in with Klarna, Google or Microsoft. Run the provider's own sign-in with the values from methods() and send the id_token it gives you:
const { klarna, google, microsoft } = await client.auth.methods()
async function finish(provider, idToken) {
const response = await client.auth.signInWithProvider(provider, { idToken })
if (response.outcome === 'pending-approval') return showAwaitingApproval()
// signed-in, linked or created: the client now holds the customer's access token.
// response.company is set when the customer joined their company through its sign-in domain.
}
// Klarna — <script src="https://js.klarna.com/web-sdk/v1/klarna.js" defer></script>
if (klarna) {
const sdk = await Klarna.init({ clientId: klarna.clientId, environment: klarna.environment })
sdk.Identity.button({ id: 'klarna-signin', scope: klarna.scope, redirectUri: `${location.origin}/account/klarna-callback` })
.mount('#klarna-signin')
sdk.Identity.on('signin', (signin) => finish('klarna', signin.user_account_linking.user_account_linking_id_token))
}
// Google — <script src="https://accounts.google.com/gsi/client" async></script>
if (google) {
window.google.accounts.id.initialize({ client_id: google.clientId, callback: ({ credential }) => finish('google', credential) })
window.google.accounts.id.renderButton(document.getElementById('google-signin'), { theme: 'outline', size: 'large' })
}
// Microsoft — npm i @azure/msal-browser
if (microsoft) {
const msal = new PublicClientApplication({ auth: { clientId: microsoft.clientId, authority: microsoft.authority, redirectUri: `${location.origin}/account/sign-in` } })
await msal.initialize()
const result = await msal.loginPopup({ scopes: microsoft.scope.split(' ') })
await finish('microsoft', result.idToken)
}
Register the redirect and origin addresses with each provider: Klarna's portal (the callback page is required, since browsers can block Klarna's popup and the flow then continues there), Authorized JavaScript origins on the Google OAuth client, and a Single-page application redirect URI on the Microsoft app registration.
The API verifies the token against the provider's keys and the store's client id, then:
- A linked customer is signed in.
- A customer with the same email is linked, but only when the provider confirms the address. Klarna and Google do; Microsoft does not, because an organization's administrator can give any address to a work account. Without confirmation the API answers
409 IDENTITY_EMAIL_NOT_VERIFIED: let the customer sign in with email, then calllinkProvider. - Otherwise a customer is created. A Microsoft or Google Workspace sign-in from an organization whose domain is on a company (company sign-in domains, with Companies via sign-in on) creates a company contact and makes it a member, even when registration is closed. Anyone else becomes a private customer when registration is open, with manual approval as for
register(HTTP 202, no tokens).
Existing customers join their company the same way the next time they sign in.
linkProvider(provider, { idToken }) / unlinkProvider(provider)
Connect or disconnect a provider on the signed-in customer's account, for example from My account. Linking from a signed-in session is how a Microsoft user with an existing account connects Microsoft. getMe() lists the connected providers in identities.
await client.auth.linkProvider('microsoft', { idToken }) // 409 IDENTITY_ALREADY_LINKED if another customer has it
await client.auth.unlinkProvider('microsoft')
refresh(refreshToken)
Refresh the access token using a stored refresh token.
const { accessToken } = await client.auth.refresh(storedRefreshToken)
logout()
await client.auth.logout()
getProfile() / updateProfile(params)
const profile = await client.auth.getProfile()
await client.auth.updateProfile({
name: 'Anna L Svensson',
phone: '+46701234567',
})
Key types
interface AuthResponse {
accessToken: string
refreshToken: string
customer: CustomerProfile
}
interface CustomerProfile {
id: string
email: string
name: string
phone?: string
}