diff --git a/src/app/auth/signin/page.tsx b/src/app/auth/signin/page.tsx
deleted file mode 100644
index a505ba7..0000000
--- a/src/app/auth/signin/page.tsx
+++ /dev/null
@@ -1,29 +0,0 @@
-"use client";
-
-import { signIn } from "next-auth/react";
-import { useSearchParams } from "next/navigation";
-import { useEffect } from "react";
-
-/**
- * Custom sign-in page that auto-redirects to Authentik.
- * Skips the default NextAuth provider chooser (no "Sign in with Authentik" button).
- */
-export default function SignInPage() {
- const searchParams = useSearchParams();
- const callbackUrl = searchParams.get("callbackUrl") || "/";
-
- useEffect(() => {
- void signIn("authentik", { callbackUrl });
- }, [callbackUrl]);
-
- return (
-
-
-
-
- Se redirecționează către autentificare...
-
-
-
- );
-}
diff --git a/src/app/auth/signin/route.ts b/src/app/auth/signin/route.ts
new file mode 100644
index 0000000..ad58334
--- /dev/null
+++ b/src/app/auth/signin/route.ts
@@ -0,0 +1,74 @@
+import { NextRequest, NextResponse } from "next/server";
+
+/**
+ * Server-side signin route that initiates OAuth flow with Authentik.
+ * Fetches CSRF token from NextAuth, POSTs to provider signin,
+ * and redirects to Authentik's authorize URL — no visible page.
+ */
+export async function GET(request: NextRequest) {
+ const callbackUrl =
+ request.nextUrl.searchParams.get("callbackUrl") || "/";
+ const baseUrl = process.env.NEXTAUTH_URL || "https://tools.beletage.ro";
+
+ try {
+ // Use internal URL for server-to-server calls (avoid external roundtrip)
+ const internalBase = `http://127.0.0.1:${process.env.PORT || "3000"}`;
+
+ // Step 1: Get CSRF token from NextAuth
+ const csrfRes = await fetch(`${internalBase}/api/auth/csrf`, {
+ headers: { cookie: request.headers.get("cookie") || "" },
+ });
+ const csrfData = (await csrfRes.json()) as { csrfToken: string };
+ const csrfToken = csrfData.csrfToken;
+
+ // Merge request cookies with new CSRF cookies
+ const csrfSetCookies = csrfRes.headers.getSetCookie();
+ const existingCookies = request.headers.get("cookie") || "";
+ const newCookiePairs = csrfSetCookies
+ .map((c) => c.split(";")[0])
+ .filter(Boolean);
+ const mergedCookie = [existingCookies, ...newCookiePairs]
+ .filter(Boolean)
+ .join("; ");
+
+ // Step 2: POST to NextAuth's provider-specific signin
+ const signinRes = await fetch(
+ `${internalBase}/api/auth/signin/authentik`,
+ {
+ method: "POST",
+ headers: {
+ "Content-Type": "application/x-www-form-urlencoded",
+ cookie: mergedCookie,
+ },
+ body: new URLSearchParams({ csrfToken, callbackUrl }).toString(),
+ redirect: "manual",
+ },
+ );
+
+ // Step 3: Get the redirect URL (Authentik's authorize endpoint)
+ const location = signinRes.headers.get("location");
+ if (location) {
+ // Build absolute URL if relative
+ const redirectUrl = location.startsWith("http")
+ ? location
+ : `${baseUrl}${location}`;
+ const response = NextResponse.redirect(redirectUrl);
+
+ // Forward all set-cookie headers to browser (CSRF token, state, etc.)
+ for (const cookie of csrfSetCookies) {
+ response.headers.append("set-cookie", cookie);
+ }
+ for (const cookie of signinRes.headers.getSetCookie()) {
+ response.headers.append("set-cookie", cookie);
+ }
+ return response;
+ }
+ } catch (error) {
+ console.error("[auth/signin] Server-side redirect failed:", error);
+ }
+
+ // Fallback: redirect to NextAuth's built-in signin page
+ return NextResponse.redirect(
+ `${baseUrl}/api/auth/signin?callbackUrl=${encodeURIComponent(callbackUrl)}`,
+ );
+}