awinogrodzki / next-firebase-auth-edge

Next.js Firebase Authentication for Edge and Node.js runtimes. Compatible with latest Next.js features.
https://next-firebase-auth-edge-docs.vercel.app/
MIT License
468 stars 42 forks source link

404 Error on API Routes When Using SRC Folder Structure #241

Closed JumboDaniel closed 1 week ago

JumboDaniel commented 3 weeks ago

Description

When using the next-firebase-auth-edge package with a Next.js 14 project that uses the App Router and a src folder structure, the automatically generated API routes (/api/login and /api/logout) return 404 errors.

Steps to Reproduce

  1. Set up a Next.js 14 project with App Router and src folder structure
  2. Install and configure next-firebase-auth-edge as per documentation
  3. Implement the middleware as shown bellow
  4. Attempt to access /api/login or /api/logout

Expected Behavior

The /api/login and /api/logout routes should be accessible and function as described in the documentation.

Actual Behavior

Accessing these routes results in a 404 error. Manually creating these routes in src/app/api/ works, but defeats the purpose of automatic route generation.

Environment

Additional Context

The example provided in the documentation works correctly with a flat project structure. The issue seems to only occur when using a src folder structure. I changed the older structure to a flat one and it worked.

Question

Is there a way to configure the package to work with a src folder structure without manually creating the API routes?

Middleware file

` import { NextRequest } from "next/server"; import { authMiddleware } from "next-firebase-auth-edge"; import { clientConfig, serverConfig } from "@/lib/firebase/edgeConfig";

export async function middleware(request: NextRequest) { return authMiddleware(request, { loginPath: "/api/login", logoutPath: "/api/logout", apiKey: clientConfig.apiKey, cookieName: serverConfig.cookieName, cookieSignatureKeys: serverConfig.cookieSignatureKeys, cookieSerializeOptions: serverConfig.cookieSerializeOptions, serviceAccount: serverConfig.serviceAccount, }); } export const config = { matcher: [ "/", "/((?!_next|api|.\.).)", "/api/login", "/api/logout", ], }; `

Login File

` "use client"; import * as React from "react"; import Link from "next/link";

//// import { Input } from "@/components/ui/input"; import { RobotoFont } from "@/components/font"; import { SubmitButton } from "@/components/ui/submit-button"; import { PasswordInput } from "@/components/ui/password-input"; import { signInWithPassword } from "@/actions/auth"; import { useFormState } from "react-dom"; import { GoogleSignin } from "@/components/auth/google-signin";

export default function Login() { const [state, formAction] = useFormState(signInWithPassword, undefined); React.useEffect(() => { console.log(state); async function SetBrowserCookies() { await fetch("/api/login", { headers: { Authorization: Bearer ${state?.idToken}, }, }); } if (state?.success) { console.log("is it trying", state?.success, true); SetBrowserCookies(); console.log("is it done", state?.success, true); } }, [state]);

return ( <section className={space-y-12 max-w-xl my-auto container}>

Login

{/* form */}
email address
Forgot Password
      <div className="text-red-500 not-sr-only text-sm my-2">
        {state?.message}
      </div>
      <SubmitButton
        className="rounded-full w-full uppercase mt-8 relative"
        size={`lg`}
      >
        Login
      </SubmitButton>
    </form>
    <div className={`${RobotoFont.className} text-right mt-4`}>
      <p className="">
        <span className="">Don&apos;t have an account? </span>&nbsp;
        <Link className="text-[]" href={`/auth/signup`}>
          Signup
        </Link>
      </p>
    </div>
    <div className={`${RobotoFont.className} mt-4 text-right`}>
      <div className="my-10">
        <div className="flex items-center gap-4">
          <div className="h-[1px] flex-1 bg-black" />
          <p className="text-black-foreground">or</p>
          <div className="h-[1px] flex-1 bg-black" />
        </div>
      </div>
      <GoogleSignin />
    </div>
  </div>
</section>

); } `

form action

` export async function signInWithPassword(state: FormState, formData: FormData) { const email = formData.get("email") as string; const password = formData.get("password") as string; try { const credential = await signInWithEmailAndPassword(FirebaseAuth, email, password); const idToken = await credential.user.getIdToken(); return{ credential, idToken, message:"Login successful, redirecting...", success:true }

} catch (error: unknown) { // console.log("", JSON.stringify(error)); return mapFirebaseErrorToFormState(error); } } `

awinogrodzki commented 2 weeks ago

Hey @JumboDaniel!

Thanks for reporting. As far as I know, the directory structure should not affect how auth middleware is working. I will try to reproduce the issue and get back to you.

awinogrodzki commented 2 weeks ago

Hey @JumboDaniel!

I have modified starter example to use src dir: https://github.com/awinogrodzki/next-firebase-auth-edge/pull/245

Everything seems to be working as expected.

Have you moved middleware.ts to src/middleware.ts?

awinogrodzki commented 1 week ago

I will close the issue now as it seems to be due to incorrect middleware.ts file placement. Feel free to re-open if otherwise

JumboDaniel commented 5 days ago

Thank you very much, I found out that was the issue.