What is MFA, and why does your app need it?

MFA is included with User Management (free up to 1 million MAUs) and can be enabled in just a few steps. However, should you choose to support MFA in-house, it is important to remember that implementation requires sizable changes to the backend and the frontend.

The basics

MFA stands for Multi-Factor Authentication: it’s an added layer of security to your app that makes it more difficult for hackers or impersonators to steal and use a user’s credentials. 

Understanding MFA starts with a truism that developers have known for years, but is becoming more widely acknowledged: passwords are inherently insecure. They’re stealable, hackable, brute forceable, forgettable, and in most cases, short and poorly chosen (only 1 in 3 Americans uses a password manager). MFA seeks to remedy that by adding a second layer of authentication on top of your usual username / password scheme.

You can think of MFA as requiring two types of identification:

  1. Something that you know (your password)
  2. Something that you have (your device)

(Sometimes you can also use something that you are, like biometrics, fingerprints, etc., but this is much less common today).

Passwords are pretty easy to steal, and they don’t prove that you’re you. Devices, specifically your phone, are much harder to steal. Neither of these is perfectly secure by themselves, but combined, you’re in pretty good shape. MFA can be tedious to implement for your app – we’ll dive into this later – but more security for your users means better outcomes for your business.

Note: MFA is included with WorkOS User Management and is free up to 1 million MAUs. It can be enabled in just a few steps.

MFA makes your accounts more secure, and that’s good for business

Security isn’t solely the domain of paranoid engineers anymore; it’s part and parcel of building a startup today, especially one that’s going to sell things to enterprises. The basic idea is that getting breached is a devastating, catastrophic business event, and implementing MFA is a big step in the right direction towards preventing it. The average cost of a data breach can be in the millions, and it’s steadily climbing.

Virtually every major breach in the past 10 years has involved, and in one way or another, someone is gaining access to an account fraudulently. A great example is a Twitter incident in 2020, where a hacker got access to Twitter’s internal admin panel and used it to (of all things) spread cryptocurrency scams. The speculation is that the hacker got access through stealing an employee’s credentials.

MFA is most impactful with consumer focused apps handling sensitive data like banks, credit cards, e-commerce, etc. But it’s important for your run of the mill SaaS app as well – the chances that your early customers mature into enterprise deals is near 0 if accounts get compromised. As you try to move up market and sell larger deals, security becomes a given, not a nice-to-have, and MFA is an easy place to start that journey.

Types of MFA and how they work

Let’s run through the different types of MFA and how they work. Chances are you’ve interacted with all of these at one point or another. They all rely on a roughly similar type of interface, where you get a code (usually a 4-6 digit one) that you input in a form field on the login screen. This One-Time Password (OTP) is usually time bound and expires after a while. 

We’ll go in order of security, from least secure to most secure.

1. Email

Email is the least secure form of MFA, because email itself isn’t device bound. You can log into your Gmail account from any device anywhere, as long as you have your password – which defeats the purpose of MFA in the first place. It’s still more secure than just a password, since the likelihood that a hacker gets both your account password and your email account password is relatively low.

2. SMS

SMS is probably the most popular of the methods listed here. Though there are exceptions such as virtual numbers and text forwarding, generally, if you can get an SMS at the number you specified, you have that device (usually your phone) on hand. 

It’s far from foolproof though, and less secure than you might think (WorkOS no longer supports SMS-based MFA due to known security issues). There are plenty of ways for hackers to get access to your MFA code like smishing or SIM swaps, which is actually exactly what happened to Reddit a few years ago with their data breach.


TOTP stands for Time-Based One Time Password (rolls off the tongue) and it’s the scheme that underlies authentication apps like Authy and Google Authenticator. The basic gist is that you use cryptography to generate a secure code and input that code into the app you’re trying to sign into. TOTP was first proposed as a spec from the IETF (Internet Engineering Task Force) in 2011, and has since become quite popular.

A little more on what’s going on under the hood: when you sign up for whatever app you’re using initially, it will display a QR code that you scan with your phone. That code generates a cryptographic secret stored on your device, while a corresponding one sits on the server of the app. And when you combine that secret with the current time of day using some special cryptographic functions, you get a 6 digit code. Input that code into the app – which has the same secret and time of day, and thus knows the code it’s looking for – and you’re good to go.

What makes TOTP so secure is that nothing is getting sent – through the magic of cryptography, the app knows what the code needs to be separately from your device. You can think of it like two doors with the same lock and the same key. So there’s no chance of someone intercepting your MFA codes, since they’re never sent over the internet (like in SMS or Email based MFA).

