In Depth: Email Verification Isn't as Simple as You Think
[In Depth #38] You can't trust an email address you haven't verified, so why are you storing them in your database?
A friend of mine sent through the following:
I was examining an app we've been maintaining for a bajillion years, and noticing that our process for allowing someone to update their email address was perhaps lacking, securitywise. Yes, we were reissuing a verification email and resetting their verification status, but it occurred to me, what if they typed their email address wrong? Did we just overwrite their current email with a bogus email? And when I started thinking through a solution it got less straightforward - do I store the pending email address as a separate field? Or embed it in the verification link somehow? Do I need to send an email to the original email address as well, as an extra security measure? Should I have the user confirm their password when they are updating their email address?
This poses a bunch of great questions, so we'll work through each and see how they fit into the bigger picture of email verification.
However, before we do that, there are two questions we need to answer:
Do We Need to Verify Email Addresses?
It depends on what your app does, and the sort of data it processes.
If your app doesn't process any sensitive or personal data, and the email address is basically just a username - used for the purposes of authentication and account recovery, then there isn't much need to verify email addresses. You don't need to care about it being a legitimate email if you don't send users important emails, and if a user loses their password, they can just create a new account.
However, you should verify email address any time you care about:
- Account recovery - if a user typos their email, they can't recover their account.
- Contacting your users - you can't email them if you don't have their real email.
- Identifying users - legal and compliance often requires you to know your users, and to do that, you need legitimate email addresses.
- Reducing spam and abuse - You don't want spam/abuse victims being signed up to your app without their knowledge.
- Delivery Reputation - your email sending reputation could be damaged if you're sending emails to fake or non-user addresses.
- Multi-Factor Authentication (MFA) - email OTPs are a simple and useful MFA option for non-technical folks
- Security Alerts - you need a way to notify users of suspicious activity on their account.
- Prevent Impersonation / Privilege Escalation - many apps rely on checking for
@company.comin the user's email address to unlock admin features, without verification this can be trivial to exploit. Even with manual account verification - if a staff sees the account email and is tricked into thinking it's a staff account.
Granted, a bunch of these could be considered the user's fault responsibility, and if they get their own email address wrong, then that's their problem. If this is the case for you and your app, then you might not need email verification.
However, if you're serious about your apps and looking after your users, then Email Verification is important. You cannot trust or safely use an email address until it has been verified by the user.
How Does Laravel Do It?
Ok, before we work through their questions, let's see what the default behaviour in Laravel is. To test this, I set up a fresh Laravel app (with laravel new) using the Livewire Starter Kit. This will give us basic user account scaffolding to test.
Laravel's Default

It shouldn't be a surprise that by default there is no email verification enabled.
As per the docs, enabling email verification is trivial, add the Illuminate\Contracts\Auth\MustVerifyEmail interface to your User model, and the verified middleware to your routes.
Once it's enabled, you'll be presented with the verification challenge:

Changing your email address immediately saves the new email, and resets verification:

Fairly basic and standard approach, which is to be expected.
However, this implementation leaves a bunch of our questions unanswered, and raises some concerns when you consider what happens if the user doesn't immediately complete the verification.
If we consider our list of reasons for having email verification, I have the following concerns immediately: