Forum Academy Marketplace Showcase Pricing Features

🔑 Building an app that stores multiple user API keys - not just mine

To quote @josh in Request for a Security Q&A Guide

That’s precisely what I want to do. However, my experience is that API keys need to be saved in the database as plain text which means they are still viewable by me and anyone who gains unauthorized access to my editor or database. That doesn’t seem right :confused:

Also, and please correct me if I am wrong, there isn’t a way to actually add API keys stored in the Bubble db to an API call in a “secret” or “private” way… meaning that these keys would have to be added in as parameters which, according to @mishav, can be seen by routers or other prying eyes:

So is it really okay to save other user’s API keys in a bubble database? If so, then how do you do it so that the application creator can’t see them? And if that’s not possible, is the only other way to achieve this with storing OAuth2 session tokens?
Thanks in advance :smiley:

1 Like

@antony, since that was your post that Josh had responded to on all of your security questions, would you by any chance have any pointers here?

@eve, can you assist here? Or perhaps flag this thread for a response from engineering? Thanks in advance. :slight_smile:

Using Api connector or plugins, credentials can not be change dynamically unfortunately.

Plugins can be given API keys dynamically through the use of parameters, as I had mentioned.

Are you confirming that this can’t be done in a secure way?

Hi! Yeah, indeed would be cool to have a way to set secrets from users as environment variables, however that’s very tricky to do in a way that not even the app maker can see it due to how encryption works.
In short, at the very moment the user pastes the key in the browser you could grab it since you control the page.
So in the end you can have they key one way or the another and your users have to trust you.

Privacy through untrusted setup (which means your users do not trust you) like that can only be achieved by installed, open source and build verifiable apps. Unless there’s some innovation I’m unaware of.

It really depends on what type of key you are talking about.

If you are asking people to paste a key into your app, and then you are using that as a parameter on a URL … it had better be for something fairly safe.

However it looks like you are talking about Oauth2 which is a very different thing.

The keys are in the Header, not the URL.

And in this case you are usually given a time limited token, which can be refreshed. If you don’t have the right credentials … you can’t refresh. If the user revokes access - it can’t be refreshed.

So whilst you should be looking after the Token, they are, by design, limited in the damage they can do should they get into the wild.

Therefore, storing it in the database in text is probably no terrible thing. Particularly as you need other credentials as well.

The issue we have with Bubble is that we also have to store OUR creds in text.

I have asked several times that the “secret” implemented in the Server Side Plugins should be available in the API connector.

The way I have got round this before is to use a third party to hold the tokens (in this case auth0) or use a small webtask to run the call. This means the credentials are not all in Bubble.

Nigel! I was hoping you would chime in :slight_smile:

I see, so really the current “securest” way to integrate 3rd party services for multiple users via their API keys is to use Oauth2. Store the temporary token in plain text. Refresh it as they need it.

Assuming a bad actor obtains short lived access to my application

Zues forbid, if someone gained unauthorized control of my bubble application, then they could commandeer OAuth2 tokens saved in plain text. But, because the tokens need to be refreshed and are scoped to my application, a bad actor could at most use them only from my service. So they would have to not only have access, but for long enough to write custom code which would have to execute on my app in production. As a result, they would have to push an update, which would at least leave a trace. Assuming the breach is detected quickly and I still have access to my application, then I change my passwords / editor access permissions PLUS roll back the update. At this point, the breach has hopefully been fully contained. wait a minute that’s not true. Couldn’t someone potentially write malicious logic on the development version of my application. Then copy over OAuth2 tokens from the live database to development and execute their logic against those tokens? All without pushing anything into production?

Anyway, in general, if a bad actor locks me out of my bubble application, then I’m assuming I need to immediately notify Bubble of the breach for my application to be turned off / restarted from a pre-breach save point? What’s the process look like (does Bubble do anything to confirm it’s really me asking for a reset instead of a bad actor)?

Assuming a bad actor pushes an update that has done malicious things for a few hours or days

Correct me if I am wrong… but the damage is done?.. if they took actions with OAuth2 tokens on my hypothetical customer’s Plaid, Coinbase, insert other financial service, account, then that’s irreversible? Best I can do is remove the malicious workflows (plugins, whatever it may be)?

Standing back a bit

Am I crazy for asking these questions? Because I’m under the impression that these are table stakes considerations for building any SaaS… not just one one bubble. When it comes to security, it’s not a question of “If a breach” will happen but “when a breach happens” and I want to be confident that my app is built in a way and I have protocol in place to limit those liabilities. … Please no one tell me that security should be an after thought one day when maybe my application has lots of users.

Hey, thanks for your message Vini :slight_smile:

I think I see what you’re saying. I guess my concern isn’t about whether I can get my users to trust me. They trust me. And if it were that simple, it wouldn’t matter much that I have access to their Stripe accounts, Social Security Number, which ever sensitive thing… because I’m a good guy and I’m not going to do anything dumb to loose their trust or ruin their lives.

No, my concern is how do I limit the damage that can result from someone not nice getting access to the sensitive things that my users have trusted me with.

… but it looks like the answer to that is OAuth2 tokens.

Ah I didn’t meant specifically you, should’ve made it clear, “trusted/untrusted setup” is a term from cryptography. Untrusted would be more or less the same of the “double blind” studies used in medicine out there. Not the actual trust between people.

Anyway, temporary tokens are good and as far as I know, Oauth refresh token isn’t (or shouldn’t be) exposed to the browser so it stays within Bubble’s servers. So that’s secure.

Ah, gotcha Vini! I apologize, I misunderstood. Thanks again for your message :slight_smile:

Hi, were you able to find a way to dynamically use api keys?

I’m trying to use different stripe api keys based the specific user and thought it might be similar to what you were trying to do.

Depending on your use case, you may be able to get away with using Stripe Connect. But if you absolutely need individual user’s Stripe API keys, then unfortunately I did not come up with a better solution than the one presented here :frowning: Sorry!

1 Like