Back to Arky

Authentication

Sign in storefront customers and operator accounts with email codes

Arky has two separate sign-in surfaces:

  • initialize from arky-sdk/storefront keeps a store’s customer sessions;
  • createAdmin from arky-sdk/admin keeps an operator account session.

Storefront Customers

import { initialize } from "arky-sdk/storefront";
import { createOrderToken } from "arky-sdk/utils";

const arky = initialize("arky_pk_...", {
	locale: "en",
	createVisitorIdentity: () => ({
		customer_id: crypto.randomUUID(),
		session_id: crypto.randomUUID(),
	}),
	createSessionId: () => crypto.randomUUID(),
	createId: () => crypto.randomUUID(),
	createOrderToken,
});

A first stateful call (a cart, a form, a chat) starts a visitor session: a customer with a visitor token, kept by the SDK. To sign the customer in, ask for a code and verify it:

const requested = await arky.customer.requestCode({
	email: "ana@example.com",
	language: "en",
});
console.log(requested.email_verification.expires_at);

await arky.customer.verify({ code: "123456" });

const me = await arky.customer.getMe();
if (me.customer.type.type === "verified") console.log(me.customer.type.email);
  • The code email’s id comes from your createId. When the answer is lost, requesting the same address in the same language again reuses that id, so the customer gets one email; pass id yourself to pick it.
  • language is the language of the code email, one of the store’s languages.
  • The code email goes out with the template the store selected for sign_in_code, from its sending address. A code request is refused at once while the store has none selected, the template has no text in language, the sending address isn’t ready or the store’s email is paused, so show your own message then. See Store Email.
  • A code lasts ten minutes and allows five wrong tries; an address gets at most one new code a minute. When the publishable key has a bot check, send the provider’s token as bot_check_token.
  • verify makes the signed-in session under an id from your createSessionId, and the customer’s email becomes verified. If another customer of the store already holds that address, the visitor’s cart and history move to that customer and the session continues as them.

Change The Email

On a signed-in session, requestCode starts an email change instead of a sign-in. The code goes to the new address, and changeEmail proves it:

await arky.customer.requestCode({
	email: "ana.new@example.com",
	language: "en",
});

await arky.customer.changeEmail({ code: "654321" });

The session stays signed in and the email becomes the new verified address. The customer’s other signed-in sessions end, and the old address gets the store’s email_changed email in the language of the code request. A change to an address another verified customer holds is refused, and so is the code request while the store has no email_changed email selected. A token refresh in between keeps the pending change, so the code still completes it. updateMe can’t replace or remove a proven email; only a code changes it. To sign in as someone else instead, call logout first.

Read the session, follow changes, or sign out:

console.log(arky.session.get(), arky.isAuthenticated);

const stop = arky.onAuthStateChanged((session) => {
	console.log(session?.customer.id ?? "signed out");
});

await arky.customer.logout();
stop();
Important

The arky_pk_... key identifies the store and is safe in browser code. It signs nobody in. Never put a secret key in storefront code; the SDK creates and stores the customer’s own session tokens.

Operator Accounts

import { createAdmin } from "arky-sdk/admin";

const sdk = createAdmin({ apiUrl: "https://api.arky.io" });

const pending = await sdk.account.auth.requestCode({ email: "lena@example.com" });
await sdk.account.auth.verify({ session_id: pending.session_id, code: "123456" });

const account = await sdk.account.getMe();

The Arky sign-in code is one of Arky’s own emails, sent from Arky’s address. For a store’s own login page, pass the store’s id to both calls: sdk.account.auth.requestCode({ email, store_id }) and sdk.account.auth.verify({ session_id, code, store_id }). The Admin client keeps and refreshes its session.

For trusted jobs, create one of the store’s secret keys and pass it as secretKey; see API keys.

Expired Codes

A customer code is accepted only by the session that asked for it, and an account code only with its own session_id. When a code expires, ask for a new one instead of retrying old state.

try {
	await arky.customer.verify({ code: "000000" });
} catch (error) {
	console.error(error instanceof Error ? error.message : "Verification failed");
}

Next Steps