flask-httpauth: How is get_password decorator mean

2020-07-22 19:32发布

问题:

I wonder if anyone has used this flask extension to simplify the http-basic-auth.

Basically I don't understand this example:

users = {
    "john": "hello",
    "susan": "bye"
}

@auth.get_password
def get_pw(username):
    if username in users:
        return users[username]
    return None

The get_password decorator seems like to return the clear password of the given user and if it matches to the one the user has provided, then the authorization will be granted.

But no one should have access to the clear passwords of the users in first place. I usually send the clear password and username to the backend, hash the password and compare it to the existing hashed password in the database.

How has this been envisioned?

UPDATE:

The link to the docs sheds some more light. since there a second decorator required to achieve this:

@auth.hash_password
def hash_pw(username, password):
    get_salt(username)
    return hash(password, salt)

Literally the rule is get_password(username) == hash_password(password)

The way I understand this to work is get_password returns the user's hashed password in the database, which needs to be equal to the currently hashed password defined in hash_password method.

The problem is though, I am using sha256_crypt from passlib.

def verify_password(password, hashed_password_in_db, password_hash_version):
    if password_hash_version == 1:
        return sha256_crypt.verify(password, hashed_password_in_db)
    return False 

In here you can't hash the given password and compare it to the stored hashed password. I have to use the method sha256_crypt.verify(password, hashed_password_in_db), which returns false or true.

Is there a way to achieve this or do I have to roll my own custom solution? Thanks

回答1:

I'm the developer of Flask-HTTPAuth. Sorry I missed this question.

I just released a new version that gives you a way to use your custom function to verify a password. Instead of defining get_password and hash_password callbacks you can now use a verify_password callback that leaves the password verification completely up to you. For example, in your case you would use this callback:

@auth.verify_password
def verify_password(email, password):
    return check_auth(email, password)

I hope this helps!



回答2:

I just realized this questions remained unanswered.

I am sure the project flask-httpauth is great for cases, where you intend to use md5 hash.

But as in my case, if you use sha256_crypt you can't make it work with this extension, due the way it works. (See my updated question)

What I ended up doing is to use this snippet written by the maker of flask.

The method check_auth is exactly what I needed as it returns boolean.

In my case I have defined it like this to make it work with sha256_crypt

def check_auth(email, password):
    em_login_provider = ndb.Key('AuthProvider', get_provider_id(constants.EMAIL, email)).get()        
    if em_login_provider and em_login_provider.active:
        user = em_login_provider.user                
        if user and verify_password(password, user.password_hash, user.password_hash_version):
            return True
    return False