OAuth Guide

Configure Link to connect to institutions via OAuth

Introduction to OAuth

Some institutions use an OAuth authentication flow, in which Plaid Link redirects the end user to their bank's website or mobile app to authenticate. While the use of OAuth is most common in Europe, a number of U.S. banks are beginning to adopt OAuth flows, rather than the Plaid-hosted experience in Link. This means that the Plaid Link flow will include a redirect where the user is brought to the bank's site or app to authenticate before returning to Plaid Link.

When to use OAuth flows

All developers should implement support for OAuth flows in their integrations. OAuth flows are commonly used by institutions in Europe. If your app only supports institutions outside Europe, it is still strongly recommended that you implement OAuth support as soon as possible, as several large US financial institutions are moving to OAuth-based flows.

All OAuth flows are backwards-compatible with non-OAuth flows, as well as with advanced Link flows such as Returning User Experience, Instant Match, and micro-deposit based verification. You can safely implement OAuth at any time without impacting non-OAuth institutions.

Because OAuth support requires client-side changes, we recommend implementing OAuth support even before you've been enabled for OAuth, especially if integrating with mobile SDKs, in order to allow sufficient time for app approval and distribution.

For a full list of Plaid’s integrations that use OAuth, you can call the /institutions/get endpoint with your desired country_codes and the oauth option set to true. The response for all institutions also includes an oauth field, which indicates whether or not Plaid uses OAuth to authenticate users for that institution.

Some institutions are in the process of converting from non-OAuth integrations to OAuth-based integrations. These institutions will have multiple records available to institutions endpoints, with one representing the OAuth version of the institution and one representing the non-OAuth version.

Overview of OAuth implementation

Supporting OAuth requires several steps. These are are outlined at a high level below.

Required OAuth implementation steps
  1. Complete your application profile: Your application profile, which can be configured in the Plaid Dashboard, is used to populate screens in the OAuth flow. Some institutions in the US require that this application profile be completed before OAuth can be enabled. For more information, see application profile.

  2. Make sure you have implemented Link tokens: OAuth requires the use of Link tokens. If you are using a legacy implementation with public keys rather than Link tokens, see the Link token migration guide.

  3. Configure your redirect URI: Your redirect URI will need to be added to Plaid's allowlist. Additional configuration is also required for mobile SDKs. See Redirect URI configuration.

  4. Provide your redirect URI to /link/token/create: When creating a Link token, you will need to provide your redirect URI (or Android package name). See Plaid API configuration.

  5. Handle a second Link initialization: In most cases, you will need to implement logic that launches Link a second time after the user completes the OAuth flow. The exact details of this implementation will vary by client platform. See Client-side configuration and Persisting user state when re-initializing Link. Make sure to implement this logic everywhere Link is initialized, including update mode flows.

  6. Wait for approval: Once you have completed the steps above, and already have (or have requested) Production access, Plaid will contact you to let you know when your account has been enabled for OAuth in Production. Once you have been approved, then any users linking new Items in your app will automatically be routed through an OAuth Link flow at any institution where OAuth flows are live and currently available to you.

  7. (If applicable) Migrate existing Items: If you are an Plaid existing developer and Plaid has informed you that you are required to implement OAuth for a given institution, you will also have received an OAuth Migration Guide via email from Plaid. Refer to the guide for detailed instructions on migrating existing Items.

Recommended, optional OAuth implementation steps
  1. Listen for consent expiration webhooks: Some institutions require users to periodically re-affirm their consent to avoid Item expiration. If an Item is about to expire, Plaid will fire a PENDING_EXPIRATION webhook. You can refresh a user's consent via update mode. For more information, see Refreshing consent.

  2. Handle consent revocation: OAuth institutions often allow users to revoke access to all accounts or to specific accounts. If an end user revokes access to a linked account, you can give them the option to restore their account using update mode or to delete their data from your app. For more information, see Managing consent revocation.

  3. Handle Link events: OAuth flows have a different sequence of Link events than non-OAuth flows. If you plan to track Link events to measure conversion or other metrics, you may need to handle these events differently for OAuth. See Link callbacks for OAuth.

  4. (Europe only) Enable QR Code authentication: Some institutions in Europe support QR Code-based authentication flows. To enable these flows, you will need to contact your account manager. For more information, see QR Code authentication.

