Announcing Dash Bio 1.0.0 🎉 : a one-stop-shop for bioinformatics and drug development visualizations.

Get username for authenticated user with Dash Basic Auth

I am trying to use Dash Basic Auth for my app.

Is there a way I can get the username for the authenticated user within the app?

I would like to use that to customize how the app works based on their username.

Thanks!

With Basic Auth you should use cookies, flask.session or Flask Session extension (to store it server side). Remember to clean session on logout.

Here’s where the username and password are decoded in the dash-auth package: https://github.com/plotly/dash-auth/blob/6550439d67474c3317ad213ca688d5a5f8ace257/dash_auth/basic_auth.py#L12-L20. You should be able to use similar code inside your callback to decode the flask.request.headers.get('Authorization', None) header.

1 Like

Hello, could you pls share a more detailed example for authentication in multi page app?

1 Like

hey @chriddyp , thx for the great work with dash.

Just like @zxyzxy I tried to fiddle with that but had some issues, an example of how to access that info wld be great.

I am doing an app with several tabs, but some shld require user privilege, hence, i wld like to be able to identify the user which is signed up.

Thx again,

E Pattaro

Edit:
I just changed

    username_password_utf8 = username_password.decode('utf-8')
    username, password = username_password_utf8.split(':')

to:

    username_password_utf8 = username_password.decode('utf-8')
    username, password = username_password_utf8.split(':')
    self._username = username

in dash_auth/basic_auth.py
and it worked okay (access the user’s username through auth._username in the dash app)

2 Likes

Hi @epattaro, thx for the proposed solution!
Could you please share an example how do you call auth._username in the dash app?

I did the changes to dash_auth/basic_auth.py as you have proposed but when I call auth._username from application I receive: AttributeError: 'BasicAuth' object has no attribute '_username'.
That makes sence because variable is not set yet in a start, but will be set later on during runtime.

Looks like I have missed something important here…

Update:
Looks like I got the idea. In dash user guide example app is already processed before authorization check and is just shown after is_authorized method confirms the pair.
To make layout depends on user id, it should be included in callback part…

Roman

hi @epattaro
I’m also trying to do something similar. I want to store the username input in a variable. How did you end up retrieving the username input?

hi @blsmith,

could you share with me how you were able to retrieve the username from the basic authentication process? thanks!

I easily made it work the same idea like this:

  1. In BasicAuth’s construction function, def __init__, add the field _username by adding the line
    self._username = ''
    (I don’t know whether this one is crucial, but I vaguely thought one must or should add class fields in the initializer in python)

  2. Indeed add the self._username = username that @epattaro above suggested

  3. Finally, to access it from your app, and to avoid @blsmith’s ‘no attribute’ error: Make sure you try to get the attribute from your BasicAuth instance, not from the raw class itself! So, assuming you use in your app
    auth = dash_auth.BasicAuth(app,VALID_USERNAME_PASSWORD_PAIRS)
    simply later access it with, e.g.
    myauthenticateduser = auth._username.
    Crucially, as @blsmith mentioned, be careful about timing: while the authentication is still going on, the app code is already being processed in the background, so make sure the app accesses the _username field maybe only e.g. after all is properly loaded, in genuine ‘run time’ (e.g. in a callback), rather than e.g. directly after the auth = dash_auth.BasicAuth(...) entry.

Btw, if anyone is also keen to not let your app know the entire raw unhashed password list, I have implemented a basic solution to this; I’m neither authentication specialist nor python pro and don’t know whether there are any relevant downsides to this but it’s simple and I’m happy to share if anyone interested.

3 Likes

Btw, if anyone is also keen to not let your app know the entire raw unhashed password list, I have implemented a basic solution to this; I’m neither authentication specialist nor python pro and don’t know whether there are any relevant downsides to this but it’s simple and I’m happy to share if anyone interested.

I am interested to check it out. Thanks!

I added it to github: https://github.com/fhabermacher/public_dash-auth_ext . You pass it the list of usernames-hashes, as well as the (constant) salt used in the hashing (you find in my edited basic_auth.py the way to create the corresponding hashes from raw passwords). Let me know if issues!
[post now reposeted, to be reply instead of separate post]

1 Like

Is there a callback that can be invoked once the user is authorized using basic auth? For example I’d like to display Hello John once John has been authenticated. The layout as some on this thread have mentioned is rendered prior to the authentication is completed.

As is pointed out above, auth._username will provide a password but you can’t access it until the app is loaded so make sure a callback initiates the request

I think the way from epattaro is a bit risky, as the username is written as a global variable (as the authentication object is shared). If multiple users are logged in it is unclear to whom it belongs. However, I might be wrong here so correct me if so. Anyway, another solution that works is as follows. You can actually use Flask.request to get the username from the header. Just import it and access it by calling request.authorization[‘username’] in a callback. You can find a minimal working example here.

Cheers Chris

1 Like

Thank you all for sharing, I have tried this solution but only I can access the username inside a callbacks. I would like to change the layout of the app according to the user who logs in, for example giving more functionality to one user than to the other. do you know if this is possible?