summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWichert Akkerman <wichert@wiggy.net>2011-01-19 17:14:51 +0100
committerWichert Akkerman <wichert@wiggy.net>2011-01-19 17:14:51 +0100
commitcbccade72ab39d6bb3fbe87e4ef6493ec60f131a (patch)
tree0f6e5c11d38cf78d407185a1a98d5e30a84761b6
parent6194896e75d5d0c98fe857d754280df2ff78a4f9 (diff)
parent69869eee461afe127ff36ef6b81d518e9f9a25a0 (diff)
downloadpyramid-cbccade72ab39d6bb3fbe87e4ef6493ec60f131a.tar.gz
pyramid-cbccade72ab39d6bb3fbe87e4ef6493ec60f131a.tar.bz2
pyramid-cbccade72ab39d6bb3fbe87e4ef6493ec60f131a.zip
Merge branch 'tokens'
-rw-r--r--CHANGES.txt3
-rw-r--r--pyramid/authentication.py11
-rw-r--r--pyramid/tests/test_authentication.py28
3 files changed, 40 insertions, 2 deletions
diff --git a/CHANGES.txt b/CHANGES.txt
index 11bcaadb5..7bd878fca 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -299,6 +299,9 @@ Bug Fixes
Features
--------
+- When using the auth_tkt authentication plugin accept a ``tokens`` parameter
+ in :py:func:`pyramid.security.remember`.
+
- If a resource implements a ``__resource_url__`` method, it will be called
as the result of invoking the ``pyramid.url.resource_url`` function to
generate a URL, overriding the default logic. See the new "Generating The
diff --git a/pyramid/authentication.py b/pyramid/authentication.py
index 9de306b80..133b8381b 100644
--- a/pyramid/authentication.py
+++ b/pyramid/authentication.py
@@ -1,6 +1,7 @@
from codecs import utf_8_decode
from codecs import utf_8_encode
import datetime
+import re
import time
from paste.auth import auth_tkt
@@ -14,6 +15,9 @@ from pyramid.request import add_global_response_headers
from pyramid.security import Authenticated
from pyramid.security import Everyone
+
+VALID_TOKEN = re.compile(r"^[A-Za-z][A-Za-z0-9+_-]*$")
+
class CallbackAuthenticationPolicy(object):
""" Abstract class """
def authenticated_userid(self, request):
@@ -430,7 +434,7 @@ class AuthTktCookieHelper(object):
environ = request.environ
return self._get_cookies(environ, '', max_age=EXPIRE)
- def remember(self, request, userid, max_age=None):
+ def remember(self, request, userid, max_age=None, tokens=()):
""" Return a set of Set-Cookie headers; when set into a response,
these headers will represent a valid authentication ticket."""
max_age = max_age or self.max_age
@@ -449,10 +453,15 @@ class AuthTktCookieHelper(object):
userid = encoder(userid)
user_data = 'userid_type:%s' % encoding
+ for token in tokens:
+ if not (isinstance(token, str) and VALID_TOKEN.match(token)):
+ raise ValueError("Invalid token %r", token)
+
ticket = self.auth_tkt.AuthTicket(
self.secret,
userid,
remote_addr,
+ tokens=tokens,
user_data=user_data,
cookie_name=self.cookie_name,
secure=self.secure)
diff --git a/pyramid/tests/test_authentication.py b/pyramid/tests/test_authentication.py
index 49d655466..d3b5dd2c3 100644
--- a/pyramid/tests/test_authentication.py
+++ b/pyramid/tests/test_authentication.py
@@ -599,7 +599,33 @@ class TestAuthTktCookieHelper(unittest.TestCase):
self.assertEqual(values[0]['max-age'], '500')
self.failUnless(values[0]['expires'])
-
+
+ def test_remember_tokens(self):
+ plugin = self._makeOne('secret')
+ request = self._makeRequest()
+ result = plugin.remember(request, 'other', tokens=('foo', 'bar'))
+ self.assertEqual(len(result), 3)
+
+ self.assertEqual(result[0][0], 'Set-Cookie')
+ self.failUnless("'tokens': ('foo', 'bar')" in result[0][1])
+
+ self.assertEqual(result[1][0], 'Set-Cookie')
+ self.failUnless("'tokens': ('foo', 'bar')" in result[1][1])
+
+ self.assertEqual(result[2][0], 'Set-Cookie')
+ self.failUnless("'tokens': ('foo', 'bar')" in result[2][1])
+
+ def test_remember_non_string_token(self):
+ plugin = self._makeOne('secret')
+ request = self._makeRequest()
+ self.assertRaises(ValueError, plugin.remember, request, 'other', tokens=(u'foo',))
+
+ def test_remember_invalid_token_format(self):
+ plugin = self._makeOne('secret')
+ request = self._makeRequest()
+ self.assertRaises(ValueError, plugin.remember, request, 'other', tokens=('foo bar',))
+ self.assertRaises(ValueError, plugin.remember, request, 'other', tokens=('1bar',))
+
def test_forget(self):
plugin = self._makeOne('secret')
request = self._makeRequest()