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

sveltekit-auth-example

v5.8.5

Published

SvelteKit Authentication Example

Readme

SvelteKit Authentication and Authorization Example

License Node Svelte

A complete, production-ready authentication and authorization starter for Svelte 5 and SvelteKit 2. Skip the boilerplate — get secure local accounts, Google OAuth, MFA, email verification, role-based access control, OWASP-compliant password hashing, and bot protection out of the box.

Features

| | | | ------------------------------------------------ | --------------------------------------- | | ✅ Local accounts (email + password) | ✅ Sign in with Google / Google One Tap | | ✅ Multi-factor authentication (MFA via email) | ✅ Email verification | | ✅ Forgot password / email reset (Brevo) | ✅ User profile management | | ✅ Session management + timeout | ✅ Rate limiting | | ✅ Role-based access control | ✅ Password complexity enforcement | | ✅ Content Security Policy (CSP) | ✅ OWASP-compliant password hashing | | ✅ Cloudflare Turnstile CAPTCHA (bot protection) | |

Stack

Requirements

Setting up the project

  1. Get the project and set up the database
# Clone the repo to your current directory
git clone https://github.com/nstuyvesant/sveltekit-auth-example.git

# Install the dependencies
cd sveltekit-auth-example
yarn install

# Create PostgreSQL database (only works if you have PostgreSQL installed)
bash db_create.sh
  1. Create a Google API client ID per these instructions. Make sure you include http://localhost:3000 and http://localhost in the Authorized JavaScript origins, and http://localhost:3000/auth/google/callback in the Authorized redirect URIs for your Client ID for Web application. Do not access the site using http://127.0.0.1:3000 — use http://localhost:3000 or it will not work.

  2. Create a free Brevo account and generate an API Key under SMTP & API settings. Set EMAIL to the sender address verified in your Brevo account.

  3. Create a .env file at the top level of the project with the following values (substituting your own id and PostgreSQL username and password):

DATABASE_URL=postgres://user:password@localhost:5432/auth
DATABASE_SSL=false
DOMAIN=http://localhost:3000
JWT_SECRET=replace_with_your_own
BREVO_KEY=replace_with_your_own
EMAIL=replace_with_your_own
PUBLIC_GOOGLE_CLIENT_ID=replace_with_your_own
PUBLIC_TURNSTILE_SITE_KEY=replace_with_your_own
TURNSTILE_SECRET_KEY=replace_with_your_own

Run locally

# Start the dev server and open the app in a new browser tab
yarn dev -- --open

Build and preview

# Build for production
yarn build

# Preview the production build
yarn preview

Valid logins

The db_create.sql script adds three users to the database with obvious roles:

| Email | Password | Role | | ------------------- | ------------ | ------- | | [email protected] | Admin1234! | admin | | [email protected] | Teacher1234! | teacher | | [email protected] | Student1234! | student |

MFA note: Local account logins require a 6-digit code sent to the user's email address. To successfully log in with the seed accounts above, either update their email addresses in the database to your own (UPDATE users SET email = '[email protected]' WHERE email = '[email protected]';), or retrieve the code directly from the mfa_codes table after submitting the login form (SELECT code FROM mfa_codes;).

How it works

The website supports two types of authentication:

  1. Local accounts via username (email) and password
    • The login form (/src/routes/login/+page.svelte) sends the login info as JSON to endpoint /auth/login
    • The endpoint passes the JSON to PostgreSQL function authenticate(json) which hashes the password and compares it to the stored hashed password in the users table. The function returns JSON containing a session ID (v4 UUID) and user object (sans password).
    • The endpoint sends this session ID as an httpOnly SameSite cookie and the user object in the body of the response.
    • The client stores the user object in appState (see /src/lib/app-state.svelte.ts).
    • Further requests to the server include the session cookie. The hooks.ts handle() method extracts the session cookie, looks up the user and attaches it to RequestEvent.locals so server-side code can check locals.user.role to see if the request is authorized and return an HTTP 401 status if not.
  2. Sign in with Google
    • Sign in with Google is initialized in /src/routes/+layout.svelte.
    • Google One Tap prompt is displayed on the initially loaded page unless Intelligent Tracking Prevention is enabled in the browser.
    • Sign in with Google button is on the login page (/src/routes/login/+page.svelte) and register page (/src/routes/register/+page.svelte).
    • Clicking either button opens a new window asking the user to authorize this website. If the user OKs it, a JSON Web Token (JWT) is sent to a callback function.
    • The callback function (in /src/lib/google.ts) sends the JWT to an endpoint on this server /auth/google.
    • The endpoint decodes and validates the user information then calls the PostgreSQL function start_gmail_user_session to upsert the user to the database returning a session id in an httpOnly SameSite cookie and user in the body of the response.
    • The client stores the user object in appState (see /src/lib/app-state.svelte.ts).
    • Further requests to the server work identically to local accounts above.

There is some overhead to checking the user session in a database each time versus using a JWT; however, validating each request avoids problems discussed in this article. For a high-volume website, I would use Redis or the equivalent.

The forgot password / password reset functionality uses a JWT and Brevo to send the email. You would need to have a Brevo account and set the BREVO_KEY and EMAIL environment variables (see setup instructions above). Email sending is in src/lib/server/brevo.ts and the email templates are in src/lib/server/email/. This code could easily be replaced by nodemailer or something similar.