Recently, I put some time aside to write a two-factor authentication app for macOS for personal use. A nice perk of working at Sqreen is what we call the “Sqreenity” — getting to set aside a week at a time to work on your own project ideas. Twofa was my Sqreenity a few weeks ago, after I realized I would want to use a command-line based client for 2FA for macOS, but one with my requirements does not exist yet.
The elevator pitch is that twofa is a command-line app that uses Touch ID to protect your secrets. Oh, and it is open sourced at https://github.com/sqreen/twofa (under the MIT license).
If 2FA is your jam, and you are tired of transferring random strings of digits from your smartphone to the computer, you may find it useful. Check it out, any feedback about it would be amazing.
That’s more or less the executive summary. However, if you are curious about the why, and the how, read on.
Background on 2FA
Skip straight to The rationale for twofa, if you know what the “F” in 2FA stands for, what TOTP is, and what APIs are.
Wait, what exactly is two-factor authentication?
So let’s start at the beginning. I subscribe to a point of view about security that stipulates: passwords are insecure, and bad.
If you have an account that is protected with a username and a password, and nothing else, then the only thing keeping intruders out of your account is their laziness.
As long as the account in question contains cat memes, family photos, and other items of value mainly to yourself, you are good to go. Your threat model permits the use of just passwords.
If you need to protect an account that contains data that’s valuable to others, the picture changes.
As soon as your account becomes valuable, the inconvenience of attacking you will not be a deterrent to a motivated attacker.
This is true, by the way, even when 2FA is in use. It just sets the bar much much higher on the security and inconvenience measures.
This is where 2FA comes in. It stands for “two-factor authentication.” The “factor” in this case refers to a specific “way” to prove who you are. If you use a multi-factor authentication scheme, it means you are diversifying to impede attackers.
Some examples of different single-factor authentication methods:
- If you use only password protection, you could say your authentication factor is “something you know” (i.e. your password).
- If you used an iris scanner to authenticate, you would still be using single-factor authentication. The factor in this case would be “something you are” (i.e. your eyes are inherently unique to you, without you having to do anything about it).
- If you authenticate with a passport, your factor would become “something you have” (i.e. there is only one valid copy of your passport in existence, and it is not easily duplicable).
Trick(y) question: if you authenticate with two passwords, is that two-factor authentication?
No. It is still the same factor of “something you know”, only applied twice. However, if you used a combination of different factors, you would be using 2 or even 3-factor authentication.
Wait, so what is TOTP and why does it matter?
TOTP stands for Time-based One Time Password, and it is the informal name of an algorithm that is commonly used for 2FA online. You feed it with a secret value that never changes, and the current time, and it will spit out a code valid for a set period of time (e.g. 30 seconds). This is why one of the inputs is the current time.
So if your clock is wrong, the codes you generate will be invalid. TOTP matters in this context because it is one of the most common methods for implementing 2FA.
Wait, so what is an API?
An API is programmer-speak for ways of telling the computer what to do, or asking it for information.
For example, if your computer has a way to set and get the time, then programmers will use the “time API” to get that information.
In this post, I will refer to the system Keychain APIs. It is the means for a program to tell the operating system “hey, store this secret value” or “fetch that secret value.”
Now, with the prerequisites out of the way, let me get into why I wrote twofa as a tool for 2FA for macOS in the first place.
The rationale for twofa
When your day-to-day involves using many services, it can be nice to have the 2FA code available directly on your computer. We use 2FA extensively at Sqreen, and at some point it becomes irritating to be interrupted for code re-entry on a regular basis.
“Oh, I see you are working on something. Stop it, get your phone, and authenticate. Sorry to break your flow.” — Some third-party service
Sometimes, this means of doing 2FA is beyond irritating, and gets outright stressful. Imagine getting a PagerDuty alert in the middle of the night. You rush to log into AWS, and get asked for your 2FA code. You reach for your trusty 4 year old iPhone 5s, and it decides to be super slow.
“Please wait a minute or two while I load this application as slow… as… I… can… I’m sure your PagerDuty can wait.”
Why write a new app for 2FA for macOS?
Okay, we’ve established the background about 2FA and why it matters, as well as why it can be annoying, so why not use an existing solution that can be used on the computer? While there’s no Google Authenticator for doing 2FA for macOS, there is 1Password and Authy. Both seem to be pretty popular, and 1Password even seems to support Touch ID.
These are great options, and it just comes down to how you use your tools.
Personally, I just don’t like installing and using new GUI applications, unless I absolutely need to. For many tasks, it is unavoidable, and clearly you often need a GUI, but for 2FA code generation it’s not a given. I find it much easier to type “twofa get aws” in the Terminal (which is likely already open) than to locate an icon, click on it, locate the appropriate account visually, then click on it to copy the code.
Also, 1Password is much more than just an 2FA code generator. I would rather use a smaller tool that provides just what I need, than a bigger tool that offers functionality I will never use.
It is super useful, though, to have something like 1Password integrated directly into the browser (where you usually need the 2FA code in the first place), but there’s a way to achieve an even better experience (subjectively, of course, and assuming you like keyboard shortcuts) using Automator. I’ll get to that in a bit.
Surely, command-line TOTP generators already exist though?
Yes, there are tools for this. But most don’t describe their seed storage, which makes it harder to choose. And none use Touch ID.
Why is the lack of Touch ID important?
It’s important because of what we touched on earlier. A password is a “what I know” authentication factor, and another is “what I have.” And TOTP depends on having a “secret value.”
So why do we say that app-based 2FA is actually 2FA, and not just the same “what I know” factor as password?
The answer is – because you can not exfiltrate the secret from your smartphone. Non-jailbroken iPhones and non-rooted Android phones offer a reasonably secure storage for your TOTP secret value.
The conclusion here is that if your TOTP secret can be easily duplicated, it ceases being a “what you know” factor. And with that — you revert from having 2-factor authentication to having two instances of a single-factor authentication.
That’s the problem. While smartphones are reasonably locked down by default, computers aren’t. So a command line tool that stores your TOTP secret in a file somewhere, kind of misses the point of having 2FA in the first place.
So how does ‘twofa’ achieve proper 2FA-ness?
Macs that have Touch ID, come with a special piece of hardware called the T2 security chip. You can read the details here: https://www.apple.com/mac/docs/Apple_T2_Security_Chip_Overview.pdf.
The executive summary, however, is that each T2 chip has a unique encryption key called UID (“Unique ID”) fused in its silicon. This key can not be seen or used by software directly, but applications can ask the chip to perform cryptographic operations with the key, and return the result.
This means data encrypted with this key cannot be decrypted on any other device.
Furthermore, macOS uses the Secure Enclave (part of the T2 chip) to bind the keychain contents to the device. From the overview doc above:
“Software running on the Secure Enclave takes advantage of the UID to protect device-specific secrets such as Touch ID data, FileVault class keys, and the Keychain.”
“The UID allows data to be cryptographically tied to a particular device.”
So with all that background, all ‘twofa’ has to do is use the macOS keychain, indicate that the data needs to be bound to the device, and voila. It is standing on the shoulders of giants, but the end result should be that it is an actual, honest-to-god second factor — real 2FA for macOS — and not just a way to mimic 2FA.
For the record, ‘twofa’ will work on non-Touch ID Macs as well. This scenario is handled automatically by macOS, which acts as the middleman between ‘twofa’ and the Secure Enclave. While still better than using plain passwords, this mode will be significantly less secure.
Can other applications on the same Mac access my data?
Nope, other applications will not be able to access or modify this data.
An interesting aspect of how Apple has designed its systems is that the API for binding data to the device is not accessible to most programs.
To use it, you have to jump through some hoops. First, you need to sign up for an Apple Developer account. This will set you back some time and money.
Then you need to declare to Apple what features your application means to use: “Hey, Apple, I would like to use Touch ID for this app, and have some space for storing data, but I will not use iCloud, or HomeKit, so forget about those.”
Then, after creating the application, you need to digitally sign it with an Apple-approved private key.
What this does is, among other things, guarantee:
- that applications NOT signed with your key (i.e. any other application) cannot access the same data that your application can.
- that your application cannot be modified to do something malicious. I.e. it would be impossible for somebody to modify ‘twofa’ to email them your one-time passwords every time you use it. Because by doing so, the digital signature that identifies your application, would be changed, and the operating system would refuse to carry out the requested data access.
So no, other applications will not be able to access your data. Nor can it be tricked into doing something with your data that it shouldn’t.
What about the user experience?
The experience and ease of use of command-line utilities is subjective, so I won’t evangelize that part too much. However, some 2FA clients have a browser extension, which is very handy.
So here’s a neat workflow I settled on that compensates for the lack of a browser extension (subjectively. At least, it does if you like keyboard shortcuts).
It’s really simple. First, open the Automator app, and create a “Quick Action” document like this:
This will pop up a dialog box with an input field, where you can enter the account ID, and pass it to the twofa command line utility. Since the utility puts the code directly into the pasteboard, this is all you need.
Now assign a keyboard shortcut in the Keyboard prefpane and you are golden:
Here’s how that looks in action:
After clicking OK, the 2FA code will be copied to the pasteboard so I can paste it directly where I’m logging in.
While the current state of twofa as a Touch ID-aware 2FA for macOS tool is ok for bare minimum workflows, there is a very exciting next step that could be taken.
Namely, it could be modified to implement FIDO 2.0 Client to Authentication Protocol, and then it could support the WebAuthN API. This is an industry-standard API for browsers to authenticate users using cryptographic keys directly in the browser.
However, for now, I am sufficiently happy with the state of this as a command-line utility. It is pretty useful for me, and I hope it can be of some use to others as well. If you try it out yourself, let me know what you think on Twitter @jkirsteins or shoot me an email at email@example.com.