66 lines
2.5 KiB
TypeScript
66 lines
2.5 KiB
TypeScript
import { NextRequest, NextResponse } from "next/server";
|
|
import { authClient } from "@/lib/supabase";
|
|
import { requestOrigin } from "@/lib/request-origin";
|
|
import { authDestination } from "@/shared/account";
|
|
import { createRecoveryGrant, recoveryCookie } from "@/lib/password-recovery";
|
|
import { accountProfile } from "@/lib/profile";
|
|
export async function GET(request: NextRequest) {
|
|
const origin = requestOrigin(request, process.env.MINEGEO_URL);
|
|
const code = request.nextUrl.searchParams.get("code");
|
|
const tokenHash = request.nextUrl.searchParams.get("token_hash");
|
|
const legacyToken = request.nextUrl.searchParams.get("legacy_recovery_token");
|
|
const type = request.nextUrl.searchParams.get("type");
|
|
const next = authDestination(request.nextUrl.searchParams.get("next"));
|
|
if (
|
|
code ||
|
|
legacyToken ||
|
|
(tokenHash &&
|
|
(type === "email" || type === "recovery" || type === "magiclink"))
|
|
) {
|
|
const client = await authClient();
|
|
let { data, error } = code
|
|
? await client.auth.exchangeCodeForSession(code)
|
|
: legacyToken
|
|
? await client.auth.exchangeCodeForSession(legacyToken)
|
|
: await client.auth.verifyOtp({
|
|
token_hash: tokenHash!,
|
|
type: type as "email" | "recovery" | "magiclink",
|
|
});
|
|
// Older email templates could place a recovery token hash in /code=...
|
|
// instead of a PKCE code. Only Supabase can decide whether it is valid.
|
|
if (legacyToken && error)
|
|
({ data, error } = await client.auth.verifyOtp({
|
|
token_hash: legacyToken,
|
|
type: "recovery",
|
|
}));
|
|
if (!error && data.user) {
|
|
await accountProfile(data.user);
|
|
const destination =
|
|
type === "recovery" || legacyToken ? "/auth/reset-password" : next;
|
|
const response = NextResponse.redirect(new URL(destination, origin));
|
|
if (destination === "/auth/reset-password") {
|
|
const { data: claims } = await client.auth.getClaims();
|
|
const sessionId = claims?.claims.session_id;
|
|
if (typeof sessionId === "string")
|
|
response.cookies.set(
|
|
recoveryCookie,
|
|
createRecoveryGrant(
|
|
data.user.id,
|
|
sessionId,
|
|
process.env.SUPABASE_SECRET_KEY!,
|
|
),
|
|
{
|
|
httpOnly: true,
|
|
sameSite: "lax",
|
|
secure: new URL(origin).protocol === "https:",
|
|
path: "/",
|
|
maxAge: 600,
|
|
},
|
|
);
|
|
}
|
|
return response;
|
|
}
|
|
}
|
|
return NextResponse.redirect(new URL("/log-in?auth=failed", origin));
|
|
}
|