Client-side and server-side
This section covers the difference between client-side and server-side operations in your app
Before we explore different categories of security related to Bubble directly, we need to highlight an important topic that will be mentioned repeatedly throughout this article series: the difference between client-side and server-side from a security perspective.
When you run a Bubble app, two computers are working together to get the job done:
- The device you are using, such as a smart phone, tablet or computer
- The Bubble server which stores the database and performs many workflow actions
Although third-party services like plugins, APIs and external database connections can introduce more systems into the mix, your device and the Bubble server are the two necessary components needed to make your app run.
These two systems are what we are discussing when we're talking about client-side and server-side.
Not all actions and expressions in Bubble need to be processed on the Bubble server. Client-side is an umbrella term for all operations that are handled on the user's device. While Bubble is a no-code platform, your app runs in all major web browsers: this means that we have to make the final app use code that browsers can recognize.
In short, client-side operations:
- Take place in the user's browser.
- Include rendering the user interface, handling user interactions, and processing data before sending it to the server.
- Generally involve visual elements and user experience, such as animations, form validation, and user input.
- Can be less secure, as the code is accessible and can be manipulated by malicious users.
When a user starts loading your page, the server and the device (client) work in tandem to complete the job. It's useful when discussing security to get an understanding of what happens where, because the two sides have different security profiles.
After all, while the browser hides this from you, a web application in the end is a collection of files and data streams that the server sends to the user's device. These files and data are stored on the device and the browser uses them to display things on the page and accept input.
On the client-side, where users interact with the data, some information must be accessible and not encrypted; otherwise, it would be unusable.
However, this doesn't mean the client-side is "insecure." Instead, the key is to recognize who or what is trusted with specific information. Client-side code is secure from third parties but is controlled by the visitors to the page.
The challenge, therefore, is to balance the need to provide useful information to users (such as search results) and allow input (like form submissions) with measures like privacy rules and workflow conditions. These measures ensure that the server has the final say about what information is shared and how the data from users is validated, avoiding exposing information that the user is not supposed to see or interact with.
Let's first have a look at what happens when a user loads a page in your app for the first time:
When you load a page in a Bubble app, your browser does a few things:
- It connects to the Bubble server using the HTTP protocol, encrypted with TLS (https)
- It downloads various files to the user's device:
- HTML, CSS (files that dictate the appearance of the page)
- Images, fonts, and other media displayed on the page.
- built-in files generated by Bubble, that are required for the app to work at all
- plugin JS code loaded from Bubble's servers, generated from what the plugin author built in the plugin editor
- third-party JS loaded by plugins or by user-added custom headers (e.g. a Google analytics plugin might load and run JS files supplied by Google)
- Establishes a WebSocket connection
- This allows for real-time communication between the client-side browser and the Bubble server and makes sure the data on the page is dynamic and instantly updated if something changes
- Loads any necessary data: The browser fetches data from the Bubble database (and third-party APIs if needed) and displays the data in the elements on the page that reference it
- Listens for user input: The page is now loaded and the user can start providing inputs such as data in input elements and element clicks. Some of these actions are handled on the client-side, while others are sent to the Bubble server for processing (server-side)
As we can see, a lot of data is moved from Bubble's server to the user's device when the page loads, and this is necessary for the app to run.
Let's look closer at point number 5: the loading of necessary data. This means that Bubble checks the database for any data needed to display on the page. For example, if you are loading a page that shows a list of Tasks from the database, all the fields on the Task data type that the privacy rules allow the current user to see, are downloaded.
This has some implications for your security:
The data is encrypted on the server and while in transit. It is then decrypted on the device, and stored in the browser as plaintext.
Bubble downloads all fields on a given data type. In other words, if you just show the Task name on the screen, Bubble still downloads all other fields to local storage.
To protect specific things or their fields, you must set up Privacy Rules to stop Bubble from downloading it. All fields stored on the Current user (except those hidden by privacy rules) are always downloaded when the page loads, regardless of how you set your app up
The fact that the data is downloaded to the local device does not mean the user can freely tamper with it: that part is still securely handled on the server. It just means the data can be viewed.
Many actions that you run in your app do not need to be sent to the server to be completed – indeed, many of them can't be processed on the server since they refer to things happening locally on your user's device.
For example, events, actions and conditions such as the ones listed below will in many cases be completed locally:
- 1.Navigating between pages by use of the Go to page action.
- 2.Displaying or hiding elements.
- 3.Changing the appearance or styling of elements (colors, fonts, etc.).
- 4.Validating user input in forms before submitting the data to the Bubble server.
- 5.Performing calculations or manipulating data locally.
- 6.Saving custom states with local content (such as user input)
- 7.Triggering animations or visual effects.
- 9.Do when condition is true where the condition does not happens server-side
- 10.Do every X seconds
This is not an exhaustive list, and plugins can add more points. The list serves to illustrate that actions and expressions that don't rely on requests to the database will often be handled client-side, and as such can theoretically be tampered with.
It's important to keep in mind that workflows can mix events, actions and conditions that do or do not rely on the server to complete: for example, a client-side event can trigger a server-side action and vice versa.
On the Bubble server, things work differently. All data on the server (stored in your app's database) is securely encrypted, and server-side workflows are executed in a manner that keeps them safe from malicious interference.
In short, server-side operations:
- 1.Occur on the Bubble server, away from the user's browser.
- 2.Involve processing, aggregating, storing, and retrieving data from the app's database, as well as running server-side workflows and performing calculations.
- 3.They are responsible for tasks like authentication, database queries, and executing complex logic.
- 4.Are more secure, as they are processed in a protected environment.
Just like some operations can only happen on the client, others cannot happen without involving the Bubble server.
For example, events, actions and conditions such as the ones listed below will need to be handled server-side:
- 1.Creating, updating, and deleting items in the database
- 2.Running server-side workflows (workflows that involve the database and API workflows)
- 3.Performing complex calculations, aggregation and data processing
- 4.Querying the database and filtering data
- 5.Managing user authentication and access control
- 6.Integrating with third-party APIs or SQL databases
- 7.Sending emails or other notifications to users
- 8.Handling file uploads and storage
What we can draw from these descriptions is a few simple conclusions:
- Data that reaches the user's device can be viewed by that user, even if it's not visible on the page: you need to control the flow of data that reaches the user device to make sure you are not sending more than the user is supposed to have access to. Privacy Rules take care of this.
- Workflows and conditions performed on the device should not be considered secure: you need to be aware of what kind of processing take place on the server and what takes place on the client
With that understanding, let's move on to the more practical aspects of security.