Search code examples
web2py

Custom bcrypt validation with Web2py


I have an auth.login() form for the purpose of login.

What I want to achieve is: when I enter a username and a password, the validator takes the password and computes its bcrypt hash and compares it with the hash stored in a MySQL dB.

Now, thanks to Anthony, I understand that the CRYPT() method needs to be modified.

What I have so far in db.py:

def check(value):
//do bcrypt logic here

class CUSTOM_CRYPT:
    def __init__(self, error_message='error'):
        self.e = error_message
    def __call__(self, value):
        if check(value):
            return (value, None)
        return (value, self.e)

custom_auth_table.password.requires = [IS_STRONG(min=5, special=0, upper=0, number=0),CUSTOM_CRYPT()]

This gives me the error:

Validation error, field:password <__restricted__.CUSTOM_CRYPT instance>

How can I make this work? Thanks!

My MySQL database (auth-user table) just contains entries such as:

ID | Username | Password
1  | tom93    | $2b$12$5vkWB4HzKsOqvbII2IV9m.MqxLi9/fqrjbzyiett.a.6iQEf/p6Su
2  | jan88    | $2b$12$eovbX99oTIvz6ItgVsqI4e6o9KJuILHzZxnF.EVM0qbAU1xFrBi2.

Solution

  • No, you don't want the custom validator to do the checking (it doesn't know what to check against -- that is handled via the web2py Auth code). Rather, the validator should simply be used to transform the incoming cleartext password into the password hash that you want to store in the database. The workflow is as follows:

    • At registration, the submitted password goes through the validator and its output (the hashed password) is what gets stored in the database.
    • At login, the submitted password goes through the validator and is hashed. web2py's Auth login method then compares this hashed password to the value stored in the database, rejecting the login if they don't match.

    So, you want something like this:

    def bcrypt_validator(password):
        return (bycrpt(password), None)
    
    custom_auth_table.password.requires = [IS_STRONG(min=5, special=0, upper=0, number=0),
                                           bcrypt_validator]
    

    where the bcrypt function (which you must define) generates the hash that you want to store in the database.