logo

MFA Challenges

Multi-Factor Authentication (MFA)

This workflow section will go over how to handle syncs that require completing multi-factor authentication (MFA) in order to complete a sync. When a sync progresses, it may hit “challenges” before account data can be fetched. This indicates that the end user must answer additional security questions.
At this point, the /sync endpoint will return a   challenges  object. This object includes an   id   for the challenge itself (as well as the   connection_id   to which it refers). There is also an indication of whether or not the challenge is time-sensitive (in the  expires   fields).
The   challenges   object also provides information about the   type   of MFA questions that need to be answered, the  question   that needs to be answered, and if you   should_answer   it. If the challenges have a   type   of “image,” “choices,” or “image_choices,” then an additional field will appear with the options or image(s) you need to pass to your users. At this point, if you do not address the MFA challenges and leave the sync stuck at this stage, the   status   of the connection you’re syncing will be “challenges.” Below are some examples of the various types of MFA challenges.
An example “question” response body, which represents MFA questions with an answer that can by typed in by your users and passed through to us:
{
    "challenges": [
        {
            "connection_id": 4224865,
            "expires": null,
            "id": 1669462,
            "question": "Which company bought Jin Yang’s app \"Not Hotdog\"?",
            "should_answer": true,
            "type": "question",
        }
    ]
}
An example “choices” response body, where your end user must choose from a set of multiple choice options:
        {
            "challenges": [
                {
                    "connection_id": 4224865,
                    "choices": [
                        {"key": 0, "value": "1234", "category": null},
                        {"key": 1, "value": "42", "category": null},
                    ],
                    "expires": null,
                    "id": 1669464,
                    "question": "What is the ultimate answer?",
                    "should_answer": true,
                    "type": "choices",
                }
            ]
        }
Note: when answering “choices”, you must pass the choice index (starting at 0) or   key  . The answer should not be a string.
An example “image” response body, for MFA that involves an image you should present to your user:
 
    {
        "challenges": [
            {
                "connection_id": 4224865,
                "image": {
                    "html": "<img src=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAF8AAAArCAIAAACRncN1AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAABrSURBVGhD7dBBDQAgDAAxhOyJf2d4QMFOQZMq6Hlz2dgpdoqdYqfYKXaKnWKn2Cl2ip1ip9gpdoqdYqfYKXaKnWKn2Cl2ip1ip9gpdoqdYqfYKXaKnWKn2Cl2ip1ip9gpdoqdYqfYKXZ2cz+IzsQgTvoGnQAAAABJRU5ErkJggg==\" />",
                    "source": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAF8AAAArCAIAAACRncN1AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAABrSURBVGhD7dBBDQAgDAAxhOyJf2d4QMFOQZMq6Hlz2dgpdoqdYqfYKXaKnWKn2Cl2ip1ip9gpdoqdYqfYKXaKnWKn2Cl2ip1ip9gpdoqdYqfYKXaKnWKn2Cl2ip1ip9gpdoqdYqfYKXZ2cz+IzsQgTvoGnQAAAABJRU5ErkJggg=="
                },
                "expires": null,
                "id": 1669464,
                "question": "What's in the box?",
                "should_answer": true,
                "type": "image",
            }
        ]
    }
​
An example   image_choices   object, when your user has to select a specific image from a set of multiple options. Note this is an incomplete response body. This is to illustrate how the   image_choices   object will be presented:
"image_choices": [
    {
        "category": null,
        "html": "<img src=\"https://image.quovo.com/images/login_01.gif\">",
        "key": 0,
        "source": "https://image.quovo.com/images/login_01.gif",
        "value": 0
    },
    {
        "category": null,
        "html": "<img src=\"https://image.quovo.com/images/login_02.gif\">",
        "key": 1,
        "source": "https://image.quovo.com/images/login_02.gif",
        "value": 1
    },
... 
Note: when answering   image_choices  , you must pass the choice index (starting at 0) or   key  . The answer should not be a string.
From the   challenges   object, you can prompt your users to answer whichever questions they need to. Once your user has answered the question(s), make a POST /sync request and pass the answer(s) back through along with the   challenge_id   
curl -X POST \
    -H "Authorization: Bearer a724809d37d0a21b7e9257f45cee416f5aec61993ab4b09e" \
    -H "Content-Type: application/json" \
    -d '{"answers": [{"challenge_id": 1669462, "answer": "Periscope"}]}' \
    "https://api.quovo.com/v3/connections/141415/sync"

Checking Sync Progress

After you resolve the MFA challenges, you should continue to call GET /sync or watch your POST call to confirm the end user entered the correct information.