next-auth icon indicating copy to clipboard operation
next-auth copied to clipboard

Firebase Adapter Fails with App Name Already exist error

Open satish860 opened this issue 2 years ago • 7 comments

Adapter type

@next-auth/firebase-adapter

Environment

yarn dev

Reproduction URL

https://github.com/satish860/codegist

Describe the issue

I am getting the following error.

FirebaseError: Firebase: Firebase App named '[DEFAULT]' already exists with different options or config (app/duplicate-app).

image

In my initial debugging, I found Firebase adapter is trying to initialize the app, which is already initialized.

What if we can add the similar code // Initialize Firebase const app = !getApps().length ? initializeApp(firebaseConfig) : getApp();

How to reproduce

Step 1: Run the app in the repo using Yarn dev Step 2: Click the Sign link Step 3: You will be getting the following auth error screen

image

Expected behavior

It should redirect me to the Provider Login screen

satish860 avatar Jul 14 '22 04:07 satish860

@chanceaclark let's revisit and allow passing an app, as people might have already set up one outside next-auth. 👍

balazsorban44 avatar Jul 15 '22 02:07 balazsorban44

Going through this same issue please kindly fix or if there's a workaround I would love to know.

ifeoluwaayo avatar Jul 26 '22 14:07 ifeoluwaayo

Any scope of passing an firestore object created from firebase-admin ? that would solve our security rules issues #5049

Chibionos avatar Jul 29 '22 23:07 Chibionos

@ifeoluwaayo how are you setting up your security rules, I am curious as I see I cannot open the security rules for the collections this adapters requires. Did you find a work around ?

Chibionos avatar Jul 29 '22 23:07 Chibionos

So I think there is a big gotcha here: If you initialize a firebase app on the client, you need to initialize a new one on the server as well.

I went ahead and added some logic in #5055 to make sure we get the default app or initialize a new one to prevent that duplicate app issue. Along with that I also added some documentation about reusing your client app inside the server config.

chanceaclark avatar Jul 31 '22 17:07 chanceaclark

I'm facing this same issue, I hope this gets merged quickly

27lakshay avatar Aug 22 '22 10:08 27lakshay

@27lakshay @chanceaclark I am waiting for that PR too. It's been very long and I can imagine the workload that people have. So let's cross our fingers 🤞 that will have some attention soon.

itsmylife avatar Aug 23 '22 18:08 itsmylife

The reason this is happening is because, you're trying to override an instance that has no identifier given. The docs for this is extremely confusing but, here's something to think about:

import { initializeApp } from 'firebase/app';
const firebaseApp = initializeApp({ ... });

If you did something like this previously somewhere in your codebase and it was executed before the adapter was able to create an instance, it'll default to "[DEFAULT]". There's a second parameter that's optional that allows you to have multiple instances with an identifier you provide. i.e initializeApp({ ... }, identifierString). A simple solution to this could be something like, initializeApp({ ... }, "NEXT_AUTH"). As of right now, the adapter assumes that there's no firebase instance anywhere else in the app so, it instances a new copy without an identifier so, it gets pushed as '[DEFAULT]' which triggers that error if you have any other instances that attempt to use the same identifier.

Specifically, on this line:

export function FirestoreAdapter({
  emulator,
  ...firebaseOptions
}: FirebaseOptions & FirestoreAdapterOptions): Adapter {
  const firebaseApp = initializeApp(firebaseOptions) // This line pushes a new instance with the identifier '[DEFAULT]'
  const db = getFirestore(firebaseApp)

https://github.com/nextauthjs/next-auth/blob/main/packages/adapter-firebase/src/index.ts#L41

Problem is that if you were to remediate this and pass an app, you'd run into breaking changes.

There's a couple things wrong with the adapter that should probably be corrected sometime soon. You shouldn't be initializing a new default app. You should be able to pass an instanced app so that there's some obvious source of truth that is visible and fits different use-cases. From a developer standpoint, when firebase errors like it does and you have multiple instances of firebase active on the app, you literally have to go through each one to figure out which one errored. To avoid that, it should be clear. An adapter is meant to provide an interface between NEXT_AUTH datatypes and firebase so there's a compatibility layer between both. It should not be instancing things. I can fix this myself because, I ran into this error, took me a couple hours to figure out it was this and now I am here.

Secondly, [firebase adapter] - Firebase adapter requires open security rules we cannot allow in production (https://github.com/nextauthjs/next-auth/issues/5049) exposes a very insecure approach that is actively being pitched as a possible solution. This is totally incorrect. Having insecure database rules where access is not controlled makes a lot of this a no-opt solution when it comes to production ready environments.

There's probably a solid amount of users that use this adapter with open security rules without actually realizing it and that puts user-data at risk if you're not in a development environment. It's a small problem if you have small users. It starts to multiply as your user-base grows.

sbhadr avatar Sep 29 '22 04:09 sbhadr

It seems to me that Firebase wants you to get the existing app.

In my own adapter for Firebase admin SDK I experienced this issue, and I wound up implementing a fix:

import { initializeApp, getApp, getApps } from 'firebase-admin/app'

const appList = getApps()
const appName = 'firebase-admin-adapter' // arbitrary name
const app = !!appList.length && !!appList.find(a => a.name === appName)
    ? getApp(appName)
    : initializeApp(options, appName)

I see the current firebase adapter initializes the app without verifying whether one already exists. The example above imports from firebase-admin, but I presume firebase to have these functions too.

drunkenvalley avatar Oct 08 '22 21:10 drunkenvalley

@drunkenvalley . Are you using the below code on firebase.config.js or [...nextauth].js

import { initializeApp, getApp, getApps } from 'firebase-admin/app'

const appList = getApps()
const appName = 'firebase-admin-adapter' // arbitrary name
const app = !!appList.length && !!appList.find(a => a.name === appName)
    ? getApp(appName)
    : initializeApp(options, appName)

bcthakre avatar Oct 16 '22 21:10 bcthakre

Thanks Balazs. Will there be a documentation on how to update current setup. Also, what changes need to be done on firestore security rules. Best Regards, Bhupendrasinh ThakreOn Feb 5, 2023, at 7:33 AM, Balázs Orbán @.***> wrote: Closed #4927 as completed via 6445eb6.

—Reply to this email directly, view it on GitHub, or unsubscribe.You are receiving this because you commented.Message ID: @.***>

bcthakre avatar Feb 06 '23 04:02 bcthakre

Will the update be posted in this thread? I'm running into the same issue, not using firebase anywhere except for in [...nextauth].ts

PigeonZow avatar Feb 08 '23 08:02 PigeonZow