Firebase Firestore Permission Denied Error when signInWithEmailAndPassword - javascript

I want to create a node js app which downloads some data from the firestore. Although I've done everything like it's shown in tutorials I've been stuck with reading document from the firestore for hours. I have a very simple database structure with simple security rules:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /partners/{document=**} {
allow read: if true;
}
}
}
In my code I just want to login into firebase using email and password and then download one document under existing path:
const firebase = require("firebase/app");
require("firebase/auth");
require("firebase/firestore");
const email = <correct email>
const password = <correct password>
var firestoreConfig = {
...
};
// Initialize Firebase
firebase.initializeApp(firestoreConfig);
firebase.auth().signInWithEmailAndPassword(email, password)
.then(function(user){
const userId = user.user.uid
const firestore = firebase.firestore();
console.log(`logged to firestore as ${userId}`)
firestore.doc("/partner/test/communication/544a3deec/messages/2e5b89b8-c48f-4d4f").get()
.then(function(data){
console.log(`${Object.keys(data).length}`);
})
.catch(function(error){
console.log(error);
})
})
and the error is
{ FirebaseError: Missing or insufficient permissions.
at new FirestoreError (/Users/cb/Documents/IdeaProjects/node-hello/node_modules/#firebase/firestore/dist/index.node.cjs.js:1205:28)
at fromRpcStatus (/Users/cb/Documents/IdeaProjects/node-hello/node_modules/#firebase/firestore/dist/index.node.cjs.js:5246:12)
at fromWatchChange (/Users/cb/Documents/IdeaProjects/node-hello/node_modules/#firebase/firestore/dist/index.node.cjs.js:5482:35)
at PersistentListenStream.onMessage (/Users/cb/Documents/IdeaProjects/node-hello/node_modules/#firebase/firestore/dist/index.node.cjs.js:15817:27)
at /Users/cb/Documents/IdeaProjects/node-hello/node_modules/#firebase/firestore/dist/index.node.cjs.js:15750:30
at /Users/cb/Documents/IdeaProjects/node-hello/node_modules/#firebase/firestore/dist/index.node.cjs.js:15786:28
at /Users/cb/Documents/IdeaProjects/node-hello/node_modules/#firebase/firestore/dist/index.node.cjs.js:14218:20
at process._tickCallback (internal/process/next_tick.js:68:7)
code: 'permission-denied',
name: 'FirebaseError',
toString: [Function] }
I see that the login was successful because it printed out the uid of the user. What can be the issue ? Security rules or I just completely don't understand the firestore ?
EDIT:
Changed my code according to Doug answer:
firebase.initializeApp(firestoreConfig);
firebase.auth().onAuthStateChanged(function(user) {
if (user) {
const userId = user.uid
const firestore = firebase.firestore();
console.log(`logged firestore as ${userId}`)
firestore.doc("/partner/test/communication/544a3deec/messages/2e5b89b8-c48f-4d4f").get()
.then(function(data){
console.log(`${Object.keys(data).length}`);
})
.catch(function(error){
console.log(error);
})
} else {
}
});
firebase.auth().signInWithEmailAndPassword(email, password)
.catch(function(error){
console.log(error);
})
same error as before

There is a typo in the code, an additional s for partner.

Related

How can i create a server-side authentication system with express.js and firebase?

I have already tried it with the code below however once i login every device on my network is capable of automatically logging in. How can I create a secure authentication system?
.post('/logIn', async (req, res) => {
const context = { error: false }
await signInWithEmailAndPassword(auth, req.body.email, req.body.password)
.catch(err => {context.error = true})
if (context.error) {
return res.render('auth/logIn.ejs', context)
} else {
return res.redirect('/')
}
})
If possible can somebody redirect me to a youtube video or article from which I can find a solution?
You can dictace the behavioir using auth state persistence
import { getAuth, setPersistence, signInWithEmailAndPassword, browserSessionPersistence } from "firebase/auth";
const auth = getAuth();
setPersistence(auth, browserSessionPersistence)
.then(() => {
return signInWithEmailAndPassword(auth, email, password);
})
.catch((error) => {
// Handle Errors here.
const errorCode = error.code;
const errorMessage = error.message;
});
This will log out users if they end their session, i.e, close their browser.
You can read more about it here: https://firebase.google.com/docs/auth/web/auth-state-persistence

Firebase auth password reset

I'm working on a firebase app that contains an authentication system that allows users to sign up/login and create a profile. The app stores and calls profile info about the users. The system worked just fine until I realized there's no way for a user to reset their password. So I added sendPasswordResetEmail function and it's been downhill since then. I'm a newbie to firebase and to StackOverflow so forgive the mess you're about to see. Am I missing something in that function?
const resetpassword = async () => {
const email = document.getElementById('email').value;
try {
const { user } = auth.sendPasswordResetEmail(email);
alert('Password Reset Email Sent!');
}
catch(error) {
console.log("error ===>", error);
if (error.message === "Firebase: Error (auth/user-not-found).") {
alert("There is no user corresponding to this email address.")}
else (errorCode == 'auth/invalid-email') {
alert(errorMessage)}
}
}
If you are using firebase version 9 then use code snippet below to reset user password
import { getAuth, sendPasswordResetEmail } from "firebase/auth";
const auth = getAuth();
sendPasswordResetEmail(auth, email)
.then(() => {
// Password reset email sent!
// ..
})
.catch((error) => {
const errorCode = error.code;
const errorMessage = error.message;
// ..
});

Firebase signInWithEmailAndPassword and onAuthStateChanged Realtime Database logging issue

I'm working on a webpage using HTML5 CCS etc, where it uses a authentication process using firebase for users. Its my first time ever working on firebase, so i still have no idea how to correctly code using it.
I manually add a admin user on firebase, so i can use those credentials to log in to the webpage. In the signInWithEmailAndPassword i used a code to log into the console some information about credentials, but whats happening is that while it does work (the authentication). The only way it logs info into the console is when i don't redirect the user to another page using the onAuthStateChanged (basically not using it at all).
Basically it authenticates correctly, but its doesn't log the info in the realtime database unless i remove the onAuthStateChanged.
Here is the code
signInWithEmailAndPassword(auth, email, password)
.then((userCredential) => {
// Signed in
const user = userCredential.user;
const dt = new Date();
update(ref(database, 'users/' + user.uid), {
Email: email,
Password: password,
Last_Login: dt
})
alert('Usuario ingresado!')
location.href = 'test.html'
})
.catch((error) => {
const errorCode = error.code;
const errorMessage = error.message;
alert(errorMessage)
});
});
const user = auth.currentUser;
onAuthStateChanged(auth, (user) => {
if (user) {
// User is signed in, see docs for a list of available properties
// https://firebase.google.com/docs/reference/js/firebase.User
const uid = user.uid;
location.href = 'test.html'
// ...
} else {
// User is signed out
// ...
}
});
I heard this process is asynchronous.
Calls to Firebase (and most modern cloud APIs) are asynchronous, since they may take some time to complete. But as soon as the user is signed in, the local onAuthStateChanged will be called - which interrupts the write to the database.
If the user always actively signs in to this page (so you always call signIn...), then you don't need the onAuthStateChanged handler and can just include the navigation code in the then:
signInWithEmailAndPassword(auth, email, password)
.then((userCredential) => {
// Signed in
const user = userCredential.user;
const dt = new Date();
update(ref(database, 'users/' + user.uid), {
Email: email,
Password: password,
Last_Login: dt
}).then(() => {
location.href = 'test.html'; // 👈
})
})
.catch((error) => {
const errorCode = error.code;
const errorMessage = error.message;
alert(errorMessage)
});
});

