Adaptive, Step-Up Multi-Factor Authentication

Indranil Jha

Plain-old authentication is boring. Today I'm going to show you how you can enhance your application's security by providing smart multi-factor authentication (MFA), the kind that takes contextual and behavior-based factors into account.

Through this article, I'll explain how this security pattern works. Just know that this pattern is universally applicable to any web-based, mobile, or desktop applications.

Why Adaptive Multi-Factor Authentication?

While normal MFA is a big step up above no MFA, it isn't perfect. MFA causes lots of pain points for users who quickly get frustrated when they're required to use multiple factors to authenticate all the time.

A great way to solve the inherent usability problems that come along with multi-factor is to use adaptive MFA. Adaptive MFA is a pattern in which the application you're logging into takes into account context about your authentication request:

What IP address are you making the request from? What geographic location are you making the request from? What client are you making the request from (a specific version of Chrome? Firefox? Android?) Etc.

By storing and using simple machine learning models on this data, the application you're logging into can selectively decide whether or not to force you (the end-user) to prove your identity using a second factor.

And, while adaptive MFA is great, you can get even more sophisticated by using step-up MFA.

What is Step-Up Multi-Factor Authentication?

Step-up MFA is a pattern commonly used to ensure the user is who they say they are before a sensitive operation is performed.

For example, let's say I go to visit my bank's website. I log in and I'm prompted for MFA, so I enter an SMS code and am let into my account. A few minutes later, I decide I want to change my password, so I go to the change password page. But, before I'm allowed to change my password, the bank website asks me to perform another MFA, so I re-enter a new SMS code into the website to prove I am who I say I am.

This pattern is referred to as step-up MFA because the application is asking me to "step up" and prove that I am who I say I am.

This pattern helps prevent a scenario where, after logging into my bank account, I walk away from my computer and an attacker tries to change my password maliciously. Because the bank website re-prompts the attacker for MFA (step-up), they prevent the attacker from compromising my account credentials.

Cool, right?!

How Do I Implement Adaptive, Step-Up Multi-Factor Authentication?

Great question! =)

If you're doing it yourself, the answer is not always obvious—as you essentially have to custom build the contextual analysis code, the step-up logic, etc. using whatever programming language/web framework/development tools are at your disposal.

There isn't any one-size-fits-all solution I'm aware of that magically solves these issues without a tremendous amount of custom development.

But, if you're using a service like Okta to manage your users already (Okta is an API service that handles user registration, login, authentication, authorization, MFA, etc.), you can get this behavior working without a ton of custom development work.

Okta Multi-Factor Authentication Considerations

Okta provides stand-alone REST-based MFA APIs (also called Factor APIs) that can be used directly by any application to leverage MFA. These APIs allow you to support basic MFA in your applications.

However, because these API's are stand-alone, they do not honor any contextual or behavioral information.

Moreover, the stand-alone Factor APIs need to use an Okta API Token which must be protected and secured, hence, this approach is not suitable for client-side applications without a server-side backend.

Consequently, in order to leverage Okta's adaptive MFA functionalities, your application needs to take a slightly different approach.

Introducing Factor Sequencing

How about going passwordless? By leveraging Okta's factor sequencing you can completely bypass traditional password authentication and still carry out MFA operations.

At a high level, here’s how it works:

Configure factor sequencing in your Okta authentication policy. Use factors such as Okta Verify, SMS, FIDO2 etc. Start the authentication flow using Okta's authentication API without providing a password Pass the end-client information in your API call

Okta’s authentication API will evaluate any pre-configured authentication policies you might have. If valid, this request will prompt the end-user for MFA. Your application can then call the factor API to verify the user's MFA challenge was successfully completed.

Benefits of Factor Sequencing

The benefit of this approach is that MFA can be performed entirely from the browser or client-side code (mobile/desktop)--no server-side code is required!

How Adaptive Multi-Factor Authentication Works with Okta

Here is a sequence diagram of the passwordless design pattern for the MFA flow we've discussed.

Example Multi-Factor Authentication Implementation

I recently built this single page application which leverages the design patterns discussed to achieve step-up MFA.

You can use this codebase as a kick-off point for your own application development if you'd like. I built this application in JavaScript (Vue.js), so the code should be fairly easy to follow regardless of what language you use.

If you'd like to see a demo of how this works, I put together a short YouTube video (below) which walks you through it.

How Multi-Factor Authentication with Okta Works Under the Hood

After a user logs into an application using an internal identity system and initiates a transaction, the application starts the authentication flow with Okta, passing along only the user ID and the user's application context information.

POST /api/v1/authn HTTP/1.1
Host: https://*******
Accept: application/json
Content-Type: application/json
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.86 Safari/537.36
Content-Type: text/plain
{ "username": "" }

NOTE: No credentials are passed in the API call to Okta.

Okta then evaluates the user's context from the HTTP headers and applies any pre-configured authentication policies. If the user is not authorized based on their application context, Okta will reply with an unauthorized response.

Otherwise, Okta will return a response with a

and a list of enrolled MFA factors to choose from. The application then prompts the user to choose an MFA factor and calls the MFA API with the selection.

POST /api/v1/authn/factors/smsqufwjrnT7fvcVR0h7/verify HTTP/1.1
Host: https://*******
{ "stateToken": "00CIWUamZgqt9Rfs1RIitioKRL7h7IWcKY0wqCVneC" }

Following this, the user receives an MFA challenge as a response. For example, if the chosen factor is SMS, the user will receive an OTP via SMS to their enrolled phone. The user then responds to the MFA challenge and the application calls the MFA API to verify the MFA response.

POST /api/v1/authn/factors/smsqufwjrnT7fvcVR0h7/verify HTTP/1.1
Host: https://*******
{ "stateToken": "00CIWUamZgqt9Rfs1RIitioKRL7h7IWcKY0wqCVneC", "passCode": "477492" }

Finally, Okta evaluates the MFA response and sends back the verification status. The application allows the transaction to proceed if the verification response indicates successful MFA.

What You Should Know About Adaptive, Step-Up Multi-Factor Authentication

In this post, we've talked about why adaptive and step-up MFA are so great. You've also learned how to implement these patterns using Okta.

If you'd like to learn more about how these patterns work, check out Okta's sign on policy API docs.

Indranil Jha
Senior CIAM Specialist

Indranil is a Customer Identity and Access Management Specialist at Okta. He has 17 years of extensive experience in Identity and Access management domain.