External MFA
To enhance the security of user interactions in online banking, it is often necessary to implement Multi-Factor Authentication (MFA) mechanisms. While Q2 provides several default options for multi-factor authentication, we also provide the ability to create an external MFA extension that can be seamlessly integrated into login, transaction authorization, and event-driven validation (Patrol).
Let’s take a look the flow of an External MFA extension.

The extension is loaded and your logic handles verification. When completed/successful, the front-end of your extension calls the back-end of your extension via
requestExtensionData
to generate and provide an External MFA token.The back-end of your extension generates a token and sets it with HQ.
HQ stores the token in session and responds back to the back-end of your extension.
If successful, your extension responds back to your front-end with the generated token.
The front-end of your extension passes the token to the UUX platform via the Tecton
verifyMFA
action.UUX takes the token and passes it back to HQ. This token is passed back to HQ in different ways depending on the UUX workflow MFA is being initiated on.
HQ verifies the token passed against the one set by your extension and will respond back to UUX to complete MFA.
Once UUX has completed the MFA workflow, it will respond back to your
verifyMFA
call with a success or failure response.
Integration Options
Standard Integration
Our standard integration allows you to create a custom MFA experience within the online banking platform using a server-side or client-side rendered Tecton extension. This can be as simple as a custom form or as complex as a full multi-step authentication process.
Note
For an walkthrough of creating a Standard External MFA extension, see our External MFA tutorial.
Redirect-Based Authentication
Redirection-based authentication allows your extension to securely redirect out for user authentication and redirect back into your extension for final handling. This method is commonly used with OAuth 2.0 and OpenID Connect providers using PAR (Pushed Authorization Requests), PKCE (Proof Key for Code Exchange), or other secure methods.
At its simplest, redirection-based authentication works like this:
When a user is prompted for MFA, we redirect them to an authorization endpoint:
The identity provider authenticates the user.
After successful authentication, the identity provider redirects back to your provided
redirect_uri
with an authorization code.The generated
verify.html
page in your extension captures the authorization code and sends it to your application server:tecton.connected.then(function () { const params = new URLSearchParams(window.location.search); tecton.sources.requestExtensionData({ route: 'token_handler', body: { code: params.get('code') } })...
Your application server exchanges this code for access and identity tokens:
async def token_handler(self): verify_code = self.request_body.get("code") payload = { "grant_type": "authorization_code", "code": verify_code, "redirect_uri": f"{os.path.join(self.base_assets_url, 'verify.html')}", "client_id": client_id, "client_secret": client_secret, } response = await q2_requests.post("https://idp.example.com/access_token", data=payload)
After validating the response, your extension sets a generated token with HQ and responds back to the front-end of your extension.
async def token_handler(self): ... # If successful validation token = uuid.uuid4().hex return await self.set_external_mfa_token(token)
The
verify.html
page passes the token to the UUX platform via the Tecton verifyMFA action to complete the workflow.
Creating a Redirection-Based Authentication Extension
$ q2 create_extension
New Extension Name: MyExternalMFA
What type of extension are you creating?
1) Online (default) <---------
2) SSO (Third Party Integration)
3) Ardent (API)
4) Q2Console (Backoffice)
5) Central (Legacy Backoffice)
6) Adapter
7) Audit Action
8) Custom Health Check
9) Message Bus
10) Caliper API Custom Endpoint
11) Base Extension
Please make a selection and press Return [1]: 1
Select type of Online extension to generate
1) Server Side Rendered (Default) <---------
2) Client Side Rendered
Please make a selection and press Return: 1
Select type of Online integration to generate
1) Authenticated (Default)
2) Unauthenticated
3) External MFA <---------
Please make a selection and press Return [1]: 3
Select type of MFA integration to generate
1) Standard (Default)
2) Redirect-Based Authentication <---------
Please make a selection and press Return [1]: 2
This will generate a new extension with the necessary files and structure to implement redirection-based authentication.
Pre-authentication Access
One important thing to note for External MFA extensions is that when rendered in the authentication flow, the session is not yet fully authenticated. This means that WedgeOnlineBanking calls are not available to your extension and you will instead need to rely on Q2API.
DBObjects can conditionally switch between WedgeOnlineBanking and Q2API based on the authentication state, but in the event you need to determine whether to use WedgeOnlineBanking or Q2API, you can check the is_authenticated
attribute of your extension.
from q2_sdk.hq.hq_api.wedge_online_banking import AcceptDisclaimer
from q2_sdk.hq.hq_api.q2_api import DisclaimerFormMarkAsAccepted
async def disclaimer_example_method(self):
if self.is_authenticated:
# Use WedgeOnlineBanking
params_obj = AcceptDisclaimer.ParamsObj(
self.logger,
hq_credentials=self.hq_credentials,
disclaimer_data_id=1234
)
response = await AcceptDisclaimer.execute(params_obj)
else:
# Use Q2API
params_obj = DisclaimerFormMarkAsAccepted.ParamsObj(
self.logger,
user_id=22
disclaimer_form_data_id=1234
)
response = await AcceptDisclaimer.execute(params_obj)
return response
For more information on the difference between WedgeOnlineBanking and Q2API, please visit our HQ API documentation.
Contextual MFA Information
When creating an External MFA extension, you may have a need for contextual information about the MFA request. This information is available on the self.mfa_info
object in your extension.
The self.mfa_info
object can contain the following attributes depending on the workflow in which MFA is being initiated:
mfa_context
- The workflow context in which MFA is being initiated.transaction_ids
- A list of transaction IDs associated with the MFA request. Available when the MFA context is transaction authentication.audit_action_id
- The ID of the audit action associated with the MFA request. Available when the MFA context is event-driven validation.audit_action_name
- The name of the audit action associated with the MFA request. Available when the MFA context is event-driven validation.registration_value
- Current user registration value for the MFA provider. Present if registration value is required and present for the user in the Q2_MFARegistration table.sso_identifier
- Present if user has an SSOIdentifier in the Q2_SSOUserLogon table.