Show and Tell: full authentication flow example, dash-auth-flow

dash-auth-flow

Batteries-included authentication flow in Dash.

This has landing pages and functions to run the entire authentication flow:

  • home
  • login
  • logout
  • register
  • forgot password
  • change password
  • view and edit profile details & password

This uses flask-login on the backend, using some code from the very useful dash-flask-login. Data is held in users.db .

pip install pipenv 
pipenv install --ignore-pipfile 
pipenv shell 

python create_tables.py # test@test.com / test 
python app.py

UI experience GIF

Example of logout screen:

Notes:

  • this uses MailJet as the email API. You need a free MailJet API key
  • your send-from email and API key/secret need to be entered in config/keys.py
  • if you want to use something else, change the send_password_key function in utilities/auth.py
  • add pages in pages/ .
  • the app’s basic layout and routing happens in app.py
  • app is created and auth is built in server.py
  • config is in utilities/config.txt and utilities/config.py
14 Likes

I like what I made here, but the problem remains that each content page will start to load, with potentially sensitive information, regardless of whether a user is authenticated.

So you have to repeatedly catch all the authentication errors in page callbacks, which is annoying. I’m going to figure out how to avoid this.

Example at http://dash-auth-flow.herokuapp.com/login

An even simpler version of this is at https://github.com/russellromney/basic-dash-auth-flow

It just uses the Flask session object to validate or invalidate the user’s session, server-side.

7 Likes

hi,
goog job.

could you tell how can I implement this kind of stuff, in multi layout app, there is a nav bar, and on the nav bar are located hrefs to the layouts.

Great work Russel!!! Congratulations !
I will try to implement it.

Hey, really great work. Any idea on how to return the user ID into the app if the user is authenticated?

The user’s ID will be in the current_user Flask-Login object. See the user model definition in dash-auth-flow: https://github.com/russellromney/dash-auth-flow/blob/df989323b4f253582773685afb7f2347256de6ce/utilities/auth.py#L22

from flask_login import current_user
# some code
x = current_user.id

The dash-auth-flow example implements all this with navbar, multi pages, etc.

Hi, thank you for the fast reply. I am very new into dash and flask, so the dash_auth_flow looks very complicated tome at the moment. I tried to use the current_user from the flask_login in the simple example. I wanted to show the user name on the homepage if a user authentification was sucessful. So instead of writting html.H2(‘Homepage’) I tried html.H2(current_user). However I always get the error message:

AttributeError: ‘Flask’ object has no attribute ‘login_manager’

Any idea what I am doing wrong?

Okay. Ignore the current_user stuff for now as you are new to it (watch https://www.youtube.com/watch?v=2dEM-s3mRLE for an overview and do the tutorial at https://blog.miguelgrinberg.com/post/the-flask-mega-tutorial-part-v-user-logins for hands-on practice).

Try this: put the user’s email into the Flask session variable. In the login page callback function, when the function doessession['authed']=True, add the following code, replacing with the variable containing the user’s email:

session['email'] = the_user_email

Then in the home page, you can write a callback function that returns session['email'] to the children property of the html.H2 where you want it.

Generally, you should learn about Flask and Dash a lot more before you use authentication. If you need authentication, you need to understand the framework well to make sure it is safe.

2 Likes

Great work here! May I know if the simple version of this is workable with a multipage app (I do not need to implement the full version since it is a basic app)? I tried to implement it but having issues preventing direct access when typing the full URL.

It works with a full app. In your routing function, make sure to check whether the user is authed before returning the page, and return the login page if not.

Thanks for the reply Russell.

Do I need to add any codes to my multipage pages when doing this? Or this simplified version just has to make sure that the app.py callback is based on what you mentioned (meaning I only need to edit my multipage app app.py for this to work)?

Appreciate a demo if you have the time for it and will certainly help new Dash users like me.

Hey russellthehippo
Can you guide me how we can deploy it on heroku, sines it required run create_table.py firstly to create database but on heroku we can only give one file as our index or main file.

Run create_tables.py locally and save the sqlite3 database as part of the application that you upload to Heroku. That flat file that will work on Heroku.

3 Likes

instead of baking authentication and authorization inside the app itself, consider deploying an identity-aware proxy in front of your app, that would handle user authentication by integrating with your authentication provider (i.e. Google, Microsoft, Okta, Auth0) AND authorization (which users are allowed). There are open source, on-premise and cloud-managed solutions, depending on your deployment strategy.

i.e. check out this example https://github.com/gwrun/tutorials/tree/main/plotly-dash/docker-compose

I just git cloned your repo and noticed that config.txt is in the main directory and not in folder utilities.
Also, in Pycharm there is a read squiggly under [database] and = in config.txt.

amazing example. Thank you very much for sharing!!!

Hi @russellthehippo, are you interested in adding multifactor authentication? Like Google Authenticator and others based on TOTP or HOTP.

1 Like