TOTP: (way) more secure than SMS, but more annoying than Push
Ever wonder how Google Authenticator works? Learn why TOTP 2FA is drastically more secure than SMS 2FA and the security and usability tradeoffs it makes.
Welcome back to the two factor authentication (2FA) series!
If you haven’t already, check out the first article in the series that explains what 2FA is and why you really should enable it on your accounts (yes, even if you have a strong, unique password).
The previous article in the series outlines why you should favor more secure 2FA methods than SMS if at all possible.
One of those methods is using Google Authenticator or a similar app on your phone to generate 2FA codes. Have you ever heard of these apps or wondered how they actually work? Well, today you’ll find out!
In this article, we are going to cover the common time-based one-time passwords (TOTP) implementation of 2FA. We’ll use the abbreviation TOTP 2FA as we cover the technical details, highlight security vulnerabilities, and discuss usability tradeoffs.
A few administrative things to clear up before we dive in. I will be using the following terms throughout this post:
- service provider to refer to the website service provider (e.g., Google, Facebook, Twitter, etc.);
- OTP to mean one-time password; and
- trusted device to refer to any device capable of running an authenticator app that can generate OTPs according to the TOTP specification, such as Google Authenticator. Typically, a trusted device is a smartphone or tablet, but can also include desktops, laptops, smart watches, etc.
And finally, a quick reminder that the authentication factors associated with 2FA are the knowledge factor (something you know) and the possession factor (something you have).
Let’s get into it!
Registration flow for first time TOTP 2FA users
Throughout this article, we will be following Alice, our recurring friend, as she navigates the TOTP 2FA workflows. Let’s start off by taking a look at the registration workflow by way of a diagram! A picture is worth a thousand words, right?
After Alice starts the 2FA registration process, the service provider displays a QR code in Alice’s browser and prompts her to scan it with an authenticator app on her trusted device. If Alice does not already have an authenticator app, then she must install one before continuing.
There are many apps available that implement the TOTP specification. For example, Google Authenticator, Authy, Duo Mobile, Auth0 Guardian, and FreeOTP are all capable of generating OTPs in the same exact way. Alice chooses one of these and installs it from her trusted device’s app store.
Here is a screenshot of the Google Authenticator app:
After installing the authenticator app, Alice uses it to scan the QR code displayed in her browser, which saves a shared secret onto her trusted device. This shared secure is foundational in how TOTP works and I will explain how later on, but there are two simple things to highlight here. First, the value is shared; Alice has a copy and the service provider has a copy. Second, the value is secret; only Alice and the service provider should ever have access to it. I’m sure your “someone is gonna steal it!” sense is tingling already. Hold tight! Let’s not get ahead of ourselves.
After scanning the QR code, the authenticator app starts automatically generating OTPs for Alice’s account. These are typically 6 digits long and change every 30 seconds or so. To complete the TOTP 2FA registration process, Alice types the current OTP displayed on her trusted device into her browser. This allows the service provider to verify that it is the correct OTP and enable TOTP 2FA on Alice’s account.
It would be quite fair to say that TOTP 2FA registration is more complicated than SMS 2FA. The first time Alice ever sets up TOTP 2FA, she will need to download a new app to her trusted device, use that app to scan a QR code, and manually type the current OTP into her browser. Compare that to SMS 2FA, where Alice only needs to enter her phone number and manually type a code into her browser. Luckily, TOTP 2FA gets simpler after the initial registration process.
Registration flow for experienced TOTP 2FA users
Alice only needs to install an authenticator app on her phone a single time. As mentioned previously, most authenticator apps implement the standard TOTP algorithm and can therefore generate the same OTP codes. Alice’s choice of which authenticator app to use is mainly based on which user experience she prefers.
The diagram above shows the registration flow if Alice already has an authenticator app installed on her trusted device. She only has to scan the QR code with her existing app and then manually type in the OTP from the authenticator app to enable TOTP 2FA on her account.
Alice only needs to complete the registration process once for each of her accounts. The authentication process is even simpler than registration!
Authentication during login
The only thing that Alice has to do during the login process is manually type the OTP displayed on her trusted device into her browser.
This workflow is quite simple and arguably more user friendly than SMS 2FA.
The main improvement is that nothing is sent over the network from the service provider to Alice’s trusted device. The shared secret is used to generate the OTPs locally in the authenticator app. This means that Alice does not need a cell or data connection to use TOTP 2FA. Not only does that beat waiting for a text to arrive, but it is also great for people in areas with bad reception or traveling abroad where they might not have any connection at all.
In addition to the usability benefits, TOTP 2FA is significantly, dramatically more secure than SMS 2FA. If you take a peek back at the SMS 2FA article, you’ll notice that a huge source of vulnerabilities came from the phone company and network. Eliminating those has huge security benefits: no more social engineering people at the phone company, no more insider threats at the phone company, no more SS7 attacks on the phone network redirecting your texts, etc.
However, TOTP 2FA does have its own flaws. Before we cover those, let’s answer a question that some readers have likely been asking themselves: How the heck does the service provider know that Alice entered the correct OTP?!
Scan a QR code, get a shared secret!
The shared secret is foundational to how TOTP 2FA works and I want to quickly explain how it gets transferred from the service provider to the trusted device.
A QR code is simply a way of encoding some data, such as plain text characters. You can see in the examples above that QR codes can be created to encode any text you want. Go ahead and check out The QR Code Generator. Type some text in the box and watch the QR code change in real time to encode whatever you typed in. Don’t believe it? Download the QR Scanner (Privacy Friendly) on Android or a similar app on iOS and scan the QR code shown on your screen. The app on your phone will show the same exact text. Not magic! Just math!
The QR code displayed during the TOTP 2FA registration process encodes information that the authenticator app on the trusted device needs to function correctly. The technical details are defined in a specification, but at a high level the QR code includes things like Alice’s email address/username and the name of the service provider so that the app can label which OTPs go with which accounts. Most importantly, it includes the shared secret.
So, after the authenticator app on the trusted device gets the shared secret from the QR code, how does it actually generate the OTP?
How the OTP is generated and validated
Back in the introduction article to this series, we discussed two important properties of cryptographic hash functions that were critical to understanding the basics of how passwords are securely stored in a database. Cryptographic hashes are used extensively in the TOTP algorithm, so we will revisit them at a high level.
The most important property to recall is that cryptographic hash functions are deterministic; the same input values will always generate the same output hash values.
On the trusted device, the TOTP algorithm provides the shared secret and the current time as input values to a hash function. I’ll use a hand wavy explanation and say that some other tricky math calculations happen, but essentially the output hash value is the OTP! The server can run the exact same calculation because it has a copy of the shared secret and, thanks to the Network Time Protocol (NTP), has the same current time. The service provider can verify that Alice entered the correct OTP value during registration and authentication because the same calculation is being run locally on both the trusted device and on the service provider’s servers.
There are some other important properties about cryptographic hash functions that are useful to understand potential attacks on TOTP 2FA, but they are out of scope of this article. I wrote a follow up article covering those details here!
Hopefully, this makes it clear how the OTP is generated and validated and why nothing needs to be sent over the network by a third party like the phone company. This is the major reason that TOTP 2FA is so much more secure than SMS 2FA. However, this architecture also introduces some other challenges that SMS 2FA does not have: protecting the shared secret.
Steal the shared secret from the service provider!
If an attacker is able to obtain a copy of the shared secret, then they can generate valid OTPs on-demand, which completely compromises TOTP 2FA.
To prevent the shared secret from being immediately compromised in the event of a data breach, the service provider must store the shared secret securely (see NIST 800-63B).
Another opportunity to talk about cryptographic hashes! Remember, another key property is that they are one-way functions; given the output hash value, it is computationally infeasible to calculate the original input. While this is the ideal property that we want when securely storing passwords, it will not work for storing the shared secret. Remember, the TOTP algorithm needs the original shared secret value as input, so if we store the shared secret as a hash, then we lose access to the original value.
Instead, the service provider will encrypt the shared secret using an encryption key. This both prevents it from being stored insecurely as plain text in the database and allows the service provider to use the key to decrypt the secret when it is needed. Each time a user logs in, the original shared secret value can be provided as input to the hash function in the TOTP algorithm. This sounds great, but now the service provider needs to store the encryption key somewhere safe too! If the encryption key and encrypted shared secrets are both stored in the same database that the hackers breached, then all of the secrets can be trivially decrypted and used to “prove possession” of any user’s phone. Clearly, not a good thing.
There are many solutions to the problem of key management, such as using a hardware security module (HSM), but explaining those is out of scope for this article. The important takeaway is that service providers have a responsibility to implement TOTP the right way and one mistake could jeopardize the security of every single user’s 2FA if the database is breached.
It would be ideal if the service provider did not save any information in the database that could compromise the 2FA method in the event of a database breach. Later in this series we will talk about Push 2FA and U2F 2FA, which both take that exact approach. Stay tuned!
Steal the shared secret from Alice’s trusted device!
Since the secret is shared between the service provider and Alice’s trusted device, it can obviously be stolen from Alice’s device too! In fact, this is arguably more likely to happen.
Someone could physically steal Alice’s trusted device. If the device does not have full disk encryption enabled, then the hacker could simply pull the shared secret off of the hard drive. More scary than that, the trusted device might not even be locked and the hacker can simply navigate directly to the authenticator app to see which services are registered along with the usernames and OTPs for each.
Aside from physical compromise, the trusted device can also be compromised by software. In the introduction article to this series, we discussed how many 2FA methods are vulnerable to malware and keyloggers. TOTP 2FA is one of those vulnerable methods. Alice could accidentally get malware on her trusted device that is designed to steal the shared secret.
Protecting the trusted device becomes paramount in the context of TOTP 2FA.
If Alice loses her trusted device, can she still log into her account?
If Alice loses her trusted device (or it is stolen), then she may clearly be worried about someone maliciously logging into her account. However, it is unlikely that a random passerby who finds her trusted device (e.g. her phone) will also have her password and be able to quickly log into her accounts. Unless Alice has been targeted specifically, it is likely that she will have time to take preventative action to protect her accounts.
That preventative action is to revoke the shared secrets that were stored on her trusted device so that they become useless to whomever might find them. This, of course, requires logging into her accounts! But, in order to log into her accounts, Alice needs both her password and her trusted device... Luckily, there are several account recovery options that are likely to be available.
The de facto standard implementation of TOTP 2FA adds an additional step to the registration process which provides the user with a set of one-time use recovery codes.
These codes are intended to be stored somewhere safe and independent of your trusted device; print them on a piece of paper that you leave at home, securely store them on your computer, etc. Where and how to save these recovery codes deserves an article of its own. However, the relevant point here is that Alice could use a recovery code in place of an OTP generated by her authenticator app if she lost her trusted device, she uninstalled the authenticator app, etc.
A second recovery option for TOTP 2FA is to utilize multiple trusted devices. During the registration workflow, Alice could install an authenticator app on both her phone and her tablet and use each to scan the single QR code displayed in her browser. This way, both her phone and her tablet would have a copy of the shared secret and would be able to generate the same exact OTP codes. If Alice lost her phone, then she could use the tablet she left at home to successfully log into her accounts. This strategy can work very well for anyone who has an old device lying around the house and doesn’t want to deal with printing out or otherwise securely storing recovery codes. However, keeping track of the multiple trusted devices is critically important! All of the trusted devices can be used to generate valid OTPs, so enable encryption on all of them and don’t misplace them!
If Alice didn’t have the foresight to save her recovery codes and/or scan the QR code with multiple trusted devices, then she is in a tight spot. Her last resort would be to reach out to the service provider’s support desk and see if they have an account recovery process. This varies widely from company to company. For example, some have well established criteria to prove that you are the genuine account holder, while other companies have no recovery process at all and she would be permanently locked out of her account.
After logging into her account with a recovery method, Alice should revoke the shared secret that was stored on her trusted device so that if anyone does gain access to her trusted device, the shared secret is already useless. Then, Alice can re-enable TOTP 2FA for that same account with her new trusted device (e.g., she might buy a new phone). Unfortunately, this process would need to be performed for each individual account that Alice had TOTP 2FA enabled on. Quite a tedious process, indeed.
Vulnerable to phishing and MITM attacks
The diagram below shows that TOTP 2FA joins the list of 2FA methods that are vulnerable to phishing attacks.
In this familiar scenario, Alice thinks that she is on a legitimate site, so she logs in with her password. In the background, the hackers running the phishing site use the password Alice just handed over to log into the real site. The phishing site then prompts Alice for the OTP generated by the authenticator app on her trusted device. Again, Alice thinks she is on the legitimate site and knows that she has TOTP 2FA enabled on her account, so she happily enters the OTP into the phishing site. As soon as she does, the hackers can use that valid OTP to successfully log into Alice’s account on the real site. Game over.
TOTP 2FA is similarly vulnerable to Man in the Middle (MITM) attacks. The phishing attack relies on fake websites that look real to trick Alice. If Alice falls victim to a MITM attack, then she actually connects to the real website, but does so on an insecure HTTP connection. This allows hackers to read all of the network web traffic, including the OTP that Alice manually entered into her browser.
Remember, HTTPS helps prevent MITM attacks; you should go install HTTPS Everywhere to help with this!
Wrap up
TOTP 2FA does a much better job of proving “something you have” than SMS 2FA.
With SMS 2FA, the OTP is generated by the service provider and sent to the device associated with your phone number. I talked about the issues with that architecture and how the OTP can be stolen in a variety of ways during transit through the phone network. With TOTP 2FA, the authenticator app on the trusted device visually scans a QR code to obtain the shared secret, which is used locally to generate the OTP. Never sending the shared secret over the network reduces the remote attack surface significantly. It also has some nice usability gains, such as not needing wait for slow text messages to arrive or the need for a network connection at all.
However, TOTP 2FA definitely has its drawbacks in terms of usability and security.
In terms of usability, there are some mild annoyances that can grate on users over time. For example, manually typing the OTP into the browser is annoying, but becomes hugely frustrating if the OTP rotates to a new 6 digit code as you are typing it into the browser. If you didn’t catch all 6 digits, then hit that backspace key and start again. As we’ll see later in this series, Push 2FA and U2F 2FA remove the need to manually type anything into your browser; a huge UX improvement.
Another usability challenge is the fact that your trusted device is often your phone, which is literally a device optimized to steal your attention. I can’t tell you how many times I have picked up my phone to get an OTP from my authenticator app and gotten distracted by an incoming text message from a friend, a waiting email, or a tempting glance through a blog post. Five minutes later I remember that I should be working, put my phone down, and look back at the computer screen that is sitting there still waiting for an OTP. Back to the phone to grab the OTP and get back to work. Admittedly, this distraction issue is not specific to TOTP 2FA and applies to all 2FA methods that treat phones as a trusted device.
In terms of security, TOTP 2FA introduces the importance of keeping the shared secret safe on both the trusted device and the service provider’s servers is specific to TOTP 2FA. If your trusted device is your phone, then you’re probably going to notice pretty quickly if it goes missing, which will likely allow you to act before someone finds it and tries to get into your accounts. However, you will never know if the shared secret is stolen from the service provider unless they tell you. Depending on their security posture, they might not even know they were compromised!
As I highlighted previously, a much more secure architecture would be one in which the service provider does not save any information that could compromise the 2FA method in the event of a database breach. Later in this series we are going to talk about Push 2FA and U2F 2FA, which both take that exact approach.
And finally, let’s not forget that, like most 2FA methods, TOTP 2FA is vulnerable to malware on the trusted device, MITM attacks, and phishing attacks.
If you’ve stuck it out til the end, then you should definitely join the email list below to make sure you don’t miss the next article in this 2FA series! Still to come are articles on Push and U2F, which are each more secure than TOTP and arguably easier to use as well.
Edit: Check out the next article in this 2FA series: A medium dive on the Time-based One-time Passwords (TOTP) spec
Thanks to Jordan Fischer, Kristie Butler, Reuven Gonzales, and Peter Nakagami for reading drafts of this and to copious friends and colleagues for feedback on the diagrams.