At Twitter, we want to make it easy as possible to secure your account. Designing a secure authentication protocol is tough; designing one that is also simple and intuitive is even harder. We think our new login verification feature is an improvement in both security and usability, and we’re excited to share it with you.
Traditional two-factor authentication protocols require a shared secret between the user and the service. For instance, OTP protocols use a shared secret modulated by a counter (HOTP) or timer (TOTP). A weakness of these protocols is that the shared secret can be compromised if the server is compromised. We chose a design that is resilient to a compromise of the server-side data’s confidentiality: Twitter doesn’t persistently store secrets, and the private key material needed for approving login requests never leaves your phone.
Other previous attacks against two-factor authentication have taken advantage of compromised SMS delivery channels. This solution avoids that because the key necessary to approve requests never leaves your phone. Also, our updated login verification feature provides additional information about the request to help you determine if the login request you see is the one you’re making.
Now you can enroll in login verification and approve login requests right from the Twitter app on iOS and Android. Simply tap a button on your phone, and you’re good to go. This means you don’t have to wait for a text message and then type in the code each time you sign in on twitter.com.
When you enroll, your phone generates an asymmetric 2048-bit RSA keypair, which stores the private key locally on the device and sends the public key, which Twitter stores as part of your user object in our backend store, to the server.
Whenever you initiate a login request by sending your username and password, Twitter will generate a challenge and request ID –– each of which is a 190-bit (32 alphanumerics) random nonce –– and store them in memcached. The request ID nonce is returned to the browser or client attempting to authenticate, and then a push notification is sent to your phone, letting you know you have a login verification request.
Within your Twitter app, you can then view the outstanding request, which includes several key pieces of information: time, geographical location, browser, and the login request’s challenge nonce. At that point, you can choose to approve or deny the request. If you approve the request, the client will use its private key to respond by signing the challenge. If the signature is correct, the login request will be marked as verified.
In the meantime, the original browser will poll the server with the request ID nonce. When the request is verified, the polling will return a session token and the user will be signed in.
Login verification is more secure and easier to use. And you can still sign in even if you lose your phone.
The private key is only stored on the phone. However, there’s still a way to sign in to Twitter even if you don’t have your phone or can’t connect to Twitter –– by using your backup code. We encourage you to store it somewhere safe.
To make the backup code work without sharing secrets, we use an algorithm inspired by S/KEY. During enrollment, your phone generates a 64-bit random seed, SHA256 hashes it 10,000 times, and turns it into a 60-bit (12 characters of readable base32) string. It sends this string to our servers. The phone then asks you to write down the next backup code, which is the same seed hashed 9,999 times. Later, when you send us the backup code to sign in, we hash it one time, and then verify that the resulting value matches the value we initially stored. Then, we store the value you sent us, and the next time you generate a backup code it will hash the seed 9,998 times.
This means that you don’t have to be connected to Twitter to generate a valid backup code. And, due to the one-way property of the hash algorithm, if ever an attacker could read the data on our servers, he/she won’t be able to generate one.
In addition to storing your backup codes safely, we encourage you to backup your phone. If you have an iPhone, you should make an encrypted backup, which stores the cryptographic material necessary to recover your account easily in case you lose your phone or upgrade to a new phone. Also if you’re upgrading, you can simply un-enroll on your old phone and re-enroll on your new phone.
Twitter clients that use XAuth authentication, which expects a username and a password, don’t always support login verification directly. Instead, you’ll need to go to twitter.com on the web, navigate to your password settings, and generate a temporary password. You can use this password instead of your regular password to sign in over XAuth.
We’ll continue to make improvements so signing in to Twitter is even easier and more secure. For example, we’re working on building login verification into our clients and exposing a login verification API for other XAuth clients so people who don’t have access to the web also have a seamless login experience.
Did someone say … cookies?