fix: cookie stuff
This commit is contained in:
parent
f10772084d
commit
329a71931b
@ -7,15 +7,32 @@ function getSharedCookieDomain(req: NextRequest): string | undefined {
|
||||
return host.endsWith('profit-planet.partners') ? '.profit-planet.partners' : undefined
|
||||
}
|
||||
|
||||
function splitSetCookieHeader(header: string): string[] {
|
||||
const parts: string[] = []
|
||||
let start = 0
|
||||
let inExpires = false
|
||||
for (let i = 0; i < header.length; i++) {
|
||||
const lower = header.slice(i, i + 8).toLowerCase()
|
||||
if (lower === 'expires=') inExpires = true
|
||||
if (inExpires && header[i] === ';') inExpires = false
|
||||
if (!inExpires && header[i] === ',') {
|
||||
parts.push(header.slice(start, i).trim())
|
||||
start = i + 1
|
||||
}
|
||||
}
|
||||
const last = header.slice(start).trim()
|
||||
if (last) parts.push(last)
|
||||
return parts
|
||||
}
|
||||
|
||||
function readSetCookies(res: Response): string[] {
|
||||
const anyHeaders = res.headers as any
|
||||
if (typeof anyHeaders.getSetCookie === 'function') return anyHeaders.getSetCookie()
|
||||
const single = res.headers.get('set-cookie')
|
||||
return single ? [single] : []
|
||||
return single ? splitSetCookieHeader(single) : []
|
||||
}
|
||||
|
||||
function parseRefreshCookie(setCookie: string) {
|
||||
// refreshToken=VALUE; Max-Age=...; Expires=...; SameSite=...; ...
|
||||
const m = setCookie.match(/^refreshToken=([^;]*)/i)
|
||||
if (!m) return null
|
||||
const value = m[1] ?? ''
|
||||
@ -52,7 +69,23 @@ export async function POST(req: NextRequest) {
|
||||
const refreshSetCookie = setCookies.find((c) => /^refreshToken=/i.test(c))
|
||||
if (refreshSetCookie) {
|
||||
const parsed = parseRefreshCookie(refreshSetCookie)
|
||||
if (parsed) {
|
||||
if (parsed?.value) {
|
||||
// Clear host-only duplicates first.
|
||||
out.cookies.set('refreshToken', '', {
|
||||
path: '/',
|
||||
httpOnly: true,
|
||||
secure: true,
|
||||
sameSite: 'lax',
|
||||
maxAge: 0,
|
||||
})
|
||||
out.cookies.set('__Secure-refreshToken', '', {
|
||||
path: '/',
|
||||
httpOnly: true,
|
||||
secure: true,
|
||||
sameSite: 'lax',
|
||||
maxAge: 0,
|
||||
})
|
||||
|
||||
out.cookies.set('refreshToken', parsed.value, {
|
||||
domain: getSharedCookieDomain(req),
|
||||
path: '/',
|
||||
|
||||
@ -28,6 +28,12 @@ export async function POST(req: NextRequest) {
|
||||
}
|
||||
|
||||
const out = NextResponse.json(data, { status })
|
||||
|
||||
// Clear host-only variants
|
||||
out.cookies.set('refreshToken', '', { path: '/', httpOnly: true, secure: true, sameSite: 'lax', maxAge: 0 })
|
||||
out.cookies.set('__Secure-refreshToken', '', { path: '/', httpOnly: true, secure: true, sameSite: 'lax', maxAge: 0 })
|
||||
|
||||
// Clear shared-domain variant
|
||||
out.cookies.set('refreshToken', '', {
|
||||
domain: getSharedCookieDomain(req),
|
||||
path: '/',
|
||||
@ -36,5 +42,6 @@ export async function POST(req: NextRequest) {
|
||||
sameSite: 'lax',
|
||||
maxAge: 0,
|
||||
})
|
||||
|
||||
return out
|
||||
}
|
||||
|
||||
@ -7,11 +7,30 @@ function getSharedCookieDomain(req: NextRequest): string | undefined {
|
||||
return host.endsWith('profit-planet.partners') ? '.profit-planet.partners' : undefined
|
||||
}
|
||||
|
||||
function splitSetCookieHeader(header: string): string[] {
|
||||
// Handles "Expires=Wed, 21 Oct ..." commas.
|
||||
const parts: string[] = []
|
||||
let start = 0
|
||||
let inExpires = false
|
||||
for (let i = 0; i < header.length; i++) {
|
||||
const lower = header.slice(i, i + 8).toLowerCase()
|
||||
if (lower === 'expires=') inExpires = true
|
||||
if (inExpires && header[i] === ';') inExpires = false
|
||||
if (!inExpires && header[i] === ',') {
|
||||
parts.push(header.slice(start, i).trim())
|
||||
start = i + 1
|
||||
}
|
||||
}
|
||||
const last = header.slice(start).trim()
|
||||
if (last) parts.push(last)
|
||||
return parts
|
||||
}
|
||||
|
||||
function readSetCookies(res: Response): string[] {
|
||||
const anyHeaders = res.headers as any
|
||||
if (typeof anyHeaders.getSetCookie === 'function') return anyHeaders.getSetCookie()
|
||||
const single = res.headers.get('set-cookie')
|
||||
return single ? [single] : []
|
||||
return single ? splitSetCookieHeader(single) : []
|
||||
}
|
||||
|
||||
function parseRefreshCookie(setCookie: string) {
|
||||
@ -35,11 +54,24 @@ export async function POST(req: NextRequest) {
|
||||
const apiBase = process.env.NEXT_PUBLIC_API_BASE_URL
|
||||
if (!apiBase) return NextResponse.json({ message: 'Missing NEXT_PUBLIC_API_BASE_URL' }, { status: 500 })
|
||||
|
||||
// Prefer a single parsed cookie value to avoid "refreshToken=old; refreshToken=new" ambiguity.
|
||||
const rt =
|
||||
req.cookies.get('refreshToken')?.value ??
|
||||
req.cookies.get('__Secure-refreshToken')?.value ??
|
||||
''
|
||||
|
||||
const headers: Record<string, string> = {}
|
||||
if (rt) {
|
||||
headers.cookie = `refreshToken=${rt}`
|
||||
} else {
|
||||
// fallback (best-effort)
|
||||
const cookie = req.headers.get('cookie') ?? ''
|
||||
if (cookie) headers.cookie = cookie
|
||||
}
|
||||
|
||||
const apiRes = await fetch(`${apiBase}/api/refresh`, {
|
||||
method: 'POST',
|
||||
headers: { cookie },
|
||||
headers,
|
||||
cache: 'no-store',
|
||||
})
|
||||
|
||||
@ -50,7 +82,24 @@ export async function POST(req: NextRequest) {
|
||||
const refreshSetCookie = setCookies.find((c) => /^refreshToken=/i.test(c))
|
||||
if (refreshSetCookie) {
|
||||
const parsed = parseRefreshCookie(refreshSetCookie)
|
||||
if (parsed) {
|
||||
if (parsed?.value) {
|
||||
// Clear any host-only variants on the frontend host to prevent duplicates.
|
||||
out.cookies.set('refreshToken', '', {
|
||||
path: '/',
|
||||
httpOnly: true,
|
||||
secure: true,
|
||||
sameSite: 'lax',
|
||||
maxAge: 0,
|
||||
})
|
||||
out.cookies.set('__Secure-refreshToken', '', {
|
||||
path: '/',
|
||||
httpOnly: true,
|
||||
secure: true,
|
||||
sameSite: 'lax',
|
||||
maxAge: 0,
|
||||
})
|
||||
|
||||
// Set the shared-domain cookie used across subdomains.
|
||||
out.cookies.set('refreshToken', parsed.value, {
|
||||
domain: getSharedCookieDomain(req),
|
||||
path: '/',
|
||||
|
||||
Loading…
Reference in New Issue
Block a user