Implementing 2FA in the context of an API

Guillaume Viguier-Just
4 min readAug 23, 2017

--

“Two-factor authentication (also known as 2FA) is a method of confirming a user’s claimed identity by utilizing a combination of two different components.”, according to Wikipedia. 2FA is a quite powerful way to implement security for your web application, and make sure a user performing a request is really who they are, and not an external attacker. But how do you implement it in the context of an API ?

The different forms of 2FAs

The most common form of 2FA is using SMS. You probably all know it. When you pay via credit card, you are being asked to confirm your identity via a code which is sent to your phone number via SMS and which you need to enter in the payment application. If you enter the correct code, this means that you have in your possession the credit card number but also the phone of the person you claim to be, so there is enough assumption to think that you are who you claim, and the payment is authorized.

There are, however, other ways to verify your identity via 2FA which do not require SMS (which can become expensive). There are for example TOTP applications, such as Duo Mobile or FreeOTP, which allow you to generate an access code (without requiring any Internet connection besides for initial setup), which would then be asked by your application.

You could also enable a very basic form of 2FA via security questions, or ask users to have 2 email addresses and send a security code to the secondary email address of a user, but obviously these kinds of 2FAs would be much less secure than a temporary token sent via SMS or generated via a mobile application.

Just keep in mind that SMS is not the only form of 2FA out there, and that depending on your end users (and your budget: SMS can become pretty expensive), you might want to consider using something else.

Where to integrate 2FA ?

The next question is: when do you want to require your users to use 2FA ? Unfortunately, the answer, as with many software engineering questions is: it depends ! Depending on the security you want to require, you might want to ask your users to use 2FA every time they login, or every time they perform a specific operation, such as changing their password. You could also require 2FA or simply give your users the option to use it, by enabling it in their profile. You could even try to be smarter and require 2FA for your users only when they log in with a different browser or from a different location than the one they are usually in. It’s entirely up to you.

No matter what you chose, think security but also think user friendlyness. It could be pretty annoying for your users if they are not able to perform some operation in your application because they do not have mobile coverage at the place they are in (and though can’t receive the SMS your app sent out).

How to integrate it in your API ?

That was my initial problem (and the reason I wrote this article). When you are in a traditional website, the process seems rather simple in theory: user X wants to perform a 2FA enabled operation, the application sends them a token (via SMS for example), the user then enters this code in a form, the code is verified in the background and the operation is authorized. But when you have an API, the operation that requires 2FA can be just an API endpoint, so in this case, how is the code communicated to the API endpoint ?

The answer is actually quite simple: use a custom header. Normally, your API endpoints require your users to provide some token (whether it’s an OAuth token, or JSON Web Token or something else) for authentication, via the Authorization header. For example, with a JWT:

Authorization: Bearer eyJgbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6ImhpZC1kZXYifQ.eyJpZCI6IjU5MTk3NzNiYTY4ODc0MDBiYmVmZDc1YiIsImV4cCI6MTUwMzk5OTQ5OSwiaWF0IjoxNTAzMzk0Njk5fQ.jzES0z3XLYnXn9GPYk0P72q5DsAJX-owedHWd4Ftt_7F2mS45WYvHZIZVMrCmniVlLw2a7qOiWaqffA8yk2BnFjGsjfWqptEFEFYXRC-a1zxmmxN6gHEHXfA9FjlbsQZwk3QpuTamKiKHmqsK8hYKzRoFNGyOl6bxrwD8MMLD9w2ZnkpvXCrVFBnNfP3O2uM85fhBLlp-ukPGkoXCmZQ50UPMihhSwfW8pK3pSWaHTpIgIhJsESUBET3n1nZPyJ-fuplAv1MYFgPpf72jFN3G9uy5Z0VSOb55qRd-R0d_k_sbItUGPjQmOUzUZVo8CE2ysHIyvFf7Bj1C9xw6Pdv7d

In an endpoint in which you need your user to use 2FA, you simply require them to provide another header, for example X-YourApp-2FA, with the code that was sent to them via SMS or created via an application. For example:

X-YourApp-2FA: 123456

If the header is not there or the code in the header is wrong, you send a 401 with the header:

X-YourApp-2FA: required

You will probably also need to create another API endpoint to allow your client applications to trigger the generation of a code (and send your users an SMS) but this is “just” creating a custom action REST endpoint.

As a note, I didn’t find, in my research on this topic, any standard header that could be used for this. If any of you know of such a standard header (or work towards standardization), do let me know via comments. In the mean-time though, if you want to implement 2FA within an API, a custom header is the way to go.

Originally published at https://www.gvj-web.com on August 23, 2017.

--

--