From a2c7c7a49bceeaaab2853e7e73c3671979d4c9ed Mon Sep 17 00:00:00 2001 From: Matthew Wilkes Date: Mon, 5 Dec 2016 12:16:26 +0100 Subject: Create a new ICSRF implementation for getting CSRF tokens, split out from the session machinery. Adds configuration of this to the csrf_options configurator commands. Make the default implementation a fallback to the old one. Documentation patches for new best practices given updates CSRF implementation. --- docs/api/csrf.rst | 18 +++++ docs/api/interfaces.rst | 3 + docs/api/session.rst | 4 - docs/narr/security.rst | 191 ++++++++++++++++++++++++++++++++++++++++++++++++ docs/narr/sessions.rst | 175 -------------------------------------------- 5 files changed, 212 insertions(+), 179 deletions(-) create mode 100644 docs/api/csrf.rst (limited to 'docs') diff --git a/docs/api/csrf.rst b/docs/api/csrf.rst new file mode 100644 index 000000000..3125bdac9 --- /dev/null +++ b/docs/api/csrf.rst @@ -0,0 +1,18 @@ +.. _csrf_module: + +:mod:`pyramid.csrf` +------------------- + +.. automodule:: pyramid.csrf + + .. autofunction:: get_csrf_token + + .. autofunction:: new_csrf_token + + .. autoclass:: SessionCSRF + :members: + + .. autofunction:: check_csrf_origin + + .. autofunction:: check_csrf_token + diff --git a/docs/api/interfaces.rst b/docs/api/interfaces.rst index a212ba7a9..2ca472616 100644 --- a/docs/api/interfaces.rst +++ b/docs/api/interfaces.rst @@ -44,6 +44,9 @@ Other Interfaces .. autointerface:: IRoutePregenerator :members: + .. autointerface:: ICSRF + :members: + .. autointerface:: ISession :members: diff --git a/docs/api/session.rst b/docs/api/session.rst index 56c4f52d7..53bae7c52 100644 --- a/docs/api/session.rst +++ b/docs/api/session.rst @@ -9,10 +9,6 @@ .. autofunction:: signed_deserialize - .. autofunction:: check_csrf_origin - - .. autofunction:: check_csrf_token - .. autofunction:: SignedCookieSessionFactory .. autofunction:: UnencryptedCookieSessionFactoryConfig diff --git a/docs/narr/security.rst b/docs/narr/security.rst index 77e7fd707..b4fb3b8a8 100644 --- a/docs/narr/security.rst +++ b/docs/narr/security.rst @@ -765,3 +765,194 @@ which would allow the attacker to control the content of the payload. Re-using a secret across two different subsystems might drop the security of signing to zero. Keys should not be re-used across different contexts where an attacker has the possibility of providing a chosen plaintext. + +Preventing Cross-Site Request Forgery Attacks +--------------------------------------------- + +`Cross-site request forgery +`_ attacks are a +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`. + +.. index:: + single: csrf.get_csrf_token + +Using the ``csrf.get_csrf_token`` Method +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +To get the current CSRF token, use the +:data:`pyramid.csrf.get_csrf_token` method. + +.. code-block:: python + + from pyramid.csrf import get_csrf_token + token = get_csrf_token(request) + +The ``get_csrf_token()`` method accepts a single argument: the request. It +returns a CSRF *token* string. If ``get_csrf_token()`` or ``new_csrf_token()`` +was invoked previously for this user, then the existing token will be returned. +If no CSRF token previously existed for this user, then a new token will be set +into the session and returned. The newly created token will be opaque and +randomized. + + +Using the ``get_csrf_token`` global in templates +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Templates have a ``get_csrf_token()`` method inserted into their globals, which +allows you to get the current token without modifying the view code. This +method takes no arguments and returns a CSRF token string. 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. + +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 = "${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. + +.. index:: + single: csrf.new_csrf_token + +Using the ``csrf.new_csrf_token`` Method +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +To explicitly create a new CSRF token, use the ``csrf.new_csrf_token()`` +method. This differs only from ``csrf.get_csrf_token()`` inasmuch as it +clears any existing CSRF token, creates a new CSRF token, sets the token into +the user, and returns the token. + +.. code-block:: python + + from pyramid.csrf import get_csrf_token + token = new_csrf_token() + +.. note:: + + It is not possible to force a new CSRF token from a template. If you + want to regenerate your CSRF token then do it in the view code and return + the new token as part of the context. + +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. + +By default, it checks for a POST parameter named ``csrf_token`` or a header +named ``X-CSRF-Token``. + +.. code-block:: python + + from pyramid.session import check_csrf_token + + def myview(request): + # Require CSRF Token + check_csrf_token(request) + + # ... + +.. _auto_csrf_checking: + +Checking CSRF Tokens Automatically +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. versionadded:: 1.7 + +: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 +:meth:`pyramid.config.Configurator.set_default_csrf_options` directive. +For example: + +.. code-block:: python + + from pyramid.config import Configurator + + config = Configurator() + config.set_default_csrf_options(require_csrf=True) + +CSRF checking may be explicitly enabled or disabled on a per-view basis using +the ``require_csrf`` view option. A value of ``True`` or ``False`` will +override the default set by ``set_default_csrf_options``. For example: + +.. code-block:: python + + @view_config(route_name='hello', require_csrf=False) + def myview(request): + # ... + +When CSRF checking is active, the token and header used to find the +supplied CSRF token will be ``csrf_token`` and ``X-CSRF-Token``, respectively, +unless otherwise overridden by ``set_default_csrf_options``. The token is +checked against the value in ``request.POST`` which is the submitted form body. +If this value is not present, then the header will be checked. + +In addition to token based CSRF checks, if the request is using HTTPS then 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` or +:class:`pyramid.exceptions.BadCSRFOrigin` 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`` response 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`. + +.. code-block:: python + + @view_config(request_method='POST', check_csrf=True, ...) + def myview(request): + ... + +.. note:: + 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`. diff --git a/docs/narr/sessions.rst b/docs/narr/sessions.rst index 5b24201a9..90b5f4585 100644 --- a/docs/narr/sessions.rst +++ b/docs/narr/sessions.rst @@ -321,178 +321,3 @@ flash storage. single: preventing cross-site request forgery attacks single: cross-site request forgery attacks, prevention -Preventing Cross-Site Request Forgery Attacks ---------------------------------------------- - -`Cross-site request forgery -`_ attacks are a -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`. - -.. index:: - single: session.get_csrf_token - -Using the ``session.get_csrf_token`` Method -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -To get the current CSRF token from the session, use the -``session.get_csrf_token()`` method. - -.. code-block:: python - - token = request.session.get_csrf_token() - -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 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 -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. - -.. 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 -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -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. - -By default, it checks for a POST parameter named ``csrf_token`` or a header -named ``X-CSRF-Token``. - -.. code-block:: python - - from pyramid.session import check_csrf_token - - def myview(request): - # Require CSRF Token - check_csrf_token(request) - - # ... - -.. _auto_csrf_checking: - -Checking CSRF Tokens Automatically -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. versionadded:: 1.7 - -: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 -:meth:`pyramid.config.Configurator.set_default_csrf_options` directive. -For example: - -.. code-block:: python - - from pyramid.config import Configurator - - config = Configurator() - config.set_default_csrf_options(require_csrf=True) - -CSRF checking may be explicitly enabled or disabled on a per-view basis using -the ``require_csrf`` view option. A value of ``True`` or ``False`` will -override the default set by ``set_default_csrf_options``. For example: - -.. code-block:: python - - @view_config(route_name='hello', require_csrf=False) - def myview(request): - # ... - -When CSRF checking is active, the token and header used to find the -supplied CSRF token will be ``csrf_token`` and ``X-CSRF-Token``, respectively, -unless otherwise overridden by ``set_default_csrf_options``. The token is -checked against the value in ``request.POST`` which is the submitted form body. -If this value is not present, then the header will be checked. - -In addition to token based CSRF checks, if the request is using HTTPS then 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` or -:class:`pyramid.exceptions.BadCSRFOrigin` 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`` response 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`. - -.. code-block:: python - - @view_config(request_method='POST', check_csrf=True, ...) - def myview(request): - ... - -.. note:: - 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`. -- cgit v1.2.3 From 313c251497f6cdb3e5ca961a8092a2356aa502fc Mon Sep 17 00:00:00 2001 From: Jure Cerjak Date: Mon, 5 Dec 2016 16:06:08 +0100 Subject: Fix tests and documentation in various places, and feedback following review regarding naming of variables and code cleanup. --- docs/api/csrf.rst | 10 ++++++---- docs/api/interfaces.rst | 2 +- docs/narr/security.rst | 34 +++++++++++++++++++++++++--------- docs/narr/sessions.rst | 4 +--- 4 files changed, 33 insertions(+), 17 deletions(-) (limited to 'docs') diff --git a/docs/api/csrf.rst b/docs/api/csrf.rst index 3125bdac9..89fb0c4b2 100644 --- a/docs/api/csrf.rst +++ b/docs/api/csrf.rst @@ -5,14 +5,16 @@ .. automodule:: pyramid.csrf + .. autoclass:: SessionCSRF + :members: + + .. autoclass:: CookieCSRF + :members: + .. autofunction:: get_csrf_token .. autofunction:: new_csrf_token - .. autoclass:: SessionCSRF - :members: - .. autofunction:: check_csrf_origin .. autofunction:: check_csrf_token - diff --git a/docs/api/interfaces.rst b/docs/api/interfaces.rst index 2ca472616..b88209a36 100644 --- a/docs/api/interfaces.rst +++ b/docs/api/interfaces.rst @@ -44,7 +44,7 @@ Other Interfaces .. autointerface:: IRoutePregenerator :members: - .. autointerface:: ICSRF + .. autointerface:: ICSRFPolicy :members: .. autointerface:: ISession diff --git a/docs/narr/security.rst b/docs/narr/security.rst index b4fb3b8a8..6962a0fe3 100644 --- a/docs/narr/security.rst +++ b/docs/narr/security.rst @@ -146,7 +146,7 @@ For example, the following view declaration protects the view named # config is an instance of pyramid.config.Configurator config.add_view('mypackage.views.blog_entry_add_view', - name='add_entry.html', + name='add_entry.html', context='mypackage.resources.Blog', permission='add') @@ -725,7 +725,7 @@ object that implements the following interface: """ Return ``True`` if any of the ``principals`` is allowed the ``permission`` in the current ``context``, else return ``False`` """ - + def principals_allowed_by_permission(self, context, permission): """ Return a set of principal identifiers allowed by the ``permission`` in ``context``. This behavior is optional; if you @@ -777,11 +777,27 @@ 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. +:app:`Pyramid` provides facilities to create and check CSRF tokens. + +By default :app:`Pyramid` comes with a session-based CSRF implementation +:class:`pyramid.csrf.SessionCSRF`. To use it, you must first enable +a :term:`session factory` as described in +:ref:`using_the_default_session_factory` or +:ref:`using_alternate_session_factories`. Alternatively, you can use +a cookie-based implementation :class:`pyramid.csrf.CookieCSRF` which gives +some additional flexibility as it does not require a session for each user. +You can also define your own implementation of +:class:`pyramid.interfaces.ICSRFPolicy` and register it with the +:meth:`pyramid.config.Configurator.set_default_csrf_options` directive. -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`. +For example: + +.. code-block:: python + + from pyramid.config import Configurator + + config = Configurator() + config.set_default_csrf_options(implementation=MyCustomCSRFPolicy()) .. index:: single: csrf.get_csrf_token @@ -866,7 +882,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`. If the token is valid, it +token with :func:`pyramid.csrf.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. @@ -876,7 +892,7 @@ named ``X-CSRF-Token``. .. code-block:: python - from pyramid.session import check_csrf_token + from pyramid.csrf import check_csrf_token def myview(request): # Require CSRF Token @@ -955,4 +971,4 @@ include ``check_csrf=True`` as a view predicate. See 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`. + from calling :func:`pyramid.csrf.check_csrf_token`. diff --git a/docs/narr/sessions.rst b/docs/narr/sessions.rst index 90b5f4585..86fe2a139 100644 --- a/docs/narr/sessions.rst +++ b/docs/narr/sessions.rst @@ -12,8 +12,7 @@ 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. +sessions, and a session-specific feature: flash messages. .. index:: single: session factory (default) @@ -320,4 +319,3 @@ flash storage. .. index:: single: preventing cross-site request forgery attacks single: cross-site request forgery attacks, prevention - -- cgit v1.2.3 From fe0d223ad08bcab724d216b3a877b690c5795f73 Mon Sep 17 00:00:00 2001 From: Matthew Wilkes Date: Fri, 9 Dec 2016 11:25:03 +0100 Subject: Rename implementation to ICSRFStoragePolicy --- docs/api/interfaces.rst | 2 +- docs/narr/security.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'docs') diff --git a/docs/api/interfaces.rst b/docs/api/interfaces.rst index b88209a36..e542a6be0 100644 --- a/docs/api/interfaces.rst +++ b/docs/api/interfaces.rst @@ -44,7 +44,7 @@ Other Interfaces .. autointerface:: IRoutePregenerator :members: - .. autointerface:: ICSRFPolicy + .. autointerface:: ICSRFStoragePolicy :members: .. autointerface:: ISession diff --git a/docs/narr/security.rst b/docs/narr/security.rst index 6962a0fe3..04c236e0b 100644 --- a/docs/narr/security.rst +++ b/docs/narr/security.rst @@ -787,7 +787,7 @@ a :term:`session factory` as described in a cookie-based implementation :class:`pyramid.csrf.CookieCSRF` which gives some additional flexibility as it does not require a session for each user. You can also define your own implementation of -:class:`pyramid.interfaces.ICSRFPolicy` and register it with the +:class:`pyramid.interfaces.ICSRFStoragePolicy` and register it with the :meth:`pyramid.config.Configurator.set_default_csrf_options` directive. For example: -- cgit v1.2.3 From 7c0f098641fda4207ea6fa50c58b289926038697 Mon Sep 17 00:00:00 2001 From: Matthew Wilkes Date: Wed, 12 Apr 2017 11:57:56 +0100 Subject: Use the webob CookieProfile in the Cookie implementation, rename some implemenations based on feedback, split CSRF implementation and option configuration and make the csrf token function exposed as a system default rather than a renderer event. --- docs/api/config.rst | 1 + docs/api/csrf.rst | 4 ++-- docs/narr/extconfig.rst | 1 + docs/narr/security.rst | 8 ++++---- 4 files changed, 8 insertions(+), 6 deletions(-) (limited to 'docs') diff --git a/docs/api/config.rst b/docs/api/config.rst index c76d3d5ff..a785b64ad 100644 --- a/docs/api/config.rst +++ b/docs/api/config.rst @@ -37,6 +37,7 @@ .. automethod:: set_authentication_policy .. automethod:: set_authorization_policy .. automethod:: set_default_csrf_options + .. automethod:: set_csrf_storage_policy .. automethod:: set_default_permission .. automethod:: add_permission diff --git a/docs/api/csrf.rst b/docs/api/csrf.rst index 89fb0c4b2..f890ee660 100644 --- a/docs/api/csrf.rst +++ b/docs/api/csrf.rst @@ -5,10 +5,10 @@ .. automodule:: pyramid.csrf - .. autoclass:: SessionCSRF + .. autoclass:: SessionCSRFStoragePolicy :members: - .. autoclass:: CookieCSRF + .. autoclass:: CookieCSRFStoragePolicy :members: .. autofunction:: get_csrf_token diff --git a/docs/narr/extconfig.rst b/docs/narr/extconfig.rst index 4009ec1dc..c20685cbf 100644 --- a/docs/narr/extconfig.rst +++ b/docs/narr/extconfig.rst @@ -263,6 +263,7 @@ Pre-defined Phases - :meth:`pyramid.config.Configurator.override_asset` - :meth:`pyramid.config.Configurator.set_authorization_policy` - :meth:`pyramid.config.Configurator.set_default_csrf_options` +- :meth:`pyramid.config.Configurator.set_csrf_storage_policy` - :meth:`pyramid.config.Configurator.set_default_permission` - :meth:`pyramid.config.Configurator.set_view_mapper` diff --git a/docs/narr/security.rst b/docs/narr/security.rst index 04c236e0b..e67f7b98c 100644 --- a/docs/narr/security.rst +++ b/docs/narr/security.rst @@ -780,15 +780,15 @@ and then requiring that it be present in all potentially unsafe requests. :app:`Pyramid` provides facilities to create and check CSRF tokens. By default :app:`Pyramid` comes with a session-based CSRF implementation -:class:`pyramid.csrf.SessionCSRF`. To use it, you must first enable +:class:`pyramid.csrf.SessionCSRFStoragePolicy`. To use it, you must first enable a :term:`session factory` as described in :ref:`using_the_default_session_factory` or :ref:`using_alternate_session_factories`. Alternatively, you can use -a cookie-based implementation :class:`pyramid.csrf.CookieCSRF` which gives +a cookie-based implementation :class:`pyramid.csrf.CookieCSRFStoragePolicy` which gives some additional flexibility as it does not require a session for each user. You can also define your own implementation of :class:`pyramid.interfaces.ICSRFStoragePolicy` and register it with the -:meth:`pyramid.config.Configurator.set_default_csrf_options` directive. +:meth:`pyramid.config.Configurator.set_csrf_storage_policy` directive. For example: @@ -797,7 +797,7 @@ For example: from pyramid.config import Configurator config = Configurator() - config.set_default_csrf_options(implementation=MyCustomCSRFPolicy()) + config.set_csrf_storage_policy(MyCustomCSRFPolicy()) .. index:: single: csrf.get_csrf_token -- cgit v1.2.3 From 2ded2fc216b4caaf0d97813413943e0838b6eaaa Mon Sep 17 00:00:00 2001 From: Matthew Wilkes Date: Wed, 26 Apr 2017 15:41:47 +0100 Subject: Apply drafting changes to documentation. --- docs/glossary.rst | 5 +++++ docs/narr/security.rst | 4 ++++ docs/narr/sessions.rst | 4 ---- 3 files changed, 9 insertions(+), 4 deletions(-) (limited to 'docs') diff --git a/docs/glossary.rst b/docs/glossary.rst index 0a46fac3b..0cf96f488 100644 --- a/docs/glossary.rst +++ b/docs/glossary.rst @@ -891,6 +891,11 @@ Glossary :meth:`pyramid.config.Configurator.set_session_factory` for more information. + CSRF storage policy + A utility that implements :class:`pyramid.interfaces.ICSRFStoragePolicy` + which is responsible for allocating CSRF tokens to a user and verifying + that a provided token is acceptable. + Mako `Mako `_ is a template language which refines the familiar ideas of componentized layout and inheritance diff --git a/docs/narr/security.rst b/docs/narr/security.rst index e67f7b98c..86e5c1ef4 100644 --- a/docs/narr/security.rst +++ b/docs/narr/security.rst @@ -766,6 +766,10 @@ a secret across two different subsystems might drop the security of signing to zero. Keys should not be re-used across different contexts where an attacker has the possibility of providing a chosen plaintext. +.. index:: + single: preventing cross-site request forgery attacks + single: cross-site request forgery attacks, prevention + Preventing Cross-Site Request Forgery Attacks --------------------------------------------- diff --git a/docs/narr/sessions.rst b/docs/narr/sessions.rst index 86fe2a139..7e2469d54 100644 --- a/docs/narr/sessions.rst +++ b/docs/narr/sessions.rst @@ -315,7 +315,3 @@ flash storage. ['info message'] >>> request.session.peek_flash() [] - -.. index:: - single: preventing cross-site request forgery attacks - single: cross-site request forgery attacks, prevention -- cgit v1.2.3 From 4b3603ad2f4850605c45e1b7bf4f077584303641 Mon Sep 17 00:00:00 2001 From: Matthew Wilkes Date: Wed, 26 Apr 2017 15:43:18 +0100 Subject: Move CSRF storage policy registration out of PHASE_1 config and simplify tests given previous improvements to CSRF. --- docs/narr/extconfig.rst | 1 - 1 file changed, 1 deletion(-) (limited to 'docs') diff --git a/docs/narr/extconfig.rst b/docs/narr/extconfig.rst index c20685cbf..4009ec1dc 100644 --- a/docs/narr/extconfig.rst +++ b/docs/narr/extconfig.rst @@ -263,7 +263,6 @@ Pre-defined Phases - :meth:`pyramid.config.Configurator.override_asset` - :meth:`pyramid.config.Configurator.set_authorization_policy` - :meth:`pyramid.config.Configurator.set_default_csrf_options` -- :meth:`pyramid.config.Configurator.set_csrf_storage_policy` - :meth:`pyramid.config.Configurator.set_default_permission` - :meth:`pyramid.config.Configurator.set_view_mapper` -- cgit v1.2.3 From 682a9b9df6f42f8261daa077f04b47b65bf00c34 Mon Sep 17 00:00:00 2001 From: Michael Merickel Date: Sat, 29 Apr 2017 01:43:38 -0500 Subject: final cleanup of csrf decoupling in #2854 - Renamed `SessionCSRFStoragePolicy` to `LegacySessionCSRFStoragePolicy` for the version that uses the legacy `ISession.get_csrf_token` and `ISession.new_csrf_token` apis and set that as the default. - Added new `SessionCSRFStoragePolicy` that stores data in the session similar to how the `SessionAuthenticationPolicy` works. - `CookieCSRFStoragePolicy` did not properly return the newly generated token from `get_csrf_token` after calling `new_csrf_token`. It needed to cache the new value since the response callback does not affect the current request. - `CookieCSRFStoragePolicy` was not forwarding the `domain` value to the `CookieProfile` causing that setting to be ignored. - Removed `check_csrf_token` from the `ICSRFStoragePolicy` interface to simplify implementations of storage policies. - Added an introspectable item for the configured storage policy so that it appears on the debugtoolbar. - Added a change note on `ISession` that it no longer required the csrf methods. - Leave deprecated shims in ``pyramid.session`` for ``check_csrf_origin`` and ``check_csrf_token``. --- docs/api/csrf.rst | 3 +++ docs/narr/security.rst | 1 + docs/narr/templates.rst | 4 ++++ 3 files changed, 8 insertions(+) (limited to 'docs') diff --git a/docs/api/csrf.rst b/docs/api/csrf.rst index f890ee660..38501546e 100644 --- a/docs/api/csrf.rst +++ b/docs/api/csrf.rst @@ -5,6 +5,9 @@ .. automodule:: pyramid.csrf + .. autoclass:: LegacySessionCSRFStoragePolicy + :members: + .. autoclass:: SessionCSRFStoragePolicy :members: diff --git a/docs/narr/security.rst b/docs/narr/security.rst index 86e5c1ef4..ddf496b69 100644 --- a/docs/narr/security.rst +++ b/docs/narr/security.rst @@ -824,6 +824,7 @@ If no CSRF token previously existed for this user, then a new token will be set into the session and returned. The newly created token will be opaque and randomized. +.. _get_csrf_token_in_templates: Using the ``get_csrf_token`` global in templates ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/docs/narr/templates.rst b/docs/narr/templates.rst index 6b3b5fcce..4eadbd2f0 100644 --- a/docs/narr/templates.rst +++ b/docs/narr/templates.rst @@ -228,6 +228,10 @@ These values are provided to the template: provided if the template is rendered as the result of a ``renderer=`` argument to the view configuration being used. +``get_csrf_token()`` + A convenience function to access the current CSRF token. See + :ref:`get_csrf_token_in_templates` for more information. + ``renderer_name`` The renderer name used to perform the rendering, e.g., ``mypackage:templates/foo.pt``. -- cgit v1.2.3