npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@authrim/sveltekit

v0.1.7

Published

SvelteKit SDK for Authrim authentication

Readme

@authrim/sveltekit

npm version License

Official SvelteKit SDK for Authrim authentication.

Features

  • Passkey Authentication - WebAuthn-based passwordless login
  • Email Code (OTP) - One-time password via email
  • Social Login - Google, GitHub, Apple, Microsoft, Facebook
  • Svelte Stores - Reactive authentication state
  • Server-Side Integration - SvelteKit hooks and load functions
  • SSR Support - Full server-side rendering compatibility
  • TypeScript - Complete type definitions
  • UI Components - Ready-to-use authentication components

Requirements

  • Node.js >= 18
  • SvelteKit >= 2.0
  • Svelte >= 4.0 or >= 5.0
  • @authrim/core >= 0.1.10

Installation

# pnpm (recommended)
pnpm add @authrim/sveltekit @authrim/core

# npm
npm install @authrim/sveltekit @authrim/core

# yarn
yarn add @authrim/sveltekit @authrim/core

Note: @authrim/core is a peer dependency that provides the underlying authentication logic. You need to install it alongside @authrim/sveltekit, but you don't need to import from it directly—all necessary types and functions are re-exported from @authrim/sveltekit.

Quick Start

1. Create Auth Client

// src/lib/auth.ts
import { createAuthrim } from '@authrim/sveltekit';

export const auth = await createAuthrim({
  issuer: 'https://auth.example.com',
  clientId: 'your-client-id',
});

By default, @authrim/sveltekit uses server-mediated auth: Direct Auth artifacts are redeemed by your SvelteKit server and OAuth/OIDC tokens are not returned to browser JavaScript. Server session cookies are HttpOnly and AES-GCM encrypted with AUTHRIM_SESSION_SECRET; use at least 32 bytes of high-entropy secret material.

2. Set Up Server-Mediated Auth Endpoints

// src/routes/authrim/session/exchange/+server.ts
import { createDirectAuthSessionHandlers } from '@authrim/sveltekit/server';
import { AUTHRIM_ISSUER, AUTHRIM_CLIENT_ID, AUTHRIM_SESSION_SECRET } from '$env/static/private';

const handlers = createDirectAuthSessionHandlers({
  issuer: AUTHRIM_ISSUER,
  clientId: AUTHRIM_CLIENT_ID,
  sessionSecret: AUTHRIM_SESSION_SECRET,
});

export const POST = handlers.exchange;
// src/routes/authrim/session/+server.ts
import { createDirectAuthSessionHandlers } from '@authrim/sveltekit/server';
import { AUTHRIM_ISSUER, AUTHRIM_CLIENT_ID, AUTHRIM_SESSION_SECRET } from '$env/static/private';

const handlers = createDirectAuthSessionHandlers({
  issuer: AUTHRIM_ISSUER,
  clientId: AUTHRIM_CLIENT_ID,
  sessionSecret: AUTHRIM_SESSION_SECRET,
});

export const GET = handlers.session;
// src/routes/authrim/session/logout/+server.ts
import { createDirectAuthSessionHandlers } from '@authrim/sveltekit/server';
import { AUTHRIM_ISSUER, AUTHRIM_CLIENT_ID, AUTHRIM_SESSION_SECRET } from '$env/static/private';

const handlers = createDirectAuthSessionHandlers({
  issuer: AUTHRIM_ISSUER,
  clientId: AUTHRIM_CLIENT_ID,
  sessionSecret: AUTHRIM_SESSION_SECRET,
});

export const POST = handlers.logout;

3. Set Up Server Hooks

// src/hooks.server.ts
import { createAuthHandle } from '@authrim/sveltekit/server';
import { AUTHRIM_SESSION_SECRET } from '$env/static/private';

export const handle = createAuthHandle({
  sessionSecret: AUTHRIM_SESSION_SECRET,
});

4. Configure Type Safety

// src/app.d.ts
import type { ServerAuthContext } from '@authrim/sveltekit/server';

declare global {
  namespace App {
    interface Locals {
      auth?: ServerAuthContext;
    }
  }
}

export {};

5. Set Up AuthProvider

<!-- src/routes/+layout.svelte -->
<script lang="ts">
  import { AuthProvider } from '@authrim/sveltekit/components';
  import { auth } from '$lib/auth';

  export let data;
</script>

<AuthProvider
  {auth}
  initialSession={data.auth?.session}
  initialUser={data.auth?.user}
>
  <slot />
</AuthProvider>
// src/routes/+layout.server.ts
import { createAuthLoad } from '@authrim/sveltekit/server';

export const load = createAuthLoad();

6. Use Authentication

