Search code examples
pythonbasic-authenticationcherrypy

Basic Auth for CherryPy webapp


I'm trying to create a very basic cherrypy webapp that will ask the user for a username and password before the first (and only) page loads. I used the example set forth in CherryPy docs here: http://cherrypy.readthedocs.org/en/latest/basics.html#authentication

Here's my specific code for wsgi.py:

import cherrypy
from cherrypy.lib import auth_basic
from myapp import myapp

USERS = {'jon': 'secret'}

def validate_password(username, password):
    if username in USERS and USERS[username] == password:
       return True
    return False

conf = {
    '/': {
       'tools.auth_basic.on': True,
       'tools.auth_basic.realm': 'localhost',
       'tools.auth_basic.checkpassword': validate_password
    }
}

if __name__ == '__main__':

    cherrypy.config.update({
        'server.socket_host': '127.0.0.1',
        'server.socket_port': 8080,
    })

    # Run the application using CherryPy's HTTP Web Server
    cherrypy.quickstart(myapp(), '/', conf)

The above code will get me a browser user/pass prompt however when I click OK to the prompt, I get the following error:

Traceback (most recent call last):
  File "/usr/local/lib/python2.7/site-packages/cherrypy/_cprequest.py", line 667, in respond
    self.hooks.run('before_handler')
  File "/usr/local/lib/python2.7/site-packages/cherrypy/_cprequest.py", line 114, in run
    raise exc
TypeError: validate_password() takes exactly 2 arguments (3 given)

I'm not sure where it thinks it's getting that 3rd argument from. Any thoughts? Thanks!


Solution

  • From the documentation of cherrypy

       checkpassword: a callable which checks the authentication credentials.
            Its signature is checkpassword(realm, username, password). where
            username and password are the values obtained from the request's
            'authorization' header.  If authentication succeeds, checkpassword
            returns True, else it returns False.
    

    So your implementation of checkpassword has to follow the same api which is: checkpassword(realm, username, password), and what you've show us is missing the first parameter - realm.