Aura Auth
Configuration

Identity Schema

Configure and extend the identity schema Aura Auth uses to validate user data, across Zod, Valibot, ArkType, and TypeBox.

The identity option on createAuth defines the schema Aura Auth uses to validate and shape user identity data. The schema you provide is also used to derive the User and Session types used across the rest of the library, so setting it up correctly gets you type-safe access to your custom fields everywhere User/Session are used.

@/lib/auth.ts
import { createAuth } from "@aura-stack/auth"
import { identitySchema, zod } from "@aura-stack/auth/identity/zod"

export const auth = createAuth({
  oauth: [],
  identity: {
    schema: identitySchema.extend({
      role: zod.enum(["user", "admin"]),
    }),
  },
})

Options

OptionTypeRequiredDescription
schemaValidator-specific schema typeNoExtends the default identity schema for your chosen validator. See Choosing a validator.
unknownKeys"strip" | "passthrough" | "strict"No (default "strip")Controls how fields not defined in the schema are handled. strip removes them, passthrough allows them through unvalidated, strict throws.
skipValidationbooleanNo (default false)Skips identity validation entirely. See Disabling validation.

Choosing a validator

Zod, Valibot, ArkType, and TypeBox are supported as the first-class and import its default schema from @aura-stack/auth/identity/:schema.

Built-in type inference (via InferUser/InferSession) is supported for Zod, Valibot, and ArkType. TypeBox is supported for validation but does not support direct type inference — see the Type Inference section for the workaround.

Extending the default schema

Each supported validator ships a default identitySchema containing the required base fields. Extend it with whatever additional fields your application needs.

lib/auth.ts
import { createAuth } from "@aura-stack/auth"
import { identitySchema, zod } from "@aura-stack/auth/identity/zod"

const schema = identitySchema.extend({
  role: zod.enum(["admin", "user"]),
})

export const auth = createAuth({
  oauth: [],
  identity: {
    schema,
  },
})
lib/auth.ts
import { createAuth } from "@aura-stack/auth"
import { identitySchema, valibot } from "@aura-stack/auth/identity/valibot"

const schema = valibot.object({
  ...identitySchema.entries,
  role: valibot.enum({ admin: "admin", user: "user" }),
})

export const auth = createAuth({
  oauth: [],
  identity: {
    schema,
  },
})
lib/auth.ts
import { createAuth } from "@aura-stack/auth"
import { identitySchema, arktype } from "@aura-stack/auth/identity/arktype"

const schema = identitySchema.and({
  role: arktype.type.enumerated(["admin", "user"]),
})

export const auth = createAuth({
  oauth: [],
  identity: {
    schema,
  },
})
lib/auth.ts
import { createAuth } from "@aura-stack/auth"
import { identitySchema, typebox } from "@aura-stack/auth/identity/typebox"

const schema = typebox.Object({
  ...identitySchema.properties,
  role: typebox.Union([typebox.Literal("admin"), typebox.Literal("user")]),
})

export const auth = createAuth({
  oauth: [],
  identity: {
    schema,
  },
})

Type inference

Aura Auth provides utility types to infer User and Session from your identity schema, so the rest of your application gets type safety and autocompletion on custom fields without manual duplication.

Infer directly from the auth instance with InferUser/InferSession, or from the schema itself with UserFrom/SessionFrom.

lib/auth.ts
import { createAuth } from "@aura-stack/auth"
import { identitySchema, zod } from "@aura-stack/auth/identity/zod"
import type { UserFrom, SessionFrom, InferUser, InferSession } from "@aura-stack/auth/identity"

const schema = identitySchema.extend({
  role: zod.enum(["admin", "user"]),
  permissions: zod.array(zod.string()),
})

type _User = UserFrom<typeof schema>
type _Session = SessionFrom<typeof schema>

export const auth = createAuth({
  oauth: [],
  identity: {
    schema,
  },
})

export type User = InferUser<typeof auth>
export type Session = InferSession<typeof auth>
lib/auth.ts
import { createAuth } from "@aura-stack/auth"
import { identitySchema, valibot } from "@aura-stack/auth/identity/valibot"
import type { InferUser, InferSession, UserFrom, SessionFrom } from "@aura-stack/auth/identity"

const schema = valibot.object({
  ...identitySchema.entries,
  role: valibot.enum({ admin: "admin", user: "user" }),
})

type _User = UserFrom<typeof schema>
type _Session = SessionFrom<typeof schema>

export const auth = createAuth({
  oauth: [],
  identity: {
    schema,
  },
})

export type User = InferUser<typeof auth>
export type Session = InferSession<typeof auth>
lib/auth.ts
import { createAuth } from "@aura-stack/auth"
import { identitySchema, arktype } from "@aura-stack/auth/identity/arktype"
import type { InferUser, InferSession, UserFrom, SessionFrom } from "@aura-stack/auth/identity"

const schema = identitySchema.and({
  role: arktype.type.enumerated(["admin", "user"]),
})

type _User = UserFrom<typeof schema>
type _Session = SessionFrom<typeof schema>

export const auth = createAuth({
  oauth: [],
  identity: {
    schema,
  },
})

export type User = InferUser<typeof auth>
export type Session = InferSession<typeof auth>

Aura Auth does not currently support inferring types directly from a TypeBox schema, due to the computational cost of TypeBox's type inference. As a workaround, use TypeBox's own Static type to derive User and Session from your schema manually.

lib/auth.ts
import { createAuth } from "@aura-stack/auth"
import { identitySchema, typebox } from "@aura-stack/auth/identity/typebox"

const schema = typebox.Object({
  ...identitySchema.properties,
  role: typebox.Union([typebox.Literal("admin"), typebox.Literal("user")]),
})

export type User = typebox.Static<typeof schema>
export type Session = typebox.Static<typeof schema>

export const auth = createAuth({
  oauth: [],
  identity: {
    schema,
  },
})

Handling unknown keys

By default, fields present on an incoming identity object but absent from your schema are silently removed (strip). Change this with unknownKeys if you need unvalidated passthrough fields, or want unexpected fields to fail loudly during development.

@/lib/auth.ts
import { createAuth } from "@aura-stack/auth"

export const auth = createAuth({
  oauth: [],
  identity: {
    unknownKeys: "strict", // throws if the identity object has fields outside the schema
  },
})

Disabling validation

When schema validation isn't relevant to your application, set skipValidation to true to accept any shape of identity object without enforcement.

@/lib/auth.ts
import { createAuth } from "@aura-stack/auth"

export const auth = createAuth({
  oauth: [],
  identity: {
    skipValidation: true,
  },
})

Skipping validation removes Aura Auth's guarantee that User/Session objects match your declared shape at runtime. Only disable this if your upstream identity provider or database layer already enforces the shape you need.

On this page