<!-- src/routes/+page.svelte -->
<script lang="ts">
  import { getAuthContext } from '@authrim/sveltekit';

  const auth = getAuthContext();
  const { session, user, isAuthenticated, loadingState } = auth.stores;

  async function handleLogin() {
    const result = await auth.passkey.login();
    if (result.error) {
      console.error(result.error.message);
    }
  }
</script>

{#if $loadingState !== 'idle'}
  <p>Loading...</p>
{:else if $isAuthenticated}
  <p>Welcome, {$user?.name}</p>
  <button on:click={() => auth.signOut()}>Sign Out</button>
{:else}
  <button on:click={handleLogin}>Sign In with Passkey</button>
{/if}

API Reference

createAuthrim(config)

Creates an Authrim client instance.

const auth = await createAuthrim({
  issuer: 'https://auth.example.com',
  clientId: 'your-client-id',
  storage: {
    storage: 'sessionStorage', // 'memory' | 'sessionStorage' | 'localStorage'
    prefix: 'authrim',
  },
});

The default authMode is 'server'. Set authMode: 'browser' only when this SvelteKit app intentionally uses browser-held OAuth/OIDC tokens.

const auth = await createAuthrim({
  issuer: 'https://auth.example.com',
  clientId: 'your-client-id',
  authMode: 'browser',
  browserPublicClientMode: 'strict',
});

Authentication Namespaces

auth.passkey

// Login with Passkey
const result = await auth.passkey.login();

// Login with Conditional UI (autofill)
const result = await auth.passkey.login({ conditional: true });

// Sign up with Passkey
const result = await auth.passkey.signUp({ email: '[email protected]' });

// Register new Passkey (requires authentication)
const credential = await auth.passkey.register();

// Check support
auth.passkey.isSupported(); // boolean
await auth.passkey.isConditionalUIAvailable(); // Promise<boolean>

// Cancel Conditional UI
auth.passkey.cancelConditionalUI();

auth.emailCode

// Send verification code
const result = await auth.emailCode.send('[email protected]');

// Verify code
const result = await auth.emailCode.verify('[email protected]', '123456');

// Check pending verification
auth.emailCode.hasPendingVerification('[email protected]'); // boolean
auth.emailCode.getRemainingTime('[email protected]'); // seconds
auth.emailCode.clearPendingVerification('[email protected]');

auth.social

// Login with popup
const result = await auth.social.loginWithPopup('google');

// Login with redirect
await auth.social.loginWithRedirect('github');

// Handle callback (after redirect)
if (auth.social.hasCallbackParams()) {
  const result = await auth.social.handleCallback();
}

// Get supported providers
auth.social.getSupportedProviders(); // ['google', 'github', 'apple', 'microsoft', 'facebook']

auth.session

// Get current session
const result = await auth.session.get();

// Validate session
const isValid = await auth.session.validate();

// Get user
const user = await auth.session.getUser();

// Refresh session cache
const session = await auth.session.refresh();

// Check authentication
const isAuth = await auth.session.isAuthenticated();

// Clear cache
auth.session.clearCache();

Shortcuts

// Sign in
await auth.signIn.passkey();
await auth.signIn.social('google');

// Sign up
await auth.signUp.passkey({ email: '[email protected]' });

// Sign out
await auth.signOut();
await auth.signOut({ redirectUri: '/login' });

Svelte Stores

All stores are Readable (not Writable) to ensure events are the source of truth.

const { session, user, isAuthenticated, loadingState, error } = auth.stores;

| Store | Type | Description | |-------|------|-------------| | session | Readable<Session \| null> | Current session | | user | Readable<User \| null> | Current user | | isAuthenticated | Readable<boolean> | Authentication status (derived from session) | | loadingState | Readable<AuthLoadingState> | Current loading state | | error | Readable<AuthError \| null> | Last error |

AuthLoadingState

| State | Description | |-------|-------------| | 'idle' | Completely stable (also after errors) | | 'initializing' | Initial session check | | 'authenticating' | Login/signup in progress | | 'refreshing' | Session refresh in progress | | 'signing_out' | Sign out in progress |

Important: After any operation completes (success or error), loadingState returns to 'idle'. Use error !== null to detect error conditions.

Events

// Subscribe to events
const unsubscribe = auth.on('auth:login', ({ session, user, method }) => {
  console.log('Logged in:', user.email, 'via', method);
});

auth.on('auth:logout', ({ redirectUri }) => {
  console.log('Logged out');
});

auth.on('auth:error', ({ error }) => {
  console.error('Auth error:', error.message);
});

auth.on('session:changed', ({ session, user }) => {
  console.log('Session changed');
});

auth.on('session:expired', ({ reason }) => {
  console.log('Session expired:', reason);
});

// Unsubscribe
unsubscribe();

Cleanup

// When not using AuthProvider, manually cleanup resources
auth.destroy();

Components

AuthProvider

Provides auth context to child components.

<script lang="ts">
  import { AuthProvider } from '@authrim/sveltekit/components';
  import { auth } from '$lib/auth';

  export let data;
</script>

<AuthProvider
  {auth}
  initialSession={data.auth?.session}
  initialUser={data.auth?.user}
>
  <slot />
</AuthProvider>

Props:

  • auth (required): Authrim client instance
  • initialSession: Session from SSR
  • initialUser: User from SSR

SignInButton

<script lang="ts">
  import { SignInButton } from '@authrim/sveltekit/components';
</script>

<!-- Passkey login -->
<SignInButton
  method="passkey"
  on:success={({ detail }) => console.log(detail.user)}
  on:error={({ detail }) => console.error(detail.message)}
>
  Sign In with Passkey
</SignInButton>

<!-- Social login -->
<SignInButton method="social" provider="google">
  Sign In with Google
</SignInButton>

SignOutButton

<script lang="ts">
  import { SignOutButton } from '@authrim/sveltekit/components';
</script>

<SignOutButton
  redirectUri="/login"
  on:success={() => console.log('Signed out')}
  on:error={({ detail }) => console.error(detail)}
>
  Sign Out
</SignOutButton>

UserProfile

<script lang="ts">
  import { UserProfile } from '@authrim/sveltekit/components';
</script>

<UserProfile showAvatar showEmail>
  <svelte:fragment slot="avatar" let:user>
    <img src={user.picture} alt={user.name} />
  </svelte:fragment>
</UserProfile>

ProtectedRoute

<script lang="ts">
  import { ProtectedRoute } from '@authrim/sveltekit/components';
</script>

<ProtectedRoute redirectTo="/login" includeReturnPath>
  <Dashboard />

  <svelte:fragment slot="loading">
    <Spinner />
  </svelte:fragment>

  <svelte:fragment slot="unauthenticated">
    <p>Please sign in to continue.</p>
  </svelte:fragment>
</ProtectedRoute>

Server-Side Integration

Handle Hook

// src/hooks.server.ts
import { createAuthHandle } from '@authrim/sveltekit/server';
import { AUTHRIM_SESSION_SECRET } from '$env/static/private';

export const handle = createAuthHandle({
  sessionSecret: AUTHRIM_SESSION_SECRET,
  cookieName: 'authrim_session',
  secure: true,
  sameSite: 'lax',
});

Protected Routes (Server)

// src/routes/dashboard/+page.server.ts
import { requireAuth } from '@authrim/sveltekit/server';

export const load = requireAuth({
  loginUrl: '/login',
  redirectParam: 'redirectTo',
});

Layout Data

// src/routes/+layout.server.ts
import { createAuthLoad } from '@authrim/sveltekit/server';

export const load = createAuthLoad();

Helper Functions

import {
  isAuthenticated,
  getUser,
  getSession,
  getAuthFromEvent
} from '@authrim/sveltekit/server';

// In +page.server.ts or hooks
export const load = async ({ locals }) => {
  if (isAuthenticated(locals)) {
    const user = getUser(locals);
    const session = getSession(locals);
    // ...
  }
};

// In handle hook
const authContext = getAuthFromEvent(event);

Package Exports

// Main client
import { createAuthrim, getAuthContext, setAuthContext } from '@authrim/sveltekit';

// Server utilities
import {
  createAuthHandle,
  requireAuth,
  createAuthLoad,
  isAuthenticated,
  getUser,
  getSession
} from '@authrim/sveltekit/server';

// Components
import {
  AuthProvider,
  SignInButton,
  SignOutButton,
  UserProfile,
  ProtectedRoute
} from '@authrim/sveltekit/components';

// Stores (for advanced use)
import { createAuthStores } from '@authrim/sveltekit/stores';

Design Principles

  1. Stores are observation-only: All stores are Readable, not Writable. This ensures that the event system is the single source of truth.

  2. Events are source of truth: Store updates are projections of events. This makes the data flow predictable and debuggable.

  3. Components are thin wrappers: UI components delegate behavior to props/events. They don't implement business logic.

  4. SSR-first: Full server-side rendering support with proper hydration handling.

  5. Type safety: Complete TypeScript support with strict typing.

Security Considerations

  • PKCE: All OAuth flows use PKCE (Proof Key for Code Exchange)
  • Secure Storage: Session tokens are stored securely with configurable storage options
  • CSRF Protection: State parameter validation for OAuth flows
  • HttpOnly Cookies: Server-side session cookies are HttpOnly and encrypted by default

License

Apache-2.0

Links