4. App (bonus)

If you’re someone like Google who has the luxury of assuming your users have multiple apps of yours installed on a particular device, you can use that to your MFA advantage. When signing into Google on a new device, they will prompt you to open another Google app (usually YouTube in my experience), and click on a simple “Yes/No” prompt in the app asking if that new signup is you.

When you’re choosing which MFA method(s) you want to support in the app you’re building, you’re going to face the usual tradeoffs between security and ease of use. SMS is the easiest – and probably most common – but isn’t entirely secure. TOTP is highly secure, but requires downloading a specialized app, building a flow for QR codes, etc.

One last thing to note: though most apps implement MFA as a requirement for initial sign in, an alternative design pattern is to only require password on initial sign in, and then require MFA later when a user wants to do something that should require “heightened access” like update their profile, view confidential information, etc.

Implementing MFA on the backend

No matter which MFA method(s) you choose to implement, it’s going to require significant changes to your backend. At the least, you’ll need to make adjustments to your users table to account for who has MFA enabled. You’ll likely need at least one new table to track your MFA method of choice. If you’re using an authentication-as-a-service provider of course, this is all much easier.

1. Email and SMS

Email and SMS have similar implementation considerations, with SMS being a bit more complicated. Both require some form of the following workflow on sign up: 

  • User signs up (or is already signed up, but wants to add MFA)
  • User chooses MFA method (if multiple available)
  • User enters email or phone number
  • Backend sends code to verify that the user owns the email or phone number
  • Email or phone number gets stored in the backend for future use

And a separate workflow on sign in:

  • User attempts to sign in
  • [optional] app confirms MFA method with user
  • Server generates OTP and sends to user
  • User inputs OTP
  • Server verifies OTP

You can start to see that several parts of these workflows will involve database storage and retrieval, plus the behind the scenes stuff like expiration timestamps for these codes.

Email is straightforward: you probably already have a transactional email provider like Mailgun, and you can use it for MFA too. For SMS, most developers today will use something like Twilio to outsource the nastiness of managing SMS manually. 


Implementing TOTP isn’t a complete nightmare, but does involve some specialized knowledge. A good place to start is reading the spec. The initial workflow looks something like this:

  • User signs up (or decides to add MFA)
  • App displays a QR code to the user
  • User scans QR code with auth app, and stores secret locally
  • Server also stores secret locally

And then on subsequent login:

  • Server generates OTP by combining timestamp and secret
  • User does the same
  • If it matches, the user is authenticated

Since TOTP doesn’t require any data to travel over the internet (or SMS), you don’t need to worry about anything outside of the server itself. You’ll need a table in the database to store each user’s secret (or each device’s, depending on implementation). In general, you should be able to implement the basic mechanics of it in a few dozen lines of code. 

But as always, the devil is in the details. You’ll want to implement some sort of rate limit to avoid brute force attacks. You’ll likely need a dependency for generating the QR codes, and it’s best practice to build some sort of recovery flow in case users switch devices. And because of clock drift/skew, implementations usually allow for some sort of rolling window of OTP validity. 

Implementing MFA on the frontend

We covered a sample of the kinds of workflows that MFA requires in the previous section, and each is going to require some corresponding frontend work. You’ll need to consider:

  1. Adjustments to your existing signup flow that add in the MFA steps
  2. A flow for initial MFA setup where users can add an email/number/device
  3. A flow for generating and inputting an OTP as part of sign in
  4. Flows for removing MFA or resetting MFA to a different device

There are also some niche but important details to consider (the kinds of things that discerning users might notice and appreciate). A good example is managing the HTML input fields for the OTP. Most companies won’t even bother to correctly label the input types, so that on mobile, the number keyboard shows up instead of the entire keyboard. Things like that are simple. But consider the below, where Stripe actually separates each number of the OTP into its own form field. This is nice, because when you type a number it automatically progresses to the next one. Stripe also auto-submits once you have all 6 numbers in there. 

Contrast this with a more traditional app like Trinet, using Email MFA. They don’t bother to attach a type to the HTML input, so on mobile, I’m stuck typing on the small number keys (assuming I’m not copying and pasting).

Small details like this can help take MFA – something that your users might consider a chore – and make it not so bad after all.

In this article

This site uses cookies to improve your experience. Please accept the use of cookies on this site. You can review our cookie policy here and our privacy policy here. If you choose to refuse, functionality of this site will be limited.