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

That could certainly be an interesting feature to add! I’ll open an issue on the repo. It would require using Twilio or something similar for SMS, or a TOTP/HOTP integration.

edit: issue is here

Or you could use an email system. That’s how I perform my MFA.

It’s also interesting, because if you log someone in, you need to know whether or not they are verified completely (MFA successful). You need to make sure, that if they are in between that they can’t access the user’s info unless MFA successful.

If they aren’t verified, you’d reset to the login route again.

Using things like google, Microsoft, etc would handle this for you, but requires registering your app with those services typically.

1 Like

Right - it would allow either phone or email, there isn’t any phone service integrated right now.

I’m thinking for semi-verified users you can do

if  user.is_authenticated and user.is_verified:
    login_and_allow_access()
else:
    ...

without worrying about state management.

I definitely have built the provider integrations before but it’s quite a bit more complicated than what I’d want to provide (or support) for beginner- to intermediate-level coders who are using these batteries-included answers.

I guess you wont know until you try.

I have different routes for login and login/verify. But I guess it could all be handled by the same page, so it wouldnt be an issue inside dash.

1 Like

Russell,

Thank you very much for sharing, I was trying to find something similar and I didn’t think so, I was using standard Dash authentication, it was horrible, with what you shared, I implemented it and I thought it was great. Thank you very much. I only used the standard login, I share how it turned out. Thank you one more time.

ceu

3 Likes

Major update - Dash Pages and granular layout authentication

@all, I’ve launched a major upgrade and update to dash-auth-flow. Most of the changes are updates which bring dash-auth-flow into the Dash 2.0+ era - Dash Pages, consolidated imports, etc. It also adds a guide for running locally and deploying to Fly.io, a proper .env file structure, and smooth transitions between login and logout.

Each layout function can be explicitly unprotected by adding the @unprotected decorator to the layout function. All layout functions are protected by default.

from utils.auth import protect_layouts

app = Dash(__name__,...)
protect_layouts(default=True) # require authentication on all pages layouts by default

...
import dash
from utils.auth import unprotected

dash.register_page(__name__, path="/unprotected")

@unprotected
def layout():
    """This layout function will be accessible to unauthenticated users."""
    return html.Div("Page Content")

I think this update will make dash-auth-flow much more useful and accessible for all Dash users, as Dash pages is a significant improvement over previous routing designs.

The example is deployed and moved from Heroku to Fly.io; check it out at https://dash-auth-flow.fly.dev

See the updated code at GitHub - russellromney/dash-auth-flow: Batteries-included authentication flow with Dash.

In a future update, I’m going to add MFA via TOTP authenticator apps (Google Authenticator, Authy) and SMS (with an SMS provider), and add a system for arbitrary email/sms providers. Let me know if these updates will be of interest to you and if you’d like to sponsor that development.

6 Likes

HI @russellthehippo,

Would you be interested in exploring the possibility of implementing a user control function for password management?

This feature would entail two aspects:

  1. Forcing Password Change on First Login: Users would be required to change their password when they log in for the first time.

  2. Password Expiry Redirect: If a user’s password hasn’t been updated in a specified period, like 180 days, they would be redirected to the password change page after logging in.

2 Likes

Sounds interesting.

  1. Forcing Password Change on First Login
    I’m assuming this is a situation where the user is a password for their email? in this case it will work to add a field to the user, first_login_pw_changed_at as an integer timestamp, None by default. In the before request auth function, redirect the user to the change password screen or send a reset password link if that is None. When they change their password and that field is None, add the timestamp in the field and and redirect to login
  2. Password Expiry Redirect
    This could be also solved with a field on the user record pw_updated_at or pw_expires_at which is a timestamp updated at each password changed. The before_request auth function checks if that was 180 days ago, or if the expiry has passed - if so, send a reset password link or redirect to the change password page

The implementations for both of these are fairly easy - I’d love a pull request with the functionality and a .env flag for these features if you’re interested and beat me to it! Otherwise I’ll do it as part of the MFA update

1 Like