Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(sveltekit): Refresh session cookie expiry & introduce auth method #9694

Merged
merged 6 commits into from
Jan 20, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions apps/dev/sveltekit/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,12 @@
},
"devDependencies": {
"@sveltejs/adapter-auto": "next",
"@sveltejs/kit": "next",
"svelte": "3.55.0",
"@sveltejs/kit": "2.4.1",
"@sveltejs/vite-plugin-svelte": "^3.0.0",
"svelte": "^4",
"svelte-check": "2.10.2",
"typescript": "5.2.2",
"vite": "4.0.5"
"vite": "^5"
},
"dependencies": {
"@auth/sveltekit": "workspace:*"
Expand Down
2 changes: 1 addition & 1 deletion apps/dev/sveltekit/src/routes/+layout.server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@ import type { LayoutServerLoad } from "./$types"

export const load: LayoutServerLoad = async (event) => {
return {
session: await event.locals.getSession(),
session: await event.locals.auth(),
}
}
2 changes: 1 addition & 1 deletion apps/dev/sveltekit/svelte.config.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import adapter from "@sveltejs/adapter-auto"
import { vitePreprocess } from "@sveltejs/kit/vite"
import { vitePreprocess } from "@sveltejs/vite-plugin-svelte"

/** @type {import('@sveltejs/kit').Config} */
const config = {
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/lib/utils/web.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ export function randomString(size: number) {
return Array.from(bytes).reduce(r, "")
}

function isAction(action: string): action is AuthAction {
export function isAction(action: string): action is AuthAction {
ThangHuuVu marked this conversation as resolved.
Show resolved Hide resolved
return actions.includes(action as AuthAction)
}

Expand Down
11 changes: 7 additions & 4 deletions packages/frameworks-sveltekit/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,25 +38,28 @@
"@sveltejs/kit": "^2.0.0",
"@sveltejs/package": "^1.0.0",
"@sveltejs/vite-plugin-svelte": "^3.0.0",
"@types/set-cookie-parser": "^2.4.7",
"svelte": "^4.0.0",
"svelte-check": "^3.4.3",
"tslib": "^2.4.1",
"vite": "^5.0.0",
"vitest": "^1.0.0"
},
"dependencies": {
"@auth/core": "workspace:*"
"@auth/core": "workspace:*",
"set-cookie-parser": "^2.6.0"
},
"peerDependencies": {
"svelte": "^3.54.0 || ^4.0.0",
"@sveltejs/kit": "^1.0.0 || ^2.0.0"
"@sveltejs/kit": "^1.0.0 || ^2.0.0",
"svelte": "^3.54.0 || ^4.0.0"
ThangHuuVu marked this conversation as resolved.
Show resolved Hide resolved
ThangHuuVu marked this conversation as resolved.
Show resolved Hide resolved
},
"type": "module",
"types": "./index.d.ts",
"files": [
"client.*",
"index.*",
"providers",
"vendored",
ThangHuuVu marked this conversation as resolved.
Show resolved Hide resolved
"src"
],
"exports": {
Expand All @@ -77,4 +80,4 @@
},
"./package.json": "./package.json"
}
}
}
61 changes: 39 additions & 22 deletions packages/frameworks-sveltekit/src/lib/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
*
* When deploying your app outside Vercel, set the `AUTH_TRUST_HOST` variable to `true` for other hosting providers like Cloudflare Pages or Netlify.
*
* The callback URL used by the [providers](https://authjs.dev/getting-started/providers) must be set to the following, unless you override {@link SvelteKitAuthConfig.prefix}:
* The callback URL used by the [providers](https://authjs.dev/getting-started/providers) must be set to the following, unless you override {@link SvelteKitAuthConfig.basePath}:
* ```
* [origin]/auth/callback/[provider]
* ```
Expand Down Expand Up @@ -199,7 +199,7 @@

/// <reference types="@sveltejs/kit" />
import type { Handle, RequestEvent } from "@sveltejs/kit"

import { parse } from "set-cookie-parser"
import { dev, building } from "$app/environment"
import { base } from "$app/paths"
import { env } from "$env/dynamic/private"
Expand All @@ -215,18 +215,27 @@ export type {
User,
} from "@auth/core/types"

export async function getSession(
req: Request,
async function auth(
event: RequestEvent,
config: SvelteKitAuthConfig
): ReturnType<App.Locals["getSession"]> {
): ReturnType<App.Locals["auth"]> {
setEnvDefaults(env, config)
config.trustHost ??= true

const prefix = config.prefix ?? `${base}/auth`
const url = new URL(prefix + "/session", req.url)
const { request: req } = event

const basePath = config.basePath ?? `${base}/auth`
const url = new URL(basePath + "/session", req.url)
const request = new Request(url, { headers: req.headers })
ThangHuuVu marked this conversation as resolved.
Show resolved Hide resolved
const response = await Auth(request, config)

const authCookies = parse(response.headers.getSetCookie())
for (const cookie of authCookies) {
const { name, value, ...options } = cookie
// @ts-expect-error - Review: SvelteKit and set-cookie-parser are mismatching
event.cookies.set(name, value, { path: "/", ...options })
}

const { status = 200 } = response
const data = await response.json()

Expand All @@ -236,16 +245,7 @@ export async function getSession(
}

/** Configure the {@link SvelteKitAuth} method. */
export interface SvelteKitAuthConfig extends Omit<AuthConfig, "raw"> {
/**
* Defines the base path for the auth routes.
* If you change the default value,
* you must also update the callback URL used by the [providers](https://authjs.dev/reference/core/providers).
*
* @default `${base}/auth` - `base` is the base path of your SvelteKit app, configured in `svelte.config.js`.
*/
prefix?: string
}
export interface SvelteKitAuthConfig extends Omit<AuthConfig, "raw"> {}

const actions: AuthAction[] = [
"providers",
Expand All @@ -270,28 +270,38 @@ export function SvelteKitAuth(
return async function ({ event, resolve }) {
const _config = typeof config === "object" ? config : await config(event)
setEnvDefaults(env, _config)
const { prefix = `${base}/auth` } = _config
_config.basePath ??= `${base}/auth`
ThangHuuVu marked this conversation as resolved.
Show resolved Hide resolved

const { url, request } = event

event.locals.getSession ??= () => getSession(request, _config)
event.locals.auth ??= () => auth(event, _config)
event.locals.getSession ??= event.locals.auth

const action = url.pathname
.slice(prefix.length + 1)
.slice(_config.basePath.length + 1)
.split("/")[0] as AuthAction
ThangHuuVu marked this conversation as resolved.
Show resolved Hide resolved

if (!actions.includes(action) || !url.pathname.startsWith(prefix + "/")) {
if (!isAction(action) || !url.pathname.startsWith(_config.basePath + "/")) {
return resolve(event)
}

return Auth(request, _config)
ThangHuuVu marked this conversation as resolved.
Show resolved Hide resolved
}
}

// TODO: Get this function from @auth/core/util
function isAction(action: string): action is AuthAction {
return actions.includes(action as AuthAction)
}

declare global {
// eslint-disable-next-line @typescript-eslint/no-namespace
namespace App {
interface Locals {
auth(): Promise<Session | null>
/**
* @deprecated Use `auth` instead.
*/
ThangHuuVu marked this conversation as resolved.
Show resolved Hide resolved
getSession(): Promise<Session | null>
}
interface PageData {
Expand All @@ -309,11 +319,18 @@ declare module "$env/dynamic/private" {
export function setEnvDefaults(envObject: any, config: SvelteKitAuthConfig) {
if (building) return

try {
const url = env.AUTH_URL ?? base
if (url) config.basePath = new URL(url).pathname
} catch {
ThangHuuVu marked this conversation as resolved.
Show resolved Hide resolved
} finally {
config.basePath ??= "/auth"
}

config.redirectProxyUrl ??= env.AUTH_REDIRECT_PROXY_URL
config.secret ??= env.AUTH_SECRET
config.trustHost ??= !!(
env.AUTH_URL ??
env.NEXTAUTH_URL ??
env.AUTH_TRUST_HOST ??
env.VERCEL ??
env.NODE_ENV !== "production" ??
Expand Down
Loading
Loading