Description
I see no straightforward way to implement two-factor authentication (2FA) in Parse Server. Ideally this would allow:
- 2FA using one or more methods (Google authenticator, SMS, email)
- Device memory (with periodic expiration) so users don't necessarily need to enter the second factor all the time
- Any particular user to have 2FA enabled/disabled optionally
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.