Tres Seaver
2014-12-16 9689d4ee19a898919e841a2e31bf8e203d7c1ffd
Merge pull request #18 from jurov/userdata_dict

Make identity['userdata'] actually usable
3 files modified
114 ■■■■■ changed files
docs/plugins.rst 7 ●●●●● patch | view | raw | blame | history
repoze/who/plugins/auth_tkt.py 31 ●●●●● patch | view | raw | blame | history
repoze/who/plugins/tests/test_authtkt.py 76 ●●●● patch | view | raw | blame | history
docs/plugins.rst
@@ -88,6 +88,13 @@
   <http://westpoint.ltd.uk/advisories/Paul_Johnston_GSEC.pdf>`_ reports
   that as many as 3% of users change their IP addresses legitimately
   during a session.
.. note::
   Plugin supports remembering user data in the cookie by saving user dict into ``identity['userdata']``
   parameter of ``remember`` method. They are sent unencrypted and protected by checksum.
   Data will then be returned every time by ``identify``. This dict must be compatible with
   ``urllib.urlencode`` function (``urllib.urlparse.urlencode`` in python 3).
   Saving keys/values with unicode characters is supported only under python 3.
.. module:: repoze.who.plugins.basicauth
repoze/who/plugins/auth_tkt.py
@@ -7,6 +7,11 @@
import time
from wsgiref.handlers import _monthname     # Locale-independent, RFC-2616
from wsgiref.handlers import _weekdayname   # Locale-independent, RFC-2616
try:
    from urllib.parse import urlencode, parse_qsl
except ImportError:
    from urllib import urlencode
    from urlparse import parse_qsl
from zope.interface import implementer
@@ -27,6 +32,7 @@
@implementer(IIdentifier, IAuthenticator)
class AuthTktCookiePlugin(object):
    userid_typename = 'userid_type'
    userid_type_decoders = {'int': int,
                            'unicode': lambda x: utf_8_decode(x)[0],
                           }
@@ -79,14 +85,12 @@
        if self.timeout and ( (timestamp + self.timeout) < time.time() ):
            return None
        userid_typename = 'userid_type:'
        user_data_info = user_data.split('|')
        for datum in filter(None, user_data_info):
            if datum.startswith(userid_typename):
                userid_type = datum[len(userid_typename):]
                decoder = self.userid_type_decoders.get(userid_type)
                if decoder:
                    userid = decoder(userid)
        user_data_dict = dict(parse_qsl(user_data))
        userid_type = user_data_dict.get(self.userid_typename)
        if userid_type:
            decoder = self.userid_type_decoders.get(userid_type)
            if decoder:
                userid = decoder(userid)
            
        environ['REMOTE_USER_TOKENS'] = tokens
        environ['REMOTE_USER_DATA'] = user_data
@@ -96,7 +100,7 @@
        identity['timestamp'] = timestamp
        identity['repoze.who.plugins.auth_tkt.userid'] = userid
        identity['tokens'] = tokens
        identity['userdata'] = user_data
        identity['userdata'] = user_data_dict
        return identity
    # IIdentifier
@@ -129,15 +133,16 @@
        who_userid = identity['repoze.who.userid']
        who_tokens = tuple(identity.get('tokens', ()))
        who_userdata = identity.get('userdata', '')
        who_userdata_dict = identity.get('userdata', {})
        encoding_data = self.userid_type_encoders.get(type(who_userid))
        if encoding_data:
            encoding, encoder = encoding_data
            who_userid = encoder(who_userid)
            # XXX we are discarding the userdata passed in the identity?
            who_userdata = 'userid_type:%s' % encoding
            who_userdata_dict[self.userid_typename] = encoding
        who_userdata = urlencode(who_userdata_dict)
        old_data = (userid, tokens, userdata)
        new_data = (who_userid, who_tokens, who_userdata)
