Plaid Integration

@natedogg, I don’t want to hijack your Qoins thread, so I figured it would be better to start a new one about connecting to Plaid. I am attempting the Simple Integration as outlined in the Plaid Quickstart Guide

I have included the following tags in an html element, but I am getting an error:

<form id="some-id" method="POST" action="/plaid-auth"></form>

<script
  src="https://cdn.plaid.com/link/stable/link-initialize.js"
  data-client-name="MY APP NAME"
  data-form-id="some-id"
  data-key="b54e....................."
  data-product="auth"
  data-env="tartan">
</script>

[details=Returns an Error]Oh no!

We’re having some temporary technical difficulties right now. We’re working on the problem as fast as we can!

In the meantime, try refreshing the page or hitting “back” on your browser just in case things are working again…

We’re really sorry![/details]


From the Plaid guide:

In the example above, the form some-id had action=“/authenticate”. So we’ll add a /authenticate route to our server side code that expects a POST request with a field named public_token in the request body. We’ll then use that public_token along with our private client_id and secret to retrieve a Plaid access_token (via the /exchange_token endpoint). This access_token should be saved in a database and used to retrieve account and transaction data.

I am confused by their use of “we”. I assume this means me? Weird.

Anyway, because completion of the Plaid form redirects to myapp.bubbleapps.io/authenticate I assume I need to expose an API endpoint (with the same name as the form’s action=“/authenticate”), with a text parameter of “public_token”. I’ll then use this to trigger an API connector to exchange this for an access token.

First, how do I resolve the error listed above?

Second, What is the best way to save this access token? (since it is specific to my app, not each user, correct?)

So in order to get this to work well with Bubble, I made some changes to the Plaid Link code provided to make it client side instead of server side.

So instead of:

<form id="some-id" method="POST" action="/plaid-auth"></form>

I used:

<form id="some-id" method="GET" action="[INSERT RE-DIRECT URL HERE]"></form>

Basically what will happen here is that once the user has finished using the Link module, they’ll be re-directed to the URL that you provide. Once that page loads, the parameters public-token, institution-name, and institution-type will be available in the URL of that page. From there, you can access them and save them to the database.

The public token is safe to expose, as it has to be exchanged for an access token for the user using your API keys.

Each user that connects their bank accounts will have their own unique public token and access token.

5 Likes

Gentleman and a scholar. Thank you.

1 Like

Question. I have this working, but how do I get an account_id?

The account_id is necessary to retrieve a Stripe Bank Account Token via the /exchange_token endpoint.

The plaid login form successfully redirects to my URL with the public_token parameter. The URL also contains “account_id=” but no value.

bubbleapps.io/version-test/plaid_test?account_id=&institution%5Bname%5D=Wells+Fargo&institution%5Btype%5D=wells&public_token=4349f4a...

Once your user has linked their account via the module, first you’ll need to get an access token using the same /exchange_token endpoint that you mentioned.

Then you’ll need to use the API Connector to get the user’s accounts with Auth. You’ll get a list of accounts, with account_ids that you can exchange for a bank token.

Cool. Thanks for the response.

In that scenario, how do you know which account to debit?

See this Stripe + Plaid Demo which allows the user to select the account they want to use.

Is there any way to add the selectAccount parameter set to “true” in the code mentioned above? Or do I need to use the code mentioned in Stripe’s ACH Guide instead?

<button id='linkButton'>Open Plaid Link</button>
<script src="https://cdn.plaid.com/link/stable/link-initialize.js"></script>
<script>
var linkHandler = Plaid.create({
  env: 'tartan',
  clientName: 'Stripe / Plaid Test',
  key: '[Plaid key]',
  product: 'auth',
  selectAccount: true,
  onSuccess: function(public_token, metadata) {
    // Send the public_token and account ID to your app server.
    console.log('public_token: ' + public_token);
    console.log('account ID: ' + metadata.account_id);
  },
});

// Trigger the Link UI
document.getElementById('linkButton').onclick = function() {
  linkHandler.open();
};
</script>

The only issue is the button doesn’t seem to work… Try Here

The easiest way is just to display the API call response in a repeating group and let them select an account. Then, save the current cell’s account_id to the user and reference it in future calls.

1 Like

Thanks man. Appreciate the help.

1 Like

A small update, in case anybody is curious in the future, I got the javascript from Stripe’s ACH Guide to work by using the correct public key. I falsely assumed the popup would testable by just copying their code, but a 401 error prevents the button from functioning without a proper key.

That being said, they code works fine in an online javascript editor, but it gives an error when used in Bubble’s html element - not sure why. It gives an Uncaught ReferenceError: Plaid is not defined. If anybody understands how to fix this, please don’t hesitate to share.

The account_id and public_key are returned successfully (they can be seen within Chrome’s javascript console). But since they don’t appear to be available as url parameters I’m not sure how I would capture and store those values. This is unfortunate because the Plaid Link module allows the user to select the account they want to debit within the same form, which would make for a nicer UI.

That being said, I’m going to try @natedogg’s suggestion. If anybody sees a quick fix here, I’m all ears.

@natedogg, can the access_token, stored on the user, be exposed as client safe? I feel like it shouldn’t be, but if not, how do I dynamically insert it in the Auth data call?

I know I’m not @natedogg and I’m not 100% sure about this but can’t you control the that using Data roles in the Privacy tab? I haven’t had the chance to dive into adding something like this yet, I just noticed that I had to create a role for users to be able to “Enable auto-binding on parent elements thing” setting I just discovered. Sure saved me some time creating the workflows for the user input fields.

I believe the data roles are meant to protect information stored in the database, which is a separate issue. Of course credentials shouldn’t be visible to anyone, so a privacy role is necessary.

When marking something as client-safe in the API Connector that info is sent to the client’s browser, making it insecure. Exposing the access_token to the client seems to defeat the purpose of Plaid’s authentication, but I don’t see it explicitly stated not to do this.

Ah, that makes more sense now. I wasn’t thinking about the setting in the API Connector. Great question!

I’m a stickler for those kind of things, so I don’t save the access_token.

If you create an API Connector call to get the access_token, and set it to use in Bubble as data, you can insert the call every time you need the token.

Just for clarification:

Can we store Access Token to Server DB? if Yes, is it safe? If NO, how can we use Plaid in scheduler?

Yes, it is safe to store access tokens locally as long as your API keys are being passed into your application securely as environmental variables. Storing these tokens is highly recommended - if not required - as all future API interactions for a user require the input of an access token.

From: https://github.com/plaid/support/issues/171

1 Like

Thanks for the info. Plaid also mentions this in their documentation. But, what about marking the access_token as client safe in the API Connector?

Update from Plaid Support:
“No, while public_tokens may be exposed in an app or browser, access_tokens should not be.”

1 Like

If you can’t mark the access_token as client safe, how are you dynamically inserting each user’s access_token for a Get Transactions call?

I swear I remember seeing a solution posted somewhere, but I can’t seem to find it.

You can insert the API call for the access token inside of the API call for the data that you need.

The access_token parameter is dynamic. Doesn’t that mean you’ve marked it as client safe?