Identity and authentication

Lakebed Auth is the built-in identity layer for capsules. Guest auth works with zero setup, and Google sign-in is first-party: no OAuth dashboards, no keys to configure, no redirect URIs to register. Render <SignInWithGoogle /> and it works, in dev and in hosted deploys.

Identity contract

An authenticated identity has one durable authorization key:

ctx.auth.userId === ctx.auth.subject; // google:usr_...

userId is opaque and immutable. It does not encode the deploy hostname, so a generated deploy URL and a custom domain resolve to the same userId. Key all user-owned data on it.

ctx.auth.identityAliases lists audience-scoped legacy aliases (google:ps_...), including at least the current audience's alias even for apps that never changed hostnames. Aliases exist only so an app with rows keyed before stable subjects existed can find and rewrite them. Never key new data on an alias; always use userId.

Email, emailVerified, name, and picture are profile data. A verified email may help your app locate a pending invitation, but it is never an authorization key and never evidence of access — not even as a fallback while verification is unavailable. Email changes do not change userId, and two accounts with the same email remain distinct users.

What your app can rely on

Auth shape

type Auth = {
  userId: string;
  subject?: string; // same immutable key as userId for authenticated identities
  identityAliases?: string[]; // migration-only audience-scoped aliases
  displayName: string;
  provider: "guest" | "google";
  isGuest: boolean;
  isAuthenticated: boolean;
  isLoading?: boolean; // client-only
  email?: string;
  emailVerified?: boolean;
  picture?: string;
};

Local dev

npx lakebed dev uses first-party Lakebed Auth automatically, including real Google sign-in on localhost. Nothing to configure.

For guest identities in dev, set the global guest with npx lakebed auth as alice, or use per-tab identities with ?lakebed_guest=alice in the app URL.

Migrating from older identities

Identity records created by the previous external broker are not automatically linked to first-party google:usr_... identities; users must sign in again. If application data is keyed by an older provider subject, migrate it through explicit reauthorization or account linking. Never infer a link from email. identityAliases does not cover external-broker subjects; it only lists Lakebed Auth pairwise aliases.