Like everything in security, whether or not it’s safe to use email as a delivery channel for two-factor authentication (2FA) will depend on who your users are and what you're trying to protect.
That said, email based 2FA is usually going to protect your users more than it is going to hurt them, especially if it's offered as an option alongside more secure channels like TOTP. Much like SMS based 2FA, which can protect 96% of bulk phishing attacks and 76% of targeted attacks, any 2FA is going to be better than no 2FA at all.
A quick note: email verification vs. 2FA
This post addresses the tradeoffs of ongoing login verification using email two-factor authentication. Verifying a user's email address the first time they provide it is a best practice to reduce fraud, ensure deliverability, and maintain a good sending reputation.
Services like Chase bank offer email 2FA as an option alongside SMS 2FA.
What email 2FA will protect
There are three types of authentication factors:
- Something you know (like a password)
- Something you have (like a phone or key)
- Something you are (like FaceID)
Using two different factors means that you support 2FA. The benefit of 2FA is that if one of the factors is compromised, your account is usually still protected. It makes it much harder for an attacker to gain access.
Username and password login is increasingly insecure since many people reuse passwords and passwords are constantly leaked in data breaches. Sites like haveibeenpwned.com show us how common simple passwords like 123456 are:
Email based 2FA will protect accounts where the first factor was compromised due to:
- Brute forced or guessed passwords (like 123456 or Spring2020)
- Credential stuffing
Email based 2FA would help protect users against these types of attacks and minimize their risk for account takeover.
Other benefits of a 2FA email channel
There are a few additional advantages to offering an email option for 2FA:
- Familiar data requirement - users are used to providing their email to a service for important account updates and password reset emails.
- Easy onboarding - like SMS 2FA, email 2FA does not require another app or any additional setup to configure.
- Existing personally identifiable information (PII) - using email means that your users don't have to give you additional PII like a phone number.
What email 2FA won't protect
The problem with email as a 2FA delivery channel is that the most common first factor, a password, can usually be reset via an email. That means that an attacker only has to compromise one factor, your email inbox, to take over your account. This can happen if they know your email account password or if they have access to a live session (e.g. if you leave your email logged into a shared computer).
This kind of threat leaves some people in already vulnerable situations, like those with distrusting roommates or partners with access to your device, at risk.
Fortunately, common email providers like Gmail encourage security checkups to protect users.
Why 2FA? Magic links and passwordless login
If usernames and passwords are so insecure, some argue why bother with them at all? Services like Slack have popularized magic links, or one-time login links that bypass the standard username and login requirement. This kind of passwordless login is open to the same risks as email 2FA if the attacker has access to your email account. Magic links do remove the expectation that people use unique complicated passwords to stay secure for every site, and that is a user experience win for many.
Adding email 2FA, verification, or magic links to your application
Supporting an email channel is easy with Twilio's Verify API. Check out the docs to set up your account to send verification emails. The API will handle generating and checking tokens as well as fast, scalable deliverability.
Once you've configured your SendGrid account and connected it to your Verify service, here's a peak at the code you'll need to start a verification:
# Install the twilio-cli from https://twil.io/cli twilio api:verify:v2:services:verifications:create \ --service-sid VAXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX \ --to firstname.lastname@example.org \ --channel email
The neat thing about the Verify API is with just a couple parameter changes you're all set to send SMS verifications too:
twilio api:verify:v2:services:verifications:create \ --service-sid VAXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX \ --to +15017122661 \ --channel sms
Check out these full tutorials for sending email verification messages in your language:
- [PHP] Verifying Email Addresses in PHP Got Easy
Let me know if you have any questions, and I can't wait to see what you build.