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
| Flow | Provider name | Notes |
|---|---|---|
| OAuth | google, github, azure, … | Redirect-based; adapter must support the provider |
| Magic link | magic | OTP via email; set mode: "otp" |
| Email + password | email | Set mode: "password" |
| Passkey | passkey | WebAuthn; 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 authenticationprotected: true— requires any valid sessionroles: ['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.