I’ve designed my app to allow the user to choose from several authentication and verification methods:
Email + password
Email + emailed token (accounts-passwordless)
Email + authenticator app (accounts-2fa)
Email + WebAuthn API
They can choose to enable one or more of these methods. When logging in, if multiple authentication methods were setup for the user account, the user is prompted to choose one. Every method works great on its own if only 1 is configured. However, if the user configures both accounts-passwordless and accounts-2fa, and selects accounts-passwordless as the method they wish to use for a given session, Meteor.passwordlessLoginWithToken() does not allow them to log in using the token alone, it throws an error “2FA code must be informed” (as per the docs)
Is there some way to allow the user to login using accounts-passwordless alone even when accounts-2fa is enabled for the user? It’s overkill to have the user enter: email + password + token-from-email + token-from-authenticator-app.
What I’m wanting to do is allow the user choices and flexibility. A user might want to enable passwordless as a backup to their 2FA, so if they lose their phone (which has the authenticator app), they can still login using passwordless. But given that having 2FA enabled always forces its use, they wouldn’t be able to log into my app if they lose their phone.
Yes, 2FA offers stronger protection than passwordless via email, which itself offers better protection than a password alone, but plenty of apps & sites are perfectly fine with using passwordless alone. I don’t see the point of forcing 2FA on top of passwordless.
BTW, what I’m trying to setup is exactly how Stripe does its MFA:
There must be a mechanism to reset 2fa based on an initial reference (which in your case seems to be email). In our user flow, resetting 2fa will remove the 2fa requirements, login the user, and redirect the user to setting up a new 2fa.
Although I admit that there are routes that are redundant to 2fa e.g. passkeys which are 2fa by themselves.
@rjdavid I may have misunderstood your response, but if the user loses access to their 2FA authenticator and you allow them to reset 2FA by authenticating via password alone, doesn’t that defeat the whole purpose of 2FA? In your workflow, how do you authenticate the user to allow them to reset an unavailable 2FA authenticator?
Understood, however, that outlines my problem. I’m unable to use accounts-passwordless via email to login the user to reset their 2FA because once the user has registered an authenticator using accounts-2fa, accounts-passwordless then forces the use of 2FA to authenticate. Instead, they should operate independently of each other.
It would be email + password + token from authenticator or email + token from email + token from authenticator - it shouldn’t require all 4, but should require all 3.
If you think it shouldn’t be the case, open an issue on the repo.
I think this is a situation where meteor’s “easy to use” gets in the way of “I want to customise it” - would be really nice if these packages just exposed the necessary functionality without necessarily modifying login behaviour unless you opted in.
In my opinion, it’s poor design and creates a poor user experience if there is no secure, alternate backup authentication method available to users who choose to use an Authenticator App as a 2FA method (because phones are easily lost or broken, and some Authenticator Apps (e.g. Google Authenticator) require you to have the old phone to transfer the accounts to the new phone). I believe those methods include:
A hardware security key with verification enabled (PIN or biometric)
Recovery Codes provided at 2FA registration (safely stored, preferably offline)
Passkeys (once they become more readily available)
An emailed, short-duration TOTP (Time-based One-Time Password)
Push-based notification to a sister app (not common)
Did I miss any? (SMS is currently not recommended for authentication verification because of its multiple vulnerabilities and how easily SMS can be hacked.)
Currently, Meteor provides direct support for only one of the 5 methods listed above (accounts-passwordless). Unfortunately, the design of that package prevents it from being used as a backup authentication method to accounts-2fa. My preference would be to make has2faEnabled an optional check as I’ve suggested in Feature Request #12512.
As designers and developers, if we want to promote the widespread adoption of secure means of authentication, simply being secure isn’t enough. It also has to be easy and convenient for anyone to use.
If you are a paying customer, we can make two small charges (less than $1 US) to your credit card. If you can tell us the amount of those charges, then we will disable 2FA and immediately reverse the charges.
That sounds like it’s secure enough, but there’d be much less of a hassle if a secondary backup means of authentication was instead available.