Application profile

Before configuring OAuth, be sure to complete your application profile, which can be found in the Plaid Dashboard, under Team Settings->Application. The information provided here will be shown on OAuth flows and helps end users understand what your app is and why it is requesting access, which can improve conversion. In addition, some US institutions require the institution profile to be completed and will not allow apps with an empty profile to access their OAuth implementations.

Redirect URI configuration

Redirect URIs and desktop web

OAuth flows will still work on desktop web even if you don't set up a redirect URI. However, implementing OAuth flows in this way is strongly discouraged, because the resulting OAuth flow will not work for users on mobile web. For a robust integration, specify a redirect URI.

In order for Plaid to return control back to your application after a user completes the bank's OAuth flow, you'll need to create a redirect URI. The redirect URI will be the location from which Link will be re-launched to complete the OAuth flow, and is typically a dedicated page for launching Link. https://domainname.com/oauth-page is an example of a typical redirect URI.

On the page pointed to by the redirect URI, you will need to initialize a second instance of Link; the client-side configuration section details exactly how Link should be configured on that page. Once you have determined what URI you will be using, add it to the configuration settings on the developer dashboard, under the Team Settings->API menu.

Note that the redirect URI must use https. The one exception is on Sandbox, where, for testing purposes, redirect URIs pointing to localhost are allowed over http. Custom URI schemes are not supported in any environment.

  • For web, Webviews, iOS SDK, or React Native on iOS, add the redirect URI to the Allowed redirect URIs.
  • For Link iOS SDK or React native on iOS, your redirect URI must be also registered as an app link to enable app2app authentication flows. You will need to configure an Apple App Association File. Custom URI schemes are not supported; a proper universal link must be used.
  • For Link Android SDK or React Native on Android, add your Android package name(s) to the Allowed Android package names list. Plaid will automatically create your redirect URI and its contents based on your package name. Instead of passing redirect_uri in the following steps, you will use android_package_name.

Plaid API configuration

On the server side, you'll need to ensure that you specify the redirect_uri (or android_package_name, when building for Android) and user.client_user_id parameters when calling the /link/token/create endpoint. Do not use query parameters when specifying the redirect_uri.

