Bypass user login

Hi guys, this is a general safety question when building anvil apps. Typically this is how I structure my login page on my apps. Clients land on a login page where they are presented with a login button. Upon clicking the “Login” button, they are presented with the standard Anvil Login form. If the user is recognized by the details they entered (email and password), then it allows them to proceed to the main form of the app.

Is it possible for a malicious user to intercept this code on line 17 in the browser and simply set:

user = True

If they manage to do this, it will open the Main form of the app.

I know how to do user permissions through role assignment in server code when I return data table rows belonging to specific users or admins. For example:

if user['email'] == 'john.smith@example.com':
    return app_tables.secret_table.client_readable()

So I won’t be returning any confidential data table rows to unauthorized users, but I still don’t want to grant anyone access to the other forms on my app. So my basic questions is, can the login form be bypassed as mentioned above? If so, how would I allow a form to be opened from server side code?

2 Likes

The short answer here is yes. As per the docs, client code (that executes in the browser) can be manipulated. Server code is secure. Hence you should always validate access (and data for that matter) on both the client and server. It looks like you already do this on the server.

I am not sure that there is a way to prevent access to form code … perhaps others have some options here.

I wonder if there could be a way to control access via a redirection to a secure app once the user has logged in ?

If you think about it though, you could probably build everything so that without server cooperation the forms would simply be a useless array of meaningless buttons.

What is your reason to prevent access to form code if there is no data provided? If you edit your code to manually bypass line 17’s check, what does the app look like?

I guess the question is as long as no data is provided (ie using the server to control what is presented) are the forms valuable?

As a side note, you could consider putting line 17 in a while loop to constantly represent the login form if login fails.
Something like:

while not anvil.users.get_user():
   user = anvil.users.login_with_form(allow_cancel=False)

However this will override your ability for users to continue without logging in (apart from editing the form code).

The question comes more from curiosity than an actual need to protect the blank forms. I think giving malicious users as little insight as possible is always valuable.

Unless someone else has some input, I’ll keep designing the app as you mentioned: “… build everything so that without server cooperation the forms would simply be a useless array of meaningless buttons.”

I can’t think of any way to prevent users from seeing that. Anything which you return can be seen. You should also know that users can directly jump to any form they want using the javascript console.

If you do not want users to see a data, never keep it on the client-side. Only return them through server functions after checking if a user is allowed to access it or not.

3 Likes

That goes for code as well. For example, it may seem wise to put a long calculation on the Browser, but if its algorithm is proprietary…

1 Like

Don’t forget that, if your form has the code to dynamically create the UI, a malicious user will be able to see what your code is able to create. So trying to obfuscate the UI or to build it dynamically as late as possible (as opposed to making a form in the IDE) will only delay the malicious user’s success by a few minutes.

The only way to hide your UI would be for the server to serve the UI as chunks of HTML rendered on the server side (which would defeat a good part of the purpose of using Anvil) or for the server to serve information about both the UI and the data, and have the form building the UI based on the instructions coming from the server. You would create your own scripting language to build the UI.

It would require too much effort, not worth for my apps. I’m happy with leaving the 99.9% of users without access to sensitive data and UI, and leave the remaining 0.1% of hackers with the access to the UI.

1 Like