Skip to content

Commit

Permalink
Merge branch 'main' into ndom91/throw-missing-secret
Browse files Browse the repository at this point in the history
  • Loading branch information
ThangHuuVu committed Mar 25, 2024
2 parents bf63cd4 + 5ea8b7b commit 24c5ea3
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 58 deletions.
8 changes: 8 additions & 0 deletions docs/docs/reference/warnings.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,11 @@ The `debug` option was evaluated to `true`. It adds extra logs in the terminal w
## CSRF disabled

You were trying to get a CSRF response from Auth.js (eg.: by calling a `/csrf` endpoint), but in this setup, CSRF protection via Auth.js was turned off. This is likely if you are not directly using `@auth/core` but a framework library (like `@auth/sveltekit`) that already has CSRF protection built-in. You likely won't need the CSRF response.

## Env URL and basePath redundant

`AUTH_URL` (or `NEXTAUTH_URL`) and `authConfig.basePath` are both declared. This is a configuration mistake - you should either remove the `authConfig.basePath` configuration, or remove the `pathname` of `AUTH_URL` (or `NEXTAUTH_URL`). Only one of them is needed.

## Env URL basePath mismatch

`AUTH_URL` (or `NEXTAUTH_URL`) and `authConfig.basePath` are both declared, but they don't match. This is a configuration mistake. `@auth/core` will use `basePath` to construct the full URL to the corresponding action (/signin, /signout, etc.) in this case.
2 changes: 1 addition & 1 deletion packages/core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -439,7 +439,7 @@ export interface AuthConfig {
/**
* The base path of the Auth.js API endpoints.
*
* @default "/auth"
* @default "/api/auth" in "next-auth"; "/auth" with all other frameworks
*/
basePath?: string
}
40 changes: 13 additions & 27 deletions packages/frameworks-sveltekit/src/lib/actions.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
import { redirect } from "@sveltejs/kit"
import type { RequestEvent } from "@sveltejs/kit"
import { parse } from "set-cookie-parser"
import { dev } from "$app/environment"
import { env } from "$env/dynamic/private"

import { Auth, raw, skipCSRFCheck } from "@auth/core"
import type { AuthAction } from "@auth/core/types"
import { Auth, createActionURL, raw, skipCSRFCheck } from "@auth/core"
import type { SvelteKitAuthConfig } from "./types"
import { setEnvDefaults } from "./env"

