mirror of
https://github.com/tiennm99/llmapikey.git
synced 2026-07-18 18:18:32 +00:00
- Next.js 15 App Router (JS+JSDoc): landing, auth-gated dashboard, docs - GitHub OAuth via Supabase; identity anchored on numeric provider_id - key provisioning: reserve-then-mint-persist-compensate, one key per account - api_keys in unexposed llmapikey schema via direct Postgres; RLS deny-all - live minting gated behind PROVISIONING_ENABLED; Vercel auto-deploy disabled - unit tests (mask, request-body), RLS deny-all test, reconcile script
36 lines
1019 B
JavaScript
36 lines
1019 B
JavaScript
import { NextResponse } from "next/server";
|
|
|
|
import { createServerAuthClient } from "@/lib/supabase/server-client";
|
|
|
|
/**
|
|
* OAuth callback: exchange the GitHub auth code for a Supabase session cookie,
|
|
* then redirect to `next` (default /dashboard).
|
|
*
|
|
* @param {Request} request
|
|
*/
|
|
export async function GET(request) {
|
|
const { searchParams, origin } = new URL(request.url);
|
|
const code = searchParams.get("code");
|
|
const next = sanitizeNext(searchParams.get("next"));
|
|
|
|
if (code) {
|
|
const supabase = await createServerAuthClient();
|
|
const { error } = await supabase.auth.exchangeCodeForSession(code);
|
|
if (!error) {
|
|
return NextResponse.redirect(`${origin}${next}`);
|
|
}
|
|
}
|
|
return NextResponse.redirect(`${origin}/?auth_error=1`);
|
|
}
|
|
|
|
/**
|
|
* Only allow same-origin relative paths to avoid open-redirect.
|
|
*
|
|
* @param {string | null} next
|
|
* @returns {string}
|
|
*/
|
|
function sanitizeNext(next) {
|
|
if (next && next.startsWith("/") && !next.startsWith("//")) return next;
|
|
return "/dashboard";
|
|
}
|