Michael Merickel
2018-10-15 2b024920847481592b1a13d4006d2a9fa8881d72
commit | author | age
a1a9fb 1 import unittest
ca3df8 2 import warnings
449287 3 from pyramid import testing
f5b9e9 4 from pyramid.compat import (
CM 5     text_,
6     bytes_,
7     )
449287 8
CM 9 class TestCallbackAuthenticationPolicyDebugging(unittest.TestCase):
10     def setUp(self):
11         from pyramid.interfaces import IDebugLogger
12         self.config = testing.setUp()
13         self.config.registry.registerUtility(self, IDebugLogger)
14         self.messages = []
15
16     def tearDown(self):
17         del self.config
bf902d 18
449287 19     def debug(self, msg):
CM 20         self.messages.append(msg)
21
22     def _makeOne(self, userid=None, callback=None):
23         from pyramid.authentication import CallbackAuthenticationPolicy
24         class MyAuthenticationPolicy(CallbackAuthenticationPolicy):
25             def unauthenticated_userid(self, request):
26                 return userid
27         policy = MyAuthenticationPolicy()
28         policy.debug = True
29         policy.callback = callback
30         return policy
31
32     def test_authenticated_userid_no_unauthenticated_userid(self):
33         request = DummyRequest(registry=self.config.registry)
34         policy = self._makeOne()
35         self.assertEqual(policy.authenticated_userid(request), None)
36         self.assertEqual(len(self.messages), 1)
37         self.assertEqual(
38             self.messages[0],
39             'pyramid.tests.test_authentication.MyAuthenticationPolicy.'
40             'authenticated_userid: call to unauthenticated_userid returned '
41             'None; returning None')
42
43     def test_authenticated_userid_no_callback(self):
44         request = DummyRequest(registry=self.config.registry)
45         policy = self._makeOne(userid='fred')
46         self.assertEqual(policy.authenticated_userid(request), 'fred')
47         self.assertEqual(len(self.messages), 1)
48         self.assertEqual(
49             self.messages[0],
50              "pyramid.tests.test_authentication.MyAuthenticationPolicy."
51             "authenticated_userid: there was no groupfinder callback; "
52             "returning 'fred'")
53
54     def test_authenticated_userid_with_callback_fail(self):
55         request = DummyRequest(registry=self.config.registry)
56         def callback(userid, request):
57             return None
58         policy = self._makeOne(userid='fred', callback=callback)
59         self.assertEqual(policy.authenticated_userid(request), None)
60         self.assertEqual(len(self.messages), 1)
61         self.assertEqual(
62             self.messages[0],
63             'pyramid.tests.test_authentication.MyAuthenticationPolicy.'
64             'authenticated_userid: groupfinder callback returned None; '
65             'returning None')
66
67     def test_authenticated_userid_with_callback_success(self):
68         request = DummyRequest(registry=self.config.registry)
69         def callback(userid, request):
70             return []
71         policy = self._makeOne(userid='fred', callback=callback)
72         self.assertEqual(policy.authenticated_userid(request), 'fred')
73         self.assertEqual(len(self.messages), 1)
74         self.assertEqual(
75             self.messages[0],
76             "pyramid.tests.test_authentication.MyAuthenticationPolicy."
77             "authenticated_userid: groupfinder callback returned []; "
78             "returning 'fred'")
79
07c9ee 80     def test_authenticated_userid_fails_cleaning_as_Authenticated(self):
CM 81         request = DummyRequest(registry=self.config.registry)
82         policy = self._makeOne(userid='system.Authenticated')
83         self.assertEqual(policy.authenticated_userid(request), None)
84         self.assertEqual(len(self.messages), 1)
85         self.assertEqual(
86             self.messages[0],
87             "pyramid.tests.test_authentication.MyAuthenticationPolicy."
88             "authenticated_userid: use of userid 'system.Authenticated' is "
89             "disallowed by any built-in Pyramid security policy, returning "
90             "None")
91
92     def test_authenticated_userid_fails_cleaning_as_Everyone(self):
93         request = DummyRequest(registry=self.config.registry)
94         policy = self._makeOne(userid='system.Everyone')
95         self.assertEqual(policy.authenticated_userid(request), None)
96         self.assertEqual(len(self.messages), 1)
97         self.assertEqual(
98             self.messages[0],
99             "pyramid.tests.test_authentication.MyAuthenticationPolicy."
100             "authenticated_userid: use of userid 'system.Everyone' is "
101             "disallowed by any built-in Pyramid security policy, returning "
102             "None")
103
449287 104     def test_effective_principals_no_unauthenticated_userid(self):
CM 105         request = DummyRequest(registry=self.config.registry)
106         policy = self._makeOne()
107         self.assertEqual(policy.effective_principals(request),
108                          ['system.Everyone'])
109         self.assertEqual(len(self.messages), 1)
110         self.assertEqual(
111             self.messages[0],
112             "pyramid.tests.test_authentication.MyAuthenticationPolicy."
2220a3 113             "effective_principals: unauthenticated_userid returned None; "
449287 114             "returning ['system.Everyone']")
CM 115
116     def test_effective_principals_no_callback(self):
117         request = DummyRequest(registry=self.config.registry)
118         policy = self._makeOne(userid='fred')
119         self.assertEqual(
120             policy.effective_principals(request),
121             ['system.Everyone', 'system.Authenticated', 'fred'])
122         self.assertEqual(len(self.messages), 2)
123         self.assertEqual(
124             self.messages[0],
125             'pyramid.tests.test_authentication.MyAuthenticationPolicy.'
126             'effective_principals: groupfinder callback is None, so groups '
127             'is []')
128         self.assertEqual(
129             self.messages[1],
130             "pyramid.tests.test_authentication.MyAuthenticationPolicy."
131             "effective_principals: returning effective principals: "
132             "['system.Everyone', 'system.Authenticated', 'fred']")
133
134     def test_effective_principals_with_callback_fail(self):
135         request = DummyRequest(registry=self.config.registry)
136         def callback(userid, request):
137             return None
138         policy = self._makeOne(userid='fred', callback=callback)
139         self.assertEqual(
140             policy.effective_principals(request), ['system.Everyone'])
141         self.assertEqual(len(self.messages), 2)
142         self.assertEqual(
143             self.messages[0],
144             'pyramid.tests.test_authentication.MyAuthenticationPolicy.'
145             'effective_principals: groupfinder callback returned None as '
146             'groups')
147         self.assertEqual(
148             self.messages[1],
149             "pyramid.tests.test_authentication.MyAuthenticationPolicy."
150             "effective_principals: returning effective principals: "
151             "['system.Everyone']")
152
153     def test_effective_principals_with_callback_success(self):
154         request = DummyRequest(registry=self.config.registry)
155         def callback(userid, request):
156             return []
157         policy = self._makeOne(userid='fred', callback=callback)
158         self.assertEqual(
159             policy.effective_principals(request),
160             ['system.Everyone', 'system.Authenticated', 'fred'])
161         self.assertEqual(len(self.messages), 2)
162         self.assertEqual(
163             self.messages[0],
164             'pyramid.tests.test_authentication.MyAuthenticationPolicy.'
165             'effective_principals: groupfinder callback returned [] as groups')
166         self.assertEqual(
167             self.messages[1],
168             "pyramid.tests.test_authentication.MyAuthenticationPolicy."
169             "effective_principals: returning effective principals: "
170             "['system.Everyone', 'system.Authenticated', 'fred']")
a1a9fb 171
07c9ee 172     def test_effective_principals_with_unclean_principal_Authenticated(self):
CM 173         request = DummyRequest(registry=self.config.registry)
174         policy = self._makeOne(userid='system.Authenticated')
175         self.assertEqual(
176             policy.effective_principals(request),
177             ['system.Everyone'])
178         self.assertEqual(len(self.messages), 1)
179         self.assertEqual(
180             self.messages[0],
181             "pyramid.tests.test_authentication.MyAuthenticationPolicy."
182             "effective_principals: unauthenticated_userid returned disallowed "
183             "'system.Authenticated'; returning ['system.Everyone'] as if it "
184             "was None")
185
186     def test_effective_principals_with_unclean_principal_Everyone(self):
187         request = DummyRequest(registry=self.config.registry)
188         policy = self._makeOne(userid='system.Everyone')
189         self.assertEqual(
190             policy.effective_principals(request),
191             ['system.Everyone'])
192         self.assertEqual(len(self.messages), 1)
193         self.assertEqual(
194             self.messages[0],
195             "pyramid.tests.test_authentication.MyAuthenticationPolicy."
196             "effective_principals: unauthenticated_userid returned disallowed "
197             "'system.Everyone'; returning ['system.Everyone'] as if it "
198             "was None")
199
a1a9fb 200 class TestRepozeWho1AuthenticationPolicy(unittest.TestCase):
CM 201     def _getTargetClass(self):
b60bdb 202         from pyramid.authentication import RepozeWho1AuthenticationPolicy
a1a9fb 203         return RepozeWho1AuthenticationPolicy
CM 204
fcc272 205     def _makeOne(self, identifier_name='auth_tkt', callback=None):
CM 206         return self._getTargetClass()(identifier_name, callback)
bf902d 207
a1a9fb 208     def test_class_implements_IAuthenticationPolicy(self):
CM 209         from zope.interface.verify import verifyClass
b60bdb 210         from pyramid.interfaces import IAuthenticationPolicy
a1a9fb 211         verifyClass(IAuthenticationPolicy, self._getTargetClass())
CM 212
213     def test_instance_implements_IAuthenticationPolicy(self):
214         from zope.interface.verify import verifyObject
b60bdb 215         from pyramid.interfaces import IAuthenticationPolicy
a1a9fb 216         verifyObject(IAuthenticationPolicy, self._makeOne())
CM 217
2526d8 218     def test_unauthenticated_userid_returns_None(self):
CM 219         request = DummyRequest({})
220         policy = self._makeOne()
221         self.assertEqual(policy.unauthenticated_userid(request), None)
222
223     def test_unauthenticated_userid(self):
224         request = DummyRequest(
225             {'repoze.who.identity':{'repoze.who.userid':'fred'}})
226         policy = self._makeOne()
227         self.assertEqual(policy.unauthenticated_userid(request), 'fred')
228
a1a9fb 229     def test_authenticated_userid_None(self):
CM 230         request = DummyRequest({})
231         policy = self._makeOne()
7ec9e7 232         self.assertEqual(policy.authenticated_userid(request), None)
2526d8 233
a1a9fb 234     def test_authenticated_userid(self):
CM 235         request = DummyRequest(
236             {'repoze.who.identity':{'repoze.who.userid':'fred'}})
237         policy = self._makeOne()
7ec9e7 238         self.assertEqual(policy.authenticated_userid(request), 'fred')
fcc272 239
07c9ee 240     def test_authenticated_userid_repoze_who_userid_is_None(self):
CM 241         request = DummyRequest(
242             {'repoze.who.identity':{'repoze.who.userid':None}})
243         policy = self._makeOne()
244         self.assertEqual(policy.authenticated_userid(request), None)
245
fcc272 246     def test_authenticated_userid_with_callback_returns_None(self):
CM 247         request = DummyRequest(
248             {'repoze.who.identity':{'repoze.who.userid':'fred'}})
dba59c 249         def callback(identity, request):
fcc272 250             return None
CM 251         policy = self._makeOne(callback=callback)
7ec9e7 252         self.assertEqual(policy.authenticated_userid(request), None)
fcc272 253
CM 254     def test_authenticated_userid_with_callback_returns_something(self):
255         request = DummyRequest(
256             {'repoze.who.identity':{'repoze.who.userid':'fred'}})
dba59c 257         def callback(identity, request):
fcc272 258             return ['agroup']
CM 259         policy = self._makeOne(callback=callback)
7ec9e7 260         self.assertEqual(policy.authenticated_userid(request), 'fred')
07c9ee 261
CM 262     def test_authenticated_userid_unclean_principal_Authenticated(self):
263         request = DummyRequest(
264             {'repoze.who.identity':{'repoze.who.userid':'system.Authenticated'}}
265             )
266         policy = self._makeOne()
267         self.assertEqual(policy.authenticated_userid(request), None)
268
269     def test_authenticated_userid_unclean_principal_Everyone(self):
270         request = DummyRequest(
271             {'repoze.who.identity':{'repoze.who.userid':'system.Everyone'}}
272             )
273         policy = self._makeOne()
274         self.assertEqual(policy.authenticated_userid(request), None)
a1a9fb 275
CM 276     def test_effective_principals_None(self):
b60bdb 277         from pyramid.security import Everyone
a1a9fb 278         request = DummyRequest({})
CM 279         policy = self._makeOne()
7ec9e7 280         self.assertEqual(policy.effective_principals(request), [Everyone])
a1a9fb 281
CM 282     def test_effective_principals_userid_only(self):
b60bdb 283         from pyramid.security import Everyone
CM 284         from pyramid.security import Authenticated
a1a9fb 285         request = DummyRequest(
CM 286             {'repoze.who.identity':{'repoze.who.userid':'fred'}})
287         policy = self._makeOne()
7ec9e7 288         self.assertEqual(policy.effective_principals(request),
a1a9fb 289                          [Everyone, Authenticated, 'fred'])
CM 290
291     def test_effective_principals_userid_and_groups(self):
b60bdb 292         from pyramid.security import Everyone
CM 293         from pyramid.security import Authenticated
a1a9fb 294         request = DummyRequest(
CM 295             {'repoze.who.identity':{'repoze.who.userid':'fred',
296                                     'groups':['quux', 'biz']}})
dba59c 297         def callback(identity, request):
fcc272 298             return identity['groups']
CM 299         policy = self._makeOne(callback=callback)
7ec9e7 300         self.assertEqual(policy.effective_principals(request),
a1a9fb 301                          [Everyone, Authenticated, 'fred', 'quux', 'biz'])
CM 302
fcc272 303     def test_effective_principals_userid_callback_returns_None(self):
b60bdb 304         from pyramid.security import Everyone
fcc272 305         request = DummyRequest(
CM 306             {'repoze.who.identity':{'repoze.who.userid':'fred',
307                                     'groups':['quux', 'biz']}})
dba59c 308         def callback(identity, request):
fcc272 309             return None
CM 310         policy = self._makeOne(callback=callback)
7ec9e7 311         self.assertEqual(policy.effective_principals(request), [Everyone])
fcc272 312
07c9ee 313     def test_effective_principals_repoze_who_userid_is_None(self):
CM 314         from pyramid.security import Everyone
315         request = DummyRequest(
316             {'repoze.who.identity':{'repoze.who.userid':None}}
317             )
318         policy = self._makeOne()
319         self.assertEqual(policy.effective_principals(request), [Everyone])
320
321     def test_effective_principals_repoze_who_userid_is_unclean_Everyone(self):
322         from pyramid.security import Everyone
323         request = DummyRequest(
324             {'repoze.who.identity':{'repoze.who.userid':'system.Everyone'}}
325             )
326         policy = self._makeOne()
327         self.assertEqual(policy.effective_principals(request), [Everyone])
328
329     def test_effective_principals_repoze_who_userid_is_unclean_Authenticated(
330         self):
331         from pyramid.security import Everyone
332         request = DummyRequest(
333             {'repoze.who.identity':{'repoze.who.userid':'system.Authenticated'}}
334             )
335         policy = self._makeOne()
336         self.assertEqual(policy.effective_principals(request), [Everyone])
337
a1a9fb 338     def test_remember_no_plugins(self):
CM 339         request = DummyRequest({})
340         policy = self._makeOne()
7ec9e7 341         result = policy.remember(request, 'fred')
a1a9fb 342         self.assertEqual(result, [])
CM 343
344     def test_remember(self):
fcc272 345         authtkt = DummyWhoPlugin()
a1a9fb 346         request = DummyRequest(
CM 347             {'repoze.who.plugins':{'auth_tkt':authtkt}})
348         policy = self._makeOne()
7ec9e7 349         result = policy.remember(request, 'fred')
a1a9fb 350         self.assertEqual(result[0], request.environ)
CM 351         self.assertEqual(result[1], {'repoze.who.userid':'fred'})
bf902d 352
76144d 353     def test_remember_kwargs(self):
RB 354         authtkt = DummyWhoPlugin()
355         request = DummyRequest(
356             {'repoze.who.plugins':{'auth_tkt':authtkt}})
357         policy = self._makeOne()
358         result = policy.remember(request, 'fred', max_age=23)
359         self.assertEqual(result[1], {'repoze.who.userid':'fred', 'max_age': 23})
360
a1a9fb 361     def test_forget_no_plugins(self):
CM 362         request = DummyRequest({})
363         policy = self._makeOne()
7ec9e7 364         result = policy.forget(request)
a1a9fb 365         self.assertEqual(result, [])
CM 366
367     def test_forget(self):
fcc272 368         authtkt = DummyWhoPlugin()
a1a9fb 369         request = DummyRequest(
CM 370             {'repoze.who.plugins':{'auth_tkt':authtkt},
371              'repoze.who.identity':{'repoze.who.userid':'fred'},
372              })
373         policy = self._makeOne()
7ec9e7 374         result = policy.forget(request)
a1a9fb 375         self.assertEqual(result[0], request.environ)
CM 376         self.assertEqual(result[1], request.environ['repoze.who.identity'])
377
378 class TestRemoteUserAuthenticationPolicy(unittest.TestCase):
379     def _getTargetClass(self):
b60bdb 380         from pyramid.authentication import RemoteUserAuthenticationPolicy
a1a9fb 381         return RemoteUserAuthenticationPolicy
CM 382
fcc272 383     def _makeOne(self, environ_key='REMOTE_USER', callback=None):
CM 384         return self._getTargetClass()(environ_key, callback)
bf902d 385
a1a9fb 386     def test_class_implements_IAuthenticationPolicy(self):
CM 387         from zope.interface.verify import verifyClass
b60bdb 388         from pyramid.interfaces import IAuthenticationPolicy
a1a9fb 389         verifyClass(IAuthenticationPolicy, self._getTargetClass())
CM 390
391     def test_instance_implements_IAuthenticationPolicy(self):
392         from zope.interface.verify import verifyObject
b60bdb 393         from pyramid.interfaces import IAuthenticationPolicy
a1a9fb 394         verifyObject(IAuthenticationPolicy, self._makeOne())
CM 395
2526d8 396     def test_unauthenticated_userid_returns_None(self):
CM 397         request = DummyRequest({})
398         policy = self._makeOne()
399         self.assertEqual(policy.unauthenticated_userid(request), None)
400
401     def test_unauthenticated_userid(self):
402         request = DummyRequest({'REMOTE_USER':'fred'})
403         policy = self._makeOne()
404         self.assertEqual(policy.unauthenticated_userid(request), 'fred')
405
a1a9fb 406     def test_authenticated_userid_None(self):
CM 407         request = DummyRequest({})
408         policy = self._makeOne()
7ec9e7 409         self.assertEqual(policy.authenticated_userid(request), None)
bf902d 410
a1a9fb 411     def test_authenticated_userid(self):
CM 412         request = DummyRequest({'REMOTE_USER':'fred'})
413         policy = self._makeOne()
7ec9e7 414         self.assertEqual(policy.authenticated_userid(request), 'fred')
a1a9fb 415
CM 416     def test_effective_principals_None(self):
b60bdb 417         from pyramid.security import Everyone
a1a9fb 418         request = DummyRequest({})
CM 419         policy = self._makeOne()
7ec9e7 420         self.assertEqual(policy.effective_principals(request), [Everyone])
a1a9fb 421
CM 422     def test_effective_principals(self):
b60bdb 423         from pyramid.security import Everyone
CM 424         from pyramid.security import Authenticated
a1a9fb 425         request = DummyRequest({'REMOTE_USER':'fred'})
CM 426         policy = self._makeOne()
7ec9e7 427         self.assertEqual(policy.effective_principals(request),
a1a9fb 428                          [Everyone, Authenticated, 'fred'])
CM 429
430     def test_remember(self):
431         request = DummyRequest({'REMOTE_USER':'fred'})
432         policy = self._makeOne()
7ec9e7 433         result = policy.remember(request, 'fred')
a1a9fb 434         self.assertEqual(result, [])
bf902d 435
a1a9fb 436     def test_forget(self):
CM 437         request = DummyRequest({'REMOTE_USER':'fred'})
438         policy = self._makeOne()
7ec9e7 439         result = policy.forget(request)
a1a9fb 440         self.assertEqual(result, [])
fcc272 441
048754 442 class TestAuthTktAuthenticationPolicy(unittest.TestCase):
fcc272 443     def _getTargetClass(self):
b60bdb 444         from pyramid.authentication import AuthTktAuthenticationPolicy
fcc272 445         return AuthTktAuthenticationPolicy
801adf 446
DK 447     def _makeOne(self, callback, cookieidentity, **kw):
448         inst = self._getTargetClass()('secret', callback, **kw)
449         inst.cookie = DummyCookieHelper(cookieidentity)
450         return inst
451
ca3df8 452     def setUp(self):
MM 453         self.warnings = warnings.catch_warnings()
454         self.warnings.__enter__()
455         warnings.simplefilter('ignore', DeprecationWarning)
456
457     def tearDown(self):
458         self.warnings.__exit__(None, None, None)
459
801adf 460     def test_allargs(self):
DK 461         # pass all known args
462         inst = self._getTargetClass()(
463             'secret', callback=None, cookie_name=None, secure=False,
464             include_ip=False, timeout=None, reissue_time=None,
87771a 465             hashalg='sha512', samesite=None,
801adf 466             )
DK 467         self.assertEqual(inst.callback, None)
19b820 468
MM 469     def test_hashalg_override(self):
470         # important to ensure hashalg is passed to cookie helper
471         inst = self._getTargetClass()('secret', hashalg='sha512')
472         self.assertEqual(inst.cookie.hashalg, 'sha512')
fcc272 473
2526d8 474     def test_unauthenticated_userid_returns_None(self):
CM 475         request = DummyRequest({})
476         policy = self._makeOne(None, None)
477         self.assertEqual(policy.unauthenticated_userid(request), None)
478
479     def test_unauthenticated_userid(self):
480         request = DummyRequest({'REMOTE_USER':'fred'})
481         policy = self._makeOne(None, {'userid':'fred'})
482         self.assertEqual(policy.unauthenticated_userid(request), 'fred')
483
fcc272 484     def test_authenticated_userid_no_cookie_identity(self):
CM 485         request = DummyRequest({})
486         policy = self._makeOne(None, None)
7ec9e7 487         self.assertEqual(policy.authenticated_userid(request), None)
bf902d 488
fcc272 489     def test_authenticated_userid_callback_returns_None(self):
CM 490         request = DummyRequest({})
dba59c 491         def callback(userid, request):
fcc272 492             return None
CM 493         policy = self._makeOne(callback, {'userid':'fred'})
7ec9e7 494         self.assertEqual(policy.authenticated_userid(request), None)
fcc272 495
CM 496     def test_authenticated_userid(self):
497         request = DummyRequest({})
dba59c 498         def callback(userid, request):
fcc272 499             return True
CM 500         policy = self._makeOne(callback, {'userid':'fred'})
7ec9e7 501         self.assertEqual(policy.authenticated_userid(request), 'fred')
fcc272 502
CM 503     def test_effective_principals_no_cookie_identity(self):
b60bdb 504         from pyramid.security import Everyone
fcc272 505         request = DummyRequest({})
CM 506         policy = self._makeOne(None, None)
7ec9e7 507         self.assertEqual(policy.effective_principals(request), [Everyone])
fcc272 508
CM 509     def test_effective_principals_callback_returns_None(self):
b60bdb 510         from pyramid.security import Everyone
fcc272 511         request = DummyRequest({})
dba59c 512         def callback(userid, request):
fcc272 513             return None
CM 514         policy = self._makeOne(callback, {'userid':'fred'})
7ec9e7 515         self.assertEqual(policy.effective_principals(request), [Everyone])
fcc272 516
CM 517     def test_effective_principals(self):
b60bdb 518         from pyramid.security import Everyone
CM 519         from pyramid.security import Authenticated
fcc272 520         request = DummyRequest({})
dba59c 521         def callback(userid, request):
fcc272 522             return ['group.foo']
CM 523         policy = self._makeOne(callback, {'userid':'fred'})
7ec9e7 524         self.assertEqual(policy.effective_principals(request),
fcc272 525                              [Everyone, Authenticated, 'fred', 'group.foo'])
CM 526
527     def test_remember(self):
528         request = DummyRequest({})
529         policy = self._makeOne(None, None)
7ec9e7 530         result = policy.remember(request, 'fred')
fcc272 531         self.assertEqual(result, [])
3bef31 532
CM 533     def test_remember_with_extra_kargs(self):
534         request = DummyRequest({})
535         policy = self._makeOne(None, None)
536         result = policy.remember(request, 'fred', a=1, b=2)
537         self.assertEqual(policy.cookie.kw, {'a':1, 'b':2})
538         self.assertEqual(result, [])
bf902d 539
fcc272 540     def test_forget(self):
CM 541         request = DummyRequest({})
542         policy = self._makeOne(None, None)
7ec9e7 543         result = policy.forget(request)
fcc272 544         self.assertEqual(result, [])
CM 545
19b820 546     def test_class_implements_IAuthenticationPolicy(self):
MM 547         from zope.interface.verify import verifyClass
548         from pyramid.interfaces import IAuthenticationPolicy
549         verifyClass(IAuthenticationPolicy, self._getTargetClass())
550
551     def test_instance_implements_IAuthenticationPolicy(self):
552         from zope.interface.verify import verifyObject
553         from pyramid.interfaces import IAuthenticationPolicy
554         verifyObject(IAuthenticationPolicy, self._makeOne(None, None))
555
fcc272 556 class TestAuthTktCookieHelper(unittest.TestCase):
CM 557     def _getTargetClass(self):
b60bdb 558         from pyramid.authentication import AuthTktCookieHelper
fcc272 559         return AuthTktCookieHelper
CM 560
561     def _makeOne(self, *arg, **kw):
bd0c7a 562         helper = self._getTargetClass()(*arg, **kw)
CM 563         # laziness after moving auth_tkt classes and funcs into
564         # authentication module
565         auth_tkt = DummyAuthTktModule()
566         helper.auth_tkt = auth_tkt
567         helper.AuthTicket = auth_tkt.AuthTicket
568         helper.parse_ticket = auth_tkt.parse_ticket
569         helper.BadTicket = auth_tkt.BadTicket
570         return helper
fcc272 571
fbd5b4 572     def _makeRequest(self, cookie=None, ipv6=False):
fcc272 573         environ = {'wsgi.version': (1,0)}
fbd5b4 574
BJR 575         if ipv6 is False:
576             environ['REMOTE_ADDR'] = '1.1.1.1'
577         else:
578             environ['REMOTE_ADDR'] = '::1'
fcc272 579         environ['SERVER_NAME'] = 'localhost'
bd0c7a 580         return DummyRequest(environ, cookie=cookie)
fcc272 581
839ea0 582     def _cookieValue(self, cookie):
767e44 583         items = cookie.value.split('/')
CM 584         D = {}
585         for item in items:
586             k, v = item.split('=', 1)
587             D[k] = v
588         return D
839ea0 589
CM 590     def _parseHeaders(self, headers):
591         return [ self._parseHeader(header) for header in headers ]
592
593     def _parseHeader(self, header):
594         cookie = self._parseCookie(header[1])
595         return cookie
596
597     def _parseCookie(self, cookie):
45009c 598         from pyramid.compat import SimpleCookie
839ea0 599         cookies = SimpleCookie()
CM 600         cookies.load(cookie)
601         return cookies.get('auth_tkt')
fcc272 602
e2519d 603     def test_init_cookie_str_reissue_invalid(self):
R 604         self.assertRaises(ValueError, self._makeOne, 'secret', reissue_time='invalid value')
605
606     def test_init_cookie_str_timeout_invalid(self):
607         self.assertRaises(ValueError, self._makeOne, 'secret', timeout='invalid value')
608
609     def test_init_cookie_str_max_age_invalid(self):
610         self.assertRaises(ValueError, self._makeOne, 'secret', max_age='invalid value')
611
fcc272 612     def test_identify_nocookie(self):
bd0c7a 613         helper = self._makeOne('secret')
fcc272 614         request = self._makeRequest()
bd0c7a 615         result = helper.identify(request)
fcc272 616         self.assertEqual(result, None)
474df5 617
CM 618     def test_identify_cookie_value_is_None(self):
bd0c7a 619         helper = self._makeOne('secret')
CM 620         request = self._makeRequest(None)
621         result = helper.identify(request)
474df5 622         self.assertEqual(result, None)
bf902d 623
fcc272 624     def test_identify_good_cookie_include_ip(self):
bd0c7a 625         helper = self._makeOne('secret', include_ip=True)
CM 626         request = self._makeRequest('ticket')
627         result = helper.identify(request)
fcc272 628         self.assertEqual(len(result), 4)
839ea0 629         self.assertEqual(result['tokens'], ())
fcc272 630         self.assertEqual(result['userid'], 'userid')
839ea0 631         self.assertEqual(result['userdata'], '')
CM 632         self.assertEqual(result['timestamp'], 0)
bd0c7a 633         self.assertEqual(helper.auth_tkt.value, 'ticket')
CM 634         self.assertEqual(helper.auth_tkt.remote_addr, '1.1.1.1')
635         self.assertEqual(helper.auth_tkt.secret, 'secret')
fcc272 636         environ = request.environ
839ea0 637         self.assertEqual(environ['REMOTE_USER_TOKENS'], ())
CM 638         self.assertEqual(environ['REMOTE_USER_DATA'],'')
fcc272 639         self.assertEqual(environ['AUTH_TYPE'],'cookie')
CM 640
fbd5b4 641     def test_identify_good_cookie_include_ipv6(self):
BJR 642         helper = self._makeOne('secret', include_ip=True)
643         request = self._makeRequest('ticket', ipv6=True)
644         result = helper.identify(request)
645         self.assertEqual(len(result), 4)
646         self.assertEqual(result['tokens'], ())
647         self.assertEqual(result['userid'], 'userid')
648         self.assertEqual(result['userdata'], '')
649         self.assertEqual(result['timestamp'], 0)
650         self.assertEqual(helper.auth_tkt.value, 'ticket')
651         self.assertEqual(helper.auth_tkt.remote_addr, '::1')
652         self.assertEqual(helper.auth_tkt.secret, 'secret')
653         environ = request.environ
654         self.assertEqual(environ['REMOTE_USER_TOKENS'], ())
655         self.assertEqual(environ['REMOTE_USER_DATA'],'')
656         self.assertEqual(environ['AUTH_TYPE'],'cookie')
657
fcc272 658     def test_identify_good_cookie_dont_include_ip(self):
bd0c7a 659         helper = self._makeOne('secret', include_ip=False)
CM 660         request = self._makeRequest('ticket')
661         result = helper.identify(request)
fcc272 662         self.assertEqual(len(result), 4)
839ea0 663         self.assertEqual(result['tokens'], ())
fcc272 664         self.assertEqual(result['userid'], 'userid')
839ea0 665         self.assertEqual(result['userdata'], '')
CM 666         self.assertEqual(result['timestamp'], 0)
bd0c7a 667         self.assertEqual(helper.auth_tkt.value, 'ticket')
CM 668         self.assertEqual(helper.auth_tkt.remote_addr, '0.0.0.0')
669         self.assertEqual(helper.auth_tkt.secret, 'secret')
fcc272 670         environ = request.environ
839ea0 671         self.assertEqual(environ['REMOTE_USER_TOKENS'], ())
CM 672         self.assertEqual(environ['REMOTE_USER_DATA'],'')
fcc272 673         self.assertEqual(environ['AUTH_TYPE'],'cookie')
CM 674
675     def test_identify_good_cookie_int_useridtype(self):
bd0c7a 676         helper = self._makeOne('secret', include_ip=False)
CM 677         helper.auth_tkt.userid = '1'
678         helper.auth_tkt.user_data = 'userid_type:int'
679         request = self._makeRequest('ticket')
680         result = helper.identify(request)
fcc272 681         self.assertEqual(len(result), 4)
839ea0 682         self.assertEqual(result['tokens'], ())
fcc272 683         self.assertEqual(result['userid'], 1)
CM 684         self.assertEqual(result['userdata'], 'userid_type:int')
839ea0 685         self.assertEqual(result['timestamp'], 0)
fcc272 686         environ = request.environ
839ea0 687         self.assertEqual(environ['REMOTE_USER_TOKENS'], ())
fcc272 688         self.assertEqual(environ['REMOTE_USER_DATA'],'userid_type:int')
474df5 689         self.assertEqual(environ['AUTH_TYPE'],'cookie')
CM 690
691     def test_identify_nonuseridtype_user_data(self):
bd0c7a 692         helper = self._makeOne('secret', include_ip=False)
CM 693         helper.auth_tkt.userid = '1'
694         helper.auth_tkt.user_data = 'bogus:int'
695         request = self._makeRequest('ticket')
696         result = helper.identify(request)
474df5 697         self.assertEqual(len(result), 4)
CM 698         self.assertEqual(result['tokens'], ())
699         self.assertEqual(result['userid'], '1')
700         self.assertEqual(result['userdata'], 'bogus:int')
701         self.assertEqual(result['timestamp'], 0)
702         environ = request.environ
703         self.assertEqual(environ['REMOTE_USER_TOKENS'], ())
704         self.assertEqual(environ['REMOTE_USER_DATA'],'bogus:int')
fcc272 705         self.assertEqual(environ['AUTH_TYPE'],'cookie')
CM 706
707     def test_identify_good_cookie_unknown_useridtype(self):
bd0c7a 708         helper = self._makeOne('secret', include_ip=False)
CM 709         helper.auth_tkt.userid = 'abc'
710         helper.auth_tkt.user_data = 'userid_type:unknown'
711         request = self._makeRequest('ticket')
712         result = helper.identify(request)
fcc272 713         self.assertEqual(len(result), 4)
839ea0 714         self.assertEqual(result['tokens'], ())
CM 715         self.assertEqual(result['userid'], 'abc')
fcc272 716         self.assertEqual(result['userdata'], 'userid_type:unknown')
839ea0 717         self.assertEqual(result['timestamp'], 0)
fcc272 718         environ = request.environ
839ea0 719         self.assertEqual(environ['REMOTE_USER_TOKENS'], ())
fcc272 720         self.assertEqual(environ['REMOTE_USER_DATA'],'userid_type:unknown')
839ea0 721         self.assertEqual(environ['AUTH_TYPE'],'cookie')
CM 722
723     def test_identify_good_cookie_b64str_useridtype(self):
45009c 724         from base64 import b64encode
bd0c7a 725         helper = self._makeOne('secret', include_ip=False)
45009c 726         helper.auth_tkt.userid = b64encode(b'encoded').strip()
bd0c7a 727         helper.auth_tkt.user_data = 'userid_type:b64str'
CM 728         request = self._makeRequest('ticket')
729         result = helper.identify(request)
839ea0 730         self.assertEqual(len(result), 4)
CM 731         self.assertEqual(result['tokens'], ())
45009c 732         self.assertEqual(result['userid'], b'encoded')
839ea0 733         self.assertEqual(result['userdata'], 'userid_type:b64str')
CM 734         self.assertEqual(result['timestamp'], 0)
735         environ = request.environ
736         self.assertEqual(environ['REMOTE_USER_TOKENS'], ())
737         self.assertEqual(environ['REMOTE_USER_DATA'],'userid_type:b64str')
738         self.assertEqual(environ['AUTH_TYPE'],'cookie')
739
740     def test_identify_good_cookie_b64unicode_useridtype(self):
45009c 741         from base64 import b64encode
bd0c7a 742         helper = self._makeOne('secret', include_ip=False)
45009c 743         helper.auth_tkt.userid = b64encode(b'\xc3\xa9ncoded').strip()
bd0c7a 744         helper.auth_tkt.user_data = 'userid_type:b64unicode'
CM 745         request = self._makeRequest('ticket')
746         result = helper.identify(request)
839ea0 747         self.assertEqual(len(result), 4)
CM 748         self.assertEqual(result['tokens'], ())
45009c 749         self.assertEqual(result['userid'], text_(b'\xc3\xa9ncoded', 'utf-8'))
839ea0 750         self.assertEqual(result['userdata'], 'userid_type:b64unicode')
CM 751         self.assertEqual(result['timestamp'], 0)
752         environ = request.environ
753         self.assertEqual(environ['REMOTE_USER_TOKENS'], ())
754         self.assertEqual(environ['REMOTE_USER_DATA'],'userid_type:b64unicode')
fcc272 755         self.assertEqual(environ['AUTH_TYPE'],'cookie')
CM 756
757     def test_identify_bad_cookie(self):
bd0c7a 758         helper = self._makeOne('secret', include_ip=True)
CM 759         helper.auth_tkt.parse_raise = True
760         request = self._makeRequest('ticket')
761         result = helper.identify(request)
fcc272 762         self.assertEqual(result, None)
bf902d 763
b084d7 764     def test_identify_cookie_timeout(self):
bd0c7a 765         helper = self._makeOne('secret', timeout=1)
b084d7 766         self.assertEqual(helper.timeout, 1)
fcc272 767
e2519d 768     def test_identify_cookie_str_timeout(self):
R 769         helper = self._makeOne('secret', timeout='1')
b084d7 770         self.assertEqual(helper.timeout, 1)
e2519d 771
203cf3 772     def test_identify_cookie_timeout_aged(self):
BJR 773         import time
774         helper = self._makeOne('secret', timeout=10)
775         now = time.time()
776         helper.auth_tkt.timestamp = now - 1
777         helper.now = now + 10
778         helper.auth_tkt.tokens = (text_('a'), )
779         request = self._makeRequest('bogus')
780         result = helper.identify(request)
781         self.assertFalse(result)
782
839ea0 783     def test_identify_cookie_reissue(self):
CM 784         import time
bd0c7a 785         helper = self._makeOne('secret', timeout=10, reissue_time=0)
e2519d 786         now = time.time()
R 787         helper.auth_tkt.timestamp = now
788         helper.now = now + 1
789         helper.auth_tkt.tokens = (text_('a'), )
790         request = self._makeRequest('bogus')
791         result = helper.identify(request)
792         self.assertTrue(result)
793         self.assertEqual(len(request.callbacks), 1)
794         response = DummyResponse()
795         request.callbacks[0](request, response)
796         self.assertEqual(len(response.headerlist), 3)
797         self.assertEqual(response.headerlist[0][0], 'Set-Cookie')
798
799     def test_identify_cookie_str_reissue(self):
800         import time
801         helper = self._makeOne('secret', timeout=10, reissue_time='0')
e57f5c 802         now = time.time()
bd0c7a 803         helper.auth_tkt.timestamp = now
CM 804         helper.now = now + 1
9f2d38 805         helper.auth_tkt.tokens = (text_('a'), )
bd0c7a 806         request = self._makeRequest('bogus')
CM 807         result = helper.identify(request)
a1d395 808         self.assertTrue(result)
844e98 809         self.assertEqual(len(request.callbacks), 1)
CM 810         response = DummyResponse()
863196 811         request.callbacks[0](request, response)
a58c4a 812         self.assertEqual(len(response.headerlist), 3)
CM 813         self.assertEqual(response.headerlist[0][0], 'Set-Cookie')
839ea0 814
6a47a0 815     def test_identify_cookie_reissue_already_reissued_this_request(self):
CM 816         import time
bd0c7a 817         helper = self._makeOne('secret', timeout=10, reissue_time=0)
6a47a0 818         now = time.time()
bd0c7a 819         helper.auth_tkt.timestamp = now
CM 820         helper.now = now + 1
821         request = self._makeRequest('bogus')
6a47a0 822         request._authtkt_reissued = True
bd0c7a 823         result = helper.identify(request)
a1d395 824         self.assertTrue(result)
6a47a0 825         self.assertEqual(len(request.callbacks), 0)
CM 826
827     def test_identify_cookie_reissue_notyet(self):
828         import time
bd0c7a 829         helper = self._makeOne('secret', timeout=10, reissue_time=10)
6a47a0 830         now = time.time()
bd0c7a 831         helper.auth_tkt.timestamp = now
CM 832         helper.now = now + 1
833         request = self._makeRequest('bogus')
834         result = helper.identify(request)
a1d395 835         self.assertTrue(result)
6a47a0 836         self.assertEqual(len(request.callbacks), 0)
CM 837
5620e8 838     def test_identify_cookie_reissue_revoked_by_forget(self):
MM 839         import time
840         helper = self._makeOne('secret', timeout=10, reissue_time=0)
841         now = time.time()
842         helper.auth_tkt.timestamp = now
843         helper.now = now + 1
844         request = self._makeRequest('bogus')
845         result = helper.identify(request)
846         self.assertTrue(result)
847         self.assertEqual(len(request.callbacks), 1)
848         result = helper.forget(request)
849         self.assertTrue(result)
850         self.assertEqual(len(request.callbacks), 1)
851         response = DummyResponse()
863196 852         request.callbacks[0](request, response)
5620e8 853         self.assertEqual(len(response.headerlist), 0)
MM 854
855     def test_identify_cookie_reissue_revoked_by_remember(self):
856         import time
857         helper = self._makeOne('secret', timeout=10, reissue_time=0)
858         now = time.time()
859         helper.auth_tkt.timestamp = now
860         helper.now = now + 1
861         request = self._makeRequest('bogus')
862         result = helper.identify(request)
863         self.assertTrue(result)
864         self.assertEqual(len(request.callbacks), 1)
865         result = helper.remember(request, 'bob')
866         self.assertTrue(result)
867         self.assertEqual(len(request.callbacks), 1)
868         response = DummyResponse()
863196 869         request.callbacks[0](request, response)
5620e8 870         self.assertEqual(len(response.headerlist), 0)
MM 871
cf3177 872     def test_identify_cookie_reissue_with_tokens_default(self):
CM 873         # see https://github.com/Pylons/pyramid/issues#issue/108
884487 874         import time
bd0c7a 875         helper = self._makeOne('secret', timeout=10, reissue_time=0)
CM 876         auth_tkt = DummyAuthTktModule(tokens=[''])
877         helper.auth_tkt = auth_tkt
878         helper.AuthTicket = auth_tkt.AuthTicket
879         helper.parse_ticket = auth_tkt.parse_ticket
880         helper.BadTicket = auth_tkt.BadTicket
884487 881         now = time.time()
bd0c7a 882         helper.auth_tkt.timestamp = now
CM 883         helper.now = now + 1
884         request = self._makeRequest('bogus')
885         result = helper.identify(request)
a1d395 886         self.assertTrue(result)
884487 887         self.assertEqual(len(request.callbacks), 1)
WA 888         response = DummyResponse()
889         request.callbacks[0](None, response)
890         self.assertEqual(len(response.headerlist), 3)
891         self.assertEqual(response.headerlist[0][0], 'Set-Cookie')
767e44 892         self.assertTrue("/tokens=/" in response.headerlist[0][1])
884487 893
839ea0 894     def test_remember(self):
bd0c7a 895         helper = self._makeOne('secret')
839ea0 896         request = self._makeRequest()
bd0c7a 897         result = helper.remember(request, 'userid')
fcc272 898         self.assertEqual(len(result), 3)
dfc2b6 899
CM 900         self.assertEqual(result[0][0], 'Set-Cookie')
87771a 901         self.assertTrue(result[0][1].endswith('; Path=/; SameSite=Lax'))
a1d395 902         self.assertTrue(result[0][1].startswith('auth_tkt='))
dfc2b6 903
CM 904         self.assertEqual(result[1][0], 'Set-Cookie')
87771a 905         self.assertTrue(result[1][1].endswith(
CM 906             '; Domain=localhost; Path=/; SameSite=Lax'))
a1d395 907         self.assertTrue(result[1][1].startswith('auth_tkt='))
dfc2b6 908
CM 909         self.assertEqual(result[2][0], 'Set-Cookie')
87771a 910         self.assertTrue(result[2][1].endswith(
CM 911             '; Domain=.localhost; Path=/; SameSite=Lax'))
912         self.assertTrue(result[2][1].startswith('auth_tkt='))
913
914     def test_remember_nondefault_samesite(self):
915         helper = self._makeOne('secret', samesite='Strict')
916         request = self._makeRequest()
917         result = helper.remember(request, 'userid')
918         self.assertEqual(len(result), 3)
919
920         self.assertEqual(result[0][0], 'Set-Cookie')
921         self.assertTrue(result[0][1].endswith('; Path=/; SameSite=Strict'))
922         self.assertTrue(result[0][1].startswith('auth_tkt='))
923
924         self.assertEqual(result[1][0], 'Set-Cookie')
925         self.assertTrue(result[1][1].endswith(
926             '; Domain=localhost; Path=/; SameSite=Strict'))
927         self.assertTrue(result[1][1].startswith('auth_tkt='))
928
929         self.assertEqual(result[2][0], 'Set-Cookie')
930         self.assertTrue(result[2][1].endswith(
931             '; Domain=.localhost; Path=/; SameSite=Strict'))
932         self.assertTrue(result[2][1].startswith('auth_tkt='))
933
934     def test_remember_None_samesite(self):
935         helper = self._makeOne('secret', samesite=None)
936         request = self._makeRequest()
937         result = helper.remember(request, 'userid')
938         self.assertEqual(len(result), 3)
939
940         self.assertEqual(result[0][0], 'Set-Cookie')
941         self.assertTrue(result[0][1].endswith('; Path=/')) # no samesite
942         self.assertTrue(result[0][1].startswith('auth_tkt='))
943
944         self.assertEqual(result[1][0], 'Set-Cookie')
945         self.assertTrue(result[1][1].endswith(
946             '; Domain=localhost; Path=/'))
947         self.assertTrue(result[1][1].startswith('auth_tkt='))
948
949         self.assertEqual(result[2][0], 'Set-Cookie')
950         self.assertTrue(result[2][1].endswith(
951             '; Domain=.localhost; Path=/'))
a1d395 952         self.assertTrue(result[2][1].startswith('auth_tkt='))
fcc272 953
839ea0 954     def test_remember_include_ip(self):
bd0c7a 955         helper = self._makeOne('secret', include_ip=True)
839ea0 956         request = self._makeRequest()
bd0c7a 957         result = helper.remember(request, 'other')
fcc272 958         self.assertEqual(len(result), 3)
CM 959
839ea0 960         self.assertEqual(result[0][0], 'Set-Cookie')
87771a 961         self.assertTrue(result[0][1].endswith('; Path=/; SameSite=Lax'))
a1d395 962         self.assertTrue(result[0][1].startswith('auth_tkt='))
839ea0 963
CM 964         self.assertEqual(result[1][0], 'Set-Cookie')
87771a 965         self.assertTrue(result[1][1].endswith(
CM 966             '; Domain=localhost; Path=/; SameSite=Lax'))
a1d395 967         self.assertTrue(result[1][1].startswith('auth_tkt='))
839ea0 968
CM 969         self.assertEqual(result[2][0], 'Set-Cookie')
87771a 970         self.assertTrue(result[2][1].endswith(
CM 971             '; Domain=.localhost; Path=/; SameSite=Lax'))
a1d395 972         self.assertTrue(result[2][1].startswith('auth_tkt='))
839ea0 973
5ba063 974     def test_remember_path(self):
bd0c7a 975         helper = self._makeOne('secret', include_ip=True,
cba2e1 976                                path="/cgi-bin/app.cgi/")
5ba063 977         request = self._makeRequest()
bd0c7a 978         result = helper.remember(request, 'other')
5ba063 979         self.assertEqual(len(result), 3)
CM 980
981         self.assertEqual(result[0][0], 'Set-Cookie')
87771a 982         self.assertTrue(result[0][1].endswith(
CM 983             '; Path=/cgi-bin/app.cgi/; SameSite=Lax'))
a1d395 984         self.assertTrue(result[0][1].startswith('auth_tkt='))
5ba063 985
CM 986         self.assertEqual(result[1][0], 'Set-Cookie')
a1d395 987         self.assertTrue(result[1][1].endswith(
87771a 988             '; Domain=localhost; Path=/cgi-bin/app.cgi/; SameSite=Lax'))
a1d395 989         self.assertTrue(result[1][1].startswith('auth_tkt='))
5ba063 990
CM 991         self.assertEqual(result[2][0], 'Set-Cookie')
a1d395 992         self.assertTrue(result[2][1].endswith(
87771a 993             '; Domain=.localhost; Path=/cgi-bin/app.cgi/; SameSite=Lax'))
a1d395 994         self.assertTrue(result[2][1].startswith('auth_tkt='))
5ba063 995
CM 996     def test_remember_http_only(self):
bd0c7a 997         helper = self._makeOne('secret', include_ip=True, http_only=True)
5ba063 998         request = self._makeRequest()
bd0c7a 999         result = helper.remember(request, 'other')
5ba063 1000         self.assertEqual(len(result), 3)
CM 1001
1002         self.assertEqual(result[0][0], 'Set-Cookie')
87771a 1003         self.assertTrue(result[0][1].endswith('; HttpOnly; SameSite=Lax'))
a1d395 1004         self.assertTrue(result[0][1].startswith('auth_tkt='))
5ba063 1005
CM 1006         self.assertEqual(result[1][0], 'Set-Cookie')
c65b85 1007         self.assertTrue('; HttpOnly' in result[1][1])
a1d395 1008         self.assertTrue(result[1][1].startswith('auth_tkt='))
5ba063 1009
CM 1010         self.assertEqual(result[2][0], 'Set-Cookie')
c65b85 1011         self.assertTrue('; HttpOnly' in result[2][1])
a1d395 1012         self.assertTrue(result[2][1].startswith('auth_tkt='))
5ba063 1013
CM 1014     def test_remember_secure(self):
bd0c7a 1015         helper = self._makeOne('secret', include_ip=True, secure=True)
5ba063 1016         request = self._makeRequest()
bd0c7a 1017         result = helper.remember(request, 'other')
5ba063 1018         self.assertEqual(len(result), 3)
CM 1019
1020         self.assertEqual(result[0][0], 'Set-Cookie')
767e44 1021         self.assertTrue('; secure' in result[0][1])
a1d395 1022         self.assertTrue(result[0][1].startswith('auth_tkt='))
5ba063 1023
CM 1024         self.assertEqual(result[1][0], 'Set-Cookie')
767e44 1025         self.assertTrue('; secure' in result[1][1])
a1d395 1026         self.assertTrue(result[1][1].startswith('auth_tkt='))
5ba063 1027
CM 1028         self.assertEqual(result[2][0], 'Set-Cookie')
767e44 1029         self.assertTrue('; secure' in result[2][1])
a1d395 1030         self.assertTrue(result[2][1].startswith('auth_tkt='))
5ba063 1031
3dc86f 1032     def test_remember_wild_domain_disabled(self):
bd0c7a 1033         helper = self._makeOne('secret', wild_domain=False)
3dc86f 1034         request = self._makeRequest()
bd0c7a 1035         result = helper.remember(request, 'other')
3dc86f 1036         self.assertEqual(len(result), 2)
MM 1037
1038         self.assertEqual(result[0][0], 'Set-Cookie')
87771a 1039         self.assertTrue(result[0][1].endswith('; Path=/; SameSite=Lax'))
a1d395 1040         self.assertTrue(result[0][1].startswith('auth_tkt='))
3dc86f 1041
MM 1042         self.assertEqual(result[1][0], 'Set-Cookie')
87771a 1043         self.assertTrue(result[1][1].endswith(
CM 1044             '; Domain=localhost; Path=/; SameSite=Lax'))
a1d395 1045         self.assertTrue(result[1][1].startswith('auth_tkt='))
3dc86f 1046
188aa7 1047     def test_remember_parent_domain(self):
WA 1048         helper = self._makeOne('secret', parent_domain=True)
1049         request = self._makeRequest()
767e44 1050         request.domain = 'www.example.com'
188aa7 1051         result = helper.remember(request, 'other')
c65b85 1052         self.assertEqual(len(result), 1)
188aa7 1053
WA 1054         self.assertEqual(result[0][0], 'Set-Cookie')
87771a 1055         self.assertTrue(result[0][1].endswith(
CM 1056             '; Domain=.example.com; Path=/; SameSite=Lax'))
188aa7 1057         self.assertTrue(result[0][1].startswith('auth_tkt='))
WA 1058
1059     def test_remember_parent_domain_supercedes_wild_domain(self):
1060         helper = self._makeOne('secret', parent_domain=True, wild_domain=True)
1061         request = self._makeRequest()
767e44 1062         request.domain = 'www.example.com'
188aa7 1063         result = helper.remember(request, 'other')
c65b85 1064         self.assertEqual(len(result), 1)
87771a 1065         self.assertTrue(result[0][1].endswith(
CM 1066             '; Domain=.example.com; Path=/; SameSite=Lax'))
188aa7 1067
a1f768 1068     def test_remember_explicit_domain(self):
WA 1069         helper = self._makeOne('secret', domain='pyramid.bazinga')
1070         request = self._makeRequest()
767e44 1071         request.domain = 'www.example.com'
a1f768 1072         result = helper.remember(request, 'other')
WA 1073         self.assertEqual(len(result), 1)
1074
1075         self.assertEqual(result[0][0], 'Set-Cookie')
767e44 1076         self.assertTrue(result[0][1].endswith(
87771a 1077                 '; Domain=pyramid.bazinga; Path=/; SameSite=Lax'))
a1f768 1078         self.assertTrue(result[0][1].startswith('auth_tkt='))
WA 1079
1080     def test_remember_domain_supercedes_parent_and_wild_domain(self):
1081         helper = self._makeOne('secret', domain='pyramid.bazinga',
1082                 parent_domain=True, wild_domain=True)
1083         request = self._makeRequest()
767e44 1084         request.domain = 'www.example.com'
a1f768 1085         result = helper.remember(request, 'other')
WA 1086         self.assertEqual(len(result), 1)
767e44 1087         self.assertTrue(result[0][1].endswith(
87771a 1088                 '; Domain=pyramid.bazinga; Path=/; SameSite=Lax'))
bf902d 1089
45009c 1090     def test_remember_binary_userid(self):
CM 1091         import base64
bd0c7a 1092         helper = self._makeOne('secret')
839ea0 1093         request = self._makeRequest()
45009c 1094         result = helper.remember(request, b'userid')
839ea0 1095         values = self._parseHeaders(result)
fcc272 1096         self.assertEqual(len(result), 3)
839ea0 1097         val = self._cookieValue(values[0])
45009c 1098         self.assertEqual(val['userid'],
767e44 1099                          text_(base64.b64encode(b'userid').strip()))
839ea0 1100         self.assertEqual(val['user_data'], 'userid_type:b64str')
fcc272 1101
839ea0 1102     def test_remember_int_userid(self):
bd0c7a 1103         helper = self._makeOne('secret')
839ea0 1104         request = self._makeRequest()
bd0c7a 1105         result = helper.remember(request, 1)
839ea0 1106         values = self._parseHeaders(result)
fcc272 1107         self.assertEqual(len(result), 3)
839ea0 1108         val = self._cookieValue(values[0])
CM 1109         self.assertEqual(val['userid'], '1')
1110         self.assertEqual(val['user_data'], 'userid_type:int')
fcc272 1111
839ea0 1112     def test_remember_long_userid(self):
45009c 1113         from pyramid.compat import long
bd0c7a 1114         helper = self._makeOne('secret')
839ea0 1115         request = self._makeRequest()
bd0c7a 1116         result = helper.remember(request, long(1))
839ea0 1117         values = self._parseHeaders(result)
fcc272 1118         self.assertEqual(len(result), 3)
839ea0 1119         val = self._cookieValue(values[0])
CM 1120         self.assertEqual(val['userid'], '1')
1121         self.assertEqual(val['user_data'], 'userid_type:int')
fcc272 1122
839ea0 1123     def test_remember_unicode_userid(self):
45009c 1124         import base64
bd0c7a 1125         helper = self._makeOne('secret')
839ea0 1126         request = self._makeRequest()
45009c 1127         userid = text_(b'\xc2\xa9', 'utf-8')
bd0c7a 1128         result = helper.remember(request, userid)
839ea0 1129         values = self._parseHeaders(result)
fcc272 1130         self.assertEqual(len(result), 3)
839ea0 1131         val = self._cookieValue(values[0])
CM 1132         self.assertEqual(val['userid'],
767e44 1133                          text_(base64.b64encode(userid.encode('utf-8'))))
839ea0 1134         self.assertEqual(val['user_data'], 'userid_type:b64unicode')
fcc272 1135
6a47a0 1136     def test_remember_insane_userid(self):
bd0c7a 1137         helper = self._makeOne('secret')
6a47a0 1138         request = self._makeRequest()
CM 1139         userid = object()
5b7eee 1140         with warnings.catch_warnings(record=True) as w:
MM 1141             warnings.simplefilter('always', RuntimeWarning)
1142             result = helper.remember(request, userid)
1143             self.assertTrue(str(w[-1].message).startswith('userid is of type'))
6a47a0 1144         values = self._parseHeaders(result)
CM 1145         self.assertEqual(len(result), 3)
1146         value = values[0]
a1d395 1147         self.assertTrue('userid' in value.value)
6a47a0 1148
3bef31 1149     def test_remember_max_age(self):
bd0c7a 1150         helper = self._makeOne('secret')
839ea0 1151         request = self._makeRequest()
e2519d 1152         result = helper.remember(request, 'userid', max_age=500)
R 1153         values = self._parseHeaders(result)
1154         self.assertEqual(len(result), 3)
1155
1156         self.assertEqual(values[0]['max-age'], '500')
1157         self.assertTrue(values[0]['expires'])
1158
1159     def test_remember_str_max_age(self):
1160         helper = self._makeOne('secret')
1161         request = self._makeRequest()
bd0c7a 1162         result = helper.remember(request, 'userid', max_age='500')
839ea0 1163         values = self._parseHeaders(result)
CM 1164         self.assertEqual(len(result), 3)
1165
1166         self.assertEqual(values[0]['max-age'], '500')
a1d395 1167         self.assertTrue(values[0]['expires'])
17c4de 1168
e2519d 1169     def test_remember_str_max_age_invalid(self):
R 1170         helper = self._makeOne('secret')
1171         request = self._makeRequest()
1172         self.assertRaises(ValueError, helper.remember, request, 'userid', max_age='invalid value')
1173
17c4de 1174     def test_remember_tokens(self):
bd0c7a 1175         helper = self._makeOne('secret')
17c4de 1176         request = self._makeRequest()
bd0c7a 1177         result = helper.remember(request, 'other', tokens=('foo', 'bar'))
17c4de 1178         self.assertEqual(len(result), 3)
WA 1179
1180         self.assertEqual(result[0][0], 'Set-Cookie')
767e44 1181         self.assertTrue("/tokens=foo|bar/" in result[0][1])
17c4de 1182
WA 1183         self.assertEqual(result[1][0], 'Set-Cookie')
767e44 1184         self.assertTrue("/tokens=foo|bar/" in result[1][1])
17c4de 1185
WA 1186         self.assertEqual(result[2][0], 'Set-Cookie')
767e44 1187         self.assertTrue("/tokens=foo|bar/" in result[2][1])
17c4de 1188
87771a 1189     def test_remember_samesite_nondefault(self):
CM 1190         helper = self._makeOne('secret', samesite='Strict')
1191         request = self._makeRequest()
1192         result = helper.remember(request, 'userid')
1193         self.assertEqual(len(result), 3)
ea8120 1194
87771a 1195         self.assertEqual(result[0][0], 'Set-Cookie')
CM 1196         cookieval = result[0][1]
1197         self.assertTrue('SameSite=Strict' in
1198                         [x.strip() for x in cookieval.split(';')], cookieval)
1199
1200         self.assertEqual(result[1][0], 'Set-Cookie')
1201         cookieval = result[1][1]
1202         self.assertTrue('SameSite=Strict' in
1203                         [x.strip() for x in cookieval.split(';')], cookieval)
1204
1205         self.assertEqual(result[2][0], 'Set-Cookie')
1206         cookieval = result[2][1]
1207         self.assertTrue('SameSite=Strict' in
1208                         [x.strip() for x in cookieval.split(';')], cookieval)
1209
1210     def test_remember_samesite_default(self):
1211         helper = self._makeOne('secret')
1212         request = self._makeRequest()
1213         result = helper.remember(request, 'userid')
1214         self.assertEqual(len(result), 3)
1215
1216         self.assertEqual(result[0][0], 'Set-Cookie')
1217         cookieval = result[0][1]
1218         self.assertTrue('SameSite=Lax' in
1219                         [x.strip() for x in cookieval.split(';')], cookieval)
1220
1221         self.assertEqual(result[1][0], 'Set-Cookie')
1222         cookieval = result[1][1]
1223         self.assertTrue('SameSite=Lax' in
1224                         [x.strip() for x in cookieval.split(';')], cookieval)
1225
1226         self.assertEqual(result[2][0], 'Set-Cookie')
1227         cookieval = result[2][1]
1228         self.assertTrue('SameSite=Lax' in
1229                         [x.strip() for x in cookieval.split(';')], cookieval)
1230
dd5a91 1231     def test_remember_unicode_but_ascii_token(self):
WA 1232         helper = self._makeOne('secret')
1233         request = self._makeRequest()
1234         la = text_(b'foo', 'utf-8')
c3c0be 1235         result = helper.remember(request, 'other', tokens=(la,))
BS 1236         # tokens must be str type on both Python 2 and 3
767e44 1237         self.assertTrue("/tokens=foo/" in result[0][1])
dd5a91 1238
45009c 1239     def test_remember_nonascii_token(self):
bd0c7a 1240         helper = self._makeOne('secret')
69869e 1241         request = self._makeRequest()
45009c 1242         la = text_(b'La Pe\xc3\xb1a', 'utf-8')
bd0c7a 1243         self.assertRaises(ValueError, helper.remember, request, 'other',
45009c 1244                           tokens=(la,))
69869e 1245
WA 1246     def test_remember_invalid_token_format(self):
bd0c7a 1247         helper = self._makeOne('secret')
69869e 1248         request = self._makeRequest()
bd0c7a 1249         self.assertRaises(ValueError, helper.remember, request, 'other',
cf3177 1250                           tokens=('foo bar',))
bd0c7a 1251         self.assertRaises(ValueError, helper.remember, request, 'other',
cf3177 1252                           tokens=('1bar',))
69869e 1253
fcc272 1254     def test_forget(self):
bd0c7a 1255         helper = self._makeOne('secret')
fcc272 1256         request = self._makeRequest()
bd0c7a 1257         headers = helper.forget(request)
fcc272 1258         self.assertEqual(len(headers), 3)
839ea0 1259         name, value = headers[0]
fcc272 1260         self.assertEqual(name, 'Set-Cookie')
767e44 1261         self.assertEqual(
CM 1262             value,
1263             'auth_tkt=; Max-Age=0; Path=/; '
87771a 1264             'expires=Wed, 31-Dec-97 23:59:59 GMT; SameSite=Lax'
767e44 1265             )
839ea0 1266         name, value = headers[1]
fcc272 1267         self.assertEqual(name, 'Set-Cookie')
767e44 1268         self.assertEqual(
CM 1269             value,
1270             'auth_tkt=; Domain=localhost; Max-Age=0; Path=/; '
87771a 1271             'expires=Wed, 31-Dec-97 23:59:59 GMT; SameSite=Lax'
767e44 1272             )
839ea0 1273         name, value = headers[2]
fcc272 1274         self.assertEqual(name, 'Set-Cookie')
767e44 1275         self.assertEqual(
CM 1276             value,
1277             'auth_tkt=; Domain=.localhost; Max-Age=0; Path=/; '
87771a 1278             'expires=Wed, 31-Dec-97 23:59:59 GMT; SameSite=Lax'
767e44 1279             )
a1a9fb 1280
bd0c7a 1281 class TestAuthTicket(unittest.TestCase):
CM 1282     def _makeOne(self, *arg, **kw):
1283         from pyramid.authentication import AuthTicket
1284         return AuthTicket(*arg, **kw)
1285
1286     def test_ctor_with_tokens(self):
1287         ticket = self._makeOne('secret', 'userid', 'ip', tokens=('a', 'b'))
1288         self.assertEqual(ticket.tokens, 'a,b')
1289
1290     def test_ctor_with_time(self):
1291         ticket = self._makeOne('secret', 'userid', 'ip', time='time')
1292         self.assertEqual(ticket.time, 'time')
1293
1294     def test_digest(self):
1295         ticket = self._makeOne('secret', 'userid', '0.0.0.0', time=10)
1296         result = ticket.digest()
1297         self.assertEqual(result, '126fd6224912187ee9ffa80e0b81420c')
1298
801adf 1299     def test_digest_sha512(self):
DK 1300         ticket = self._makeOne('secret', 'userid', '0.0.0.0',
1301                                time=10, hashalg='sha512')
1302         result = ticket.digest()
1303         self.assertEqual(result, '74770b2e0d5b1a54c2a466ec567a40f7d7823576aa49'\
1304                                  '3c65fc3445e9b44097f4a80410319ef8cb256a2e60b9'\
1305                                  'c2002e48a9e33a3e8ee4379352c04ef96d2cb278')
1306
bd0c7a 1307     def test_cookie_value(self):
CM 1308         ticket = self._makeOne('secret', 'userid', '0.0.0.0', time=10,
1309                                tokens=('a', 'b'))
1310         result = ticket.cookie_value()
1311         self.assertEqual(result,
1312                          '66f9cc3e423dc57c91df696cf3d1f0d80000000auserid!a,b!')
1313
54d313 1314     def test_ipv4(self):
BJR 1315         ticket = self._makeOne('secret', 'userid', '198.51.100.1',
1316                                time=10, hashalg='sha256')
1317         result = ticket.cookie_value()
1318         self.assertEqual(result, 'b3e7156db4f8abde4439c4a6499a0668f9e7ffd7fa27b'\
1319                                  '798400ecdade8d76c530000000auserid!')
1320
1321     def test_ipv6(self):
1322         ticket = self._makeOne('secret', 'userid', '2001:db8::1',
1323                                time=10, hashalg='sha256')
1324         result = ticket.cookie_value()
1325         self.assertEqual(result, 'd025b601a0f12ca6d008aa35ff3a22b7d8f3d1c1456c8'\
1326                                  '5becf8760cd7a2fa4910000000auserid!')
1327
bd0c7a 1328 class TestBadTicket(unittest.TestCase):
CM 1329     def _makeOne(self, msg, expected=None):
1330         from pyramid.authentication import BadTicket
1331         return BadTicket(msg, expected)
1332
1333     def test_it(self):
1334         exc = self._makeOne('msg', expected=True)
1335         self.assertEqual(exc.expected, True)
1336         self.assertTrue(isinstance(exc, Exception))
1337
1338 class Test_parse_ticket(unittest.TestCase):
801adf 1339     def _callFUT(self, secret, ticket, ip, hashalg='md5'):
bd0c7a 1340         from pyramid.authentication import parse_ticket
801adf 1341         return parse_ticket(secret, ticket, ip, hashalg)
bd0c7a 1342
801adf 1343     def _assertRaisesBadTicket(self, secret, ticket, ip, hashalg='md5'):
bd0c7a 1344         from pyramid.authentication import BadTicket
801adf 1345         self.assertRaises(BadTicket,self._callFUT, secret, ticket, ip, hashalg)
bd0c7a 1346
CM 1347     def test_bad_timestamp(self):
1348         ticket = 'x' * 64
1349         self._assertRaisesBadTicket('secret', ticket, 'ip')
1350
1351     def test_bad_userid_or_data(self):
1352         ticket = 'x' * 32 + '11111111' + 'x' * 10
1353         self._assertRaisesBadTicket('secret', ticket, 'ip')
1354
1355     def test_digest_sig_incorrect(self):
1356         ticket = 'x' * 32 + '11111111' + 'a!b!c'
1357         self._assertRaisesBadTicket('secret', ticket, '0.0.0.0')
1358
1359     def test_correct_with_user_data(self):
eb2bc8 1360         ticket = text_('66f9cc3e423dc57c91df696cf3d1f0d80000000auserid!a,b!')
bd0c7a 1361         result = self._callFUT('secret', ticket, '0.0.0.0')
801adf 1362         self.assertEqual(result, (10, 'userid', ['a', 'b'], ''))
DK 1363
1364     def test_correct_with_user_data_sha512(self):
eb2bc8 1365         ticket = text_('7d947cdef99bad55f8e3382a8bd089bb9dd0547f7925b7d189adc1'
MM 1366                        '160cab0ec0e6888faa41eba641a18522b26f19109f3ffafb769767'
1367                        'ba8a26d02aaeae56599a0000000auserid!a,b!')
801adf 1368         result = self._callFUT('secret', ticket, '0.0.0.0', 'sha512')
bd0c7a 1369         self.assertEqual(result, (10, 'userid', ['a', 'b'], ''))
ef992f 1370
54d313 1371     def test_ipv4(self):
eb2bc8 1372         ticket = text_('b3e7156db4f8abde4439c4a6499a0668f9e7ffd7fa27b798400ecd'
MM 1373                        'ade8d76c530000000auserid!')
54d313 1374         result = self._callFUT('secret', ticket, '198.51.100.1', 'sha256')
BJR 1375         self.assertEqual(result, (10, 'userid', [''], ''))
1376
1377     def test_ipv6(self):
eb2bc8 1378         ticket = text_('d025b601a0f12ca6d008aa35ff3a22b7d8f3d1c1456c85becf8760'
MM 1379                        'cd7a2fa4910000000auserid!')
54d313 1380         result = self._callFUT('secret', ticket, '2001:db8::1', 'sha256')
BJR 1381         self.assertEqual(result, (10, 'userid', [''], ''))
1382
ef992f 1383 class TestSessionAuthenticationPolicy(unittest.TestCase):
MM 1384     def _getTargetClass(self):
1385         from pyramid.authentication import SessionAuthenticationPolicy
1386         return SessionAuthenticationPolicy
1387
1388     def _makeOne(self, callback=None, prefix=''):
1389         return self._getTargetClass()(prefix=prefix, callback=callback)
1390
1391     def test_class_implements_IAuthenticationPolicy(self):
1392         from zope.interface.verify import verifyClass
1393         from pyramid.interfaces import IAuthenticationPolicy
1394         verifyClass(IAuthenticationPolicy, self._getTargetClass())
1395
1396     def test_instance_implements_IAuthenticationPolicy(self):
1397         from zope.interface.verify import verifyObject
1398         from pyramid.interfaces import IAuthenticationPolicy
1399         verifyObject(IAuthenticationPolicy, self._makeOne())
1400
1401     def test_unauthenticated_userid_returns_None(self):
1402         request = DummyRequest()
1403         policy = self._makeOne()
1404         self.assertEqual(policy.unauthenticated_userid(request), None)
1405
1406     def test_unauthenticated_userid(self):
1407         request = DummyRequest(session={'userid':'fred'})
1408         policy = self._makeOne()
1409         self.assertEqual(policy.unauthenticated_userid(request), 'fred')
1410
1411     def test_authenticated_userid_no_cookie_identity(self):
1412         request = DummyRequest()
1413         policy = self._makeOne()
1414         self.assertEqual(policy.authenticated_userid(request), None)
1415
1416     def test_authenticated_userid_callback_returns_None(self):
1417         request = DummyRequest(session={'userid':'fred'})
1418         def callback(userid, request):
1419             return None
1420         policy = self._makeOne(callback)
1421         self.assertEqual(policy.authenticated_userid(request), None)
1422
1423     def test_authenticated_userid(self):
1424         request = DummyRequest(session={'userid':'fred'})
1425         def callback(userid, request):
1426             return True
1427         policy = self._makeOne(callback)
1428         self.assertEqual(policy.authenticated_userid(request), 'fred')
1429
1430     def test_effective_principals_no_identity(self):
1431         from pyramid.security import Everyone
1432         request = DummyRequest()
1433         policy = self._makeOne()
1434         self.assertEqual(policy.effective_principals(request), [Everyone])
1435
1436     def test_effective_principals_callback_returns_None(self):
1437         from pyramid.security import Everyone
1438         request = DummyRequest(session={'userid':'fred'})
1439         def callback(userid, request):
1440             return None
1441         policy = self._makeOne(callback)
1442         self.assertEqual(policy.effective_principals(request), [Everyone])
1443
1444     def test_effective_principals(self):
1445         from pyramid.security import Everyone
1446         from pyramid.security import Authenticated
1447         request = DummyRequest(session={'userid':'fred'})
1448         def callback(userid, request):
1449             return ['group.foo']
1450         policy = self._makeOne(callback)
1451         self.assertEqual(policy.effective_principals(request),
1452                          [Everyone, Authenticated, 'fred', 'group.foo'])
1453
1454     def test_remember(self):
1455         request = DummyRequest()
1456         policy = self._makeOne()
1457         result = policy.remember(request, 'fred')
1458         self.assertEqual(request.session.get('userid'), 'fred')
1459         self.assertEqual(result, [])
1460
1461     def test_forget(self):
1462         request = DummyRequest(session={'userid':'fred'})
1463         policy = self._makeOne()
1464         result = policy.forget(request)
1465         self.assertEqual(request.session.get('userid'), None)
1466         self.assertEqual(result, [])
1467
1468     def test_forget_no_identity(self):
1469         request = DummyRequest()
1470         policy = self._makeOne()
1471         result = policy.forget(request)
1472         self.assertEqual(request.session.get('userid'), None)
1473         self.assertEqual(result, [])
bd0c7a 1474
bf902d 1475 class TestBasicAuthAuthenticationPolicy(unittest.TestCase):
CR 1476     def _getTargetClass(self):
1477         from pyramid.authentication import BasicAuthAuthenticationPolicy as cls
1478         return cls
1479
1480     def _makeOne(self, check):
1481         return self._getTargetClass()(check, realm='SomeRealm')
1482
1483     def test_class_implements_IAuthenticationPolicy(self):
1484         from zope.interface.verify import verifyClass
1485         from pyramid.interfaces import IAuthenticationPolicy
1486         verifyClass(IAuthenticationPolicy, self._getTargetClass())
1487
1488     def test_unauthenticated_userid(self):
1489         import base64
1490         request = testing.DummyRequest()
1491         request.headers['Authorization'] = 'Basic %s' % base64.b64encode(
407e30 1492             bytes_('chrisr:password')).decode('ascii')
bf902d 1493         policy = self._makeOne(None)
CR 1494         self.assertEqual(policy.unauthenticated_userid(request), 'chrisr')
1495
1496     def test_unauthenticated_userid_no_credentials(self):
1497         request = testing.DummyRequest()
1498         policy = self._makeOne(None)
1499         self.assertEqual(policy.unauthenticated_userid(request), None)
1500
1501     def test_unauthenticated_bad_header(self):
1502         request = testing.DummyRequest()
1503         request.headers['Authorization'] = '...'
1504         policy = self._makeOne(None)
1505         self.assertEqual(policy.unauthenticated_userid(request), None)
1506
1507     def test_unauthenticated_userid_not_basic(self):
1508         request = testing.DummyRequest()
1509         request.headers['Authorization'] = 'Complicated things'
1510         policy = self._makeOne(None)
1511         self.assertEqual(policy.unauthenticated_userid(request), None)
1512
1513     def test_unauthenticated_userid_corrupt_base64(self):
1514         request = testing.DummyRequest()
1515         request.headers['Authorization'] = 'Basic chrisr:password'
1516         policy = self._makeOne(None)
1517         self.assertEqual(policy.unauthenticated_userid(request), None)
1518
1519     def test_authenticated_userid(self):
1520         import base64
1521         request = testing.DummyRequest()
1522         request.headers['Authorization'] = 'Basic %s' % base64.b64encode(
407e30 1523             bytes_('chrisr:password')).decode('ascii')
bf902d 1524         def check(username, password, request):
CR 1525             return []
1526         policy = self._makeOne(check)
1527         self.assertEqual(policy.authenticated_userid(request), 'chrisr')
1528
5cc157 1529     def test_authenticated_userid_utf8(self):
CH 1530         import base64
1531         request = testing.DummyRequest()
6c98b1 1532         inputs = (b'm\xc3\xb6rk\xc3\xb6:'
MM 1533                   b'm\xc3\xb6rk\xc3\xb6password').decode('utf-8')
604297 1534         request.headers['Authorization'] = 'Basic %s' % (
6c98b1 1535             base64.b64encode(inputs.encode('utf-8')).decode('latin-1'))
5cc157 1536         def check(username, password, request):
CH 1537             return []
1538         policy = self._makeOne(check)
604297 1539         self.assertEqual(policy.authenticated_userid(request),
MM 1540                          b'm\xc3\xb6rk\xc3\xb6'.decode('utf-8'))
1541
1542     def test_authenticated_userid_latin1(self):
1543         import base64
1544         request = testing.DummyRequest()
6c98b1 1545         inputs = (b'm\xc3\xb6rk\xc3\xb6:'
MM 1546                   b'm\xc3\xb6rk\xc3\xb6password').decode('utf-8')
604297 1547         request.headers['Authorization'] = 'Basic %s' % (
6c98b1 1548             base64.b64encode(inputs.encode('latin-1')).decode('latin-1'))
604297 1549         def check(username, password, request):
MM 1550             return []
1551         policy = self._makeOne(check)
1552         self.assertEqual(policy.authenticated_userid(request),
1553                          b'm\xc3\xb6rk\xc3\xb6'.decode('utf-8'))
5cc157 1554
bf902d 1555     def test_unauthenticated_userid_invalid_payload(self):
CR 1556         import base64
1557         request = testing.DummyRequest()
1558         request.headers['Authorization'] = 'Basic %s' % base64.b64encode(
407e30 1559             bytes_('chrisrpassword')).decode('ascii')
bf902d 1560         policy = self._makeOne(None)
CR 1561         self.assertEqual(policy.unauthenticated_userid(request), None)
1562
1563     def test_remember(self):
1564         policy = self._makeOne(None)
1565         self.assertEqual(policy.remember(None, None), [])
1566
1567     def test_forget(self):
1568         policy = self._makeOne(None)
1569         self.assertEqual(policy.forget(None), [
1570             ('WWW-Authenticate', 'Basic realm="SomeRealm"')])
1571
830bcb 1572
DG 1573 class TestExtractHTTPBasicCredentials(unittest.TestCase):
1574     def _get_func(self):
1575         from pyramid.authentication import extract_http_basic_credentials
1576         return extract_http_basic_credentials
1577
1578     def test_no_auth_header(self):
1579         request = testing.DummyRequest()
1580         fn = self._get_func()
1581
1582         self.assertIsNone(fn(request))
1583
1584     def test_invalid_payload(self):
1585         import base64
1586         request = testing.DummyRequest()
1587         request.headers['Authorization'] = 'Basic %s' % base64.b64encode(
1588             bytes_('chrisrpassword')).decode('ascii')
1589         fn = self._get_func()
1590         self.assertIsNone(fn(request))
1591
1592     def test_not_a_basic_auth_scheme(self):
1593         import base64
1594         request = testing.DummyRequest()
1595         request.headers['Authorization'] = 'OtherScheme %s' % base64.b64encode(
1596             bytes_('chrisr:password')).decode('ascii')
1597         fn = self._get_func()
1598         self.assertIsNone(fn(request))
1599
1600     def test_no_base64_encoding(self):
1601         request = testing.DummyRequest()
1602         request.headers['Authorization'] = 'Basic ...'
1603         fn = self._get_func()
1604         self.assertIsNone(fn(request))
1605
1606     def test_latin1_payload(self):
1607         import base64
1608         request = testing.DummyRequest()
1609         inputs = (b'm\xc3\xb6rk\xc3\xb6:'
1610                   b'm\xc3\xb6rk\xc3\xb6password').decode('utf-8')
1611         request.headers['Authorization'] = 'Basic %s' % (
1612             base64.b64encode(inputs.encode('latin-1')).decode('latin-1'))
1613         fn = self._get_func()
1614         self.assertEqual(fn(request), (
1615             b'm\xc3\xb6rk\xc3\xb6'.decode('utf-8'),
1616             b'm\xc3\xb6rk\xc3\xb6password'.decode('utf-8')
1617         ))
1618
1619     def test_utf8_payload(self):
1620         import base64
1621         request = testing.DummyRequest()
1622         inputs = (b'm\xc3\xb6rk\xc3\xb6:'
1623                   b'm\xc3\xb6rk\xc3\xb6password').decode('utf-8')
1624         request.headers['Authorization'] = 'Basic %s' % (
1625             base64.b64encode(inputs.encode('utf-8')).decode('latin-1'))
1626         fn = self._get_func()
1627         self.assertEqual(fn(request), (
1628             b'm\xc3\xb6rk\xc3\xb6'.decode('utf-8'),
1629             b'm\xc3\xb6rk\xc3\xb6password'.decode('utf-8')
1630         ))
1631
693cb0 1632     def test_namedtuple_return(self):
DG 1633         import base64
1634         request = testing.DummyRequest()
1635         request.headers['Authorization'] = 'Basic %s' % base64.b64encode(
1636             bytes_('chrisr:pass')).decode('ascii')
1637         fn = self._get_func()
1638         result = fn(request)
1639
1640         self.assertEqual(result.username, 'chrisr')
1641         self.assertEqual(result.password, 'pass')
767e44 1642         
a1a9fb 1643 class DummyContext:
CM 1644     pass
1645
bd0c7a 1646 class DummyCookies(object):
CM 1647     def __init__(self, cookie):
1648         self.cookie = cookie
1649
1650     def get(self, name):
1651         return self.cookie
1652
a1a9fb 1653 class DummyRequest:
767e44 1654     domain = 'localhost'
bd0c7a 1655     def __init__(self, environ=None, session=None, registry=None, cookie=None):
ef992f 1656         self.environ = environ or {}
MM 1657         self.session = session or {}
449287 1658         self.registry = registry
844e98 1659         self.callbacks = []
bd0c7a 1660         self.cookies = DummyCookies(cookie)
844e98 1661
CM 1662     def add_response_callback(self, callback):
1663         self.callbacks.append(callback)
a1a9fb 1664
fcc272 1665 class DummyWhoPlugin:
a1a9fb 1666     def remember(self, environ, identity):
CM 1667         return environ, identity
bf902d 1668
a1a9fb 1669     def forget(self, environ, identity):
CM 1670         return environ, identity
fcc272 1671
CM 1672 class DummyCookieHelper:
1673     def __init__(self, result):
1674         self.result = result
1675
1676     def identify(self, *arg, **kw):
1677         return self.result
1678
1679     def remember(self, *arg, **kw):
3bef31 1680         self.kw = kw
fcc272 1681         return []
CM 1682
1683     def forget(self, *arg):
1684         return []
1685
839ea0 1686 class DummyAuthTktModule(object):
CM 1687     def __init__(self, timestamp=0, userid='userid', tokens=(), user_data='',
801adf 1688                  parse_raise=False, hashalg="md5"):
839ea0 1689         self.timestamp = timestamp
CM 1690         self.userid = userid
1691         self.tokens = tokens
1692         self.user_data = user_data
1693         self.parse_raise = parse_raise
801adf 1694         self.hashalg = hashalg
DK 1695         def parse_ticket(secret, value, remote_addr, hashalg):
839ea0 1696             self.secret = secret
CM 1697             self.value = value
1698             self.remote_addr = remote_addr
1699             if self.parse_raise:
1700                 raise self.BadTicket()
1701             return self.timestamp, self.userid, self.tokens, self.user_data
1702         self.parse_ticket = parse_ticket
bf902d 1703
839ea0 1704         class AuthTicket(object):
CM 1705             def __init__(self, secret, userid, remote_addr, **kw):
1706                 self.secret = secret
1707                 self.userid = userid
1708                 self.remote_addr = remote_addr
1709                 self.kw = kw
1710
1711             def cookie_value(self):
767e44 1712                 result = {
CM 1713                     'secret':self.secret,
1714                     'userid':self.userid,
1715                     'remote_addr':self.remote_addr
1716                     }
839ea0 1717                 result.update(self.kw)
767e44 1718                 tokens = result.pop('tokens', None)
CM 1719                 if tokens is not None:
1720                     tokens = '|'.join(tokens)
1721                     result['tokens'] = tokens
1722                 items = sorted(result.items())
1723                 new_items = []
1724                 for k, v in items:
1725                     if isinstance(v, bytes):
1726                         v = text_(v)
1727                     new_items.append((k,v))
1728                 result = '/'.join(['%s=%s' % (k, v) for k,v in new_items ])
839ea0 1729                 return result
CM 1730         self.AuthTicket = AuthTicket
1731
1732     class BadTicket(Exception):
1733         pass
1734
844e98 1735 class DummyResponse:
CM 1736     def __init__(self):
a58c4a 1737         self.headerlist = []
bf902d 1738