Files

30 lines
1.5 KiB
TypeScript

// 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 <img> 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<Response> {
return new Response("signing out is a POST", { status: 405, headers: { allow: "POST" } })
}
export async function POST(request: Request): Promise<Response> {
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))
}