The AuthKit library for SvelteKit provides convenient helpers for authentication and session management using WorkOS & AuthKit with SvelteKit.
- 🚀 5-minute setup - Complete authentication in 3 files
- 🔒 Secure by default - Production-ready security settings
- 📱 Platform agnostic - Works on Node.js, Cloudflare Workers, Vercel Edge
- 🎯 Type-safe - Full TypeScript support with auto-completion
- ⚡ Zero config - Works with environment variables out of the box
- 🧩 SvelteKit native - Feels like a built-in SvelteKit feature
Install the package with:
npm install @workos-inc/authkit-sveltekitor
yarn add @workos-inc/authkit-sveltekitMake sure the following values are present in your .env environment variables file. The client ID and API key can be found in the WorkOS dashboard, and the redirect URI can also be configured there.
WORKOS_CLIENT_ID="client_..." # retrieved from the WorkOS dashboard
WORKOS_API_KEY="sk_test_..." # retrieved from the WorkOS dashboard
WORKOS_COOKIE_PASSWORD="<your password>" # generate a secure password here
WORKOS_REDIRECT_URI="http://localhost:5173/callback" # configured in the WorkOS dashboardWORKOS_COOKIE_PASSWORD is the private key used to encrypt the session cookie. It has to be at least 32 characters long. You can use the 1Password generator or the openssl library to generate a strong password via the command line:
openssl rand -base64 32Certain environment variables are optional and can be used to debug or configure cookie settings.
| Environment Variable | Default Value | Description |
|---|---|---|
WORKOS_COOKIE_MAX_AGE |
34560000 (400 days) |
Maximum age of the cookie in seconds |
WORKOS_COOKIE_DOMAIN |
None | Domain for the cookie. When empty, the cookie is only valid for the current domain |
WORKOS_COOKIE_NAME |
'workos_session' |
Name of the session cookie |
WORKOS_COOKIE_SAMESITE |
'lax' |
SameSite attribute for cookies. Options: 'lax', 'strict', or 'none' |
Example usage:
WORKOS_COOKIE_MAX_AGE='600'
WORKOS_COOKIE_DOMAIN='example.com'
WORKOS_COOKIE_NAME='my-auth-cookie'Warning
Setting WORKOS_COOKIE_SAMESITE='none' allows cookies to be sent in cross-origin contexts (like iframes), but reduces protection against CSRF attacks. This setting forces cookies to be secure (HTTPS only) and should only be used when absolutely necessary for your application architecture.
Tip
WORKOS_COOKIE_DOMAIN can be used to share WorkOS sessions between apps/domains. Note: The WORKOS_COOKIE_PASSWORD would need to be the same across apps/domains. Not needed for most use cases.
Create or update your src/hooks.server.ts file:
import { createAuthKitHandle } from '@workos-inc/authkit-sveltekit';
export const handle = createAuthKitHandle();For advanced configuration:
import { createAuthKitHandle } from '@workos-inc/authkit-sveltekit';
export const handle = createAuthKitHandle({
protectedPaths: ['/dashboard', '/admin'],
excludePaths: ['/login', '/logout', '/callback', '/public'],
loginPath: '/auth/signin'
});Add the following to your src/app.d.ts file:
import type { AuthLocals } from '@workos-inc/authkit-sveltekit';
declare global {
namespace App {
interface Locals extends AuthLocals {}
// ... your other type definitions
}
}
export {};Create src/routes/login/+server.ts:
export { GET } from '@workos-inc/authkit-sveltekit/login';For custom configuration:
import { loginHandler } from '@workos-inc/authkit-sveltekit';
export const GET = loginHandler({
screenHint: 'sign-in' // or 'sign-up'
});Create src/routes/logout/+server.ts:
export { POST } from '@workos-inc/authkit-sveltekit/logout';Create src/routes/callback/+server.ts:
export { GET } from '@workos-inc/authkit-sveltekit/callback';For custom success handling:
import { callbackHandler } from '@workos-inc/authkit-sveltekit';
export const GET = callbackHandler({
onSuccess: async (user, session) => {
// Custom logic after successful authentication
console.log(`User ${user.email} signed in`);
}
});Use the authentication data that's automatically populated in locals:
<!-- src/routes/+page.svelte -->
<script>
import { page } from '$app/stores';
$: user = $page.data.user;
</script>
{#if user}
<h1>Welcome back, {user.firstName}!</h1>
<form method="POST" action="/logout">
<button type="submit">Sign Out</button>
</form>
{:else}
<a href="/login">Sign In</a>
{/if}In your +layout.server.ts:
import type { LayoutServerLoad } from './$types';
export const load: LayoutServerLoad = async ({ locals }) => {
return {
user: locals.user
};
};AuthKit SvelteKit provides ready-to-use Svelte components:
<script>
import { SignInButton, SignOutButton, UserProfile } from '@workos-inc/authkit-sveltekit/components';
import { page } from '$app/stores';
$: user = $page.data.user;
</script>
{#if user}
<UserProfile {user} />
<SignOutButton />
{:else}
<SignInButton screenHint="sign-up">Create Account</SignInButton>
{/if}<!-- Custom sign-in button -->
<SignInButton screenHint="sign-up" class="btn btn-primary">
Create Your Account
</SignInButton>
<!-- User profile with custom template -->
<UserProfile {user} let:user>
<div class="profile">
<img src={user.profilePictureUrl} alt="Profile" />
<span>{user.firstName} {user.lastName}</span>
<small>{user.email}</small>
</div>
</UserProfile>Use reactive stores for client-side authentication state:
<script>
import { authUser, isAuthenticated } from '@workos-inc/authkit-sveltekit/stores';
</script>
{#if $isAuthenticated}
<p>Welcome back, {$authUser.firstName}!</p>
{:else}
<p>Please sign in to continue.</p>
{/if}Use requireAuth to protect page load functions:
// src/routes/dashboard/+page.server.ts
import { requireAuth } from '@workos-inc/authkit-sveltekit';
export const load = requireAuth(async ({ locals }) => {
// locals.user is guaranteed to exist and fully typed
return {
user: locals.user,
dashboardData: await fetchDashboardData(locals.user.id)
};
});Protect API endpoints with withAuth:
// src/routes/api/user/+server.ts
import { json } from '@sveltejs/kit';
import { withAuth } from '@workos-inc/authkit-sveltekit';
export const GET = withAuth(async ({ locals }) => {
return json({
user: locals.user,
timestamp: new Date().toISOString()
});
});// src/hooks.server.ts
import { createAuthKitHandle } from '@workos-inc/authkit-sveltekit';
export const handle = createAuthKitHandle({
protectedPaths: ['/dashboard', '/admin'],
excludePaths: ['/login', '/logout', '/callback', '/api/public'],
loginPath: '/auth/signin',
populateLocals: true
});// src/hooks.server.ts
import { createAuthKitHandle, loadAuthKitEnv } from '@workos-inc/authkit-sveltekit';
const config = loadAuthKitEnv(); // Loads from WORKOS_* environment variables
export const handle = createAuthKitHandle({
...config,
protectedPaths: ['/dashboard']
});Access organization data through locals:
// src/routes/dashboard/+page.server.ts
export const load = requireAuth(async ({ locals }) => {
const { user, organizationId, role, permissions } = locals;
return {
user,
organization: organizationId ? await getOrganization(organizationId) : null,
userRole: role,
userPermissions: permissions
};
});Refresh user sessions to get the latest data:
<script>
import { invalidateAll } from '$app/navigation';
async function refreshSession() {
// Trigger a refresh of all load functions
await invalidateAll();
}
</script>
<button on:click={refreshSession}>Refresh Session</button>Handle authentication errors gracefully:
// src/routes/api/protected/+server.ts
import { json, error } from '@sveltejs/kit';
import { withAuth } from '@workos-inc/authkit-sveltekit';
export const GET = withAuth(async ({ locals }) => {
try {
const data = await fetchSensitiveData(locals.user.id);
return json(data);
} catch (err) {
console.error('API error:', err);
throw error(500, 'Failed to fetch data');
}
});Add environment variables to your Vercel deployment:
vercel env add WORKOS_CLIENT_ID
vercel env add WORKOS_API_KEY
vercel env add WORKOS_REDIRECT_URI
vercel env add WORKOS_COOKIE_PASSWORDAdd to your wrangler.toml:
[vars]
WORKOS_CLIENT_ID = "your_client_id"
WORKOS_REDIRECT_URI = "https://your-app.pages.dev/callback"
# Add secrets using wrangler
# npx wrangler secret put WORKOS_API_KEY
# npx wrangler secret put WORKOS_COOKIE_PASSWORDAdd environment variables in your Netlify dashboard or netlify.toml:
[build.environment]
WORKOS_CLIENT_ID = "your_client_id"
WORKOS_REDIRECT_URI = "https://your-app.netlify.app/callback"# In your Dockerfile
ENV WORKOS_CLIENT_ID=your_client_id
ENV WORKOS_REDIRECT_URI=https://your-app.com/callbackFor advanced use cases, you can access the underlying session manager:
import { getSessionManager } from '@workos-inc/authkit-sveltekit';
// In a server-side context
const sessionManager = getSessionManager();
const authResult = await sessionManager.withAuth(request);Access the WorkOS client directly for advanced operations:
import { getWorkOS } from '@workos-inc/authkit-ssr';
const workos = getWorkOS();
const organizations = await workos.organizations.listOrganizations({
limit: 10
});Implement custom session storage for special deployment needs:
import { createSvelteKitAuthKit, SvelteKitStorage } from '@workos-inc/authkit-sveltekit';
class CustomStorage extends SvelteKitStorage {
// Override storage methods for custom behavior
}
const sessionManager = createSvelteKitAuthKit({
storage: new CustomStorage(config)
});// Re-exported from @workos-inc/node
export type { User, Impersonator } from '@workos-inc/node';
// Re-exported from @workos-inc/authkit-ssr
export type { AuthResult, Session } from '@workos-inc/authkit-ssr';
// SvelteKit-specific types
export interface AuthLocals {
user: User | null;
sessionId?: string;
organizationId?: string;
role?: string;
permissions?: string[];
impersonator?: Impersonator;
accessToken?: string;
}| Function | Description |
|---|---|
createAuthKitHandle(options?) |
Creates SvelteKit handle function |
requireAuth(loadFn, loginPath?) |
Wraps load functions to require auth |
withAuth(handler) |
Wraps API handlers to require auth |
loadAuthKitEnv(prefix?) |
Loads config from environment variables |
| Component | Props | Description |
|---|---|---|
SignInButton |
screenHint?, returnPathname?, class? |
Pre-built sign-in button |
SignOutButton |
returnTo?, class? |
Pre-built sign-out button |
UserProfile |
user, children? |
User profile display |
| Store | Type | Description |
|---|---|---|
authUser |
Readable<User | null> |
Current user state |
isAuthenticated |
Readable<boolean> |
Authentication status |
userOrganizations |
Readable<Organization[]> |
User's organizations |
currentOrganization |
Readable<Organization | null> |
Current organization |
Check out our examples for different use cases:
- Minimal Setup - Get started in 5 minutes
- Organizations - Multi-tenant applications
- Role-based Access - Permission-based routing
- Cloudflare Pages - Edge deployment
If you're migrating from a manual WorkOS implementation:
- Replace your custom hooks.server.ts with
createAuthKitHandle() - Replace manual route handlers with the provided exports
- Update your app.d.ts to extend
AuthLocals - Replace manual session checks with
requireAuthandwithAuth
| Old Pattern | New Pattern |
|---|---|
| Custom session management | createAuthKitHandle() |
| Manual login routes | export { GET } from '@workos-inc/authkit-sveltekit/login' |
| Custom auth checks | requireAuth(), withAuth() |
| Manual user state | $page.data.user, stores |
- Ensure all environment variables are set correctly
- Verify
WORKOS_COOKIE_PASSWORDis 32+ characters - Restart your development server after adding environment variables
- Check that
WORKOS_REDIRECT_URImatches your callback route exactly - Ensure the callback route (
/callback/+server.ts) is properly configured - Verify the redirect URI is configured in your WorkOS dashboard
- Ensure you've extended
AuthLocalsin yourapp.d.tsfile - Restart your TypeScript language server
- Check that you're importing types from the correct paths
- Verify your application is running on the same domain as configured
- Check cookie security settings in production vs development
- Ensure
WORKOS_COOKIE_DOMAINis correctly configured if set
Enable debug logging to troubleshoot issues:
// src/hooks.server.ts
import { createAuthKitHandle } from '@workos-inc/authkit-sveltekit';
export const handle = createAuthKitHandle({
debug: true // Enable debug logs
});We welcome contributions! Please see our Contributing Guide for details.
MIT © WorkOS