
Security News
Attackers Are Hunting High-Impact Node.js Maintainers in a Coordinated Social Engineering Campaign
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.
Authentication for SvelteKit
Developed by Stephen Shkeda
stephenshkeda@gmail.com
svauth is a complete open source authentication solution for SvelteKit applications.
Designed from the ground up to support SvelteKit and serverless.
Heavily inspired by NextAuth.js.
Written for Svelte Hack 2023.
This is a monorepo containing the following packages / projects:
svauth packagenpm install svauth
yarn add svauth
pnpm add svauth
// hooks.server.ts
import Svauth from 'svauth';
import { Google } from 'svauth/providers';
import { GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET } from '$env/static/private';
export const handle = Svauth({
providers: [
Google({
clientId: GOOGLE_CLIENT_ID,
clientSecret: GOOGLE_CLIENT_SECRET
})
]
});
// routes/+page.server.ts
import type { PageServerLoad } from './$types';
export const load = (async (event) => {
return {
session: await event.locals.getSession()
};
}) satisfies PageServerLoad;
<script lang="ts">
// routes/+page.svelte
import { session, signIn, signOut } from 'svauth/client';
</script>
{#if $session}
<button on:click={() => signOut()}> Sign out </button>
<p>Logged in as {$session.user.email}</p>
{:else}
<button on:click={() => signIn('google')}> Sign in with Google </button>
<p>Not signed in</p>
{/if}
Please contact me directly, stephenshkeda@gmail.com, to report serious issues that might impact the security of sites using svauth.
| Name | Description |
|---|---|
| SVAUTH_SECRET | The secret used to encrypt the session. |
| SVAUTH_URL | The URL of the application. |
| PUBLIC_SVAUTH_PREFIX | The prefix used for the svauth routes. |
For production environments, if SVAUTH_URL is not set, VERCEL_URL will be used. For development environments, SVAUTH_URL defaults to localhost:5173.
PUBLIC_SVAUTH_PREFIX is optional and defaults to /auth.
The Svauth function is used to create the Svauth handler.
| Name | Type | Description |
|---|---|---|
options | SvauthOptions | The options object. |
| Name | Type | Default | Description |
|---|---|---|---|
providers | Provider[] | An array of providers. | |
adapter | Adapter | The adapter to link svauth with a database. | |
expires | number | string | 30d | The expiration time of the session. When number is passed that is used as a value in seconds, when string is passed it is resolved to a time span and added to the current timestamp. |
// hooks.server.ts
import Svauth from 'svauth';
export const handle = Svauth({
providers: [
Google({
clientId: GOOGLE_CLIENT_ID,
clientSecret: GOOGLE_CLIENT_SECRET
})
],
expires: '14d'
});
The event.locals object contains the following properties:
| Name | Type | Description |
|---|---|---|
getSession() | async | Returns the current session. |
// routes/+page.server.ts
import type { PageServerLoad } from './$types';
export const load = (async (event) => {
return {
session: await event.locals.getSession()
};
}) satisfies PageServerLoad;
The session store is the easiest way to obtain information on current session.
session returns 4 possible values:
Note: If you are obtaining the session during load, session will not return false.
<script lang="ts">
import { session } from 'svauth/client';
</script>
{#if $session}
<p>Logged in as {$session.user.email}</p>
{:else}
<p>Not signed in</p>
{/if}
The Session object is returned by the session store.
| Name | Type | Description |
|---|---|---|
User | User | The user object. |
expires | Date | The expiration time of the session. |
issuedAt | Date | The time the session was issued. |
The User object is found inside the Session object.
| Name | Type | Description |
|---|---|---|
id | string | The user's ID. |
email | string | The user's email. |
name | string | The user's name. |
image | string | A link to the user's image |
The signIn function is used to sign in a user.
| Name | Type | Default | Description |
|---|---|---|---|
provider | string | The provider to sign in with. | |
redirect | string | Current user's location | The URL to redirect the user to after signing out. |
<script lang="ts">
import { signIn } from 'svauth/client';
</script>
<button on:click={() => signIn('google')}> Sign in with Google </button>
The signOut function is used to sign out a user.
| Name | Type | Default | Description |
|---|---|---|---|
redirect | string | Current user's location | The URL to redirect the user to after signing out. |
<script lang="ts">
import { signOut } from 'svauth/client';
</script>
<button on:click={() => signOut()}> Sign out </button>
Currently, svauth has support for three OAuth providers:
In the future, I plan to add support for more providers.
https://developers.google.com/identity/protocols/oauth2 https://developers.google.com/identity/openid-connect/openid-connect
https://console.developers.google.com/apis/credentials
The "Authorized redirect URIs" used when creating the credentials must include your full domain and end in the callback path.
For example:
// hooks.server.ts
import Svauth from 'svauth';
import { Google } from 'svauth/providers';
import { GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET } from '$env/static/private';
export const handle = Svauth({
providers: [
Google({
clientId: GOOGLE_CLIENT_ID,
clientSecret: GOOGLE_CLIENT_SECRET
})
]
});
https://discord.com/developers/docs/topics/oauth2
https://discord.com/developers/applications
The "Redirects" used when creating the credentials must include your full domain and end in the callback path.
For example:
// hooks.server.ts
import Svauth from 'svauth';
import { Discord } from 'svauth/providers';
import { DISCORD_CLIENT_ID, DISCORD_CLIENT_SECRET } from '$env/static/private';
export const handle = Svauth({
providers: [
Discord({
clientId: DISCORD_CLIENT_ID,
clientSecret: DISCORD_CLIENT_SECRET
})
]
});
https://docs.github.com/en/developers/apps/building-oauth-apps/authorizing-oauth-apps
https://github.com/settings/developers
The "Authorization callback URL" used when creating the credentials must include your full domain and end in the callback path.
For example:
// hooks.server.ts
import Svauth from 'svauth';
import { GitHub } from 'svauth/providers';
import { GITHUB_CLIENT_ID, GITHUB_CLIENT_SECRET } from '$env/static/private';
export const handle = Svauth({
providers: [
GitHub({
clientId: GITHUB_CLIENT_ID,
clientSecret: GITHUB_CLIENT_SECRET
})
]
});
// routes/hooks.server.ts
import Svauth from 'svauth';
import { Google } from 'svauth/providers';
import { Prisma } from 'svauth/adapters';
import prisma from './server/prisma';
import { GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET } from '$env/static/private';
export const handle = Svauth({
providers: [
Google({
clientId: GOOGLE_CLIENT_ID,
clientSecret: GOOGLE_CLIENT_SECRET
})
],
adapter: Prisma(prisma)
});
// prisma/schema.prisma
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "mysql"
url = env("DATABASE_URL")
relationMode = "prisma"
}
model Account {
id String @id @default(cuid())
userId String
provider String
providerAccountId String
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
@@unique([provider, providerAccountId])
@@index([userId])
}
model Session {
id String @id @default(cuid())
userId String
issuedAt DateTime @default(now())
expires DateTime
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
@@index([userId])
}
model User {
id String @id @default(cuid())
name String
email String @unique
picture String
accounts Account[]
sessions Session[]
}
The SignInWithGoogleButton component is a simple button that will sign the user in with Google.
https://developers.google.com/identity/gsi/web/guides/overview
https://console.developers.google.com/apis/credentials
The "Authorized JavaScript origins" used when creating the credentials must include your HTTP origins.
For example:
| Name | Type | Default | Description |
|---|---|---|---|
oneTap | boolean | false | Whether to use Google One Tap sign in. |
type | standard | icon | standard | The button type.button. |
theme | outline | filled_blue | filled_black | outline | The button theme. |
size | large | medium | small | large | The button size. |
text | signin_with | signup_with | continue_with | signin | signin_with | The button text. |
shape | rectangular | pill | circle | square | rectangular | The button shape. |
logo_alignment | left | center | left | The Google logo alignment. |
width | number | The button width, in pixels. | |
locale | string | The button language. |
<script lang="ts">
// routes/+page.svelte
import { SignInWithGoogleButton } from 'svauth/components';
</script>
<SignInWithGoogleButton />
ISC
Portions of this page are reproduced from work created and shared by Google and used according to terms described in the Creative Commons 4.0 Attribution License.
FAQs
Authentication for SvelteKit
We found that svauth demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.

Security News
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.

Security News
Node.js has paused its bug bounty program after funding ended, removing payouts for vulnerability reports but keeping its security process unchanged.