[Welcome] [TitleIndex] [WordIndex

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 import get_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):
    get_response().set_header('WWW-Authenticate', 'Basic realm="%s"' % self.realm)
    return AccessError.format(self)

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 ensure_access():
    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

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


Links


CategoryCookbook


2010-09-22 22:14