Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FirebaseServerApp] Failed to initialize in Next.JS Edge Runtime #8299

Assignees

Comments

@JoseVSeb
Copy link
Contributor

JoseVSeb commented Jun 5, 2024

Operating System

N/A

Browser Version

N/A

Firebase SDK Version

10.12.2

Firebase SDK Product:

Auth

Describe your project's tooling

Next.JS

Describe the problem

I cannot use initializeServerApp in Next.JS middleware (Edge runtime) to secure the server at middleware as intended.

However, just commenting out isBrowser() guard clause makes it run as intended.

I understand why it fails (Edge runtime is essentially the same as Browser runtime) and why the guard clause is there, but implementing security in Next.JS middleware is a life-saver in code complexity.

Third-party libraries like next-firebase-auth-edge require the use of service account credentials which is not ideal especially since FirebaseServerApp does what is required without the same.

Steps and code to reproduce issue

  1. Initialize Next.JS project.
  2. Set up Firebase Auth on the client side.
  3. Set up service worker to inject the Authorization header as in https://firebase.google.com/codelabs/firebase-nextjs
  4. Set up Next.JS middleware to secure requests using initializeServerApp and Auth
// middleware.ts
const getIdTokenInServer = () => {
  const prefix = "Bearer ";
  const authorizationHeader = headers().get("Authorization");
  if (!authorizationHeader?.startsWith(prefix)) return null;
  return authorizationHeader.split(prefix)[1] ?? null;
};
const getFirebaseServerApp = () => {
  const idToken = getIdTokenInServer();
  // fails with guard clause but works fine if it's removed
  return initializeServerApp(
    firebaseConfig,
    idToken ? { authIdToken: idToken } : {},
  );
};
const getAuthInServer = () => getAuth(getFirebaseServerApp());
export async function middleware(req: NextRequest) {
  const auth = getAuthInServer();
  await auth.authStateReady()

  if (!auth.currentUser) return NextResponse.redirect(/** redirect url */);

  /** other authorization logic */

  return NextResponse.next();
}
@JoseVSeb JoseVSeb added new A new issue that hasn't be categoirzed as question, bug or feature request question labels Jun 5, 2024
@jbalidiong jbalidiong added needs-attention and removed new A new issue that hasn't be categoirzed as question, bug or feature request labels Jun 5, 2024
@jdgamble555
Copy link

@JoseVSeb - This is related to #8284, but I can't get a response on this even though it is possibly a simple fix.

😦

J

@codercatdev
Copy link

@jdgamble555
Copy link

Problem is that solution does not solve this issue, nor allow you to use initializeServerApp.

J

@JoseVSeb
Copy link
Contributor Author

Same issue, so I followed this https://dev.to/geiel/how-to-use-firebase-authentication-in-nextjs-13-client-and-server-side-1bbn

That solution is from nearly a year before FirebaseServerApp was added and was for firebase-admin. It does not apply here. FirebaseServerApp builds on top of FirebaseApp (which was meant for the browser) without the login flow (replaced by passing idToken in initialization), making it fully compatible with Edge runtime. Only the isBrowser() guard clause prevents it from doing so.

@JoseVSeb
Copy link
Contributor Author

JoseVSeb commented Jun 13, 2024

#1773 is the source of the issue. it was initially applied to detect Firebase Lite in browsers, it seems, and was changed to include web workers as well. But that is invalid as it's not explicitly checking if it's a WebWorker.

@jdgamble555
Copy link

Then the question becomes how do you differentiate a Web Worker from a Cloudflare Worker (what Vercel Edge uses too).

Possible fix:

https://community.cloudflare.com/t/how-to-detect-the-cloudflare-worker-runtime/293715/2

Of course you would need to check for other potential environments like Fastify... and maybe Deno and Bun runtimes as well to be complete...

J

FWI there maybe more issues other than isBrowser, but we can't check for them until this is fixed.

@JoseVSeb
Copy link
Contributor Author

We could use self instanceof WorkerGlobalScope to detect web worker.

JoseVSeb added a commit to JoseVSeb/firebase-js-sdk that referenced this issue Jun 13, 2024
update browser detection logic:
detect either window or web worker (WorkerGlobalScope).

fixes firebase#8299 firebase#8284
JoseVSeb added a commit to JoseVSeb/firebase-js-sdk that referenced this issue Jun 13, 2024
update browser detection logic:
detect either window or web worker (WorkerGlobalScope).

fixes firebase#8299 firebase#8284
JoseVSeb added a commit to JoseVSeb/firebase-js-sdk that referenced this issue Jun 13, 2024
update browser detection logic:
detect either window or web worker (WorkerGlobalScope).

fixes firebase#8299 firebase#8284
@JoseVSeb
Copy link
Contributor Author

JoseVSeb commented Jun 16, 2024

another issue ReferenceError: FinalizationRegistry is not defined.
Edge runtime doesn't support FinalizationRegistry but @firebase/app uses it in FirebaseServerAppImpl unconditionally, even if there is a guard clause in initializeServerApp that suggests that it is needed only if releaseOnDeref is provided in config.

JoseVSeb added a commit to JoseVSeb/firebase-js-sdk that referenced this issue Jun 16, 2024
… is unsupported by runtime

FinalizationRegistry is required only if releaseOnDeref is provided in config; guard clause in initializeServerApp throws error if it's unsupported.

firebase#8299
JoseVSeb added a commit to JoseVSeb/firebase-js-sdk that referenced this issue Jun 16, 2024
…upported

FinalizationRegistry is required only if releaseOnDeref is provided in config; guard clause in initializeServerApp throws error if it's unsupported.

firebase#8299
@isaniovitor
Copy link

Same problem here, any updates?

@JoseVSeb
Copy link
Contributor Author

Same problem here, any updates?

merging #8315 and #8320 should fix it.

JoseVSeb added a commit to JoseVSeb/firebase-js-sdk that referenced this issue Jun 26, 2024
update browser detection logic:
detect either window or web worker (WorkerGlobalScope).

fixes firebase#8299 firebase#8284
@DellaBitta
Copy link
Contributor

I just merged PR #8315 and #8335 which should fix this issue in our next release. Please open a new issue and add a link to this one for context if you continue to have related problems.

Thanks everyone for the reports and the submissions!

@jdgamble555
Copy link

@DellaBitta - Is there a @next or a way to test this before release?

@JoseVSeb
Copy link
Contributor Author

@jdgamble555 you can use firebase@canary

@jdgamble555
Copy link

@JoseVSeb - Thanks! This seems to work so far. I have only tested this on a cloudflare worker with firestore/lite and FirebaseServerApp. I'm not sure if other firebase providers have problems, but these two seem to work.

Will keep you posted in a new post if something fails.

J

tom-andersen pushed a commit that referenced this issue Jul 24, 2024
Update browser detection logic: Detect either window or web worker (WorkerGlobalScope).
This updates the implementation to `isBrowser()` and adds a new function `isWebWorker()`.

Fixes #8299 #8284
@firebase firebase locked and limited conversation to collaborators Jul 29, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.