Could not link another auth method - firebase auth - javascript

I am signing in user using mobile number and then i want him to enter email and password later. (after logging in)
I am trying to link email,password Auth method to current PhoneAuth method.
But it's giving me an error:
Cannot read property 'link' of undefined
Here is code:
import { firebaseAuth,fire, messaging } from '../../config/constants';
var credential = fire.auth.EmailAuthProvider.credential(email, password);
fire.auth.currentUser.link(credential).then(function(user) {
console.log("Account linking success", user);
}, function(error) {
console.log("Account linking error", error);
});
And in config/constants
import firebase from 'firebase'
require("firebase/firestore");
const config = {
apiKey: "AIzxxxxxxxxxxxxxxxxxxKXI",
authDomain: "payxxxxxxxxxxxxja1.firebaseapp.com",
databaseURL: "https://payxxxxxxxxxxja1.firebaseio.com",
projectId: "payxxxxxxxxxxxxja1",
storageBucket: "payxxxxxxxxxxxja1.appspot.com",
messagingSenderId: "281xxxxx5xxxxx6"
}
firebase.initializeApp(config)
export const fire = firebase
export const ref = firebase.database().ref()
export const firebaseAuth = firebase.auth
export const messaging = firebase.messaging();
I think something is wrong with fire.auth or fire.auth()
Thanks

link has been removed in favor of linkWithCredential starting with Firebase JS version 4.0.0: https://firebase.google.com/support/release-notes/js#4.0.0
Also make sure the current user is ready:
firebase.auth().onAuthStateChange(user => {
if (user) {
// currentUser is not null.
} else {
// currentUser is null.
}
});

Related

How to use Firebase Emulator to write to Firestore, Storage?

My Firebase Function runs in the emulator and writes to the same collection and document:
import * as functions from "firebase-functions";
export const MakeUppercase = functions.firestore.document('Messages/{docId}').onCreate((snap, context) => {
try {
const original = snap.data().original;
const uppercase = original.toUpperCase();
return snap.ref.set({ uppercase }, { merge: true });
} catch (error) {
console.error(error);
}
});
That works great. Now I want to write to a different collection in the Firestore emulator:
import { initializeApp } from "firebase/app";
import * as functions from "firebase-functions";
import { getFirestore, connectFirestoreEmulator } from "firebase/firestore";
const firebaseConfig = {
apiKey: "...",
authDomain: "triggerable-functions-project.firebaseapp.com",
projectId: "triggerable-functions-project",
storageBucket: "triggerable-functions-project.appspot.com",
messagingSenderId: "...",
appId: "..."
};
const app = initializeApp(firebaseConfig);
const db = getFirestore();
connectFirestoreEmulator(db, 'localhost', 8080);
export const MakeUppercase = functions.firestore.document('Messages/{docId}').onCreate((snap, context) => {
try {
const original = snap.data().original;
const uppercase = original.toUpperCase();
return db.firestore().collection('AnotherCollection').doc(context.params.docId).set({ uppercase }, { merge: true });
} catch (error) {
console.error(error);
}
});
That throws this error:
TypeError: db.firestore is not a function
I either have an incorrect Firestore DocumentReference or I didn't import a necessary module.
Let's write to Cloud Firestore. Same code, new module, different DocumentReference:
import * as admin from "firebase-admin";
...
return admin.firestore().collection('AnotherCollection').doc(context.params.docId).set({ uppercase }, { merge: true });
Same error:
TypeError: admin.firestore is not a function
Let's write to the Storage emulator:
import { getStorage, connectStorageEmulator, ref, uploadString } from "firebase/storage";
...
const storage = getStorage();
connectStorageEmulator(storage, "localhost", 9199);
...
return storage.collection('AnotherCollection').doc(context.params.docId).set({ uppercase }, { merge: true });
That throws the same error:
TypeError: storage.collection is not a function
Let's write to Cloud Storage:
const storageRef = ref(storage, 'Messages');
...
return uploadString(storageRef, uppercase);
The log says that the function executed without errors but when I go to Firebase Console I don't see the file in Cloud Storage.
Here's my final code. Why is app declared but never used?
import { initializeApp } from "firebase/app";
import * as functions from "firebase-functions";
import { getFirestore, connectFirestoreEmulator } from "firebase/firestore";
import { getStorage, connectStorageEmulator, ref, uploadString } from "firebase/storage";
import * as admin from "firebase-admin";
const firebaseConfig = {
apiKey: "...",
authDomain: "triggerable-functions-project.firebaseapp.com",
projectId: "triggerable-functions-project",
storageBucket: "triggerable-functions-project.appspot.com",
messagingSenderId: "...",
appId: "..."
};
const app = initializeApp(firebaseConfig);
const db = getFirestore();
connectFirestoreEmulator(db, 'localhost', 8080);
const storage = getStorage();
const storageRef = ref(storage, 'Messages');
connectStorageEmulator(storage, "localhost", 9199);
export const MakeUppercase = functions.firestore.document('Messages/{docId}').onCreate((snap, context) => {
try {
const original = snap.data().original;
const uppercase = original.toUpperCase();
return uploadString(storageRef, uppercase);
} catch (error) {
console.error(error); // emulator always throws an "unhandled error": "Your function timed out after ~60s."
}
});
You're using the new(ish) modular syntax of the v9 and later SDKs when you call getFirestore. With that new API, most calls are no longer namespaced, but are top-level functions. So there are no longer any public methods on the db object you have (as the error message says), but instead you have to pass the db object when calling those top-level functions.
The equivalent of this code:
db.firestore().collection('AnotherCollection').doc(context.params.docId).set({ uppercase }, { merge: true });
Would be:
setDoc(
doc(db, 'AnotherCollection', context.params.docId),
{ uppercase }, { merge: true })
)
Which is pretty close to the code sample in the documentation on setting a document with the v9 syntax, so I recommend keeping that handy while converting the rest of the code to the new API. The Upgrade from version 8 to the modular Web SDK guide is also a good place to get started, as are the blog posts Introducing the new Firebase JS SDK and The new Firebase JS SDK is now GA
Thanks, #Frank van Puffelen! Here's my Firebase version 9 code for writing to a different directory in the emulator:
import { initializeApp } from "firebase/app";
import * as functions from "firebase-functions";
import { getFirestore, connectFirestoreEmulator, setDoc, doc } from "firebase/firestore";
const firebaseConfig = {
apiKey: "...",
authDomain: "triggerable-functions-project.firebaseapp.com",
projectId: "triggerable-functions-project",
storageBucket: "triggerable-functions-project.appspot.com",
messagingSenderId: "...",
appId: "..."
};
const firebaseApp = initializeApp(firebaseConfig);
const db = getFirestore(firebaseApp);
connectFirestoreEmulator(db, 'localhost', 8080);
export const MakeUppercase = functions.firestore.document('Messages/{docId}').onCreate((snap, context) => {
try {
const original = snap.data().original;
const uppercase = original.toUpperCase();
return setDoc(
doc(db, 'AnotherCollection', context.params.docId),
{ uppercase }, { merge: true }
);
} catch (error) {
console.error(error);
}
});
Commenting out the emulator
connectFirestoreEmulator(db, 'localhost', 8080);
writes to Cloud Firestore. This threw an error:
Connection GRPC stream error. Code: 7 Message: 7 PERMISSION_DENIED: Missing or insufficient permissions.
I'm not going to worry about that, I presume that the emulator isn't intended to write to the Cloud.
As for Storage, my original code executes without errors but nothing writes to Storage in the emulator. Trying Cloud Storage, my Firebase Console refuses to set up Storage.
The documentation explains why I kept getting "not a function" errors. Instead of thinking of a Firestore location as a place with an address (in the namespace), in version 9 Firestore locations are functions with parameters.
While the version 8 APIs are based on a dot-chained namespace and
service pattern, version 9's modular approach means that your code
will be organized principally around functions.
David East explained in a blog post that the old (version 8) Firebase managed namespaces on the window but version 9 uses ES modules:
Historically libraries have been loaded and managed via a namespace on
the window, such as window.firebase. This technique does not allow for
tree shaking and lacks other benefits of the JavaScript module system.

