Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion app/.env.local.example
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ NEXTAUTH_URL=http://localhost:3000
# https://generate-secret.vercel.app/32 to generate a secret.
# Note: Changing a secret may invalidate existing sessions
# and/or verification tokens.
SECRET=secret
NEXTAUTH_SECRET=secret

AUTH0_ID=
AUTH0_SECRET=
Expand Down
3 changes: 1 addition & 2 deletions app/pages/api/auth/[...nextauth].ts
Original file line number Diff line number Diff line change
Expand Up @@ -189,9 +189,8 @@ export const authOptions: NextAuthOptions = {
PatreonProvider({
clientId: process.env.PATREON_ID,
clientSecret: process.env.PATREON_SECRET,
})
}),
],
secret: process.env.SECRET,
debug: true,
theme: {
colorScheme: "auto",
Expand Down
7 changes: 4 additions & 3 deletions src/core/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,10 @@ export interface NextAuthOptions {
providers: Provider[]
/**
* A random string used to hash tokens, sign cookies and generate cryptographic keys.
* If not specified is uses a hash of all configuration options, including Client ID / Secrets for entropy.
* The default behavior is volatile, and **it is strongly recommended** you explicitly specify a value
* to avoid invalidating end user sessions when configuration changes are deployed.
* If not specified, it falls back to `jwt.secret` or `NEXTAUTH_SECRET` from environment vairables.
* Otherwise it will use a hash of all configuration options, including Client ID / Secrets for entropy.
*
* NOTE: The last behavior is extrmely volatile, and will throw an error in production.
* * **Default value**: `string` (SHA hash of the "options" object)
* * **Required**: No - **but strongly recommended**!
*
Expand Down
22 changes: 11 additions & 11 deletions src/jwt/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,8 @@ const DEFAULT_MAX_AGE = 30 * 24 * 60 * 60 // 30 days
const now = () => (Date.now() / 1000) | 0

/** Issues a JWT. By default, the JWT is encrypted using "A256GCM". */
export async function encode({
token = {},
secret,
maxAge = DEFAULT_MAX_AGE,
}: JWTEncodeParams) {
export async function encode(params: JWTEncodeParams) {
const { token = {}, secret, maxAge = DEFAULT_MAX_AGE } = params
const encryptionSecret = await getDerivedEncryptionKey(secret)
return await new EncryptJWT(token)
.setProtectedHeader({ alg: "dir", enc: "A256GCM" })
Expand All @@ -28,10 +25,8 @@ export async function encode({
}

/** Decodes a NextAuth.js issued JWT. */
export async function decode({
token,
secret,
}: JWTDecodeParams): Promise<JWT | null> {
export async function decode(params: JWTDecodeParams): Promise<JWT | null> {
const { token, secret } = params
if (!token) return null
const encryptionSecret = await getDerivedEncryptionKey(secret)
const { payload } = await jwtDecrypt(token, encryptionSecret, {
Expand All @@ -55,7 +50,11 @@ export interface GetTokenParams<R extends boolean = false> {
* @default false
*/
raw?: R
secret: string
/**
* The same `secret` used in the `NextAuth` configuration.
* Defaults to the `NEXTAUTH_SECRET` environment variable.
*/
secret?: string
decode?: JWTOptions["decode"]
logger?: LoggerInstance | Console
}
Expand All @@ -78,6 +77,7 @@ export async function getToken<R extends boolean = false>(
raw,
decode: _decode = decode,
logger = console,
secret = process.env.NEXTAUTH_SECRET,
} = params ?? {}

if (!req) throw new Error("Must pass `req` to JWT getToken()")
Expand All @@ -103,7 +103,7 @@ export async function getToken<R extends boolean = false>(

try {
// @ts-expect-error
return await _decode({ token, ...params })
return await _decode({ token, secret })
} catch {
// @ts-expect-error
return null
Expand Down
6 changes: 5 additions & 1 deletion src/jwt/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,11 @@ export interface JWTDecodeParams {
}

export interface JWTOptions {
/** The secret used to encode/decode the NextAuth.js issued JWT. */
/**
* The secret used to encode/decode the NextAuth.js issued JWT.
* @deprecated Set the `NEXTAUTH_SECRET` environment vairable or
* use the top-level `secret` option instead
*/
secret: string
/**
* The maximum age of the NextAuth.js issued JWT in seconds.
Expand Down
4 changes: 4 additions & 0 deletions src/next/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ async function NextAuthNextHandler(
options: NextAuthOptions
) {
const { nextauth, ...query } = req.query

options.secret =
options.secret ?? options.jwt?.secret ?? process.env.NEXTAUTH_SECRET

const handler = await NextAuthHandler({
req: {
host: detectHost(req.headers["x-forwarded-host"]),
Expand Down