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
|
||||
---
|
||||
|
||||
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.
|
||||
|
||||
:::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
|
||||
}),
|
||||
```
|
||||
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.
|
||||
@@ -296,4 +296,16 @@ export interface AuthConfig {
|
||||
cookies?: Partial<CookiesOptions>
|
||||
/** @todo */
|
||||
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 warnings: WarningCode[] = []
|
||||
|
||||
if (!warned && options.debug) warnings.push("debug_enabled")
|
||||
if (!warned && options.debug) warnings.push("debug-enabled")
|
||||
|
||||
if (!options.trustHost) {
|
||||
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 { skipCSRFCheck } from "../index.js"
|
||||
import { SessionStore } from "./cookie.js"
|
||||
import { init } from "./init.js"
|
||||
import renderPage from "./pages/index.js"
|
||||
import * as routes from "./routes/index.js"
|
||||
|
||||
import type {
|
||||
RequestInternal,
|
||||
ResponseInternal,
|
||||
AuthConfig,
|
||||
ErrorPageParam,
|
||||
RequestInternal,
|
||||
ResponseInternal,
|
||||
} from "../types.js"
|
||||
|
||||
export async function AuthInternal<
|
||||
@@ -19,6 +20,8 @@ export async function AuthInternal<
|
||||
): Promise<ResponseInternal<Body>> {
|
||||
const { action, providerId, error, method } = request
|
||||
|
||||
const csrfDisabled = authOptions.skipCSRFCheck === skipCSRFCheck
|
||||
|
||||
const { options, cookies } = await init({
|
||||
authOptions,
|
||||
action,
|
||||
@@ -28,6 +31,7 @@ export async function AuthInternal<
|
||||
csrfToken: request.body?.csrfToken,
|
||||
cookies: request.cookies,
|
||||
isPost: method === "POST",
|
||||
csrfDisabled,
|
||||
})
|
||||
|
||||
const sessionStore = new SessionStore(
|
||||
@@ -48,12 +52,22 @@ export async function AuthInternal<
|
||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion
|
||||
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 {
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: { csrfToken: options.csrfToken } as any,
|
||||
cookies,
|
||||
}
|
||||
}
|
||||
case "signin":
|
||||
if (pages.signIn) {
|
||||
let signinUrl = `${pages.signIn}${
|
||||
@@ -125,8 +139,7 @@ export async function AuthInternal<
|
||||
} else {
|
||||
switch (action) {
|
||||
case "signin":
|
||||
// Verified CSRF Token required for all sign in routes
|
||||
if (options.csrfTokenVerified && options.provider) {
|
||||
if ((csrfDisabled || options.csrfTokenVerified) && options.provider) {
|
||||
const signin = await routes.signin(
|
||||
request.query,
|
||||
request.body,
|
||||
@@ -138,8 +151,7 @@ export async function AuthInternal<
|
||||
|
||||
return { redirect: `${options.url}/signin?csrf=true`, cookies }
|
||||
case "signout":
|
||||
// Verified CSRF Token required for signout
|
||||
if (options.csrfTokenVerified) {
|
||||
if (csrfDisabled || options.csrfTokenVerified) {
|
||||
const signout = await routes.signout(sessionStore, options)
|
||||
if (signout.cookies) cookies.push(...signout.cookies)
|
||||
return { ...signout, cookies }
|
||||
@@ -150,6 +162,7 @@ export async function AuthInternal<
|
||||
// Verified CSRF Token required for credentials providers only
|
||||
if (
|
||||
options.provider.type === "credentials" &&
|
||||
!csrfDisabled &&
|
||||
!options.csrfTokenVerified
|
||||
) {
|
||||
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 */
|
||||
csrfToken?: string
|
||||
/** Is the incoming request a POST request? */
|
||||
csrfDisabled: boolean
|
||||
isPost: boolean
|
||||
cookies: RequestInternal["cookies"]
|
||||
}
|
||||
@@ -38,6 +39,7 @@ export async function init({
|
||||
cookies: reqCookies,
|
||||
callbackUrl: reqCallbackUrl,
|
||||
csrfToken: reqCsrfToken,
|
||||
csrfDisabled,
|
||||
isPost,
|
||||
}: InitParams): Promise<{
|
||||
options: InternalOptions
|
||||
@@ -117,26 +119,28 @@ export async function init({
|
||||
|
||||
const cookies: cookie.Cookie[] = []
|
||||
|
||||
const {
|
||||
csrfToken,
|
||||
cookie: csrfCookie,
|
||||
csrfTokenVerified,
|
||||
} = await createCSRFToken({
|
||||
options,
|
||||
cookieValue: reqCookies?.[options.cookies.csrfToken.name],
|
||||
isPost,
|
||||
bodyValue: reqCsrfToken,
|
||||
})
|
||||
|
||||
options.csrfToken = csrfToken
|
||||
options.csrfTokenVerified = csrfTokenVerified
|
||||
|
||||
if (csrfCookie) {
|
||||
cookies.push({
|
||||
name: options.cookies.csrfToken.name,
|
||||
value: csrfCookie,
|
||||
options: options.cookies.csrfToken.options,
|
||||
if (!csrfDisabled) {
|
||||
const {
|
||||
csrfToken,
|
||||
cookie: csrfCookie,
|
||||
csrfTokenVerified,
|
||||
} = await createCSRFToken({
|
||||
options,
|
||||
cookieValue: reqCookies?.[options.cookies.csrfToken.name],
|
||||
isPost,
|
||||
bodyValue: reqCsrfToken,
|
||||
})
|
||||
|
||||
options.csrfToken = csrfToken
|
||||
options.csrfTokenVerified = csrfTokenVerified
|
||||
|
||||
if (csrfCookie) {
|
||||
cookies.push({
|
||||
name: options.cookies.csrfToken.name,
|
||||
value: csrfCookie,
|
||||
options: options.cookies.csrfToken.options,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const { callbackUrl, callbackUrlCookie } = await createCallbackUrl({
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
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.
|
||||
@@ -38,7 +38,7 @@ export const logger: LoggerInstance = {
|
||||
}
|
||||
},
|
||||
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}`)
|
||||
},
|
||||
debug(message, metadata) {
|
||||
|
||||
Reference in New Issue
Block a user