SMS two factor authentication

Two Factor Authentication, SMS and NIST

How many movies and TV shows have you seen where asks somebody else about a secret that they share? If they give the right answer, their identity is confirmed. If they don’t, they’re an imposter, an alien from Planet X in disguise.

Shared secrets are the basis of authentication in computer security. And two shared secrets – two factor – are even better than one, especially when the first is a password that many people have difficulty managing in a secure way. This is what we’re doing when we use both a password and a code that’s texted to us. And this week, we got told to stop using text messages for the second secret.


I’m seeing a lot of stories circulating about NIST (the US National Institute of Standards and Technology) “banning” SMS from two-factor authentication with a lot of sensational headlines: “NIST Prepares To Ban SMS-Based Two-Factor Authentication”, “New U.S. Guidelines Could Halt Use of SMS for Two-Factor Authentication”, “SMS-based two-factor authentication will soon be banned”.

These are sensational and attention-grabbing, making it sound like the government is going to shut down SMS-based two-factor authentication tomorrow… so no more “code in a text message” from Google, Paypal, Apple, Twitter…

Meanwhile in the real world, NIST has no authority to ban SMS1 – it doesn’t create laws or regulations. It does write guidelines and set standards that might be required for federal government procurements, so when NIST says “no more SMS for two factor authentication”, the US government might require that services it uses no longer use SMS for authentication. But NIST isn’t going to shut down Google’s or Paypal’s or anyone else’s use of SMS as a second factor.

Many businesses and government agencies will voluntarily follow NISTs recommendation, so although they have no power to compel anyone to stop using SMS, many organizations will anyway.

What NIST actually said

Reading the actual NIST draft document, you’ll find that NIST recommends that developers of new systems use alternatives to SMS in multi-factor authentication, that SMS for multi-factor is deprecated, and recommends push notifications as a potential alternative.

The document goes on to recommend specifics for the representation of the secret being shared (at least 6 digits, at least 20 bits of entropy) and how that secret should be transmitted and handled. All of which makes good sense.

There’s nothing here that should be controversial when reported accurately.

Why stop using SMS?

SMS feels secure, right? You need your phone to receive a text message, and if someone else has your phone then you’re probably worrying about a whole lot more than just your text messages – and you can cut off service to that phone once you realize it’s gone.

Unfortunately, SMS is a lot less secure than you might think.

The system is vulnerable to social engineering attacks 2– a cracker contacts your cellular company, convinces them they’re you (not too difficult these days when so much information about people is readily available) and gets your cell service redirected. It’s also vulnerable to technical attacks on the cellular system itself.

These aren’t theoretical attacks on SMS – SMS has been documented as compromised multiple times already. 3,4,5

If not SMS then what?

SMS text messages are appealing because almost everyone carries a phone with them, so almost everyone can receive a text message with a login secret in it.

Today, almost everyone’s phone is a smart phone. Smart phones can run apps and apps can receive notifications.

This gives us two easy alternatives: app-based code generators and push notifications.

App-based code generators

Authy and Google Authenticator are both commonly used code-based authenticator apps. To use them you share a code between the app and the service you’re authenticating it with. When you want to authenticate yourself, the app will generate an annoyingly long code which is valid for a short period of time. You enter that code when you login and you’re set.

Both are easy to add support for to existing login flows and are compatible with RFC6238 – TOTP: Time-Based One-Time Password Algorithm.

Until recently, Blizzard Entertainment’s Authenticator app also generated a unique code. Blizzard recently switched it to using notification-style authentication. You can also buy physical authenticator which will generate a code.

Notification-based authentication

For notification-based authentication you have an app associated with the web site or application you’re logging into. You login using your password, and the app receives a notification asking you to confirm the login. This is the second factor.

Some applications do this kind of authentication in other ways – for instance, Slack allows you to get a “magic link” in email which will automatically log you into your Slack instance.

User priorities

This sounds like a mess, right? What are you supposed to do now? Turn off second factor SMS authentication after you’ve been lectured over and over to start using it?

Let’s get some priorities clear.

Keep in mind that passwords (usually the first factor in two factor authentication) are difficult for most humans to manage well – many people reuse them and/or don’t use strong passwords.

Also, while SMS is vulnerable to attack, the attacks on it aren’t casual (like a piece of software doing an automated login attack with passwords gleaned from compromised web sites) – they require human effort and at least today will be targeted attacks rather than “throw some pasta on the wall and see what sticks”.

With that in mind:

  1. code generators and app notifications are a better, stronger second factor than SMS text messages
  2. SMS text messages are a better second factor than none at all
  3. still use unique, strong passwords – using a second authentication factor doesn’t let you off the hook here

Developer priorities

As a developer:

  1. offer a second factor for authentication using an app-based notification if you have an app
  2. fall back to a code generator for users who don’t have apps or if you don’t offer an app
  3. be sure to transmit the second factor in a secure manner
  4. be sure to have enough complexity in the second factor that it’s not easily guessable/crackable (the NIST recommendation is at least 6 digits, and use an established algorithm like the ones discussed in RFC7238: TOTP: Time-Based One-Time Password Algorithm). It should also be for one time use.
  5. require your users to use strong passwords, communicating the requirements of the passwords to them clearly
  6. store user passwords securely, use a strong one way hash and salt the password

The Password Storage Cheat Sheet has some great recommendations on how to protect stored passwords.

And developers: forget about additional “security” questions as second (or third or fourth) factors. Those questions your bank likes to ask: “What’s your father’s middle name?”, “What was your maternal grandmother’s favorite color?”, “What is your favorite teacher’s hat size?” – these are second or nth authentication factors, but they’re terrible for security6. Just don’t even.


  1. “An obscure government agency is reinventing how the feds handle privacy”

  2. “So Hey You Should Stop Using Texts for Two-Factor Authentication” – ↩︎
  3. “How activist DeRay Mckesson’s Twitter account was hacked” – ↩︎
  4. “How Someone Allegedly Hacked Into Activists' Telegram Accounts” – ↩︎
  5. “Your mobile phone account could be hijacked by an identity thief” – ↩︎
  6. “Secrets, Lies, and Account Recovery: Lessons from the Use of Personal Knowledge Questions at Google”

Share this:
%d bloggers like this:
var _gaq = _gaq || []; var pluginUrl = '//'; _gaq.push(['_require', 'inpage_linkid', pluginUrl]); _gaq.push(['_setAccount', 'UA-239812-12']); _gaq.push(['_trackPageview']); (function() { var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true; ga.src = ('https:' == document.location.protocol ? 'https://' : 'http://') + ''; var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s); })();