MFA Challenges

When to expect them and how to test in sandbox.

Overview

Some financial institutions (FIs) require users to complete an extra verification step before returning account data. This is called an MFA challenge.

When this happens, Aerosync pauses the data job, sets its status to pending_mfa, and emits a webhook so your system knows to prompt the user to complete the challenge.

📘

Important: MFA challenges are initiated by the user's bank, not by your
integration. You cannot predict whether a given bank will require one. Your
integration should always be built to handle it.


Two types of MFA in Aerosync

It helps to understand that MFA can appear in two different contexts:

ContextWhen it happensHow it's handled
Bank linkingDuring initial widget flow, if the bank requires itHandled inline; the widget prompts the user automatically. No action required from your backend.
Data jobsAfter bank linking, when running identity, balance, or transaction history jobsHandled via webhook + widget re-launch. This is what this guide covers.

The full pending_mfa flow

Step 1: Connect a bank with MFA capability

The user connects their bank through the Aerosync widget. For banks that may require MFA on data jobs, the widget handles any inline MFA challenge at link time automatically.

Once the widget closes and onSuccess fires, you receive a connectionId. Store this.

Step 2: Create a data job

Using the connectionId, create a data fetch job:

  • Identity: POST /v2/accounts/{connectionId}/identity/job
  • Balance: POST /v2/accounts/{connectionId}/balance/job
  • Transaction History: POST /v2/accounts/{connectionId}/transactions/job

Step 3: Detect pending_mfa

If the FI requires additional verification, the job status will move to pending_mfa.

You'll know this in one of two ways:

  • Webhook (recommended): You'll receive a webhook with a pending_mfa status. Set up webhook handling, see Handle Webhooks.
  • Direct poll (backup): Check the job status via
    GET /v2/accounts/{connectionId}/job/{job_id}. A jobStatus of Pending MFA means the challenge is waiting.

Step 4: Re-launch the widget with MFA parameters

Re-launch the Aerosync widget using the same method as initial bank linking, but with three additional parameters:

ParameterValue
handleMFAtrue
jobIdThe job ID returned when you created the data job
connectionIdThe connection ID from the original bank link

The widget will launch directly into the MFA challenge screen.

Example from Web SDK configs (refer to the widget integration guide for your specific SDK implementation).

let widgetRef = initAeroSyncWidget({
  elementId: "widget",
  iframeTitle: "Connect",
  environment: "sandbox",
  token: token,
  aeroPassUserUuid: aeroPassUserUuid,
  handleMFA: true,          // required
  jobId: jobId,             // required
  connectionId: connectionId, // required
  onSuccess: function (event) {
    console.log("MFA complete", event);
  },
  onError: function (event) {
    console.log("MFA failed", event);
  },
  onClose: function () {
    console.log("Widget closed");
  }
});

widgetRef.launch();

What a user sees

When Aerosync widget is launched with handleMFA, jobId and connectionId:

Widget redirects to MFA page to complete the challenge:

When user clicks on the continue button, Aerosync will initiate the process to verify the MFA challenge:

On successful verification, Aerosync will display the success page and on clicking the 'Continue' button will close the widget.

Step 5: User completes the challenge

The widget presents the MFA challenge to the user. Once they respond:

  • Success: You'll receive a completed webhook for the job. Proceed to retrieve your data.
  • Failure: You'll receive a failed webhook. The job will not complete.

Testing in sandbox

To test the full pending_mfa flow, use the Aerosync Bank (MFA Trigger) test institution. The flow runs in two phases:

Phase 1: Set up the bank connection

  1. Launch the Aerosync widget
  2. Search for and select Aerosync Bank (MFA Trigger)
  3. Log in with the following test credentials:
    • Username: mxuser
    • Password: challenge
  4. When prompted with the MFA challenge, enter correct as the answer
  5. The widget closes, store the connectionId from onSuccess

Phase 2: Trigger and handle pending_mfa

  1. Attempt any Aerosync data job (balance, identity, or transaction history) using that connectionId. The job will return a pending_mfa status and Aerosync will emit the pending_mfa webhook
  2. Re-launch the widget with handleMFA: true, jobId, and connectionId in the config
  3. The widget launches directly into the MFA challenge. Enter correct to complete it. The widget will close on success


Did this page help you?