summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris McDonough <chrism@agendaless.com>2009-06-18 07:56:09 +0000
committerChris McDonough <chrism@agendaless.com>2009-06-18 07:56:09 +0000
commit3ea1ede5d72fa6d51accc32d36665f3a48546a57 (patch)
tree4459334b47378b9c417b106f8630591998175207
parent947b8bb21235cdaaa7d1b203ef74c814a59c31ed (diff)
downloadpyramid-3ea1ede5d72fa6d51accc32d36665f3a48546a57.tar.gz
pyramid-3ea1ede5d72fa6d51accc32d36665f3a48546a57.tar.bz2
pyramid-3ea1ede5d72fa6d51accc32d36665f3a48546a57.zip
- Add ``reissue_time`` and ``timeout`` parameters to
``repoze.bfg.authentication.AuthTktAuthenticationPolicy`` constructor. If these are passed, cookies will be reset every so often (cadged from the same change to repoze.who lately).
-rw-r--r--CHANGES.txt5
-rw-r--r--repoze/bfg/authentication.py30
-rw-r--r--repoze/bfg/tests/test_authentication.py30
3 files changed, 60 insertions, 5 deletions
diff --git a/CHANGES.txt b/CHANGES.txt
index 2851f61ad..3b2772523 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -4,6 +4,11 @@ Next release
Features
--------
+- Add ``reissue_time`` and ``timeout`` parameters to
+ ``repoze.bfg.authentication.AuthTktAuthenticationPolicy``
+ constructor. If these are passed, cookies will be reset every so
+ often (cadged from the same change to repoze.who lately).
+
- The matchdict related to the matching of a Routes route is available
on the request as the ``matchdict`` attribute:
``request.matchdict``. If no route matched, this attribute will be
diff --git a/repoze/bfg/authentication.py b/repoze/bfg/authentication.py
index 6be27f47e..5aca0c110 100644
--- a/repoze/bfg/authentication.py
+++ b/repoze/bfg/authentication.py
@@ -1,3 +1,5 @@
+import time
+
from codecs import utf_8_decode
from codecs import utf_8_encode
from paste.request import get_cookies
@@ -183,6 +185,18 @@ class AuthTktAuthenticationPolicy(CallbackAuthenticationPolicy):
Default: ``False``. Make the requesting IP address part of
the authentication data in the cookie. Optional.
+ ``timeout``
+
+ Default: ``None``. Maximum age in seconds allowed for a cookie
+ to live. If ``timeout`` is specified, you must also set
+ ``reissue_time`` to a lower value.
+
+ ``reissue_time``
+
+ Default: ``None``. 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.
"""
implements(IAuthenticationPolicy)
def __init__(self,
@@ -190,12 +204,16 @@ class AuthTktAuthenticationPolicy(CallbackAuthenticationPolicy):
callback=None,
cookie_name='repoze.bfg.auth_tkt',
secure=False,
- include_ip=False):
+ include_ip=False,
+ timeout=None,
+ reissue_time=None):
self.cookie = AuthTktCookieHelper(
secret,
cookie_name=cookie_name,
secure=secure,
include_ip=include_ip,
+ timeout=timeout,
+ reissue_time=reissue_time,
)
self.callback = callback
@@ -223,11 +241,16 @@ class AuthTktCookieHelper(object):
}
def __init__(self, secret, cookie_name='auth_tkt', secure=False,
- include_ip=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, request):
@@ -249,6 +272,9 @@ class AuthTktCookieHelper(object):
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):
diff --git a/repoze/bfg/tests/test_authentication.py b/repoze/bfg/tests/test_authentication.py
index 258fadfd2..f3df22005 100644
--- a/repoze/bfg/tests/test_authentication.py
+++ b/repoze/bfg/tests/test_authentication.py
@@ -177,11 +177,19 @@ class TestAutkTktAuthenticationPolicy(unittest.TestCase):
from repoze.bfg.authentication import AuthTktAuthenticationPolicy
return AuthTktAuthenticationPolicy
- def _makeOne(self, callback, cookieidentity):
- inst = self._getTargetClass()('secret', callback)
+ def _makeOne(self, callback, cookieidentity, **kw):
+ inst = self._getTargetClass()('secret', callback, **kw)
inst.cookie = DummyCookieHelper(cookieidentity)
return inst
+ def test_allargs(self):
+ # pass all known args
+ inst = self._getTargetClass()(
+ 'secret', callback=None, cookie_name=None, secure=False,
+ include_ip=False, timeout=None, reissue_time=None,
+ )
+ self.assertEqual(inst.callback, None)
+
def test_class_implements_IAuthenticationPolicy(self):
from zope.interface.verify import verifyClass
from repoze.bfg.interfaces import IAuthenticationPolicy
@@ -266,7 +274,8 @@ class TestAuthTktCookieHelper(unittest.TestCase):
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',
@@ -274,6 +283,7 @@ class TestAuthTktCookieHelper(unittest.TestCase):
remote_addr,
tokens=tokens,
user_data=userdata,
+ time=time,
cookie_name=cookie_name,
secure=secure)
return ticket.cookie_value()
@@ -499,6 +509,20 @@ class TestAuthTktCookieHelper(unittest.TestCase):
self.assertEqual(name, 'Set-Cookie')
self.assertEqual(value, 'auth_tkt=""""; Path=/; Domain=.localhost')
+ def test_timeout_no_reissue(self):
+ self.assertRaises(ValueError, self._makeOne, 'userid', timeout=1)
+
+ def test_timeout_lower_than_reissue(self):
+ self.assertRaises(ValueError, self._makeOne, 'userid', timeout=1,
+ reissue_time=2)
+
+ def test_identify_bad_cookie_expired(self):
+ import time
+ helper = self._makeOne('secret', timeout=2, reissue_time=1)
+ val = self._makeTicket(userid='userid', time=time.time()-3)
+ request = self._makeRequest({'HTTP_COOKIE':'auth_tkt=%s' % val})
+ result = helper.identify(request)
+ self.assertEqual(result, None)
class DummyContext:
pass