The Nigerian fintech ecosystem runs heavily on open banking aggregators. Startups use platforms like Mono, Okra, and Stitch to verify income, retrieve bank statements, and initiate direct debit mandates. Because these platforms use OAuth 2.0 or proprietary variations of account linking, the security burden falls heavily on how the fintech application handles the redirect callbacks and stores the resulting consent tokens.

If your implementation of the OAuth flow is flawed, an attacker can link their own bank account to a victim's loan application, or worse, hijack the victim's bank connection to view their entire transaction history.

Map the full consent path

Our penetration test starts exactly where your application creates a link request. We follow the user journey through the provider's consent screen, the redirect callback handling, the temporary code-for-token exchange, data retrieval API calls, token refresh cycles, relinking prompts, and final revocation. We record the user identity, the provider account ID, the OAuth state value, the requested scope, the token owner in the database, and the final link state at every single step.

The test scope must explicitly name the aggregator provider, the environment (sandbox vs. live), the user roles, the data types handled, the callback URLs, the storage systems (e.g., Redis, PostgreSQL), and the backend services authorized to use the grant. Note: The aggregator's infrastructure itself stays outside our testing scope unless you hold written approval from them.

1. Consent token storage and transmission security

Consent tokens are equivalent to the user's banking password. We trace these tokens through your application logs, exception error records, Kafka message queues, database tables, database backups, support dashboard tools, and monitoring analytics (like Sentry or Datadog).

Tokens must stay completely out of URLs, browser `localStorage`, client HTTP responses, and plaintext logs. Storage access must be cryptographically limited to the exact microservice that needs the grant. We verify that tokens are encrypted at rest using AES-GCM or AWS KMS, and that developers cannot casually query the database to read a user's active token.

2. Consent initiation CSRF vulnerability (The Confused Deputy)

Cross-Site Request Forgery (CSRF) in account linking is catastrophic. We attempt to start a link from a malicious external site, reuse an expired request payload, change the target account reference, and forcibly replace an existing link.

The attack works like this: The attacker starts the linking process on their own account and receives the final callback URL containing the authorization `code`. Instead of visiting it, they trick a logged-in victim into clicking that callback URL. If the application does not validate the `state` parameter against the victim's active session, it will bind the attacker's bank account to the victim's profile.

The application must require a valid user session, cryptographically bind the initiation request to that specific session (via an anti-CSRF token in the `state` parameter), and require a clear manual action before overwriting a previously linked account.

3. State parameter validation in the OAuth callback

We deeply inspect the `state` parameter validation logic. We remove the parameter entirely, replace it with a random string, replay an old state value, and swap callback values between two active test users. A pass requires a strong, single-use, cryptographically secure state value strictly tied to the initiating session and the intended callback URI.

A failed state check must immediately halt the token exchange. It must log a security exception and leave any previously existing bank link untouched.

4. Scope of data access versus scope claimed

We compare your product's stated business purpose, the text on the user consent screen, the requested API scopes (e.g., `auth`, `transactions`, `identity`), the data actually stored in your database, and the API calls your backend makes to the aggregator.

A pass requires the absolute minimum scope necessary to support the stated feature. If you only need to verify a user's name matches their BVN, you must not request or store their 12-month transaction history. Calls outside the granted scope must fail on the provider side, but your application must also automatically purge any extra JSON fields returned by the aggregator that it does not strictly require for its business logic.

5. Token revocation and session termination

We test the end of the lifecycle. We click "Remove Account" in the UI, we sign out, we permanently delete the user account, and we attempt to replace an active grant with a new one. A pass requires the old token to immediately stop working. Scheduled background jobs must recognize the revocation and halt polling.

The application must issue an explicit revocation API call to the aggregator. If the aggregator's revocation API fails or times out, your system must not silently fail; it must create a visible retry path for the operations team or queue the revocation for automated retry. The user interface must immediately reflect the true disconnected provider state.

6. Handling Webhook spoofing for Account Updates

Aggregators often use webhooks to notify your application when a user's bank link expires, when new transactions are available, or when a user revokes consent directly from the bank's portal. We attack your webhook receiver endpoint by sending forged JSON payloads.

If your backend does not validate the webhook signature using the aggregator's secret key, we can send a fake webhook claiming a user's account was successfully linked to a fraudulent BVN, or force your system to disconnect a legitimate user by spoofing a `consent.revoked` event. We test signature validation, replay protection, and IP whitelisting on all webhook endpoints.

7. Bypassing biometric authorization prompts

When a user attempts to link an account, many high-security aggregators prompt the user to authorize the action using their bank app's biometric sensor (FaceID or Fingerprint). We heavily test the integration between the aggregator's web view and the native bank app.

If the aggregator uses an insecure deep-link callback to determine if the biometric check passed (e.g., `simpalabs://link-success?auth_token=12345`), we intercept this deep link. We use tools like Frida or Objection to bypass the local biometric prompt entirely, manually triggering the deep link intent. The aggregator assumes the user successfully scanned their face, when in reality, the attacker simply forced the success callback locally on the device. A secure architecture mandates that the biometric success signal must travel directly from the bank's servers to the aggregator's servers, completely bypassing the local mobile operating system's Deep Link router.

Evidence rule

Prove token ownership and revocation

A penetration test report must show the initiating user, the expected state, the callback result, the stored grant owner, the approved scope, and the revocation result. Secrets and live tokens must be heavily masked. Engineers need enough HTTP request and state evidence to reproduce the control failure in staging without exposing a live production token.

Share the open banking provider, the consent flow, the application roles, and the target launch date.

Book an Open Banking Security Audit

Frequently asked questions

What is the consent token in an open banking integration and why is it sensitive?

A consent token lets the application request data allowed by the user's grant (e.g., transaction history, BVN, identity). Its power depends on the provider, scope, and lifetime. You must store it as a highly encrypted secret, restrict internal access, and automatically revoke it when the user deletes their account.

What is a re-consent attack in open banking?

A re-consent attack occurs when an attacker forces a user's session to link to the attacker's bank account, or forces the attacker's session to link to a victim's bank account. This happens if the OAuth state parameter is missing or predictable.

How does account linking security differ from payment API security?

Account linking tests focus entirely on the OAuth 2.0 lifecycle: consent boundaries, callback binding, CSRF mitigation, token handling, data scope minimization, and revocation. Payment testing checks transaction state, settlement hashes, and replay attacks.

Related reading

Blog: Embedded finance security testing · Open banking API security Nigeria · OAuth security audit

Services: Penetration testing · API security