I'm here because I'm working on this repo.
When i compare the hash from firebase and this hash i created using the utility created by firebase for the same password using the same salt and the same parameters, they are not the same.
Is someone getting any idea for a sample of solution ? I'm totally stuck and i do not understand what is happening here ^^'
Thx !
EDIT : the hash function ( aslo here )
hash (password, salt) {
return new Promise((resolve, reject) => {
exec(
`${__dirname}/../scrypt/scrypt "${this.signerKey}" "${salt}" "${this.saltSeparator}" "${this.rounds}" "${this.memCost}" -P <<< "${password}"`,
{ shell: '/bin/bash' },
(error, stdout) => error ? reject(error) : resolve(stdout),
)
})
}
EDIT 2 : I forgot to say that, but I export users password hash using the admin sdk.
The Firebase documentation states that "on successful sign-in, Firebase re-hashes the user's password with the internal Firebase hashing algorithm". If you've already logged in you would see a unique hash so I do not think you should be expecting an exact match to your project's keys.
I answer myself : the probleme was coming from the way I export users. I was using JS Admin SDK and the listUsers() function, but apparently that's not return to you the right password hash (maybe for security, I asked i will update this post when I know).
If you want to export your users and use firebase-scrypt to verify their password, export your users using firebase-tools and the command auth:export
Related
Before adding a new user to Firebase Authentication should the name be qualified first:
The name must not be null
The name must not be empty
The name must contain one D character at least
Examples:
"Frank van Puffelen" => It is unacceptable because there is no D character
"Doug Stevenson" => It is acceptable
"Alex Mamo" => It is unacceptable because there is no D character
"Renaud Tarnec" => It is acceptable
"" => It is unacceptable because it is empty value
NULL => It is unacceptable because it is a null value
On the client side before adding a new user I check if the name follows the above qualifiers or not but the problem is if someone modifies the code.
The client side is not safe and I should check again on the server side if the name follows the rules or not.
So the question is why there is no Rules tab inside Firebase Authentication?
Since you want to check that the user name (the displayName I guess) follows the set of constraints listed at the top of your question you can take advantage of the new blocking Cloud Functions that "let you execute custom code that modifies the result of a user signing in to your app".
For example:
exports.checkDisplayName = functions.auth.user().beforeCreate((user, context) => {
if (!user.displayName || !user.displayName.toUpperCase().includes('D')) {
throw new functions.auth.HttpsError(
'invalid-argument', `displayName is invalid`); // adapt as follows
}
});
More details in the specific section of the doc, and in particular on how to catch and handle the error in your front-end.
The security rules concept is used to prevent unauthorized access to your Firebase resources such as database and storage. The displayName property is optional irrespective of which authentication method you chose.
If you require users to have a displayName then you can:
Check if user has displayName set every time they login. If not, then redirect them to a screen where they can set a name.
Disable sign-ups directly from Firebase client SDKs and use Firebase Cloud Functions with the Admin SDK to create user. No one else can reverse engineer the functions code so the validation on server side will ensure a user has displayName.
exports.createUser = functions.https.onCall((data, context) => {
const { displayName, email, password } = data;
// check if displayName is valid
// if not return error
// create user using Admin SDK if all data provided is valid
return { message: "User created" };
});
Then you can login your user with the Client SDK using signInWithEmailAndPassword()
In case you are using any Auth providers e.g. Google, Facebook and the display name is unavailable for some reason, then you'll need some custom logic as explain in method 1 above.
Either of the solution does not prevent users from using updateProfile() APIs so make sure have some validation on client end as well and report such events somewhere in the database where you can monitor it.
I'm trying to use multi-tenancy in firebase. All has gone well, except that after creating a user, the returned user missing the tenantId. I'm trying to create a custom claim with hasura so that I can tell the user's tenant:
exports.processSignUp = functions.auth.user().onCreate((user) => {
const customClaims = {
"https://hasura.io/jwt/claims": {
"x-hasura-default-role": "user",
"x-hasura-allowed-roles": ["user"],
"x-hasura-user-id": user.uid,
"x-hasura-tenant-id": user.tenantId,
},
};
However, there seems to be a bug where the onCreate request does not properly return the tenantId, as acknowledged here: https://issuetracker.google.com/issues/160809045
Unfortunately I can't fetch the user again to try and grab the tenantId there because the user is scoped to the tenant. It won't find the user given the user's id because I haven't set the tenant.
Does anyone more familiar with firebase/google identity management know of a work-around until that bug is fixed?
I already meet familiar with this case. Using Google identity tenant and Hasura too
And I can check user.tenantId as normally. I see this post 1 year ago. But still want to give you comment with a familiar case
I must be missing something really basic here... but any time I make a call to my Cloud Firestore db and I try to institute any kind of rules for security, they always fail.
Doing something like
match /users/{userId} {
allow create, read, update: if true;
}
works, but it obviously defeats the point. However, if I do any kind of additional scrutiny, such as the go-to example in all the docs like
match /users/{userId} {
allow create, read, update: if request.auth.uid != null;
}
it fails every time. Am I missing something obvious in how I'm wiring together my client side code?
Here's my client side code that logs the user in, and then makes a call to the db to grab a user.
(Note that in my db the keys for the users are by email, not by uid)
// this is a snippet from the code where I log the user in
firebase.auth().signInWithEmailAndPassword(email, FIREBASE_USER_PASSWORD)
.then(user => {
// the user comes back successfully logged in,
// I grab its uid and add it to a preparedUser object that I've been building,
// then pass this user to my getFirestoreUserObject function
preparedUser.uid = user.uid;
getFirestoreUserObject({dispatch, user: preparedUser, navigate});
})
// then the getFirestoreUserObject function:
// note that all the code below works fine when there are no security rules in place
const getFirestoreUserObject = ({dispatch, user, navigate}) => {
const {name, email, imageUrl} = user;
// if I ask for currentUser here, I get back my logged in user
const currentUser = firebase.auth().currentUser;
// email is defined correctly here as the user's email
firebase.firestore().collection('users').doc(`${email}`)
.get() // the request fails here due to insufficient permissions
.then(doc => {
if (doc.exists) {
const currentUser = doc.data();
getUserFavorites({dispatch, currentUser, navigate});
} else {
createUserInFirestore({dispatch, user, navigate});
}
})
};
Is there something obvious that I'm missing? If I log a user in via firebase.auth(), and then immediately after call firebase.firestore(), shouldn't that have the context of the auth'd user? If not, how do I pass it to the firestore call?
Thanks!
After weeks of searching, and firestore and auth both working independently but not together... it was the most simple thing.
I was on firebase 4.x, which was the latest available when I started my project. Then, when I came around to adding auth rules, the latest published documentation on firebase for how to do the db rules (which I hadn't even looked at when I started, but came back to months later when I was ready to implement them) were listed using firebase 5.y. Updated my package.json, npm install, and everything magically worked :(
Hope this can help someone else... make sure you're on at least version 5!
Update emulators using: npm install -g firebase-tools
June 2021
Still have the issue with firebase cli 9.12.1.
Had to downgrade firebase JS to 8.3.1 to make it work but with that version it tries to verify the user online and not with the emulator
See this post
I had the same problem but what ended up working for me is updating the firebase cli by running npm install -g firebase-tools which in turn updated the cloud firestore emulator
NB: There might be a different way of updating your firebase cli depending on the method of installation that you used. The above solution will work if you used npm to install the firebase cli. For other ways of updating the firebase cli, see the firebase docs.
You should use firebase.firestore().collection('users').doc(`${currentUser.uid}`).get() instead of firebase.firestore().collection('users').doc(`${email}`).get().
This is because your security rules
match /users/{userId} {
allow create, read, update: if request.auth.uid != null;
}
check for the uid of the user when determining whether or not to provide access to the data to the user, not the user's email.
Hope that helped.
So, maybe I missed this somewhere in the docs but I couldn't find anything of the sort.
I wan't my users to have to type in their current password to be able to create a new one. From what I understand if the user is authenticated he is able to update his password without providing his current one.
Even if this might be somewhat secure I would rather have him type his old one to prevent people from going on already authenticated sessions from say family members or so and changing the pw.
Is there any way to do this?
(I have no problem using the Admin SDK since I already set up a server for these kind of things)
UPDATE: (Use - reauthenticateWithCredential)
var user = firebaseApp.auth().currentUser;
var credential = firebase.auth.EmailAuthProvider.credential(
firebase.auth().currentUser.email,
providedPassword
);
// Prompt the user to re-provide their sign-in credentials
user.reauthenticateWithCredential(credential).then(function() {
// User re-authenticated.
}).catch(function(error) {
// An error happened.
});
PREVIOUS VERSION
you can use reauthenticate API to do so. I am assuming you want to verify a current user's password before allowing the user to update it. So in web you do something like the following:
reauthenticateAndRetrieveDataWithCredential- DEPRECATED
firebase.auth().currentUser.reauthenticateAndRetrieveDataWithCredential(
firebase.auth.EmailAuthProvider.credential(
firebase.auth().currentUser.email,
providedPassword
)
);
If this succeeds, then you can call
firebase.auth().currentUser.updatePassword(newPassword);
How to do user authentication from wordpress database in nodeJS.
I need to validate user if username/password is correct, using wordpress database. Wordpress is using PHPass PHP library to encrypt passwords. But I need to match password in NodeJS.
Edit: Today there is an implementation which supports Wordpress portable hashes: wordpress-hash-node.
Previous reply:
Sigh... I took an interest in this, and spent half an hour pouring through PHPass source code. Then I googled for node phpass.
Edit: On closer inspection, this seems to only implement bcrypt encryption, while the PHPass default (which I think Wordpress uses) is something they call "Portable Hashes". node-phpass throws 'Portable hashes are not implemented' when you ask for Portable Hashes. I suggest you implement that for node-phpass and send a pull request.
For Wordpress 4.9.5, in NodeJS after
npm i wordpress-hash-node
var hasher = require('wordpress-hash-node');
let wordpressHashPass = "$P$BzPE3JGpq4CUpvpMHhtPh3lZmIoG.s1";
let wordpressPlainTextPass = '(&#fZsImcKq7K3Lmd&qBe!Jx';
var checked = hasher.CheckPassword(wordpressPlainTextPass, wordpressHashPass); //This will return true
console.log(checked); // returns true
var hasher = require('wordpress-hash-node');
let wordpressHashPass = "$P$BzPE3JGpq4CUpvpMHhtPh3lZmIoG.s1";
let wordpressPlainTextPass = 'goodday';
var checked = hasher.CheckPassword(wordpressPlainTextPass, wordpressHashPass); //This will return false
console.log(checked); // returns false
wordpressHashPass is the MD5 hashed password that you can find in the wp_users table of Wordpress for a user.
wordpressPlainTextPass is the plain text password that the user types in the password field.
The method CheckPassword compares the plain text password and the hash password. It returns true if it coincides and false if it does not coincides.