fix(oauth): use separate Set-Cookie headers for multiple cookies

Browser cannot parse multiple cookies from a single Set-Cookie header
joined by comma (RFC 6265). Use Headers.append() to send each cookie
in its own Set-Cookie header. Fixes state/verifier cookie mismatch.
This commit is contained in:
emil
2026-05-15 01:59:56 +03:00
parent da6208de50
commit b71902b686
4 changed files with 22 additions and 34 deletions
+6 -9
View File
@@ -106,17 +106,14 @@ export const GET: APIRoute = async ({ url, request }) => {
expiresAt,
});
const cookies = [
`${COOKIE_NAME}=${sessionToken}; HttpOnly; SameSite=Strict; Max-Age=604800; Path=/`,
`${VERIFIER_COOKIE_NAME}=; HttpOnly; SameSite=Strict; Max-Age=0; Path=/`,
`oauth_state=; HttpOnly; SameSite=Strict; Max-Age=0; Path=/`,
];
const headers = new Headers();
headers.set('Location', '/dm/');
headers.append('Set-Cookie', `${COOKIE_NAME}=${sessionToken}; HttpOnly; SameSite=Strict; Max-Age=604800; Path=/`);
headers.append('Set-Cookie', `${VERIFIER_COOKIE_NAME}=; HttpOnly; SameSite=Strict; Max-Age=0; Path=/`);
headers.append('Set-Cookie', `oauth_state=; HttpOnly; SameSite=Strict; Max-Age=0; Path=/`);
return new Response(null, {
status: 302,
headers: {
Location: '/dm/',
'Set-Cookie': cookies.join(', '),
},
headers,
});
};
+6 -9
View File
@@ -107,17 +107,14 @@ export const GET: APIRoute = async ({ url, request }) => {
expiresAt,
});
const cookies = [
`${COOKIE_NAME}=${sessionToken}; HttpOnly; SameSite=Strict; Max-Age=604800; Path=/`,
`${VERIFIER_COOKIE_NAME}=; HttpOnly; SameSite=Strict; Max-Age=0; Path=/`,
`oauth_state=; HttpOnly; SameSite=Strict; Max-Age=0; Path=/`,
];
const headers = new Headers();
headers.set('Location', '/dm/');
headers.append('Set-Cookie', `${COOKIE_NAME}=${sessionToken}; HttpOnly; SameSite=Strict; Max-Age=604800; Path=/`);
headers.append('Set-Cookie', `${VERIFIER_COOKIE_NAME}=; HttpOnly; SameSite=Strict; Max-Age=0; Path=/`);
headers.append('Set-Cookie', `oauth_state=; HttpOnly; SameSite=Strict; Max-Age=0; Path=/`);
return new Response(null, {
status: 302,
headers: {
Location: '/dm/',
'Set-Cookie': cookies.join(', '),
},
headers,
});
};
+5 -8
View File
@@ -22,16 +22,13 @@ export const GET: APIRoute = async ({ url }) => {
const redirectUrl = `${vkOAuthConfig.authUrl}?${params.toString()}`;
const cookies = [
`${VERIFIER_COOKIE_NAME}=${encodeURIComponent(verifier)}; HttpOnly; Secure; SameSite=Lax; Max-Age=600; Path=/`,
`oauth_state=${encodeURIComponent(state)}; HttpOnly; Secure; SameSite=Lax; Max-Age=600; Path=/`,
];
const headers = new Headers();
headers.set('Location', redirectUrl);
headers.append('Set-Cookie', `${VERIFIER_COOKIE_NAME}=${encodeURIComponent(verifier)}; HttpOnly; Secure; SameSite=Lax; Max-Age=600; Path=/`);
headers.append('Set-Cookie', `oauth_state=${encodeURIComponent(state)}; HttpOnly; Secure; SameSite=Lax; Max-Age=600; Path=/`);
return new Response(null, {
status: 302,
headers: {
Location: redirectUrl,
'Set-Cookie': cookies.join(', '),
},
headers,
});
};
+5 -8
View File
@@ -22,16 +22,13 @@ export const GET: APIRoute = async ({ url }) => {
const redirectUrl = `${yandexOAuthConfig.authUrl}?${params.toString()}`;
const cookies = [
`${VERIFIER_COOKIE_NAME}=${encodeURIComponent(verifier)}; HttpOnly; Secure; SameSite=Lax; Max-Age=600; Path=/`,
`oauth_state=${encodeURIComponent(state)}; HttpOnly; Secure; SameSite=Lax; Max-Age=600; Path=/`,
];
const headers = new Headers();
headers.set('Location', redirectUrl);
headers.append('Set-Cookie', `${VERIFIER_COOKIE_NAME}=${encodeURIComponent(verifier)}; HttpOnly; Secure; SameSite=Lax; Max-Age=600; Path=/`);
headers.append('Set-Cookie', `oauth_state=${encodeURIComponent(state)}; HttpOnly; Secure; SameSite=Lax; Max-Age=600; Path=/`);
return new Response(null, {
status: 302,
headers: {
Location: redirectUrl,
'Set-Cookie': cookies.join(', '),
},
headers,
});
};