Hey @J805,
We can appreciate your original post as it highlights the security implications of having âhiddenâ elements on your page for internal purposes. Numerous Bubblers have employed the strategy of using hidden inputs for calculations, repeating groups for queries and things of the like which are not the most secure nor most efficient. However, whatâs more troubling is the misinformation weâre seeing above on plugin security. Seeing a couple of our plugins were mentioned above in addition to a fundamental misunderstanding of API calls, we took the time to shed some light on API basics and Bubbleâs options for its plugin developers in an effort to benefit the community.
Fundamentals
API Calls
Interacting with a server/vendor for information usually involves an API call; you request some information from a location, you include an API key to identify who you are, you get a response. With the modern web standard, executing API calls is a must not just to request data from other services (Stripe, Google, etc.) but sometimes for your own application. For example, your frontend (also a client) could request information from your backend (as a server) such a userâs profile information or whether theyâre even authenticated. The web is a network of servers talking to one another which means one party is requesting information from another who may itself be requesting and returning information, making API calls a facet of web development that every developer should be knowledgeable about.
API Location
API Calls are not exclusive to the client or server, and you decide where the API call must happen as the developer. If youâre accessing your own backend, thereâs no way around exposing certain information to the user on the frontend even if thatâs a token; take a stroll through your browserâs Network tab to explore the type of information Airbnb, Uber, and Stripe send their own server when you use their frontends. See @vini_brito shortâs and sweet comment above as well.
Your userâs browser is making the API call to wherever your backend is accessible, and your backend could very well be executing API calls on its own to get what it needs. Most developers would understand the implications of making API calls to sensitive locations on the client, and thus would very likely build backends that run those API calls instead. Bubble offers the same extensibility with things like backend workflows, as you can easily take API actions from your frontend workflows and asynchronously run them on the backend. The decision lands on the developer as to where to execute an API call, and thereâs more than just security and performance to consider.
API Visibility
With the right tools and motive, almost any interface channel can be intercepted. With the few large-scale infiltrations of enterprises highlighted this year alone, everyone is aware security is no laughing matter. One way of preventing a malicious party from comprising any system is lack of visibility, which is a strong argument for making API calls on the server again. Any API call (not just those made from a browser) will not know what other API calls, queries, etc. the destination server will make, as the client you just want what youâve asked for. The same way you request a retail store employee to find you an item from the stockroom: you donât have permission to enter and rummage through the racks yourself but the employee does, you donât know anything about the processes happening, so you just wait until they return and parse the result.
Plugin Security
Bubble allows the plugin developer to decide which keys can be exposed to the client and which keys cannot. As we know, the client is generally considered unsafe in the context of working with and exposing sensitive data while the server is more secure. Separating data across both the frontend and backend may make your development more challenging, but thatâs a consideration of numerous factors including and beyond security. Bubble offers plugin developers certain types of fields to aid with the accessibility of information which is worth evaluating.
Field Types
Seeing the fields in your Bubble editor after installing a plugin can certainly make you reflect whether or not they are all required. When developing API actions (not JS actions) for plugins, the structure of the call may require some field values that the developer is knowledgable of but perhaps not their users. There are also cases where keys are required to access an API, on top of the formatting of the call itself to be compliant with what the destination server requires. Bubble solves some of the knowledge-gap and general UX problems of API actions with field types.
Here are Bubbleâs own words on field types as shared in the Bubble manual:
-
Public parameters will be modified by the user at the call level (thatâs for instance a term for query API call).
-
Hidden parameters are for the plugin builder, and wonât be exposed to the user that uses the plugin. For instance, it can be an encoding type, etc.
-
Secret parameters are good for keys, etc. Users will enter these in the Plugins Tab of the editor.
The field types are determined by the developer based on what they require from their pluginâs users. A common example is the Content-Type
header of an API call; most users would not know what that is or what the valid value would be, so the plugin developer may choose to set the value to application/json
, application/x-www-form-urlencoded
, etc. and mark the whole field as âHiddenâ so their plugin users donât have to see or deal with it at all. If they wanted to expose it to their user in the Plugins tab, theyâd opt for Secret. If they wanted to expose it all the way to the workflow action, theyâd opt for Public. The decision is made by the developer.
Key Types
When Bubble introduced client-side actions and later server-side actions to match, it gave more reason for plugin developers to take advantage of the Additional Keys section in the plugin editor. A plugin developer could ask for specific keys and values from the user in the Plugins tab and use them at their discretion for operations like initializing elements, executing API calls and more.
There are two types available here:
Public keys are included in Context object and can be accessed for both client and server actions.
Private keys are also included in the Context object are not accessible on the client.
We know these to be true because not only does this inherently make sense as a logical decision from Bubble, but also because it takes almost no time to prove:
- Setup additional keys, Public and Private (Privacy - Additional keys - Droplr)
- Create client functions, Element and Action (Privacy - Element - Droplr, Privacy - Action - Droplr)
- Create server function, Action (Privacy - Server Action - Droplr)
- Wire up some workflows for testing (Privacy - Workflows - Droplr)
- Throw on a UI and run (Privacy - UI - Droplr)
Results? Both of your client functions will be able to successfully access the Public key but not the Private key, while the server function can access both. Privacy - Execution - Droplr
Key Uses
As seen above, simply setting a value to âPublicâ or âPrivateâ has nothing to do with exposing data. To reiterate from above, having access does not equate to accessing itself. A good developer would know the implications of their decisions early on, a great developer would know the implications of neglecting proper use. This is a good time to reflect on our own approach for keys, and itâs how everyone should be building plugins: using the serviceâs own documentation.
Imagine you were building the most powerful payments plugins for Bubble, something that would offer an alternative to Bubbleâs built-in integration, really make a difference in whatâs possible with Bubble and perhaps even change how people learn by using a third-party service they already know to educate them about development altogether. If you happened to choose Stripe as a plugin developer, landed on integrating PaymentIntents, learned about Strong Customer Authentication and realized you needed to implement Stripe Elements, you would be posed with this challenge from Stripeâs documentation:
Next, create an instance of the Stripe object by providing your publishable API key as the first parameter:
var stripe = Stripe('pk_test_6tv7cR2saQ0So4FmdYhlpkOwgFcl8CuN');
Reference: Stripe Web Elements | Stripe Documentation
A competent plugin developer would understand the following concepts based on their research:
- Since Iâm showing this to my user, itâs on the client not server
- I need to load a JS library for my users
- I need to run functions using the JS library
- I need to show the rendered element from the JS library to my user
- I need to get the userâs key for my JS library to work
- I need to ask my user for that key
â´ Therefore, I need access to my userâs key on the client side.
To accomplish this, that competent developer would setup up an Additional Key, set it to Public so they can access it on the client and then pull it to load the library, run their functions and ultimately hit their goal. To add even more confidence into their build, that developer would reference Stripeâs documentation to see if itâs safe or even permissible to pull the Publishable Key to the client which is where theyâll find the following:
Publishable API keys are meant solely to identify your account with Stripe, they arenât secret. In other words, they can safely be published in places like your Stripe.js JavaScript code, or in an Android or iPhone app.
Secret API keys should be kept confidential and only stored on your own servers. Your accountâs secret API key can perform any API request to Stripe without restriction.
Reference: API keys | Stripe Documentation
The above still doesnât consider the longevity of tokens, functions with external dependencies, and other issues/arguments against running things client-side versus server-side. Weâd delve into the basics of the other services mentioned in posts above but that may be better served as a good mental or development exercise for practice with plugin development.
We welcome healthy discussion any time of the day, but sharing incorrect and invalid information that can derail or discourage the community at large is not acceptable. 