From fcc8787374f1a1bb6a53e61de77b5a57e71d20b1 Mon Sep 17 00:00:00 2001 From: chenpei Date: Tue, 7 Jul 2026 13:31:01 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=85=AC=E7=BD=91=E5=85=8D?= =?UTF-8?q?=E7=99=BB=E4=BC=9A=E8=AF=9DCookie=E5=88=A4=E5=AE=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/__tests__/auth-cookie.test.ts | 33 +++++++++++++++++++++++++++++++ lib/auth-cookie.ts | 18 ++++++++++------- 2 files changed, 44 insertions(+), 7 deletions(-) diff --git a/lib/__tests__/auth-cookie.test.ts b/lib/__tests__/auth-cookie.test.ts index e792ae2..ff92d7d 100644 --- a/lib/__tests__/auth-cookie.test.ts +++ b/lib/__tests__/auth-cookie.test.ts @@ -7,6 +7,14 @@ import { } from '@/lib/auth-cookie' describe('auth cookie protocol resolution', () => { + function restoreEnv(name: string, value: string | undefined) { + if (value === undefined) { + delete process.env[name] + } else { + process.env[name] = value + } + } + it('HTTPS 请求使用 secure cookie', () => { expect( resolveSecureAuthCookieFromRequest({ @@ -30,6 +38,31 @@ describe('auth cookie protocol resolution', () => { ).toBe(false) }) + it('公网域名经过内网 HTTP 反代时仍使用 secure cookie', () => { + const originalAppPublicUrl = process.env.APP_PUBLIC_URL + const originalNextAuthUrl = process.env.NEXTAUTH_URL + process.env.APP_PUBLIC_URL = 'https://sc.jiansun.vip' + process.env.NEXTAUTH_URL = 'https://sc.jiansun.vip' + + jest.isolateModules(() => { + const { + resolveSecureAuthCookieFromRequest: resolveWithPublicHost, + } = require('@/lib/auth-cookie') + + expect( + resolveWithPublicHost({ + headers: { + host: 'sc.jiansun.vip', + 'x-forwarded-proto': 'http', + }, + }) + ).toBe(true) + }) + + restoreEnv('APP_PUBLIC_URL', originalAppPublicUrl) + restoreEnv('NEXTAUTH_URL', originalNextAuthUrl) + }) + it('优先和兜底 cookie 名称都可返回', () => { expect(getAuthSessionCookieName(true)).toBe(SECURE_AUTH_SESSION_COOKIE_NAME) expect(getAuthSessionCookieName(false)).toBe(PLAIN_AUTH_SESSION_COOKIE_NAME) diff --git a/lib/auth-cookie.ts b/lib/auth-cookie.ts index 4a811d0..2e1cfeb 100644 --- a/lib/auth-cookie.ts +++ b/lib/auth-cookie.ts @@ -104,24 +104,28 @@ function resolveSecureCookieFromPublicBase(headersLike?: HeaderAccessor, url?: s const publicUrl = new URL(AUTH_COOKIE_BASE_URL) const forwardedHost = getHeaderValue(headersLike, 'x-forwarded-host') const host = forwardedHost || getHeaderValue(headersLike, 'host') || (url ? new URL(url).host : '') + if (!host) { + return null + } - return !host || host === publicUrl.host + const normalizedHost = host.split(',')[0].trim().toLowerCase() + return normalizedHost === publicUrl.host.toLowerCase() ? true : null } catch { - return true + return null } } export function resolveSecureAuthCookieFromRequest(request?: RequestLike) { + const secureFromPublicBase = resolveSecureCookieFromPublicBase(request?.headers, request?.url) + if (secureFromPublicBase === true) { + return true + } + const protocolFromHeaders = resolveProtocolFromHeaders(request?.headers) if (protocolFromHeaders) { return protocolFromHeaders === 'https' } - const secureFromPublicBase = resolveSecureCookieFromPublicBase(request?.headers, request?.url) - if (secureFromPublicBase !== null) { - return secureFromPublicBase - } - const protocolFromNextUrl = normalizeProtocol(request?.nextUrl?.protocol) if (protocolFromNextUrl) { return protocolFromNextUrl === 'https'