How to fix firebase "User is not authorized" error even though user is authenticated in registration flow?

Im trying to do a variety of firebase actions in one call in a react-native app using react-native-firebase. the flow goes something like this:
create user in authentication
send image to storage
send data to firestore
During the image-storage phase, the imgRef.putFile() function errors out saying the user isn't authorized. However im using createUserWithEmailAndPassword() (which authenticates a user in on completion) and then using the returned credential to do the rest of the work, image storage and firestore creations.
firebase storage rules are set to allow only authenticated users. here's the ruleset:
rules_version = '2';
service firebase.storage {
match /b/{bucket}/o {
match /{allPaths=**} {
allow read, write: if request.auth != null;
}
}
}
Also, I have enabled anonymous signin in authentication methods.
here's the initial action up until the error point:
return (dispatch) => {
dispatch({ type: types.REGISTER_USER });
console.log('starting registration process...');
firebase
.firestore()
.collection('users')
.where('username', '==', username)
.get()
.then((querySnapshot) => {
console.log(querySnapshot);
if (querySnapshot.empty !== true) {
registrationFail(dispatch, 'Username already taken. Try again.');
console.log("Registrant's username already exists");
} else {
console.log('Registrants username is unique');
firebase
.auth()
.createUserWithEmailAndPassword(email, pass)
.then((userCredential) => {
uploadImg(dispatch, img, userCredential.user.uid)
here's the uploadImg() function:
const uploadImg = async (dispatch, uri, uid) => {
console.log('Starting image upload...');
dispatch({ type: types.UPLOAD_IMG, info: 'Uploading profile image...' });
const uploadUri = Platform.OS === 'ios' ? uri.replace('file://', '') : uri;
const imgRef = firebase.storage().ref('profile-images').child(uid);
return imgRef
.putFile(uploadUri, { contentType: 'image/png' })
.then((success) => {
console.log('profile image upload successful.')
return imgRef;
})
.catch((err) => {
console.log('profile image upload failed: ' + err)
uploadImgFail(dispatch, err.message);
});
};
again, the error that logs in the console is:
profile image upload failed: Error: User is not authorized to perform the desired action.
logging the firebase.auth().currentUser right before the uploading() function returns the current user object successfully.
this security rule issue also happens with Firestore, despite my security ruleset for the given collection being:
match /databases/{database}/documents {
match /users/{uid} {
// allow new user to check phone numbers
allow read: if true
allow update, create: if request.auth != null
allow delete: if request.auth.uid == uid
}
}
This is a part of my registration flow. I collect input, send relevant data to redux action, create a user, once the user is created, I add some data to a document in firestore. this makes no sense. im referencing the documentation and it still doesn't work.
How can this be fixed?
It seems to be an issue with firebase that you have to logout() the user once before you can log in after user creation. I faced the same issue and this is my workaround:
firebase.auth().signInWithEmailAndPassword(userEmail,userPass).catch((error) => {
/*console.log('Could not log in user');*/
console.log(error);
firebase.auth().createUserWithEmailAndPassword(userEmail,userPass).catch((error) => {
/*console.log('Could not create user');*/
console.log(error);
}).then(result => {
firebase.auth().signOut().then(() => {
firebase.auth().signInWithEmailAndPassword(userEmail,userPass).then(result => {
/*console.log("here is you logged in user");*/
})
});
});
});
});

How to set the user as logged in on firebase.auth(node.js)?

I have an app using sign in with a custom token, written on webpack observes. What I want to do now is mark the user after successful login by custom token as logged on firebase auth and firebase firestore, where I have the collections with users, and document for each user with data and some uid. I don't know how to to that.
Here is my code:
generateToken(uid) {
const uid = 'some-uid';
this.trigger(this.signals.action.onGenerateToken);
firebase.admin.auth().createCustomToken(uid)
.then((customToken) => {
console.log(customToken);
})
.catch(function (error){
if (error.Code === 'auth/invalid-custom-token') {
alert('The token you provided is not valid.');
}
else {
this.trigger(this.signals.error.onGenerateToken);
}
})
}
login(uid) {
firebase.auth().signInWithCustomToken(token)
.then(function() {
var user = firebase.auth().currentUser;
if (user) {
//mark the user as active (logged) after successful login on firebase auth and firebase firestore
};
this.trigger(this.signals.success.onLogin);
})
.catch(function(error) {
if (errorCode === 'auth/too-many-requests') {
this.trigger(this.signals.error.tooManyRequests);
}
else {
this.trigger(this.signals.error.userDisabled);
}
});
}
If I understand your question correctly, first create a reference to your user document, then call update() on the reference and pass in an object containing the properties you want to update and their new values.
let userRef = firebase.database().ref('users/' + userId);
userRef.update({active:true});
Check the firebase docs for more info on how to read and write to firebase.

Categories

Resources