To run your tests in network tab, it is very simple.
First open your preview page
Open your browser dev tools (I use chrome)
Select Network
Refresh your browser
Look at what comes up, and most importantly, focus on finding the below three value sets
maggregate is an aggregate search and that occurs when getting a count of something, and from what I understand that happens via ‘do a search for:count’ and a reference to an RG list of things count
search is the search of the RG. You can even play around with some other tabs like Response to see the complete response and all of the characters returned
What is the difference between a client side redirect and serverside redirect? Is that associated with navigating to another page or is it to do with how data is retrieved?
A server side redirect never loads the page contents and sends you straight to the redirect page. A client side redirect loads the page, then runs the redirect. A client can cancel the redirect from their browser to remain on the page.
I’d imagine can force 302 server side redirect if conditional is do search for user, constraint is unique id equals current user unique id: first item doesn’t contain role.
Just got on the computer and tested this out and it works, it will perform a 302 redirect
You can also get a 302 redirect without needing to search via combination of privacy rules and data structure for any page that has a content type. Below are screen shots of setup for privacy rules, two data types and page content type plus the trigger with condition for go to page action.
The above will work to execute a 302 redirect if the user is logged in or not logged in and whether or not you have a default role on the user data type set or not. In my opinion, the combination of the privacy rules, data structure and conditional trigger is the best approach since it doesn’t necessitate any search of the DB, nor does it require more than one trigger to check if it needs to redirect or not, and if for some reason the redirect fails, the data should still be secure.
One thing to keep in mind, is if the user were to trick the client device into a false role, it is still imperative to have data structure or privacy rules to ensure the user only accesses data they should access.
I’m not sure that all of this is necessary. You could also put the following condition on the single “Go to page” action:
When Current User is logged out OR (When Current User is logged in and Current User’s Role is not X)
This is just for the page, the data would be protected by privacy rules. I don’t think there’s any point in only showing the user’s role if the roles are part of an option set anyway, since those are public.
That is a client side redirect because of use of the Current Users Role…point of my suggestions is to have server side redirects to ensure the user never gets a chance to alter the response from the client device to still access data or a page. It is basically to ensure real security.
It’s not a client side redirect in this context and with that expression, I’ve tested it. “Current User is logged out” covers the “exploit” we recently discovered. @georgecollier can you confirm?
To explain:
Current user is logged out = Serverside condition
Go to page (in this context) = Serverside action
Both evaluated on the server, can’t be spoofed. You can’t spoof “Current user is logged in” with a cookie or all of Bubble would be compromised.
I can confirm it for you. One of the issues is that your statement of conditional was not a single ‘current user is logged out’, it had an OR statement which is where you the security vulnerability is and can result in a 200 redirect. Gotta look at the entire statement.
Here is video demonstration and explanation.
To have an optimized approach in terms of WUs, ease of maintaining app (ie: single trigger and single condition with no OR or AND operators) as well as most secure in terms of privacy rules I would recommend to use the approach I outlined since it always results in a 302 redirect, except when the page thing is not set, it does a 200 redirect, but since the page thing is not set, there is no data that could be leaked, so a non issue.
But if you have an OR statement that allows a user to be logged in and their role is not X it performs a 200 redirect and opens up the possibility for the user to override the client response to change their role to X.
Would love to know what you find. My understanding was for WU efficiently you frontload the “lightest” conditions first so as to not incur the whole cost of the expression. It wouldn’t really make sense to have ORs and ANDs otherwise, right? If my example expression doesn’t stop being evaluated at that exact moment then that would be the equivalent of using AND instead of OR (Edit: Actually I can see how it might be possible to separate this, since Bubble is using an abstracted “interpreted” language as the “middleman” between our expressions and the actual JS, nvm on this point. It would depend on the extent to which expressions are “chunked.”).
In this particular instance it doesn’t really matter for securities sake. Let’s assume it stops immediately after Current user is logged out, okay your redirect goes through. If it needs to evaluate the whole expression, okay it’s still true. It’s all done serverside anyway unless you add a client side condition, in which case for whatever reason that clientside condition is evaluated first, breaking the serverside redirect.
Since it’s being evaluated on the server, the client never sees the “progress” of it, it’s either evaluated or not evaluated in either case.
Very interesting. Just tested, and if I use page is loaded with condition the current user is logged in and current user role is not X, it does do a 302 redirect.
Yup, the only way to break this is by adding another clientside condition on it, or to add another action to the workflow.
Your original method reminds me of this post which I found to be very complicated and perhaps a result of not being able to use parentheses back in 2019:
Edit: I could see how this method might be good for traceability and extra redundancy but still it seems very overkill to me. There was also no WU back then, it was just capacity, so you could get away with constantly searching.
The reason we did it was for efficiency. In normal logic, for the expression ‘if P or Q’, if P is true, then we don’t need to check Q because the expression will be true regardless. The general idea is that Bubble does the same optimisation (and doesn’t evaluate Q if P is true in this simple case).
I just did a very simple test and it looks like this is true. For expressions:
P or Q
e.g Do a search:first item is not empty or Current user’s X
P or Q or R
e.g Search:first item is not empty or Search first item is not empty or Search first item is not empty