Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1import base64 

2import binascii 

3import hashlib 

4import hmac 

5import os 

6import time 

7import warnings 

8 

9from zope.deprecation import deprecated 

10from zope.interface import implementer 

11 

12from webob.cookies import JSONSerializer, SignedSerializer 

13 

14from pyramid.compat import pickle, PY2, text_, bytes_, native_ 

15from pyramid.csrf import check_csrf_origin, check_csrf_token 

16 

17from pyramid.interfaces import ISession 

18from pyramid.util import strings_differ 

19 

20 

21def manage_accessed(wrapped): 

22 """ Decorator which causes a cookie to be renewed when an accessor 

23 method is called.""" 

24 

25 def accessed(session, *arg, **kw): 

26 session.accessed = now = int(time.time()) 

27 if session._reissue_time is not None: 

28 if now - session.renewed > session._reissue_time: 

29 session.changed() 

30 return wrapped(session, *arg, **kw) 

31 

32 accessed.__doc__ = wrapped.__doc__ 

33 return accessed 

34 

35 

36def manage_changed(wrapped): 

37 """ Decorator which causes a cookie to be set when a setter method 

38 is called.""" 

39 

40 def changed(session, *arg, **kw): 

41 session.accessed = int(time.time()) 

42 session.changed() 

43 return wrapped(session, *arg, **kw) 

44 

45 changed.__doc__ = wrapped.__doc__ 

46 return changed 

47 

48 

49def signed_serialize(data, secret): 

50 """ Serialize any pickleable structure (``data``) and sign it 

51 using the ``secret`` (must be a string). Return the 

52 serialization, which includes the signature as its first 40 bytes. 

53 The ``signed_deserialize`` method will deserialize such a value. 

54 

55 This function is useful for creating signed cookies. For example: 

56 

57 .. code-block:: python 

58 

59 cookieval = signed_serialize({'a':1}, 'secret') 

60 response.set_cookie('signed_cookie', cookieval) 

61 

62 .. deprecated:: 1.10 

63 

64 This function will be removed in :app:`Pyramid` 2.0. It is using 

65 pickle-based serialization, which is considered vulnerable to remote 

66 code execution attacks and will no longer be used by the default 

67 session factories at that time. 

68 

69 """ 

70 pickled = pickle.dumps(data, pickle.HIGHEST_PROTOCOL) 

71 try: 

72 # bw-compat with pyramid <= 1.5b1 where latin1 is the default 

73 secret = bytes_(secret) 

74 except UnicodeEncodeError: 

75 secret = bytes_(secret, 'utf-8') 

76 sig = hmac.new(secret, pickled, hashlib.sha1).hexdigest() 

77 return sig + native_(base64.b64encode(pickled)) 

78 

79 

80deprecated( 

81 'signed_serialize', 

82 'This function will be removed in Pyramid 2.0. It is using pickle-based ' 

83 'serialization, which is considered vulnerable to remote code execution ' 

84 'attacks.', 

85) 

86 

87 

88def signed_deserialize(serialized, secret, hmac=hmac): 

89 """ Deserialize the value returned from ``signed_serialize``. If 

90 the value cannot be deserialized for any reason, a 

91 :exc:`ValueError` exception will be raised. 

92 

93 This function is useful for deserializing a signed cookie value 

94 created by ``signed_serialize``. For example: 

95 

96 .. code-block:: python 

97 

98 cookieval = request.cookies['signed_cookie'] 

99 data = signed_deserialize(cookieval, 'secret') 

100 

101 .. deprecated:: 1.10 

102 

103 This function will be removed in :app:`Pyramid` 2.0. It is using 

104 pickle-based serialization, which is considered vulnerable to remote 

105 code execution attacks and will no longer be used by the default 

106 session factories at that time. 

107 """ 

108 # hmac parameterized only for unit tests 

109 try: 

110 input_sig, pickled = ( 

111 bytes_(serialized[:40]), 

112 base64.b64decode(bytes_(serialized[40:])), 

113 ) 

114 except (binascii.Error, TypeError) as e: 

115 # Badly formed data can make base64 die 

116 raise ValueError('Badly formed base64 data: %s' % e) 

117 

118 try: 

119 # bw-compat with pyramid <= 1.5b1 where latin1 is the default 

120 secret = bytes_(secret) 

121 except UnicodeEncodeError: 

122 secret = bytes_(secret, 'utf-8') 

123 sig = bytes_(hmac.new(secret, pickled, hashlib.sha1).hexdigest()) 

124 

125 # Avoid timing attacks (see 

126 # http://seb.dbzteam.org/crypto/python-oauth-timing-hmac.pdf) 

127 if strings_differ(sig, input_sig): 

128 raise ValueError('Invalid signature') 

129 

130 return pickle.loads(pickled) 

131 

132 

133deprecated( 

134 'signed_deserialize', 

135 'This function will be removed in Pyramid 2.0. It is using pickle-based ' 

136 'serialization, which is considered vulnerable to remote code execution ' 

137 'attacks.', 

138) 

139 

140 

141class PickleSerializer(object): 

142 """ A serializer that uses the pickle protocol to dump Python 

143 data to bytes. 

144 

145 This is the default serializer used by Pyramid. 

146 

147 ``protocol`` may be specified to control the version of pickle used. 

148 Defaults to :attr:`pickle.HIGHEST_PROTOCOL`. 

149 

150 """ 

151 

152 def __init__(self, protocol=pickle.HIGHEST_PROTOCOL): 

153 self.protocol = protocol 

154 

155 def loads(self, bstruct): 

156 """Accept bytes and return a Python object.""" 

157 try: 

158 return pickle.loads(bstruct) 

159 # at least ValueError, AttributeError, ImportError but more to be safe 

160 except Exception: 

161 raise ValueError 

162 

163 def dumps(self, appstruct): 

164 """Accept a Python object and return bytes.""" 

165 return pickle.dumps(appstruct, self.protocol) 

166 

167 

168JSONSerializer = JSONSerializer # api 

169 

170 

171def BaseCookieSessionFactory( 

172 serializer, 

173 cookie_name='session', 

174 max_age=None, 

175 path='/', 

176 domain=None, 

177 secure=False, 

178 httponly=False, 

179 samesite='Lax', 

180 timeout=1200, 

181 reissue_time=0, 

182 set_on_exception=True, 

183): 

184 """ 

185 Configure a :term:`session factory` which will provide cookie-based 

186 sessions. The return value of this function is a :term:`session factory`, 

187 which may be provided as the ``session_factory`` argument of a 

188 :class:`pyramid.config.Configurator` constructor, or used as the 

189 ``session_factory`` argument of the 

190 :meth:`pyramid.config.Configurator.set_session_factory` method. 

191 

192 The session factory returned by this function will create sessions 

193 which are limited to storing fewer than 4000 bytes of data (as the 

194 payload must fit into a single cookie). 

195 

196 .. warning: 

197 

198 This class provides no protection from tampering and is only intended 

199 to be used by framework authors to create their own cookie-based 

200 session factories. 

201 

202 Parameters: 

203 

204 ``serializer`` 

205 An object with two methods: ``loads`` and ``dumps``. The ``loads`` 

206 method should accept bytes and return a Python object. The ``dumps`` 

207 method should accept a Python object and return bytes. A ``ValueError`` 

208 should be raised for malformed inputs. 

209 

210 ``cookie_name`` 

211 The name of the cookie used for sessioning. Default: ``'session'``. 

212 

213 ``max_age`` 

214 The maximum age of the cookie used for sessioning (in seconds). 

215 Default: ``None`` (browser scope). 

216 

217 ``path`` 

218 The path used for the session cookie. Default: ``'/'``. 

219 

220 ``domain`` 

221 The domain used for the session cookie. Default: ``None`` (no domain). 

222 

223 ``secure`` 

224 The 'secure' flag of the session cookie. Default: ``False``. 

225 

226 ``httponly`` 

227 Hide the cookie from Javascript by setting the 'HttpOnly' flag of the 

228 session cookie. Default: ``False``. 

229 

230 ``samesite`` 

231 The 'samesite' option of the session cookie. Set the value to ``None`` 

232 to turn off the samesite option. Default: ``'Lax'``. 

233 

234 ``timeout`` 

235 A number of seconds of inactivity before a session times out. If 

236 ``None`` then the cookie never expires. This lifetime only applies 

237 to the *value* within the cookie. Meaning that if the cookie expires 

238 due to a lower ``max_age``, then this setting has no effect. 

239 Default: ``1200``. 

240 

241 ``reissue_time`` 

242 The number of seconds that must pass before the cookie is automatically 

243 reissued as the result of a request which accesses the session. The 

244 duration is measured as the number of seconds since the last session 

245 cookie was issued and 'now'. If this value is ``0``, a new cookie 

246 will be reissued on every request accessing the session. If ``None`` 

247 then the cookie's lifetime will never be extended. 

248 

249 A good rule of thumb: if you want auto-expired cookies based on 

250 inactivity: set the ``timeout`` value to 1200 (20 mins) and set the 

251 ``reissue_time`` value to perhaps a tenth of the ``timeout`` value 

252 (120 or 2 mins). It's nonsensical to set the ``timeout`` value lower 

253 than the ``reissue_time`` value, as the ticket will never be reissued. 

254 However, such a configuration is not explicitly prevented. 

255 

256 Default: ``0``. 

257 

258 ``set_on_exception`` 

259 If ``True``, set a session cookie even if an exception occurs 

260 while rendering a view. Default: ``True``. 

261 

262 .. versionadded: 1.5a3 

263 

264 .. versionchanged: 1.10 

265 

266 Added the ``samesite`` option and made the default ``'Lax'``. 

267 """ 

268 

269 @implementer(ISession) 

270 class CookieSession(dict): 

271 """ Dictionary-like session object """ 

272 

273 # configuration parameters 

274 _cookie_name = cookie_name 

275 _cookie_max_age = max_age if max_age is None else int(max_age) 

276 _cookie_path = path 

277 _cookie_domain = domain 

278 _cookie_secure = secure 

279 _cookie_httponly = httponly 

280 _cookie_samesite = samesite 

281 _cookie_on_exception = set_on_exception 

282 _timeout = timeout if timeout is None else int(timeout) 

283 _reissue_time = ( 

284 reissue_time if reissue_time is None else int(reissue_time) 

285 ) 

286 

287 # dirty flag 

288 _dirty = False 

289 

290 def __init__(self, request): 

291 self.request = request 

292 now = time.time() 

293 created = renewed = now 

294 new = True 

295 value = None 

296 state = {} 

297 cookieval = request.cookies.get(self._cookie_name) 

298 if cookieval is not None: 

299 try: 

300 value = serializer.loads(bytes_(cookieval)) 

301 except ValueError: 

302 # the cookie failed to deserialize, dropped 

303 value = None 

304 

305 if value is not None: 

306 try: 

307 # since the value is not necessarily signed, we have 

308 # to unpack it a little carefully 

309 rval, cval, sval = value 

310 renewed = float(rval) 

311 created = float(cval) 

312 state = sval 

313 new = False 

314 except (TypeError, ValueError): 

315 # value failed to unpack properly or renewed was not 

316 # a numeric type so we'll fail deserialization here 

317 state = {} 

318 

319 if self._timeout is not None: 

320 if now - renewed > self._timeout: 

321 # expire the session because it was not renewed 

322 # before the timeout threshold 

323 state = {} 

324 

325 self.created = created 

326 self.accessed = renewed 

327 self.renewed = renewed 

328 self.new = new 

329 dict.__init__(self, state) 

330 

331 # ISession methods 

332 def changed(self): 

333 if not self._dirty: 

334 self._dirty = True 

335 

336 def set_cookie_callback(request, response): 

337 self._set_cookie(response) 

338 self.request = None # explicitly break cycle for gc 

339 

340 self.request.add_response_callback(set_cookie_callback) 

341 

342 def invalidate(self): 

343 self.clear() # XXX probably needs to unset cookie 

344 

345 # non-modifying dictionary methods 

346 get = manage_accessed(dict.get) 

347 __getitem__ = manage_accessed(dict.__getitem__) 

348 items = manage_accessed(dict.items) 

349 values = manage_accessed(dict.values) 

350 keys = manage_accessed(dict.keys) 

351 __contains__ = manage_accessed(dict.__contains__) 

352 __len__ = manage_accessed(dict.__len__) 

353 __iter__ = manage_accessed(dict.__iter__) 

354 

355 if PY2: 

356 iteritems = manage_accessed(dict.iteritems) 

357 itervalues = manage_accessed(dict.itervalues) 

358 iterkeys = manage_accessed(dict.iterkeys) 

359 has_key = manage_accessed(dict.has_key) 

360 

361 # modifying dictionary methods 

362 clear = manage_changed(dict.clear) 

363 update = manage_changed(dict.update) 

364 setdefault = manage_changed(dict.setdefault) 

365 pop = manage_changed(dict.pop) 

366 popitem = manage_changed(dict.popitem) 

367 __setitem__ = manage_changed(dict.__setitem__) 

368 __delitem__ = manage_changed(dict.__delitem__) 

369 

370 # flash API methods 

371 @manage_changed 

372 def flash(self, msg, queue='', allow_duplicate=True): 

373 storage = self.setdefault('_f_' + queue, []) 

374 if allow_duplicate or (msg not in storage): 

375 storage.append(msg) 

376 

377 @manage_changed 

378 def pop_flash(self, queue=''): 

379 storage = self.pop('_f_' + queue, []) 

380 return storage 

381 

382 @manage_accessed 

383 def peek_flash(self, queue=''): 

384 storage = self.get('_f_' + queue, []) 

385 return storage 

386 

387 # CSRF API methods 

388 @manage_changed 

389 def new_csrf_token(self): 

390 token = text_(binascii.hexlify(os.urandom(20))) 

391 self['_csrft_'] = token 

392 return token 

393 

394 @manage_accessed 

395 def get_csrf_token(self): 

396 token = self.get('_csrft_', None) 

397 if token is None: 

398 token = self.new_csrf_token() 

399 return token 

400 

401 # non-API methods 

402 def _set_cookie(self, response): 

403 if not self._cookie_on_exception: 

404 exception = getattr(self.request, 'exception', None) 

405 if ( 

406 exception is not None 

407 ): # dont set a cookie during exceptions 

408 return False 

409 cookieval = native_( 

410 serializer.dumps((self.accessed, self.created, dict(self))) 

411 ) 

412 if len(cookieval) > 4064: 

413 raise ValueError( 

414 'Cookie value is too long to store (%s bytes)' 

415 % len(cookieval) 

416 ) 

417 response.set_cookie( 

418 self._cookie_name, 

419 value=cookieval, 

420 max_age=self._cookie_max_age, 

421 path=self._cookie_path, 

422 domain=self._cookie_domain, 

423 secure=self._cookie_secure, 

424 httponly=self._cookie_httponly, 

425 samesite=self._cookie_samesite, 

426 ) 

427 return True 

428 

429 return CookieSession 

430 

431 

432def UnencryptedCookieSessionFactoryConfig( 

433 secret, 

434 timeout=1200, 

435 cookie_name='session', 

436 cookie_max_age=None, 

437 cookie_path='/', 

438 cookie_domain=None, 

439 cookie_secure=False, 

440 cookie_httponly=False, 

441 cookie_samesite='Lax', 

442 cookie_on_exception=True, 

443 signed_serialize=signed_serialize, 

444 signed_deserialize=signed_deserialize, 

445): 

446 """ 

447 .. deprecated:: 1.5 

448 Use :func:`pyramid.session.SignedCookieSessionFactory` instead. 

449 Caveat: Cookies generated using ``SignedCookieSessionFactory`` are not 

450 compatible with cookies generated using 

451 ``UnencryptedCookieSessionFactory``, so existing user session data 

452 will be destroyed if you switch to it. 

453 

454 Configure a :term:`session factory` which will provide unencrypted 

455 (but signed) cookie-based sessions. The return value of this 

456 function is a :term:`session factory`, which may be provided as 

457 the ``session_factory`` argument of a 

458 :class:`pyramid.config.Configurator` constructor, or used 

459 as the ``session_factory`` argument of the 

460 :meth:`pyramid.config.Configurator.set_session_factory` 

461 method. 

462 

463 The session factory returned by this function will create sessions 

464 which are limited to storing fewer than 4000 bytes of data (as the 

465 payload must fit into a single cookie). 

466 

467 Parameters: 

468 

469 ``secret`` 

470 A string which is used to sign the cookie. 

471 

472 ``timeout`` 

473 A number of seconds of inactivity before a session times out. 

474 

475 ``cookie_name`` 

476 The name of the cookie used for sessioning. 

477 

478 ``cookie_max_age`` 

479 The maximum age of the cookie used for sessioning (in seconds). 

480 Default: ``None`` (browser scope). 

481 

482 ``cookie_path`` 

483 The path used for the session cookie. 

484 

485 ``cookie_domain`` 

486 The domain used for the session cookie. Default: ``None`` (no domain). 

487 

488 ``cookie_secure`` 

489 The 'secure' flag of the session cookie. 

490 

491 ``cookie_httponly`` 

492 The 'httpOnly' flag of the session cookie. 

493 

494 ``cookie_samesite`` 

495 The 'samesite' option of the session cookie. Set the value to ``None`` 

496 to turn off the samesite option. Default: ``'Lax'``. 

497 

498 ``cookie_on_exception`` 

499 If ``True``, set a session cookie even if an exception occurs 

500 while rendering a view. 

501 

502 ``signed_serialize`` 

503 A callable which takes more or less arbitrary Python data structure and 

504 a secret and returns a signed serialization in bytes. 

505 Default: ``signed_serialize`` (using pickle). 

506 

507 ``signed_deserialize`` 

508 A callable which takes a signed and serialized data structure in bytes 

509 and a secret and returns the original data structure if the signature 

510 is valid. Default: ``signed_deserialize`` (using pickle). 

511 

512 .. versionchanged: 1.10 

513 

514 Added the ``samesite`` option and made the default ``'Lax'``. 

515 """ 

