next-auth
semver
^4.22.0postconditions15functions10last verified2026-06-23coverage score100%Postconditions: what we check
- encode · encode-no-try-catchwarningWhensecret parameter is undefined, null, or empty string; or EncryptJWT failsThrows
TypeError from @panva/hkdf when secret is missing; Error from jose during encryption failureRequired handlingCaller MUST wrap encode() in try/catch when called outside of NextAuth's own jwt.encode callback. Common error: NEXTAUTH_SECRET not set → TypeError from hkdf. Handle gracefully: log the configuration error and fail the request with 500. Note: encode() inside NextAuth's jwt.encode option is protected by the framework.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[1] - decode · decode-no-try-catchwarningWhenToken encrypted with different secret (key rotation), malformed token, or missing secretThrows
JWEDecryptionFailed (wrong secret), JWEInvalid/JWTInvalid (malformed), TypeError (missing secret)Required handlingCaller MUST wrap decode() in try/catch when calling directly. Common scenarios: 1. Secret rotation: old tokens throw JWEDecryptionFailed → return null/401, force re-auth 2. Malformed/tampered token: JWEInvalid → return 401, do not expose error details 3. Missing NEXTAUTH_SECRET: TypeError → configuration error, fail fast with clear message Note: getToken() from next-auth/jwt already wraps decode() in try/catch internally. This postcondition applies only to direct decode() calls.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[1] - getServerSession · getserversession-null-not-checkederrorWhenNo active session (user not logged in, expired token, or invalid cookie)ReturnsnullRequired handlingCaller MUST check the return value for null before accessing session properties. getServerSession() returns null when: no session cookie present, session expired, or token validation fails. Accessing .user or other properties on null causes TypeError. Pattern: const session = await getServerSession(authOptions); if (!session) return redirect('/login');costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[2]
- getServerSession · getserversession-authoptions-mismatchwarningWhenauthOptions not passed or different from [...nextauth] route configReturnsnull (silently returns null when options mismatch)Required handlingCaller MUST pass the same authOptions object used in the [...nextauth] route handler. In App Router, getServerSession(authOptions) is required — omitting authOptions returns null silently. Common mistake: importing authOptions from wrong file or passing partial config. Always export authOptions from a single shared location.costhighin prodsilent failureusers seeauthentication failurevisibilitysilentSources[2]
- getToken · gettoken-null-not-checkederrorWhenNo valid JWT cookie present, token expired, or decode failsReturnsnullRequired handlingCaller MUST check the return value for null before accessing token properties. getToken() returns null when: no session cookie, decode fails (wrong secret, malformed token), or cookie name doesn't match. Accessing properties on null causes TypeError. Pattern: const token = await getToken({ req }); if (!token) return res.status(401).json({ error: 'Unauthorized' });costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[3]
- getToken · gettoken-missing-reqwarningWhenreq parameter is undefined or nullThrows
TypeError: Cannot read properties of undefined (reading 'headers')Required handlingCaller MUST pass a valid request object to getToken(). In API routes, pass { req }. In middleware, pass { req: request }. Missing req causes an immediate TypeError. This is a coding error, not a runtime condition — ensure req is always provided.costlowin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[4] - getToken · gettoken-missing-secretwarningWhenNEXTAUTH_SECRET environment variable not set and no secret option providedThrows
MissingSecret: Please define a `secret` in production by setting the NEXTAUTH_SECRET environment variable.Required handlingCaller MUST ensure NEXTAUTH_SECRET is set in the environment or pass secret option to getToken({ req, secret }). In development, NextAuth generates a random secret with a warning. In production, missing secret throws MissingSecret error. This is a deployment configuration issue — validate env vars at startup.costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[1] - signIn · signin-error-not-checkederrorWhenAuthentication fails when called with redirect:false (wrong credentials, provider error)ReturnsSignInResponse with error field set (e.g., { error: 'CredentialsSignin', status: 401, ok: false, url: null })Required handlingWhen using signIn('credentials', { redirect: false }), caller MUST check the .error property of the returned object. signIn() does NOT throw on auth failure — it returns { error: 'CredentialsSignin', ok: false }. Common mistake: using try/catch instead of checking response.error. Pattern: const res = await signIn('credentials', { ...data, redirect: false }); if (res?.error) { showError(res.error); } else { router.push('/dashboard'); }costmediumin prodsilent failureusers seedegraded performancevisibilitysilentSources[5]
- signIn · signin-providers-fetch-failurewarningWhenNetwork error when calling /api/auth/csrf or /api/auth/signin endpointReturnsundefined (signIn returns undefined when the internal fetch fails)Required handlingCaller SHOULD handle the case where signIn() returns undefined, which happens when the internal fetch to the auth API fails (network error, server down). The internal fetchData utility catches fetch errors and returns null, which propagates as undefined from signIn(). Pattern: const res = await signIn(...); if (!res) { showNetworkError(); }costlowin prodsilent failureusers seedegraded performancevisibilitysilentSources[5]
- signOut · signout-network-error-not-handledwarningWhenNetwork error when calling /api/auth/signout endpointReturnsundefined (internal fetchData catches and returns null)Required handlingCaller SHOULD handle the case where signOut({ redirect: false }) returns undefined or the redirect fails due to network error. The internal fetchData utility catches fetch errors and returns null. If using redirect:false, check the return value before using .url property. Pattern: const res = await signOut({ redirect: false }); if (res?.url) { window.location.href = res.url; } else { showError('Sign out failed'); }costlowin prodsilent failureusers seedegraded performancevisibilitysilentSources[6]
- withAuth · withauth-no-secretwarningWhenNEXTAUTH_SECRET not set and secret option not providedReturnsRedirects to /api/auth/error page with console error loggedRequired handlingCaller MUST ensure NEXTAUTH_SECRET is set in the environment or pass secret option in middleware config. Without a secret, withAuth cannot decode the JWT token and redirects all users to the error page. This is a deployment configuration error. The middleware logs 'NO_SECRET' error to console. Validate env vars in CI/CD pipeline.costhighin proddegraded serviceusers seeservice unavailablevisibilityvisibleSources[7]
- withAuth · withauth-authorized-callback-falsewarningWhenauthorized callback returns false (user authenticated but not authorized)ReturnsRedirects to sign-in page (not error page)Required handlingWhen using the authorized callback for role-based access, be aware that returning false redirects to the sign-in page, NOT an 'access denied' page. This can confuse authenticated users who lack permissions. To show a proper 403 page, handle authorization in the page component instead of the middleware authorized callback. Pattern: callbacks: { authorized: ({ token }) => token?.role === 'admin' }costlowin proddegraded serviceusers seedegraded performancevisibilityvisibleSources[7]
- getSession · getsession-null-not-checkederrorWhenNo active session or network error fetching /api/auth/sessionReturnsnullRequired handlingCaller MUST check the return value for null before accessing session properties. getSession() returns null when: user not authenticated, session expired, or network error fetching the session endpoint. The internal fetchData utility catches fetch errors and returns null. Accessing .user on null causes TypeError. Pattern: const session = await getSession(); if (!session) { redirectToLogin(); }costmediumin prodimmediate exceptionusers seeservice unavailablevisibilityvisibleSources[8]
- getCsrfToken · getcsrftoken-undefined-not-checkedwarningWhenNetwork error fetching /api/auth/csrf, server down, or non-2xx responseReturnsundefined (internal fetchData catches fetch errors and returns null; getCsrfToken returns response?.csrfToken)Required handlingCaller MUST check the return value before submitting custom sign-in forms. getCsrfToken() returns undefined when: the /api/auth/csrf endpoint is unreachable, the server returns a non-2xx response, or NEXTAUTH_URL is misconfigured. fetchData() in client/_utils.js catches all errors, logs CLIENT_FETCH_ERROR, and returns null — getCsrfToken's `response?.csrfToken` then yields undefined. Submitting a custom sign-in POST with an undefined csrfToken triggers a CSRF rejection on the server (MissingCSRF error in [...nextauth] handler), producing a silent auth failure that looks like "credentials wrong" to users. Pattern: const csrf = await getCsrfToken(); if (!csrf) { showNetworkError(); return; }costmediumin prodsilent failureusers seeauthentication failurevisibilitysilentSources[9]
- getProviders · getproviders-null-not-checkedwarningWhenNetwork error fetching /api/auth/providers, server down, or empty provider listReturnsnull (internal fetchData catches fetch errors and returns null)Required handlingCaller MUST check the return value for null before iterating providers. getProviders() returns null when: the /api/auth/providers endpoint is unreachable, the server returns a non-2xx response, NEXTAUTH_URL is misconfigured, or no providers are configured. Object.values(null) and Object.entries(null) throw TypeError, which crashes the custom sign-in page with a blank screen. The internal fetchData catches the underlying fetch error silently and logs CLIENT_FETCH_ERROR — there is no exception for the caller to catch. Pattern: const providers = await getProviders(); if (!providers) { showFallbackSignIn(); return; } Object.values(providers).map(p => <button .../>)costmediumin prodimmediate exceptionusers seeauthentication failurevisibilityvisibleSources[10]
Sources
Every postcondition cites at least one of these. Grouped by source type; numbered to match the footnotes above.
Official documentation
- [1]next-auth.js.org/configuration/optionsOptions
- [2]next-auth.js.org/configuration/nextjsNextjs
- [3]next-auth.js.org/tutorials/securing-pages-and-api-routesSecuring Pages And Api Routes
- [4]next-auth.js.org/tutorials/securing-pages-and-api-routesSecuring Pages And Api Routes
- [5]next-auth.js.org/getting-started/clientClient
- [6]next-auth.js.org/getting-started/clientClient
- [7]next-auth.js.org/configuration/nextjsNextjs
- [8]next-auth.js.org/getting-started/clientClient
- [9]next-auth.js.org/getting-started/clientClient
- [10]next-auth.js.org/getting-started/clientClient
Research notes
Curator notes from SOURCES.md captured when the profile was written so you can verify the reasoning, not just the rules.
Sources: next-auth
Official Documentation
- Main docs: https://next-auth.js.org/getting-started/introduction
- JWT options: https://next-auth.js.org/configuration/options#jwt
- Secret config: https://next-auth.js.org/configuration/options#secret
- getToken: https://next-auth.js.org/tutorials/securing-pages-and-api-routes#using-gettoken
- Callbacks reference: https://next-auth.js.org/configuration/callbacks
- Error codes: https://next-auth.js.org/errors
- v4 upgrade guide: https://next-auth.js.org/getting-started/upgrade-v4
Source Code Evidence
- JWT implementation:
next-auth/jwt/index.js— confirms encode/decode can throw, getToken catches errors internally - hkdf dependency:
@panva/hkdf— throws TypeError when ikm (secret) is undefined/null/empty - jose dependency:
joselibrary'sjwtDecryptthrowsJWEDecryptionFailed,JWTExpired,JWTInvalid
Security Advisories
- CVE-2022-29214 — Open redirect via callbackUrl (fixed in 4.3.3) https://github.com/nextauthjs/next-auth/security/advisories/GHSA-pg5p-wwp8-97g8
- CVE-2023-48309 — Authorization bypass via id_token (fixed in 4.24.5) https://github.com/nextauthjs/next-auth/security/advisories/GHSA-7r7x-4c4q-c4qf
Real-World Usage Evidence
| Repo | Version | Pattern |
|---|---|---|
| dub.co | 4.24.11 | getToken() in middleware, signIn() with response check |
| cal.com | 4.24.13 | encode() in jwt callback, getToken() in API routes |
| taxonomy | 4.22.1 | getToken() in middleware |
| formbricks | 4.24.12 | getToken() in proxy |
Need a different package?
Request a profile