-
-
Notifications
You must be signed in to change notification settings - Fork 4.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Two-Factor Authentication #4024
Comments
We could probably bake 2FA in, with QRcode generation, and secure login/sessions. This would be a major feature where users could opt-in for 2FA. That would be quite a major development touching a few areas of the API, but that wouldn’t be anything unachievable |
What do you think of the beforeLogin trigger solution? I noticed a discussion on that a few days ago but it didn't end up addressing the suggestion. |
That would be kind of messy as tou’ll Need to store each user’s secret anyway, enforce etc.. that could help you, but i’d Like that to be baked in :) |
I like the sound of a native 2FA solution as well! I will try to start looking into a first stab at this soon. |
Just bumping this, I think this would be 💯 % awesome to put this in. If I were to just brainstorm off the top of my head this is what comes to mind.
As for blocking requests when pending 2fa, the primary concern is in making sure that until the user can authenticate themselves they should not be granted access as themselves. Since we have ACLs, this, in a nutshell, means we need to treat them like they're anonymous and subjected to the restrictions of public read/write. There are a number of ways this could be done, but I'm wondering if maybe not returning the user on successful login with 2fa enabled would be the easiest. Instead we could return something to indicate that further authentication is required. That's a pretty rough outline, and it doesn't elaborate on how the SDKs would go about handling this, but it would be a start in the right direction 👍 . |
That would be at session token emission level, when enabling 2FA, all sessions would be destroyed, the 2FA logIn flow could force having an additional ‘code’ property alongside username/email + password, I dot believe there’s a need for a temporary state (valid username + pass) waiting for ussename + password. Also, providing username + code only should work instead of username + password ? |
Perhaps providing the 2FA code in je password field would be ok-ish, not sure... |
The username and the code combined would have to be something separate, but it would use some stage so you can't just jump to it unless you've already logged in. The thought of having 2FA directly with the username and password did occur to me as well. Normally it's requested separately, but honestly I can't think of a good reason why it's not requested up front. If we did, we just authorize on an all or none basis, either it matches password and the 2F code or it fails. That could make it a lot easier to do this, no extraneous 'stage' or 'steps' required (beyond the step of validating the 2F token itself). |
The thing above would have to be something like The only issue with having the password and two factor go together is when your 2nd factor is something like a static code that's generated upon successful login. You wouldn't be able to get your code to login with until you had successfully logged in in the first place. If we did an adapter to allow extra 2FA methods that could screw things up if someone did something like an SMS or email code. |
To enable2FA you usually have to provide the generate code to guarantee he user has property setup his account, so no chance to get locked out. Maybe an endpoint /enable2FA that takes the sessionToken (you need to be loggedin) and the 2FA code, if you fail to provide a valid code, your account stays 1FA secured, upon success, the sessionToken gets regenerated, and 2FA is enforced |
Yep, for setting it up the user would have to successfully provide the proper 2F code at least once before it can be enabled. Could split that up into something like We would need to save and track that a user is in a state of:
Maybe could add a step for disabling two factor if we want to keep it strict. |
@flovilmart, @jasonm1, @montymxb |
We haven’t worked on it, it’s still up for grabs |
well i think everything can be achieved through cloud code, baking it in is a bit more difficult. |
@georgesjamous are you any other suggestion? |
Well, i would wait for a fully implemented solution without cloudcode to use it. There are many ways to achieve this, for a quick setup you could do it by implementing 2 functions 'verifyAccount' and 'provide2fa'. And if the beforeSaveHook works for '_Session', you can deny any session that is authenticated via the legacy login by responding with an error. (i have never tried a hook with sessions) |
Session hooks do NOT work. There is an issue and pending PR for this functionality. Just FYI |
Guys how about implement this with more general tools like Authelia. |
Well then if there is no way we can intercept the login request just from using cloud then its impossible - at this point - to implement 2FA securely. |
Maybe we also can set login endpoint to |
what do you mean by this ? |
Login endpoint. |
@georgesjamous and other guys any idea about this? |
@mnlbox Any other solution using cloud code only will not be secure. The only problem is that you cannot intercept login (or sessions) at this time in cloud code, and if you implement you own, anyone with sufficient knowledge (clientkey, appid, username and password) could login the traditional way and get a session token. If you are determined to have 2fa working right away (and this is what i think is going on here), a messy way would be to fork parse-server, alter it so you can get a beforeSave hook on sessions. Once you do, whenever a session is created you can check for a 'temporary-one-time-use-2fa-token' that is generated by your 2fa code. So, |
Maybe useful: https://passwordless.net/ |
@mnlbox Did you find any solution in the end? |
I haven’t! |
Too bad you moved to Strapi, I was about to start working on it as we’ll need it for future projects. |
@flovilmart please tell result here. Maybe we can switch back to Parse if it have 2FA support. |
We haven’t started yet. The best way to get it faster would for for you to implement it and propose a PR |
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions. |
What about:
So you may have unauthorized user log-in but not capable of doing anything. Could be a good solution? We could try to implement it @Etto91 |
This could be implemented on the _User class, adding the TOTP token to the _user object (private obviously) in order to create a session, as user need to provide the username, password and OTP. One security enhancement would be to generate a restricted session token, that is used solely with an OTP and valid a few minutes. This session Would ne generated on successful user login. |
@mnlbox, @flovilmart, @georgesjamous, @addisonElliott has anyone tried to work on this recently ? or got any pointers. I found this PR #5305 which is a start, 2FA is a really essential and useful feature that should be part of any authentication system, it would be great if we could pick this back up and work on an implementation |
very bad pr #5305 :) |
@Etto91 you got further than anyone else with it so not so bad. I dont suppose you did any more work on it that I can use for inspiration :D I don't know much about the parse internals but you seem to. |
Re-opening as discussion around this feature continues. |
@mtrezza happy to be a part of the implementation of it but I will need some assistance or someone who knows the parse internals to brainstorm with. @Etto91 seems to be be on the right track aside from the security gaps. For my own use case I want to integrate Google Authenticator app. In my mind the way this works is that the user is logs in - they then get a basic session which cannot do any parse actions, other than call functions which may utilise My own use case utilised custom auth adapters which make use of So as I see it in the framework the bases that need to be covered all start with the following:
After that I am unsure of parse internals other than a basic understanding as well as the PR by @Etto91 which has given me some kind of base, aside from that I am happy to take direction and not reinvent the wheel i.e add 3rd party libraries to assist in the creation of Google Auth OTP etc. |
Or maybe we grant some kind of new session, then with the OTP code submission we pass this new session type along with the validation, if it validates then we pass back a normal session string which the user, on their client side OTP page can use |
Hey all, I've just created a PR (#6977) that continues the work towards inbuilt 2FA (thanks to flovilmart for his work in getting this started). My implementation requires users to enrol via Now, once a user logs in, a custom error (212) will be called. This is where the UI would have to show 'enter code', where the user would go to Google Authenticator, copy the code, and enter in the app. Calling Parse.User.logIn('username','password','token') with the token they've entered will allow the entry, providing it's a vaild code. In order to force every user to enable the 2FA such as @REPTILEHAUS has suggested, you could use What are all of your thoughts on this approach? |
Yep! |
I see no straightforward way to implement two-factor authentication (2FA) in Parse Server. Ideally this would allow:
I initially started implementing this in my client-side code (PHP) for my Administrator users using Goole Authenticator, but then I realized anyone with the AppID and the Admin password can simply write their own code to get around it. Oops.
I then thought about storing a second factor, or possibly an IP whitelist, and rejecting any requests in beforeSave, beforeDelete, or beforeFind Cloud Code where the client did not provide the second factor, but that seems clunky. It is also difficult to rate-limit, since the malicious user would be able to log in and only be blocked at the point of accessing data. Further, I believe the second factor would need to be stored apart from the User object itself, since once logged in, the user can access its own data.
@flovilmart suggested using a 3rd party Auth adapter, for example Google, which could potentially work in my case since I only care about the extra security for certain users. However, I don't want to require Google login for everyone, which means native username/password login is still available. Checking triggers in Cloud Code for the particular users could be a workaround, but again, the user would be checked at the point of accessing data, not logging in. I also don't know if this solution would generalize to others' use cases.
One solution I see is to add a beforeLogin trigger in Cloud code. A routine in this trigger could check the second factor (stored with the user object) and reject the Login if it does not match or is not provided. This would also allow for IP whitelisting for certain users (reject login attempts from non-listed IPs) or any variety of custom authentication methods.
Another may be to have per-user control over the authentication method. For example, if a user can login with Google, the user can ONLY login with Google, and not username/password.
I am not familiar enough with how Parse Server handles logins to know if the beforeLogin trigger is feasible, or if some other 2FA system would be easier to implement.
The text was updated successfully, but these errors were encountered: