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