An image of a combination padlock

 Everyone and their mother already knows about 2FA. You enter your password, you receive a message with a one-time password on your phone. Simple enough. Relying on secondary communication channels, however, is not always the best option – sometimes, it’s not even possible. This is where TOTP comes in to save the day. 

The usual 2FA suspects 

The most popular method of 2FA today is using an alternative communication channel like SMS, Voice, or email. It relies on the fact that a phone number belongs to a specific person, and only that person can access that channel. This method is easy to implement and does not require any special logic or setup on the client side since every smartphone today can use those channels out of the box.  

Some clients, for instance, simply do not want to share their personal contacts (GSM, email), or we are not allowed to store them because of the data protection policy. We had a case like that on a project involving a school, where we needed to allow students to access our platform but were not allowed to store their personal information due to a privacy policy regarding minors.  

An alternative approach: Time-based one-time password  (TOTP)

There is a way to leverage cryptography and its properties to implement an alternative method for 2FA. It requires us to pair the 2FA device (usually a smartphone) with our service only once and then use it without any communication between the two.  Instead of sending the code over a communication channel to the device, TOTP enables us to generate it on both client (device) and server (service).

RFC 6238 standard describes TOTP as an implementation of the OTP algorithm using time as the source of random seed for code generation using the HMAC algorithm for providing cryptographic security.  

How does it work?

Let’s break that down a bit. This method assumes that both client and server have synchronized clocks (to a reasonable degree), and we can rely on that fact thanks to the ubiquitous NTP (Network Time Protocol). Another fact that this algorithm relies on is that client and server will exchange a secret during the initialization phase (private key exchange). Having both those facts in mind, we can calculate the same code on the client and server during a specific time window using the function:  

HMAC(private_key, time).  

Pairing flow (Private key exchange)
  • Client requests private key from server  
  • Server generates new private key using secure random algorithm  
  • Server safely stores private key and links it to client who requested it  
  • Server presents private key to client (Usually in a QR code format on web application)  
  • Client receives private key (Usually by scanning QR code on web application)  
  • Client safely stores private key for future use  

Authentication flow (Code verification)

  • Client provides his credentials (Username and password) on login  
  • If credentials are correct, server requests TOTP input from client  
  • Client calculates TOTP based on HMAC(secret, time) and provides it to server  
  • Server calculates TOTP based on HMAC(secret, time) and compares it to provided code  
  • If codes match, authentication is successful, otherwise, it fails  

We can choose how wide we want our time window to be. For example, calculating new code every second will leave little time for our user to enter the code and lead to limited usability. That is why 30-second time duration is usually used, and it is achieved by truncating the current time before applying the HMAC calculation.  

Now the only challenge is that we need something on our client’s device to implement this logic and provide OTP. There are ready solutions out there, like Google authenticator. 

Using TOTP as our method of 2FA means there is no need to accept and store any personal data from users, like phone numbers or email. There is also no additional cost associated with sending codes to users. The cherry on top of all that is higher security since there is no way to intercept any codes sent during the authentication flow.  

How to implement TOTP

There are lots of ready-to-use solutions, both for client and server. Multiple libraries for Java developers are available, some of which even include spring boot integration. If something generic is preferred, multiple standalone servers are available.  

Since we had our existing battle-tested in-house system already running, we did not want to introduce any more complexity and impact the existing system’s performance. To support TOTP, we decided to deploy a standalone open-source solution called Keycloak.  

TOTP is just one of Keycloaks many nice features, but it is much more than that. It is a complete authentication and authorization solution with support for OAuth, SAML, and user federation with any other systems using custom plugins.  

In our case, Keycloak is exposed over a public endpoint and provides complete TOTP functionality, like device pairing, QR code generation, code generation and validation, and all necessary security defenses against brute force or DoS (Denial of Service) attacks.  

There were some challenges, though. We had to provide a way for Keycloak to verify the user’s credentials (username and password) during a 2FA login. Instead of importing all password hashes from our own system and keeping them synchronized, we opted to write a custom plugin that will simply delegate any password validation to our own system and let Keycloak handle all other parts of TOTP flow.  

The drawbacks  

Although TOTP is a great solution for 2FA, it does have some drawbacks to consider:  

  • It requires a client application like google authenticator  
  • Lost device recovery can be tricky  
  • Requires additional pairing step before device can be used  
  • Needs frontend support (Where QR code will be served for pairing)  

The verdict

Despite the afore mentioned drawbacks, TOTP is an excellent alternative to the usual 2FA channels, and it makes it possible to perform 2FA without storing sensitive user data like a phone number or email address.  

Although it does require a client-side application, it is easy to install and set up. On the server side, many well-tested and supported solutions can be easily integrated into existing systems.  

So, if you provide any kind of service requiring authentication and offer a 2FA mechanism to your users, consider TOTP an interesting and secure alternative to traditional 2FA methods.