Paul Johnston <paul....@gmail.com> added the comment:

Ok, I've produced a patch for this, let me know what you think.

----------
status: unread -> chatting

__________________________________
Repoze Bugs <b...@bugs.repoze.org>
<http://bugs.repoze.org/issue83>
__________________________________
Index: repoze/who/plugins/tests/test_authtkt.py
===================================================================
--- repoze/who/plugins/tests/test_authtkt.py	(revision 5195)
+++ repoze/who/plugins/tests/test_authtkt.py	(working copy)
@@ -29,7 +29,8 @@
 
     def _makeTicket(self, userid='userid', remote_addr='0.0.0.0',
                     tokens = [], userdata='userdata',
-                    cookie_name='auth_tkt', secure=False):
+                    cookie_name='auth_tkt', secure=False,
+                    time=None):
         from paste.auth import auth_tkt
         ticket = auth_tkt.AuthTicket(
             'secret',
@@ -37,6 +38,7 @@
             remote_addr,
             tokens=tokens,
             user_data=userdata,
+            time=time,
             cookie_name=cookie_name,
             secure=secure)
         return ticket.cookie_value()
@@ -115,6 +117,14 @@
         result = plugin.identify(environ)
         self.assertEqual(result, None)
     
+    def test_identify_bad_cookie_expired(self):
+        import time
+        plugin = self._makeOne('secret', timeout=2, reissue_time=1)
+        val = self._makeTicket(userid='userid', time=time.time()-3)
+        environ = self._makeEnviron({'HTTP_COOKIE':'auth_tkt=%s' % val})
+        result = plugin.identify(environ)
+        self.assertEqual(result, None)
+
     def test_remember_creds_same(self):
         plugin = self._makeOne('secret')
         val = self._makeTicket(userid='userid')
@@ -250,6 +260,20 @@
                          ('Set-Cookie',
                           'auth_tkt="%s"; Path=/' % new_val))
 
+    def test_remember_creds_reissue(self):
+        import time
+        plugin = self._makeOne('secret', reissue_time=1)
+        old_val = self._makeTicket(userid='userid', userdata='', time=time.time()-2)
+        environ = self._makeEnviron({'HTTP_COOKIE':'auth_tkt=%s' % old_val})
+        new_val = self._makeTicket(userid='userid', userdata='')
+        result = plugin.remember(environ, {'repoze.who.userid':'userid',
+                                           'userdata':''})
+        self.assertEqual(type(result[0][1]), str)
+        self.assertEqual(len(result), 3)
+        self.assertEqual(result[0],
+                         ('Set-Cookie',
+                          'auth_tkt="%s"; Path=/' % new_val))
+
     def test_forget(self):
         plugin = self._makeOne('secret')
         environ = self._makeEnviron()
@@ -301,3 +325,9 @@
         plugin = make_plugin(secretfile=path)
         self.assertEqual(plugin.secret, 's33kr1t')
 
+    def test_timeout_reissue(self):
+        try:
+            self._makeOne('userid', timeout=1)
+            self.assertEqual(1, 2)
+        except ValueError, e:
+            pass
Index: repoze/who/plugins/auth_tkt.py
===================================================================
--- repoze/who/plugins/auth_tkt.py	(revision 5195)
+++ repoze/who/plugins/auth_tkt.py	(working copy)
@@ -1,6 +1,7 @@
 from codecs import utf_8_decode
 from codecs import utf_8_encode
 import os
+import time
 
 from paste.request import get_cookies
 from paste.auth import auth_tkt
@@ -25,11 +26,17 @@
         }
     
     def __init__(self, secret, cookie_name='auth_tkt',
-                 secure=False, include_ip=False):
+                 secure=False, include_ip=False,
+                 timeout=None, reissue_time=None):
         self.secret = secret
         self.cookie_name = cookie_name
         self.include_ip = include_ip
         self.secure = secure
+        if timeout and (not reissue_time or reissue_time > timeout):
+            raise ValueError('When timeout is specified, reissue_time must '
+                             'be set to a lower value')
+        self.timeout = timeout
+        self.reissue_time = reissue_time
 
     # IIdentifier
     def identify(self, environ):
@@ -50,6 +57,9 @@
         except auth_tkt.BadTicket:
             return None
 
+        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):
@@ -126,7 +136,8 @@
         old_data = (userid, tokens, userdata)
         new_data = (who_userid, who_tokens, who_userdata)
 
-        if old_data != new_data:
+        if old_data != new_data or (self.reissue_time and
+                timestamp + self.reissue_time < time.time()):
             ticket = auth_tkt.AuthTicket(
                 self.secret,
                 who_userid,
@@ -157,6 +168,8 @@
                 cookie_name='auth_tkt',
                 secure=False,
                 include_ip=False,
+                timeout=None,
+                reissue_time=None,
                ):
     if (secret is None and secretfile is None):
         raise ValueError("One of 'secret' or 'secretfile' must not be None.")
@@ -168,6 +181,8 @@
             raise ValueError("No such 'secretfile': %s" % secretfile)
         secret = open(secretfile).read().strip()
     plugin = AuthTktCookiePlugin(secret, cookie_name,
-                                 _bool(secure), _bool(include_ip))
+                                 _bool(secure), _bool(include_ip),
+                                 timeout and int(timeout),
+                                 reissue_time and int(reissue_time))
     return plugin
 
Index: docs/narr.rst
===================================================================
--- docs/narr.rst	(revision 5195)
+++ docs/narr.rst	(working copy)
@@ -212,7 +212,7 @@
 
 .. module:: repoze.who.plugins.auth_tkt
 
-.. class:: AuthTktCookiePlugin(secret [, cookie_name='auth_tkt' [, secure=False [, include_ip=False]]])
+.. class:: AuthTktCookiePlugin(secret [, cookie_name='auth_tkt' [, secure=False [, include_ip=False [, timeout=None [, reissue_time=None]]]]])
 
   An :class:`AuthTktCookiePlugin` is an ``IIdentifier`` plugin which
   remembers its identity state in a client-side cookie.  This plugin
@@ -224,7 +224,12 @@
   will be sent across any HTTP or HTTPS connection; if it is True, the
   cookie will be sent only across an HTTPS connection.  If
   *include_ip* is True, the ``REMOTE_ADDR`` of the WSGI environment
-  will be placed in the cookie.
+  will be placed in the cookie. If *timeout* is specfied, it is the
+  maximum age in seconds allowed for a cookie. If *reissue_time* is
+  specified, when we encounter a cookie that is older than the reissue
+  time (in seconds), but younger that the timeout, a new cookie will
+  be issued. If *timeout* is specified, you must also set
+  *reissue_time* to a lower value.
 
 .. note::
    Using the *include_ip* setting for public-facing applications may
_______________________________________________
Repoze-dev mailing list
Repoze-dev@lists.repoze.org
http://lists.repoze.org/listinfo/repoze-dev

Reply via email to