OAuth support requires use of Link tokens. The legacy client-side settings oauthRedirectUri and oauthNonce are ignored and will not be read. If you are still using a legacy public key, see the Link token migration guide.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
const response = await client.createLinkToken({
user: {
client_user_id: '123-test-user-id',
},
client_name: 'Plaid Test App',
products: [transactions'],
country_codes: ['US'],
language: 'en',
webhook: 'https://sample-web-hook.com',
redirect_uri: 'https://domainname.com/oauth-page'
}) .catch((err) => {
// handle error
});
const linkToken = response.link_token;

Client-side configuration

Depending on your client platform, Link may require additional configuration to work with OAuth. Detailed instructions for each platform are provided below.

Link integration typeAdditional Link configuration required?
Desktop webStrongly recommended
Mobile webYes
WebviewYes
Android SDKNo, but app package registration required
iOS SDKYes
React Native (Android)No, but app package registration required
React Native (iOS)Yes
ReactYes
Desktop web, mobile web, or React

You will need to launch Link twice, once before and once after the OAuth redirect. The first time, set the token parameter to a Link token that was generated by calling /link/token/create with a redirect_uri. The user will be redirected to the bank's site or mobile app (if app2app is available).

After the user completes the OAuth flow on the bank's site or app, the redirect URI (for example, https://domainname.com/oauth-page) will be called in order to return control to your application. On the page pointed to by the redirect URI, you will need to initialize an instance of Link, configured as described below.

To complete the flow, re-initialize Link with two configuration parameters: the same Link token from the first initialization and the full receivedRedirectUri from window.location.href. The standard Link callback onSuccess will be triggered as usual once the user completes the second Link instance.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
import React, { useEffect } from 'react';
import { usePlaidLink } from 'react-plaid-link';
const OAuthLink = () => {
const linkToken = localStorage.getItem('link_token');
const onSuccess = React.useCallback((public_token: string) => {
// send public_token to server, retrieve access_token and item_id
// return to "https://domainname.com" upon completion
});
const onExit = (err, metatdata) => {
// handle error...
};
const config: Parameters<typeof usePlaidLink>[0] = {
token: linkToken!,
receivedRedirectUri: window.location.href,
onSuccess,
onExit,
};
const { open, ready, error } = usePlaidLink(config);
// automatically re-initialize Link
useEffect(() => {
if (ready) {
open();
}
}, [ready, open]);
return <></>;
};
export default OAuthLink;

Redirect URIs and desktop web

OAuth flows will work on desktop web when no redirect URI is specified; if you have not provided a redirect URI to /link/token/create, you do not need to re-launch Link on desktop web. However, implementing OAuth flows in this way is strongly discouraged, because the resulting OAuth flow will not work for users on mobile web. For a robust integration, specify a redirect URI and re-launch Link as described above.

Webview

You will need to launch Link twice, once before and once after the OAuth redirect. The first time, set the token parameter to a Link token that was generated by calling /link/token/create with a redirect_uri. The user will be redirected to the bank's site (in a new tab) or mobile app (if app2app is available).

1
2
https://cdn.plaid.com/link/v2/stable/link.html? isWebview=true
&token=GENERATED_LINK_TOKEN

After the user completes the OAuth flow on the bank's site or app, the redirect URI will be called in order to return control to your application. On the page pointed to by the redirect URI, you will need to initialize an instance of Link, configured as described below.

The redirect URI will also have query parameters and fragment identifiers appended to it, similar to the sample receivedRedirectUri provided in the example below - be sure to pass the full string into the receivedRedirectUri parameter when initializing Link the second time, along with the same Link token from the first initialization.

1
2
https://cdn.plaid.com/link/v2/stable/link.html? isWebview=true
&token=SAME_GENERATED_LINK_TOKEN&receivedRedirectUri=https://domainname.com/oauth-page?oauth_state_id=9d5feadd-a873-43eb-97ba-422f35ce849b
iOS

Using OAuth with the Link iOS SDK requires LinkKit version 2.0.5 or later.

First, generate a Link token by calling /link/token/create and passing in a redirect_uri. Your oauthRedirectUri must also be added to the Plaid dashboard and should be configured as a universal link (not a custom URI) using an Apple App Association File, as described in Redirect URI configuration.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// With custom configuration
let linkToken = "<#GENERATED_LINK_TOKEN#>"
let onSuccess: (LinkSuccess) -> Void = { (success) in
// Read success.publicToken here
// Log/handle success.metadata here
}
let linkConfiguration = LinkTokenConfiguration(linkToken: linkToken, onSuccess: onSuccess)
let handlerResult = Plaid.create(linkConfiguration)
switch handlerResult {
case .success(let handler):
self.handler = handler
handler.open(presentUsing: .viewController(self))
case .failure(let error):
// Log and handle the error here.
}

Once the user completes the OAuth process on the bank's site or app, control will be handed back to your app via your redirect URI universal link. Provide the redirect URI universal link to the handler created in the above step to continue Link.

1
2
3
4
5
let redirectUri = <#YOUR_OAUTH_RESPONSE_URL#>
let error = self.handler.continueFrom(redirectUri: redirectUri)
if let error = error {
// Log and handle the error here.
}
React Native on iOS

As React Native on iOS uses universal links for OAuth, it is required to add the following code to the AppDelegate in the native iOS code:

1
2
3
4
5
6
7
8
- (BOOL)application:(UIApplication *)application
continueUserActivity:(NSUserActivity *)userActivity
restorationHandler:(void (^)(NSArray * _Nullable))restorationHandler
{
return [RCTLinkingManager application:application
continueUserActivity:userActivity
restorationHandler:restorationHandler];
}

The above code block informs the React Native Linking library when the application is opened through a universal link. The React Native Plaid Link SDK will correctly continue OAuth when the application is opened through the registered universal link.

The PlaidLink component handles Universal Links by default. For integrations that use PlaidLink.openLink, Universal Links will not be handled by default. The useDeepLinkRedirector hook must be invoked by the component that calls PlaidLink.openLink.

Android SDK and Android on React Native

Generate a Link token by calling /link/token/create and passing in an android_package_name. Your package name (e.g. com.example.testapp) must also be added to the Plaid dashboard. Do not pass in redirect_uri in the /link/token/create call. Then, proceed to open Link with the generated token.

Persisting user state when re-initializing Link

When re-initializing Link after OAuth redirection, the same Link token from the first initialization must be used. It is up to you to determine the best way to retain user state and provide the correct link_token upon redirect. The receivedRedirectUri field must not contain any extra query parameters or fragments than what is provided upon redirect. A correct receivedRedirectUri will look something like the following example:

1
https://domainname.com/oauth-page?oauth_state_id=9d5feadd-a873-43eb-97ba-422f35ce849b`
  • If Link is re-initialized in the same browser session as the first Link initialization, you can store the Link token in a cookie or local storage in the browser for easy access when reinitializing Link. For example, the Plaid Quickstart uses localStorage.setItem to store the token.
  • If Link is re-initialized in a different browser session than the first Link initialization, you can store a mapping of the Link token associated with the user (server-side). Upon opening the second browsing session, authenticate the user, fetch the corresponding Link token from the server, and use it to reinitialize Link.

Testing OAuth in Sandbox

To test out the OAuth flow in the Sandbox environment, you can use Platypus OAuth Bank (ins_127287). The dummy institution does not direct you to a real bank's site, but allows you to grant, deny, or simulate errors from the placeholder OAuth page instead. You can test OAuth on Sandbox even if Plaid has not yet enabled OAuth flows for your account.

Note that unlike other Sandbox institutions, Platypus OAuth Bank does not support custom Sandbox data or programmatically creating Items via /sandbox/public_token/create.

Link callbacks for OAuth

The sequence of Link callback events will look a little different from non-OAuth flows.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
OPEN (view_name = CONSENT)
TRANSITION_VIEW view_name = SELECT_INSTITUTION)
SELECT_INSTITUTION
TRANSITION_VIEW (view_name = CREDENTIAL)
SUBMIT_CREDENTIALS
TRANSITION_VIEW (view_name = LOADING)
TRANSITION_VIEW (view_name = MFA, mfa_type = device)
SUBMIT_MFA (mfa_type = device)
TRANSITION_VIEW (view_name = LOADING)
TRANSITION_VIEW (view_name = MFA, mfa_type = code)
SUBMIT_MFA (mfa_type = code)
TRANSITION_VIEW (view_name = LOADING)
TRANSITION_VIEW (view_name = CONNECTED)
HANDOFF
onSuccess
1
2
3
4
5
6
7
8
9
OPEN (view_name = CONSENT)
TRANSITION_VIEW (view_name = SELECT_INSTITUTION)
SELECT_INSTITUTION
SUBMIT_CREDENTIALS
SELECT_INSTITUTION
OPEN_OAUTH
TRANSITION_VIEW (view_name = CONNECTED)
HANDOFF
onSuccess

