Skip to content

Commit 0ea9679

Browse files
fix: improve logger (#4970)
* fix: add debug warning, only show warnings once * fix: prefer `debug` for details * remove url * test: fix tests * Update docs/docs/errors.md Co-authored-by: Thang Vu <31528554+ThangHuuVu@users.noreply.github.com> * Update callback.ts Co-authored-by: Thang Vu <31528554+ThangHuuVu@users.noreply.github.com>
1 parent 8ec940b commit 0ea9679

File tree

14 files changed

+130
-130
lines changed

14 files changed

+130
-130
lines changed

docs/docs/errors.md

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -61,17 +61,20 @@ There should also be further details logged when this occurs, such as the error
6161

6262
### Signin / Callback
6363

64-
#### GET_AUTHORIZATION_URL_ERROR
64+
#### SIGNIN_OAUTH_ERROR
6565

66-
This error can occur when we cannot get the OAuth v1 request token and generate the authorization URL.
66+
This error occurs during the redirection to the authorization URL of the OAuth provider. Possible causes:
6767

68-
Please double check your OAuth v1 provider settings, especially the OAuth token and OAuth token secret.
68+
1. Cookie handling
69+
Either PKCE code verifier or the generation of the CSRF token hash in the internal state failed.
6970

70-
#### SIGNIN_OAUTH_ERROR
71+
If set, check your [`cookies` configuration](/configuration/options#cookies), and make sure the browser is not blocking/restricting cookies.
72+
73+
2. OAuth misconfiguration
7174

72-
This error can occur in one of a few places, first during the redirect to the authorization URL of the provider. Next, in the signin flow while creating the PKCE code verifier. Finally, during the generation of the CSRF Token hash in the internal state during signin.
75+
Please check your OAuth provider and make sure your URLs and other options are correctly set.
7376

74-
Please check your OAuth provider settings and make sure your URLs and other options are correctly set on the provider side.
77+
If you are using an OAuth v1 provider, check your OAuth v1 provider settings, especially the OAuth token and OAuth token secret.
7578

7679
#### CALLBACK_OAUTH_ERROR
7780

@@ -151,12 +154,6 @@ This error occurs when there was an issue deleting the session from the database
151154

152155
### Other
153156

154-
#### SEND_VERIFICATION_EMAIL_ERROR
155-
156-
This error occurs when the Email Authentication Provider is unable to send an email.
157-
158-
Check your mail server configuration.
159-
160157
#### MISSING_NEXTAUTH_API_ROUTE_ERROR
161158

162159
This error happens when `[...nextauth].js` file is not found inside `pages/api/auth`.

docs/docs/warnings.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,12 @@ Twitter OAuth 2.0 is currently in beta as certain changes might still be necessa
3737

3838
Some APIs are still experimental; they may be changed or removed in the future. Use at your own risk.
3939

40+
#### DEBUG_ENABLED
41+
42+
You have enabled the `debug` option. It is meant for development only, to help you catch issues in your authentication flow and you should consider removing this option when deploying to production. One way of only allowing debugging while not in production is to set `debug: process.env.NODE_ENV !== "production"`, so you can commit this without needing to change the value.
43+
44+
If you want to log debug messages during production anyway, we recommend setting the [`logger` option](/configuration/options#logger) with proper sanitization of potentially sensitive user information.
45+
4046
## Adapter
4147

4248
### ADAPTER_TYPEORM_UPDATING_ENTITIES

packages/next-auth/src/client/__tests__/csrf.test.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ test("when the fetch fails it'll throw a client fetch error", async () => {
7979
await waitFor(() => {
8080
expect(logger.error).toHaveBeenCalledTimes(1)
8181
expect(logger.error).toBeCalledWith("CLIENT_FETCH_ERROR", {
82-
path: "csrf",
82+
url: "/api/auth/csrf",
8383
error: new SyntaxError("Unexpected token s in JSON at position 0"),
8484
})
8585
})

packages/next-auth/src/client/__tests__/providers.test.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ test("when failing to fetch the providers, it'll log the error", async () => {
5757
await waitFor(() => {
5858
expect(logger.error).toHaveBeenCalledTimes(1)
5959
expect(logger.error).toBeCalledWith("CLIENT_FETCH_ERROR", {
60-
path: "providers",
60+
url: "/api/auth/providers",
6161
error: new SyntaxError("Unexpected token s in JSON at position 0"),
6262
})
6363
})

packages/next-auth/src/client/__tests__/session.test.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ test("if there's an error fetching the session, it should log it", async () => {
7171
await waitFor(() => {
7272
expect(logger.error).toHaveBeenCalledTimes(1)
7373
expect(logger.error).toBeCalledWith("CLIENT_FETCH_ERROR", {
74-
path: "session",
74+
url: "/api/auth/session",
7575
error: new SyntaxError("Unexpected token S in JSON at position 0"),
7676
})
7777
})

packages/next-auth/src/client/__tests__/sign-in.test.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,7 @@ test("when it fails to fetch the providers, it redirected back to signin page",
256256
expect(logger.error).toHaveBeenCalledTimes(1)
257257
expect(logger.error).toBeCalledWith("CLIENT_FETCH_ERROR", {
258258
error: "Error when retrieving providers",
259-
path: "providers",
259+
url: "/api/auth/providers",
260260
})
261261
})
262262
})

packages/next-auth/src/client/_utils.ts

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,20 +35,17 @@ export async function fetchData<T = any>(
3535
logger: LoggerInstance,
3636
{ ctx, req = ctx?.req }: CtxOrReq = {}
3737
): Promise<T | null> {
38+
const url = `${apiBaseUrl(__NEXTAUTH)}/${path}`
3839
try {
3940
const options = req?.headers.cookie
4041
? { headers: { cookie: req.headers.cookie } }
4142
: {}
42-
const res = await fetch(`${apiBaseUrl(__NEXTAUTH)}/${path}`, options)
43+
const res = await fetch(url, options)
4344
const data = await res.json()
4445
if (!res.ok) throw data
4546
return Object.keys(data).length > 0 ? data : null // Return null if data empty
4647
} catch (error) {
47-
logger.error("CLIENT_FETCH_ERROR", {
48-
error: error as Error,
49-
path,
50-
...(req ? { header: req.headers } : {}),
51-
})
48+
logger.error("CLIENT_FETCH_ERROR", { error: error as Error, url })
5249
return null
5350
}
5451
}

packages/next-auth/src/core/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,8 +90,8 @@ export async function NextAuthHandler<
9090

9191
const assertionResult = assertConfig({ options: userOptions, req })
9292

93-
if (typeof assertionResult === "string") {
94-
logger.warn(assertionResult)
93+
if (Array.isArray(assertionResult)) {
94+
assertionResult.forEach(logger.warn)
9595
} else if (assertionResult instanceof Error) {
9696
// Bail out early if there's an error in the user config
9797
const { pages, theme } = userOptions

packages/next-auth/src/core/lib/assert.ts

Lines changed: 28 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,9 @@ import {
99
import parseUrl from "../../utils/parse-url"
1010
import { defaultCookies } from "./cookie"
1111

12-
import type { NextAuthHandlerParams, RequestInternal } from ".."
12+
import type { RequestInternal } from ".."
1313
import type { WarningCode } from "../../utils/logger"
14+
import type { NextAuthOptions } from "../types"
1415

1516
type ConfigError =
1617
| MissingAPIRoute
@@ -19,7 +20,7 @@ type ConfigError =
1920
| MissingAuthorize
2021
| MissingAdapter
2122

22-
let twitterWarned = false
23+
let warned = false
2324

2425
function isValidHttpUrl(url: string, baseUrl: string) {
2526
try {
@@ -37,28 +38,35 @@ function isValidHttpUrl(url: string, baseUrl: string) {
3738
*
3839
* REVIEW: Make some of these and corresponding docs less Next.js specific?
3940
*/
40-
export function assertConfig(
41-
params: NextAuthHandlerParams & {
42-
req: RequestInternal
43-
}
44-
): ConfigError | WarningCode | undefined {
41+
export function assertConfig(params: {
42+
options: NextAuthOptions
43+
req: RequestInternal
44+
}): ConfigError | WarningCode[] {
4545
const { options, req } = params
4646

47+
const warnings: WarningCode[] = []
48+
49+
if (!warned) {
50+
if (!req.host) warnings.push("NEXTAUTH_URL")
51+
52+
// TODO: Make this throw an error in next major. This will also get rid of `NODE_ENV`
53+
if (!options.secret && process.env.NODE_ENV !== "production")
54+
warnings.push("NO_SECRET")
55+
56+
if (options.debug) warnings.push("DEBUG_ENABLED")
57+
}
58+
59+
if (!options.secret && process.env.NODE_ENV === "production") {
60+
return new MissingSecret("Please define a `secret` in production.")
61+
}
62+
4763
// req.query isn't defined when asserting `unstable_getServerSession` for example
4864
if (!req.query?.nextauth && !req.action) {
4965
return new MissingAPIRoute(
5066
"Cannot find [...nextauth].{js,ts} in `/pages/api/auth`. Make sure the filename is written correctly."
5167
)
5268
}
5369

54-
if (!options.secret) {
55-
if (process.env.NODE_ENV === "production") {
56-
return new MissingSecret("Please define a `secret` in production.")
57-
} else {
58-
return "NO_SECRET"
59-
}
60-
}
61-
6270
const callbackUrlParam = req.query?.callbackUrl as string | undefined
6371

6472
const url = parseUrl(req.host)
@@ -69,9 +77,6 @@ export function assertConfig(
6977
)
7078
}
7179

72-
// This is below the callbackUrlParam check because it would obscure the error
73-
if (!req.host) return "NEXTAUTH_URL"
74-
7580
const { callbackUrl: defaultCallbackUrl } = defaultCookies(
7681
options.useSecureCookies ?? url.base.startsWith("https://")
7782
)
@@ -119,8 +124,10 @@ export function assertConfig(
119124
return new MissingAdapter("E-mail login requires an adapter.")
120125
}
121126

122-
if (!twitterWarned && hasTwitterOAuth2) {
123-
twitterWarned = true
124-
return "TWITTER_OAUTH_2_BETA"
127+
if (!warned) {
128+
if (hasTwitterOAuth2) warnings.push("TWITTER_OAUTH_2_BETA")
129+
warned = true
125130
}
131+
132+
return warnings
126133
}

packages/next-auth/src/core/lib/email/signin.ts

Lines changed: 16 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,8 @@ import type { InternalOptions } from "../../types"
99
export default async function email(
1010
identifier: string,
1111
options: InternalOptions<"email">
12-
) {
13-
const { url, adapter, provider, logger, callbackUrl, theme } = options
14-
12+
): Promise<string> {
13+
const { url, adapter, provider, callbackUrl, theme } = options
1514
// Generate token
1615
const token =
1716
(await provider.generateVerificationToken?.()) ??
@@ -34,22 +33,18 @@ export default async function email(
3433
const params = new URLSearchParams({ callbackUrl, token, email: identifier })
3534
const _url = `${url}/callback/${provider.id}?${params}`
3635

37-
try {
38-
// Send to user
39-
await provider.sendVerificationRequest({
40-
identifier,
41-
token,
42-
expires,
43-
url: _url,
44-
provider,
45-
theme,
46-
})
47-
} catch (error) {
48-
logger.error("SEND_VERIFICATION_EMAIL_ERROR", {
49-
identifier,
50-
url,
51-
error: error as Error,
52-
})
53-
throw new Error("SEND_VERIFICATION_EMAIL_ERROR")
54-
}
36+
// Send to user
37+
await provider.sendVerificationRequest({
38+
identifier,
39+
token,
40+
expires,
41+
url: _url,
42+
provider,
43+
theme,
44+
})
45+
46+
return `${url}/verify-request?${new URLSearchParams({
47+
provider: provider.id,
48+
type: provider.type,
49+
})}`
5550
}

0 commit comments

Comments
 (0)