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 Multi-Factor Authentication (MFA)
/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.
{ "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.
/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 Checking Sync Progress
/sync
or watch your POST call to confirm the end user entered the correct information.