From 35259d7b1f029391a839c96f7750d6b3433ad2c9 Mon Sep 17 00:00:00 2001 From: ejo Date: Sat, 9 Jul 2011 13:29:38 -0700 Subject: Old sentence was grammatically incorrect, literally meant that the URL or button in question did not know it was redirecting the user. It is the user who does not know, so "unwittingly" is replaced with "secretly"; "surreptitiously" would be another accurate alternative. An alternative sentence construction that maintains the word "unwittingly" would be, e.g., "...might click on a URL or button on another website and be unwittingly redirected to your application to perform some command that requires elevated privileges." --- docs/narr/sessions.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs/narr/sessions.rst') diff --git a/docs/narr/sessions.rst b/docs/narr/sessions.rst index 97e3ebc55..365ee395b 100644 --- a/docs/narr/sessions.rst +++ b/docs/narr/sessions.rst @@ -288,7 +288,7 @@ Preventing Cross-Site Request Forgery Attacks `Cross-site request forgery `_ attacks are a phenomenon whereby a user with an identity on your website might click on a -URL or button on another website which unwittingly redirects the user to your +URL or button on another website which secretly redirects the user to your application to perform some command that requires elevated privileges. You can avoid most of these attacks by making sure that the correct *CSRF -- cgit v1.2.3 From 6ce1e0cf1a141767ee0aca70786c15dd993347c5 Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Wed, 20 Jul 2011 06:10:38 -0400 Subject: add more index markers --- docs/narr/sessions.rst | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) (limited to 'docs/narr/sessions.rst') diff --git a/docs/narr/sessions.rst b/docs/narr/sessions.rst index 365ee395b..6ff9e3dea 100644 --- a/docs/narr/sessions.rst +++ b/docs/narr/sessions.rst @@ -15,6 +15,9 @@ implementations :app:`Pyramid` provides out of the box, how to store and retrieve data from sessions, and two session-specific features: flash messages, and cross-site request forgery attack prevention. +.. index:: + single: session factory (default) + .. _using_the_default_session_factory: Using The Default Session Factory @@ -65,6 +68,9 @@ application by using the ``session_factory`` argument to the the server) for anything but the most basic of applications where "session security doesn't matter". +.. index:: + single: session object + Using a Session Object ---------------------- @@ -137,6 +143,7 @@ Some gotchas: .. index:: single: pyramid_beaker single: Beaker + single: session factory (alternates) .. _using_alternate_session_factories: @@ -153,7 +160,7 @@ based sessions, and encrypted cookie-based sessions. See ``pyramid_beaker``. .. index:: - single: session factory + single: session factory (custom) Creating Your Own Session Factory --------------------------------- @@ -184,6 +191,9 @@ log messages for single-time display without having direct access to an HTML template. The user interface consists of a number of methods of the :term:`session` object. +.. index:: + single: session.flash + Using the ``session.flash`` Method ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -222,6 +232,9 @@ The ``allow_duplicate`` argument defaults to ``True``. If this is ``False``, and you attempt to add a message value which is already present in the queue, it will not be added. +.. index:: + single: session.pop_flash + Using the ``session.pop_flash`` Method ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -255,6 +268,9 @@ been popped. >>> request.session.pop_flash() [] +.. index:: + single: session.peek_flash + Using the ``session.peek_flash`` Method ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -298,6 +314,9 @@ post. To use CSRF token support, you must enable a :term:`session factory` as described in :ref:`using_the_default_session_factory` or :ref:`using_alternate_session_factories`. +.. index:: + single: session.get_csrf_token + Using the ``session.get_csrf_token`` Method ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -330,6 +349,9 @@ input field named ``csrf_token``: if token != request.POST['csrf_token']: raise ValueError('CSRF token did not match') +.. index:: + single: session.new_csrf_token + Using the ``session.new_csrf_token`` Method ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -- cgit v1.2.3 From fe9316332511de945924effd8a049db79f34e761 Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Tue, 19 Jun 2012 21:42:44 -0400 Subject: point at pyramid_beaker docs rather than its github page --- docs/narr/sessions.rst | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) (limited to 'docs/narr/sessions.rst') diff --git a/docs/narr/sessions.rst b/docs/narr/sessions.rst index 6ff9e3dea..1aa1b6341 100644 --- a/docs/narr/sessions.rst +++ b/docs/narr/sessions.rst @@ -151,13 +151,12 @@ Using Alternate Session Factories --------------------------------- At the time of this writing, exactly one alternate session factory -implementation exists, named ``pyramid_beaker``. This is a session -factory that uses the `Beaker `_ library -as a backend. Beaker has support for file-based sessions, database -based sessions, and encrypted cookie-based sessions. See -`http://github.com/Pylons/pyramid_beaker -`_ for more information about -``pyramid_beaker``. +implementation exists, named ``pyramid_beaker``. This is a session factory +that uses the `Beaker `_ library as a backend. +Beaker has support for file-based sessions, database based sessions, and +encrypted cookie-based sessions. See `the pyramid_beaker documentation +`_ for more +information about ``pyramid_beaker``. .. index:: single: session factory (custom) -- cgit v1.2.3 From 76430b07f199cdbdbd19f463367c72eda1b537c3 Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Fri, 2 Nov 2012 13:13:26 -0400 Subject: explain csrf token stealing potentiality --- docs/narr/sessions.rst | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'docs/narr/sessions.rst') diff --git a/docs/narr/sessions.rst b/docs/narr/sessions.rst index 1aa1b6341..f7da7838e 100644 --- a/docs/narr/sessions.rst +++ b/docs/narr/sessions.rst @@ -63,10 +63,15 @@ application by using the ``session_factory`` argument to the this implementation is, by default, *unencrypted*. You should not use it when you keep sensitive information in the session object, as the information can be easily read by both users of your application and third - parties who have access to your users' network traffic. Use a different - session factory implementation (preferably one which keeps session data on - the server) for anything but the most basic of applications where "session - security doesn't matter". + parties who have access to your users' network traffic. And if you use this + sessioning implementation, and you inadvertently create a cross-site + scripting vulnerability in your application, because the session data is + stored unencrypted in a cookie, it will also be easier for evildoers to + obtain the current user's cross-site scripting token. In short, use a + different session factory implementation (preferably one which keeps session + data on the server) for anything but the most basic of applications where + "session security doesn't matter", and you are sure your application has no + cross-site scripting vulnerabilities. .. index:: single: session object -- cgit v1.2.3 From 0a9a29e9391e9b8639de61473bbe4865a6b0551e Mon Sep 17 00:00:00 2001 From: Tshepang Lekhonkhobe Date: Tue, 29 Jan 2013 00:16:29 +0200 Subject: pluralize --- docs/narr/sessions.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs/narr/sessions.rst') diff --git a/docs/narr/sessions.rst b/docs/narr/sessions.rst index f7da7838e..fa4affd8a 100644 --- a/docs/narr/sessions.rst +++ b/docs/narr/sessions.rst @@ -29,7 +29,7 @@ during your :app:`Pyramid` configuration. A very basic, insecure sample session factory implementation is provided in the :app:`Pyramid` core. It uses a cookie to store session information. This implementation has the following -limitation: +limitations: - The session information in the cookies used by this implementation is *not* encrypted, so it can be viewed by anyone with access to the -- cgit v1.2.3 From 88cafdd3cf621d0a117f0e2e8c924c07dfbf5ef1 Mon Sep 17 00:00:00 2001 From: Tshepang Lekhonkhobe Date: Sat, 23 Mar 2013 12:03:45 +0200 Subject: no need to qualify Python interactive sessions Sphinx automatically notices them as Python snippets and gives them syntax highlighting. These snippets are also too short to deserve linenos. --- docs/narr/sessions.rst | 43 +++++++++++++++++-------------------------- 1 file changed, 17 insertions(+), 26 deletions(-) (limited to 'docs/narr/sessions.rst') diff --git a/docs/narr/sessions.rst b/docs/narr/sessions.rst index fa4affd8a..c4f4b5f07 100644 --- a/docs/narr/sessions.rst +++ b/docs/narr/sessions.rst @@ -252,25 +252,19 @@ that were added to the flash queue, and empties the queue. .. method:: pop_flash(queue='') -.. code-block:: python - :linenos: - - >>> request.session.flash('info message') - >>> request.session.pop_flash() - ['info message'] +>>> request.session.flash('info message') +>>> request.session.pop_flash() +['info message'] Calling ``session.pop_flash()`` again like above without a corresponding call to ``session.flash()`` will return an empty list, because the queue has already been popped. -.. code-block:: python - :linenos: - - >>> request.session.flash('info message') - >>> request.session.pop_flash() - ['info message'] - >>> request.session.pop_flash() - [] +>>> request.session.flash('info message') +>>> request.session.pop_flash() +['info message'] +>>> request.session.pop_flash() +[] .. index:: single: session.peek_flash @@ -285,18 +279,15 @@ popped from flash storage. .. method:: peek_flash(queue='') -.. code-block:: python - :linenos: - - >>> request.session.flash('info message') - >>> request.session.peek_flash() - ['info message'] - >>> request.session.peek_flash() - ['info message'] - >>> request.session.pop_flash() - ['info message'] - >>> request.session.peek_flash() - [] +>>> request.session.flash('info message') +>>> request.session.peek_flash() +['info message'] +>>> request.session.peek_flash() +['info message'] +>>> request.session.pop_flash() +['info message'] +>>> request.session.peek_flash() +[] .. index:: single: preventing cross-site request forgery attacks -- cgit v1.2.3 From d95a2732eb2f972df9fb2f954ae374b8acd06727 Mon Sep 17 00:00:00 2001 From: Luke Cyca Date: Sun, 2 Jun 2013 19:08:44 -0700 Subject: Edited narrative docs about CSRF --- docs/narr/sessions.rst | 53 +++++++++++++++++++++++++++++--------------------- 1 file changed, 31 insertions(+), 22 deletions(-) (limited to 'docs/narr/sessions.rst') diff --git a/docs/narr/sessions.rst b/docs/narr/sessions.rst index c4f4b5f07..52b4860b3 100644 --- a/docs/narr/sessions.rst +++ b/docs/narr/sessions.rst @@ -298,14 +298,15 @@ Preventing Cross-Site Request Forgery Attacks `Cross-site request forgery `_ attacks are a -phenomenon whereby a user with an identity on your website might click on a -URL or button on another website which secretly redirects the user to your -application to perform some command that requires elevated privileges. - -You can avoid most of these attacks by making sure that the correct *CSRF -token* has been set in an :app:`Pyramid` session object before performing any -actions in code which requires elevated privileges that is invoked via a form -post. To use CSRF token support, you must enable a :term:`session factory` +phenomenon whereby a user who is logged in to your website might inadvertantly +load a URL because it is linked from, or embedded in, an attacker's website. +If the URL is one that may modify or delete data, the consequences can be dire. + +You can avoid most of these attacks by issuing a unique token to the browser +and then requiring that it be present in all potentially unsafe requests. +:app:`Pyramid` sessions provide facilities to create and check CSRF tokens. + +To use CSRF tokens, you must first enable a :term:`session factory` as described in :ref:`using_the_default_session_factory` or :ref:`using_alternate_session_factories`. @@ -324,33 +325,41 @@ To get the current CSRF token from the session, use the The ``session.get_csrf_token()`` method accepts no arguments. It returns a CSRF *token* string. If ``session.get_csrf_token()`` or -``session.new_csrf_token()`` was invoked previously for this session, the +``session.new_csrf_token()`` was invoked previously for this session, then the existing token will be returned. If no CSRF token previously existed for -this session, a new token will be will be set into the session and returned. +this session, then a new token will be will be set into the session and returned. The newly created token will be opaque and randomized. You can use the returned token as the value of a hidden field in a form that -posts to a method that requires elevated privileges. The handler for the -form post should use ``session.get_csrf_token()`` *again* to obtain the -current CSRF token related to the user from the session, and compare it to -the value of the hidden form field. For example, if your form rendering -included the CSRF token obtained via ``session.get_csrf_token()`` as a hidden -input field named ``csrf_token``: +posts to a method that requires elevated privileges, or supply it as a request +header in AJAX requests. The handler for the URL that receives the request +should then require that the correct CSRF token is supplied. -.. code-block:: python - :linenos: +Using the ``session.check_csrf_token`` Method +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - token = request.session.get_csrf_token() - if token != request.POST['csrf_token']: - raise ValueError('CSRF token did not match') +In request handling code, you can check the presence and validity of a CSRF +token with ``session.check_csrf_token(request)``. If the token is valid, +it will return True, otherwise it will raise ``HTTPBadRequest``. + +By default, it checks for a GET or POST parameter named ``csrf_token`` or a +header named ``X-CSRF-Token``. .. index:: single: session.new_csrf_token +Checking CSRF Tokens With A View Predicate +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +A convenient way to require a valid CSRF Token for a particular view is to +include ``check_csrf=True`` as a view predicate. +See :meth:`pyramid.config.Configurator.add_route`. + + Using the ``session.new_csrf_token`` Method ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -To explicitly add a new CSRF token to the session, use the +To explicitly create a new CSRF token, use the ``session.new_csrf_token()`` method. This differs only from ``session.get_csrf_token()`` inasmuch as it clears any existing CSRF token, creates a new CSRF token, sets the token into the session, and returns the -- cgit v1.2.3 From 009f843d7d72d3a9d8cc35c08db9b77e247111f5 Mon Sep 17 00:00:00 2001 From: Luke Cyca Date: Tue, 4 Jun 2013 22:25:37 -0700 Subject: Add examples to narrative CSRF docs --- docs/narr/sessions.rst | 43 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) (limited to 'docs/narr/sessions.rst') diff --git a/docs/narr/sessions.rst b/docs/narr/sessions.rst index 52b4860b3..7ec280c8a 100644 --- a/docs/narr/sessions.rst +++ b/docs/narr/sessions.rst @@ -332,7 +332,32 @@ The newly created token will be opaque and randomized. You can use the returned token as the value of a hidden field in a form that posts to a method that requires elevated privileges, or supply it as a request -header in AJAX requests. The handler for the URL that receives the request +header in AJAX requests. + +For example, include the CSRF token as a hidden field: + +.. code-block:: html + +
+ + +
+ +Or, include it as a header in a jQuery AJAX request: + +.. code-block:: javascript + + var csrfToken = ${request.session.get_csrf_token()}; + $.ajax({ + type: "POST", + url: "/myview", + headers: { 'X-CSRF-Token': csrfToken } + }).done(function() { + alert("Deleted"); + }); + + +The handler for the URL that receives the request should then require that the correct CSRF token is supplied. Using the ``session.check_csrf_token`` Method @@ -345,6 +370,16 @@ it will return True, otherwise it will raise ``HTTPBadRequest``. By default, it checks for a GET or POST parameter named ``csrf_token`` or a header named ``X-CSRF-Token``. +.. code-block:: python + + def myview(request): + session = request.session + + # Require CSRF Token + session.check_csrf_token(request): + + ... + .. index:: single: session.new_csrf_token @@ -355,6 +390,12 @@ A convenient way to require a valid CSRF Token for a particular view is to include ``check_csrf=True`` as a view predicate. See :meth:`pyramid.config.Configurator.add_route`. +.. code-block:: python + + @view_config(request_method='POST', check_csrf=True, ...) + def myview(request): + ... + Using the ``session.new_csrf_token`` Method ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -- cgit v1.2.3 From a5da4dbbb2f5876740004c5fc9ffb15ae600d35e Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Tue, 6 Aug 2013 03:34:52 -0400 Subject: add redis session mention --- docs/narr/sessions.rst | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) (limited to 'docs/narr/sessions.rst') diff --git a/docs/narr/sessions.rst b/docs/narr/sessions.rst index 7ec280c8a..82440060c 100644 --- a/docs/narr/sessions.rst +++ b/docs/narr/sessions.rst @@ -148,6 +148,7 @@ Some gotchas: .. index:: single: pyramid_beaker single: Beaker + single: pyramid_redis_sessions single: session factory (alternates) .. _using_alternate_session_factories: @@ -155,11 +156,17 @@ Some gotchas: Using Alternate Session Factories --------------------------------- -At the time of this writing, exactly one alternate session factory -implementation exists, named ``pyramid_beaker``. This is a session factory -that uses the `Beaker `_ library as a backend. -Beaker has support for file-based sessions, database based sessions, and -encrypted cookie-based sessions. See `the pyramid_beaker documentation +At the time of this writing, exactly two alternate session factories +exist. + +The first is named ``pyramid_redis_sessions``. It can be downloaded from PyPI. +It uses Redis as a backend. It is the recommended persistent session solution +at the time of this writing. + +The second is named ``pyramid_beaker``. This is a session factory that uses the +`Beaker `_ library as a backend. Beaker has +support for file-based sessions, database based sessions, and encrypted +cookie-based sessions. See `the pyramid_beaker documentation `_ for more information about ``pyramid_beaker``. -- cgit v1.2.3 From 49d634bd813e63c3db5e56d29376126c2646182a Mon Sep 17 00:00:00 2001 From: Paul Everitt Date: Mon, 12 Aug 2013 19:29:23 -0400 Subject: All wrapped up, pre-merge. --- docs/narr/sessions.rst | 2 ++ 1 file changed, 2 insertions(+) (limited to 'docs/narr/sessions.rst') diff --git a/docs/narr/sessions.rst b/docs/narr/sessions.rst index 7ec280c8a..7ba46c92c 100644 --- a/docs/narr/sessions.rst +++ b/docs/narr/sessions.rst @@ -181,6 +181,8 @@ implementation in the :mod:`pyramid.session` module as inspiration. .. index:: single: flash messages +.. _flash_messages: + Flash Messages -------------- -- cgit v1.2.3 From 190b5644c473286f8066c9eb430c567dfdeb4913 Mon Sep 17 00:00:00 2001 From: "Karl O. Pinc" Date: Wed, 2 Oct 2013 13:36:05 -0500 Subject: Docs: sessions.rst: Explain example. --- docs/narr/sessions.rst | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'docs/narr/sessions.rst') diff --git a/docs/narr/sessions.rst b/docs/narr/sessions.rst index 358977089..eafa9dbf9 100644 --- a/docs/narr/sessions.rst +++ b/docs/narr/sessions.rst @@ -99,6 +99,10 @@ example: else: return Response('Fred was not in the session') +The first time this view is invoked produces ``Fred was not in the +session``. Subsequent invocations produce ``Fred was in the +session``. + You can use a session much like a Python dictionary. It supports all dictionary methods, along with some extra attributes, and methods. -- cgit v1.2.3 From 66be39bf656a2840931603bc959e38ff95e53164 Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Wed, 2 Oct 2013 15:35:24 -0400 Subject: - Removed mention of ``pyramid_beaker`` from docs. Beaker is no longer maintained. Point people at ``pyramid_redis_sessions`` instead. --- docs/narr/sessions.rst | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) (limited to 'docs/narr/sessions.rst') diff --git a/docs/narr/sessions.rst b/docs/narr/sessions.rst index 358977089..f8279b0a5 100644 --- a/docs/narr/sessions.rst +++ b/docs/narr/sessions.rst @@ -146,8 +146,6 @@ Some gotchas: you've changed sessioning data. .. index:: - single: pyramid_beaker - single: Beaker single: pyramid_redis_sessions single: session factory (alternates) @@ -156,20 +154,11 @@ Some gotchas: Using Alternate Session Factories --------------------------------- -At the time of this writing, exactly two alternate session factories -exist. - -The first is named ``pyramid_redis_sessions``. It can be downloaded from PyPI. +At the time of this writing, exactly one project-endorsed alternate session +factory exists named``pyramid_redis_sessions``. It can be downloaded from PyPI. It uses Redis as a backend. It is the recommended persistent session solution at the time of this writing. -The second is named ``pyramid_beaker``. This is a session factory that uses the -`Beaker `_ library as a backend. Beaker has -support for file-based sessions, database based sessions, and encrypted -cookie-based sessions. See `the pyramid_beaker documentation -`_ for more -information about ``pyramid_beaker``. - .. index:: single: session factory (custom) -- cgit v1.2.3 From b31cdc5beb173716235a026d264dafde12fea109 Mon Sep 17 00:00:00 2001 From: "Karl O. Pinc" Date: Wed, 2 Oct 2013 14:47:01 -0500 Subject: Docs: sessions.rst: Sessions only work when the client cooperates. --- docs/narr/sessions.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'docs/narr/sessions.rst') diff --git a/docs/narr/sessions.rst b/docs/narr/sessions.rst index eafa9dbf9..db1e0ea20 100644 --- a/docs/narr/sessions.rst +++ b/docs/narr/sessions.rst @@ -101,7 +101,8 @@ example: The first time this view is invoked produces ``Fred was not in the session``. Subsequent invocations produce ``Fred was in the -session``. +session``, assuming of course that the client side maintains the +session's identity across multiple requests. You can use a session much like a Python dictionary. It supports all dictionary methods, along with some extra attributes, and methods. -- cgit v1.2.3 From ab2fedf7adaec0a56a69beed35312c88d7961c6c Mon Sep 17 00:00:00 2001 From: Chris McDonough Date: Wed, 2 Oct 2013 17:47:17 -0400 Subject: fix the docs build and get rid of stray references to Beaker --- docs/narr/sessions.rst | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'docs/narr/sessions.rst') diff --git a/docs/narr/sessions.rst b/docs/narr/sessions.rst index f4da5d82a..649d22bd2 100644 --- a/docs/narr/sessions.rst +++ b/docs/narr/sessions.rst @@ -159,10 +159,10 @@ Some gotchas: Using Alternate Session Factories --------------------------------- -At the time of this writing, exactly one project-endorsed alternate session -factory exists named``pyramid_redis_sessions``. It can be downloaded from PyPI. -It uses Redis as a backend. It is the recommended persistent session solution -at the time of this writing. +At the time of this writing, exactly one project-endorsed alternate session +factory exists named :term:`pyramid_redis_sessions`. It can be downloaded from +PyPI. It uses the Redis database as a backend. It is the recommended +persistent session solution at the time of this writing. .. index:: single: session factory (custom) -- cgit v1.2.3 From 3acee31f86bcde8abbb4e63715afc5ca67976eaf Mon Sep 17 00:00:00 2001 From: Michael Merickel Date: Thu, 17 Oct 2013 13:32:49 -0500 Subject: fix documentation for csrf checking --- docs/narr/sessions.rst | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) (limited to 'docs/narr/sessions.rst') diff --git a/docs/narr/sessions.rst b/docs/narr/sessions.rst index 649d22bd2..f33bc6132 100644 --- a/docs/narr/sessions.rst +++ b/docs/narr/sessions.rst @@ -363,25 +363,27 @@ Or, include it as a header in a jQuery AJAX request: The handler for the URL that receives the request should then require that the correct CSRF token is supplied. -Using the ``session.check_csrf_token`` Method -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Checking CSRF Tokens Manually +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ In request handling code, you can check the presence and validity of a CSRF -token with ``session.check_csrf_token(request)``. If the token is valid, -it will return True, otherwise it will raise ``HTTPBadRequest``. +token with :func:`pyramid.session.check_csrf_token(request)``. If the token is +valid, it will return ``True``, otherwise it will raise ``HTTPBadRequest``. +Optionally, you can specify ``raises=False`` to have the check return ``False`` +instead of raising an exception. By default, it checks for a GET or POST parameter named ``csrf_token`` or a header named ``X-CSRF-Token``. .. code-block:: python - def myview(request): - session = request.session + from pyramid.session import check_csrf_token + def myview(request): # Require CSRF Token - session.check_csrf_token(request): + check_csrf_token(request) - ... + # ... .. index:: single: session.new_csrf_token -- cgit v1.2.3 From 8df7a71d99bbeb7819e8a2752012d51202669aa6 Mon Sep 17 00:00:00 2001 From: Michael Merickel Date: Sat, 19 Oct 2013 01:30:58 -0500 Subject: update the docs --- docs/narr/sessions.rst | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) (limited to 'docs/narr/sessions.rst') diff --git a/docs/narr/sessions.rst b/docs/narr/sessions.rst index 358977089..1d914f9ea 100644 --- a/docs/narr/sessions.rst +++ b/docs/narr/sessions.rst @@ -43,24 +43,23 @@ limitations: It is digitally signed, however, and thus its data cannot easily be tampered with. -You can configure this session factory in your :app:`Pyramid` -application by using the ``session_factory`` argument to the -:class:`~pyramid.config.Configurator` class: +You can configure this session factory in your :app:`Pyramid` application +by using the :meth:`pyramid.config.Configurator.set_session_factory`` method. .. code-block:: python :linenos: - from pyramid.session import UnencryptedCookieSessionFactoryConfig - my_session_factory = UnencryptedCookieSessionFactoryConfig('itsaseekreet') - + from pyramid.session import SignedCookieSessionFactory + my_session_factory = SignedCookieSessionFactory('itsaseekreet') + from pyramid.config import Configurator - config = Configurator(session_factory = my_session_factory) + config = Configurator() + config.set_session_factory(my_session_factory) .. warning:: - Note the very long, very explicit name for - ``UnencryptedCookieSessionFactoryConfig``. It's trying to tell you that - this implementation is, by default, *unencrypted*. You should not use it + By default the :func:`~pyramid.session.SignedCookieSessionFactory` + implementation is *unencrypted*. You should not use it when you keep sensitive information in the session object, as the information can be easily read by both users of your application and third parties who have access to your users' network traffic. And if you use this -- cgit v1.2.3 From 5ac519452613b7bd5df22293c2ccb3b9c3597ef4 Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Mon, 10 Feb 2014 01:10:05 -0600 Subject: - Update list of session packages - Update Quick Tour section on sessions - Closes PR #1150 --- docs/narr/sessions.rst | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) (limited to 'docs/narr/sessions.rst') diff --git a/docs/narr/sessions.rst b/docs/narr/sessions.rst index fb5035373..8da743a01 100644 --- a/docs/narr/sessions.rst +++ b/docs/narr/sessions.rst @@ -158,10 +158,24 @@ Some gotchas: Using Alternate Session Factories --------------------------------- -At the time of this writing, exactly one project-endorsed alternate session -factory exists named :term:`pyramid_redis_sessions`. It can be downloaded from -PyPI. It uses the Redis database as a backend. It is the recommended -persistent session solution at the time of this writing. +The following session factories exist at the time of this writing. + +======================= ======= ============================= +Session Factory Backend Description +======================= ======= ============================= +pyramid_redis_sessions_ Redis_ Server-side session library + for Pyramid, using Redis for + storage. +pyramid_beaker_ Beaker_ Session factory for Pyramid + backed by the Beaker + sessioning system. +======================= ======= ============================= + +.. _pyramid_redis_sessions: https://pypi.python.org/pypi/pyramid_redis_sessions +.. _Redis: http://redis.io/ + +.. _pyramid_beaker: https://pypi.python.org/pypi/pyramid_beaker +.. _Beaker: http://beaker.readthedocs.org/en/latest/ .. index:: single: session factory (custom) -- cgit v1.2.3 From 99d7c44610ad56bac0e90ba119b003ef11b2eb5a Mon Sep 17 00:00:00 2001 From: Pavlo Kapyshin Date: Wed, 7 Jan 2015 14:51:45 +0200 Subject: Fix rendering --- docs/narr/sessions.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'docs/narr/sessions.rst') diff --git a/docs/narr/sessions.rst b/docs/narr/sessions.rst index 8da743a01..f20a36d81 100644 --- a/docs/narr/sessions.rst +++ b/docs/narr/sessions.rst @@ -44,7 +44,7 @@ It is digitally signed, however, and thus its data cannot easily be tampered with. You can configure this session factory in your :app:`Pyramid` application -by using the :meth:`pyramid.config.Configurator.set_session_factory`` method. +by using the :meth:`pyramid.config.Configurator.set_session_factory` method. .. code-block:: python :linenos: @@ -380,7 +380,7 @@ Checking CSRF Tokens Manually ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ In request handling code, you can check the presence and validity of a CSRF -token with :func:`pyramid.session.check_csrf_token(request)``. If the token is +token with ``pyramid.session.check_csrf_token(request)``. If the token is valid, it will return ``True``, otherwise it will raise ``HTTPBadRequest``. Optionally, you can specify ``raises=False`` to have the check return ``False`` instead of raising an exception. -- cgit v1.2.3 From 47e85294779814f14e02327eb4d378197bbaeb29 Mon Sep 17 00:00:00 2001 From: Pavlo Kapyshin Date: Wed, 7 Jan 2015 19:10:31 +0200 Subject: Provide a ref to check_csrf_token --- docs/narr/sessions.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs/narr/sessions.rst') diff --git a/docs/narr/sessions.rst b/docs/narr/sessions.rst index f20a36d81..5c103405a 100644 --- a/docs/narr/sessions.rst +++ b/docs/narr/sessions.rst @@ -380,7 +380,7 @@ Checking CSRF Tokens Manually ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ In request handling code, you can check the presence and validity of a CSRF -token with ``pyramid.session.check_csrf_token(request)``. If the token is +token with :func:`pyramid.session.check_csrf_token`. If the token is valid, it will return ``True``, otherwise it will raise ``HTTPBadRequest``. Optionally, you can specify ``raises=False`` to have the check return ``False`` instead of raising an exception. -- cgit v1.2.3 From 7cb892010592f52cb754c428f648390043ac75a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kiss=20Gy=C3=B6rgy?= Date: Sat, 30 May 2015 16:15:11 +0200 Subject: Added notes on check_csrf view predicate. Also it is an add_view parameter, not add_route. --- docs/narr/sessions.rst | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'docs/narr/sessions.rst') diff --git a/docs/narr/sessions.rst b/docs/narr/sessions.rst index 5c103405a..f37cc3c7d 100644 --- a/docs/narr/sessions.rst +++ b/docs/narr/sessions.rst @@ -56,7 +56,7 @@ by using the :meth:`pyramid.config.Configurator.set_session_factory` method. config = Configurator() config.set_session_factory(my_session_factory) -.. warning:: +.. warning:: By default the :func:`~pyramid.session.SignedCookieSessionFactory` implementation is *unencrypted*. You should not use it @@ -112,7 +112,7 @@ Extra attributes: An integer timestamp indicating the time that this session was created. ``new`` - A boolean. If ``new`` is True, this session is new. Otherwise, it has + A boolean. If ``new`` is True, this session is new. Otherwise, it has been constituted from data that was already serialized. Extra methods: @@ -225,7 +225,7 @@ method: request.session.flash('mymessage') The ``flash()`` method appends a message to a flash queue, creating the queue -if necessary. +if necessary. ``flash()`` accepts three arguments: @@ -406,7 +406,7 @@ Checking CSRF Tokens With A View Predicate A convenient way to require a valid CSRF Token for a particular view is to include ``check_csrf=True`` as a view predicate. -See :meth:`pyramid.config.Configurator.add_route`. +See :meth:`pyramid.config.Configurator.add_view`. .. code-block:: python @@ -414,6 +414,12 @@ See :meth:`pyramid.config.Configurator.add_route`. def myview(request): ... +.. note:: + A mismatch of csrf token is treated like any other predicate miss, and the + predicate system, when it doesn't find a view, raises ``HTTPNotFound`` + instead of ``HTTPBadRequest``, so ``check_csrf=True`` behavior is different + from calling :func:`pyramid.session.check_csrf_token`. + Using the ``session.new_csrf_token`` Method ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -- cgit v1.2.3 From d5923976b090e3538d9e655d72361cbfab6a250a Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Sun, 31 May 2015 11:48:55 -0700 Subject: - update testing and templating remarks - grammar, punctuation, 79-column rewrapping, case corrections --- docs/narr/sessions.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'docs/narr/sessions.rst') diff --git a/docs/narr/sessions.rst b/docs/narr/sessions.rst index f37cc3c7d..916c6c1f6 100644 --- a/docs/narr/sessions.rst +++ b/docs/narr/sessions.rst @@ -415,7 +415,7 @@ See :meth:`pyramid.config.Configurator.add_view`. ... .. note:: - A mismatch of csrf token is treated like any other predicate miss, and the + A mismatch of CSRF token is treated like any other predicate miss, and the predicate system, when it doesn't find a view, raises ``HTTPNotFound`` instead of ``HTTPBadRequest``, so ``check_csrf=True`` behavior is different from calling :func:`pyramid.session.check_csrf_token`. -- cgit v1.2.3 From 42049eb25d91a45d46f581a18d82a91b63470290 Mon Sep 17 00:00:00 2001 From: Steve Piercy Date: Fri, 16 Oct 2015 05:09:21 -0700 Subject: minor grammar, rewrap 79 cols (cherry picked from commit a18960a) --- docs/narr/sessions.rst | 239 +++++++++++++++++++++++-------------------------- 1 file changed, 113 insertions(+), 126 deletions(-) (limited to 'docs/narr/sessions.rst') diff --git a/docs/narr/sessions.rst b/docs/narr/sessions.rst index 916c6c1f6..db554a93b 100644 --- a/docs/narr/sessions.rst +++ b/docs/narr/sessions.rst @@ -6,45 +6,44 @@ Sessions ======== -A :term:`session` is a namespace which is valid for some period of -continual activity that can be used to represent a user's interaction -with a web application. +A :term:`session` is a namespace which is valid for some period of continual +activity that can be used to represent a user's interaction with a web +application. -This chapter describes how to configure sessions, what session -implementations :app:`Pyramid` provides out of the box, how to store and -retrieve data from sessions, and two session-specific features: flash -messages, and cross-site request forgery attack prevention. +This chapter describes how to configure sessions, what session implementations +:app:`Pyramid` provides out of the box, how to store and retrieve data from +sessions, and two session-specific features: flash messages, and cross-site +request forgery attack prevention. .. index:: single: session factory (default) .. _using_the_default_session_factory: -Using The Default Session Factory +Using the Default Session Factory --------------------------------- -In order to use sessions, you must set up a :term:`session factory` -during your :app:`Pyramid` configuration. +In order to use sessions, you must set up a :term:`session factory` during your +:app:`Pyramid` configuration. -A very basic, insecure sample session factory implementation is -provided in the :app:`Pyramid` core. It uses a cookie to store -session information. This implementation has the following -limitations: +A very basic, insecure sample session factory implementation is provided in the +:app:`Pyramid` core. It uses a cookie to store session information. This +implementation has the following limitations: -- The session information in the cookies used by this implementation - is *not* encrypted, so it can be viewed by anyone with access to the - cookie storage of the user's browser or anyone with access to the - network along which the cookie travels. +- The session information in the cookies used by this implementation is *not* + encrypted, so it can be viewed by anyone with access to the cookie storage of + the user's browser or anyone with access to the network along which the + cookie travels. -- The maximum number of bytes that are storable in a serialized - representation of the session is fewer than 4000. This is - suitable only for very small data sets. +- The maximum number of bytes that are storable in a serialized representation + of the session is fewer than 4000. This is suitable only for very small data + sets. -It is digitally signed, however, and thus its data cannot easily be -tampered with. +It is digitally signed, however, and thus its data cannot easily be tampered +with. -You can configure this session factory in your :app:`Pyramid` application -by using the :meth:`pyramid.config.Configurator.set_session_factory` method. +You can configure this session factory in your :app:`Pyramid` application by +using the :meth:`pyramid.config.Configurator.set_session_factory` method. .. code-block:: python :linenos: @@ -59,17 +58,17 @@ by using the :meth:`pyramid.config.Configurator.set_session_factory` method. .. warning:: By default the :func:`~pyramid.session.SignedCookieSessionFactory` - implementation is *unencrypted*. You should not use it - when you keep sensitive information in the session object, as the - information can be easily read by both users of your application and third - parties who have access to your users' network traffic. And if you use this - sessioning implementation, and you inadvertently create a cross-site - scripting vulnerability in your application, because the session data is - stored unencrypted in a cookie, it will also be easier for evildoers to - obtain the current user's cross-site scripting token. In short, use a - different session factory implementation (preferably one which keeps session - data on the server) for anything but the most basic of applications where - "session security doesn't matter", and you are sure your application has no + implementation is *unencrypted*. You should not use it when you keep + sensitive information in the session object, as the information can be + easily read by both users of your application and third parties who have + access to your users' network traffic. And, if you use this sessioning + implementation, and you inadvertently create a cross-site scripting + vulnerability in your application, because the session data is stored + unencrypted in a cookie, it will also be easier for evildoers to obtain the + current user's cross-site scripting token. In short, use a different + session factory implementation (preferably one which keeps session data on + the server) for anything but the most basic of applications where "session + security doesn't matter", and you are sure your application has no cross-site scripting vulnerabilities. .. index:: @@ -78,10 +77,9 @@ by using the :meth:`pyramid.config.Configurator.set_session_factory` method. Using a Session Object ---------------------- -Once a session factory has been configured for your application, you -can access session objects provided by the session factory via -the ``session`` attribute of any :term:`request` object. For -example: +Once a session factory has been configured for your application, you can access +session objects provided by the session factory via the ``session`` attribute +of any :term:`request` object. For example: .. code-block:: python :linenos: @@ -98,13 +96,12 @@ example: else: return Response('Fred was not in the session') -The first time this view is invoked produces ``Fred was not in the -session``. Subsequent invocations produce ``Fred was in the -session``, assuming of course that the client side maintains the -session's identity across multiple requests. +The first time this view is invoked produces ``Fred was not in the session``. +Subsequent invocations produce ``Fred was in the session``, assuming of course +that the client side maintains the session's identity across multiple requests. You can use a session much like a Python dictionary. It supports all -dictionary methods, along with some extra attributes, and methods. +dictionary methods, along with some extra attributes and methods. Extra attributes: @@ -112,42 +109,39 @@ Extra attributes: An integer timestamp indicating the time that this session was created. ``new`` - A boolean. If ``new`` is True, this session is new. Otherwise, it has - been constituted from data that was already serialized. + A boolean. If ``new`` is True, this session is new. Otherwise, it has been + constituted from data that was already serialized. Extra methods: ``changed()`` - Call this when you mutate a mutable value in the session namespace. - See the gotchas below for details on when, and why you should - call this. + Call this when you mutate a mutable value in the session namespace. See the + gotchas below for details on when and why you should call this. ``invalidate()`` - Call this when you want to invalidate the session (dump all data, - and -- perhaps -- set a clearing cookie). + Call this when you want to invalidate the session (dump all data, and perhaps + set a clearing cookie). -The formal definition of the methods and attributes supported by the -session object are in the :class:`pyramid.interfaces.ISession` -documentation. +The formal definition of the methods and attributes supported by the session +object are in the :class:`pyramid.interfaces.ISession` documentation. Some gotchas: -- Keys and values of session data must be *pickleable*. This means, - typically, that they are instances of basic types of objects, - such as strings, lists, dictionaries, tuples, integers, etc. If you - place an object in a session data key or value that is not - pickleable, an error will be raised when the session is serialized. - -- If you place a mutable value (for example, a list or a dictionary) - in a session object, and you subsequently mutate that value, you must - call the ``changed()`` method of the session object. In this case, the - session has no way to know that is was modified. However, when you - modify a session object directly, such as setting a value (i.e., - ``__setitem__``), or removing a key (e.g., ``del`` or ``pop``), the - session will automatically know that it needs to re-serialize its - data, thus calling ``changed()`` is unnecessary. There is no harm in - calling ``changed()`` in either case, so when in doubt, call it after - you've changed sessioning data. +- Keys and values of session data must be *pickleable*. This means, typically, + that they are instances of basic types of objects, such as strings, lists, + dictionaries, tuples, integers, etc. If you place an object in a session + data key or value that is not pickleable, an error will be raised when the + session is serialized. + +- If you place a mutable value (for example, a list or a dictionary) in a + session object, and you subsequently mutate that value, you must call the + ``changed()`` method of the session object. In this case, the session has no + way to know that it was modified. However, when you modify a session object + directly, such as setting a value (i.e., ``__setitem__``), or removing a key + (e.g., ``del`` or ``pop``), the session will automatically know that it needs + to re-serialize its data, thus calling ``changed()`` is unnecessary. There is + no harm in calling ``changed()`` in either case, so when in doubt, call it + after you've changed sessioning data. .. index:: single: pyramid_redis_sessions @@ -183,14 +177,13 @@ pyramid_beaker_ Beaker_ Session factory for Pyramid Creating Your Own Session Factory --------------------------------- -If none of the default or otherwise available sessioning -implementations for :app:`Pyramid` suit you, you may create your own -session object by implementing a :term:`session factory`. Your -session factory should return a :term:`session`. The interfaces for -both types are available in +If none of the default or otherwise available sessioning implementations for +:app:`Pyramid` suit you, you may create your own session object by implementing +a :term:`session factory`. Your session factory should return a +:term:`session`. The interfaces for both types are available in :class:`pyramid.interfaces.ISessionFactory` and -:class:`pyramid.interfaces.ISession`. You might use the cookie -implementation in the :mod:`pyramid.session` module as inspiration. +:class:`pyramid.interfaces.ISession`. You might use the cookie implementation +in the :mod:`pyramid.session` module as inspiration. .. index:: single: flash messages @@ -205,9 +198,9 @@ Flash Messages factory` as described in :ref:`using_the_default_session_factory` or :ref:`using_alternate_session_factories`. -Flash messaging has two main uses: to display a status message only once to -the user after performing an internal redirect, and to allow generic code to -log messages for single-time display without having direct access to an HTML +Flash messaging has two main uses: to display a status message only once to the +user after performing an internal redirect, and to allow generic code to log +messages for single-time display without having direct access to an HTML template. The user interface consists of a number of methods of the :term:`session` object. @@ -235,22 +228,21 @@ The ``message`` argument is required. It represents a message you wish to later display to a user. It is usually a string but the ``message`` you provide is not modified in any way. -The ``queue`` argument allows you to choose a queue to which to append -the message you provide. This can be used to push different kinds of -messages into flash storage for later display in different places on a -page. You can pass any name for your queue, but it must be a string. -Each queue is independent, and can be popped by ``pop_flash()`` or -examined via ``peek_flash()`` separately. ``queue`` defaults to the -empty string. The empty string represents the default flash message -queue. +The ``queue`` argument allows you to choose a queue to which to append the +message you provide. This can be used to push different kinds of messages into +flash storage for later display in different places on a page. You can pass +any name for your queue, but it must be a string. Each queue is independent, +and can be popped by ``pop_flash()`` or examined via ``peek_flash()`` +separately. ``queue`` defaults to the empty string. The empty string +represents the default flash message queue. .. code-block:: python request.session.flash(msg, 'myappsqueue') -The ``allow_duplicate`` argument defaults to ``True``. If this is -``False``, and you attempt to add a message value which is already -present in the queue, it will not be added. +The ``allow_duplicate`` argument defaults to ``True``. If this is ``False``, +and you attempt to add a message value which is already present in the queue, +it will not be added. .. index:: single: session.pop_flash @@ -259,12 +251,12 @@ Using the ``session.pop_flash`` Method ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Once one or more messages have been added to a flash queue by the -``session.flash()`` API, the ``session.pop_flash()`` API can be used to -pop an entire queue and return it for use. +``session.flash()`` API, the ``session.pop_flash()`` API can be used to pop an +entire queue and return it for use. To pop a particular queue of messages from the flash object, use the session -object's ``pop_flash()`` method. This returns a list of the messages -that were added to the flash queue, and empties the queue. +object's ``pop_flash()`` method. This returns a list of the messages that were +added to the flash queue, and empties the queue. .. method:: pop_flash(queue='') @@ -288,10 +280,10 @@ been popped. Using the ``session.peek_flash`` Method ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Once one or more messages has been added to a flash queue by the -``session.flash()`` API, the ``session.peek_flash()`` API can be used to -"peek" at that queue. Unlike ``session.pop_flash()``, the queue is not -popped from flash storage. +Once one or more messages have been added to a flash queue by the +``session.flash()`` API, the ``session.peek_flash()`` API can be used to "peek" +at that queue. Unlike ``session.pop_flash()``, the queue is not popped from +flash storage. .. method:: peek_flash(queue='') @@ -322,8 +314,8 @@ You can avoid most of these attacks by issuing a unique token to the browser and then requiring that it be present in all potentially unsafe requests. :app:`Pyramid` sessions provide facilities to create and check CSRF tokens. -To use CSRF tokens, you must first enable a :term:`session factory` -as described in :ref:`using_the_default_session_factory` or +To use CSRF tokens, you must first enable a :term:`session factory` as +described in :ref:`using_the_default_session_factory` or :ref:`using_alternate_session_factories`. .. index:: @@ -342,9 +334,9 @@ To get the current CSRF token from the session, use the The ``session.get_csrf_token()`` method accepts no arguments. It returns a CSRF *token* string. If ``session.get_csrf_token()`` or ``session.new_csrf_token()`` was invoked previously for this session, then the -existing token will be returned. If no CSRF token previously existed for -this session, then a new token will be will be set into the session and returned. -The newly created token will be opaque and randomized. +existing token will be returned. If no CSRF token previously existed for this +session, then a new token will be set into the session and returned. The newly +created token will be opaque and randomized. You can use the returned token as the value of a hidden field in a form that posts to a method that requires elevated privileges, or supply it as a request @@ -359,7 +351,7 @@ For example, include the CSRF token as a hidden field: -Or, include it as a header in a jQuery AJAX request: +Or include it as a header in a jQuery AJAX request: .. code-block:: javascript @@ -372,18 +364,17 @@ Or, include it as a header in a jQuery AJAX request: alert("Deleted"); }); - -The handler for the URL that receives the request -should then require that the correct CSRF token is supplied. +The handler for the URL that receives the request should then require that the +correct CSRF token is supplied. Checking CSRF Tokens Manually ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ In request handling code, you can check the presence and validity of a CSRF -token with :func:`pyramid.session.check_csrf_token`. If the token is -valid, it will return ``True``, otherwise it will raise ``HTTPBadRequest``. -Optionally, you can specify ``raises=False`` to have the check return ``False`` -instead of raising an exception. +token with :func:`pyramid.session.check_csrf_token`. If the token is valid, it +will return ``True``, otherwise it will raise ``HTTPBadRequest``. Optionally, +you can specify ``raises=False`` to have the check return ``False`` instead of +raising an exception. By default, it checks for a GET or POST parameter named ``csrf_token`` or a header named ``X-CSRF-Token``. @@ -401,12 +392,12 @@ header named ``X-CSRF-Token``. .. index:: single: session.new_csrf_token -Checking CSRF Tokens With A View Predicate +Checking CSRF Tokens with a View Predicate ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -A convenient way to require a valid CSRF Token for a particular view is to -include ``check_csrf=True`` as a view predicate. -See :meth:`pyramid.config.Configurator.add_view`. +A convenient way to require a valid CSRF token for a particular view is to +include ``check_csrf=True`` as a view predicate. See +:meth:`pyramid.config.Configurator.add_view`. .. code-block:: python @@ -415,23 +406,19 @@ See :meth:`pyramid.config.Configurator.add_view`. ... .. note:: - A mismatch of CSRF token is treated like any other predicate miss, and the + A mismatch of a CSRF token is treated like any other predicate miss, and the predicate system, when it doesn't find a view, raises ``HTTPNotFound`` instead of ``HTTPBadRequest``, so ``check_csrf=True`` behavior is different from calling :func:`pyramid.session.check_csrf_token`. - Using the ``session.new_csrf_token`` Method ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -To explicitly create a new CSRF token, use the -``session.new_csrf_token()`` method. This differs only from -``session.get_csrf_token()`` inasmuch as it clears any existing CSRF token, -creates a new CSRF token, sets the token into the session, and returns the -token. +To explicitly create a new CSRF token, use the ``session.new_csrf_token()`` +method. This differs only from ``session.get_csrf_token()`` inasmuch as it +clears any existing CSRF token, creates a new CSRF token, sets the token into +the session, and returns the token. .. code-block:: python token = request.session.new_csrf_token() - - -- cgit v1.2.3 From 6b35eb6ca3b271e2943d37307c925c5733e082d9 Mon Sep 17 00:00:00 2001 From: Michael Merickel Date: Sun, 10 Apr 2016 20:50:10 -0500 Subject: rewrite csrf checks to support a global setting to turn it on - only check csrf on POST - support "pyramid.require_default_csrf" setting - support "require_csrf=True" to fallback to the global setting to determine the token name --- docs/narr/sessions.rst | 42 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 40 insertions(+), 2 deletions(-) (limited to 'docs/narr/sessions.rst') diff --git a/docs/narr/sessions.rst b/docs/narr/sessions.rst index db554a93b..3baed1cb8 100644 --- a/docs/narr/sessions.rst +++ b/docs/narr/sessions.rst @@ -389,8 +389,43 @@ header named ``X-CSRF-Token``. # ... -.. index:: - single: session.new_csrf_token +.. _auto_csrf_checking: + +Checking CSRF Tokens Automatically +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. versionadded:: 1.7 + +:app:`Pyramid` supports automatically checking CSRF tokens on POST requests. +Any other request may be checked manually. This feature can be turned on +globally for an application using the ``pyramid.require_default_csrf`` setting. + +If the ``pyramid.required_default_csrf`` setting is a :term:`truthy string` or +``True`` then the default CSRF token parameter will be ``csrf_token``. If a +different token is desired, it may be passed as the value. Finally, a +:term:`falsey string` or ``False`` will turn off automatic CSRF checking +globally on every POST request. + +No matter what, CSRF checking may be explicitly enabled or disabled on a +per-view basis using the ``require_csrf`` view option. This option is of the +same format as the ``pyramid.require_default_csrf`` setting, accepting strings +or boolean values. + +If ``require_csrf`` is ``True`` but does not explicitly define a token to +check, then the token name is pulled from whatever was set in the +``pyramid.require_default_csrf`` setting. Finally, if that setting does not +explicitly define a token, then ``csrf_token`` is the token required. This token +name will be required in ``request.params`` which is a combination of the +query string and a submitted form body. + +It is always possible to pass the token in the ``X-CSRF-Token`` header as well. +There is currently no way to define an alternate name for this header without +performing CSRF checking manually. + +If CSRF checks fail then a :class:`pyramid.exceptions.BadCSRFToken` exception +will be raised. This exception may be caught and handled by an +:term:`exception view` but, by default, will result in a ``400 Bad Request`` +resposne being sent to the client. Checking CSRF Tokens with a View Predicate ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -411,6 +446,9 @@ include ``check_csrf=True`` as a view predicate. See instead of ``HTTPBadRequest``, so ``check_csrf=True`` behavior is different from calling :func:`pyramid.session.check_csrf_token`. +.. index:: + single: session.new_csrf_token + Using the ``session.new_csrf_token`` Method ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -- cgit v1.2.3 From 15b97dc81c8bcdc039f8f2293f85812f68a076da Mon Sep 17 00:00:00 2001 From: Michael Merickel Date: Sun, 10 Apr 2016 20:51:23 -0500 Subject: deprecate the check_csrf predicate --- docs/narr/sessions.rst | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'docs/narr/sessions.rst') diff --git a/docs/narr/sessions.rst b/docs/narr/sessions.rst index 3baed1cb8..4e8f6db88 100644 --- a/docs/narr/sessions.rst +++ b/docs/narr/sessions.rst @@ -430,6 +430,10 @@ resposne being sent to the client. Checking CSRF Tokens with a View Predicate ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +.. deprecated:: 1.7 + Use the ``require_csrf`` option or read :ref:`auto_csrf_checking` instead + to have :class:`pyramid.exceptions.BadCSRFToken` exceptions raised. + A convenient way to require a valid CSRF token for a particular view is to include ``check_csrf=True`` as a view predicate. See :meth:`pyramid.config.Configurator.add_view`. -- cgit v1.2.3 From 769da1215a0287f4161e58f36d8d4b7650154202 Mon Sep 17 00:00:00 2001 From: Michael Merickel Date: Sun, 10 Apr 2016 21:14:22 -0500 Subject: cleanup some references in the docs --- docs/narr/sessions.rst | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) (limited to 'docs/narr/sessions.rst') diff --git a/docs/narr/sessions.rst b/docs/narr/sessions.rst index 4e8f6db88..d66e86258 100644 --- a/docs/narr/sessions.rst +++ b/docs/narr/sessions.rst @@ -367,6 +367,21 @@ Or include it as a header in a jQuery AJAX request: The handler for the URL that receives the request should then require that the correct CSRF token is supplied. +.. index:: + single: session.new_csrf_token + +Using the ``session.new_csrf_token`` Method +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +To explicitly create a new CSRF token, use the ``session.new_csrf_token()`` +method. This differs only from ``session.get_csrf_token()`` inasmuch as it +clears any existing CSRF token, creates a new CSRF token, sets the token into +the session, and returns the token. + +.. code-block:: python + + token = request.session.new_csrf_token() + Checking CSRF Tokens Manually ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -425,7 +440,7 @@ performing CSRF checking manually. If CSRF checks fail then a :class:`pyramid.exceptions.BadCSRFToken` exception will be raised. This exception may be caught and handled by an :term:`exception view` but, by default, will result in a ``400 Bad Request`` -resposne being sent to the client. +response being sent to the client. Checking CSRF Tokens with a View Predicate ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -449,18 +464,3 @@ include ``check_csrf=True`` as a view predicate. See predicate system, when it doesn't find a view, raises ``HTTPNotFound`` instead of ``HTTPBadRequest``, so ``check_csrf=True`` behavior is different from calling :func:`pyramid.session.check_csrf_token`. - -.. index:: - single: session.new_csrf_token - -Using the ``session.new_csrf_token`` Method -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -To explicitly create a new CSRF token, use the ``session.new_csrf_token()`` -method. This differs only from ``session.get_csrf_token()`` inasmuch as it -clears any existing CSRF token, creates a new CSRF token, sets the token into -the session, and returns the token. - -.. code-block:: python - - token = request.session.new_csrf_token() -- cgit v1.2.3 From f12005b92fa9bb33f082bd50747eb11791605cff Mon Sep 17 00:00:00 2001 From: Donald Stufft Date: Fri, 15 Apr 2016 17:41:35 -0400 Subject: Only Accept CSRF Tokens in headers or POST bodies Previously `check_csrf_token` would allow passing in a CSRF token in through a the URL of a request. However this is a security issue because a CSRF token must not be allowed to leak, and URLs regularly get copy/pasted or otherwise end up leaking to the outside world. --- docs/narr/sessions.rst | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'docs/narr/sessions.rst') diff --git a/docs/narr/sessions.rst b/docs/narr/sessions.rst index d66e86258..ad086268b 100644 --- a/docs/narr/sessions.rst +++ b/docs/narr/sessions.rst @@ -391,8 +391,8 @@ will return ``True``, otherwise it will raise ``HTTPBadRequest``. Optionally, you can specify ``raises=False`` to have the check return ``False`` instead of raising an exception. -By default, it checks for a GET or POST parameter named ``csrf_token`` or a -header named ``X-CSRF-Token``. +By default, it checks for a POST parameter named ``csrf_token`` or a header +named ``X-CSRF-Token``. .. code-block:: python @@ -430,8 +430,7 @@ If ``require_csrf`` is ``True`` but does not explicitly define a token to check, then the token name is pulled from whatever was set in the ``pyramid.require_default_csrf`` setting. Finally, if that setting does not explicitly define a token, then ``csrf_token`` is the token required. This token -name will be required in ``request.params`` which is a combination of the -query string and a submitted form body. +name will be required in ``request.POST`` which is the submitted form body. It is always possible to pass the token in the ``X-CSRF-Token`` header as well. There is currently no way to define an alternate name for this header without -- cgit v1.2.3 From 21d5beaed1641e1f50ab1ab3c481b1c8f3ad1173 Mon Sep 17 00:00:00 2001 From: Donald Stufft Date: Fri, 15 Apr 2016 17:59:55 -0400 Subject: Have Automatic CSRF on all unsafe HTTP methods Instead of only protecting against unsafe POST requests, have the automatic CSRF protect on all methods which are not defined as "safe" by RFC2616. --- docs/narr/sessions.rst | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'docs/narr/sessions.rst') diff --git a/docs/narr/sessions.rst b/docs/narr/sessions.rst index ad086268b..0e895ff81 100644 --- a/docs/narr/sessions.rst +++ b/docs/narr/sessions.rst @@ -411,15 +411,16 @@ Checking CSRF Tokens Automatically .. versionadded:: 1.7 -:app:`Pyramid` supports automatically checking CSRF tokens on POST requests. -Any other request may be checked manually. This feature can be turned on -globally for an application using the ``pyramid.require_default_csrf`` setting. +:app:`Pyramid` supports automatically checking CSRF tokens on requests with an +unsafe method as defined by RFC2616. Any other request may be checked manually. +This feature can be turned on globally for an application using the +``pyramid.require_default_csrf`` setting. If the ``pyramid.required_default_csrf`` setting is a :term:`truthy string` or ``True`` then the default CSRF token parameter will be ``csrf_token``. If a different token is desired, it may be passed as the value. Finally, a :term:`falsey string` or ``False`` will turn off automatic CSRF checking -globally on every POST request. +globally on every request. No matter what, CSRF checking may be explicitly enabled or disabled on a per-view basis using the ``require_csrf`` view option. This option is of the -- cgit v1.2.3 From 65dee6e4ca0c0c607e97db0c9e55768f10591a58 Mon Sep 17 00:00:00 2001 From: Donald Stufft Date: Fri, 15 Apr 2016 20:42:20 -0400 Subject: In addition to CSRF token, verify the origin too Add an additional layer of protection against CSRF by verifying the actual origin of the request in addition to the CSRF token. We only do this check on sites hosted behind HTTPS because only HTTPS sites have evidence to show that the Referrer header is not being spuriously removed by random middleware boxes. --- docs/narr/sessions.rst | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'docs/narr/sessions.rst') diff --git a/docs/narr/sessions.rst b/docs/narr/sessions.rst index 0e895ff81..7cf96ac7d 100644 --- a/docs/narr/sessions.rst +++ b/docs/narr/sessions.rst @@ -437,6 +437,14 @@ It is always possible to pass the token in the ``X-CSRF-Token`` header as well. There is currently no way to define an alternate name for this header without performing CSRF checking manually. +In addition to token based CSRF checks, the automatic CSRF checking will also +check the referrer of the request to ensure that it matches one of the trusted +origins. By default the only trusted origin is the current host, however +additional origins may be configured by setting +``pyramid.csrf_trusted_origins`` to a list of domain names (and ports if they +are non standard). If a host in the list of domains starts with a ``.`` then +that will allow all subdomains as well as the domain without the ``.``. + If CSRF checks fail then a :class:`pyramid.exceptions.BadCSRFToken` exception will be raised. This exception may be caught and handled by an :term:`exception view` but, by default, will result in a ``400 Bad Request`` -- cgit v1.2.3