// SPDX-License-Identifier: LicenseRef-ConusAI-Template-1.0 // POST /auth/sign-out: revokes the session row and redirects to the provider's end-session // endpoint, which sends the browser to /auth/signed-out. // // POST, with the fetch-metadata half of csrf.ts's check: revoking a session is a state change, so // it must not hang on a GET, which a prefetch, a crawler or an fires unprompted, and a // cross-site form POST is refused the same way the API refuses one. The synchronizer token itself // cannot be checked here -- a plain HTML form cannot send a header -- so the metadata a browser // always sends is the check. import { authRoutes } from "../../../src/server/app" import { authResponse } from "../../../src/server/auth-response" import { betterAuthSignOut } from "../../../src/server/better-auth-session" // kit:convex-better-auth export const dynamic = "force-dynamic" export const runtime = "nodejs" export async function GET(): Promise { return new Response("signing out is a POST", { status: 405, headers: { allow: "POST" } }) } export async function POST(request: Request): Promise { const site = request.headers.get("sec-fetch-site") if (site !== null && site !== "same-origin" && site !== "none") { return new Response("a cross-site sign-out is refused", { status: 403 }) } const betterAuth = await betterAuthSignOut(request) // kit:convex-better-auth if (betterAuth) return betterAuth // kit:convex-better-auth return authResponse(request, async () => (await authRoutes()).signOut(request)) }