I’m struggling looking for a way to encrypt & decrypt sensible API data for using it on API calls.
Scenario description: I’m setting API calls to integrate different services using API Connector Plugin with “none/self-handled” method, setting the client_id/secret as private values and then storing tokens/refresh for each user (with privacy rules applied).
My main concern is the possibility of a hacker / malicious user logging in the editor and having both user tokens (in db) and api’s id & secret (in api connector) as strings, they could gather the information. So i would need to encypt or: a) user’s tokens b) client id/secret c) both
I found some possible approaches but with some weak points:
Encrypting and decrypting the data client-side using a plugin: The encryption key is visible on the editor, so if a user logs, can get the data decrypted
Using Bubbles Server Side functions/plugin to encrypt/decrypt data (and using Node’s crypto for example): Same as previous step,if a user manage to log in, he can go to the custom plugin and get the encryption key to decode the string.
Using an external microservice (for example AWS Lambda or Google Secret Manager): Seems to be the best approach, i prefer GCloud ecosystem.
The main problem i’m finding with the this approach is that a malicious user could still request the data if managing to see the request to this services.
problem scenario: app requests a key from a microservice through a server side function, wouldn’t a user with editor access be able to enter to the API request (like step 2) and get the access data for that call? (google’s cloud functions/secrets works with service accounts)
Is there anyway to store “secret/hashed” values into bubble’s database/plugin builder? (There is a request for this already in the forum)
Is encrypting/decrypting the API secret dynamically an option? > If the client secret is dynamic (for changing it on each request) it wouldn’t be private on API connector, so it can be seen as a request header pretty easily.
If you reach this point, thank you for your patience!
I completely understand your concern. When handling credentials for external sources, you need to be carefull of course, but it is very hard to make any system 100 % safe.
The approach I would follow (and one I do follow myself) would be to store refresh and access tokens (with privacy control) and then use MFA for your app so any hacker etc. can’t get access to the editor. Make sure refresh tokens can only be used once and make the access_token expire in a relatively short time (say 3600 seconds).
Regarding encrypting/decrypting client_id/credentials, you still need a secret key, and where would you store that?
Point is, security is an endless pursuit - you need to stop at some point. If a hacker gets access to your editor, you are screwed anyway, so this should be your main concern (MFA, rotate password, use a password manager etc.).
I think i saw a post where you describe that process, thats why i tagged you . User’s tokens doesnt concern me much, since they are private in the DB (but as strings though) and a hacker cant do much without client credentials. That’s a great security measure (in fact, its listed under Auth0 best practices):
Give tokens an expiration: Technically, once a token is signed, it is valid forever—unless the signing key is changed or expiration explicitly set. This could pose potential issues so have a strategy for expiring and/or revoking tokens.
I’m storing them in API connector (as text strings), following with my response, this is what is worrying me the most, an enviroment with the tokens and credentials as strings all in one place.
That’s why i considered Google’s secrets, it has an automated secret rotation (that can be done with google cloud functions). In case of following this approach, i can’t figure how can i ‘hide’ the request credentials when calling Google Secrets API, i would be having the same problem of storing them in bubble.
Yes, its like a snowball of problems , password rotation/managing for the editor is the first mesure to take i think.
I completely agree that it is not optimal - a way to store secured env’s would be much appreciated, but for what its worth MFA is your friend here. I would advice against building too much prematurely as it will become a snowball, as you said yourself
I’m late to the party, but perhaps this will help some people.
Do not do API calls that require a key/token in the browser. Create a backend workflow to handle these and call it from the front end
If you encrypt / decrypt a key, do it in the backend
We are encrypting the user’s key/token and then storing it in their user record (and use privacy rules)
Note about privacy: Sometimes a user will require another user’s key. Example: When posting a credit card payment using Flutterwave, you need to use the key of the merchant and NOT the user. So that key in the merchant’s table will need privacy exposed to any user, therefore 3 above.
When the user requires the key for an API call, we decrypt the stored string and use that as the key for backend API calls
This is about as good as we can get it right now inside the app.
Would love to hear if anyone can add to this or if they feel this approach is not sufficient.