How do you know that an API does what it says it does?
Having been in fintech for a while, I’ve noticed something in common between the many new startups that come and go. They all require access to personal information.
A specific example that comes to mind is the Plaid-like solution we developed while working on amal. We’d ask customers for their bank credentials[ajy] and then proceed to login on their behalf in order to share the resulting account information with the 3rd party application they are using (e.g. for transferring money, tracking their spending, etc).
I’ve noticed similar things with companies that try to optimize the checkout experience – almost always by becoming the interface layer that users use, necessarily being exposed to sensitive cardholder information like the card number, CVC and even PIN number in some instances[axo].
The problem in all of these situations is that these apps require users to trust them, but provide no means for verification that this trust is not misplaced.
“Trust, but verify” — Russian proverb
Is there a better way?
Many throw their hands in the air and point to the protectionist practices of financial institutions that prevent data sharing — without APIs, the only real option for authenticating users is with the same credentials they use themselves.
To explore better ways forward, let’s make a few assumptions (and eliminate thorny edge cases that frontload a lot of complexity):
- The application handles sensitive data
- It performs a deterministic task (i.e. same inputs result in the same output)
- It does not rely on state
- The application doesn’t keep logs (or retains anonymized and desensitized logs to aid in debugging)
What we’re after
Let’s be clear about what we’re after.
If an app holds the assumptions we set earlier, then we should be able to use that app in a way that allows independent third parties to verify that the app is doing exactly what it says it’s doing.
In the case of a checkout app for instance, we should be able to verify that it’s not stealing customer’s card details and siphoning them off to the Russian mafia.
This is simple-enough to do, to some extent, on front-end applications – because we can inspect the code ourselves (albeit, obfuscated code to an increasing degree). Still, worst case we’d still be able to track network requests being made from the application – as well as any usage of local storage to ensure there’s nothing fishy going on.
But what about the backend? They are completely opaque to anyone outside the server; true black-boxes, where only the inputs and outputs can be observed, but not what’s performed inside.
This is exacerbated by the fact that front-ends are also the front-lines of the war against all sorts of user-side attacks (CSRF, poisoning, etc). This has resulted in things like CORS, that prevent clients from making HTTP requests that would otherwise work completely fine on backends.
Options For Greater Transparency
1. Fatter front-end’s for security
[ajy] It’s so sad that it’s come to this. Sharing bank credentials with 3rd parties should never be ok, and yet it seems to be the only practical way that third party apps can communicate with financial institutions.