Multi user app - secure personalized pages

So I’m trying to work out how to use the Basic Authentication that Dash provides to keep track of which user logged in and store that information so I can display a page with customized information but I am uncertain how Dash handles things.

From the looks of it, the basic auth gets called on page load and the username can be stored in a variable but as it’s not in the actual app yet it would be stored as a global variable. Wouldn’t that get altered again then when another user starts using the page?

One solution I’ve been thinking of is to just start the app normally with two main divs. One with a login form and the rest hidden. Upon entering the right user/pass combo, the login form becomes hidden, and the rest of the page is unhidden with the contents dynamically created based on the username. The username would just be stored in a hidden intermediate value div.

This seems to be seemingly easier to implement and allow multiple users to use the same instance of the app with their own pages displayed. I am however concerned that there may be some inherent security risks that I am unaware of.

For security I’m planning to:
Store the user info in an sql database. Username will be in one table, a cryptographically-secure-pseudo-random salt in another database, and a hashed version of the combo of the password+salt in the same database/table as the username. The password provided by the user attempting to login will be combined with the salt, hashed, and then compared to the stored hashed, password+salt combo. The login info for the sql server itself will be stored in a separate config file so all the app sees are variables.

I’ll be doing my best to check the inputs for SQL injection attacks as well.

Are there any things I haven’t thought of or reasons why this approach just wouldn’t work?

5 Likes

I’m looking to implement this in the near future but am unsure if this is the best way to proceed as I’m still pretty new to development. Perhaps someone more experienced like @chriddyp or @nedned can shed some light on the matter and as to why the method used in BasicAuth may be more desirable or highlight some fatal flaw in the method I’ve outlined.

I’m afraid I don’t have any experience with auth stuff and Dash, so can’t offer any suggestions sorry!

Your solution sounds like a good one. We’ve worked with a client on a similar setup. Rather than using a separate div, userIDs were passed via the URL, and the entire app operated within an iframe, with JS handling the encryption. It worked beautifully, and yours should be very similar (except with the encryption being handled within python)

Hey, great to hear from you guys!

@charleyferrari I had looked into passing the userID to the URL but I read about some vulnerability doing that so I looked for something else. Now I’m not sure if the way you have implemented it would be vulnerable, but the scenario I read about went something like this:

If one user copy/pastes their custom URL and sends it to another person and then the other person just has to wait for the first person to be logged in at some point and is then able to access the page with the first person’s URL and the server thinks they’re logged in already and gives the second person access.

Something in the category of session fixation/session management vulnerabilities.

Again, it’s totally possible that what you did was fine. I just chose to look for a different way as with my limited understanding of things as a developer I wasn’t sure if I could implement it correctly.

For anyone who finds this thread later like I did, I built a template to allow for multi-user authentication, each with a dedicated view based on the user that’s logged in.

I hope this will help others who had difficulty finding a good solution to this problem. The key here is to use Flask as the base app instead of Dash and run dash as an embedded application. This will allow you to utilize the authentication packages from Flask instead of trying to build a solution within Dash.

3 Likes

Hi @ seanmajorpayne,
in your method is not possible to use @Callbacks and filters? Only static dashboard?
https://community.plotly.com/t/python-plotly-dash-with-flask-login-how-to-properly-place-callback