516 

517 class SerializerWrapper(object): 

518 def __init__(self, secret): 

519 self.secret = secret 

520 

521 def loads(self, bstruct): 

522 return signed_deserialize(bstruct, secret) 

523 

524 def dumps(self, appstruct): 

525 return signed_serialize(appstruct, secret) 

526 

527 serializer = SerializerWrapper(secret) 

528 

529 return BaseCookieSessionFactory( 

530 serializer, 

531 cookie_name=cookie_name, 

532 max_age=cookie_max_age, 

533 path=cookie_path, 

534 domain=cookie_domain, 

535 secure=cookie_secure, 

536 httponly=cookie_httponly, 

537 samesite=cookie_samesite, 

538 timeout=timeout, 

539 reissue_time=0, # to keep session.accessed == session.renewed 

540 set_on_exception=cookie_on_exception, 

541 ) 

542 

543 

544deprecated( 

545 'UnencryptedCookieSessionFactoryConfig', 

546 'The UnencryptedCookieSessionFactoryConfig callable is deprecated as of ' 

547 'Pyramid 1.5. Use ``pyramid.session.SignedCookieSessionFactory`` instead.' 

548 ' Caveat: Cookies generated using SignedCookieSessionFactory are not ' 

549 'compatible with cookies generated using UnencryptedCookieSessionFactory, ' 

550 'so existing user session data will be destroyed if you switch to it.', 

551) 

552 

553 

554def SignedCookieSessionFactory( 

555 secret, 

556 cookie_name='session', 

557 max_age=None, 

558 path='/', 

559 domain=None, 

560 secure=False, 

561 httponly=False, 

562 samesite='Lax', 

563 set_on_exception=True, 

564 timeout=1200, 

565 reissue_time=0, 

566 hashalg='sha512', 

567 salt='pyramid.session.', 

568 serializer=None, 

569): 

