From b91595316d569c120eb3c61a70e5e90261ebde0a Mon Sep 17 00:00:00 2001 From: Mannu Date: Sun, 24 May 2026 13:01:01 +0530 Subject: [PATCH] fix: use APP_URL for OAuth/verify redirects behind Dokploy proxy Behind Traefik, request.url resolves to http://0.0.0.0:3000/... (the internal Docker address). Using that as the redirect base sent browsers to 0.0.0.0, causing ERR_SSL_PROTOCOL_ERROR. Switch all server-side redirects in the Google callback and verify-email routes to use NEXT_PUBLIC_APP_URL (with tia.manohargupta.com fallback). Co-Authored-By: Claude Sonnet 4.6 --- src/app/api/auth/google/callback/route.ts | 12 +++++++----- src/app/api/auth/verify-email/route.ts | 10 ++++++---- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/src/app/api/auth/google/callback/route.ts b/src/app/api/auth/google/callback/route.ts index d721a39..7b45423 100644 --- a/src/app/api/auth/google/callback/route.ts +++ b/src/app/api/auth/google/callback/route.ts @@ -6,6 +6,8 @@ import { logAudit } from "@/lib/audit"; export const dynamic = "force-dynamic"; +const APP_URL = process.env.NEXT_PUBLIC_APP_URL || "https://tia.manohargupta.com"; + export async function GET(request: Request) { const url = new URL(request.url); const code = url.searchParams.get("code"); @@ -17,7 +19,7 @@ export async function GET(request: Request) { // 1. CSRF / integrity check — returned state must match what we sent. if (!code || !state || !storedState || state !== storedState || !verifier) { - return NextResponse.redirect(new URL("/login?error=oauth", request.url)); + return NextResponse.redirect(new URL("/login?error=oauth", APP_URL)); } try { @@ -31,7 +33,7 @@ export async function GET(request: Request) { { headers: { Authorization: `Bearer ${tokens.accessToken()}` } }, ); if (!profileRes.ok) { - return NextResponse.redirect(new URL("/login?error=oauth", request.url)); + return NextResponse.redirect(new URL("/login?error=oauth", APP_URL)); } const profile = (await profileRes.json()) as { sub: string; email: string; email_verified: boolean; @@ -40,7 +42,7 @@ export async function GET(request: Request) { // 4. HARD requirement: Google must confirm the email is verified. if (!profile.email || !profile.email_verified) { - return NextResponse.redirect(new URL("/login?error=unverified", request.url)); + return NextResponse.redirect(new URL("/login?error=unverified", APP_URL)); } // 5. Find or create the user. @@ -92,7 +94,7 @@ export async function GET(request: Request) { await logAudit({ userId, action: "login", request, metadata: { method: "google" } }); const response = NextResponse.redirect( - new URL(isNewUser ? "/onboarding" : "/", request.url), + new URL(isNewUser ? "/onboarding" : "/", APP_URL), ); response.cookies.set("tia_session", sessionToken, { httpOnly: true, @@ -106,6 +108,6 @@ export async function GET(request: Request) { return response; } catch (e) { console.error("Google callback error:", e); - return NextResponse.redirect(new URL("/login?error=oauth", request.url)); + return NextResponse.redirect(new URL("/login?error=oauth", APP_URL)); } } diff --git a/src/app/api/auth/verify-email/route.ts b/src/app/api/auth/verify-email/route.ts index 9d62883..7ce7c7f 100644 --- a/src/app/api/auth/verify-email/route.ts +++ b/src/app/api/auth/verify-email/route.ts @@ -4,11 +4,13 @@ import { logAudit } from "@/lib/audit"; export const dynamic = "force-dynamic"; +const APP_URL = process.env.NEXT_PUBLIC_APP_URL || "https://tia.manohargupta.com"; + // GET — the link target from the verification email. export async function GET(request: Request) { const token = new URL(request.url).searchParams.get("token"); if (!token) { - return NextResponse.redirect(new URL("/login?error=verify", request.url)); + return NextResponse.redirect(new URL("/login?error=verify", APP_URL)); } try { @@ -19,7 +21,7 @@ export async function GET(request: Request) { LIMIT 1 `; if (rows.length === 0) { - return NextResponse.redirect(new URL("/login?error=verify", request.url)); + return NextResponse.redirect(new URL("/login?error=verify", APP_URL)); } const verifyId = rows[0].id; @@ -39,7 +41,7 @@ export async function GET(request: Request) { `; await logAudit({ userId, action: "email_verified", request }); - const response = NextResponse.redirect(new URL("/onboarding", request.url)); + const response = NextResponse.redirect(new URL("/onboarding", APP_URL)); response.cookies.set("tia_session", sessionToken, { httpOnly: true, secure: process.env.NODE_ENV === "production", @@ -50,6 +52,6 @@ export async function GET(request: Request) { return response; } catch (e) { console.error("Verify email error:", e); - return NextResponse.redirect(new URL("/login?error=verify", request.url)); + return NextResponse.redirect(new URL("/login?error=verify", APP_URL)); } }