Overview

UPDATE! I’m not working with CKAN as much anymore but, to my understanding, this has been addressed in CKAN now. Check the PR for details. You may also want to checkout Queensland Government’s standalone plugin (because they are awesome, most of the below was based on them, and it supports older versions, which based on this CKAN ticket, seems isn’t supported yet).

This is just what I did with the help from the amazing examples at ckanext-security and ckan-ex-qgov.

Hopefully this will help explain how to set this up for others.

This hasn’t been cleaned up (e.g. files could be in a directory, better naming, removing unused/commented code, etc.)

Setup

There are:

  1. 3 files to add to your extension
  2. Edits needed to your plugin.py
  3. Ensure streaming=False is set

Here’s a PR that has it implemented.

3 Files to add

Add these 3 files (orig_anti_csrf.py, anti_csrf.py, and anti_csrf3.py) to your extension (e.g. ckanext-extension_name/ckanext/extension_name/[new_files.py])

  1. orig_anti_csrf.py - which was based on qgoc anti_csrf.py
  2. anti_csrf.py - which was based on security anti_csrf.py
  3. anti_csrf3.py - which was based on security middleware.py

Edits to your plugin.py

# CSRF IMPORTS
import anti_csrf3
import orig_anti_csrf

...

class ExtensionNamePlugin(plugins.SingletonPlugin):
    plugins.implements(plugins.IBlueprint)
    
    ...
    
    # CSRF FOR PYLONS
    def __init__(self, **kwargs):
        '''Setup pylons CSRF.
        '''
        orig_anti_csrf.intercept_csrf()
    


    # IBlueprint
    
    # CSRF FOR FLASK
    def get_blueprint(self):
        '''Return a Flask Blueprint object to be registered by the app.
        Setup Flask CSRF.
        '''

        blueprint = Blueprint(self.name, self.__module__)


        @blueprint.before_app_request
        def before_app_request():
            '''Abort invalid Flask requests based on CSRF token.
            '''
            print(request)
            if not anti_csrf3.is_valid():
                log.debug("Invalid CSRF attempt.")
                extra_vars = {'code': [403], 'content': 'Your form submission could not be validated.'}
                return base.render('error_document_template.html', extra_vars=extra_vars)


        @blueprint.after_app_request
        def after_app_request(response):
            '''Update every Flask response with CSRF token.
            '''
            anti_csrf3.after_request_function(response)
            return response

Set streaming=False

CKAN 2.8.3 has this set, but if you’re older than that, you’ll need to set streaming=False in ckan/config/middleware/pylons_app.py (see PR #4657).