570 """ 

571 .. versionadded:: 1.5 

572 

573 Configure a :term:`session factory` which will provide signed 

574 cookie-based sessions. The return value of this 

575 function is a :term:`session factory`, which may be provided as 

576 the ``session_factory`` argument of a 

577 :class:`pyramid.config.Configurator` constructor, or used 

578 as the ``session_factory`` argument of the 

579 :meth:`pyramid.config.Configurator.set_session_factory` 

580 method. 

581 

582 The session factory returned by this function will create sessions 

583 which are limited to storing fewer than 4000 bytes of data (as the 

584 payload must fit into a single cookie). 

585 

586 Parameters: 

587 

588 ``secret`` 

589 A string which is used to sign the cookie. The secret should be at 

590 least as long as the block size of the selected hash algorithm. For 

591 ``sha512`` this would mean a 512 bit (64 character) secret. It should 

592 be unique within the set of secret values provided to Pyramid for 

593 its various subsystems (see :ref:`admonishment_against_secret_sharing`). 

594 

595 ``hashalg`` 

596 The HMAC digest algorithm to use for signing. The algorithm must be 

597 supported by the :mod:`hashlib` library. Default: ``'sha512'``. 

598 

599 ``salt`` 

600 A namespace to avoid collisions between different uses of a shared 

601 secret. Reusing a secret for different parts of an application is 

602 strongly discouraged (see :ref:`admonishment_against_secret_sharing`). 

603 Default: ``'pyramid.session.'``. 

604 

605 ``cookie_name`` 

606 The name of the cookie used for sessioning. Default: ``'session'``. 

607 

608 ``max_age`` 

609 The maximum age of the cookie used for sessioning (in seconds). 

610 Default: ``None`` (browser scope). 

611 

612 ``path`` 

613 The path used for the session cookie. Default: ``'/'``. 

614 

615 ``domain`` 

616 The domain used for the session cookie. Default: ``None`` (no domain). 

617 

618 ``secure`` 

619 The 'secure' flag of the session cookie. Default: ``False``. 

620 

621 ``httponly`` 

622 Hide the cookie from Javascript by setting the 'HttpOnly' flag of the 

623 session cookie. Default: ``False``. 

624 

625 ``samesite`` 

626 The 'samesite' option of the session cookie. Set the value to ``None`` 

627 to turn off the samesite option. Default: ``'Lax'``. 

628 

629 ``timeout`` 

630 A number of seconds of inactivity before a session times out. If 

631 ``None`` then the cookie never expires. This lifetime only applies 

632 to the *value* within the cookie. Meaning that if the cookie expires 

633 due to a lower ``max_age``, then this setting has no effect. 

634 Default: ``1200``. 

635 

636 ``reissue_time`` 

637 The number of seconds that must pass before the cookie is automatically 

638 reissued as the result of accessing the session. The 

639 duration is measured as the number of seconds since the last session 

640 cookie was issued and 'now'. If this value is ``0``, a new cookie 

641 will be reissued on every request accessing the session. If ``None`` 

642 then the cookie's lifetime will never be extended. 

643 

644 A good rule of thumb: if you want auto-expired cookies based on 

645 inactivity: set the ``timeout`` value to 1200 (20 mins) and set the 

646 ``reissue_time`` value to perhaps a tenth of the ``timeout`` value 

647 (120 or 2 mins). It's nonsensical to set the ``timeout`` value lower 

648 than the ``reissue_time`` value, as the ticket will never be reissued. 

649 However, such a configuration is not explicitly prevented. 

650 

651 Default: ``0``. 

652 

653 ``set_on_exception`` 

654 If ``True``, set a session cookie even if an exception occurs 

655 while rendering a view. Default: ``True``. 

656 

657 ``serializer`` 

658 An object with two methods: ``loads`` and ``dumps``. The ``loads`` 

659 method should accept bytes and return a Python object. The ``dumps`` 

660 method should accept a Python object and return bytes. A ``ValueError`` 

661 should be raised for malformed inputs. If a serializer is not passed, 

662 the :class:`pyramid.session.PickleSerializer` serializer will be used. 

663 

664 .. warning:: 

665 

666 In :app:`Pyramid` 2.0 the default ``serializer`` option will change to 

667 use :class:`pyramid.session.JSONSerializer`. See 

668 :ref:`pickle_session_deprecation` for more information about why this 

669 change is being made. 

670 

671 .. versionadded: 1.5a3 

672 

673 .. versionchanged: 1.10 

674 

675 Added the ``samesite`` option and made the default ``Lax``. 

676 

677 """ 

678 if serializer is None: 

679 serializer = PickleSerializer() 

680 warnings.warn( 

681 'The default pickle serializer is deprecated as of Pyramid 1.9 ' 

682 'and it will be changed to use pyramid.session.JSONSerializer in ' 

683 'version 2.0. Explicitly set the serializer to avoid future ' 

684 'incompatibilities. See "Upcoming Changes to ISession in ' 

685 'Pyramid 2.0" for more information about this change.', 

686 DeprecationWarning, 

687 stacklevel=1, 

688 ) 

689 

690 signed_serializer = SignedSerializer( 

691 secret, salt, hashalg, serializer=serializer 

692 ) 

693 

694 return BaseCookieSessionFactory( 

695 signed_serializer, 

696 cookie_name=cookie_name, 

697 max_age=max_age, 

698 path=path, 

699 domain=domain, 

700 secure=secure, 

701 httponly=httponly, 

702 samesite=samesite, 

703 timeout=timeout, 

704 reissue_time=reissue_time, 

705 set_on_exception=set_on_exception, 

706 ) 

707 

708 

709check_csrf_origin = check_csrf_origin # api 

710deprecated( 

711 'check_csrf_origin', 

712 'pyramid.session.check_csrf_origin is deprecated as of Pyramid ' 

713 '1.9. Use pyramid.csrf.check_csrf_origin instead.', 

714) 

715 

716check_csrf_token = check_csrf_token # api 

717deprecated( 

718 'check_csrf_token', 

719 'pyramid.session.check_csrf_token is deprecated as of Pyramid ' 

720 '1.9. Use pyramid.csrf.check_csrf_token instead.', 

721)