If the user closes the bank's OAuth window without completing the OAuth flow, Link will emit a CLOSE_OAUTH event.

If Plaid encounters an error from the bank's OAuth flow, or if the user chooses to not grant access via their OAuth login attempt, Link will emit the following events once the user returns to Link:

1
2
FAIL_OAUTH
TRANSITION_VIEW (view_name = ERROR, error = null)

Once you receive the onSuccess callback from an OAuth flow, the integration steps going forward are the same as for non-OAuth flows.

Refreshing consent

When using OAuth, end users may need to refresh their access-consent after a certain amount of time. To see when a user will need to re-authenticate, make a request to the /item/get endpoint and see the consent_expiration_time field. Plaid will also send a PENDING_EXPIRATION webhook one week before a user’s access-consent is set to expire. In order to continue receiving data for that user, ensure they re-authenticate via update mode prior to that date.

Managing consent revocation

Many institutions that support OAuth provide a means for the end user to revoke consent via their website. If an end user revokes consent, the Item will enter an ITEM_LOGIN_REQUIRED state after approximately 24-28 hours. We recommend giving the user an opportunity to either verify that they intended to remove the Item or to indicate that they did not mean to revoke access. If the user verifies that they meant to remove the Item or does not respond after a few days, delete the Item and associated data. If the user did not mean to revoke access, they can re-authorize access by going through the standard update mode flow.

