Core Concepts

Authentication, authorization, and session management.

Authentication

Kavach supports OAuth (Google, GitHub, etc.), email + password, magic link (OTP), and passkey. You configure providers in kavach.config.js — the UI components and sign-in API work the same regardless of which you choose.

Client-side setup

Create a kavach instance in your root layout and share it via Svelte context. Must run in onMount — browser only.

<!-- src/routes/+layout.svelte -->
<script>
  import { setContext, onMount } from 'svelte'
  import { page } from '$app/stores'

  const kavach = $state({})
  setContext('kavach', kavach)

  onMount(async () => {
    const { createKavach } = await import('kavach')
    const { adapter, logger } = await import('$kavach/auth')
    const { invalidateAll } = await import('$app/navigation')
    const instance = createKavach(adapter, { logger, invalidateAll })
    Object.assign(kavach, instance)
    instance.onAuthChange($page.url)
  })
</script>

Sign in / sign out

<script>
  import { getContext } from 'svelte'
  const kavach = getContext('kavach')
</script>

<!-- OAuth -->
<button onclick={() => kavach.signIn({ provider: 'google' })}>Continue with Google</button>

<!-- Email + password -->
<button onclick={() => kavach.signIn({ provider: 'email', email, password })}>Sign in</button>

<!-- Magic link -->
<button onclick={() => kavach.signIn({ provider: 'magic', email })}>Send magic link</button>

<button onclick={() => kavach.signOut()}>Sign out</button>

Auth flows

FlowProvider nameNotes
OAuthgoogle, github, azure, …Redirect-based; adapter must support the provider
Magic linkmagicOTP via email; set mode: "otp"
Email + passwordemailSet mode: "password"
PasskeypasskeyWebAuthn; Supabase and Firebase only

Authorization

Route protection is declared in kavach.config.js and enforced automatically by kavach.handle on every request. No per-route auth checks needed.

Route rules

// kavach.config.js
export default {
  rules: [
    { path: '/auth',      public: true },       // no auth needed
    { path: '/',          public: true },
    { path: '/dashboard', protected: true },     // any authenticated user
    { path: '/admin',     roles: ['admin'] },    // specific role required
    { path: '/api',       roles: ['user', 'admin'] }
  ],
  roleHome: {
    admin: '/admin',     // where admins land after login
    user:  '/dashboard'
  }
}

How rules are evaluated

  • Rules are prefix-matched in order — first match wins
  • public: true — accessible without authentication
  • protected: true — requires any valid session
  • roles: ['admin'] — requires one of the listed roles
  • Unauthenticated access to protected route → redirect to auth route
  • Wrong role → redirect to roleHome[role] or auth route

Session Management

Kavach uses stateless cookie-based sessions — no server-side session store required. The session is stored in an httpOnly cookie, parsed on each request by kavach.handle, and available as event.locals.session in all load functions.

The full session chain

// 1. kavach.handle parses the cookie and sets locals.session
// src/hooks.server.js
import { kavach } from '$kavach/auth'
export const handle = kavach.handle

// 2. Pass session to all pages via layout.server
// src/routes/+layout.server.js
export function load({ locals }) {
  return { session: locals.session }
}

// 3. Guard individual routes
// src/routes/dashboard/+page.server.js
import { redirect } from '@sveltejs/kit'
export function load({ locals }) {
  if (!locals.session) redirect(303, '/auth')
  return { user: locals.session.user }
}

// 4. Access in components via $page.data
// src/routes/+page.svelte
<script>
  import { page } from '$app/stores'
  $: user = $page.data.session?.user
</script>
<p>Hello {user?.email}</p>

Session shape

{
  user: {
    id: 'uuid',
    email: 'user@example.com',
    role: 'user'
  },
  access_token: 'jwt...',
  refresh_token: 'token...',
  expires_in: 3600
}

Token refresh

When the adapter fires an auth state change (e.g. after OAuth callback), the client POSTs to /auth/session. The server validates the token via the adapter, writes a fresh cookie, and calls invalidateAll() to re-run load functions.

Next Steps

Kavach — Authentication made simple llms.txt