Csrf Validation Problem For Requests With Content-Type: Application/json

I am developing TinyMCE extension for yii http://www.yiiframework.com/extension/newtinymce

TinyMCE has a plugin for spellchecking, this plugin relies on json-rpc service on server side (https://github.com/tinymce/tinymce_spellchecker_php).

I have written an action for yii which will handle all requests for this service: TinyMceSpellcheckerAction.php

But when csrf validation is enabled all requests to this service will be rejected because requests have content-type is "application/json" and even if csrf token will be passed within request - it could not be validated by Yii.

I have following suggestions in order to solve this problem:

  1. Skip validation, for all requests with content-type application/json in CHttpRequest

  2. Move csrf validation, from CHttpRequest into filter in controllers

  3. Separate entry point for such requests

So my question is - what is the best way to handle such requests with Yii?

About first suggestion, corespounding request class below:




class HttpRequest extends CHttpRequest

{

    public function validateCsrfToken($event)

    {

        $contentType = isset($_SERVER["CONTENT_TYPE"]) ? $_SERVER["CONTENT_TYPE"] : null;

        if ($contentType !== 'application/json')

            parent::validateCsrfToken($event);

    }

}



it is not about content type, but rather how is the request prepared. CSRF works for every POST request by default. Problem is with AJAX POST request which should have CSRF token, but they don’t (you should add it by yourself). If you can’t add CSRF token to some AJAX requests you should consider disabling CSRF in some cases. I do not know if disabling it by content-type is good solution, because it is insecure as it is too generic. In applications I am familiar with we rather created custom HttpRequest with whitelist for some controller/action entries so you could disable CSRF just for single action:




class HttpRequest extends CHttpRequest {


    public $dont_validate_csrf_routes = array();


   public function validateCsrfToken($event) {

        if( !in_array(Yii::app()->request->url, $this->dont_validate_csrf_routes) ) {

            parent::validateCsrfToken($event);

        }

    }

}