<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
    <channel>
        <title>Okta Client SDK Blog</title>
        <link>https://okta-client-architecture.netlify.app/proposals</link>
        <description>Okta Client SDK Blog</description>
        <lastBuildDate>Tue, 23 Dec 2025 00:04:02 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <language>en</language>
        <item>
            <title><![CDATA[Direct Auth Kotlin SDK]]></title>
            <link>https://okta-client-architecture.netlify.app/proposals/003-direct-auth-kotlin</link>
            <guid>https://okta-client-architecture.netlify.app/proposals/003-direct-auth-kotlin</guid>
            <pubDate>Tue, 23 Dec 2025 00:04:02 GMT</pubDate>
            <description><![CDATA[This proposal outlines the design for a Kotlin Multiplatform library that provides the interfaces and methods necessary]]></description>
            <content:encoded><![CDATA[<p>This proposal outlines the design for a Kotlin Multiplatform library that provides the interfaces and methods necessary
to implement native sign-in flows using Okta's Direct Authentication APIs. This
concept is part of a larger pattern for Authentication Flows within the Okta SDK. By using this library, developers can
build fully customized and integrated sign-in experiences, including support for
Multi-Factor Authentication (MFA), directly within their native applications.The design is guided by the principles and
API surface defined in the reference Direct Authentication API documentation,
while adapting them to be idiomatic for modern Kotlin development.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="motivation">Motivation<a href="https://okta-client-architecture.netlify.app/proposals/003-direct-auth-kotlin#motivation" class="hash-link" aria-label="Direct link to Motivation" title="Direct link to Motivation">​</a></h2>
<p>Currently, developers building native applications that integrate with Okta typically rely on a browser-based,
redirected authentication flow. While secure and effective, this approach has several drawbacks for native clients:</p>
<ul>
<li><strong>Poor User Experience:</strong> Redirecting users out of the application to a system browser for sign-in creates a jarring
and disconnected experience. It breaks the flow of the native application and can feel less polished and integrated.</li>
<li><strong>Limited UI Customization:</strong> The sign-in and MFA pages are hosted by Okta. Developers have limited control over the
look and feel, making it difficult to create a seamless experience that matches their application's branding and
design system.</li>
<li><strong>Infeasibility in Browser-less Environments:</strong> Many valid use-cases for authentication exist where a web browser is
not available. This includes command-line interface (CLI) tools, IoT devices, and other "headless" systems. The
browser-based flow is not a viable option for these platforms.</li>
</ul>
<p>To work around these issues, developers might attempt to call Okta's low-level authentication APIs directly. This is a
complex and error-prone process, requiring the developer to manually manage the authentication state machine, handle
various MFA challenges, and ensure secure token handling.</p>
<p>This proposal seeks to address these problems by providing a high-level, stateful SDK specifically for Direct
Authentication. This will empower developers to easily build custom, native authentication flows that provide a superior
user experience, match their application's branding, and support a wider range of client types, all without needing to
manage the underlying complexity of the authentication protocol.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="design-objectives">Design objectives<a href="https://okta-client-architecture.netlify.app/proposals/003-direct-auth-kotlin#design-objectives" class="hash-link" aria-label="Direct link to Design objectives" title="Direct link to Design objectives">​</a></h2>
<p>Authenticate users using Okta's Direct Authentication API, enabling native sign-in experiences supporting Multi-Factor
Authentication (MFA).</p>
<p>This enables developers to build native sign-in workflows into their applications, while leveraging MFA to securely
authenticate users, without the need to present a browser. Furthermore, this enables passwordless authentication
scenarios by giving developers the power to choose which primary and secondary authentication factors to use when
challenging a user for their credentials.</p>
<p>This library provides the classes and methods necessary to implement native sign-in, directed by the developer, to
follow specific workflows to meet your application's user experience.</p>
<h1>Proposed solution</h1>
<p>This proposal outlines the design for a Kotlin Multiplatform library that provides the interfaces and methods necessary
to implement native sign-in flows using Okta's Direct Authentication APIs. By using this library, developers can build
fully customized and integrated sign-in experiences, including support for Multi-Factor Authentication (MFA), directly
within their native applications.</p>
<p>The initial implementation of this multiplatform library will focus on delivering support for Android as the first
target platform. This will allow us to build a robust foundation and gather feedback from the mobile development
community. Following the successful launch on Android, the library will be extended to support Java, enabling its use in
a wider range of desktop and server-side applications.</p>
<p>A hybrid approach that combines both imperative and reactive paradigms will be used. This will be achieved by exposing a
<code>StateFlow&lt;DirectAuthenticationState&gt;</code> alongside the imperative start function. This allows developers to choose the
pattern that best fits their platform's architecture and development style.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="detailed-design">Detailed design<a href="https://okta-client-architecture.netlify.app/proposals/003-direct-auth-kotlin#detailed-design" class="hash-link" aria-label="Direct link to Detailed design" title="Direct link to Detailed design">​</a></h2>
<p>The core of the library is designed around a central interface, DirectAuthenticationFlow, which is configured via a
DirectAuthenticationFlowBuilder. The authentication process is modeled as a state
machine, where each step returns a DirectAuthenticationState that informs the application of the next required action.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="directauthenticationflow-interface">DirectAuthenticationFlow Interface<a href="https://okta-client-architecture.netlify.app/proposals/003-direct-auth-kotlin#directauthenticationflow-interface" class="hash-link" aria-label="Direct link to DirectAuthenticationFlow Interface" title="Direct link to DirectAuthenticationFlow Interface">​</a></h3>
<p>The DirectAuthenticationFlow is the primary entry point for developers. It exposes a single start method to initiate the
authentication process. Once started, the flow returns a DirectAuthenticationState. Upon receiving a
DirectAuthenticationState.Authenticated state, the application is responsible for storing the returned Token object, for
example by using Credential.store() from the AuthFoundation library.</p>
<p>The authenticationState property is a StateFlow that emits updates to the current state of the authentication process.
This is ideal for applications that prefer a reactive programming model, allowing
them to observe state changes and update the UI accordingly.</p>
<div class="language-kotlin codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-kotlin codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * The primary interface for interacting with the Okta Direct Authentication API.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> *</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * This interface defines the contract for initiating an authentication flow. An instance</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * of this interface can be created using the `DirectAuthenticationFlow.create` builder.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">interface</span><span class="token plain"> DirectAuthenticationFlow </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * Indicates authentication flow state.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">val</span><span class="token plain"> authenticationState</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> StateFlow</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token plain">DirectAuthenticationState</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * Starts the direct authentication flow with an initial factor.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     *</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * This is the entry point for authenticating a user. Depending on the server's policy</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * and the provided factor, the flow may complete in a single step or require</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * additional steps, such as providing a secondary factor.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     *</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param loginHint A hint to the authorization server about the user's identity,</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     *  such as a username or email address.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param primaryFactor The initial authentication factor to use (e.g., a [PrimaryFactor.Password]).</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @return A [DirectAuthenticationState] of the flow after processing the initial factor</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">suspend</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">fun</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">start</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">loginHint</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> String</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> primaryFactor</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> PrimaryFactor</span><span class="token punctuation" style="color:#393A34">)</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> DirectAuthenticationState</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="directauthenticationflowbuilder">DirectAuthenticationFlowBuilder<a href="https://okta-client-architecture.netlify.app/proposals/003-direct-auth-kotlin#directauthenticationflowbuilder" class="hash-link" aria-label="Direct link to DirectAuthenticationFlowBuilder" title="Direct link to DirectAuthenticationFlowBuilder">​</a></h3>
<p>To create an instance of DirectAuthenticationFlow, developers use a builder that provides a fluent API for
configuration. The builder validates essential parameters such as issuerUrl and clientId at
creation time to prevent runtime errors. Upon creation, all configured properties are collected into a
DirectAuthenticationContext object, which encapsulates the configuration for the authentication
session, as described in the
Authentication Flow Context documentation. This context is then passed to the internal DirectAuthenticationFlow
implementation.</p>
<div class="language-kotlin codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-kotlin codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * A builder used to configure and create an instance of [DirectAuthenticationFlow].</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> *</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * This class provides a fluent API for setting the necessary parameters for the</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * Direct Authentication flow, such as the issuer URL, client ID, and scopes.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> *</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * An instance of this builder should be created using the [DirectAuthenticationFlow.create] factory method.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> DirectAuthenticationFlowBuilder </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">constructor</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * The intended user action for the authentication flow.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     *</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * This parameter indicates what the user is trying to achieve with the authentication request.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * For example, [DirectAuthenticationIntent.SIGN_IN] or [DirectAuthenticationIntent.RECOVERY].</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     *</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * Defaults to [DirectAuthenticationIntent.SIGN_IN].</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">var</span><span class="token plain"> directAuthenticationIntent </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> DirectAuthenticationIntent</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">SIGN_IN</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * The list of grant types the client application supports for the Direct Authentication flow.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     *</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * This list informs the authorization server about the authentication methods the client can handle,</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * such as passwords, OTP, or OOB (out-of-band) factors.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">var</span><span class="token plain"> supportedGrantType </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">listOf</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        GrantType</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">Password</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        GrantType</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">Oob</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        GrantType</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">Otp</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        GrantType</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">OobMfa</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        GrantType</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">OtpMfa</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        GrantType</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">WebAuthn</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        GrantType</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">WebAuthnMfa</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * A list of Authentication Context Class Reference values.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     *</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * This OIDC parameter requests that the user be authenticated with a particular level of assurance.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * The values are defined by the authorization server's policy.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">var</span><span class="token plain"> acrValues </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> listOf</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token plain">String</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * The HTTP client executor used to make network requests.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     *</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * This allows consumers to provide a custom implementation for making HTTP requests,</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * such as one that integrates with their existing networking stack or adds custom</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * headers for logging or analytics.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     *</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * Defaults to an instance of [KtorHttpExecutor] which uses Ktor's HTTP client.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">var</span><span class="token plain"> apiExecutor</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> ApiExecutor </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">KtorHttpExecutor</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * The logger used by the SDK to output diagnostic information.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     *</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * This allows consumers to integrate the SDK's logging with their application's</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * existing logging framework, such as Timber or a custom solution. It can also be</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * replaced with a mock implementation for testing purposes.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     *</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * Defaults to an instance of [AuthFoundationLoggerImpl] which logs to Android's Logcat.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">var</span><span class="token plain"> logger</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> AuthFoundationLogger </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">AuthFoundationLoggerImpl</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * The clock used for time-sensitive operations.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     *</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * This defaults to a clock that returns the current time in epoch seconds.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">var</span><span class="token plain"> clock</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> OidcClock </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> OidcClock </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> System</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">currentTimeMillis</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">/</span><span class="token plain"> </span><span class="token number" style="color:#36acaa">1000</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">companion</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">object</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         * Creates an instance of [DirectAuthenticationFlow] using the builder pattern.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         *</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         * @param issuerUrl The base URL of the Authorization Server. This is the issuer URI for the authorization server that will be used for the flow. For example: `https://dev-123456.okta.com`.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         * @param clientId The client ID of the application. This ID is obtained from the Okta developer console when you register your application.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         * @param scope The OAuth 2.0 scopes the application is requesting. Scopes are used to specify what access privileges are being requested for access tokens. For example: `openid`, `profile`, `email`, and `offline_access`.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         * @param buildAction A lambda with a [DirectAuthenticationFlowBuilder] receiver to configure the flow's parameters.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         *</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         * @return A [Result] containing the configured [DirectAuthenticationFlow] on success,</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         * or an exception on failure.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">fun</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">create</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            issuerUrl</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> String</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            clientId</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> String</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            scope</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> List</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token plain">String</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            buildAction</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">DirectAuthenticationFlowBuilder</span><span class="token punctuation" style="color:#393A34">.</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> Unit</span><span class="token punctuation" style="color:#393A34">)</span><span class="token operator" style="color:#393A34">?</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">null</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">)</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> Result</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token plain">DirectAuthenticationFlow</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> runCatching </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// TODO(https://oktainc.atlassian.net/browse/OKTA-10087 return the DirectAuthenticatorFlow implementation)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getOrElse</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> Result</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">failure</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">it</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="network-abstraction">Network abstraction<a href="https://okta-client-architecture.netlify.app/proposals/003-direct-auth-kotlin#network-abstraction" class="hash-link" aria-label="Direct link to Network abstraction" title="Direct link to Network abstraction">​</a></h3>
<p>The SDK's networking layer is designed to be flexible and extensible through a set of defined interfaces, ensuring it
can be adapted to various project requirements without being tied to a specific HTTP client library. This abstraction is
centered around the <code>ApiExecutor</code> interface.</p>
<ul>
<li>
<p><strong><code>ApiExecutor</code>:</strong> This is the core of the network abstraction. It defines a single <code>execute</code> method that takes an
<code>ApiRequest</code> and returns an <code>ApiResponse</code>. By providing a custom implementation of this interface, developers can
integrate the SDK with their application's existing networking stack, whether it's based on Ktor, OkHttp or another
library. This is particularly useful for sharing a single HTTP client instance, adding custom interceptors for
logging or analytics, or managing advanced configurations like certificate pinning.</p>
</li>
<li>
<p><strong><code>ApiRequest</code> Hierarchy:</strong> Instead of depending on a specific library's request builder, the SDK defines its own
request interfaces:</p>
<ul>
<li><code>ApiRequest</code>: The base interface defining common elements like the URL, HTTP method, headers, and query
parameters.</li>
<li><code>ApiFormRequest</code>: An extension for requests with <code>application/x-www-form-urlencoded</code> bodies, which is standard for
many OAuth 2.0 token exchanges. It includes a <code>formParameters()</code> method.</li>
<li><code>ApiRequestBody</code>: An extension for requests with a raw body, such as <code>application/json</code>, providing the body as a
<code>ByteArray</code>.</li>
</ul>
<p>The SDK internally constructs objects that implement these interfaces. The <code>ApiExecutor</code> implementation is then
responsible for translating these abstract request definitions into a concrete HTTP request for its underlying client
library.</p>
</li>
<li>
<p><strong><code>ApiResponse</code>:</strong> This interface standardizes the representation of an HTTP response, providing access to the status
code, headers, and raw body (<code>ByteArray</code>). This ensures that the SDK's internal logic can parse the response
consistently, regardless of which HTTP client is used to perform the request.</p>
</li>
</ul>
<p>By abstracting the entire request/response cycle, the <code>DirectAuthenticationFlow</code> remains completely decoupled from the
underlying networking implementation. This design enhances <strong>flexibility</strong>, allowing developers to use the tools they
are already familiar with, and dramatically improves <strong>testability</strong> by making it simple to provide a mock <code>ApiExecutor</code>
to simulate various network responses and error conditions during unit testing.</p>
<div class="language-kotlin codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-kotlin codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * An interface for executing API requests.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">interface</span><span class="token plain"> ApiExecutor </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * Executes the given API request.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     *</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param request The [ApiRequest] to execute.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @return The [ApiResponse] containing the response from the API.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">suspend</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">fun</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">execute</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">request</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> ApiRequest</span><span class="token punctuation" style="color:#393A34">)</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> ApiResponse</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * A specification for an HTTP API request to be executed by an [ApiExecutor].</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> *</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * This interface defines all the necessary components of a request, such as the</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * target URI, HTTP method, headers, and body.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">interface</span><span class="token plain"> ApiRequest </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * The HTTP method to be used for the request (e.g., GET, POST).</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     *</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @return The HTTP method as an [ApiRequestMethod].</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">fun</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">method</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> ApiRequestMethod</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * Returns a map of HTTP headers to be included with the request.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     *</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @return A map of header names to their corresponding values.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">fun</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">headers</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> Map</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token plain">String</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> List</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token plain">String</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * Returns the complete URL for the request, including the scheme, host, and path.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     *</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @return The request URL as a string.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">fun</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">url</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> String</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * Returns a map of URL query parameters to be appended to the request URI.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     *</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @return A map of query parameters, or null if there are none.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">fun</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">query</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> Map</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token plain">String</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> String</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token operator" style="color:#393A34">?</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">null</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * An extension of [ApiRequest] for requests that include form parameters in the body.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">interface</span><span class="token plain"> ApiFormRequest </span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> ApiRequest </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * The MIME type of the request body (e.g., `application/x-www-form-urlencoded`).</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     *</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * This is typically used for methods like POST or PUT to indicate the format of the body content.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">fun</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">contentType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> String</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * Returns a map of form parameters to be sent as the request body with a</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * `application/x-www-form-urlencoded` content type.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     *</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * This allows for multiple values per key, which will be encoded as repeated key-value pairs</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * in the request body (e.g., `key=value1&amp;key=value2`).</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     *</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @return A map of form parameters, or null if there are none.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">fun</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">formParameters</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> Map</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token plain">String</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> List</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token plain">String</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * An extension of [ApiRequest] for requests that include a body.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">interface</span><span class="token plain"> ApiRequestBody </span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> ApiRequest </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * The MIME type of the request body (e.g., `application/json`).</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     *</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * This is typically used for methods like POST or PUT to indicate the format of the body content.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">fun</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">contentType</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> String</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * Returns the body of the request as a byte array.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     *</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * This is typically used for methods like POST or PUT with content types like `application/json`.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     *</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @return The request body, or null if the request has no body.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">fun</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">body</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> ByteArray</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * Represents the response from an HTTP API request executed by an [ApiExecutor].</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> *</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * This interface provides access to all components of the response, including the</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * status code, headers, and body.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">interface</span><span class="token plain"> ApiResponse </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/** The HTTP status code from the server's response (e.g., 200 for OK). */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">val</span><span class="token plain"> statusCode</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> Int</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/** The raw response body as a byte array, or null if there is no body. */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">val</span><span class="token plain"> body</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> ByteArray</span><span class="token operator" style="color:#393A34">?</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/** A map of all response headers. */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">val</span><span class="token plain"> headers</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> Map</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token plain">String</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> List</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token plain">String</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/** The length of the response body in bytes, as reported by the `Content-Length` header. */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">val</span><span class="token plain"> contentLength</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> Long</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/** The MIME type of the response body, as reported by the `Content-Type` header. */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">val</span><span class="token plain"> contentType</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> String</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="factors">Factors<a href="https://okta-client-architecture.netlify.app/proposals/003-direct-auth-kotlin#factors" class="hash-link" aria-label="Direct link to Factors" title="Direct link to Factors">​</a></h3>
<p>Authentication factors are represented by a sealed interface hierarchy, which maps directly to the PrimaryFactor,
SecondaryFactor types in the reference API. This allows for a
type-safe representation of the different authentication methods.</p>
<div class="language-kotlin codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-kotlin codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * Represents an authentication factor that can be used as a secondary factor in an MFA flow.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * This excludes primary-only factors like passwords.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">sealed</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">interface</span><span class="token plain"> SecondaryFactor </span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> PrimaryFactor</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * Represents an authentication factor used in a Direct Authentication flow.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> *</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * Factors are categorized as either Primary or Secondary to support multi-stage</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * authentication workflows.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">sealed</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">interface</span><span class="token plain"> PrimaryFactor </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * A password factor, which can only be used as a primary factor.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     *</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param password The user's password.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">data</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">Password</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">val</span><span class="token plain"> password</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> String</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> PrimaryFactor</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * An OTP (One-Time Passcode) factor.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     *</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param passCode The one-time passcode provided by the user.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">data</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">Otp</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">val</span><span class="token plain"> passCode</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> String</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> SecondaryFactor</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * An OOB (Out-of-Band) factor, such as a push notification.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     *</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param channel The channel through which the OOB challenge should be sent.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">data</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">Oob</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">val</span><span class="token plain"> channel</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> OobChannel</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> SecondaryFactor</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * A WebAuthn factor, used for phishing-resistant authentication with hardware</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * authenticators or biometrics.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">data</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">object</span><span class="token plain"> WebAuthn </span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> SecondaryFactor</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="directauthenticationstate">DirectAuthenticationState<a href="https://okta-client-architecture.netlify.app/proposals/003-direct-auth-kotlin#directauthenticationstate" class="hash-link" aria-label="Direct link to DirectAuthenticationState" title="Direct link to DirectAuthenticationState">​</a></h3>
<p>The DirectAuthenticationState sealed class represents the various states of the authentication flow. Each state
corresponds to a specific step in the process, guiding the application on what action to take next.</p>
<div class="language-kotlin codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-kotlin codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * Represents the current state of a Direct Authentication flow.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> *</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * This sealed interface defines the possible outcomes after an authentication step. The flow can</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * either be complete, resulting in a [Authenticated] state, or require further user interaction,</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * such as in an [MfaRequired] state or [Continuation] state</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">sealed</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">interface</span><span class="token plain"> DirectAuthenticationState </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * The initial state of the authentication flow, before any action has been taken.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">data</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">object</span><span class="token plain"> Idle </span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> DirectAuthenticationState</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * The authentication flow has been canceled</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">data</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">object</span><span class="token plain"> Canceled </span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> DirectAuthenticationState</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * This state indicates that the authentication process is still pending and awaiting user action.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * Such as waiting for the user to complete an out-of-band (OOB) authentication step.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     *</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param timestamp The time in milliseconds when the authorization became pending.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> AuthorizationPending </span><span class="token keyword" style="color:#00009f">internal</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">constructor</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">val</span><span class="token plain"> timestamp</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> Long</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> DirectAuthenticationState</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * This state indicates that the user has been authenticated and tokens have been issued.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     *</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param token The [Token] containing the access, refresh, and ID tokens.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> Authenticated </span><span class="token keyword" style="color:#00009f">internal</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">constructor</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">val</span><span class="token plain"> token</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> Token</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> DirectAuthenticationState</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * The authentication flow requires an additional factor to complete.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     *</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * This state indicates that the user must perform a Multi-Factor Authentication (MFA)</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * step to proceed.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     *</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param context The [DirectAuthenticationContext] associated with this state.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param mfaContext The context required to continue the MFA flow.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> MfaRequired </span><span class="token keyword" style="color:#00009f">internal</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">constructor</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">val</span><span class="token plain"> context</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> DirectAuthenticationContext</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">internal</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">val</span><span class="token plain"> mfaContext</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> MfaContext</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> DirectAuthenticationState </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         * Continues the authentication flow with the selected MFA factor.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         *</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         * @param secondaryFactor The secondary [SecondaryFactor] to use for MFA (e.g., [PrimaryFactor.Otp], [PrimaryFactor.WebAuthn], etc.).</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         * @return The next [DirectAuthenticationState] in the flow.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">suspend</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">fun</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">resume</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">secondaryFactor</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> SecondaryFactor</span><span class="token punctuation" style="color:#393A34">)</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> DirectAuthenticationState </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token function" style="color:#d73a49">TODO</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string-literal singleline string" style="color:#e3116c">"Not yet implemented"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * Represents a state where an out-of-band (OOB) challenge has been initiated, and the</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * client must poll to determine the result.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     *</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * This state occurs after initiating an OOB flow, such as sending a push notification to</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * Okta Verify. The client should use the [poll] method to check if the user has</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * completed the authentication step.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     *</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param context The [DirectAuthenticationContext] associated with this state.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param pollContext The context required to poll for the OOB authentication result.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> OobAuthenticate </span><span class="token keyword" style="color:#00009f">internal</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">constructor</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">val</span><span class="token plain"> context</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> DirectAuthenticationContext</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">internal</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">val</span><span class="token plain"> pollContext</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> PollContext</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> DirectAuthenticationState </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         * Polls the token endpoint to check the status of the OOB authentication.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         *</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         * This method should be called periodically until the state transitions to [Authenticated]</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         * or an error occurs.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         *</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         * @return A [Result] containing the new [DirectAuthenticationState]. If the user has not</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         * yet completed the action, the result will be a success containing [AuthorizationPending].</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">suspend</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">fun</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">poll</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> DirectAuthenticationState </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token function" style="color:#d73a49">TODO</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string-literal singleline string" style="color:#e3116c">"Not yet implemented"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="directauthenticationerror">DirectAuthenticationError<a href="https://okta-client-architecture.netlify.app/proposals/003-direct-auth-kotlin#directauthenticationerror" class="hash-link" aria-label="Direct link to DirectAuthenticationError" title="Direct link to DirectAuthenticationError">​</a></h3>
<p>The <code>DirectAuthenticationError</code> sealed class represents various error states that can occur during the direct
authentication process. It provides detailed information about the nature of the error,
distinguishing between internal SDK errors, API-specific errors, and OAuth2-specific errors.</p>
<div class="language-kotlin codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-kotlin codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * Represents the various error states of direct authentication.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">sealed</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> DirectAuthenticationError </span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> DirectAuthenticationState </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * Represents an internal error that occurred during the direct authentication process.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * This is typically used for non-HTTP related errors caused by unexpected conditions such as network failures or JSON parsing issues.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     *</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param errorCode A string representing the specific error code.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param description An optional description of the error.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param throwable The [Throwable] that caused this error.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> InternalError </span><span class="token keyword" style="color:#00009f">internal</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">constructor</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">val</span><span class="token plain"> errorCode</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> String</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">val</span><span class="token plain"> description</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> String</span><span class="token operator" style="color:#393A34">?</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">null</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">val</span><span class="token plain"> throwable</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> Throwable</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">DirectAuthenticationError</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * Represents an HTTP error that occurred during the direct authentication process.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     *</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param error A string representing the error.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param httpStatusCode The [HttpStatusCode] associated with this error.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">sealed</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">HttpError</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">val</span><span class="token plain"> httpStatusCode</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> HttpStatusCode</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">DirectAuthenticationError</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         * An API-specific error that occurred during the direct authentication process.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         *</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         * https://developer.okta.com/docs/reference/api/error-codes/</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         *</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         * @param errorCode A string representing the specific error code.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         * @param errorSummary An optional summary of the error.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         * @param errorLink An optional link to more information about the error.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         * @param errorId An optional unique identifier for the error instance.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         * @param errorCauses An optional list of causes for the error.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         * @param httpStatusCode The [HttpStatusCode] associated with this error.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">ApiError</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">val</span><span class="token plain"> errorCode</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> String</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">val</span><span class="token plain"> errorSummary</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> String</span><span class="token operator" style="color:#393A34">?</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">val</span><span class="token plain"> errorLink</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> String</span><span class="token operator" style="color:#393A34">?</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">val</span><span class="token plain"> errorId</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> String</span><span class="token operator" style="color:#393A34">?</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">val</span><span class="token plain"> errorCauses</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> List</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token plain">String</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token operator" style="color:#393A34">?</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            httpStatusCode</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> HttpStatusCode</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">HttpError</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">httpStatusCode</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         * An OAuth2-specific error that occurred during the direct authentication process.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         *</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         * https://datatracker.ietf.org/doc/html/rfc6749#section-4.1.2.1</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         *</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         * @param error A string representing the error.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         * @param errorDescription An optional description of the error.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         * @param httpStatusCode The [HttpStatusCode] associated with this error.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">Oauth2Error</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">val</span><span class="token plain"> error</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> String</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            httpStatusCode</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> HttpStatusCode</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">val</span><span class="token plain"> errorDescription</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> String</span><span class="token operator" style="color:#393A34">?</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">HttpError</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">httpStatusCode</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="directauthenticationerrorcode">DirectAuthenticationErrorCode<a href="https://okta-client-architecture.netlify.app/proposals/003-direct-auth-kotlin#directauthenticationerrorcode" class="hash-link" aria-label="Direct link to DirectAuthenticationErrorCode" title="Direct link to DirectAuthenticationErrorCode">​</a></h3>
<p>The <code>DirectAuthenticationErrorCode</code> enum defines specific error codes used within the Direct Authentication flow. These
codes help in identifying the exact nature of an authentication error, including custom codes for MFA requirements and
standard OAuth2 error codes.</p>
<div class="language-kotlin codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-kotlin codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * Error codes specific to Direct Authentication.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">internal</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">enum</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">DirectAuthenticationErrorCode</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">val</span><span class="token plain"> code</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> String</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token function" style="color:#d73a49">MFA_REQUIRED</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string-literal singleline string" style="color:#e3116c">"mfa_required"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// Custom error code for MFA requirement</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token function" style="color:#d73a49">AUTHORIZATION_PENDING</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string-literal singleline string" style="color:#e3116c">"authorization_pending"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">// Custom error code for authorization pending</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// following are standard OAuth2 error codes https://datatracker.ietf.org/doc/html/rfc6749#section-4.1.2.1</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token function" style="color:#d73a49">ACCESS_DENIED</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string-literal singleline string" style="color:#e3116c">"access_denied"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token function" style="color:#d73a49">INVALID_GRANT</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string-literal singleline string" style="color:#e3116c">"invalid_grant"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token function" style="color:#d73a49">INVALID_REQUEST</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string-literal singleline string" style="color:#e3116c">"invalid_request"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token function" style="color:#d73a49">INVALID_SCOPE</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string-literal singleline string" style="color:#e3116c">"invalid_scope"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token function" style="color:#d73a49">INVALID_CLIENT</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string-literal singleline string" style="color:#e3116c">"invalid_client"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token function" style="color:#d73a49">UNAUTHORIZED_CLIENT</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string-literal singleline string" style="color:#e3116c">"unauthorized_client"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token function" style="color:#d73a49">UNSUPPORTED_GRANT_TYPE</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string-literal singleline string" style="color:#e3116c">"unsupported_grant_type"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token function" style="color:#d73a49">UNSUPPORTED_RESPONSE_TYPE</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string-literal singleline string" style="color:#e3116c">"unsupported_response_type"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token function" style="color:#d73a49">TEMPORARILY_UNAVAILABLE</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string-literal singleline string" style="color:#e3116c">"temporarily_unavailable"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token function" style="color:#d73a49">SERVER_ERROR</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string-literal singleline string" style="color:#e3116c">"server_error"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="continuation">Continuation<a href="https://okta-client-architecture.netlify.app/proposals/003-direct-auth-kotlin#continuation" class="hash-link" aria-label="Direct link to Continuation" title="Direct link to Continuation">​</a></h3>
<p>The Continuation sealed class is a specialized DirectAuthenticationState that represents points in the authentication
flow where the process is paused, awaiting further client-side action. This is
common in flows that require more than a simple data entry, such as interacting with platform APIs (like WebAuthn) or
handling out-of-band (OOB) verification. Each subclass of Continuation provides a
proceed function, which the application calls to continue the flow after the required action is completed.</p>
<div class="language-kotlin codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-kotlin codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * Represents a state in the Direct Authentication flow where further action is required to proceed.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> *</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * This is a special type of [DirectAuthenticationState] that indicates the flow is paused,</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * pending input from the user or another client-side process.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> *</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * @param context The [DirectAuthenticationContext] associated with this state.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * @param mfaContext An optional context for MFA flows, which may be present if the continuation</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> * is part of a multi-factor sequence.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic"> */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">sealed</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">Continuation</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">val</span><span class="token plain"> context</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> DirectAuthenticationContext</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">val</span><span class="token plain"> mfaContext</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> MfaContext</span><span class="token operator" style="color:#393A34">?</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">null</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> DirectAuthenticationState </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * A continuation that requires a WebAuthn (passkey) challenge to be completed.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     *</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * This state provides the necessary challenge data to interact with the platform's</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * WebAuthn/passkey APIs.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     *</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param challengeData The challenge data from the server, to be passed to the platform's WebAuthn API.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param context The [DirectAuthenticationContext] associated with this state.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param mfaContext An optional context for MFA flows.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> WebAuthn </span><span class="token keyword" style="color:#00009f">internal</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">constructor</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">val</span><span class="token plain"> challengeData</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> String</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        context</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> DirectAuthenticationContext</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        mfaContext</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> MfaContext</span><span class="token operator" style="color:#393A34">?</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">null</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">Continuation</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">context</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> mfaContext</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         * Proceeds with the authentication flow with the response from the WebAuthn/passkey ceremony.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         *</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         * @param authenticationResponseJson The JSON response from the platform's WebAuthn API.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         * @return The next [DirectAuthenticationState] in the flow.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">suspend</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">fun</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">proceed</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">authenticationResponseJson</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> String</span><span class="token punctuation" style="color:#393A34">)</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> Result</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token plain">DirectAuthenticationState</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token function" style="color:#d73a49">TODO</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string-literal singleline string" style="color:#e3116c">"Not yet implemented"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * A continuation that requires the user to enter a code, such as an OTP from an</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * authenticator app or a code sent via email/SMS.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     *</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param bindingContext Internal context required to continue the flow.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param context The [DirectAuthenticationContext] associated with this state.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param mfaContext An optional context for MFA flows.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> Prompt </span><span class="token keyword" style="color:#00009f">internal</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">constructor</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">val</span><span class="token plain"> bindingContext</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> BindingContext</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        context</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> DirectAuthenticationContext</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        mfaContext</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> MfaContext</span><span class="token operator" style="color:#393A34">?</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">null</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">Continuation</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">context</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> mfaContext</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         * Proceeds with the authentication flow with the user-provided code.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         *</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         * @param code The one-time code entered by the user.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         * @return The next [DirectAuthenticationState] in the flow.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">suspend</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">fun</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">proceed</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">code</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> String</span><span class="token punctuation" style="color:#393A34">)</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> Result</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token plain">DirectAuthenticationState</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token function" style="color:#d73a49">TODO</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string-literal singleline string" style="color:#e3116c">"Not yet implemented"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * A continuation for an out-of-band (OOB) flow, where authentication happens on another device.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     *</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * This state is common for flows like "Okta Verify Push" where the user approves a prompt</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * on their phone.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     *</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param bindingContext Internal context required to continue the flow.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param context The [DirectAuthenticationContext] associated with this state.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     * @param mfaContext An optional context for MFA flows.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">     */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">class</span><span class="token plain"> Transfer </span><span class="token keyword" style="color:#00009f">internal</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">constructor</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">val</span><span class="token plain"> bindingContext</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> BindingContext</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        context</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> DirectAuthenticationContext</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        mfaContext</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> MfaContext</span><span class="token operator" style="color:#393A34">?</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">null</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">Continuation</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">context</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> mfaContext</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         * A code that can be displayed to the user to link devices or verify the transaction.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">val</span><span class="token plain"> bindingCode </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> bindingContext</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">bindingCode</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token comment" style="color:#999988;font-style:italic">/**</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         * Proceeds with the authentication flow by polling the server to check the status of the</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         * out-of-band authentication.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         *</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         * @return The next [DirectAuthenticationState] in the flow, which will typically be</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         * [DirectAuthenticationState.Authenticated] once the user has approved the OOB prompt.</span><br></span><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">         */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">suspend</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">fun</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">proceed</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> Result</span><span class="token operator" style="color:#393A34">&lt;</span><span class="token plain">DirectAuthenticationState</span><span class="token operator" style="color:#393A34">&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token function" style="color:#d73a49">TODO</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string-literal singleline string" style="color:#e3116c">"Not yet implemented"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="example-usage">Example usage<a href="https://okta-client-architecture.netlify.app/proposals/003-direct-auth-kotlin#example-usage" class="hash-link" aria-label="Direct link to Example usage" title="Direct link to Example usage">​</a></h3>
<p>Here is a simplified example of how a developer might use the Direct Authentication SDK to implement a custom sign-in
flow in an Android application using a imperative style. This example assumes the existence of UI components to collect
user input
and display messages.</p>
<div class="language-kotlin codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-kotlin codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token comment" style="color:#999988;font-style:italic">// Create the DirectAuthenticationFlow instance using the builder</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">val</span><span class="token plain"> flow </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> DirectAuthenticationFlowBuilder</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">create</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    issuerUrl </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string-literal singleline string" style="color:#e3116c">"https://example.com"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    clientId </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string-literal singleline string" style="color:#e3116c">"client-id"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    scope </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">listOf</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string-literal singleline string" style="color:#e3116c">"openid"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token string-literal singleline string" style="color:#e3116c">"profile"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token string-literal singleline string" style="color:#e3116c">"email"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getOrThrow</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// Start the authentication flow with the user's login and password</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">flow</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">start</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    loginHint </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string-literal singleline string" style="color:#e3116c">"fake.user@okta.com"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    primaryFactor </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> PrimaryFactor</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">Password</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string-literal singleline string" style="color:#e3116c">"SuperSecretPassword"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">also</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> initialStatus </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// Recursively handle all intermediate steps until a Success status or exception thrown.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    runCatching </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">resolveAuthStatus</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">initialStatus</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">onSuccess</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> completedStatus </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token keyword" style="color:#00009f">val</span><span class="token plain"> token </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> completedStatus</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">token</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// Credential.store(token) // Store tokens securely</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// Proceed with authenticated actions</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">onFailure</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// Handle errors (e.g., network issues, invalid credentials)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token function" style="color:#d73a49">println</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string-literal singleline string" style="color:#e3116c">"Authentication failed: </span><span class="token string-literal singleline interpolation interpolation-punctuation punctuation" style="color:#393A34">${</span><span class="token string-literal singleline interpolation expression">it</span><span class="token string-literal singleline interpolation expression punctuation" style="color:#393A34">.</span><span class="token string-literal singleline interpolation expression">message</span><span class="token string-literal singleline interpolation interpolation-punctuation punctuation" style="color:#393A34">}</span><span class="token string-literal singleline string" style="color:#e3116c">"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// A tail-recursive function to handle the authentication flow until a terminal state is reached.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// Such as Authenticated, Canceled or DirectAuthenticationError.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// Recursively handles MFA requirements and continuations.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">tailrec</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">suspend</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">fun</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">resolveAuthStatus</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">authStatus</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> DirectAuthenticationState</span><span class="token punctuation" style="color:#393A34">)</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> DirectAuthenticationState </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">when</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">authStatus</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">is</span><span class="token plain"> DirectAuthenticationState</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">Authenticated</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">is</span><span class="token plain"> DirectAuthenticationState</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">Canceled</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">is</span><span class="token plain"> DirectAuthenticationError </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// Base case. Authenticated, Canceled or error</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            authStatus</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">is</span><span class="token plain"> DirectAuthenticationState</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">MfaRequired </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// MFA is required, handle the MFA context</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// Ask the user to choose a factor. Here we automatically choose an OTP factor for demonstration.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token function" style="color:#d73a49">resolveAuthStatus</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">authStatus</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">resume</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">PrimaryFactor</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">Otp</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string-literal singleline string" style="color:#e3116c">"123456"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">is</span><span class="token plain"> DirectAuthenticationState</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">OobAuthenticate </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// Prompt the user to complete an out-of-band action. For Okta Verify, show the bindingCode. Resume will poll the server for status.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token function" style="color:#d73a49">resolveAuthStatus</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">authStatus</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">poll</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">is</span><span class="token plain"> Continuation</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">Prompt </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// Prompt the user for a code. Here we automatically provide a code for demonstration.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token function" style="color:#d73a49">resolveAuthStatus</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">authStatus</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">proceed</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string-literal singleline string" style="color:#e3116c">"123456"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getOrThrow</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">is</span><span class="token plain"> Continuation</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">Transfer </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// Prompt the user to complete an out-of-band action. For Okta Verify, show the bindingCode. Resume will poll the server for status.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token function" style="color:#d73a49">resolveAuthStatus</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">authStatus</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">proceed</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getOrThrow</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">is</span><span class="token plain"> Continuation</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">WebAuthn </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// Invoke the platform's WebAuthn API with the challengeData. For demonstration, we simulate a WebAuthn response.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token function" style="color:#d73a49">resolveAuthStatus</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">authStatus</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">proceed</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string-literal singleline string" style="color:#e3116c">"authenticationResponseJson"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getOrThrow</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>Alternatively, developers can choose to use a reactive style by collecting the authenticationState flow. This approach
is well-suited for applications that leverage reactive programming paradigms, such as those using Jetpack Compose or
other state-driven UI frameworks. In this example, we launch a coroutine to collect state changes and handle them
accordingly.</p>
<div class="language-kotlin codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-kotlin codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token plain"> </span><span class="token keyword" style="color:#00009f">val</span><span class="token plain"> flow </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> DirectAuthenticationFlowBuilder</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">create</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    issuerUrl </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string-literal singleline string" style="color:#e3116c">"https://example.com"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    clientId </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string-literal singleline string" style="color:#e3116c">"client-id"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    scope </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">listOf</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string-literal singleline string" style="color:#e3116c">"openid"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token string-literal singleline string" style="color:#e3116c">"profile"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token string-literal singleline string" style="color:#e3116c">"email"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">getOrThrow</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// Launch a coroutine to collect state changes from the flow.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">val</span><span class="token plain"> job </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> launch </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    flow</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">authenticationState</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">collect</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token function" style="color:#d73a49">handleAuthStatus</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">it</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// Start the flow, which will emit the initial status to the collector.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">flow</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">start</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string-literal singleline string" style="color:#e3116c">"name"</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> PrimaryFactor</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">Password</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string-literal singleline string" style="color:#e3116c">"secret"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token comment" style="color:#999988;font-style:italic">// job.cancel()</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">private</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">suspend</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">fun</span><span class="token plain"> </span><span class="token function" style="color:#d73a49">handleAuthStatus</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">authStatus</span><span class="token operator" style="color:#393A34">:</span><span class="token plain"> DirectAuthenticationState</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">when</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">authStatus</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">is</span><span class="token plain"> DirectAuthenticationState</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">Authenticated </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// Authentication is complete. You can access the token here.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            authStatus</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">token</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">is</span><span class="token plain"> DirectAuthenticationState</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">MfaRequired </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// Ask the user to choose a factor. Here we automatically choose an OTP factor for demonstration.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            authStatus</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">resume</span><span class="token punctuation" style="color:#393A34">(</span><span class="token plain">PrimaryFactor</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">Otp</span><span class="token punctuation" style="color:#393A34">(</span><span class="token string-literal singleline string" style="color:#e3116c">"123456"</span><span class="token punctuation" style="color:#393A34">)</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">is</span><span class="token plain"> DirectAuthenticationState</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">OobAuthenticate </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            </span><span class="token comment" style="color:#999988;font-style:italic">// Prompt the user to complete an out-of-band action and continue. Resume will poll the server for status.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">            authStatus</span><span class="token punctuation" style="color:#393A34">.</span><span class="token function" style="color:#d73a49">poll</span><span class="token punctuation" style="color:#393A34">(</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token keyword" style="color:#00009f">else</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> </span><span class="token comment" style="color:#999988;font-style:italic">/* Handle other states like Idle, Canceled, AuthorizationPending, or Errors */</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">        </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<h4 class="anchor anchorWithStickyNavbar_LWe7" id="example-sequence-diagram">Example Sequence Diagram<a href="https://okta-client-architecture.netlify.app/proposals/003-direct-auth-kotlin#example-sequence-diagram" class="hash-link" aria-label="Direct link to Example Sequence Diagram" title="Direct link to Example Sequence Diagram">​</a></h4>
<p>The following sequence diagrams are simplified for clarity. In a real-world scenario, additional error handling,
logging, and edge cases would need to be considered. Handling of polling intervals is not shown for brevity.</p>
<h4 class="anchor anchorWithStickyNavbar_LWe7" id="sequence-push-oob-mfa-flow">Sequence Push OOB MFA flow<a href="https://okta-client-architecture.netlify.app/proposals/003-direct-auth-kotlin#sequence-push-oob-mfa-flow" class="hash-link" aria-label="Direct link to Sequence Push OOB MFA flow" title="Direct link to Sequence Push OOB MFA flow">​</a></h4>
<!-- -->
<h4 class="anchor anchorWithStickyNavbar_LWe7" id="sequence-otp-mfa-flow">Sequence OTP MFA flow<a href="https://okta-client-architecture.netlify.app/proposals/003-direct-auth-kotlin#sequence-otp-mfa-flow" class="hash-link" aria-label="Direct link to Sequence OTP MFA flow" title="Direct link to Sequence OTP MFA flow">​</a></h4>
<p>The following sequence diagram illustrates a multi-factor authentication flow where the user first authenticates with a
password and is then prompted for a second factor. In this example, the application provides a One-Time Passcode (OTP).</p>
<!-- -->
<h4 class="anchor anchorWithStickyNavbar_LWe7" id="sequence-okta-verify-push-with-number-challenge-flow">Sequence Okta Verify push with number challenge flow<a href="https://okta-client-architecture.netlify.app/proposals/003-direct-auth-kotlin#sequence-okta-verify-push-with-number-challenge-flow" class="hash-link" aria-label="Direct link to Sequence Okta Verify push with number challenge flow" title="Direct link to Sequence Okta Verify push with number challenge flow">​</a></h4>
<p>The following sequence diagram illustrates a multi-factor authentication flow where the user first authenticates with a
password and is then prompted for a second factor. In this example, the application provides an out-of-band (OOB)
verification method, such as Okta Verify Push with a binding code(number challenge). This flow initiates the second
factor by calling the /challenge endpoint, unlike the OTP example which calls /token directly. The /challenge endpoint
is optional and is used when the client needs the server to drive the next step, such as sending a push notification. If
the client can determine the next factor on its own (for example, by prompting the user for an OTP), it can bypass this
step and call /token directly with the factor details.</p>
<!-- -->
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="implications-on-adoption">Implications on adoption<a href="https://okta-client-architecture.netlify.app/proposals/003-direct-auth-kotlin#implications-on-adoption" class="hash-link" aria-label="Direct link to Implications on adoption" title="Direct link to Implications on adoption">​</a></h2>
<p>This library introduces a new, additive capability for building native authentication experiences. It does not introduce
any breaking changes to existing functionalities, such as browser-based redirect flows. Developers can continue to use
existing authentication methods without any impact. The primary implication for developers choosing to adopt the Direct
Authentication flow is that they assume full responsibility for building and maintaining the user interface for the
entire authentication process. This includes screens for username/password entry, multi-factor authentication (MFA)
challenges, and account recovery steps. While this provides complete control over the user experience and branding, it
requires a more significant development effort compared to redirect-based flows where the UI is hosted by Okta.</p>
<p>More information about the advantages and disadvantages of using this library can be found at the following:
<a href="https://developer.okta.com/docs/concepts/direct-authentication/" target="_blank" rel="noopener noreferrer">https://developer.okta.com/docs/concepts/direct-authentication/</a></p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="future-directions">Future directions<a href="https://okta-client-architecture.netlify.app/proposals/003-direct-auth-kotlin#future-directions" class="hash-link" aria-label="Direct link to Future directions" title="Direct link to Future directions">​</a></h2>
<p>The following are potential enhancements and directions for the Direct Authentication SDK after its initial release.</p>
<ul>
<li>
<p><strong>Multiplatform Expansion:</strong> The initial implementation will target Android. Future work could extend support to other
platforms, including JVM for server-side and desktop applications. Based on developer demand, this could be further
expanded to include JavaScript (for web clients) and native iOS/macOS targets.</p>
</li>
<li>
<p><strong><code>AuthFoundation</code> Evolution:</strong> Supporting a broader set of platforms will require evolving the underlying
<code>auth-foundation</code> library to be fully multiplatform. This may involve refactoring some of its core interfaces to be
more flexible and abstract away platform-specific dependencies, ensuring a consistent
and reusable architecture across all supported environments.</p>
</li>
<li>
<p><strong>New Authenticators:</strong> The SDK is designed to be extensible. As new authentication methods become available or are
prioritized by Okta, support for additional factors can be seamlessly integrated into the existing <code>Factor</code> and
<code>Continuation</code> models.</p>
</li>
<li>
<p><strong>Integration with <code>OAuth2Client</code>:</strong> To simplify configuration for developers already using the <code>auth-foundation</code>
library, the <code>DirectAuthenticationFlowBuilder</code> could be enhanced to accept an <code>OAuth2Client</code> instance. This would
allow the builder to automatically populate common parameters like <code>clientId</code>, <code>scope</code>, and <code>issuerUrl</code> from the
existing client, reducing boilerplate code and ensuring consistency across different authentication-related components
of an application.</p>
</li>
</ul>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="alternatives-considered">Alternatives considered<a href="https://okta-client-architecture.netlify.app/proposals/003-direct-auth-kotlin#alternatives-considered" class="hash-link" aria-label="Direct link to Alternatives considered" title="Direct link to Alternatives considered">​</a></h2>
<p>The design of <code>DirectAuthenticationFlow</code> intentionally combines elements from both imperative and reactive programming
paradigms to offer developers flexibility. Several alternative approaches were considered:</p>
<ul>
<li>
<p><strong>Purely Imperative (suspend functions only):</strong> An API could be designed using only <code>suspend</code> functions, where each
function call blocks (asynchronously) and returns the next state.</p>
<ul>
<li><em>Pros:</em> Simple to understand for developers familiar with sequential code. Follows a clear request-response
pattern.</li>
<li><em>Cons:</em> This model is less suitable for modern, state-driven UI frameworks (like Jetpack Compose or SwiftUI) which
are designed to react to streams of data. Managing UI updates would require more manual, imperative code from the
developer. It also makes handling background state changes (like from a polling operation) more complex to
propagate to the UI.</li>
</ul>
</li>
<li>
<p><strong>Purely Reactive (<code>StateFlow</code> only):</strong> The API could be designed to expose only a <code>StateFlow</code> and functions to submit
actions (e.g., <code>submitFactor(factor)</code>). The result of an action would only be observable through the flow.</p>
<ul>
<li><em>Pros:</em> Aligns perfectly with reactive UI patterns. All state changes are handled through a single, consistent
mechanism.</li>
<li><em>Cons:</em> This can make handling the result of a specific, one-off action more complex. For example, the result of
the initial <code>start</code> call (which might fail due to a simple configuration error) would be delivered asynchronously
through the flow, which can be unintuitive. It mixes immediate validation feedback with asynchronous state
transitions.</li>
</ul>
</li>
<li>
<p><strong>Chosen Hybrid Approach:</strong> The proposed design uses an imperative <code>start</code> function that returns an initial state
directly, providing immediate feedback. Subsequent state changes can then be observed through the
<code>authenticationState</code> <code>StateFlow</code>.</p>
<ul>
<li><em>Pros:</em> It offers the best of both worlds. The imperative <code>start</code> call is natural for initiating an action and
getting a direct result. The <code>StateFlow</code> is ideal for observing the subsequent, asynchronous state transitions in
a reactive way, fitting well with modern UI development.</li>
<li><em>Cons:</em> Developers need to be comfortable with both <code>suspend</code> functions and <code>Flow</code>, which adds a slight learning
curve compared to a single-paradigm approach.</li>
</ul>
</li>
</ul>
<p>By providing both an imperative entry point and a reactive state stream, the SDK empowers developers to choose the
pattern that best fits their application's architecture while promoting best practices for modern native development.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="alignment-with-reference-architecture">Alignment with Reference Architecture<a href="https://okta-client-architecture.netlify.app/proposals/003-direct-auth-kotlin#alignment-with-reference-architecture" class="hash-link" aria-label="Direct link to Alignment with Reference Architecture" title="Direct link to Alignment with Reference Architecture">​</a></h2>
<p>The KMP implementation, while heavily influenced by the original Apple (Swift) reference architecture, introduces
several key differences to provide a more idiomatic and type-safe experience for Kotlin developers. The core concepts
remain consistent, but the execution and developer interaction have been tailored to the strengths of the Kotlin
language and its ecosystem.</p>
<h4 class="anchor anchorWithStickyNavbar_LWe7" id="key-architectural-differences">Key Architectural Differences:<a href="https://okta-client-architecture.netlify.app/proposals/003-direct-auth-kotlin#key-architectural-differences" class="hash-link" aria-label="Direct link to Key Architectural Differences:" title="Direct link to Key Architectural Differences:">​</a></h4>
<table><thead><tr><th style="text-align:left">Feature</th><th style="text-align:left">Apple (Swift) Implementation (Reference)</th><th style="text-align:left">KMP (Kotlin) Implementation</th></tr></thead><tbody><tr><td style="text-align:left"><strong>State Machine &amp; Type Safety</strong></td><td style="text-align:left">A single <code>resume</code> function on the main <code>DirectAuthenticationFlow</code> object is used for all state transitions.</td><td style="text-align:left">The <code>resume</code> and <code>proceed</code> functions are moved into the specific state classes that require them (e.g., <code>MfaRequired</code>, <code>Continuation.WebAuthn</code>). This creates a more robust and type-safe state machine, guiding the developer to call only the appropriate action for a given state.</td></tr><tr><td style="text-align:left"><strong>Asynchronous Operations</strong></td><td style="text-align:left">Uses Swift's modern concurrency features (<code>async/await</code>) for handling asynchronous operations.</td><td style="text-align:left">Leverages Kotlin's native <code>suspend</code> functions and coroutines. This provides first-class support for structured concurrency, cancellation, and more readable, sequential-style asynchronous code.</td></tr><tr><td style="text-align:left"><strong>Reactive State Management</strong></td><td style="text-align:left">Employs a delegate pattern to communicate state changes back to the application.</td><td style="text-align:left">Uses <code>StateFlow</code> from Kotlin Coroutines to represent the authentication state as an observable, hot data stream. This is the idiomatic approach in modern Kotlin and integrates seamlessly with reactive UI frameworks like Jetpack Compose.</td></tr><tr><td style="text-align:left"><strong>Modeling of Factors &amp; States</strong></td><td style="text-align:left">Uses discriminated unions and type aliases to represent different factors and states.</td><td style="text-align:left">Utilizes Kotlin's <code>sealed</code> interfaces and classes for <code>PrimaryFactor</code>, <code>SecondaryFactor</code>, <code>DirectAuthenticationState</code>, and <code>Continuation</code>. This enables exhaustive <code>when</code> expressions, ensuring compile-time safety when handling different states and factors.</td></tr><tr><td style="text-align:left"><strong>Concept of <code>Continuation</code></strong></td><td style="text-align:left"><code>Continuation</code> is treated as a type of authentication factor.</td><td style="text-align:left"><code>Continuation</code> is modeled as a distinct <code>DirectAuthenticationState</code>. This clarifies that the flow is paused and awaiting an external action (like a WebAuthn ceremony), rather than requiring a new authentication factor.</td></tr><tr><td style="text-align:left"><strong>State Immutability</strong></td><td style="text-align:left">DirectAuthenticationFlow can be mutable, with properties updated as the flow progresses.</td><td style="text-align:left">States are modeled as immutable data classes. Each transition function (e.g., <code>resume</code>, <code>proceed</code>) returns a <em>new</em> state object, ensuring thread safety and predictable state management, which aligns with reactive principles.</td></tr></tbody></table>
<h4 class="anchor anchorWithStickyNavbar_LWe7" id="analysis-of-the-differences">Analysis of the differences<a href="https://okta-client-architecture.netlify.app/proposals/003-direct-auth-kotlin#analysis-of-the-differences" class="hash-link" aria-label="Direct link to Analysis of the differences" title="Direct link to Analysis of the differences">​</a></h4>
<p>The KMP (Kotlin) implementation of Okta's Direct Authentication is a Kotlin variation of the original Apple (Swift)
design. It embraces modern Kotlin features to offer a type-safe, thread-safe, and developer-friendly experience.</p>
<p>While the fundamental authentication flows and concepts are aligned, the KMP SDK is not a direct port. It has been
redesigned to be idiomatic for the Kotlin ecosystem, prioritizing:</p>
<ul>
<li><strong>Type Safety:</strong> The state machine design in the KMP version is inherently safer, reducing the possibility of runtime
errors by leveraging Kotlin's strong type system.</li>
<li><strong>Modern Asynchronicity:</strong> The use of coroutines and <code>suspend</code> functions aligns with current best practices in Kotlin
development, leading to cleaner and more manageable asynchronous code.</li>
<li><strong>Reactive Architecture:</strong> The adoption of <code>StateFlow</code> makes the KMP SDK a natural fit for modern, declarative UI
frameworks, simplifying state management for the developer.</li>
</ul>
<p>In essence, the KMP implementation takes the core principles of the Apple reference architecture and refines them to
follow Kotlin patterns, resulting in an SDK that feels native to the Kotlin language and provides a more streamlined and
secure development experience.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="in-depth-analysis-of-the-differences">In-depth analysis of the differences<a href="https://okta-client-architecture.netlify.app/proposals/003-direct-auth-kotlin#in-depth-analysis-of-the-differences" class="hash-link" aria-label="Direct link to In-depth analysis of the differences" title="Direct link to In-depth analysis of the differences">​</a></h3>
<p>Here is a detailed analysis of the differences between the OktaDirectAuth Apple (Swift) and KMP (Kotlin)
implementations, focusing on the networking layer and state mutability.</p>
<h4 class="anchor anchorWithStickyNavbar_LWe7" id="networking-layer">Networking Layer<a href="https://okta-client-architecture.netlify.app/proposals/003-direct-auth-kotlin#networking-layer" class="hash-link" aria-label="Direct link to Networking Layer" title="Direct link to Networking Layer">​</a></h4>
<p><strong>KMP (Kotlin) Implementation:</strong></p>
<p>The KMP implementation uses the <a href="https://ktor.io/" target="_blank" rel="noopener noreferrer">Ktor</a> client for handling HTTP requests. This is a modern,
multiplatform networking library from JetBrains that allows for a single networking implementation to be shared across
all target platforms.</p>
<ul>
<li><strong><code>KtorHttpExecutor</code></strong>: This class is responsible for executing API requests. It creates and configures a Ktor
<code>HttpClient</code> with plugins for timeouts, cookies, and caching. It's designed to be extensible, allowing developers to
provide their own pre-configured Ktor client if needed.</li>
<li><strong><code>DirectAuth...Request</code></strong>: These classes represent the individual API requests. They define the endpoint, HTTP
method, headers, and body of the request. This creates a clean separation between the definition of a request and its
execution.</li>
</ul>
<p><strong>Apple (Swift) Implementation:</strong></p>
<p>The Swift implementation abstracts the networking layer into a separate <code>AuthFoundation</code> framework. The <code>OktaDirectAuth</code>
module itself does not contain any code for making network calls.</p>
<ul>
<li><strong><code>APIRequest</code> protocol</strong>: Request objects, such as <code>OOBAuthenticateRequest</code>, conform to the <code>APIRequest</code> protocol
from the <code>AuthFoundation</code> framework. This protocol defines the properties of a request (URL, HTTP method, parameters,
etc.).</li>
<li><strong><code>AuthFoundation</code></strong>: This framework is responsible for taking the <code>APIRequest</code> object, executing the network call (
likely using <code>URLSession</code> internally), and decoding the response. This approach decouples the authentication logic
from the underlying networking implementation.</li>
</ul>
<p><strong>Comparison:</strong></p>
<table><thead><tr><th style="text-align:left">Feature</th><th style="text-align:left">KMP (Kotlin)</th><th style="text-align:left">Apple (Swift)</th></tr></thead><tbody><tr><td style="text-align:left"><strong>Library</strong></td><td style="text-align:left">Ktor</td><td style="text-align:left"><code>AuthFoundation</code> (custom framework)</td></tr><tr><td style="text-align:left"><strong>Abstraction</strong></td><td style="text-align:left">High (requests defined separately from execution)</td><td style="text-align:left">High (requests defined separately from execution)</td></tr><tr><td style="text-align:left"><strong>Platform</strong></td><td style="text-align:left">Multiplatform</td><td style="text-align:left">Apple-specific</td></tr><tr><td style="text-align:left"><strong>Extensibility</strong></td><td style="text-align:left">High (custom Ktor client and plugins)</td><td style="text-align:left">High (custom <code>APIRequest</code> conformances)</td></tr></tbody></table>
<h4 class="anchor anchorWithStickyNavbar_LWe7" id="state-mutability">State Mutability<a href="https://okta-client-architecture.netlify.app/proposals/003-direct-auth-kotlin#state-mutability" class="hash-link" aria-label="Direct link to State Mutability" title="Direct link to State Mutability">​</a></h4>
<p><strong>KMP (Kotlin) Implementation:</strong></p>
<p>The KMP implementation uses a reactive, unidirectional data flow model for state management, which is idiomatic for
modern Kotlin applications.</p>
<ul>
<li><strong><code>DirectAuthenticationState</code></strong>: This is a <code>sealed interface</code> that represents all possible states of the
authentication flow (e.g., <code>Idle</code>, <code>Authenticated</code>, <code>MfaRequired</code>). Using a sealed interface ensures that all possible
states are known at compile time.</li>
<li><strong><code>StateFlow</code></strong>: The <code>DirectAuthenticationFlowImpl</code> class uses a <code>MutableStateFlow</code> to hold the current
<code>DirectAuthenticationState</code>. It exposes this as an immutable <code>StateFlow</code> to clients. This allows clients (such as a UI
layer) to observe the state and react to changes automatically.</li>
<li><strong>Immutability</strong>: The <code>DirectAuthenticationState</code> objects are immutable. State transitions are handled by creating a
new state object and updating the <code>StateFlow</code>.</li>
</ul>
<p><strong>Apple (Swift) Implementation:</strong></p>
<p>The Swift implementation uses Swift's modern concurrency features, specifically <code>actor</code>s, to manage state in a
thread-safe manner.</p>
<ul>
<li><strong><code>Status</code> enum</strong>: Similar to the KMP implementation, the Swift code defines a <code>Status</code> <code>enum</code> to represent the
different states of the flow (e.g., <code>success</code>, <code>mfaRequired</code>).</li>
<li><strong><code>DirectAuthenticationFlow</code> actor</strong>: The main <code>DirectAuthenticationFlow</code> class is an <code>actor</code>. This ensures that all
access to its internal mutable state (such as the <code>_context</code> property which holds the current <code>Status</code>) is
synchronized and free of data races.</li>
<li><strong>State Updates</strong>: State is updated by calling <code>async</code> functions on the actor (e.g., <code>start</code>, <code>resume</code>). These
functions return the new <code>Status</code> upon completion. Additionally, a delegate protocol (
<code>DirectAuthenticationFlowDelegate</code>) is used to notify listeners of state changes.</li>
</ul>
<p><strong>Comparison:</strong></p>
<table><thead><tr><th style="text-align:left">Feature</th><th style="text-align:left">KMP (Kotlin)</th><th style="text-align:left">Apple (Swift)</th></tr></thead><tbody><tr><td style="text-align:left"><strong>State Representation</strong></td><td style="text-align:left"><code>sealed interface</code></td><td style="text-align:left"><code>enum</code></td></tr><tr><td style="text-align:left"><strong>State Management</strong></td><td style="text-align:left"><code>StateFlow</code> (reactive)</td><td style="text-align:left"><code>actor</code> (concurrency-safe)</td></tr><tr><td style="text-align:left"><strong>State Observation</strong></td><td style="text-align:left">Observing a <code>StateFlow</code></td><td style="text-align:left"><code>async</code>/<code>await</code> and delegate pattern</td></tr><tr><td style="text-align:left"><strong>Thread Safety</strong></td><td style="text-align:left">Guaranteed by <code>StateFlow</code> and coroutines</td><td style="text-align:left">Guaranteed by <code>actor</code></td></tr></tbody></table>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="acknowledgments">Acknowledgments<a href="https://okta-client-architecture.netlify.app/proposals/003-direct-auth-kotlin#acknowledgments" class="hash-link" aria-label="Direct link to Acknowledgments" title="Direct link to Acknowledgments">​</a></h2>
<ul>
<li>Alex Nachbaur, for her work on the okta-client-swift SDK, which served as a reference point for this design.</li>
<li>Rajdeep Nanua, for his work on the AuthFoundation library, which provides the foundational components for this SDK.</li>
</ul>]]></content:encoded>
            <category>Developer Experience</category>
        </item>
        <item>
            <title><![CDATA[Rename WebAuthenticationUI]]></title>
            <link>https://okta-client-architecture.netlify.app/proposals/002-webauthentication-rename</link>
            <guid>https://okta-client-architecture.netlify.app/proposals/002-webauthentication-rename</guid>
            <pubDate>Fri, 22 Aug 2025 22:35:21 GMT</pubDate>
            <description><![CDATA[Rename the WebAuthenticationUI framework library to more closely represent its intended purpose, and avoid confusion with WebAuthn authentication.]]></description>
            <content:encoded><![CDATA[<p>Rename the WebAuthenticationUI framework library to more closely represent its intended purpose, and avoid confusion with WebAuthn authentication.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="motivation">Motivation<a href="https://okta-client-architecture.netlify.app/proposals/002-webauthentication-rename#motivation" class="hash-link" aria-label="Direct link to Motivation" title="Direct link to Motivation">​</a></h2>
<p>The WebAuthenticationUI framework library was named during the initial development of the Client SDK, when only Swift and Kotlin were planned, and it was specifically targeting native application environments. It was also named to indicate its use as a UI-facing library. However, the <a href="https://okta-client-architecture.netlify.app/design/Foundation/#modular-library-ecosystem">SDK's modularization into logical layers</a> has been refined since then, and encompasses not only UI-facing environments, but integration into other more abstact application development frameworks.</p>
<p>Another motivation is the <a href="https://okta-client-architecture.netlify.app/proposals/0003-passkeys">upcoming support for Passkeys / WebAuthn</a>, which could result in developers confusing the WebAuthenticationUI library with WebAuthn.</p>
<p>Fundamentally, the names of these framework libraries should represent the technology or framework being used. Web-redirect sign-in ultimately will always be web-based, so naming the library after "WebAuthentication" is redundant.</p>
<p>As a result, a clearer name should be adopted to address these problems.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="design-objectives">Design objectives<a href="https://okta-client-architecture.netlify.app/proposals/002-webauthentication-rename#design-objectives" class="hash-link" aria-label="Direct link to Design objectives" title="Direct link to Design objectives">​</a></h2>
<ol>
<li>Select a new name that more clearly represents the developer's use-case.</li>
<li>Ensure the name can be consistently applied across all relevant environments.</li>
<li>Pave the way for Passkey/WebAuthn libraries.</li>
</ol>
<h1>Proposed solution</h1>
<p>The name this proposal recommends is: <strong>BrowserAuthentication</strong>. There are several reasons this name is chosen:</p>
<ul>
<li>This more specifically indicates that a browser itself will be used to enable user sign-in.</li>
<li>The <code>UI</code> suffix is dropped as it's redundant.</li>
<li>The name is generic enough that it can apply to both Apple/Android environments, native desktop applications, and potentially even Javascript environments (particularly within hybrid environments like React Native and Electron).</li>
</ul>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="detailed-design">Detailed design<a href="https://okta-client-architecture.netlify.app/proposals/002-webauthentication-rename#detailed-design" class="hash-link" aria-label="Direct link to Detailed design" title="Direct link to Detailed design">​</a></h2>
<p>The library targets / names should be changed from <code>WebAuthenticationUI</code> to <code>BrowserAuthentication</code>, with the <code>WebAuthentication</code> class also adopting the name <code>BrowserAuthentication</code>. Compilers should be able to disambiguate the namespace from the class name, but in languages where that isn't possible another name can be considered for the class.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="implications-on-adoption">Implications on adoption<a href="https://okta-client-architecture.netlify.app/proposals/002-webauthentication-rename#implications-on-adoption" class="hash-link" aria-label="Direct link to Implications on adoption" title="Direct link to Implications on adoption">​</a></h2>
<ul>
<li>This change would necessitate a major Semver version change, since this would represent a breaking API update (e.g. library/namespace names do not often support deprecation attributes in most languages).<!-- -->
<ul>
<li>In languages that support deprecation markers or type aliases, the class name itself can include these to simplify developer migration.</li>
</ul>
</li>
<li>Documentation and sample app updates would be necessary, to ensure the changes can be easily adopted by developers.</li>
<li>Package managers may need to be updated explicitly to communicate the deprecation of the old framework names to developers.</li>
</ul>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="alternatives-considered">Alternatives considered<a href="https://okta-client-architecture.netlify.app/proposals/002-webauthentication-rename#alternatives-considered" class="hash-link" aria-label="Direct link to Alternatives considered" title="Direct link to Alternatives considered">​</a></h2>
<p>Alternative names were considered, but within discussions among the Okta SDK engineers, this seemed to be the clearest and most platform-agnostic name that best communicated the library's intended purpose.</p>
<p>We also considered not making any changes, and leaving the name as-is.  But with our future roadmap plans for expanding support for the Client SDKs to more languages and platforms, this seems like the perfect time to rename this library: the scope is currently limited to two platforms (Swift and Kotlin), but over time this will become increasingly difficult to change.</p>]]></content:encoded>
            <category>Developer Experience</category>
        </item>
        <item>
            <title><![CDATA[Swift 6 Compatibility]]></title>
            <link>https://okta-client-architecture.netlify.app/proposals/001-swift6-compatibility</link>
            <guid>https://okta-client-architecture.netlify.app/proposals/001-swift6-compatibility</guid>
            <pubDate>Tue, 22 Apr 2025 22:05:11 GMT</pubDate>
            <description><![CDATA[Swift 6 introduces concurrency features that address runtime multithreading issues like data races and shared mutable state access. These changes significantly impact the Okta Client SDK, which has faced increased threading issues due to recent platform updates. To ensure stability and eliminate multithreading safety concerns, the SDK will adopt Swift 6 concurrency features and modernize its foundations.]]></description>
            <content:encoded><![CDATA[<p><a href="https://developer.apple.com/documentation/swift/adoptingswift6" target="_blank" rel="noopener noreferrer">Swift 6 introduces concurrency features</a> that address runtime multithreading issues like data races and shared mutable state access. These changes significantly impact the Okta Client SDK, which has faced increased threading issues due to recent platform updates. To ensure stability and eliminate multithreading safety concerns, the SDK will adopt Swift 6 concurrency features and modernize its foundations.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="motivation">Motivation<a href="https://okta-client-architecture.netlify.app/proposals/001-swift6-compatibility#motivation" class="hash-link" aria-label="Direct link to Motivation" title="Direct link to Motivation">​</a></h2>
<p>Swift has been incrementally introducing new concurrency features to the language which protects developers from a variety of hard-to-diagnose runtime errors. Many of these features were only available if a developer opted-in to those features. With the release of Swift 6, these optional features are enabled by default, which has a huge impact on developers.</p>
<p>More importantly, these language features make it significantly easier for developers to fix a variety of runtime problems, such as data races, preventing concurrent access to shared mutable state, and many other tricky edge-cases.</p>
<p>The Okta Client SDK has been stable for a long time, but recent updates to Swift and Apple's platforms caused rare threading issues to become much more common, negatively impacting users and introducing tricky race conditions. This is most prevalent in the race conditions around the default credential property.</p>
<p>This SDK was originally built around completion blocks, with support for Swift Concurrency <code>async</code> functions added as optional wrappers around those block-based APIs. This was because Swift Concurrency was fairly new at the time, and wasn't available to all supported versions of iOS. As a result, actor isolation context and task inheritance won't work with the SDK's current architecture.</p>
<p>To that end, the Okta Client SDK is being updated to fully support Swift 6 concurrency features, will harden its underlying foundations to leverage modern language capabilities, and to eliminate entire classes of runtime multithreading safety issues.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="design-objectives">Design objectives<a href="https://okta-client-architecture.netlify.app/proposals/001-swift6-compatibility#design-objectives" class="hash-link" aria-label="Direct link to Design objectives" title="Direct link to Design objectives">​</a></h2>
<ol>
<li>Adopt new Swift 6 language features</li>
<li>Maintain backwards compatibility with Swift 5.10</li>
<li>Enable future development to easily use new language fatures</li>
<li>Maintain an optimal Developer Experience for users of the SDK</li>
</ol>
<h1>Detailed design</h1>
<p>Ultimately Swift 6 language compatibility is a secondary concern to the concerns around data races and thread safety.  To support this, the SDK should:</p>
<ol>
<li>Update existing APIs and types to limit the surface area for mutable properties, changing common objects to value types, etc.</li>
<li>Update classes, structs, and other data types to conform to the Sendable protocol, explicitly identifying which objects can safely transit isolation contexts.</li>
<li>Adopt Swift Concurrency (e.g. async/await) and Task Inheritance to ensure proper actor isolation across context boundaries.</li>
<li>Adopt Actor types for highly-asynchronous components (e.g. Token Storage, <a title="AuthenticationFlows" href="https://okta-client-architecture.netlify.app/design/SDKGuidelines/OAuth2/AuthenticationFlows">Authentication Flows</a>, etc) to guarantee serialized access to shared state across the system.</li>
<li>Explicitly mark commonly-used properties and functions as nonisolated, implementing other thread safety features (like locks or semaphores) to prevent all APIs requiring async access.</li>
</ol>
<p>To support Swift 6 Complete Concurrency Checking, a lot of small changes needed to be made, such as marking types as conforming to Sendable, marking blocks as @Sendable, and updating other libraries to adapt to changes in interfaces defined in AuthFoundation.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="limit-mutable-api-surface-area">Limit mutable API surface area<a href="https://okta-client-architecture.netlify.app/proposals/001-swift6-compatibility#limit-mutable-api-surface-area" class="hash-link" aria-label="Direct link to Limit mutable API surface area" title="Direct link to Limit mutable API surface area">​</a></h2>
<p>Several sections of the API feature mutable state, or state spread across different properties. For example, <code>additionalHttpHeaders</code> on the OAuth2Client is defined as a <code>var</code>, or <a title="AuthenticationFlows" href="https://okta-client-architecture.netlify.app/design/SDKGuidelines/OAuth2/AuthenticationFlows">Authentication Flows</a> which contains a variety of mutable properties which change throughout the authentication flow (such as <code>authenticationUrl</code>, device authorization flow verification data, etc). Not only do these mutable properties pose problems for data race safety, but they highlight problems in consistency across a variety of APIs.</p>
<p>To limit the scope of these mutable properties, <a title="AuthenticationFlows" href="https://okta-client-architecture.netlify.app/design/SDKGuidelines/OAuth2/AuthenticationFlows">Authentication Flows</a> should all include a required <code>Context</code> type which can contain all developer-assigned customizations during an individual sign-in session, but can also contain any in-progress state that may change throughout the sign in operation.</p>
<div class="language-swift codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-swift codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">protocol</span><span class="token plain"> </span><span class="token class-name">AuthenticationFlow</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">associatedtype</span><span class="token plain"> </span><span class="token class-name">Context</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">AuthenticationContext</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">var</span><span class="token plain"> context</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">Context</span><span class="token operator" style="color:#393A34">?</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">get</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">var</span><span class="token plain"> isAuthenticating</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">Bool</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">get</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// Other common properties / functions</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">protocol</span><span class="token plain"> </span><span class="token class-name">AuthenticationContext</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">ProvidesOAuth2Parameters</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// Common properties / functions applicable to all context types</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">var</span><span class="token plain"> acrValues</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token class-name">String</span><span class="token punctuation" style="color:#393A34">]</span><span class="token operator" style="color:#393A34">?</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">get</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>Not only can this restrict the mutable values to <code>context</code> and <code>isAuthenticating</code>, but it also can simplify how authentication values can pass from flows and OAuth2Client configuration to their accompanying requests.</p>
<p>The <code>ProvidesOAuth2Parameters</code> protocol can be updated to be more expressive, allowing a flow and its context to supply information to the request based on the type of request being performed.</p>
<div class="language-swift codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-swift codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">protocol</span><span class="token plain"> </span><span class="token class-name">ProvidesOAuth2Parameters</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">func</span><span class="token plain"> </span><span class="token function-definition function" style="color:#d73a49">parameters</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> category</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">OAuth2APIRequestCategory</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token class-name">String</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> any </span><span class="token class-name">APIRequestArgument</span><span class="token punctuation" style="color:#393A34">]</span><span class="token operator" style="color:#393A34">?</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token keyword" style="color:#00009f">public</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">enum</span><span class="token plain"> </span><span class="token class-name">OAuth2APIRequestCategory</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">case</span><span class="token plain"> configuration</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">case</span><span class="token plain"> authorization</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">case</span><span class="token plain"> token</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">case</span><span class="token plain"> resource</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">case</span><span class="token plain"> other</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<p>For example, in the context for AuthorizationCodeFlow, this can be used to ensure PKCE data, state, and other values can be supplied at the correct stage of the flow.</p>
<div class="language-swift codeBlockContainer_Ckt0 theme-code-block" style="--prism-color:#393A34;--prism-background-color:#f6f8fa"><div class="codeBlockContent_QJqH"><pre tabindex="0" class="prism-code language-swift codeBlock_bY9V thin-scrollbar" style="color:#393A34;background-color:#f6f8fa"><code class="codeBlockLines_e6Vv"><span class="token-line" style="color:#393A34"><span class="token keyword" style="color:#00009f">func</span><span class="token plain"> </span><span class="token function-definition function" style="color:#d73a49">parameters</span><span class="token punctuation" style="color:#393A34">(</span><span class="token keyword" style="color:#00009f">for</span><span class="token plain"> category</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> </span><span class="token class-name">OAuth2APIRequestCategory</span><span class="token punctuation" style="color:#393A34">)</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">-&gt;</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token class-name">String</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"> any </span><span class="token class-name">APIRequestArgument</span><span class="token punctuation" style="color:#393A34">]</span><span class="token operator" style="color:#393A34">?</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// Allow the developer to supply arbitrary values</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token comment" style="color:#999988;font-style:italic">// to pass through to outgoing requests.</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">var</span><span class="token plain"> result </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> additionalParameters </span><span class="token operator" style="color:#393A34">??</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">[</span><span class="token punctuation" style="color:#393A34">:</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">switch</span><span class="token plain"> category </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">case</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">authorization</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    result</span><span class="token punctuation" style="color:#393A34">[</span><span class="token string-literal string" style="color:#e3116c">"state"</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> state</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    result</span><span class="token punctuation" style="color:#393A34">[</span><span class="token string-literal string" style="color:#e3116c">"response_type"</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> </span><span class="token string-literal string" style="color:#e3116c">"code"</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> nonce </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> nonce </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      result</span><span class="token punctuation" style="color:#393A34">[</span><span class="token string-literal string" style="color:#e3116c">"nonce"</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> nonce</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> pkce </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> pkce </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      result</span><span class="token punctuation" style="color:#393A34">[</span><span class="token string-literal string" style="color:#e3116c">"code_challenge"</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> pkce</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">codeChallenge</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      result</span><span class="token punctuation" style="color:#393A34">[</span><span class="token string-literal string" style="color:#e3116c">"code_challenge_method"</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> pkce</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">method</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain" style="display:inline-block"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// Other values ...</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">case</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">token</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">if</span><span class="token plain"> </span><span class="token keyword" style="color:#00009f">let</span><span class="token plain"> pkce </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> pkce </span><span class="token punctuation" style="color:#393A34">{</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">      result</span><span class="token punctuation" style="color:#393A34">[</span><span class="token string-literal string" style="color:#e3116c">"code_verifier"</span><span class="token punctuation" style="color:#393A34">]</span><span class="token plain"> </span><span class="token operator" style="color:#393A34">=</span><span class="token plain"> pkce</span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">codeVerifier</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">case</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">configuration</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">resource</span><span class="token punctuation" style="color:#393A34">,</span><span class="token plain"> </span><span class="token punctuation" style="color:#393A34">.</span><span class="token plain">other</span><span class="token punctuation" style="color:#393A34">:</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token comment" style="color:#999988;font-style:italic">// No special values needed in these requests</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">    </span><span class="token keyword" style="color:#00009f">break</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token punctuation" style="color:#393A34">}</span><span class="token plain"></span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><br></span><span class="token-line" style="color:#393A34"><span class="token plain">  </span><span class="token keyword" style="color:#00009f">return</span><span class="token plain"> result</span><br></span><span class="token-line" style="color:#393A34"><span class="token plain"></span><span class="token punctuation" style="color:#393A34">}</span><br></span></code></pre></div></div>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="adopt-sendable-in-classes--types">Adopt Sendable in classes / types<a href="https://okta-client-architecture.netlify.app/proposals/001-swift6-compatibility#adopt-sendable-in-classes--types" class="hash-link" aria-label="Direct link to Adopt Sendable in classes / types" title="Direct link to Adopt Sendable in classes / types">​</a></h2>
<p>In order to use strict concurrency checking, objects need to conform to <a href="https://developer.apple.com/documentation/swift/sendable" target="_blank" rel="noopener noreferrer">the Sendable protocol</a> (including blocks/closures which need to apply the @Sendable attribute) to indicate they're safe to be used or sent across isolation contexts. Adding conformances to this protocol automatically enfores a number of compilation checks which will require code changes to comply with these new checks.</p>
<p>Wherever possible, using immutable properties or value types to enable implicit conformance, but there will be times where more explicit handling of Sendable checks will be neccessary. In those cases, it may be necessary to utilize locks or semaphores where appropriate to ensure objects can be sendable.</p>
<div class="theme-admonition theme-admonition-warning admonition_xJq3 alert alert--warning"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 16 16"><path fill-rule="evenodd" d="M8.893 1.5c-.183-.31-.52-.5-.887-.5s-.703.19-.886.5L.138 13.499a.98.98 0 0 0 0 1.001c.193.31.53.501.886.501h13.964c.367 0 .704-.19.877-.5a1.03 1.03 0 0 0 .01-1.002L8.893 1.5zm.133 11.497H6.987v-2.003h2.039v2.003zm0-3.004H6.987V5.987h2.039v4.006z"></path></svg></span>warning</div><div class="admonitionContent_BuS1"><p>Overuse of locks or semaphores can introduce unneccessary overhead, or risk the introduction of deadlocks, so they should be used sparingly. If locks are used, special care must be taken to ensure deadlocks do not occur, and that their use is isolated.</p></div></div>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="use-asyncawait-and-tasks">Use <code>async/await</code> and Tasks<a href="https://okta-client-architecture.netlify.app/proposals/001-swift6-compatibility#use-asyncawait-and-tasks" class="hash-link" aria-label="Direct link to use-asyncawait-and-tasks" title="Direct link to use-asyncawait-and-tasks">​</a></h2>
<p>Much of Swift's new concurrency features center around async operations, as well as the use of Tasks. Unlike Grand Central Dispatch (GCD) and the use of blocks within Dispatch Queues, Tasks establish an inherited relationship between asynchronous operations which not only can pass along priority information, but can enable task cancellation that can propagate across multiple operations.</p>
<p>This will be a prerequisite for adopting any of these other concurrency features so this context can be maintained between operations.</p>
<p>To better understand how this will play out in the real world, consider the following example:</p>
<ol>
<li>A user clicks a "Sign In" button in their application, which triggers an event within the <code>@MainActor</code>.</li>
<li>The <code>WebAuthentication.shared</code> property is accessed which loads the <code>Okta.plist</code> configuration, implicitly creates an instance of the <code>WebAuthentication</code> class, and creates the appropriate <code>OAuth2Client</code> as well as the flows used for sign-in and -out.</li>
<li>The <code>start() async throws -&gt; Token</code> function is called, which performs a series of steps necessary to create an authorization URL.<!-- -->
<ol>
<li>The OAuth2Client performs a request to fetch the client's <code>/.well-known/openid-configuration</code> endpoint.</li>
<li>The authorize URL is fetched, PKCE data is generated, and a URL is formed.</li>
<li>A delegate function is called to allow the developer's application to alter the URL before being opened.</li>
<li>An instance of <code>ASWebAuthenticationSession</code> is initiated with the authorize URL, and is presented to the user.</li>
</ol>
</li>
<li>The browser session returns the resulting redirect URI, which the SDK consumes, validates the response data, and extracts the authorization code.</li>
<li>This code is sent to the <code>AuthorizationCodeFlow</code> instance within the <code>WebAuthentication</code> object, and is used against the <code>/token</code> endpoint to request a token.</li>
<li>In parallel to the token request, the <code>/keys</code> endpoint is fetched to proactively load the JWK keyset the authoriation server is using.</li>
<li>Once both request responses are received, the tokens are validated and returned to the developer.</li>
</ol>
<p>This workflow involves a number of asynchronous operations initiated by a user, many of which may be canceled for a variety of reasons. If completion blocks are used to trigger any of these steps, the information about task priority, the relationship between the tasks, and the cancellation of any of those operations is impossible to determine.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="use-actors-where-neccessary">Use Actors where neccessary<a href="https://okta-client-architecture.netlify.app/proposals/001-swift6-compatibility#use-actors-where-neccessary" class="hash-link" aria-label="Direct link to Use Actors where neccessary" title="Direct link to Use Actors where neccessary">​</a></h2>
<p>Actors are a relatively new capabiity within the Swift language. These are reference types, similar to classes, except there are several key differences that make them distinct from classes.</p>
<div class="theme-admonition theme-admonition-tip admonition_xJq3 alert alert--success"><div class="admonitionHeading_Gvgb"><span class="admonitionIcon_Rf37"><svg viewBox="0 0 12 16"><path fill-rule="evenodd" d="M6.5 0C3.48 0 1 2.19 1 5c0 .92.55 2.25 1 3 1.34 2.25 1.78 2.78 2 4v1h5v-1c.22-1.22.66-1.75 2-4 .45-.75 1-2.08 1-3 0-2.81-2.48-5-5.5-5zm3.64 7.48c-.25.44-.47.8-.67 1.11-.86 1.41-1.25 2.06-1.45 3.23-.02.05-.02.11-.02.17H5c0-.06 0-.13-.02-.17-.2-1.17-.59-1.83-1.45-3.23-.2-.31-.42-.67-.67-1.11C2.44 6.78 2 5.65 2 5c0-2.2 2.02-4 4.5-4 1.22 0 2.36.42 3.22 1.19C10.55 2.94 11 3.94 11 5c0 .66-.44 1.78-.86 2.48zM4 14h5c-.23 1.14-1.3 2-2.5 2s-2.27-.86-2.5-2z"></path></svg></span>tip</div><div class="admonitionContent_BuS1"><p><a href="https://docs.swift.org/swift-book/documentation/the-swift-programming-language/concurrency/#Actors" target="_blank" rel="noopener noreferrer">Swift Actors</a> and their nuances are too large of a topic to cover here, so it's important to review the relevant documentation.</p></div></div>
<p>Actors guarantee serial access to callers, ensuring that mutations are isolated and aren't susceptable to race conditions. This comes at the cost of requiring all accesses to their isolated members (from outside the actor itself, or its global context) to be asynchronous, including properties. This negatively affects the developer experience (DX), so actors should only be used within isolated areas that are seldom used directly by consumers of the SDK, and that could benefit from data race saftey.</p>
<p>The areas that should be focused on are:</p>
<ul>
<li>Token Storage / Credential subsystem</li>
<li>Authentication Flows</li>
<li>Async conveniences / internals</li>
</ul>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="token-storage">Token Storage<a href="https://okta-client-architecture.netlify.app/proposals/001-swift6-compatibility#token-storage" class="hash-link" aria-label="Direct link to Token Storage" title="Direct link to Token Storage">​</a></h3>
<p>Given that the main concerns that precipitated these updates are related to token storage, and handling of the <code>default</code> token, this is the area that should be given the most attention.</p>
<p>Since a number of classes and protocols interact to form the token storage system, it makes sense to ensure that these classes can easily coordinate with one-another without unneccessary async operations across isolation contexts. As a result, this area should share a common custom global context to ensure they all share the same <a href="https://developer.apple.com/documentation/swift/serialexecutor" target="_blank" rel="noopener noreferrer">serial executor</a>, and to simplify the way callers can coordinate with that isolation context.</p>
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="authentication-flows">Authentication Flows<a href="https://okta-client-architecture.netlify.app/proposals/001-swift6-compatibility#authentication-flows" class="hash-link" aria-label="Direct link to Authentication Flows" title="Direct link to Authentication Flows">​</a></h3>
<p><a title="AuthenticationFlows" href="https://okta-client-architecture.netlify.app/design/SDKGuidelines/OAuth2/AuthenticationFlows">Authentication Flows</a> are by their very nature asynchronous operations the user interacts with. Furthermore, the main access points (the <code>start</code> and <code>resume</code> functions) are already async functions. To simplify matters, the <a href="https://okta-client-architecture.netlify.app/api/foundation-authfoundation-public/interface/AuthenticationFlow">AuthenticationFlow</a> protocol can ensure only actors can conform to that protocol.</p>
<p>Any other property on authentication flows beyond <code>start</code> and <code>resume</code> should do their best to remain <code>nonisolated</code> either by being immutable properties referencing Sendable value types, or should utilize semaphores to ensure the <code>async</code> interactions with the actor's isolation context can be safely serialized to the caller.</p>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="optimize-developer-experience-wnonisolated-properties--functions">Optimize Developer Experience w/nonisolated properties &amp; functions<a href="https://okta-client-architecture.netlify.app/proposals/001-swift6-compatibility#optimize-developer-experience-wnonisolated-properties--functions" class="hash-link" aria-label="Direct link to Optimize Developer Experience w/nonisolated properties &amp; functions" title="Direct link to Optimize Developer Experience w/nonisolated properties &amp; functions">​</a></h2>
<p>As mentioned in the previous section, ensuring an optimal developer experience (DX) is important, and requiring all interactions with SDK APIs to be <code>async</code> would hurt the development experience and could even introduce additional bugs through improper use of these APIs by developers.</p>
<p>Therefore common patterns should be adopted to consistently, and safely, enable synchronous access to objects and classes, while maintaining thread safety. Additionally, interactions with delegates should either consistently dispatch to the <code>@MainActor</code>, or should safely inherit the caller's isolation context, to limit the number of unneccessary synchronizations across threads.</p>
<h1>Implications on adoption</h1>
<p>There are some risks in adopting Swift 6 which should be carefully avoided to reduce the negative impact on the developer experience, and to ensure quick adoption.</p>
<ul>
<li>Avoid leaking too many <code>async</code> operations to developers, preserving synchronous APIs wherever possible.</li>
<li>Provide <code>completion</code> wrappers for async operations for developers who haven't yet adopted Swift Concurrency, or who are using the SDK from synchronous contexts (e.g. SwiftUI action blocks).</li>
<li>Limit the use of actors to areas not commonly used directly by developers, or in areas that are already asynchronous (using <code>nonisolated</code> in areas that don't require complete async operations, like immutable properties or initializers).</li>
<li>Ensure task cancellation is supported, and that task priority inheritance works as expected.</li>
<li>Try to avoid crossing isolation contexts unneccessarily, inheriting actor contexts appropriately.</li>
</ul>
<h2 class="anchor anchorWithStickyNavbar_LWe7" id="future-directions">Future directions<a href="https://okta-client-architecture.netlify.app/proposals/001-swift6-compatibility#future-directions" class="hash-link" aria-label="Direct link to Future directions" title="Direct link to Future directions">​</a></h2>
<p>By using Actors and Swift 6 concurrency, this sets the stage to adopt new Swift features more easily in the future. This can also simplify tighter integration with other Apple frameworks like SwiftUI, to provide more developer conveniences and to simplify customer deployments.</p>]]></content:encoded>
            <category>Developer Experience</category>
        </item>
    </channel>
</rss>