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 all commits
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
10 changes: 6 additions & 4 deletions packages/frameworks-sveltekit/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,18 +38,20 @@
"@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 || ^5"

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@balazsorban44

Currently trying out the new Svelte 5 alongside with @auth/sveltekit.
I am currently using "svelte": "^5.0.0-next.69" but it's complaining about peerDependency still.

npm ERR! Could not resolve dependency:
npm ERR! peer svelte@"^3.54.0 || ^4.0.0 || ^5" from @auth/sveltekit@0.13.0

^5.0.0-next.69 should be working if ^5 is specfied right?

},
"type": "module",
"types": "./index.d.ts",
Expand Down Expand Up @@ -77,4 +79,4 @@
},
"./package.json": "./package.json"
}
}
}
72 changes: 45 additions & 27 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,29 @@ 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 = new Request(url, { headers: req.headers })
const { request: req } = event

const basePath = config.basePath ?? `${base}/auth`
const url = new URL(basePath + "/session", req.url)
const request = new Request(url, {
headers: { cookie: req.headers.get("cookie") ?? "" },
})
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 +247,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 +272,37 @@ 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

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)
.split("/")[0] as AuthAction
.slice(
// @ts-expect-error - basePath is defined in setEnvDefaults
_config.basePath.length + 1
)
.split("/")[0]

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

return Auth(request, _config)
return resolve(event)
}
}

// 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. */
getSession(): Promise<Session | null>
}
interface PageData {
Expand All @@ -309,11 +320,18 @@ declare module "$env/dynamic/private" {
export function setEnvDefaults(envObject: any, config: SvelteKitAuthConfig) {
if (building) return

try {
const url = env.AUTH_URL
if (url) config.basePath = new URL(url).pathname
} catch {
} finally {
config.basePath ??= `${base}/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