Handling multi-factor authentication
Some institutions require multi-factor authentication (MFA) in order to complete requests, so it's a great idea to know what kind of MFA tokens you will need to handle.
Handle MFA with our Connect Widget
We strongly recommend you use our Connect Widget to handle link creation. Our widget automatically handles the entire link creation process, including all the MFA token scenarios (inputless, numeric, QR code, or text).
General flow
The general flow for MFA is:
- You make a POST request to the institution to retrieve some data or to create a link.
- Belvo sends a 428 Token Required response, detailing which MFA method is needed to complete the request.
- You prompt the user to input the required authentication token.
- You make a Complete PATCH request for the given resource with the link ID, session ID, and user-provided authentication token.
- Belvo sends a 201 Success message.
428 Response
Below you can see an annotated payload for a 428 Token Required response. For detailed information regarding the token_generation_data
object, please see the MFA Methods section.
[
{
"code": "token_required", // Response code
"message": "A MFA token is required by the institution to login", // Human-readable description of the response.
"session": "be7a15d5f0b84d8ea60f6c12cb2a7b32", // Session ID (required in your PATCH request).
"expiry": "720", // The duration in which the end user needs to provide a token, in seconds.
"link": "449e388c-812b-4798-8743-7d11efb6becf", // Link ID of the end-user (required in your PATCH request).
"token_generation_data": {
// Contains details on the MFA Method required (inputless, numeric, qr, text).
// Please see the relevant section
// below for detailed information.
},
"request_id": "b7a3a5b3a3a2b6aa28f4cc98d55cf1f1" // The ID of the request (used for debugging purposes).
}
]
expect_user_input
In the token_generation_data
object, we include a expect_user_input
parameter. When set to false
, this indicates that the user just needs to, for example:
- Scan a QR code to complete the authentication (similar to how you authenticate the Whatsapp desktop app).
- Confirm the login on another device (similar to password-less authentication)
MFA Methods
Inputless
The Inputless MFA method requires your user to generate an authentication token using their device and provide you with the generated token. The 428 Token Required response that you receive will have inputless
in the type
field. In your UI, just prompt your user to add their input token.
[
{
"code": "token_required",
"message": "A MFA token is required by the institution to login",
"session": "be7a15d5f0b84d8ea60f6c12cb2a7b32",
"expiry": "720",
"link": "449e388c-812b-4798-8743-7d11efb6becf",
"token_generation_data": {
"instructions": "Use your app or device to generate a token",
"type": "inputless", // <-- The MFA method is inputless.
"value": null, // <-- No value is passed.
"expects_user_input": true // <-- Indicates that the user needs to provide you data to complete the authentication.
},
"request_id": "b7a3a5b3a3a2b6aa28f4cc98d55cf1f1"
}
]
After you have received your end user's token, you make a PATCH request.
Numeric
The numeric MFA method requires that your end user inputs a code in their device in order to receive the authentication token. The code that they will need to input in their device is passed in the 428 Token Required response, where the type
field will be numeric
and the value
field will contain the code that the user needs to input in their application. In your UI, you can display this code to your user so that they can then enter it in their application.
Numeric code expiry
The numeric code included in the 428 response is valid for up to 30 or 60 seconds (depending on the institution). If your user provides their generated code after this time, the institution returns another 428 response with a new numeric code.
[
{
"code": "token_required",
"message": "A MFA token is required by the institution to login",
"session": "731b8a5ed45245b3a2bd595382016b5e",
"expiry": "60",
"link": "04134743-73f9-41c3-a6dd-06cee3fab627",
"token_generation_data": {
"instructions": "Use this code to generate the token",
"type": "numeric", // <-- The MFA method is numeric.
"value": "703837", // <-- The code to display to the user.
"expects_user_input": true // <-- Indicates that the user needs to provide you data to complete the authentication.
},
"request_id": "63cece2a9374b06495a16da5b2265793"
}
]
After you have received your end user's token, you make a PATCH request.
QR code
The QR Code MFA method requires that your end user scans a QR code in order to retrieve the authentication token.
The QR code that they will need to scan with their application is passed in the 428 Token Required response, The code that they will need to input in their device is passed in the 428 Token Required response, where the type
field will be qr
and the value
field will contain the BASE64 string representation of the QR Code. You can parse this string to generate the QR code and display it to your user in your UI.
QR code expiry
The QR code included in the 428 response is valid for up to 30 or 60 seconds (depending on the institution). If your user provides their generated code after this time, the institution returns another 428 response with a new QR code.
[
{
"code": "token_required",
"message": "A MFA token is required by the institution to login",
"session": "433142d512854cf6b10a3ccc08f3fa7d",
"expiry": "60",
"link": "66a5cf30-512d-4830-b616-7dd7d6ecf09f",
"token_generation_data": {
"instructions": "Scan this QR code to generate the token",
"type": "qr", // <-- The MFA method is a QR code.
"value": "...", // <-- BASE64 string to parse and generate QR code.
"expects_user_input": true // <-- Indicates that the user needs to provide you data to complete the authentication
},
"request_id": "ce05c19b323c1caae6445aff5d4229f8"
}
]
After you have received your end user's token, you make a PATCH request.
Text
The Text MFA method requires your user to answer a security question. The 428 Token Required response that you receive will have text
in the type
field. In your UI, just prompt your user to add answer their security question and use the provided string as the value of the token
parameter in your PATCH request.
[
{
"code": "token_required",
"message": "A MFA token is required by the institution to login",
"session": "be7a15d5f0b84d8ea60f6c12cb2a7b32",
"expiry": "720",
"link": "449e388c-812b-4798-8743-7d11efb6becf",
"token_generation_data": {
"instructions": "Answer the question to proceed",
"type": "text", // <-- The MFA method is an answer to a security question .
"value": "Where were you born?", // <-- Security question user needs to answer.
"expects_user_input": true // <-- Indicates that the user needs to provide you data to complete the authentication
},
"request_id": "b7a3a5b3a3a2b6aa28f4cc98d55cf1f1"
}
]
After you have received your end user's token, you make a PATCH request.
Send MFA token after a 428 response
When you are required to provide a token during the connection process, you will receive a 428 Token Required response and instructions on which MFA method is needed. After you have prompted the user to input their authentication token, you must send a PATCH request to the Resume endpoint of the resource you want to access.
For example:
curl -X PATCH \
https://api.belvo.co/api/links/ \
-H 'Content-Type: application/json' \
-H 'Host: api.belvo.co' \
-H 'cache-control: no-cache' \
-d '{
"session": "{sessionId}",
"link": "{linkId}",
"token": "{userToken}"
}' \
-u [Secret Key ID]:[Secret Key PASSWORD]
Where:
{sessionId}
is the value in thesession
field you receive in the 428 Token Required response.{linkId}
is the value in thelink
field you receive in the 428 Token Required response.{userToken}
is the authentication token (including an answer to a security question) that your user provides.
Send MFA token with the initial request
We do not recommend that you send the MFA token with your initial request. The token may expire before it is processed by the institution, resulting in avoidable error responses. Please see Send MFA token after 428 response or use our Connect Widget.
If you know that the institution will require an MFA token as part of the request, you can pass the token as a parameter to any of our endpoints that connect to the institution:
For example:
curl -X POST \
https://api.belvo.co/api/links/ \
-H 'Content-Type: application/json' \
-H 'Host: api.belvo.co' \
-H 'cache-control: no-cache' \
-d '{
"institution": "{institutionName}",
"username": "{userName}",
"password": "{userPassword}",
"token": "{userToken}"
}' \
-u [Secret Key ID]:[Secret Key PASSWORD]
Where:
{institutionName}
is the institution code your end user wants to connect to.{userName}
is the login username of your end user.{userPassword}
is the login password of your end user.{userToken}
is the authentication token that your end user provides.
We use the token when connecting to the institution and automatically handle the MFA process.
Updated about 2 months ago