Reputation: 278
When i try to use
adapter: FirebaseAdapter(firestore)
From -> https://next-auth.js.org/adapters/firebase
After firebase v9 the docs at next-auth hasen't been updated.
i get this error: TypeError: collection is not a function
My Code:
Api keys, and client secret has been replaced with dots (...) to hide them.
import NextAuth from "next-auth";
import Providers from "next-auth/providers";
import { FirebaseAdapter } from "@next-auth/firebase-adapter";
import { getFirestore } from "firebase/firestore";
import { initializeApp, getApps } from "firebase/app";
import "firebase/firestore";
const firebaseConfig = {
apiKey: "...",
authDomain: "...",
projectId: "...",
storageBucket: "...",
messagingSenderId: "...",
appId: "...",
measurementId: "....",
};
const app = initializeApp(firebaseConfig);
const firestore = getFirestore(app);
const options = {
providers: [
Providers.Google({
clientId:
"...",
clientSecret: "...",
}),
],
adapter: FirebaseAdapter(firestore),
// database: process.env.MONGODB_URI,
};
export default (req, res) => {
NextAuth(req, res, options);
};
Upvotes: 1
Views: 3872
Reputation: 1877
Instead of using Firebase Adapter we can use Firestore Adapter with minimal and easy configuration
@auth/firebase-adapter: ^2.7.3
next": ^14.2.5
next-auth": ^4.24.10
// api/auth/[...nextauth]/route.js
const db = getFirestore();
export const authOptions = {
adapter: FirestoreAdapter(db),
providers: [...],
}
const handler = NextAuth(authOptions)
export { handler as GET, handler as POST }
here db is firestore from firebase-admin. Don't forget to initialize the firebase-admin app to use firestore.
This will handle user info on firestore by creating some collections like sessions, users, accounts etc.
Screenshot of firestore containing generated user info on sign up
Upvotes: 0
Reputation: 131
I managed to solve this same error using the following approach:
1- As firebase v9 is following a modular approach, pass destructured FirebaseClient object to the firebase adapter as follows
// pages/api/auth/[...nextauth].js
import NextAuth from "next-auth";
import GoogleProvider from "next-auth/providers/google";
import GithubProvider from "next-auth/providers/github";
import { FirebaseAdapter } from "@next-auth/firebase-adapter";
import { db } from "../../../firebase";
import {
collection,
query,
getDocs,
where,
limit,
doc,
getDoc,
addDoc,
updateDoc,
deleteDoc,
runTransaction,
} from "firebase/firestore";
export default NextAuth({
providers: [
// OAuth authentication providers
GoogleProvider({
clientId: process.env.GOOGLE_ID,
clientSecret: process.env.GOOGLE_SECRET,
}),
GithubProvider({
clientId: "",
clientSecret: "",
}),
],
adapter: FirebaseAdapter({
db,
collection,
query,
getDocs,
where,
limit,
doc,
getDoc,
addDoc,
updateDoc,
deleteDoc,
runTransaction,
}),
});
2-You might then get an error that states "cannot use toDate method of undefined", If this occurred tap into node_modules/@next-auth/firebase-adapter/dist inside index.js file replace the exports.format object with this code which adds a "?" operator after value object
exports.format = {
toFirestore(object) {
const newObjectobject = {};
for (const key in object) {
const value = object[key];
if (value === undefined)
continue;
newObjectobject[key] = value;
}
return newObjectobject;
},
fromFirestore(snapshot) {
if (!snapshot.exists())
return null;
const newUser = { ...snapshot.data(), id: snapshot.id };
for (const key in newUser) {
const value = newUser[key];
if (value?.toDate)
newUser[key] = value.toDate();
else
newUser[key] = value;
}
return newUser;
},
};
3- Last thing you have to do is inside package.json remove the "^" before the next-auth version to disable package update when you do npm install which will reset all code changes occured in step 2.
This solution assumes you have firebase.js file which should look as follows
import { initializeApp, getApps, getApp } from "firebase/app";
import { getAuth } from "firebase/auth";
import { getFirestore } from "firebase/firestore";
import { getStorage } from "firebase/storage";
const firebaseConfig = {
apiKey: "your_api_key",
authDomain: "your_auth_domain",
projectId: "your_project_Id",
storageBucket: "your_storage_bucket",
messagingSenderId: "message_sender_Id",
appId: "your_app_Id",
};
// Initialize Firebase
const app = getApps.length > 0 ? getApp() : initializeApp(firebaseConfig);
const db = getFirestore(app);
const storage = getStorage(app);
export { app, db, storage };
Hope this solves your issue.
Upvotes: 5