Expand All @@ -17,7 +15,7 @@ export async function signIn(
config: SvelteKitAuthConfig,
event: RequestEvent
) {
const { request } = event
const { request, url: { protocol } } = event
const headers = new Headers(request.headers)
const {
redirect: shouldRedirect = true,
Expand All @@ -26,7 +24,13 @@ export async function signIn(
} = options instanceof FormData ? Object.fromEntries(options) : options

const callbackUrl = redirectTo?.toString() ?? headers.get("Referer") ?? "/"
const base = createActionURL("signin", headers, config.basePath)
const base = createActionURL(
"signin",
protocol,
headers,
env,
config.basePath
)

if (!provider) {
const url = `${base}?${new URLSearchParams({ callbackUrl })}`
Expand Down Expand Up @@ -78,11 +82,11 @@ export async function signOut(
config: SvelteKitAuthConfig,
event: RequestEvent
) {
const { request } = event
const { request, url: { protocol } } = event
const headers = new Headers(request.headers)
headers.set("Content-Type", "application/x-www-form-urlencoded")

const url = createActionURL("signout", headers, config.basePath)
const url = createActionURL("signout", protocol, headers, env, config.basePath)
const callbackUrl = options?.redirectTo ?? headers.get("Referer") ?? "/"
const body = new URLSearchParams({ callbackUrl })
const req = new Request(url, { method: "POST", headers, body })
Expand All @@ -105,9 +109,9 @@ export async function auth(
setEnvDefaults(env, config)
config.trustHost ??= true

const { request: req } = event
const { request: req, url: { protocol } } = event

const sessionUrl = createActionURL("session", req.headers, config.basePath)
const sessionUrl = createActionURL("session", protocol, req.headers, env, config.basePath)
const request = new Request(sessionUrl, {
headers: { cookie: req.headers.get("cookie") ?? "" },
})
Expand All @@ -127,21 +131,3 @@ export async function auth(
if (status === 200) return data
throw new Error(data.message)
}

/**
* Extract the origin and base path from either `AUTH_URL` or `NEXTAUTH_URL` environment variables,
* or the request's headers and the {@link NextAuthConfig.basePath} option.
*/
export function createActionURL(
action: AuthAction,
headers: Headers,
basePath?: string
) {
let url = env.AUTH_URL
if (!url) {
const host = headers.get("x-forwarded-host") ?? headers.get("host")
const proto = headers.get("x-forwarded-proto")
url = `${proto === "http" || dev ? "http" : "https"}://${host}${basePath}`
}
return new URL(`${url.replace(/\/$/, "")}/${action}`)
}
52 changes: 25 additions & 27 deletions packages/next-auth/src/lib/actions.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Auth, raw, skipCSRFCheck } from "@auth/core"
import { Auth, raw, skipCSRFCheck, createActionURL } from "@auth/core"
import { headers as nextHeaders, cookies } from "next/headers"
import { redirect } from "next/navigation"

Expand All @@ -23,7 +23,14 @@ export async function signIn(
} = options instanceof FormData ? Object.fromEntries(options) : options

const callbackUrl = redirectTo?.toString() ?? headers.get("Referer") ?? "/"
const signInURL = createActionURL("signin", headers, config.basePath)
const signInURL = createActionURL(
"signin",
// @ts-expect-error `x-forwarded-proto` is not nullable, next.js sets it by default
headers.get("x-forwarded-proto"),
headers,
process.env,
config.basePath
)

if (!provider) {
signInURL.searchParams.append("callbackUrl", callbackUrl)
Expand Down Expand Up @@ -78,7 +85,14 @@ export async function signOut(
const headers = new Headers(nextHeaders())
headers.set("Content-Type", "application/x-www-form-urlencoded")

const url = createActionURL("signout", headers, config.basePath)
const url = createActionURL(
"signout",
// @ts-expect-error `x-forwarded-proto` is not nullable, next.js sets it by default
headers.get("x-forwarded-proto"),
headers,
process.env,
config.basePath
)
const callbackUrl = options?.redirectTo ?? headers.get("Referer") ?? "/"
const body = new URLSearchParams({ callbackUrl })
const req = new Request(url, { method: "POST", headers, body })
Expand All @@ -100,7 +114,14 @@ export async function update(
const headers = new Headers(nextHeaders())
headers.set("Content-Type", "application/json")

const url = createActionURL("session", headers, config.basePath)
const url = createActionURL(
"session",
// @ts-expect-error `x-forwarded-proto` is not nullable, next.js sets it by default
headers.get("x-forwarded-proto"),
headers,
process.env,
config.basePath
)
const body = JSON.stringify({ data })
const req = new Request(url, { method: "POST", headers, body })

Expand All @@ -110,26 +131,3 @@ export async function update(

return res.body
}

/**
* Extract the origin and base path from either `AUTH_URL` or `NEXTAUTH_URL` environment variables,
* or the request's headers and the {@link NextAuthConfig.basePath} option.
*/
export function createActionURL(
action: AuthAction,
h: Headers | ReturnType<typeof headers>,
basePath?: string
): URL {
const envUrl = process.env.AUTH_URL ?? process.env.NEXTAUTH_URL
if (envUrl) {
const { origin, pathname } = new URL(envUrl)
const separator = pathname.endsWith("/") ? "" : "/"
return new URL(`${origin}${pathname}${separator}${action}`)
}
const host = h.get("x-forwarded-host") ?? h.get("host")
const protocol = h.get("x-forwarded-proto") === "http" ? "http" : "https"
// @ts-expect-error `basePath` value is default'ed to "/api/auth" in `setEnvDefaults`
const { origin, pathname } = new URL(basePath, `${protocol}://${host}`)
const separator = pathname.endsWith("/") ? "" : "/"
return new URL(`${origin}${pathname}${separator}${action}`)
}
12 changes: 9 additions & 3 deletions packages/next-auth/src/lib/index.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import { Auth, type AuthConfig } from "@auth/core"
import { Auth, createActionURL, type AuthConfig } from "@auth/core"
import { headers } from "next/headers"
import { NextResponse } from "next/server"
import { reqWithEnvURL } from "./env.js"
import { createActionURL } from "./actions.js"

import type { AuthAction, Awaitable, Session } from "@auth/core/types"
import type {
Expand Down Expand Up @@ -60,7 +59,14 @@ export interface NextAuthConfig extends Omit<AuthConfig, "raw"> {
}

async function getSession(headers: Headers, config: NextAuthConfig) {
const url = createActionURL("session", headers, config.basePath)
const url = createActionURL(
"session",
// @ts-expect-error `x-forwarded-proto` is not nullable, next.js sets it by default
headers.get("x-forwarded-proto"),
headers,
process.env,
config.basePath
)
const request = new Request(url, {
headers: { cookie: headers.get("cookie") ?? "" },
})
Expand Down

0 comments on commit 24c5ea3

Please sign in to comment.