Could not reach Cloud Firestore backend. Connection failed 1 times. Most recent error: FirebaseError: [code=permission-denied]

I am getting the following error: Could not reach Cloud Firestore backend. Connection failed 1 times. Most recent error: FirebaseError: [code=permission-denied]: Permission denied on resource project disneyplus-clone-a33d5.
I am learning React and the tutorial I am learning from uses firebase. I have very little knowledge about firebase. I cannot find any solution for this error. here is my fbconfig.js :
import { initializeApp } from 'firebase/app';
import { getAuth, GoogleAuthProvider } from "firebase/auth";
import { getStorage } from "firebase/storage";
import { getFirestore } from "firebase/firestore"
const firebaseConfig = {
apiKey: "---",
authDomain: "--.firebaseapp.com",
projectId: "--",
storageBucket: "--",
messagingSenderId: "--",
appId: "--",
measurementId: "---",
};
const firebaseApp = initializeApp(firebaseConfig);
const db = getFirestore(firebaseApp);
const auth = getAuth();
const provider = new GoogleAuthProvider();
const storage = getStorage(firebaseApp);
export { auth, provider, storage };
export default db;
Here is my Home.js :
import db from '../fbconfig'
import { doc, onSnapshot, collection, query, where } from "firebase/firestore";
function Home() {
useEffect(() => {
const q = query(collection(db, "movies"))
const unsub = onSnapshot(q, (snapshot)=>{
let tempMovies = snapshot.docs.map((doc)=>{
console.log(doc.data());
return { id: doc.id, ...doc.data() }
})
});
code=permission-denied when working with Firestore is always a permissions problem on the collection you are trying to read, in this case "movies". To set permissions on a collection you can use the Firebase web gui or the command line tools.
The specific rule you will need for read access to "movies" is
match /movies {
allow get: if true;
allow list: if true;
allow update: if false;
allow create: if false;
allow delete: if false;
}
https://firebase.google.com/docs/rules/manage-deploy
Or the web ui

how can i login with facebook account?

i wanted to create a login with facebook button, so i created this code:
import { getAuth, signOut,
onAuthStateChanged, FacebookAuthProvider, signInWithPopup } from "https://www.gstatic.com/firebasejs/9.0.2/firebase-auth.js";
const firebaseConfig = {
apiKey: "AIzaSyC3GLIN5TBmCDoTfy0dEOgOdvVvqNw-ric",
authDomain: "auth-project-38aaa.firebaseapp.com",
projectId: "auth-project-38aaa",
storageBucket: "auth-project-38aaa.appspot.com",
messagingSenderId: "431888894254",
appId: "1:431888894254:web:71bb9b250fbb8a21edd2bf",
measurementId: "G-6BBPCJ3814"
};
const app = initializeApp(firebaseConfig);
const auth = getAuth(app);
// login with facebook
const facebookProvider = new FacebookAuthProvider();
const signInWithFacebook = document.querySelector('#facebook-icon');
signInWithFacebook.addEventListener('click', (e) => {
e.preventDefault();
signInWithPopup(auth, facebookProvider).then((result) => {
const user = result.user;
const credential = FacebookAuthProvider.credentialFromResult(result);
const accessToken = credential.accessToken;
})
.catch((error) => {
const errorCode = error.code;
const errorMessage = error.message;
const email = error.email;
const credential = FacebookAuthProvider.credentialFromError(error);
});
});
when i try to login with facebook it gives me this error message:
Facebook has detected that firebase sign in isn't using a secure connection to transfer information.
can you help to solve this problem, please?
For these tests you must run them with an SSL connection, if you are testing on localhost you are probably not using SSL.

GoogleAuthProvider gives error "this.ta is not a function" in web application

I am trying to set authentication with Google in my web application. I did this type of thing a couple of times on Android apps, but now when i load my application it gives error "this.ta is not a function". Maybe its something silly but i can't detect the problem. Here is what i have:
api.js
import { db, storage, auth, google_provider } from './firebase'
sign_in() {
auth.signInWithPopup(google_provider).then(result => {
var token = result.credential.accessToken;
var user = result.user;
}).catch(error => {
var errorCode = error.code;
var errorMessage = error.message;
var email = error.email;
var credential = error.credential;
})
}
firebase.js
import * as firebase from 'firebase';
const app = firebase.initializeApp({
apiKey: "my-key",
authDomain: "domain",
databaseURL: "https://domain-url",
projectId: "name",
storageBucket: "bucket",
messagingSenderId: "id"
})
export const db = app.firestore()
export const storage = app.storage().ref()
export const auth = app.auth()
export const google_provider = firebase.auth.GoogleAuthProvider()
This is the error GoogleAuthProvider Error
Maybe i am wrong in the way i initialize the GoogleAuthProvider or the way i call the API. If somebody knows something i will appreciate anything that could tell me.
Regards.
firebase.auth.GoogleAuthProvideris a constructor.
To me it looks like you forgot to initialize it with new.
export const google_provider = new firebase.auth.GoogleAuthProvider()

Linking two firebase auth methods giving me error - javascript

I am trying to link email,password Auth method to current PhoneAuth method.
But it's giving me an error:
Cannot read property 'link' of undefined
Here is code:
import { firebaseAuth,fire, messaging } from '../../config/constants';
var credential = fire.auth.EmailAuthProvider.credential(email, password);
fire.auth.currentUser.link(credential).then(function(user) {
console.log("Account linking success", user);
}, function(error) {
console.log("Account linking error", error);
});
And in config/constants
import firebase from 'firebase'
require("firebase/firestore");
const config = {
apiKey: "AIzxxxxxxxxxxxxxxxxxxKXI",
authDomain: "payxxxxxxxxxxxxja1.firebaseapp.com",
databaseURL: "https://payxxxxxxxxxxja1.firebaseio.com",
projectId: "payxxxxxxxxxxxxja1",
storageBucket: "payxxxxxxxxxxxja1.appspot.com",
messagingSenderId: "281xxxxx5xxxxx6"
}
firebase.initializeApp(config)
export const fire = firebase
export const ref = firebase.database().ref()
export const firebaseAuth = firebase.auth
export const messaging = firebase.messaging();
Please help me through this. Thanks
Following is what they have mentioned in there Docs.
Pass the AuthCredential object to the signed-in user's
linkWithCredential method:
auth.currentUser.link(credential).then(function(user) {
console.log("Account linking success", user);
}, function(error) {
console.log("Account linking error", error);
});
And following is what resolves the problem.
auth.currentUser.linkWithCredential(credential).then(function(user) {
console.log("Account linking success", user);
}, function(error) {
console.log("Account linking error", error);
});
Simply replacing link with linkWithCredential made it working. That is how dumb the Doc writer is.

Categories

Resources