Multi-factor authentication is the most reliable way to ensure the security of your users PII (personally identifiable information), and with Stormpath it’s easier than ever to implement in your application! Why is MFA super-secure? It’s simple: While a user may have a lousy password, additional factors are inherently immutable. Some common second factors of authentication include a text message with a one-time use code, a code that refreshes regularly in an app like Google Authenticator, or a USB hardware device that must be plugged into the user’s computer.

I first worked with multi-factor authentication back in the ‘90s. The saying was that a more secure way of authenticating was to combine “something you know and something you have”. The something you know was your password. The something you have was the hardware dongle with the display that changed numbers every minute.

This proved to be very effective at securing all manner of systems – from operating system lock screens to corporate Intranet websites. As smartphones have come of age and users have become savvier, MFA is more accessible to people outside of large enterprises than ever before.

Fast forward 20 years and MFA is all over the place. You’ve probably used it in your everyday life and may not even be aware. If you use a website that sends you an SMS message when you authenticate or even to change your password—that’s multi-factor authentication. The “something you have” is now your mobile phone.

It’s still hard to build MFA as a developer. You have to consider how secure your approach is, how you’ll test it, and how you will support it. Here are four challenges for building MFA into your Java application:

1. Multi-factor is Hard to Secure

Leaving the password as a given as the first factor, let’s examine the possibilities for additional factors when authenticating. The most popular and consumer-accessible types of MFA fall into three categories (listed least secure to most secure):

SMS (text messages) one-time use tokens Time-based tokens Hardware token devices

SMS-Based Multi-factor Authentication

Perhaps the most common today, and also the easiest to implement is text message-based MFA.

The flow works like this:

You log in to an application with your username and password You see is a text field asking you to input a code sent via SMS You receive an SMS with a one-time use code You enter the code in the text field and proceed on to the application

Easy, right? Unfortunately, this isn’t very secure, and security is what you’re going for if you’re implementing MFA, right? The National Institutes of Standards and Technologies (NIST) has gone so far as to say it should no longer be used at all (section 5.1.3.2). Yikes!

Note: Out-of-band authentication using the PSTN (SMS or voice) is discouraged and is being considered for removal in future editions of this guideline. 1 2 3 Note : Out - of - band authentication using the PSTN ( SMS or voice ) is discouraged and is being considered for removal in future editions of this guideline .

Why is it insecure? Here’s one scenario: Imagine you use iOS and the Messages app, which allows your text messages to come to your desktop. Now, imagine an attacker has compromised your Apple ID and password. The attacker will now be able to intercept incoming text messages, including those that are one-time codes for multi-factor authentication.

NOTE: Whenever a user logs into the Messages app for the first time, an email notification is sent letting the owner know that Messages has been used from a new device. This could tip off the real owner to their account being used by an attacker.

Time-Based Token Multi-factor Authentication

Another common, more secure, but more challenging to implement approach is called Time-Based One-Time Password algorithm or TOTP. This approach uses a secret shared between the server and the client (typically a mobile app) in conjunction with the current time to generate a one-time use code. The client knows the code by running the shared secret through the algorithm and the server can verify the posted code by running the same secret through the algorithm. The code is only valid for a set amount of time, usually 30 seconds.

The flow looks like this:

You log into an application with your username and password You see is a text field asking you to input the latest code You launch your TOTP client on your mobile phone and see the current code You enter the code in the text field and proceed on to the application.

It’s more secure than the SMS approach because there is no medium of transmission for the code. It is generated by the algorithm. The shared secret must be kept a secret for this approach to remain secure.

One of the most popular implementations is Google Authenticator. It makes the TOTP approach easier to use by showing the secret as a QR code that most mobile apps can read. This is much more reliable and easier to use than manual input of a shared secret.

Hardware Token Devices

This is the most sophisticated, secure and hardest to implement approach. This approach used to be the domain of companies building MFA for the enterprise (read: expensive).

Then, along came the Fast IDentity Online Alliance (FIDO). It has produced a device-centric standard making the ability of companies to implement hardware-based multi-factor authentication much more accessible.

The flow can work in a variety of ways, but here are two examples:

Passwordless

You launch an application on your smartphone You see a screen waiting for your fingerprint You touch your finger to the fingerprint reader You are authenticated and enter the app

Note: This mode has a good separation of concerns in that the app has no access to your fingerprint data. The hardware in the phone responds to the app with success or failure.

Second Factor

You log in to an application with your username and password You see an indicator, such as a spinner, waiting for input from your hardware device You touch the thumb-pad on your hardware device connected to your computer You proceed on to the application

Yubikeys are a good example of this mode. It’s a physical device that connects to your computer’s USB port and has a touch sensitive area to respond to an authentication request. NOTE: This touch sensitive area is NOT a fingerprint reader. Rather, it senses touch which triggers the presentation of secure login credentials that conform to the FIDO standard.

My personal preference has become Google Authenticator. It’s supported by many of the sites I use (Gmail, Amazon Web Services, Github, etc.). It’s much less likely that I will lose my phone than that I will lose a hardware token. I use a Google Authenticator app that supports secure backup of my TOTP definitions and is itself protected by requiring my fingerprint before showing me the codes. As an added bonus, this made my recent transition from iOS to Android smooth and painless.

