basic auth tool, password expiration, and HTTPRedirect.

210 views
Skip to first unread message

christophe...@yahoo.com

unread,
Jun 20, 2007, 3:14:15 PM6/20/07
to cherrypy-users
I am currently using CherryPy's basic_auth tool. I would like to add
password expiration into the mix so that when a user provides a
username / password combination, my code is called to check whether
the password has expired. If it has, I would like to throw an
HTTPRedirect.

More generally, I would like page handlers to know which username they
are being used from.

Is that possible?

Chris Marshall

Sylvain Hellegouarch

unread,
Jun 20, 2007, 3:17:57 PM6/20/07
to cherryp...@googlegroups.com
christophe...@yahoo.com a écrit :

cherypy.request.login

> Is that possible?
>

Everything is in life :)

- Sylvain

christophe...@yahoo.com

unread,
Jun 20, 2007, 3:23:28 PM6/20/07
to cherrypy-users

On Jun 20, 3:17 pm, Sylvain Hellegouarch <s...@defuze.org> wrote:
> christopherlmarsh...@yahoo.com a écrit :

Could you point me to an example of how to use it, or a write-up on
how it works?

Chris Marshall

Scott Chapman

unread,
Jun 20, 2007, 6:50:37 PM6/20/07
to cherryp...@googlegroups.com
>
>> Everything is in life :)
>>
>> - Sylvain
>>
>
> Could you point me to an example of how to use it, or a write-up on
> how it works?
>
Here's a new version of the auth handler that I've submitted to Robert
to include in the next CP release. It's a place to start in your quest:

Rather than passing in a dictionary of users, pass in a callable
function that does what you want. It will take care of calling the
function to auth a user, and it will pass in the username. Your auth
function should return a plaintext password which the auth mechanism
will use for comparing to the one supplied by the client. If you pass
back something that will never be matched (i.e. if the password has
expired), you should be running.

I haven't tested this to see what the behavior is if you passed back
None for a password and the user types in "None" as their password yet,
for instance. It has not been tested for security issues yet. YMMV.

Scott


import cherrypy
from cherrypy.lib import httpauth
import sha

def check_auth(users, encrypt=None):
"""If an authorization header contains credentials, return True,
else False."""
if 'authorization' in cherrypy.request.headers:
# make sure the provided credentials are correctly set
ah =
httpauth.parseAuthorization(cherrypy.request.headers['authorization'])
if ah is None:
raise cherrypy.HTTPError(400, 'Bad Request')

if not encrypt:
encrypt = httpauth.DIGEST_AUTH_ENCODERS[httpauth.MD5]

if callable(users):
try:
users = users() # expect it to return a dictionary
except TypeError:
password = users(ah["username"])
password = sha.new(password).hexdigest()
else:
if not isinstance(users, dict):
raise ValueError, "Authentication users must be a
dictionary"

# fetch the user password
password = users.get(ah["username"], None)

# validate the authorization by re-computing it here
# and compare it with what the user-agent provided
if httpauth.checkResponse(ah, password,
method=cherrypy.request.method,
encrypt=encrypt):
cherrypy.request.login = ah["username"]
return True

cherrypy.request.login = False
return False

Christopher Marshall

unread,
Jun 20, 2007, 7:37:04 PM6/20/07
to cherryp...@googlegroups.com
Thank you so much for that!  I can see exactly what's going on now with the users argument.

I could take a number of approaches at this point.  I may opt to pass in a function as the users argument that removes users whose passwords have timed out.  I could make that work without changing the check_auth function at all.

Chris Marshall


Chris Marshall

Christopher Marshall

unread,
Jun 20, 2007, 7:40:42 PM6/20/07
to cherryp...@googlegroups.com
I see what you are saying now, although I missed it at first.  cherrypy.request.login acts like a str which, when referenced inside of a page handler, is the username supplied to the basic_auth mechanism.

So, for example

def some_page_handler():
   print cherrypy.request.login

would, whenever someone hit the page with a browser, print to stdout the username  they had logged in as.

Thanks,

Chris Marshall

Sylvain Hellegouarch

unread,
Jun 21, 2007, 2:45:55 AM6/21/07
to cherryp...@googlegroups.com
I might be missing something but how is this different from what is
already done in CherryPy 3?

http://www.cherrypy.org/browser/tags/cherrypy-3.0.1/cherrypy/lib/auth.py

- Sylvain

Scott Chapman a écrit :

Scott Chapman

unread,
Jun 22, 2007, 2:38:24 AM6/22/07
to cherryp...@googlegroups.com
Sylvain,
The current version of auth allows you to pass in a dictionary to the
auth function. This is inefficient, meaning that you have to make a
dictionary of all users each time one needs to auth. Now you can pass
in a function, which receives the username as a parameter, and returns
that user's password, which the auth module uses for comparing to what
was submitted by the user.

It is backwards compatible with the existing auth library.

Scott

Sylvain Hellegouarch

unread,
Jun 22, 2007, 3:49:58 AM6/22/07
to cherryp...@googlegroups.com
Scott,

I get it indeed. Nicely done.

Christopher Marshall

unread,
Jun 22, 2007, 9:57:55 AM6/22/07
to cherryp...@googlegroups.com
Scott:
 
Wouldn't it be better to have the user(username) function return an encrypted password?
 
An application with a username/password database would typically not want to keep the plaintext passwords.
 
Chris Marshall 

Scott Chapman <scott...@mischko.com> wrote:

Sylvain,
The current version of auth allows you to pass in a dictionary to the
auth function. This is inefficient, meaning that you have to make a
dictionary of all users each time one needs to auth. Now you can pass
in a function, which receives the username as a parameter, and returns
that user's password, which the auth module uses for comparing to what
was submitted by the user.

It is backwards compatible with the existing auth library.

Scott

Sylvain Hellegouarch wrote:
> I might be missing something but how is this different from what is
> already done in CherryPy 3?
>
> http://www.cherrypy.org/browser/tags/cherrypy-3.0.1/cherrypy/lib/auth.py
>
> - Sylvain
>
> Scott Chapman a 飲it :

Sylvain Hellegouarch

unread,
Jun 22, 2007, 12:07:47 PM6/22/07
to cherryp...@googlegroups.com
See http://www.cherrypy.org/ticket/699

Fixed in 1682 for the current trunk.
Fixed in 1681 in the 3.0.X branch.

- Sylvain

Christopher Marshall a écrit :


> Scott:
>
> Wouldn't it be better to have the user(username) function return an
> encrypted password?
>
> An application with a username/password database would typically not
> want to keep the plaintext passwords.
>
> Chris Marshall
>

Sylvain Hellegouarch

unread,
Jun 22, 2007, 12:11:52 PM6/22/07
to cherryp...@googlegroups.com
Christopher Marshall a écrit :

> Scott:
>
> Wouldn't it be better to have the user(username) function return an
> encrypted password?
>
> An application with a username/password database would typically not
> want to keep the plaintext passwords.

You can return an encrypted password with whatever method of encryption
you need. By default the basic tool will use md5 internally. If you
prefer sha for instance you can set the "encrypt" argument of the tool
to callable that takes only one parameter, the password and will encrypt it.

Look at the unit test for that tool:
http://www.cherrypy.org/browser/trunk/cherrypy/test/test_httpauth.py

- Sylvain

Reply all
Reply to author
Forward
0 new messages