diff options
| author | Adam Mathes <adam@adammathes.com> | 2026-02-14 09:09:10 -0800 |
|---|---|---|
| committer | Adam Mathes <adam@adammathes.com> | 2026-02-14 09:09:10 -0800 |
| commit | ca1418fc0135d52a009ab218d6e24187fb355a3c (patch) | |
| tree | 95f54977609ec401f8439a30e3a158c36a5526bf /frontend/src/utils.ts | |
| parent | a39dfd30529330e3eea44bce865093158eaf2f1b (diff) | |
| download | neko-ca1418fc0135d52a009ab218d6e24187fb355a3c.tar.gz neko-ca1418fc0135d52a009ab218d6e24187fb355a3c.tar.bz2 neko-ca1418fc0135d52a009ab218d6e24187fb355a3c.zip | |
security: implement CSRF protection and improve session cookie security (fixing NK-gfh33y)
Diffstat (limited to 'frontend/src/utils.ts')
| -rw-r--r-- | frontend/src/utils.ts | 31 |
1 files changed, 31 insertions, 0 deletions
diff --git a/frontend/src/utils.ts b/frontend/src/utils.ts new file mode 100644 index 0000000..129ebbb --- /dev/null +++ b/frontend/src/utils.ts @@ -0,0 +1,31 @@ +export function getCookie(name: string): string | undefined { + const value = `; ${document.cookie}`; + const parts = value.split(`; ${name}=`); + if (parts.length === 2) return parts.pop()?.split(';').shift(); +} + +/** + * A wrapper around fetch that automatically includes the CSRF token + * for state-changing requests (POST, PUT, DELETE). + */ +export async function apiFetch(input: RequestInfo | URL, init?: RequestInit): Promise<Response> { + const method = init?.method?.toUpperCase() || 'GET'; + const isStateChanging = ['POST', 'PUT', 'DELETE'].includes(method); + + const headers = new Headers(init?.headers || {}); + + if (isStateChanging) { + const token = getCookie('csrf_token'); + if (token) { + headers.set('X-CSRF-Token', token); + } + } + + // Ensure requests are treated as coming from our own origin if needed, + // but for a same-origin API, standard fetch defaults are usually fine. + + return fetch(input, { + ...init, + headers, + }); +} |
