Documentation
ReferenceJavaScript SDKNamespacesMulti-account

Multi-account

Keeping several signed-in accounts on one device and switching between them.

Some products need one browser to hold more than one identity at a time — an agency user with a personal and a work account, a support engineer with a test account beside their own. The browser client can keep them all and switch between them without a sign-out and a sign-in.

Browser only, and off by default. Turn it on when creating the client:

createClient(url, key, { multiUser: true });

With it off, the methods on this page still exist but nothing is ever saved to the accounts store.

There are two stores, and the distinction explains everything else:

the sessionactiveOptional

One at a time. What every call uses, kept under nlv-<slug>-token.

the accounts storemanyOptional

Everything you can switch to, kept under nlv-<slug>-token-accounts. Keyed by user id — the user.id of the response, or the sub claim of the access token.

add

add(auth) → void

Registers an account in the store without making it active.

const { data } = await nulvless.auth.signIn(params);
await nulvless.auth.add(data);

You rarely need it. With multiUser on, a successful sign-in, sign-up or challenge verification saves the account automatically, and every token renewal updates it — add is for the case where you hold an Authenticated from somewhere else and want it in the list.

switch

switch(userId) → boolean

Makes a saved account the active session.

const ok = await nulvless.auth.switch('usr_4c81f0a2');
if (!ok) return; // not in the store
userIdstringRequired

From list().

Returns false rather than throwing when the account is not there, so a stale id in your UI is a no-op rather than a crash. On success it emits account-switched.

Switching does not re-authenticate. If the stored token for that account has expired and cannot refresh, the next call raises unauthorized — handle that event by dropping the entry with remove, or the user sees a broken account in the switcher forever.

deselect

deselect() → void

Drops the active session without ending it on the server.

await nulvless.auth.deselect();

The account stays in the store, so switch brings it straight back. This is the one to call when the user leaves the signed-in area to pick or add another account: with no active session the automatic refresh has nothing to renew and goes quiet, instead of keeping a session warm that no screen is using.

It is not a sign out. The session stays alive server-side and on your other devices, and nothing is revoked.

The account entry is written from the session as it stands before it is dropped, so switching back never restores a refresh token older than the one that session already spent.

list

list() → AccountEntry[]

Everything currently in the store.

const accounts = await nulvless.auth.list();
// [{ userId, access_token, expires_in }]

expires_in is seconds remaining and may be negative for an entry whose token has already lapsed — useful for greying one out before the user picks it.

remove

remove(userId) → void

Drops an account from the store.

await nulvless.auth.remove(userId);

Does not touch the active session, and does not sign anyone out on the server. It forgets a token locally, which is the right behaviour for "remove from this device" and the wrong one for "sign out" — for that, signOut.

get and set

get() → Authenticated | null · set(data) → void

The active session, read and written directly.

const active = await nulvless.auth.get();

get returns what is stored, with expires_in recomputed as seconds remaining — negative when the token has already expired. It reads storage and makes no request, so it answers "is anyone signed in" instantly, where getSession asks the server for the authoritative record.

set replaces the active session. Reach for it only when restoring a session you persisted yourself; ordinary flows store it for you.

Next

On this page