OIDC authentication helpers for SvelteKit with:
- server-side login, callback, logout, and session refresh flows
- token endpoint auth support for
none,client_secret_basic,client_secret_post,client_secret_jwt, andprivate_key_jwt - back-channel logout support through a revocation store
- signed cookie-backed sessions and PKCE/state protection
- a
handlehook for attaching auth state toevent.locals - a small
OIDCContextprovider for client-side auth state and session lifecycle handling
npm install sveltekit-oidc// src/lib/server/auth.ts
import {
createInMemoryBackChannelLogoutStore,
createOIDC
} from 'sveltekit-oidc/server';
export const oidc = createOIDC({
issuer: 'https://your-idp.example.com',
clientId: process.env.OIDC_CLIENT_ID!,
clientSecret: process.env.OIDC_CLIENT_SECRET!,
cookieSecret: process.env.OIDC_COOKIE_SECRET!,
clientAuthMethod: 'client_secret_basic',
loginPath: '/auth/login',
redirectPath: '/auth/callback',
scope: ['openid', 'profile', 'email', 'offline_access'],
clockSkewSeconds: 30,
fetchUserInfo: true,
backChannelLogoutStore: createInMemoryBackChannelLogoutStore(),
transformSession(session) {
return {
...session,
groups: session.groups,
user: session.user
? {
...session.user,
groups: session.groups
}
: session.user
};
},
cookieOptions: {
secure: process.env.NODE_ENV === 'production'
}
});// src/hooks.server.ts
import { oidc } from '$lib/server/auth';
export const handle = oidc.handle;// src/routes/auth/login/+server.ts
import { oidc } from '$lib/server/auth';
export const GET = oidc.loginHandler();// src/routes/auth/callback/+server.ts
import { oidc } from '$lib/server/auth';
export const GET = oidc.callbackHandler({
redirectTo: '/'
});// src/routes/auth/logout/+server.ts
import { oidc } from '$lib/server/auth';
export const GET = oidc.logoutHandler();
export const POST = oidc.logoutHandler();// src/routes/auth/backchannel-logout/+server.ts
import { oidc } from '$lib/server/auth';
export const POST = oidc.backChannelLogoutHandler();If you prefer form actions instead of dedicated routes:
// src/routes/+page.server.ts
import { oidc } from '$lib/server/auth';
export const actions = oidc.createActions();// src/routes/+layout.server.ts
import { oidc } from '$lib/server/auth';
export async function load(event) {
return {
session: await oidc.getPublicSession(event),
sessionManagement: await oidc.getSessionManagementConfig()
};
}<script lang="ts">
import { OIDCContext } from 'sveltekit-oidc';
let { data } = $props();
</script>
<OIDCContext
session={data.session}
config={data.sessionManagement}
logoutPath="/auth/logout"
redirectIfUnauthenticated={false}
>
<Account />
</OIDCContext><!-- src/lib/Account.svelte -->
<script lang="ts">
import { useOIDC } from 'sveltekit-oidc';
const oidc = useOIDC();
</script>
{#if oidc.isAuthenticated}
<p>Signed in as {oidc.user?.email ?? oidc.user?.name ?? oidc.session?.sub}</p>
<form method="POST" action="/auth/logout">
<button type="submit">Sign out</button>
</form>
{:else}
<a href="/auth/login?returnTo=%2Faccount">Sign in</a>
{/if}OIDCContext handles:
- local expiry redirects
check_session_iframepolling when the provider advertises it- periodic
invalidateAll()revalidation so revoked server sessions are detected - a client context for nested auth-aware components through
useOIDC()/getOIDCContext()
This repository now includes a runnable example under src/routes and src/hooks.server.ts.
Set these environment variables to enable it:
OIDC_ISSUEROIDC_CLIENT_IDOIDC_COOKIE_SECRET- optional:
OIDC_CLIENT_SECRET - optional:
OIDC_SCOPE - optional:
OIDC_POST_LOGOUT_REDIRECT_URI
cookieSecretshould be a strong random secret and must stay stable across instances.clockSkewSecondsdefaults to30and tolerates small clock drift between your app and the identity provider.createInMemoryBackChannelLogoutStore()is suitable for local development or single-instance deployments. Use Redis, SQL, or another shared store for production.- The library validates
id_tokenandlogout_tokenvalues through@sourceregistry/node-jwtand provider JWKS metadata. groupsare normalized onto the session fromgroupsandrolesclaims when present.- Use
transformClaims,transformUser, andtransformSessionto project provider-specific claims into your own session shape. check_session_iframemonitoring only runs when the provider advertises that endpoint and the session includessession_state.- Refresh token handling is automatic when a valid refresh token is present.
event.locals.oidcis attached by the hook, but you should add your ownapp.d.tsaugmentation in the consuming app for full typing.