repoze/who/plugins/tests/test_authtkt.py
@@ -93,58 +93,58 @@
        
    def test_identify_good_cookie_include_ip(self):
        plugin = self._makeOne('secret', include_ip=True)
        val = self._makeTicket(remote_addr='1.1.1.1')
        val = self._makeTicket(remote_addr='1.1.1.1', userdata='foo=123')
        environ = self._makeEnviron({'HTTP_COOKIE':'auth_tkt=%s' % val})
        result = plugin.identify(environ)
        self.assertEqual(len(result), 4)
        self.assertEqual(result['tokens'], [''])
        self.assertEqual(result['repoze.who.plugins.auth_tkt.userid'], 'userid')
        self.assertEqual(result['userdata'], 'userdata')
        self.assertEqual(result['userdata'], {'foo': '123'})
        self.assertTrue('timestamp' in result)
        self.assertEqual(environ['REMOTE_USER_TOKENS'], [''])
        self.assertEqual(environ['REMOTE_USER_DATA'],'userdata')
        self.assertEqual(environ['REMOTE_USER_DATA'],'foo=123')
        self.assertEqual(environ['AUTH_TYPE'],'cookie')
    def test_identify_good_cookie_dont_include_ip(self):
        plugin = self._makeOne('secret', include_ip=False)
        val = self._makeTicket()
        val = self._makeTicket(userdata='foo=123')
        environ = self._makeEnviron({'HTTP_COOKIE':'auth_tkt=%s' % val})
        result = plugin.identify(environ)
        self.assertEqual(len(result), 4)
        self.assertEqual(result['tokens'], [''])
        self.assertEqual(result['repoze.who.plugins.auth_tkt.userid'], 'userid')
        self.assertEqual(result['userdata'], 'userdata')
        self.assertEqual(result['userdata'], {'foo': '123'})
        self.assertTrue('timestamp' in result)
        self.assertEqual(environ['REMOTE_USER_TOKENS'], [''])
        self.assertEqual(environ['REMOTE_USER_DATA'],'userdata')
        self.assertEqual(environ['REMOTE_USER_DATA'],'foo=123')
        self.assertEqual(environ['AUTH_TYPE'],'cookie')
    def test_identify_good_cookie_int_useridtype(self):
        plugin = self._makeOne('secret', include_ip=False)
        val = self._makeTicket(userid='1', userdata='userid_type:int')
        val = self._makeTicket(userid='1', userdata='userid_type=int')
        environ = self._makeEnviron({'HTTP_COOKIE':'auth_tkt=%s' % val})
        result = plugin.identify(environ)
        self.assertEqual(len(result), 4)
        self.assertEqual(result['tokens'], [''])
        self.assertEqual(result['repoze.who.plugins.auth_tkt.userid'], 1)
        self.assertEqual(result['userdata'], 'userid_type:int')
        self.assertEqual(result['userdata'], {'userid_type': 'int'})
        self.assertTrue('timestamp' in result)
        self.assertEqual(environ['REMOTE_USER_TOKENS'], [''])
        self.assertEqual(environ['REMOTE_USER_DATA'],'userid_type:int')
        self.assertEqual(environ['REMOTE_USER_DATA'],'userid_type=int')
        self.assertEqual(environ['AUTH_TYPE'],'cookie')
    def test_identify_good_cookie_unknown_useridtype(self):
        plugin = self._makeOne('secret', include_ip=False)
        val = self._makeTicket(userid='userid', userdata='userid_type:unknown')
        val = self._makeTicket(userid='userid', userdata='userid_type=unknown')
        environ = self._makeEnviron({'HTTP_COOKIE':'auth_tkt=%s' % val})
        result = plugin.identify(environ)
        self.assertEqual(len(result), 4)
        self.assertEqual(result['tokens'], [''])
        self.assertEqual(result['repoze.who.plugins.auth_tkt.userid'], 'userid')
        self.assertEqual(result['userdata'], 'userid_type:unknown')
        self.assertEqual(result['userdata'], {'userid_type':'unknown'})
        self.assertTrue('timestamp' in result)
        self.assertEqual(environ['REMOTE_USER_TOKENS'], [''])
        self.assertEqual(environ['REMOTE_USER_DATA'],'userid_type:unknown')
        self.assertEqual(environ['REMOTE_USER_DATA'],'userid_type=unknown')
        self.assertEqual(environ['AUTH_TYPE'],'cookie')
    def test_identify_bad_cookie(self):
