chore: convert submodules to standard directories for true monorepo structure
This commit is contained in:
56
vibn-frontend/app/api/integrations/github/connect/route.ts
Normal file
56
vibn-frontend/app/api/integrations/github/connect/route.ts
Normal file
@@ -0,0 +1,56 @@
|
||||
/**
|
||||
* GET /api/integrations/github/connect
|
||||
*
|
||||
* Kicks off GitHub OAuth. Generates an unguessable `state`, stores it
|
||||
* in a short-lived (10 min) httpOnly cookie, and 302s to GitHub's
|
||||
* authorize endpoint.
|
||||
*
|
||||
* The callback route validates the cookie matches the `state` GitHub
|
||||
* echoes back, defending against login-CSRF.
|
||||
*/
|
||||
|
||||
import { NextResponse } from "next/server";
|
||||
import { randomBytes } from "crypto";
|
||||
import { authSession } from "@/lib/auth/session-server";
|
||||
import {
|
||||
buildAuthorizeUrl, isGithubOauthConfigured,
|
||||
} from "@/lib/integrations/github";
|
||||
|
||||
const STATE_COOKIE = "gh_oauth_state";
|
||||
const STATE_TTL_S = 10 * 60;
|
||||
|
||||
export async function GET(req: Request) {
|
||||
if (!isGithubOauthConfigured()) {
|
||||
return NextResponse.json(
|
||||
{ error: "GitHub OAuth is not configured on this server." },
|
||||
{ status: 503 },
|
||||
);
|
||||
}
|
||||
|
||||
const session = await authSession();
|
||||
if (!session?.user?.email) {
|
||||
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
|
||||
}
|
||||
|
||||
const url = new URL(req.url);
|
||||
// Use NEXTAUTH_URL when available — behind a proxy req.url.origin
|
||||
// resolves to the internal bind address (0.0.0.0) rather than the
|
||||
// public hostname, which GitHub then rejects as an unregistered URI.
|
||||
const appOrigin = (process.env.NEXTAUTH_URL ?? url.origin).replace(/\/$/, "");
|
||||
const callbackUrl = `${appOrigin}/api/integrations/github/callback`;
|
||||
const returnTo = url.searchParams.get("returnTo") ?? "/";
|
||||
|
||||
const state = randomBytes(16).toString("hex");
|
||||
const statePayload = `${state}:${returnTo}`;
|
||||
|
||||
const authorize = buildAuthorizeUrl(state, callbackUrl);
|
||||
const res = NextResponse.redirect(authorize);
|
||||
res.cookies.set(STATE_COOKIE, statePayload, {
|
||||
httpOnly: true,
|
||||
sameSite: "lax",
|
||||
path: "/",
|
||||
secure: url.protocol === "https:",
|
||||
maxAge: STATE_TTL_S,
|
||||
});
|
||||
return res;
|
||||
}
|
||||
Reference in New Issue
Block a user