Skip to main content

Authentication Flows

OAuth2 supports a variety of authentication flows, each with its own capabilities, configuration, and limitations. To ensure developers do not need to be experts in the variety of options available to them, these flows are "homogenized" to follow a common set of patterns that allows the peculiarities of each flow to be abstracted away from them.

To normalize these differences, implementations of these particular flows should conform to a common interface, allowing other components in the SDK to function without needing to know which specific flow is being used.

info

For more information on the details of this interface, please see AuthenticationFlow within the AuthFoundation design documentation, or its corresponding common API reference.

What constitutes an authentication flow?​

Many SDKs combine many capabilities into the same interface, blurring the lines between authentication, enrolment / registration, token storage, and so on. As more authentication flows are introduced, the complexity of these interfaces increase. To that end, authentication flows only represent the client-server communication necessary for a client to sign a client in to a server resource.

These are are classes that encapsulate the lifecycle of authenticating using a particular flow. For example, implementing the Device Authorization Grant Flow can be complex, particularly since it involves polling against the authorization server, which can increase the burden on you to get the details right. ß By using an authentication flow, developers can focus on their UI, encapsulating the individual flow's business logic.

Features of an authentication flow​

Sending REST API requests constitutes a small part of the complexities involved in building a sign in experience. The capabilities that surround these requests typically involve:

  • Communicating state changes to other parts of an application
  • Identifying when authentication has begun vs when it is completed
  • Interactions with a developer when additional data or UI is required
  • Consistently validating tokens upon successful sign-in

Some advanced features are often required which may seem nonobvious to an SDK enginer, yet many enterprise or complex consumer applications have a variety of needs, such as:

  • Supporting multiple target hosts or environments
  • Signing in with multiple users
  • Concurrent sign-in operations (e.g. special-purpose tokens used for vendor SDKs, integration of features acrsoss a company's acquisitions, or tokens restricted to readonly scopes)

For these and many other reasons, this SDK abstracts the details of how an authentication flow works, from the rest of the infrastructure surrounding it. This allows the flow's class to focus on its implementation details for formulating requests, processing responses, and implementing its particular workflow (in accordance with public standards or documentation).

Developer Experience patterns​

Different authentication flows have different requirements, but generally fall into two primary classifications:

  1. Single-step flows (e.g. 1FA sign-in)
  2. Multi-step flows (MFA sign-in, challenge/response, etc)

Each logical step may result in multiple HTTP requests, but the idea is that a step encompasses a task which may require developer or user intervention. To simplify these operations, a similar naming convention is used to indicate these steps: start is used to initiate a flow, and resume is used to continue a flow through multiple steps.

Authentication Flow interface​

All authentication flows should all feature the following common characteristics:

  • An instance of an Authentication Flow can be constructed with client configuration parameters, scopes, and other common settings that will be used to sign users in to a particular client/scope.
  • An Authentication Flow object can be used by one active sign-in session at a time.
  • Authentication Flow objects can be reused after it is finished (either successful or failed sign-in).

Since the goal of this pattern is to simplify and homogenize the calling interface for the various flows, classes that implement this interface shoudl include at a minimum:

  • A isAuthenticating boolean property.
  • A context property containing the Authentication Context for the current authentication session.
  • A reset() function to reset the flow if it needs to be prepared for another session.
  • A start(...) function to start an authentication session. It should accept the arguments necessary to perform the sign in, and an optional context.
  • An optional resume(...) function if the authentication flow is a multi-step flow.

Final token exchange​

The critical part of this pattern is the centralized and consistent business logic used to parse and validate responses from the Token API. The purpose of this interface, and its accompanying implementations, is to allow the OAuth2Client to be able to consistently exchange and process these tokens.

Once a flow is ready to formulate a request to the /token endpoint (represented by the tokenEndpoint property of OpenIdConfiguration), the flow should pass the token request to the OAuth2Client for this flow (using the exchange(token:) function) instead of attempting to perform the request itself.

This function then performs the request, processes the response, and performs all necessary validation steps.

Code Examples​

The best way to showcase how this would work is through a few examples.

const flow = ResourceOwnerFlow({
issuer: URL("https://login.example.com/"),
clientId: "theClientId",
scopes: "openid profile offline_access email"
})

try {
const token = flow.start({
username: "alex",
password: "supersecret"
})
} catch {
// Error handling
}

As you can see, each of these flows follows similar patterns, and their naming conventions are consistent. Even complex multi-factor authentication can be handled using these same simple conventions.

Supported Flows​

Some of the flows supported by this SDK are described here:

NameAPI ReferenceDescription
Resource OwnerResourceOwnerFlowSimple username/password sign in.
Authorization CodeAuthorizationCodeFlowWeb-based redirect sign in.
Device AuthorizationDeviceAuthorizationFlowHeadless sign in using a device authorization code, usually for TVs, CLIs, or other browserless devices.
JWT BearerJWTAuthorizationFlowSign in using a JWT signed by a trusted key.
Token ExchangeTokenExchangeFlowExchange one set of tokens for another.
Direct AuthenticationDirectAuthenticationFlowOkta's MFA-capable native sign in.
IDX (Interaction Code)InteractionCodeFlowOkta's policy-driven MFA sign in / registration.