makearmy-app/app/api/auth/login/route.ts
2025-10-02 18:41:42 -04:00

82 lines
2.9 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// app/api/auth/login/route.ts
import { NextRequest, NextResponse } from "next/server";
import { emailForUsername, loginDirectus } from "@/lib/directus";
export const runtime = "nodejs";
const secure = process.env.NODE_ENV === "production";
export async function POST(req: NextRequest) {
try {
const body = await req.json().catch(() => ({} as any));
const identifier =
String(body?.identifier ?? body?.email ?? body?.username ?? "").trim();
const password = String(body?.password ?? "").trim();
if (!identifier || !password) {
return NextResponse.json({ error: "Missing credentials" }, { status: 400 });
}
// 1) Try Directus directly with the identifier (email OR username)
// Directus expects the field name "email" for both.
const tryIds: string[] = [identifier];
// 2) Fallback: if it doesnt look like an email, try the canonical email (if any)
if (!identifier.includes("@")) {
try {
const em = await emailForUsername(identifier); // returns string|null
if (em && em !== identifier) tryIds.push(em);
} catch {
// ignore lookup errors, we'll just rely on the first attempt
}
}
let tokens: any = null;
let lastErr: any = null;
for (const id of tryIds) {
try {
tokens = await loginDirectus(id, password); // { access_token, refresh_token, expires? }
if (tokens) break;
} catch (e) {
lastErr = e;
}
}
if (!tokens?.access_token) {
const msg =
lastErr?.response?.data?.errors?.[0]?.message ||
lastErr?.response?.data?.error ||
lastErr?.message ||
"Invalid credentials.";
return NextResponse.json({ error: msg }, { status: 401 });
}
// Set HttpOnly cookies for your middleware
const maxAge = 60 * 60; // 1h
const res = NextResponse.json({ ok: true });
res.cookies.set("ma_at", tokens.access_token, {
path: "/",
httpOnly: true,
sameSite: "lax",
secure,
maxAge,
});
if (tokens.refresh_token) {
res.cookies.set("ma_rt", tokens.refresh_token, {
path: "/",
httpOnly: true,
sameSite: "lax",
secure,
maxAge: 60 * 60 * 24 * 30, // 30d
});
}
return res;
} catch (err: any) {
const message =
err?.response?.data?.errors?.[0]?.message ||
err?.response?.data?.error ||
err?.message ||
"Login failed";
const status = /unauth|invalid|credential/i.test(message) ? 401 : 400;
return NextResponse.json({ error: message }, { status });
}
}