mirror of
https://github.com/SrIzan10/next-auth.git
synced 2026-05-01 10:55:20 +00:00
Compare commits
3 Commits
@auth/soli
...
feat/skip-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c9a47a5138 | ||
|
|
da81e98084 | ||
|
|
56f414f8d6 |
@@ -3,57 +3,13 @@ id: warnings
|
|||||||
title: Warnings
|
title: Warnings
|
||||||
---
|
---
|
||||||
|
|
||||||
This is a list of warning output from Auth.js.
|
A list of warnings from Auth.js that need your attention.
|
||||||
|
|
||||||
All warnings indicate things which you should take a look at, but do not inhibit normal operation.
|
|
||||||
|
|
||||||
---
|
## Debug enabled
|
||||||
|
|
||||||
## Client
|
The `debug` option was evaluated to `true`. It adds extra logs in the terminal which is useful in development, but since it can print sensitive information about users, make sure to set this to `false` in production. In Node.js environments, you can for example set `debug: process.env.NODE_ENV !== "production"`. Consult with your runtime/framework on how to set this value correctly.
|
||||||
|
|
||||||
#### NEXTAUTH_URL
|
## CSRF disabled
|
||||||
|
|
||||||
Environment variable `NEXTAUTH_URL` missing. Please set it in your `.env` file.
|
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.
|
||||||
|
|
||||||
:::note
|
|
||||||
On [Vercel](https://vercel.com) deployments, we will read the `VERCEL_URL` environment variable, so you won't need to define `NEXTAUTH_URL`.
|
|
||||||
:::
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Server
|
|
||||||
|
|
||||||
These warnings are displayed on the terminal.
|
|
||||||
|
|
||||||
#### NO_SECRET
|
|
||||||
|
|
||||||
In development, we generate a `secret` based on your configuration for convenience. This is volatile and will throw an error in production. [Read more](https://authjs.dev/reference/configuration/auth-config/#secret)
|
|
||||||
|
|
||||||
#### TWITTER_OAUTH_2_BETA
|
|
||||||
|
|
||||||
Twitter OAuth 2.0 is currently in beta as certain changes might still be necessary. This is not covered by semver. See the docs https://authjs.dev/reference/providers/twitter#oauth-2
|
|
||||||
|
|
||||||
#### EXPERIMENTAL_API
|
|
||||||
|
|
||||||
Some APIs are still experimental; they may be changed or removed in the future. Use at your own risk.
|
|
||||||
|
|
||||||
## Adapter
|
|
||||||
|
|
||||||
### ADAPTER_TYPEORM_UPDATING_ENTITIES
|
|
||||||
|
|
||||||
This warning occurs when typeorm finds that the provided entities differ from the database entities. By default while not in `production` the typeorm adapter will always synchronize changes made to the entities codefiles.
|
|
||||||
|
|
||||||
Disable this warning by setting `synchronize: false` in your typeorm config
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
```js title="/pages/api/auth/[...nextauth].js"
|
|
||||||
adapter: TypeORMLegacyAdapter({
|
|
||||||
type: 'mysql',
|
|
||||||
username: process.env.DATABASE_USERNAME,
|
|
||||||
password: process.env.DATABASE_PASSWORD,
|
|
||||||
host: process.env.DATABASE_HOST,
|
|
||||||
database: process.env.DATABASE_DB,
|
|
||||||
synchronize: false
|
|
||||||
}),
|
|
||||||
```
|
|
||||||
@@ -296,4 +296,16 @@ export interface AuthConfig {
|
|||||||
cookies?: Partial<CookiesOptions>
|
cookies?: Partial<CookiesOptions>
|
||||||
/** @todo */
|
/** @todo */
|
||||||
trustHost?: boolean
|
trustHost?: boolean
|
||||||
|
skipCSRFCheck?: typeof skipCSRFCheck
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* :::danger
|
||||||
|
* This option is inteded for framework authors.
|
||||||
|
* :::
|
||||||
|
*
|
||||||
|
* Auth.js comes with built-in {@link https://authjs.dev/concepts/security#csrf CSRF} protection, but
|
||||||
|
* if you are implementing a framework that is already protected against CSRF attacks, you can skip this check by
|
||||||
|
* passing this value to {@link AuthConfig.skipCSRFCheck}.
|
||||||
|
*/
|
||||||
|
export const skipCSRFCheck = Symbol("skip-csrf-check")
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ export function assertConfig(
|
|||||||
const { url } = request
|
const { url } = request
|
||||||
const warnings: WarningCode[] = []
|
const warnings: WarningCode[] = []
|
||||||
|
|
||||||
if (!warned && options.debug) warnings.push("debug_enabled")
|
if (!warned && options.debug) warnings.push("debug-enabled")
|
||||||
|
|
||||||
if (!options.trustHost) {
|
if (!options.trustHost) {
|
||||||
return new UntrustedHost(`Host must be trusted. URL was: ${request.url}`)
|
return new UntrustedHost(`Host must be trusted. URL was: ${request.url}`)
|
||||||
|
|||||||
@@ -1,14 +1,15 @@
|
|||||||
import { SessionStore } from "./cookie.js"
|
|
||||||
import { UnknownAction } from "../errors.js"
|
import { UnknownAction } from "../errors.js"
|
||||||
|
import { skipCSRFCheck } from "../index.js"
|
||||||
|
import { SessionStore } from "./cookie.js"
|
||||||
import { init } from "./init.js"
|
import { init } from "./init.js"
|
||||||
import renderPage from "./pages/index.js"
|
import renderPage from "./pages/index.js"
|
||||||
import * as routes from "./routes/index.js"
|
import * as routes from "./routes/index.js"
|
||||||
|
|
||||||
import type {
|
import type {
|
||||||
RequestInternal,
|
|
||||||
ResponseInternal,
|
|
||||||
AuthConfig,
|
AuthConfig,
|
||||||
ErrorPageParam,
|
ErrorPageParam,
|
||||||
|
RequestInternal,
|
||||||
|
ResponseInternal,
|
||||||
} from "../types.js"
|
} from "../types.js"
|
||||||
|
|
||||||
export async function AuthInternal<
|
export async function AuthInternal<
|
||||||
@@ -19,6 +20,8 @@ export async function AuthInternal<
|
|||||||
): Promise<ResponseInternal<Body>> {
|
): Promise<ResponseInternal<Body>> {
|
||||||
const { action, providerId, error, method } = request
|
const { action, providerId, error, method } = request
|
||||||
|
|
||||||
|
const csrfDisabled = authOptions.skipCSRFCheck === skipCSRFCheck
|
||||||
|
|
||||||
const { options, cookies } = await init({
|
const { options, cookies } = await init({
|
||||||
authOptions,
|
authOptions,
|
||||||
action,
|
action,
|
||||||
@@ -28,6 +31,7 @@ export async function AuthInternal<
|
|||||||
csrfToken: request.body?.csrfToken,
|
csrfToken: request.body?.csrfToken,
|
||||||
cookies: request.cookies,
|
cookies: request.cookies,
|
||||||
isPost: method === "POST",
|
isPost: method === "POST",
|
||||||
|
csrfDisabled,
|
||||||
})
|
})
|
||||||
|
|
||||||
const sessionStore = new SessionStore(
|
const sessionStore = new SessionStore(
|
||||||
@@ -48,12 +52,22 @@ export async function AuthInternal<
|
|||||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
|
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
|
||||||
return { ...session, cookies } as any
|
return { ...session, cookies } as any
|
||||||
}
|
}
|
||||||
case "csrf":
|
case "csrf": {
|
||||||
|
if (csrfDisabled) {
|
||||||
|
options.logger.warn("csrf-disabled")
|
||||||
|
cookies.push({
|
||||||
|
name: options.cookies.csrfToken.name,
|
||||||
|
value: "",
|
||||||
|
options: { ...options.cookies.csrfToken.options, maxAge: 0 },
|
||||||
|
})
|
||||||
|
return { status: 404, cookies }
|
||||||
|
}
|
||||||
return {
|
return {
|
||||||
headers: { "Content-Type": "application/json" },
|
headers: { "Content-Type": "application/json" },
|
||||||
body: { csrfToken: options.csrfToken } as any,
|
body: { csrfToken: options.csrfToken } as any,
|
||||||
cookies,
|
cookies,
|
||||||
}
|
}
|
||||||
|
}
|
||||||
case "signin":
|
case "signin":
|
||||||
if (pages.signIn) {
|
if (pages.signIn) {
|
||||||
let signinUrl = `${pages.signIn}${
|
let signinUrl = `${pages.signIn}${
|
||||||
@@ -125,8 +139,7 @@ export async function AuthInternal<
|
|||||||
} else {
|
} else {
|
||||||
switch (action) {
|
switch (action) {
|
||||||
case "signin":
|
case "signin":
|
||||||
// Verified CSRF Token required for all sign in routes
|
if ((csrfDisabled || options.csrfTokenVerified) && options.provider) {
|
||||||
if (options.csrfTokenVerified && options.provider) {
|
|
||||||
const signin = await routes.signin(
|
const signin = await routes.signin(
|
||||||
request.query,
|
request.query,
|
||||||
request.body,
|
request.body,
|
||||||
@@ -138,8 +151,7 @@ export async function AuthInternal<
|
|||||||
|
|
||||||
return { redirect: `${options.url}/signin?csrf=true`, cookies }
|
return { redirect: `${options.url}/signin?csrf=true`, cookies }
|
||||||
case "signout":
|
case "signout":
|
||||||
// Verified CSRF Token required for signout
|
if (csrfDisabled || options.csrfTokenVerified) {
|
||||||
if (options.csrfTokenVerified) {
|
|
||||||
const signout = await routes.signout(sessionStore, options)
|
const signout = await routes.signout(sessionStore, options)
|
||||||
if (signout.cookies) cookies.push(...signout.cookies)
|
if (signout.cookies) cookies.push(...signout.cookies)
|
||||||
return { ...signout, cookies }
|
return { ...signout, cookies }
|
||||||
@@ -150,6 +162,7 @@ export async function AuthInternal<
|
|||||||
// Verified CSRF Token required for credentials providers only
|
// Verified CSRF Token required for credentials providers only
|
||||||
if (
|
if (
|
||||||
options.provider.type === "credentials" &&
|
options.provider.type === "credentials" &&
|
||||||
|
!csrfDisabled &&
|
||||||
!options.csrfTokenVerified
|
!options.csrfTokenVerified
|
||||||
) {
|
) {
|
||||||
return { redirect: `${options.url}/signin?csrf=true`, cookies }
|
return { redirect: `${options.url}/signin?csrf=true`, cookies }
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ interface InitParams {
|
|||||||
/** CSRF token value extracted from the incoming request. From body if POST, from query if GET */
|
/** CSRF token value extracted from the incoming request. From body if POST, from query if GET */
|
||||||
csrfToken?: string
|
csrfToken?: string
|
||||||
/** Is the incoming request a POST request? */
|
/** Is the incoming request a POST request? */
|
||||||
|
csrfDisabled: boolean
|
||||||
isPost: boolean
|
isPost: boolean
|
||||||
cookies: RequestInternal["cookies"]
|
cookies: RequestInternal["cookies"]
|
||||||
}
|
}
|
||||||
@@ -38,6 +39,7 @@ export async function init({
|
|||||||
cookies: reqCookies,
|
cookies: reqCookies,
|
||||||
callbackUrl: reqCallbackUrl,
|
callbackUrl: reqCallbackUrl,
|
||||||
csrfToken: reqCsrfToken,
|
csrfToken: reqCsrfToken,
|
||||||
|
csrfDisabled,
|
||||||
isPost,
|
isPost,
|
||||||
}: InitParams): Promise<{
|
}: InitParams): Promise<{
|
||||||
options: InternalOptions
|
options: InternalOptions
|
||||||
@@ -117,6 +119,7 @@ export async function init({
|
|||||||
|
|
||||||
const cookies: cookie.Cookie[] = []
|
const cookies: cookie.Cookie[] = []
|
||||||
|
|
||||||
|
if (!csrfDisabled) {
|
||||||
const {
|
const {
|
||||||
csrfToken,
|
csrfToken,
|
||||||
cookie: csrfCookie,
|
cookie: csrfCookie,
|
||||||
@@ -138,6 +141,7 @@ export async function init({
|
|||||||
options: options.cookies.csrfToken.options,
|
options: options.cookies.csrfToken.options,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const { callbackUrl, callbackUrlCookie } = await createCallbackUrl({
|
const { callbackUrl, callbackUrlCookie } = await createCallbackUrl({
|
||||||
options,
|
options,
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { AuthError } from "../../errors.js"
|
import { AuthError } from "../../errors.js"
|
||||||
|
|
||||||
export type WarningCode = "debug_enabled"
|
export type WarningCode = "debug-enabled" | "csrf-disabled"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Override any of the methods, and the rest will use the default logger.
|
* Override any of the methods, and the rest will use the default logger.
|
||||||
@@ -38,7 +38,7 @@ export const logger: LoggerInstance = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
warn(code) {
|
warn(code) {
|
||||||
const url = `https://errors.authjs.dev#${code}`
|
const url = `https://warnings.authjs.dev#${code}`
|
||||||
console.warn(`${yellow}[auth][warn][${code}]${reset}`, `Read more: ${url}`)
|
console.warn(`${yellow}[auth][warn][${code}]${reset}`, `Read more: ${url}`)
|
||||||
},
|
},
|
||||||
debug(message, metadata) {
|
debug(message, metadata) {
|
||||||
|
|||||||
Reference in New Issue
Block a user