Tres Seaver
2009-05-08 396eef1c9a9231904723dc4e976f6e2969ff7da2
commit | author | age
4a8c36 1 import binascii
CM 2
3 from paste.httpheaders import WWW_AUTHENTICATE
4 from paste.httpheaders import AUTHORIZATION
5 from paste.httpexceptions import HTTPUnauthorized
6
7 from zope.interface import implements
8
cb5426 9 from repoze.who.interfaces import IIdentifier
CM 10 from repoze.who.interfaces import IChallenger
4a8c36 11
CM 12 class BasicAuthPlugin(object):
13
c51195 14     implements(IIdentifier, IChallenger)
4a8c36 15     
d85ba6 16     def __init__(self, realm):
4a8c36 17         self.realm = realm
CM 18
c51195 19     # IIdentifier
CM 20     def identify(self, environ):
4a8c36 21         authorization = AUTHORIZATION(environ)
CM 22         try:
23             authmeth, auth = authorization.split(' ', 1)
7dfea7 24         except ValueError: # not enough values to unpack
40a968 25             return None
4a8c36 26         if authmeth.lower() == 'basic':
CM 27             try:
28                 auth = auth.strip().decode('base64')
7dfea7 29             except binascii.Error: # can't decode
40a968 30                 return None
4a8c36 31             try:
CM 32                 login, password = auth.split(':', 1)
7dfea7 33             except ValueError: # not enough values to unpack
40a968 34                 return None
7dfea7 35             auth = {'login':login, 'password':password}
CM 36             return auth
4a8c36 37
40a968 38         return None
4a8c36 39
c51195 40     # IIdentifier
CM 41     def remember(self, environ, identity):
42         # we need to do nothing here; the browser remembers the basic
43         # auth info as a result of the user typing it in.
44         pass
45
46     def _get_wwwauth(self):
47         head = WWW_AUTHENTICATE.tuples('Basic realm="%s"' % self.realm)
48         return head
49
50     # IIdentifier
51     def forget(self, environ, identity):
52         return self._get_wwwauth()
53
54     # IChallenger
55     def challenge(self, environ, status, app_headers, forget_headers):
56         head = self._get_wwwauth()
4daaea 57         if head[0] not in forget_headers:
c51195 58             head = head + forget_headers
CM 59         return HTTPUnauthorized(headers=head)
7dfea7 60
97cfa2 61     def __repr__(self):
396eef 62         return '<%s %s>' % (self.__class__.__name__,
TS 63                             id(self)) #pragma NO COVERAGE
97cfa2 64
515c69 65 def make_plugin(realm='basic'):
d85ba6 66     plugin = BasicAuthPlugin(realm)
CM 67     return plugin
68