I was looking at the ``csrfmiddleware`` package by Luke Plant and David Turner for a middleware solution the implements CRSF-protection across my site.
Some short-comings of this middleware for a who-app: - Relies on beaker to provide undiscoverable authorization; we already have the who cookie value which has same semantics. - Does not provide functionality to authorize Ajax-requests. Based on the attached doc, I'm going to implement a repoze.who-based middleware which overcomes the above. Additionally, I'm going to use ``repoze.xmliter`` to allow multiple middlewares to process XML without reparsing. Feedback welcome. \malthe
Overview ======== This package provides a WSGI middleware which relies on ``repoze.who`` cookie authentiation to implement CSRF form protection [1]. Strategy -------- In order to ensure that POST requests (which may be assumed to have side-effects) stem from authorized forms, requests must include a parameter that can only be known in theory by the authenticated user and the website. One such parameter is the ``repoze.who`` authentication cookie value, which is a digest based on the authentication credentials. The middleware creates a token based on a configurable seed and the cookie value. Only requests that can produce this token are allowed (the "403 Forbidden" status is returned otherwise). It's imperative that the token is not discoverable by third party. Extracting the validation token ------------------------------- Before looking at the POST data, the middleware consults the "X-Form-Protect" request header. If not found, the POST data is examined for a "__protect" key. Form authentication ------------------- The middleware intercepts HTML content and adds CSRF form authentication to all forms appearing on the page (by adding a hidden input field with the name "__protect"). Once verified, the parameter is stripped from the request before it reaches the WSGI application. Identity metadata ----------------- A ``repoze.who`` metadata provider is available and adds a "form_protection_token" entry to the identity object. A utility-method is available to retrieve the token from the identity. >>> from repoze.formprotect import get_form_protection_token >>> token = get_form_protection_token(identity) Note that this metadata is only required if form protection needs to be handled manually. Ajax support ------------ Using a JavaScript library such as jQuery, it's possible to submit Ajax-requests that use the POST request method, without the use of a form. In order to authenticate such requests, either a valid form protection parameter or request header must be submitted (see above). To enable for all ajax-requests, bind an event listener for the jQuery "ajaxSend" event, which adds the form validation request header [2]. jQuery.bind("ajaxSend", function(event, request, settings) { request.setRequestHeader("X-Form-Protect", %token) }); References ---------- [1] http://en.wikipedia.org/wiki/Cross-site_request_forgery [2] http://www.w3.org/TR/XMLHttpRequest/#xmlhttprequest Author ------ Malthe Borch <mbo...@gmail.com>
_______________________________________________ Repoze-dev mailing list Repoze-dev@lists.repoze.org http://lists.repoze.org/listinfo/repoze-dev