Instant authentication against an existing web application
I was thinking today about the problem of querying an existing authentication database from a new application—exactly the kind of thing web services are useful for. Then I realised that any web application protected by HTTP Basic authentication already provides a standard API against which queries can be run. Here’s the Python code to do exactly that:
def auth_against_url(url, username, password):
import urllib2, base64
request = urllib2.Request(url)
b64 = base64.encodestring('%s:%s' % (username, password))[:-1]
request.add_header('Authorization', 'Basic %s' % b64)
try:
urllib2.urlopen(request)
except urllib2.HTTPError:
return False
return True
To check a username and password against an existing application’s user database, just call the above function with the URL of a page within the existing application as the first argument. The function returns True if the username and password are valid, and False otherwise. It doesn’t get much simpler than that.
A nice side effect of using Python’s standard library modules is that they transparently support HTTPS, so authentication can take place over an encrypted channel provided the target application supports it.
Ian Bicking - 15th July 2004 01:26 - #
Chui Tey - 15th July 2004 01:47 - #
Matt - 15th July 2004 02:19 - #
A good simple solution :).
Just a quick addendum though for any implementers: be amindful of your network topology. If you're running this to a server on your private LAN or via HTTPS you're probably OK. OTOH, if you're authenticating against a public server remember that anyone on an intermediate host with a packet sniffer can retrieve both the username and password. In that case consider challenge/response auth protocols; HTTP 1.1 can do it via "Digest" authentication, or the ATOM API also allows it.
Angus - 15th July 2004 06:09 - #
Beat Bolli - 15th July 2004 13:42 - #
anders - 16th July 2004 16:58 - #
If you do a HEAD request (as opposed to GET) you won't get the body, just the status code.
Anyway, I was just reminded that this technique can cause problems in practice. If your remote machine goes away, you can do weird things to your server. This depends a lot on the server, whether it is threaded or multi-process, whether it kills processes that take too long to return, how it deals with sockets, etc. But in Python the failure is not too elegent -- usually just a hung thread or process. If you are using this in mod_python, this could effect your entire system. (I haven't tried it, but I can confirm it will effect an entire Zope server.)
I've come to believe that it is best to keep things like web requests out of a server process. It's better to have another process which can more easily be managed (killed, etc) with a queue of jobs.
In this case a queue doesn't really work, as you can't log someone in until you get a response, but it's still easier to control something like an XMLRPC request (or other reliable IPC) to a dedicated authenticating process, and let it do the actual web requests. And, of course, cache -- caching is very important here, because HTTP Basic authentication is reauthenticated for every page that is hit.
Ian Bicking - 16th July 2004 21:14 - #
Mark Eichin - 19th July 2004 06:51 - #
Anthony - 22nd July 2004 20:59 - #