# The Public FxA State Machine The public FxA state machine tracks a user's authentication state as they perform operations on their account. The state machine, its states, and its events are visible to the consumer applications. Applications generally track the state and update the UI based on it, for example providing a login button for the `Disconnected` state and link to the FxA account management page for the `Connected` state. The public state machine events correspond to user actions, for example clicking the login button or completing the OAuth flow. The public state machine is non-deterministic -- from a given state and event, there are multiple possibilities for the next state. Usually there are two possible transitions: one for a successful operation and one for a failed one. For example, when completing an oauth flow, if the operation is successful the state machine transitions to the `Connected` state, while if it fails it stays in the `Authenticating` state. Here is an overview containing some of the states and transitions: ```mermaid graph LR; Disconnected --> |"BeginOAuthFlow(Success)"| Authenticating Disconnected --> |"BeginOAuthFlow(Failure)"| Disconnected Disconnected --> |"BeginPairingFlow(Success)"| Authenticating Disconnected --> |"BeginPairingFlow(Failure)"| Disconnected Authenticating --> |"CompleteOAuthFlow(Success)"| Connected Authenticating --> |"CompleteOAuthFlow(Failure)"| Authenticating Authenticating --> |"CancelOAuthFlow"| Disconnected Connected --> |"Disconnect"| Disconnected classDef default fill:#0af, color:black, stroke:black ``` # The Internal State Machines For each public state, we also define an internal state machine that represents the process of transitioning out of that state. Internal state machine states correspond to `FirefoxAccount` method calls and events correspond to call results. Unlike the public state machine, the internal state machines are deterministic meaning that each `(state, event)` pair always results in the same next state. There are two terminal states for the internal state machines: - `Complete(new_state)`: Complete the process and transition the public state machine to a new state - `Cancel`: Cancel the process and don't change the current public state. Here are some example internal state machines: ## Disconnected ```mermaid graph TD; Authenticating["Complete(Authenticating)"]:::terminal BeginOAuthFlow --> |BeginOAuthFlowSuccess| Authenticating BeginPairingFlow --> |BeginPairingFlowSuccess| Authenticating BeginOAuthFlow --> |Error| Cancel:::terminal BeginPairingFlow --> |Error| Cancel:::terminal classDef default fill:#0af, color:black, stroke:black classDef terminal fill:#FC766A, stroke: black; ``` ## Authenticating ```mermaid graph TD; Connected["Complete(Connected)"]:::terminal CompleteOAuthFlow --> |CompleteOAuthFlowSuccess| InitializeDevice CompleteOAuthFlow --> |Error| Cancel:::terminal InitializeDevice --> |InitializeDeviceSuccess| Connected InitializeDevice --> |Error| Cancel:::terminal classDef default fill:#0af, color:black, stroke:black classDef terminal fill:#FC766A, stroke: black; ``` ## Uninitialized This is the initial state for the public state machine (not shown in the diagram above). ```mermaid graph TD; Disconnected["Complete(Disconnected)"]:::terminal Connected["Complete(Connected)"]:::terminal AuthIssues["Complete(AuthIssues)"]:::terminal GetAuthState --> |"GetAuthStateSuccess(Disconnected)"| Disconnected:::terminal GetAuthState --> |"GetAuthStateSuccess(AuthIssues)"| AuthIssues:::terminal GetAuthState --> |"GetAuthStateSuccess(Connected)"| EnsureCapabilities EnsureCapabilities --> |EnsureCapabilitiesSuccess| Connected:::terminal EnsureCapabilities --> |Error| AuthIssues:::terminal classDef default fill:#0af, color:black, stroke:black classDef terminal fill:#FC766A, stroke: black; ```