From ea7da85d5e5efbb7478cf896d50e362b8b70d53f Mon Sep 17 00:00:00 2001 From: ilia Date: Sun, 4 Jan 2026 12:10:10 -0500 Subject: [PATCH] feat: Implement session debugging and cookie management in API - Added a new API route for session management that retrieves session information and cookie data. - Enhanced error handling to provide detailed error messages in case of failures. - Updated login page to support callback URLs for redirection after successful login. - Introduced debug logging for session creation and token validation in non-production environments. --- app/api/debug/session/route.ts | 51 ++++++++++++++++++++++++++++++++++ app/login/page.tsx | 12 ++++++-- lib/auth.ts | 35 +++++++++++++++++++++-- 3 files changed, 94 insertions(+), 4 deletions(-) create mode 100644 app/api/debug/session/route.ts diff --git a/app/api/debug/session/route.ts b/app/api/debug/session/route.ts new file mode 100644 index 0000000..83572fb --- /dev/null +++ b/app/api/debug/session/route.ts @@ -0,0 +1,51 @@ +import { auth } from "@/lib/auth" +import { NextResponse } from "next/server" +import { cookies } from "next/headers" + +export async function GET(request: Request) { + try { + const session = await auth() + const cookieStore = await cookies() + const cookieHeader = request.headers.get("cookie") || "" + + // Parse cookies from header + const cookieMap: Record = {} + cookieHeader.split(";").forEach(cookie => { + const [key, value] = cookie.trim().split("=") + if (key && value) { + cookieMap[key] = decodeURIComponent(value) + } + }) + + const sessionToken = cookieStore.get("__Secure-authjs.session-token")?.value || + cookieMap["__Secure-authjs.session-token"] || + "NOT FOUND" + + return NextResponse.json({ + hasSession: !!session, + session: session ? { + user: session.user, + expires: session.expires, + } : null, + cookies: { + sessionTokenPresent: !!sessionToken && sessionToken !== "NOT FOUND", + sessionTokenPreview: sessionToken !== "NOT FOUND" ? `${sessionToken.substring(0, 20)}...` : "NOT FOUND", + allCookieKeys: Object.keys(cookieMap), + cookieHeaderLength: cookieHeader.length, + }, + env: { + hasSecret: !!process.env.NEXTAUTH_SECRET, + nextAuthUrl: process.env.NEXTAUTH_URL, + nodeEnv: process.env.NODE_ENV, + authTrustHost: process.env.AUTH_TRUST_HOST, + secretLength: process.env.NEXTAUTH_SECRET?.length || 0, + secretPreview: process.env.NEXTAUTH_SECRET ? `${process.env.NEXTAUTH_SECRET.substring(0, 10)}...` : "missing", + } + }) + } catch (error) { + return NextResponse.json({ + error: error instanceof Error ? error.message : "Unknown error", + stack: error instanceof Error ? error.stack : undefined + }, { status: 500 }) + } +} diff --git a/app/login/page.tsx b/app/login/page.tsx index 3031902..92147e6 100644 --- a/app/login/page.tsx +++ b/app/login/page.tsx @@ -23,11 +23,19 @@ export default function LoginPage() { redirect: false, }) + console.log("Sign in result:", { result, error: result?.error, ok: result?.ok, url: result?.url }) + if (result?.error) { setError("Invalid email or password") - } else { - router.push("/photos") + } else if (result?.ok) { + // Check if there's a callback URL in the query params + const params = new URLSearchParams(window.location.search) + const callbackUrl = params.get("callbackUrl") || "/photos" + console.log("Redirecting to:", callbackUrl) + router.push(callbackUrl) router.refresh() + } else { + setError("Login failed. Please try again.") } } catch { setError("An error occurred. Please try again.") diff --git a/lib/auth.ts b/lib/auth.ts index 872c99b..c1e3439 100644 --- a/lib/auth.ts +++ b/lib/auth.ts @@ -10,6 +10,7 @@ if (!nextAuthSecret) { export const { handlers, auth, signIn, signOut } = NextAuth({ trustHost: true, + debug: process.env.NODE_ENV !== "production", providers: [ Credentials({ name: "Credentials", @@ -66,6 +67,10 @@ export const { handlers, auth, signIn, signOut } = NextAuth({ async session({ session, token }) { // Always ensure session.user exists when token exists if (token && (token.id || token.email)) { + // Ensure session.user is always an object + if (!session.user) { + session.user = {} as any + } session.user = { ...session.user, id: token.id as string, @@ -73,8 +78,22 @@ export const { handlers, auth, signIn, signOut } = NextAuth({ name: (token.name as string) || session.user?.name || "", role: token.role as string, } - } else if (process.env.NODE_ENV !== "production") { - console.warn("Session callback: token missing or invalid", { token, session }) + if (process.env.NODE_ENV !== "production") { + console.log("Session callback: session created", { + userId: token.id, + email: token.email, + hasUser: !!session.user, + userKeys: session.user ? Object.keys(session.user) : [] + }) + } + } else { + console.warn("Session callback: token missing or invalid", { + hasToken: !!token, + tokenKeys: token ? Object.keys(token) : [], + hasSession: !!session, + sessionKeys: session ? Object.keys(session) : [], + sessionUser: session?.user + }) } return session } @@ -84,6 +103,18 @@ export const { handlers, auth, signIn, signOut } = NextAuth({ }, session: { strategy: "jwt", + maxAge: 30 * 24 * 60 * 60, // 30 days + }, + cookies: { + sessionToken: { + name: `__Secure-authjs.session-token`, + options: { + httpOnly: true, + sameSite: "lax", + path: "/", + secure: process.env.NODE_ENV === "production", + }, + }, }, secret: nextAuthSecret, })