User schemas
How the user schema checks every user the client accepts, and what restoring a session requires of it.
The schema you pass as createAuth's user option checks each user the
client accepts and gives the user its type. This page explains when it runs,
and the two rules it must follow so that a saved session can be restored.
Any Standard Schema library works, such as Zod, Valibot or ArkType. If your backend puts the user in the access token instead, see Users from the access token.
When the schema runs
The client runs the schema on every user it accepts:
- At sign-in.
- When
updateUserreplaces the user. - After a refresh that returns a user.
- When it restores a saved session.
- When another tab saves a session.
It keeps a frozen copy of each user it accepts. To change the user, call
updateUser.
The user's type
createAuth infers the user's type from the schema's output. Hover user to
see it:
import { , } from "@monarcode/session-kit";
import { } from "zod";
const = ({
: "my-app",
: .({ : .(), : .() }),
: (),
});
const { user } = ..();To name the types elsewhere, use UserOf<typeof auth> and
SessionOf<typeof auth>. To type the hooks from
@monarcode/session-kit/react, register the client once, as
Getting started shows.
Rules for restoring
The client saves the user beside the tokens, and runs the schema on it again when it restores the session. That sets two rules for the schema:
- Its output is a plain JSON object. Dates,
Maps and class instances can't be saved. - It accepts its own output and returns it unchanged. A one-way transform, such as one that renames a field, breaks this rule.
A schema that breaks either rule is rejected with USER_VALIDATION_FAILED
the first time it accepts a user, usually at sign-in. That way the problem
shows up at once, not as users being signed out on their next reload.
Users the schema rejects
A deploy can change the schema so that it rejects users saved before it. The
client doesn't restore such a user, so the user signs in again. A user saved by
another tab that the schema rejects signs every tab out, with
USER_VALIDATION_FAILED in state.error.