Black Lives Matter. Please consider donating to Black Girls Code today.

How to use basic authentication to solve the growing situation of new users

In my dash app,new users will increase every day,so I need restart app server to update username_password_list.How to use basic authentication to solve the growing situation of new users without restart service,thanks

1 Like

I am looking for the solution to this as well.
How to update VALID_USERNAME_PASSWORD_PAIRS without restarting the service? Thank you!

Actually, if hot reloading can solve in production that would work well too. How to do that?

Off the top of my head if you use dash-auth:

you could subclass the dash_auth.auth.Auth class to pull the authorized users from an external store/file at each 1st authentication attempt.

@Batalex Thank you! But that external store/file is also being updated. So, how to continue authentication without restarting the server?

Sorry, maybe I was not clear enough.

Let us say that users name & password are stored in a simple .json file. The idea is to read this file for each 1st authentication attemp so that if you add users to your file they will be authorized.

From dash_auth.basic_auth we can make a few adjutements:

class UpdatedBasicAuth(Auth):
    def __init__(self, app, filename:str):
        Auth.__init__(self, app)
        self._source = filename
        self._users = {}

    def is_authorized(self):
        header = flask.request.headers.get('Authorization', None)
        if not header:
            return False
        username_password = base64.b64decode(header.split('Basic ')[1])
        username_password_utf8 = username_password.decode('utf-8')
        username, password = username_password_utf8.split(':')
        return self._users.get(username) == password

    def login_request(self):
        # let's update our known users
        with open(self._source, "r", encoding="utf-8") as f:
            self._users.update(json.load(f))

        return flask.Response(
            'Login Required',
            headers={'WWW-Authenticate': 'Basic realm="User Visible Realm"'},
            status=401)

    def auth_wrapper(self, f):
        def wrap(*args, **kwargs):
            if not self.is_authorized():
                return flask.Response(status=403)

            response = f(*args, **kwargs)
            return response
        return wrap

    def index_auth_wrapper(self, original_index):
        def wrap(*args, **kwargs):
            if self.is_authorized():
                return original_index(*args, **kwargs)
            else:
                return self.login_request()
        return wrap

Of course you may want to change things a bit, depending if you want to remove authorized users etc.

1 Like

Wow! Thank you! I will try this. As of now, my approach has been to reload the gunicorn workers. But I do not want to do that as it might be dangerous. Gonna update here.

Thank you so much! It works.