[Repoze-checkins] r728 - in repoze.pam/trunk/repoze/pam: . etc plugins
Chris McDonough
chrism at agendaless.com
Sat Feb 23 22:54:42 UTC 2008
Author: Chris McDonough <chrism at agendaless.com>
Date: Sat Feb 23 17:54:41 2008
New Revision: 728
Log:
Implement basicauth plugin.
Added:
repoze.pam/trunk/repoze/pam/plugins/
repoze.pam/trunk/repoze/pam/plugins/__init__.py (contents, props changed)
repoze.pam/trunk/repoze/pam/plugins/basicauth.py (contents, props changed)
repoze.pam/trunk/repoze/pam/tests.py (contents, props changed)
Modified:
repoze.pam/trunk/repoze/pam/etc/sample-config.ini
Modified: repoze.pam/trunk/repoze/pam/etc/sample-config.ini
==============================================================================
--- repoze.pam/trunk/repoze/pam/etc/sample-config.ini (original)
+++ repoze.pam/trunk/repoze/pam/etc/sample-config.ini Sat Feb 23 17:54:41 2008
@@ -1,4 +1,5 @@
[plugin:basicauth]
+# challenge and extraction
use = egg:repoze.pam#basicauth
# challenge
realm = repoze
Added: repoze.pam/trunk/repoze/pam/plugins/__init__.py
==============================================================================
--- (empty file)
+++ repoze.pam/trunk/repoze/pam/plugins/__init__.py Sat Feb 23 17:54:41 2008
@@ -0,0 +1 @@
+# a package
Added: repoze.pam/trunk/repoze/pam/plugins/basicauth.py
==============================================================================
--- (empty file)
+++ repoze.pam/trunk/repoze/pam/plugins/basicauth.py Sat Feb 23 17:54:41 2008
@@ -0,0 +1,50 @@
+import binascii
+
+from paste.httpheaders import WWW_AUTHENTICATE
+from paste.httpheaders import AUTHORIZATION
+from paste.httpexceptions import HTTPUnauthorized
+
+from zope.interface import implements
+
+from repoze.pam.interfaces import IChallengerPlugin
+from repoze.pam.interfaces import IExtractorPlugin
+
+class BasicAuthPlugin(object):
+
+ implements(IChallengerPlugin, IExtractorPlugin)
+
+ def __init__(self, realm, requests):
+ self.realm = realm
+ self.requests = requests
+
+ # IChallengerPlugin
+ def challenge(self, environ):
+ head = WWW_AUTHENTICATE.tuples('Basic realm="%s"' % self.realm)
+ raise HTTPUnauthorized(headers=head)
+
+ # IExtractorPlugin
+ def extract(self, environ):
+ authorization = AUTHORIZATION(environ)
+ try:
+ authmeth, auth = authorization.split(' ', 1)
+ except ValueError:
+ # not enough values to unpack
+ return {}
+ if authmeth.lower() == 'basic':
+ try:
+ auth = auth.strip().decode('base64')
+ except binascii.Error:
+ # can't decode
+ return {}
+ try:
+ login, password = auth.split(':', 1)
+ except ValueError:
+ # not enough values to unpack
+ return {}
+
+ return {'login':login, 'password':password}
+
+ return {}
+
+def make_plugin(pam_conf, realm, requests):
+ return BasicAuthPlugin(realm, requests)
Added: repoze.pam/trunk/repoze/pam/tests.py
==============================================================================
--- (empty file)
+++ repoze.pam/trunk/repoze/pam/tests.py Sat Feb 23 17:54:41 2008
@@ -0,0 +1,76 @@
+import unittest
+
+class TestBasicAuthPlugin(unittest.TestCase):
+ def _getTargetClass(self):
+ from repoze.pam.plugins.basicauth import BasicAuthPlugin
+ return BasicAuthPlugin
+
+ def _makeOne(self, *arg, **kw):
+ plugin = self._getTargetClass()(*arg, **kw)
+ return plugin
+
+ def _makeEnviron(self, kw=None):
+ environ = {}
+ environ['wsgi.version'] = (1,0)
+ if kw is not None:
+ environ.update(kw)
+ return environ
+
+ def test_implements(self):
+ from zope.interface.verify import verifyClass
+ from repoze.pam.interfaces import IChallengerPlugin
+ from repoze.pam.interfaces import IExtractorPlugin
+ klass = self._getTargetClass()
+ verifyClass(IChallengerPlugin, klass)
+ verifyClass(IExtractorPlugin, klass)
+
+ def test_challenge(self):
+ plugin = self._makeOne('realm', [])
+ environ = self._makeEnviron()
+ from paste.httpexceptions import HTTPUnauthorized
+ self.assertRaises(HTTPUnauthorized, plugin.challenge, environ)
+
+ def test_extract_noauthinfo(self):
+ plugin = self._makeOne('realm', [])
+ environ = self._makeEnviron()
+ result = plugin.extract(environ)
+ self.assertEqual(result, {})
+
+ def test_extract_nonbasic(self):
+ plugin = self._makeOne('realm', [])
+ environ = self._makeEnviron({'HTTP_AUTHORIZATION':'Digest abc'})
+ result = plugin.extract(environ)
+ self.assertEqual(result, {})
+
+ def test_extract_nonbasic(self):
+ plugin = self._makeOne('realm', [])
+ environ = self._makeEnviron({'HTTP_AUTHORIZATION':'Digest abc'})
+ result = plugin.extract(environ)
+ self.assertEqual(result, {})
+
+ def test_extract_basic_badencoding(self):
+ plugin = self._makeOne('realm', [])
+ environ = self._makeEnviron({'HTTP_AUTHORIZATION':'Basic abc'})
+ result = plugin.extract(environ)
+ self.assertEqual(result, {})
+
+ def test_extract_basic_badrepr(self):
+ plugin = self._makeOne('realm', [])
+ value = 'foo'.encode('base64')
+ environ = self._makeEnviron({'HTTP_AUTHORIZATION':'Basic %s' % value})
+ result = plugin.extract(environ)
+ self.assertEqual(result, {})
+
+ def test_extract_basic_ok(self):
+ plugin = self._makeOne('realm', [])
+ value = 'foo:bar'.encode('base64')
+ environ = self._makeEnviron({'HTTP_AUTHORIZATION':'Basic %s' % value})
+ result = plugin.extract(environ)
+ self.assertEqual(result, {'login':'foo', 'password':'bar'})
+
+ def test_factory(self):
+ from repoze.pam.plugins.basicauth import make_plugin
+ plugin = make_plugin({}, 'realm', ['a', 'b'])
+ self.assertEqual(plugin.realm, 'realm')
+ self.assertEqual(plugin.requests, ['a', 'b'])
+
More information about the Repoze-checkins
mailing list