Skip to main content

Authentication

convex-svelte integrates with any authentication provider through a small, reactive API. The setupAuth() / useAuth() primitives below are the low-level integration point; on top of them, the Auth adapters section covers higher-level options that wire a specific auth system to Convex for you. For background on how authentication works in Convex generally — including hosted providers and the OpenID Connect model — see Authentication.

setupAuth / useAuth

setupAuth() accepts a reactive getter returning the auth provider's state and automatically manages client.setAuth() / client.clearAuth(). This mirrors React's ConvexProviderWithAuth — when the provider state changes (sign-in, sign-out, token refresh), the auth lifecycle updates automatically.

src/routes/+layout.svelte
<script lang="ts">
import { setupConvex, setupAuth } from "convex-svelte";
import { PUBLIC_CONVEX_URL } from "$env/static/public";

setupConvex(PUBLIC_CONVEX_URL);

// The getter is reactive — when its return values change,
// setupAuth automatically toggles setAuth/clearAuth.
setupAuth(() => ({
isLoading: false,
isAuthenticated: !!session,
fetchAccessToken: async ({ forceRefreshToken }) => {
if (!session) return null;
return await getTokenFromYourAuthProvider({ forceRefreshToken });
},
}));
</script>

useAuth() reads the resulting state in any child component:

<script lang="ts">
import { useAuth, useQuery } from "convex-svelte";
import { api } from "../convex/_generated/api.js";

const auth = useAuth();

const user = useQuery(api.users.getActive, () =>
auth.isAuthenticated ? {} : "skip",
);
</script>

{#if auth.isLoading}
Checking authentication...
{:else if !auth.isAuthenticated}
Please sign in.
{:else}
Welcome, {user.data?.name}!
{/if}

When the auth provider's isAuthenticated changes from true to false (user signs out), the internal $effect re-runs, calls clearAuth() automatically, and useAuth().isAuthenticated updates to false. No manual cleanup needed.

SSR initial state

Pass initialState to seed the server render before any client-side $effect runs:

src/routes/+layout.svelte
<script lang="ts">
import { setupConvex, setupAuth } from "convex-svelte";

let { data } = $props(); // from +layout.server.ts

setupConvex(PUBLIC_CONVEX_URL);
setupAuth(
() => ({
isLoading: session.isPending,
isAuthenticated: !!session.data,
fetchAccessToken: async ({ forceRefreshToken }) =>
getToken({ forceRefreshToken }),
}),
{ initialState: { isAuthenticated: data.isAuthenticated } },
);
</script>

The server state is trusted until the client-side auth flow settles, then the client takes over. For authenticated server-side data fetching, see Authenticated fetches.

Auth adapters

The primitives above let you wire up any provider by hand. In practice, most apps reach for a higher-level adapter that connects a specific auth system to Convex and calls setupAuth() for you, so useAuth() works out of the box.

Convex Auth

Convex Auth is Convex's built-in, officially documented auth library — authentication runs entirely on your own Convex deployment with no third-party service.

Convex Better Auth

Convex Better Auth integrates the powerful Better Auth library with Convex.

  • Svelte adapter: @mmailaender/convex-better-auth-svelte (community-maintained) — its createSvelteAuthClient() calls setupAuth() internally with a reactive session getter, so useAuth() from either package works. SSR-ready.
  • UI components: Convex Better Auth UI (community-maintained) — production-ready, shadcn-style auth and organization management for SvelteKit (and Next.js), copied into your project. Gets user and organization management running in minutes while keeping full control of the code.

Hosted providers

Convex also works with hosted identity platforms via OpenID Connect JWTs — Clerk, WorkOS AuthKit, and Auth0. There are no dedicated convex-svelte wrappers for these yet, so in a Svelte app you integrate them through the low-level setupAuth() pattern: return the provider's reactive auth state (isLoading, isAuthenticated, fetchAccessToken) from the getter.

Low-level: client.setAuth()

You can also use client.setAuth() directly for custom integrations:

<script lang="ts">
import { useConvexClient } from "convex-svelte";

const client = useConvexClient();

client.setAuth(
async () => {
return await getAuthToken();
},
(isAuthenticated) => {
console.log("Auth state changed:", isAuthenticated);
},
);
</script>

API reference

Authentication exports from convex-svelte:

ExportKindDescription
setupAuth(provider, options?)FunctionSet up reactive authentication. Manages setAuth/clearAuth automatically.
useAuth()FunctionRead auth state (isLoading, isAuthenticated) from context.
ConvexAuthProviderTypeAuth provider state: isLoading, isAuthenticated, fetchAccessToken.
SetupAuthOptionsTypeOptions for setupAuth: initialState for SSR hydration.
UseAuthReturnTypeReturn type of useAuth: isLoading, isAuthenticated.