Integrating OAuth in Your SvelteKit App: Step-by-Step with AuthJS

Integrating OAuth in Your SvelteKit

Unlocking User Authentication in SvelteKit: OAuth Strategies with AuthJS


Install required npm packages

Install the required npm package first

terminal or console
npm install @auth/core @auth/sveltekit

Read detail documentation on the authjs website

Populate .env variables

Make sure to populate .env


Don't worry about sharing my github ID and SECRET, becasue these are just random number

Populate .env.local variables

Create another file named .env.local add the AUTH_SECRET environment variable

AUTH_SECRET="This is an example"

AUTH_SECRET is a random string used by the library to encrypt tokens and email verification hashes, and it's mandatory to keep things secure!

Use the command below or to generate a random value for it.

console command
openssl rand -base64 32

Create server hook

import { SvelteKitAuth } from "@auth/sveltekit";
import GitHub from "@auth/core/providers/github";
import { GITHUB_ID, GITHUB_SECRET } from "$env/static/private";

// console.log(GITHUB_ID, " + ", GITHUB_SECRET);
// console.log(SvelteKitAuth);

export const { handle } = SvelteKitAuth({
  providers: [GitHub({ clientId: GITHUB_ID, clientSecret: GITHUB_SECRET })],

Populate +layout.server.js

export const load = async (event) => {
  return {
    session: await event.locals.auth(),

Consuming the session via page store

We can use the $ variable from anywhere on your page

  import { signIn, signOut } from '@auth/sveltekit/client'
  import { page } from '$app/stores'

{#if $}
  <p>Signed in as {$}</p>
  <button on:click={signOut}>Sign out</button>
  <img src="" />
  <p>Not signed in.</p>
  <button on:click={() => signIn('github')}>Sign in</button>

Protecting API Routes

To protect API Routes (blocking unauthorized access to resources), we can use locals.auth() just like in the layouts file to know whether a session exists or not:

import { error } from "@sveltejs/kit";

// This is the `load` function expected in a `+page.server.js` file.
export async function load({ locals }) {
  // Your authentication and logic here
  const session = await locals.auth?.();
  if (!session || !session.user) {
    error(401, "You must sign in to view movies.");

  // Returning props for the page
  return {
    props: {
      movies: [
        { title: "Alien vs Predator", id: 1 },
        { title: "Reservoir Dogs", id: 2 },

The above way of protecting a route is repetitive, as we have to use the same code for every +page.server.js route

Non repeative way of incorporating OAuth

Here is the more composed way of achieving the same result using hooks.server.js

// src/hooks.server.js
import { sequence } from "@sveltejs/kit/hooks";
import { SvelteKitAuth } from "@auth/sveltekit";
import GitHub from "@auth/core/providers/github";
import { GITHUB_ID, GITHUB_SECRET } from "$env/static/private";

const svelteKitAuth = SvelteKitAuth({
  providers: [GitHub({ clientId: GITHUB_ID, clientSecret: GITHUB_SECRET })],

const customHandle = async ({ event, resolve }) => {
  // Skip auth for public routes.
  const publicRoutes = ["/", "/qcData"]; // Add your public routes here.
  if (!publicRoutes.includes(event.url.pathname)) {
    const session = await event.locals.auth?.();
    if (!session || !session.user) {
      // If not authenticated, throw an error or redirect the user.
      return new Response("You must sign in to view this page.", {
        status: 401,

  // If the route is public or the user is authenticated, continue with the request.
  return resolve(event);

export const handle = sequence(svelteKitAuth.handle, customHandle);