2. Multi-factor Authentication is Hard to Develop in Java

At Stormpath, we recently rolled out support for two of the three approaches described above: SMS and TOTP (specifically, Google Authenticator). FIDO support is on our short-term roadmap. We’ve implemented these multi-factor approaches from top to bottom so that you don’t have to.

For each of these approaches, we have uniform interfaces. The flow is generally like this:

Create a factor Create a challenge against that factor validate the challenge

Upon successful validation, the factor transitions from an UNVERIFIED state to VERIFIED . New challenge s against the factor can then be created and verified.

This was no small task for us and it’s one of the reasons to choose Stormpath over “rolling your own”.

There are a number of considerations when adding MFA to your application. For instance, will a user be required to setup MFA during registration? Will a user have to provide a token code at every login or only under certain circumstances?

Google Authenticator TOTP in Action

I’ve created a demo Spring Security Spring Boot WebMVC application that (a) requires you to create a Google Authenticator factor the first time you login and (b) requires you to input the current code from the chosen factor each time you login.

Let’s take a peek at some Java code. Here’s a method for creating a Google Authenticator factor in the example’s MFAServiceImpl:

@Override public GoogleAuthenticatorFactor createGoogleAuthenticatorFactor(Account account, String name) { GoogleAuthenticatorFactor factor = client.instantiate(GoogleAuthenticatorFactor.class); factor.setAccountName(name); factor.setIssuer(null); factor.setStatus(FactorStatus.ENABLED); factor = account.createFactor(factor); return factor; } 1 2 3 4 5 6 7 8 9 10 11 12 @ Override public GoogleAuthenticatorFactor createGoogleAuthenticatorFactor ( Account account , String name ) { GoogleAuthenticatorFactor factor = client . instantiate ( GoogleAuthenticatorFactor . class ) ; factor . setAccountName ( name ) ; factor . setIssuer ( null ) ; factor . setStatus ( FactorStatus . ENABLED ) ; factor = account . createFactor ( factor ) ; return factor ; }

This code takes a Stormpath Account and a name and returns a GoogleAuthenticatorFactor .

Validating a challenge against the factor is very straightforward:

@Override public GoogleAuthenticatorChallengeStatus validate(Account account, String code) { return getGoogleAuthenticatorFactor(account).createChallenge(code).getStatus(); } 1 2 3 4 5 @ Override public GoogleAuthenticatorChallengeStatus validate ( Account account , String code ) { return getGoogleAuthenticatorFactor ( account ) . createChallenge ( code ) . getStatus ( ) ; }

Here, we pass in a GoogleAuthenticatorFactor and a code . The two lines of code in the example method will validate the code against the factor and return the result, which will either be success or failure.

I’ll go into a lot more detail about the workings of this MFA example in a follow-up post that focuses on implementing MFA with Stormpath.

3. Multi-factor Authentication is Hard to Test in Java

At Stormpath, we <3 tests! We’ve got a ton of unit and integration tests in the Stormpath Java SDK.

Integration testing of MFA presents a few not-insignificant challenges. In the case of SMS, user interaction is required. That is, a device is going to receive a real SMS message containing a code that needs to be entered on the challenge for validation. In the end, we created tests and left them disabled in the SDK so that they would not interfere with our automated CI (continuous integration) and release processes.

Google Authenticator integration tests are run for every build and release. How is this possible given that Google Authenticator also requires entering in a code that changes every 30 seconds? The answer lies in the underpinnings and strength of TOTP: its codes are algorithmically generated.

All that’s required is a shared key and an accurate clock (the one built into your computer will do just fine). So, to be able to test Google Authenticator MFA against the real Stormpath backend, we built a TOTPService into our test suite.

It has a static method: getTotpPassword(byte[] signingKey, long currentTime) that takes in the shared secret and the current time and returns the current valid code.

Thus, we can create a GoogleAuthenticatorFactor on the backend, use its secret to determine that latest valid code, and create and verify the challenge against the backend in an integration test.

Sounds complex? That’s why we built this at Stormpath: so you don’t have to!

4. Multi-factor Authentication is Tough to Support

If you’re going to implement multi-factor authentication, you’ll need to at least give your admins the ability to manage certain aspects of it. For instance, if a user loses their phone, an admin may need to act quickly to remove registered factors.

This could be a self-service part of your application, but you need to take extra care to perform these sorts of actions in a secure way. This is often accomplished by requiring users to receive an email or to put in additional security information (best friend’s name growing up, first city you lived in, etc.). These can all be considered additional (although pretty weak) factors.

In the Stormpath Admin Console, we have an interface to manage registered factors for an account:

MFA the Easy Way

In this post, we’ve covered some of the approaches to multi-factor authentication, the merits of each, and the challenges involved in building it yourself.

Stormpath built MFA support into the bones of our SaaS solution. And, we’ve built deep support into the Java SDK as well. With a few lines of code, you can add support for SMS and Google Authenticator within your application.

In a follow-up post, I will go into more depth on this demo project, which is a fully functional Spring Security Spring Boot WebMVC application that supports Google Authenticator MFA at each login.