Extend Meteor accounts-password to store multiple passwords - meteor

I am using the accounts-password package in my Meteor app.
I want to securely store user passwords for an external RESTful API that I will be accessing through HTTP basic access authentication (I'm aware of OAuth, but cannot use it in this case). These user passwords may differ from the passwords the users use to login to the Meteor app, so I need to store them separately.
Is it possible to extend accounts-password (or make use of its functions) to securely capture these external passwords from a user, store them against their user profile and make API calls from the server using them?
If not, how else can I achieve this simply and securely?
Many thanks in advance

In looking through the code for accounts-password, I see that it hashes the passwords, which won't work for what I want as I have to be able to decrypt back to a string that can be sent as HTTP Basic Authentication.

users is just a collection in the mongodb, thus you can store whatever you want to there and update it
Meteor.users.update({_id: Meteor.userId()}, {$set:{
'profile': {
'service1': {
username: name,
password: hash-password
}
}
}});

Related

Flutter Firebase Forgot password

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).

Firebase user login managing connection with API

I'm quite new to firebase and I am looking for best practices using it, maybe I will be able to get some advices here.
What I want to do:
User login using firebase.
Problem:
I save user info in firebase but use SQL server as database where I need that user information as userId
Question: How should I approach that?
Register user on firebase and when I get response with userId and token, save it to my sql database too?
what's my current approach:
At this stage we're thinking of creating new users via admin panel (and then these users can sign in)
Would it be good approach to add user to sql database, send email to finish registration (create pasword) and then add this user to firebase, and with response send request to my backend where I update user that he's verified, add userId and token?
It's very common to store additional information about Firebase Authentication users in your own database. Whether it's good in your use-case is subjective, but it's definitely common.
Assuming that you have a server interacting with SQL server on the user's behalf, be sure to pass the ID token from the client to the server, decode it there, and then use the UID (and other claims) from that token in your database interactions. Don't allow the user to just pass their UID, as that'd be a security risk.
For more on this scenario, see the Firebase documentation on verifying a user through their ID token.
Your approach with an admin panel is a common first approach, but not something I'd recommend. Since you'll need to allow the user's to sign in with email/password, there is nothing keeping them from calling the createUserWithEmailAndPassword API themselves on your project. So I'd recommend leaving the creation completely to the clients, and save yourself from having to consider that an abuse scenario.
If you want to control what users an access the data, store a list of email addresses (since you seem to associate that with uniquely identifying a user already) in the database, and check the email address in the ID token is in the list (and is marked as verified in the token).

How to check if current password is valid in firease admin sdk?

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.

Login with Email/Password without enabling it

My current registration process looks like this:
App sends a registration request via my REST Api to my backend with information like username, password, email etc.
My backend checks if the username is available. If it is, it creates a new user with the admin api. If this is successful as well it saves the username to the realtime db.
When I want to log in with loginWithEmailAndPassword it says that I can't because PasswordLogin is disabled.
Since I don't want anybody to just register with registerWithEmailAndPassword I want to keep it disabled.
My question now is, how can I log a user in without enabling Email/Password?
Or would there even be a possibility to exploit the system when I enable Email/Password?
EDIT: What I'm not sure about is if registrations with registerWithEmailAndPassword are guaranteed to be from my app?
firebaser here
There is no way to sign the user in to a disabled provider. I'm actually quite surprised that you can register them.
There is no way to prevent users from registering after you enable the provider.
But it's quite easy to only allow users that your administrative back-end created access to certain data. Just make the admin script write the UID of users it creates to a whitelist:
/whitelist
uid1: true
uid2: true
And then in your security rules only allow access on whitelisted users:
".read": "root.child('whitelist').child(auth.uid).exists()"

Meteor: How to create a user account on the server without sending plain text password over the wire?

I am creating an admin interface and the admin needs the ability to create user accounts, pick and change the password.
If I try to call Account.createUser on the Client, it automatically logs the user in as the new user, which is what I do not want.
An approach that will work but I am afraid might be insecure is:
Call a server side Meteor method with the username and password for the new account that the admin has picked.
On the server I can use Accounts.createUser to create the new user with password and it will return the new UserId.
But with this approach I am sending the password in plain text over the wire. We could use https and ssl and I think we will be safe, but is there a more secure way to do this?
A much better practice which avoids any user knowing any other user's password is to create the account on the server (as you suggested) but don't specify a password, instead let the user pick it later. From the docs
Call createUser with the email option and then call
Accounts.sendEnrollmentEmail. This will send the user an email with
a link to set their initial password.

Resources