Skip to main content
Glama
alexander-zuev

Kollektiv | Your private LLM knowledgebase

authorize.ts6.65 kB
import {type ConsentFormData, ConsentFormSchema} from "@/web/schemas/consentForm"; // Adjust path import {renderConsentScreen} from "@/web/templates/consent"; import {renderErrorPage} from "@/web/templates/error"; import {renderLoginScreen} from "@/web/templates/login"; import {type AuthFlowContext, AuthFlowError, getValidAuthContext} from "@/web/utils/authContext"; import {clearAuthCookie, loadAuthCookie} from "@/web/utils/cookies"; import {FormValidationError, parseFormData} from "@/web/utils/form"; import {getCurrentUser, getUserSession} from "@/features/auth/utils"; import type {AuthRequest} from "@cloudflare/workers-oauth-provider"; import type {Session, User} from "@supabase/supabase-js"; import type {Context} from "hono"; export const getAuthorizeHandler = async (c: Context) => { let ctx: AuthFlowContext; // 1. Get oauth req console.log("[GET /authorize] Handling request."); try { ctx = await getValidAuthContext(c); } catch (error) { if (error instanceof AuthFlowError) { return renderErrorPage( error.message, "Invalid Authorization Request", c, ` Try the following: 1. Clear your browser cookies 2. Run in terminal: rm -rf ~/.mcp-auth (Mac) 3. Restart your editor (Cursor, Windsurf, etc.) Full steps: https://github.com/alexander-zuev/kollektiv-mcp#connection-troubleshooting `, "Authorization Error", ); } throw error; } // 2. Check user const user: User | null = await getCurrentUser(c); // 3. If no user -> render login screen if (!user) { console.log("[GET /authorize] No User found. Rendering login screen."); return renderLoginScreen(c, ctx.client, ctx.tx); } // 4. If user -> render consent screen console.log(`[GET /authorize] Session found for user ${user.id}. Rendering consent screen.`); // Check that redirect URI belongs to this client ID? or sooner? return renderConsentScreen(c, ctx.oauthReq, ctx.client, user, ctx.tx, ctx.csrfToken); }; export const postAuthorizeHandler = async (c: Context) => { console.log("[POST /authorize] Handling request."); const tx = c.req.query("tx"); if (!tx) { console.error("[POST /authorize] No transaction ID found in the request."); return c.text("Bad Request: Missing cookie transaction id.", 400); } const user = await getCurrentUser(c); if (!user) { console.log("[POST /authorize] No session found. Returning 401 Unauthorized."); return c.text("Unauthorized", 401); } const cookieData = await loadAuthCookie(c, tx); // Validate Cookie Data and Extract OAuth Request if (!cookieData || !cookieData.oauthReq) { console.error("[POST /authorize] Failed to retrieve valid OAuth request from cookie."); clearAuthCookie(c, tx); return c.text("Bad Request: Missing or invalid authorization context.", 400); } // Parse consent form let validatedFormData: ConsentFormData; try { validatedFormData = await parseFormData(c, ConsentFormSchema); const cookieCsrf = cookieData.csrfToken; if (validatedFormData.csrf !== cookieCsrf) { clearAuthCookie(c, tx); return c.text("Forbidden", 403); } console.log( "[POST /authorize] Validated form data:", JSON.stringify(validatedFormData, null, 2), ); } catch (error) { if (error instanceof FormValidationError) { console.error("[POST /authorize] Form validation failed:", error.issues); return c.text(`Bad Request: ${error.message}`, 400); } console.error("[POST /authorize] Error processing form data:", error); return c.text("Internal Server Error: Failed to process request form.", 500); } const oauthReq: AuthRequest = cookieData.oauthReq; // Execute action based on form data if (validatedFormData.action === "deny") { const oauthReq: AuthRequest = cookieData.oauthReq; const {redirectUri, state} = oauthReq; console.log("[POST /authorize] User denied the request via form."); const redirectUrl = new URL(redirectUri); redirectUrl.searchParams.set("error", "access_denied"); // Standard error code for denial if (state) { redirectUrl.searchParams.set("state", state); } const finalRedirectUrl = redirectUrl.toString(); console.log(`[POST /authorize] Redirecting denial to: ${finalRedirectUrl}`); // 3. Perform the redirect return c.redirect(finalRedirectUrl, 302); } // At this time user should be authenticated and we have a valid session let session: Session | null; try { session = await getUserSession(c); } catch (error) { console.error("[POST /authorize] Failed to retrieve user session:", error); return c.text("Internal Server Error: Failed to retrieve user session.", 500); } if (!session) { console.error("[POST /authorize] Failed to retrieve user session."); return c.text("Internal Server Error: Failed to retrieve user session.", 500); } try { console.log(`[POST /authorize] Completing authorization for user ${user.id}.`); const {redirectTo} = await c.env.OAUTH_PROVIDER.completeAuthorization({ request: oauthReq, userId: user.id, metadata: {email: user.email}, scope: oauthReq.scope, // Pass the parsed scope array props: {userId: user.id, email: user.email, accessToken: session.access_token}, }); console.log(`[POST /authorize] Redirecting approval to: ${redirectTo}`); clearAuthCookie(c, tx); return c.redirect(redirectTo, 302); } catch (error) { console.error("[POST /authorize] Error during completeAuthorization:", error); clearAuthCookie(c, tx); // Attempt to redirect with error, using details from the cookie's oauthReq const {redirectUri, state} = oauthReq; if (redirectUri) { try { const errorRedirectUrl = new URL(redirectUri); errorRedirectUrl.searchParams.set("error", "server_error"); if (state) errorRedirectUrl.searchParams.set("state", state); return c.redirect(errorRedirectUrl.toString(), 302); } catch (e) { } } // Fallback generic error page return c.html("<h1>Server Error</h1><p>Could not complete authorization.</p>", 500); } };

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/alexander-zuev/kollektiv-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server