From d6eb6d3ad2d74d93b59661c16fa7c525986ec42a Mon Sep 17 00:00:00 2001 From: Frederic Cabassut Date: Tue, 10 Mar 2026 00:08:37 +0100 Subject: [PATCH] feat: extend API key auth to all API endpoints Bearer token authentication now works on all /api/* routes, not just /api/mcp. If a Bearer token is present it's validated first; otherwise session cookie auth is used as fallback. Updates settings UI to reflect the broader scope (tab renamed to "API", REST API curl example added) and updates the landing page feature card. Co-Authored-By: Claude Opus 4.6 --- CLAUDE.md | 4 ++ src/hooks.server.ts | 43 ++++++++++------------ src/routes/(app)/settings/+layout.svelte | 2 +- src/routes/(app)/settings/mcp/+page.svelte | 12 +++++- website/index.html | 4 +- 5 files changed, 37 insertions(+), 28 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index b8767ea..089eac8 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -98,6 +98,10 @@ tests/ unit/ # Vitest unit tests e2e/ # Playwright e2e tests (Gherkin-style) helpers/fixtures.ts # Shared authenticatedPage fixture +website/ # Static landing page (crumbs.bretzel.app) + index.html # Landing page with feature cards, screenshots, deploy section + styles.css # Landing page styles (retro parchment theme) + assets/ # Favicon, screenshots ``` ## Commands diff --git a/src/hooks.server.ts b/src/hooks.server.ts index 5a44334..bcad068 100644 --- a/src/hooks.server.ts +++ b/src/hooks.server.ts @@ -22,36 +22,31 @@ export const handle: Handle = async ({ event, resolve }) => { return resolve(event); } - // MCP endpoint: authenticate via Bearer token (API key) - if (pathname.startsWith('/api/mcp')) { + // API routes: authenticate via Bearer token if present + if (pathname.startsWith('/api/')) { const authHeader = event.request.headers.get('authorization'); const token = authHeader?.startsWith('Bearer ') ? authHeader.slice(7) : null; - if (!token) { - return new Response(JSON.stringify({ error: 'Unauthorized' }), { - status: 401, - headers: { 'Content-Type': 'application/json' } - }); - } + if (token) { + const { valid, userId } = validateApiKey(token); + if (!valid || !userId) { + return new Response(JSON.stringify({ error: 'Unauthorized' }), { + status: 401, + headers: { 'Content-Type': 'application/json' } + }); + } - const { valid, userId } = validateApiKey(token); - if (!valid || !userId) { - return new Response(JSON.stringify({ error: 'Unauthorized' }), { - status: 401, - headers: { 'Content-Type': 'application/json' } - }); - } + const user = getUserForApiKey(userId); + if (!user) { + return new Response(JSON.stringify({ error: 'Unauthorized' }), { + status: 401, + headers: { 'Content-Type': 'application/json' } + }); + } - const user = getUserForApiKey(userId); - if (!user) { - return new Response(JSON.stringify({ error: 'Unauthorized' }), { - status: 401, - headers: { 'Content-Type': 'application/json' } - }); + event.locals.user = user; + return resolve(event); } - - event.locals.user = user; - return resolve(event); } // Check if setup is complete diff --git a/src/routes/(app)/settings/+layout.svelte b/src/routes/(app)/settings/+layout.svelte index 8f6e89f..51174eb 100644 --- a/src/routes/(app)/settings/+layout.svelte +++ b/src/routes/(app)/settings/+layout.svelte @@ -32,7 +32,7 @@ class="flex items-center gap-2 rounded-sm px-3 py-2 text-sm whitespace-nowrap transition-colors {pathname === '/settings/mcp' ? 'bg-[var(--primary)]/15 text-[var(--primary)] font-medium' : 'text-[var(--text)] hover:bg-[var(--bg-base)]'}" > - MCP Server + API {#if data.user?.role === 'admin'} diff --git a/src/routes/(app)/settings/mcp/+page.svelte b/src/routes/(app)/settings/mcp/+page.svelte index f38d018..a3db93d 100644 --- a/src/routes/(app)/settings/mcp/+page.svelte +++ b/src/routes/(app)/settings/mcp/+page.svelte @@ -122,7 +122,7 @@ ${mcpJsonConfig}`);

API Keys

- API keys allow external tools (like Claude Code) to access your notes via the MCP protocol. + API keys allow external tools to access your notes via the MCP protocol and the REST API.

@@ -229,6 +229,16 @@ ${mcpJsonConfig}`); {/if} + +
+

REST API

+

+ Use your API key to authenticate requests to any /api/* endpoint: +

+
curl -H "Authorization: Bearer {activeApiKey}" \
+  {baseUrl}/api/notes
+
+

Client Configuration

diff --git a/website/index.html b/website/index.html index 495e71b..f203c13 100644 --- a/website/index.html +++ b/website/index.html @@ -145,8 +145,8 @@
-

MCP Server

-

Built-in AI integration. Connect Claude, Cursor, or any MCP client to read and write your notes.

+

API & MCP

+

Full REST API with token auth. Integrate with n8n, Zapier, or scripts. Built-in MCP server for AI tools like Claude and Cursor.