Institutions that support OAuth may also provide the end user the ability to revoke consent for a single account, without revoking consent for the entire Item. Accounts in this situation are treated the same as accounts that have been closed: no webhook will be fired, you will stop receiving transactions associated with the account, and Plaid will stop returning the account in API responses. Access can be re-authorized via the update mode flow.

Partial consent

OAuth can provide the ability for end users to configure granular permissions on their Items. For example, an end user may allow access to a checking account but not a credit card account behind the same login, or may allow an institution to share only certain account information, such as identity data but not transaction history. If an end user chooses not to share data that is required by your Link token's products configuration, or does not share access to any accounts, the Link attempt will fail. In this case, they will need to restart the Link flow.

If your app later needs to request access to a product or account that was not originally granted for that Item during Link, you can send the user to the update mode flow to authorize additional permissions.

App-to-app (aka app2app) authentication

Some banks (e.g. Chase) support an "app-to-app" experience if the user is authenticating on their mobile device and has the bank's app installed. Instead of logging in via the bank's site, the bank's app will be launched instead, from which the user will be able to log in (including via TouchID or Face ID) before being redirected back to your app. Support for app-to-app should be automatic once you have implemented support for OAuth on mobile. Note that on iOS, this requires configuring an Apple App Association file to associate your redirect URI with your app, as described under Redirect URI configuration.

The full app2app flow cannot currently be tested in the Sandbox environment. You can test that your universal link works correctly by opening it from another app (e.g. Safari, Chrome, Slack, Notes).

QR code authentication

For many European institutions, Plaid supports the ability for an end user to authenticate via their bank's mobile app—even if the user's journey begins in a desktop-based web session—in order to optimize for conversion. After the user selects an institution, they will be presented with the choice to scan a QR code and authenticate in the bank’s mobile app or to continue on desktop. When the user scans the QR code, they will be redirected to the bank’s app (or website, if the user does not have the app installed). After the user completes the OAuth flow, they will be redirected to a Plaid-owned page instructing them to return to their desktop to complete the flow.

To enable QR authentication, contact your Plaid account manager or file a Support ticket. No changes to your Link OAuth implementation are required to enable this flow.

To test out the QR code flow in the Sandbox environment, you can use Flexible Platypus Open Banking (ins_117181). When you launch Link with this institution selected in Sandbox, the QR code authentication flow will be triggered. The Sandbox institution does not direct you to a real bank's mobile app, but allows you to grant, deny, or simulate errors from the placeholder OAuth page instead.

Supported institutions for QR code authentication
Institution nameInstitution ID
Bank of Scotland - Personalins_118274
Bank of Scotland - Businessins_118276
Barclays (UK) - Mobile Banking: Businessins_118512
Barclays (UK) - Mobile Banking: Personalins_118511
Barclays (UK) - Mobile Banking: Wealth Managementins_118513
First Directins_81
Halifaxins_117246
HSBC (UK) - Businessins_118277
HSBC (UK) - Personalins_55
Lloyds Bank - Business and Commercialins_118275
Lloyds Bank - Personalins_61
Monzoins_117243
Nationwide Building Societyins_60
NatWest - Current Accountsins_115643
Revolutins_63
Royal Bank of Scotland - Current Accountsins_115642
Santander (UK) - Personal and Businessins_62
Starlingins_117520
Tesco (UK)ins_118393
TSBins_86
Ulster Bank (UK)ins_117734