I'm working on a project where I'm using the authentification of firebase to use the forgot password thing. However, I have a collection users that I use as well and need the password field to be updated in the collection as well.
Any solutions please ? I can't seem to find a way to get password from authentification.
There is (very intentionally) no way to get a user's password from Firebase, and wanting to do so typically indicates an anti-pattern in your implementation.
If you already verify the user's credentials elsewhere, you shouldn't use Firebase to do the same (but for example mint a custom token based on the external credentials). If you use Firebase to verify the user's password, you shouldn't repeat that in your code (although you can for example decode the user's ID token to determine their identity).
Related
Could I know how to get User data by Email registered to Firebase Auth?
Because I'm using Firebase auth to create users by createUserWithEmailAndPassword in the system from backend. In that method, I'm avoiding password encryption.
And In the future, If I need to update a user password from the backend I want user data. And I don't save uid in my MongoDB for security reasons.
I read so many articles that say use getUserByEmail I think this is deprecated.
How can I do this? Need help :)
The documentation doesn't say anything about getUserByEmail being deprecated. It literally says:
In some cases you will have a user's email instead of their uid. The Firebase Admin SDK supports looking up user information with an email:
So, you should just use what the documentation says.
I did some research and experiments on integrating LINE login with Firebase Auth using Flutter. I have some questions:
Looks like in Firebase Auth, there are AuthProvider, and in Flutter source code, I also found an OAuthProvider. There you can create Credential to include your idToken and access token. But I don't know how to specify the providerId in that Credential. I guess it is not possible, because Firebase hasn't integrate LINE login. The client side api: logInWithCredential can ONLY work with Firebase supported login methods, and you have to enable them in your Firebase console. Am I right?
So it looks like now I have to setup my own server to exchange LINE access token to Firebase custom token. In my server, I first verify access token and grab the LINE user profile, then I create a custom token, but there I have to decide a UID, which I have to use some pattern like LINE:${LINE_UID}. This looks like some hacking, is there a better way?
Admin API to create custom token only accept UID or optionally a user claim, I have no way to set its display name or some other basic info. So if I directly send the token with UID like LINE:${LINE_UID} to a client, then the client logInWithToken, it will create a user without display name if it doesn't exist. The only workaround I can image is, in the server-side, generate the LINE:${LINE_UID} and look up it in Admin API, if it doesn't exist, then I create a user with a proper display name. This looks again not so good, because the document said if you do logInWithToken, it will create one if it is not there, and we cannot use that because I want to set it's display name when it is created. Any better solution?
I want to link a user with multiple auth provider. I saw in the Firebase JWT, they are well included, that is cool. But those linked elements are user profile get via credential. So can we link a user to a LINE login? Which is not built-in Firebase Auth Provider? Is auth provider linking only valid for Firebase built-in provider?
Regards,
Xiang.
You're asking way too much in a single post, which makes it hard to help. I'll try to address below, but please follow the advice on How do I ask a good question going forward.
The general approach for adding LINE as an authentication provider is shown in this blog post: Authenticate your Firebase users with LINE Login. There is also a example, which shows how to use Cloud Functions as the server component for this. If you get stuck implementing those for Flutter, post the minimal, complete/standalone code that reproduces this issue.
The client side api: logInWithCredential can ONLY work with Firebase supported login methods, and you have to enable them in your Firebase console. Am I right?
Nope, you're wrong. You can also provide your own sign-in provider for Firebase, and use the tokens you mint there with the Firebase Authentication SDK.
This looks like some hacking, is there a better way?
The UID can be whatever you want, but you'll have to ensure it is unique. A common way to ensure global uniqueness is to embed some identifier for the provider in the UID. If you prefer another way to ensure global uniqueness, you're free to use that too of course.
I have no way to set its display name or some other basic info [when creating the account]
This is indeed a common problem with some providers, as you for example can't set the display name for the email+password provider until after the account has been created. With a custom provider you can put whatever information you want in the initial JWT already though.
can we link a user to a LINE login? Which is not built-in Firebase Auth Provider?
See Linking custom auth provider with Firebase
Late to the party .
but This article helps you which I publish on Medium.
I'm using A Flutter plugin LINE's native SDKs in Flutter apps with Dart. The plugin helps you integrate LINE Login features in your app. You can redirect users to LINE or a web page where they log in with their LINE credentials. package
Also, I make a git hub repo for the same.
Did you check out the firebase_auth plugin? It has lots of helpfull features.
https://pub.dev/packages/firebase_auth
I was recently having an argument with another programmer mate of mine regarding storing Firebase Auth UID (just the uid nothing else) in a cookie with sameSite: 'strict' enabled.
What's the argument about
Currently, I am working in a Nuxt JS project where I am saving the user's uid on onAuthStateChange() event in a cookie with sameSite: 'strict' enabled so that I can grab it in my serverMiddleware code and do stuff with it.
I have checked this firebase doc about managing cookie and it shows how to store the JWT idToken in a cookie and then in the server decode it.
In fact, that is who I initially coded my work. But due to some requirements, it was super helpful if I store the uid instead. So, I did that. Then I started reading about how can I hack my own data to see if anyone can harm my data from the uid in the cookie.
Then I stumbled upon to this firebase doc: Use the Cloud Firestore REST API which shows how to get the firestore data using REST API and I figured out that you need to provide Google OAuth 2.0 token in the header of the API call in order for it to work, otherwise even if you put the correct URL with all the collection name and everything (which is hard for an outsider to know, but lets assume he knows), you will get nothing but this:
{
"error": {
"code": 403,
"message": "Missing or insufficient permissions.",
"status": "PERMISSION_DENIED"
}
}
I have also tried to run code in browser console in order to hack the data out of my project. But That didn't work as well.
Now in order to get the Google OAuth 2.0 token, the person must need login access to my account which is not that easy as I have a unique long password along with 2 Step Authentication with phone OTP & push notification. Besides if anyone has login access to my Google account, he can easily go to console.firebase.com and see the data, so at that point, nothing will matter.
But I did say that if anyone is using firebase Realtime database then I will not recommend storing the uid in a cookie as the realtime database provides easy REST API without any authentication layer to fetch data. At that time I would recommend using JWT idToken instead.
So, what's the final question?
The final question is this:
If someone is using firebase auth & firebase cloud firestore (not realtime database) using firebase SDK in his project, is it secure to store just the uid in cookie instead of storing JWT idToken if it will reduce the code complexity and code execution time over using idToken?
I would love to know your thoughts on these as there are many super experienced devs beside two programmers arguing.
My friend keeps telling me that storing uid in the cookie is not sure, but when I asked him why exactly, he had no concrete answer. As what is secure and what is not a universal thing and changes as you change your tools. But in this exact context what do you guys think? I know that normally in most cases it is not a secure thing, but I am asking about this specific context only.
It is in fact fairly common to expose the UID of a user to other user to identify that user. See Firebase - Is auth.uid a shared secret?
There is nothing insecure about storing the UID in a cookie, nor in reading that cookie in your middleware. But if your middleware then assumes that the UID is the authenticated user, you have a security risk.
What is keeping any other user from putting your or my UID into that cookie, and thus getting access to your or my data?
Also note that UIDs don't change over time, so if ever one (even inadvertently) leaks, you could impersonate that user forever.
ID tokens on the other hand have a limited lifespan (currently about an hour), which limits the risk if they accidentally get exposed.
When using Firebase's Email & Password setting it seems like there are no security constraints on the password.
For example I could create the following user:
firebaseRef.createUser(
{
email: "john.doe#example.org",
password: "j"
});
I'd like to at least set a minimum password length. Does firebase provide a way to do this?
A FirebaseAuthWeakPasswordException is thrown when using a weak password (less than 6 chars) to create a new account or to update an existing account's password. Use getReason() to get a message with the reason the validation failed that you can display to your users.
See https://firebase.google.com/docs/reference/android/com/google/firebase/auth/FirebaseAuthWeakPasswordException for more details.
There is currently no way to configure a minimum password length or strength for Firebase email+password Authentication.
You could build such a restriction into your app, but tech-savvy users can bypass that by calling the API. Or you could introduce a "isPasswordApproved" flag that only a server-side process can set, and then validate the password strength there. But neither of these sound very appealing.
I would argue that implementing front-end validation here should be enough (at least in a big portion of applications).
If the purpose of this validation is to protect the user himself, then there is no harm in allowing a user to hack your app and set the password to password, go to a forum and post the credentials, and jump out of a window.
The problem is with the Reset Password form that Firebase sends. It would be nice to use it and not have to build this out as well.
I have a firebase powered app. The requirement is to update the account password by typing the currentPassword and the newPassword.
On the server (firebase cloud function + admin sdk) i need to check if the provided currentPassword is valid.
When an account is created for the first time, firebase automatically encrypts the password, and gives me back only the hash.
The problem is - this encryption is done automatically, under the covers.
Without having access to the encryption method, i can't obtain the hash of the currentPassword in order to compare it to the stored hash of the real password.. to see if this 2 hashes match.
So how can i check if the currentPassword is valid? How to get access to the same method firebase-auth uses for encryption?
I coudn't find anything relevant so far. am I using the wrong approach here? Why is it so hard to find it ?
I'm not quite sure that you can verify the password with cloud function, the point is to make sure that hackers would not be able to recover users' passwords even if they somehow hacked into the server, if you can recover the passwords by knowing the hash and salt, why wouldn't them hackers? However, you can do that in your app:
firebase.auth().currentUser.reauthenticateWithCredential(firebase.auth.EmailAuthProvider.credential(firebase.auth().currentUser.email, oldPassword);
Also, just to provide an alternative way for users who want to change their password, just send them a reset password email, this way, it's quite safe and they won't have to enter their old password:
firebase.auth().sendPasswordResetEmail(firebase.auth().currentUser.email)
passwordHash and passwordSalt are only available when you retrieve the user information via a call to listUsers(). Therefore they are only useful if you ever migrate user data from Firebase Auth to a different user management system.
For this use-case i needed to implemented 2 different approaches.
case 1: when the agent changes it's own password.
I use browser code as provided by #K.Wu - firebase automatically sends a password reset email to the user.
firebase.auth().sendPasswordResetEmail(firebase.auth().currentUser.email)
case 2: when a high privilege user: admin / manager changes the agent password
I use server code - firebase admin sdk. Here the manager doesn't know the currentPassword, and doesn't need to know since the firebase-admin can change account passwords without needing to send confirmation emails.
Still, What i don't uninterested is this:
When i create the user for the first time, firebase gives me a userRecord object which has 2 properties: passwordHash, and passwordSalt. But since i can't encrypt a given password manually, then what is the use of this 2 properties? When are they ever needed?
I considered them being specifically designed for when you compare the hash of a provided password - with this passwordHash that is stored in firebase. Seems this is not the case, and I'm still confused a bit.
Anyway splitting the password update functionality between client and server, based on who performs the action, as explained above - worked like a charm.
note: also this setup allows for the account creation to be done by admin / manager.
I think you can check against the password hash with scrypt. You need to download the scrypt config from account and compare. Please check the below docs
https://firebaseopensource.com/projects/firebase/scrypt/
Util function for scrypt if found here for hashing and verification
https://github.com/xeewi/firebase-scrypt
Note: Only listUsers() method will return the passwordHash. getUser() or no other function will return the passwordHash values.