|
⇤ ← Revision 1 as of 2005-06-15 11:20:08
Size: 2538
Comment:
|
← Revision 2 as of 2009-12-25 07:14:35 ⇥
Size: 2538
Comment: converted to 1.6 markup
|
| Deletions are marked like this. | Additions are marked like this. |
| Line 46: | Line 46: |
| Some info/code on handling Basic and Digest `Authentication` headers would be super useful too. -- RyanTomayko [[DateTime(2004-09-28T00:22:28)]] | Some info/code on handling Basic and Digest `Authentication` headers would be super useful too. -- RyanTomayko <<DateTime(2004-09-28T00:22:28)>> |
| Line 68: | Line 68: |
| -- Jeremy Field [[DateTime(2005-05-04T08:16:24)]] | -- Jeremy Field <<DateTime(2005-05-04T08:16:24)>> |
| Line 74: | Line 74: |
| * '''RFC 2617 - HTTP Authentication: Basic and Digest Access Authentication''' [[BR]] | * '''RFC 2617 - HTTP Authentication: Basic and Digest Access Authentication''' <<BR>> |
| Line 77: | Line 77: |
| * '''RFC 2616 - Hypertext Transfer Protocol -- HTTP/1.1''' [[BR]] | * '''RFC 2616 - Hypertext Transfer Protocol -- HTTP/1.1''' <<BR>> |
Problem
The quixote.errors.AccessError exception results in a HTTP 403 Forbidden response. This response is desirable when using FormBasedAuthentication but should only be used after responding with a 401 Unauthorized when using HTTP's native authentication mechanisms.
Solution
Create a variation on AccessError that results in a 401 Unauthorized response instead of a 403 Forbidden response:
from quixote.errors import AccessError
class UnauthorizedError(AccessError):
"""The request requires user authentication.
This subclass of AccessError sends a 401 instead of a 403,
hinting that the client should try again with authentication.
"""
status_code = 401
title = "Unauthorized"
description = "You are not authorized to access this resource."
def __init__(self, realm='Protected', public_msg=None, private_msg=None):
self.realm = realm
AccessError.__init__(self, public_msg, private_msg)
def format(self, request):
request.response.set_header('WWW-Authenticate', 'Basic realm="%s"' % self.realm)
return AccessError.format(self, request)When an UnauthorizedError is raised, a 401 Unauthorized response is sent with the required WWW-Authenticate headers. You should be able to use this anywhere AccessError may be used as follows:
def _q_access(request): raise UnauthorizedError(realm='Foo Realm')
Most browsers pop up a little username/password dialog containing the name of the Realm specified.
Discussion
Some info/code on handling Basic and Digest Authentication headers would be super useful too. -- RyanTomayko 2004-09-28 00:22:28
Updated for Quixote 2.0:
def format(self):
get_request().response.set_header('WWW-Authenticate', 'Basic realm="%s"' % self.realm)
return AccessError.format(self) def _q_access(self):
r = get_request()
ha = r.get_environ('HTTP_AUTHORIZATION',None)
if ha:
auth_type, auth_string = ha.split()
login, passwd = b64decode(auth_string).split(':')
...process authentication...
else:
raise UnauthorizedError-- Jeremy Field 2005-05-04 08:16:24
Links
RFC 2617 - HTTP Authentication: Basic and Digest Access Authentication
http://www.ietf.org/rfc/rfc2617.txtRFC 2616 - Hypertext Transfer Protocol -- HTTP/1.1
http://www.w3.org/Protocols/rfc2616/rfc2616.html