@@ -163,32 +163,32 @@
    def test_identify_with_checker_and_existing_account(self):
        plugin = self._makeOne('secret', userid_checker=dummy_userid_checker)
        val = self._makeTicket(userid='existing')
        val = self._makeTicket(userid='existing', userdata='foo=123')
        environ = self._makeEnviron({'HTTP_COOKIE':'auth_tkt=%s' % val})
        result = plugin.identify(environ)
        self.assertEqual(len(result), 4)
        self.assertEqual(result['tokens'], [''])
        self.assertEqual(result['repoze.who.plugins.auth_tkt.userid'], 'existing')
        self.assertEqual(result['userdata'], 'userdata')
        self.assertEqual(result['userdata'], {'foo': '123'})
        self.assertTrue('timestamp' in result)
        self.assertEqual(environ['REMOTE_USER_TOKENS'], [''])
        self.assertEqual(environ['REMOTE_USER_DATA'],'userdata')
        self.assertEqual(environ['REMOTE_USER_DATA'],'foo=123')
        self.assertEqual(environ['AUTH_TYPE'],'cookie')
    def test_remember_creds_same(self):
        plugin = self._makeOne('secret')
        val = self._makeTicket(userid='userid')
        val = self._makeTicket(userid='userid', userdata='foo=123')
        environ = self._makeEnviron({'HTTP_COOKIE':'auth_tkt=%s' % val})
        result = plugin.remember(environ, {'repoze.who.userid':'userid',
                                           'userdata':'userdata'})
                                           'userdata':{'foo': '123'}})
        self.assertEqual(result, None)
    def test_remember_creds_secure(self):
        plugin = self._makeOne('secret', secure=True)
        val = self._makeTicket(userid='userid', secure=True)
        val = self._makeTicket(userid='userid', secure=True, userdata='foo=123')
        environ = self._makeEnviron()
        result = plugin.remember(environ, {'repoze.who.userid':'userid',
                                           'userdata':'userdata'})
                                           'userdata':{'foo':'123'}})
        self.assertEqual(len(result), 3)
        self.assertEqual(result[0],
                         ('Set-Cookie',
@@ -215,9 +215,9 @@
        plugin = self._makeOne('secret')
        old_val = self._makeTicket(userid='userid')
        environ = self._makeEnviron({'HTTP_COOKIE':'auth_tkt=%s' % old_val})
        new_val = self._makeTicket(userid='other', userdata='userdata')
        new_val = self._makeTicket(userid='other', userdata='foo=123')
        result = plugin.remember(environ, {'repoze.who.userid':'other',
                                           'userdata':'userdata'})
                                           'userdata':{'foo':'123'}})
        self.assertEqual(len(result), 3)
        self.assertEqual(result[0],
                         ('Set-Cookie',
@@ -242,9 +242,9 @@
        environ = self._makeEnviron({'HTTP_COOKIE':'auth_tkt=%s' % old_val,
                                     'HTTP_HOST': 'localhost:8080',
                                    })
        new_val = self._makeTicket(userid='other', userdata='userdata')
        new_val = self._makeTicket(userid='other', userdata='foo=123')
        result = plugin.remember(environ, {'repoze.who.userid':'other',
                                           'userdata':'userdata'})
                                           'userdata':{'foo': '123'}})
        self.assertEqual(len(result), 3)
        self.assertEqual(result[0],
                         ('Set-Cookie',
@@ -268,10 +268,10 @@
        old_val = self._makeTicket(userid='userid', remote_addr='1.1.1.1')
        environ = self._makeEnviron({'HTTP_COOKIE': 'auth_tkt=%s' % old_val})
        new_val = self._makeTicket(userid='other',
                                   userdata='userdata',
                                   userdata='foo=123',
                                   remote_addr='1.1.1.1')
        result = plugin.remember(environ, {'repoze.who.userid':'other',
                                           'userdata':'userdata'})
                                           'userdata':{'foo': '123'}})
        self.assertEqual(len(result), 3)
        self.assertEqual(result[0],
                         ('Set-Cookie',
@@ -294,9 +294,9 @@
        plugin = self._makeOne('secret')
        old_val = 'BOGUS'
        environ = self._makeEnviron({'HTTP_COOKIE':'auth_tkt=%s' % old_val})
        new_val = self._makeTicket(userid='other', userdata='userdata')
        new_val = self._makeTicket(userid='other', userdata='foo=123')
        result = plugin.remember(environ, {'repoze.who.userid':'other',
                                           'userdata':'userdata'})
                                           'userdata':{'foo': '123'}})
        self.assertEqual(len(result), 3)
        self.assertEqual(result[0],
                         ('Set-Cookie',
@@ -320,11 +320,11 @@
        old_val = self._makeTicket(userid='userid')
        environ = self._makeEnviron({'HTTP_COOKIE':'auth_tkt=%s' % old_val})
        new_val = self._makeTicket(userid='userid',
                                   userdata='userdata',
                                   userdata='foo=123',
                                   tokens=['foo', 'bar'],
                                  )
        result = plugin.remember(environ, {'repoze.who.userid': 'userid',
                                           'userdata': 'userdata',
                                           'userdata': {'foo': '123'},
                                           'tokens': ['foo', 'bar'],
                                          })
        self.assertEqual(len(result), 3)
@@ -349,11 +349,11 @@
        old_val = self._makeTicket(userid='userid')
        environ = self._makeEnviron({'HTTP_COOKIE':'auth_tkt=%s' % old_val})
        new_val = self._makeTicket(userid='userid',
                                   userdata='userdata',
                                   userdata='foo=123',
                                   tokens=['foo', 'bar'],
                                  )
        result = plugin.remember(environ, {'repoze.who.userid': 'userid',
                                           'userdata': 'userdata',
                                           'userdata': {'foo': '123'},
                                           'tokens': ('foo', 'bar'),
                                          })
        self.assertEqual(len(result), 3)
@@ -378,10 +378,10 @@
        plugin = self._makeOne('secret')
        old_val = self._makeTicket(userid='userid')
        environ = self._makeEnviron({'HTTP_COOKIE':'auth_tkt=%s' % old_val})
        new_val = self._makeTicket(userid='1', userdata='userid_type:int')
        new_val = self._makeTicket(userid='1', userdata='userid_type=int')
        result = plugin.remember(environ, {'repoze.who.userid':1,
                                           'userdata':''})
                                           'userdata':{}})
        self.assertEqual(len(result), 3)
        self.assertEqual(result[0],
                         ('Set-Cookie',
@@ -395,9 +395,9 @@
        plugin = self._makeOne('secret')
        old_val = self._makeTicket(userid='userid')
        environ = self._makeEnviron({'HTTP_COOKIE':'auth_tkt=%s' % old_val})
        new_val = self._makeTicket(userid='1', userdata='userid_type:int')
        new_val = self._makeTicket(userid='1', userdata='userid_type=int')
        result = plugin.remember(environ, {'repoze.who.userid':long(1),
                                           'userdata':''})
                                           'userdata':{}})
        self.assertEqual(len(result), 3)
        self.assertEqual(result[0],
                         ('Set-Cookie',
@@ -409,13 +409,13 @@
        environ = self._makeEnviron({'HTTP_COOKIE':'auth_tkt=%s' % old_val})
        userid = b'\xc2\xa9'.decode('utf-8')
        if type(b'') == type(''):
            userdata = 'userid_type:unicode'
            userdata = 'userid_type=unicode'
        else: # pragma: no cover Py3k
            userdata = ''
        new_val = self._makeTicket(userid=userid.encode('utf-8'),
                                   userdata=userdata)
        result = plugin.remember(environ, {'repoze.who.userid':userid,
                                           'userdata':''})
                                           'userdata':{}})
        self.assertEqual(type(result[0][1]), str)
        self.assertEqual(len(result), 3)
        self.assertEqual(result[0],