From d31c07cba531c93c060102dd52fb301afd066b1e Mon Sep 17 00:00:00 2001 From: druppelt <44848632+druppelt@users.noreply.github.com> Date: Sat, 18 Apr 2026 10:08:46 +0200 Subject: [PATCH] refactor: auth header extraction for token validation a previous commit (e11c4a1) fixed an issue for ollama where a Bearer prefix was removed even if not present. This commit applies the logic of that fix to all apis. Refs: #158 --- src/middleware.ts | 79 ++++++++++++++++++++++++----------------------- 1 file changed, 41 insertions(+), 38 deletions(-) diff --git a/src/middleware.ts b/src/middleware.ts index ebde26fa..72850693 100644 --- a/src/middleware.ts +++ b/src/middleware.ts @@ -49,6 +49,13 @@ const ERRORS = { }, }; +function extractAuthorization(request: NextRequest) { + const authorization = request.headers.get("authorization") || ""; + return authorization.startsWith("Bearer ") + ? authorization.substring(7) + : authorization; +} + export async function middleware(request: NextRequest) { if (NODE_ENV === "production") console.debug(request); @@ -128,11 +135,11 @@ export async function middleware(request: NextRequest) { } } if (request.nextUrl.pathname.startsWith("/api/ai/openrouter")) { - const authorization = request.headers.get("authorization") || ""; + const authorization = extractAuthorization(request); const isDisabledModel = await hasDisabledAIModel(); if ( !verifySignature( - authorization.substring(7), + authorization, accessPassword, Date.now(), ) || @@ -168,11 +175,11 @@ export async function middleware(request: NextRequest) { } } if (request.nextUrl.pathname.startsWith("/api/ai/openaicompatible")) { - const authorization = request.headers.get("authorization") || ""; + const authorization = extractAuthorization(request); const isDisabledModel = await hasDisabledAIModel(); if ( !verifySignature( - authorization.substring(7), + authorization, accessPassword, Date.now(), ) || @@ -208,11 +215,11 @@ export async function middleware(request: NextRequest) { } } if (request.nextUrl.pathname.startsWith("/api/ai/openai")) { - const authorization = request.headers.get("authorization") || ""; + const authorization = extractAuthorization(request); const isDisabledModel = await hasDisabledAIModel(); if ( !verifySignature( - authorization.substring(7), + authorization, accessPassword, Date.now(), ) || @@ -288,11 +295,11 @@ export async function middleware(request: NextRequest) { } } if (request.nextUrl.pathname.startsWith("/api/ai/deepseek")) { - const authorization = request.headers.get("authorization") || ""; + const authorization = extractAuthorization(request); const isDisabledModel = await hasDisabledAIModel(); if ( !verifySignature( - authorization.substring(7), + authorization, accessPassword, Date.now(), ) || @@ -328,11 +335,11 @@ export async function middleware(request: NextRequest) { } } if (request.nextUrl.pathname.startsWith("/api/ai/xai")) { - const authorization = request.headers.get("authorization") || ""; + const authorization = extractAuthorization(request); const isDisabledModel = await hasDisabledAIModel(); if ( !verifySignature( - authorization.substring(7), + authorization, accessPassword, Date.now(), ) || @@ -368,11 +375,11 @@ export async function middleware(request: NextRequest) { } } if (request.nextUrl.pathname.startsWith("/api/ai/mistral")) { - const authorization = request.headers.get("authorization") || ""; + const authorization = extractAuthorization(request); const isDisabledModel = await hasDisabledAIModel(); if ( !verifySignature( - authorization.substring(7), + authorization, accessPassword, Date.now(), ) || @@ -444,11 +451,11 @@ export async function middleware(request: NextRequest) { } } if (request.nextUrl.pathname.startsWith("/api/ai/google-vertex")) { - const authorization = request.headers.get("authorization") || ""; + const authorization = extractAuthorization(request); const isDisabledModel = await hasDisabledAIModel(); if ( !verifySignature( - authorization.substring(7), + authorization, accessPassword, Date.now(), ) || @@ -490,11 +497,11 @@ export async function middleware(request: NextRequest) { } // The pollinations model only verifies access to the backend API if (request.nextUrl.pathname.startsWith("/api/ai/pollinations")) { - const authorization = request.headers.get("authorization") || ""; + const authorization = extractAuthorization(request); const isDisabledModel = await hasDisabledAIModel(); if ( !verifySignature( - authorization.substring(7), + authorization, accessPassword, Date.now(), ) || @@ -520,13 +527,11 @@ export async function middleware(request: NextRequest) { } // The ollama model only verifies access to the backend API if (request.nextUrl.pathname.startsWith("/api/ai/ollama")) { - const authorization = request.headers.get("authorization") || ""; + const authorization = extractAuthorization(request); const isDisabledModel = await hasDisabledAIModel(); if ( !verifySignature( - authorization.startsWith("Bearer ") - ? authorization.substring(7) - : authorization, + authorization, accessPassword, Date.now(), ) || @@ -551,11 +556,11 @@ export async function middleware(request: NextRequest) { } } if (request.nextUrl.pathname.startsWith("/api/search/tavily")) { - const authorization = request.headers.get("authorization") || ""; + const authorization = extractAuthorization(request); if ( request.method.toUpperCase() !== "POST" || !verifySignature( - authorization.substring(7), + authorization, accessPassword, Date.now(), ) || @@ -590,11 +595,11 @@ export async function middleware(request: NextRequest) { } } if (request.nextUrl.pathname.startsWith("/api/search/firecrawl")) { - const authorization = request.headers.get("authorization") || ""; + const authorization = extractAuthorization(request); if ( request.method.toUpperCase() !== "POST" || !verifySignature( - authorization.substring(7), + authorization, accessPassword, Date.now(), ) || @@ -629,11 +634,11 @@ export async function middleware(request: NextRequest) { } } if (request.nextUrl.pathname.startsWith("/api/search/exa")) { - const authorization = request.headers.get("authorization") || ""; + const authorization = extractAuthorization(request); if ( request.method.toUpperCase() !== "POST" || !verifySignature( - authorization.substring(7), + authorization, accessPassword, Date.now(), ) || @@ -668,11 +673,11 @@ export async function middleware(request: NextRequest) { } } if (request.nextUrl.pathname.startsWith("/api/search/bocha")) { - const authorization = request.headers.get("authorization") || ""; + const authorization = extractAuthorization(request); if ( request.method.toUpperCase() !== "POST" || !verifySignature( - authorization.substring(7), + authorization, accessPassword, Date.now(), ) || @@ -707,11 +712,11 @@ export async function middleware(request: NextRequest) { } } if (request.nextUrl.pathname.startsWith("/api/search/searxng")) { - const authorization = request.headers.get("authorization") || ""; + const authorization = extractAuthorization(request); if ( request.method.toUpperCase() !== "POST" || !verifySignature( - authorization.substring(7), + authorization, accessPassword, Date.now(), ) || @@ -736,10 +741,10 @@ export async function middleware(request: NextRequest) { } } if (request.nextUrl.pathname.startsWith("/api/crawler")) { - const authorization = request.headers.get("authorization") || ""; + const authorization = extractAuthorization(request); if ( request.method.toUpperCase() !== "POST" || - !verifySignature(authorization.substring(7), accessPassword, Date.now()) + !verifySignature(authorization, accessPassword, Date.now()) ) { return NextResponse.json( { error: ERRORS.NO_PERMISSIONS }, @@ -760,10 +765,8 @@ export async function middleware(request: NextRequest) { } } if (request.nextUrl.pathname.startsWith("/api/sse")) { - let authorization = request.headers.get("authorization") || ""; - if (authorization !== "") { - authorization = authorization.substring(7); - } else if (request.method.toUpperCase() === "GET") { + let authorization = extractAuthorization(request); + if (authorization == "" && request.method.toUpperCase() === "GET") { authorization = request.nextUrl.searchParams.get("password") || ""; } if (authorization !== accessPassword) { @@ -786,8 +789,8 @@ export async function middleware(request: NextRequest) { } } if (request.nextUrl.pathname.startsWith("/api/mcp")) { - const authorization = request.headers.get("authorization") || ""; - if (authorization.substring(7) !== accessPassword) { + const authorization = extractAuthorization(request); + if (authorization !== accessPassword) { const responseHeaders = new Headers(); responseHeaders.set("WWW-Authenticate", ERRORS.NO_PERMISSIONS.message); return NextResponse.json(