Security Tip: Account Recovery for MFA?

[Tip #119] What happens if your users lose their MFA tokens, and they never saved their recovery codes? Can you safely give them back access to their accounts?

Security Tip: Account Recovery for MFA?

Following on from our MFA theme, let's talk about recovering lost MFA tokens. Or more specifically, allowing a user who has lost access to an MFA token to recover access to their account.

This is one of the biggest hurdles when it comes to TOTP (Time-based One Time Passcode) specifically, especially in the early days when your TOTP token was configured on your phone and did not sync across devices. If you lost your phone, you could no longer access your account!

This is where recovery codes come in - you're supposed to print them out and store them securely somewhere, so if you lose your phone, you can still recover your account using a recovery code. Being a physical object you're supposed to store in a safe, recovery codes are supposed to be very hard to steal...

However, can we all honestly say that we actually do that? Because I don't! I store my recover codes in 1Password, alongside my TOTP. If I ever lost access to that account, I would lose access to my entire digital life. (Now that I type those words... I might need to make some changes...)

๐Ÿ“–
Story time!
Many years ago, at a company I used to work at, my boss lost his phone one day. He used Google Authenticator, and back then it wasn't synced between devices, so he lost access to all of his TOTP tokens. He also hadn't bothered to save his recovery codes. He was completely locked out of our company GitHub account - and as far as I am aware, the company is still locked out.

It's not uncommon for companies to have a "no account recovery" policy when TOTP/MFA tokens are lost. If you cannot present valid authentication, the company has on way to properly verify you, and will simply refuse to let you access your account. It sucks for users, but from a security point of view, it makes a lot of sense.

As developers, and folks running apps, we can either adopt this policy and reject users who lose their MFA tokens, or we can either try to handle Manual Recovery or implement some form of Automatic Recovery process.

Manual Recovery

The user needs to contact your support team, and request account recovery to disable MFA. From this point, you'll need to find some way to verify the user should have access to the account.

Here are a few common ways you could do this:

  • Ask the user to billing details match those on the account.
    Many places have a "whoever pays the bills owns the account" policy.
  • Request government identification documents that match the account name, or business name.
  • If you handle financial transactions, the user could provide screenshots of transactions to prove access to matching bank accounts.
  • Send notifications to all contact methods to advise recovery is in process - and provide an easy way to cancel recovery.
  • Enforce a cooldown period before recovery is actioned, such as 3 days.
  • Adding DNS records to linked domain names.
  • Confirming private keys if public keys are stored in the app - such as for SSH.
  • Confirming API keys.

I would advise against simply relying on email address access - if an attacker can spoof or access the user's emails, they can abuse that to bypass MFA in your app. In fact, any single one of these methods could be hijacked in a targeted attack, so I would recommend implementing multiple and making the recovery process take time to complete - with multiple staff needing to sign off.

In other words - it's a lot of work, but given it is the security of the user's account that we're talking about, it shouldn't be easy.

Automatic Recovery

Don't do it.

Ok, in fairness, there are ways you could automate the process. A number of the methods I listed above could be handled automatically, especially things like checking API tokens and SSH keys. However, you need to consider what would happen if an attacker gains access to these things too.

My recommendation here is to implement account recovery in a two-step process:

  1. Prompt the user to confirm their identity using 2 or more methods from a list of options that can be automatically checked.
    1. When the user submits those details, also record their IP address, time zone, local time, browser fingerprint, cookies, etc - i.e. as much metadata about the request as possible, to help identify potentially malicious requests.
  2. Present all the information to a staff member to review and approve, send notifications to the user, and then wait 3 days before recovering the account.

There are still manual aspects, but all the information collection will be automatic, so your staff members just need to review it.

Or, just don't allow account recovery on lost MFA. ๐Ÿคท


Securing Laravel is SPONSORED by...

Want to see your brand here?

Find out more...

If you found this security tip useful? ๐Ÿ‘
Subscribe now to get weekly Security Tips straight to your inbox, filled with practical, actionable advice to help you build safer apps.

Want to learn more? ๐Ÿค“
Upgrade to a Premium Subscription for exclusive monthly In Depth articles, or support my work with a one-off tip or recurring Sponsorship! Your support directly funds my security work in the Laravel community. ๐Ÿฅฐ

Need a second set of eyes on your code?
Book in a
Laravel Security Audit and Penetration Test today! I also offer budget-friendly Security Reviews too.

Finally, connect with me on Bluesky, or other socials, and check out Practical Laravel Security, my interactive course designed to boost your Laravel security skills.