1
0
Fork 0
mirror of https://github.com/seanmorley15/AdventureLog.git synced 2025-07-27 16:59:37 +02:00

feat: enhance CSRF token handling and add format=json to API requests

This commit is contained in:
Sean Morley 2025-01-06 14:49:23 -05:00
parent 128c33d9a1
commit 59b41c01df
3 changed files with 64 additions and 32 deletions

View file

@ -12,23 +12,23 @@ export async function GET(event) {
/** @type {import('./$types').RequestHandler} */ /** @type {import('./$types').RequestHandler} */
export async function POST({ url, params, request, fetch, cookies }) { export async function POST({ url, params, request, fetch, cookies }) {
const searchParam = url.search ? `${url.search}` : ''; const searchParam = url.search ? `${url.search}&format=json` : '?format=json';
return handleRequest(url, params, request, fetch, cookies, searchParam, false); return handleRequest(url, params, request, fetch, cookies, searchParam, true);
} }
export async function PATCH({ url, params, request, fetch, cookies }) { export async function PATCH({ url, params, request, fetch, cookies }) {
const searchParam = url.search ? `${url.search}` : ''; const searchParam = url.search ? `${url.search}&format=json` : '?format=json';
return handleRequest(url, params, request, fetch, cookies, searchParam, false); return handleRequest(url, params, request, fetch, cookies, searchParam, true);
} }
export async function PUT({ url, params, request, fetch, cookies }) { export async function PUT({ url, params, request, fetch, cookies }) {
const searchParam = url.search ? `${url.search}` : ''; const searchParam = url.search ? `${url.search}&format=json` : '?format=json';
return handleRequest(url, params, request, fetch, cookies, searchParam, false); return handleRequest(url, params, request, fetch, cookies, searchParam, true);
} }
export async function DELETE({ url, params, request, fetch, cookies }) { export async function DELETE({ url, params, request, fetch, cookies }) {
const searchParam = url.search ? `${url.search}` : ''; const searchParam = url.search ? `${url.search}&format=json` : '?format=json';
return handleRequest(url, params, request, fetch, cookies, searchParam, false); return handleRequest(url, params, request, fetch, cookies, searchParam, true);
} }
async function handleRequest( async function handleRequest(
@ -53,18 +53,25 @@ async function handleRequest(
const headers = new Headers(request.headers); const headers = new Headers(request.headers);
// Delete existing csrf cookie by setting an expired date
cookies.delete('csrftoken', { path: '/' });
// Generate a new csrf token (using your existing fetchCSRFToken function)
const csrfToken = await fetchCSRFToken(); const csrfToken = await fetchCSRFToken();
if (!csrfToken) { if (!csrfToken) {
return json({ error: 'CSRF token is missing or invalid' }, { status: 400 }); return json({ error: 'CSRF token is missing or invalid' }, { status: 400 });
} }
// Set the new csrf token in both headers and cookies
const cookieHeader = `csrftoken=${csrfToken}; Path=/; HttpOnly; SameSite=Lax`;
try { try {
const response = await fetch(targetUrl, { const response = await fetch(targetUrl, {
method: request.method, method: request.method,
headers: { headers: {
...Object.fromEntries(headers), ...Object.fromEntries(headers),
'X-CSRFToken': csrfToken, 'X-CSRFToken': csrfToken,
Cookie: `csrftoken=${csrfToken}` Cookie: cookieHeader
}, },
body: body:
request.method !== 'GET' && request.method !== 'HEAD' ? await request.text() : undefined, request.method !== 'GET' && request.method !== 'HEAD' ? await request.text() : undefined,

View file

@ -53,18 +53,25 @@ async function handleRequest(
const headers = new Headers(request.headers); const headers = new Headers(request.headers);
// Delete existing csrf cookie by setting an expired date
cookies.delete('csrftoken', { path: '/' });
// Generate a new csrf token (using your existing fetchCSRFToken function)
const csrfToken = await fetchCSRFToken(); const csrfToken = await fetchCSRFToken();
if (!csrfToken) { if (!csrfToken) {
return json({ error: 'CSRF token is missing or invalid' }, { status: 400 }); return json({ error: 'CSRF token is missing or invalid' }, { status: 400 });
} }
// Set the new csrf token in both headers and cookies
const cookieHeader = `csrftoken=${csrfToken}; Path=/; HttpOnly; SameSite=Lax`;
try { try {
const response = await fetch(targetUrl, { const response = await fetch(targetUrl, {
method: request.method, method: request.method,
headers: { headers: {
...Object.fromEntries(headers), ...Object.fromEntries(headers),
'X-CSRFToken': csrfToken, 'X-CSRFToken': csrfToken,
Cookie: `csrftoken=${csrfToken}` Cookie: cookieHeader
}, },
body: body:
request.method !== 'GET' && request.method !== 'HEAD' ? await request.text() : undefined, request.method !== 'GET' && request.method !== 'HEAD' ? await request.text() : undefined,

View file

@ -1,69 +1,84 @@
const PUBLIC_SERVER_URL = process.env['PUBLIC_SERVER_URL']; const PUBLIC_SERVER_URL = process.env['PUBLIC_SERVER_URL'];
const endpoint = PUBLIC_SERVER_URL || 'http://localhost:8000'; const endpoint = PUBLIC_SERVER_URL || 'http://localhost:8000';
import { fetchCSRFToken } from '$lib/index.server';
import { json } from '@sveltejs/kit'; import { json } from '@sveltejs/kit';
/** @type {import('./$types').RequestHandler} */ /** @type {import('./$types').RequestHandler} */
export async function GET({ url, params, request, fetch, cookies }) { export async function GET(event) {
// add the param format = json to the url or add additional if anothre param is already present const { url, params, request, fetch, cookies } = event;
if (url.search) { const searchParam = url.search ? `${url.search}&format=json` : '?format=json';
url.search = url.search + '&format=json'; return handleRequest(url, params, request, fetch, cookies, searchParam);
} else {
url.search = '?format=json';
}
return handleRequest(url, params, request, fetch, cookies);
} }
/** @type {import('./$types').RequestHandler} */ /** @type {import('./$types').RequestHandler} */
export async function POST({ url, params, request, fetch, cookies }) { export async function POST({ url, params, request, fetch, cookies }) {
return handleRequest(url, params, request, fetch, cookies, true); const searchParam = url.search ? `${url.search}&format=json` : '?format=json';
return handleRequest(url, params, request, fetch, cookies, searchParam, true);
} }
export async function PATCH({ url, params, request, fetch, cookies }) { export async function PATCH({ url, params, request, fetch, cookies }) {
return handleRequest(url, params, request, fetch, cookies, true); const searchParam = url.search ? `${url.search}&format=json` : '?format=json';
return handleRequest(url, params, request, fetch, cookies, searchParam, true);
} }
export async function PUT({ url, params, request, fetch, cookies }) { export async function PUT({ url, params, request, fetch, cookies }) {
return handleRequest(url, params, request, fetch, cookies, true); const searchParam = url.search ? `${url.search}&format=json` : '?format=json';
return handleRequest(url, params, request, fetch, cookies, searchParam, true);
} }
export async function DELETE({ url, params, request, fetch, cookies }) { export async function DELETE({ url, params, request, fetch, cookies }) {
return handleRequest(url, params, request, fetch, cookies, true); const searchParam = url.search ? `${url.search}&format=json` : '?format=json';
return handleRequest(url, params, request, fetch, cookies, searchParam, true);
} }
// Implement other HTTP methods as needed (PUT, DELETE, etc.)
async function handleRequest( async function handleRequest(
url: any, url: any,
params: any, params: any,
request: any, request: any,
fetch: any, fetch: any,
cookies: any, cookies: any,
searchParam: string,
requreTrailingSlash: boolean | undefined = false requreTrailingSlash: boolean | undefined = false
) { ) {
const path = params.path; const path = params.path;
let targetUrl = `${endpoint}/auth/${path}${url.search}`; let targetUrl = `${endpoint}/auth/${path}`;
// Ensure the path ends with a trailing slash
if (requreTrailingSlash && !targetUrl.endsWith('/')) { if (requreTrailingSlash && !targetUrl.endsWith('/')) {
targetUrl += '/'; targetUrl += '/';
} }
// Append query parameters to the path correctly
targetUrl += searchParam; // This will add ?format=json or &format=json to the URL
const headers = new Headers(request.headers); const headers = new Headers(request.headers);
const authCookie = cookies.get('auth'); // Delete existing csrf cookie by setting an expired date
cookies.delete('csrftoken', { path: '/' });
if (authCookie) { // Generate a new csrf token (using your existing fetchCSRFToken function)
headers.set('Cookie', `${authCookie}`); const csrfToken = await fetchCSRFToken();
if (!csrfToken) {
return json({ error: 'CSRF token is missing or invalid' }, { status: 400 });
} }
// Set the new csrf token in both headers and cookies
const cookieHeader = `csrftoken=${csrfToken}; Path=/; HttpOnly; SameSite=Lax`;
try { try {
const response = await fetch(targetUrl, { const response = await fetch(targetUrl, {
method: request.method, method: request.method,
headers: headers, headers: {
body: request.method !== 'GET' && request.method !== 'HEAD' ? await request.text() : undefined ...Object.fromEntries(headers),
'X-CSRFToken': csrfToken,
Cookie: cookieHeader
},
body:
request.method !== 'GET' && request.method !== 'HEAD' ? await request.text() : undefined,
credentials: 'include' // This line ensures cookies are sent with the request
}); });
if (response.status === 204) { if (response.status === 204) {
// For 204 No Content, return a response with no body
return new Response(null, { return new Response(null, {
status: 204, status: 204,
headers: response.headers headers: response.headers
@ -71,10 +86,13 @@ async function handleRequest(
} }
const responseData = await response.text(); const responseData = await response.text();
// Create a new Headers object without the 'set-cookie' header
const cleanHeaders = new Headers(response.headers);
cleanHeaders.delete('set-cookie');
return new Response(responseData, { return new Response(responseData, {
status: response.status, status: response.status,
headers: response.headers headers: cleanHeaders
}); });
} catch (error) { } catch (error) {
console.error('Error forwarding request:', error); console.error('Error forwarding request:', error);