Yii 1.1.17: CSRF token validation fails with POST via Angular Controller
<p>I have an Yii application in which I have a link (outside a form) triggering an Angular controller posting some data. The problem is that Yii does not validate the CSRF token when that happens.</p>

<p>My raw url looks like this:</p>

<pre><code>&lt;a id="yt1" href="#" ng-click="markAllAsRead(23, '1eb4e3ac755e22939a0fc8d5ea0e9bacb453319a')" title="Read All" tooltips-size="small" tooltips="1" class="notification-tool ng-isolate-scope"&gt;&lt;i class="fa fa-eye"&gt;&lt;/i&gt;&lt;/a&gt;
</code></pre>

<p>My Angular controller calls an angular service which looks like this:</p>

<pre><code>notificationsService.markAllAsRead = function (user_id, csrf) {
        var dataObject = {
            user_id: user_id,
            YII_CSRF_TOKEN: csrf
        };

        $http.post("/api/notifications/readAll", dataObject).success(function (data) {
            return data;
        });
    };
</code></pre>

<p>The POST request looks liek this:
<a href="https://i.stack.imgur.com/CTaSF.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/CTaSF.png" alt="POST request via ajax"></a></p>

<p>If I disable the CSRF validation the call succeeds. </p>

<p>Any ideas?</p>

<p>Thanks!</p>

<p><strong>COMPLETE ANSWER:</strong></p>

<p>After some investigation I noticed that the <code>$_POST</code> (also Yii's <code>$request-&gt;getPost()</code>) was actually empty, even though Angular was posting data. Reading <a href="https://stackoverflow.com/a/15485690/1475898">this answer</a> on stackoverflow it seems that it actually is an issue that has to do with Angular JS and its' default behavior to post as <code>apllication/json</code> (well, maybe not exactly an issue). As suggested by the marked answer to this question and based on the suggestion on the linked answer, I ended up overriding the <code>CHttpRequest</code> class from Yii as follows:</p>

<pre><code>class AppRequest extends CHttpRequest
{
    public function validateCsrfToken($event)
    {
        if ($this-&gt;getIsPostRequest() ||
            $this-&gt;getIsPutRequest() ||
            $this-&gt;getIsPatchRequest() ||
            $this-&gt;getIsDeleteRequest()
        ) {
            $cookies = $this-&gt;getCookies();

            $method = $this-&gt;getRequestType();
            switch ($method) {
                case 'POST':
                    if (empty($this-&gt;getPost($this-&gt;csrfTokenName))) {
                        $input = json_decode(file_get_contents('php://input'), true);;
                        $userToken = $input[$this-&gt;csrfTokenName];
                    } else {
                        $userToken = $this-&gt;getPost($this-&gt;csrfTokenName);
                    }
                    break;
                case 'PUT':
                    if (empty($this-&gt;getPut($this-&gt;csrfTokenName))) {
                        $input = json_decode(file_get_contents('php://input'), true);;
                        $userToken = $input[$this-&gt;csrfTokenName];
                    } else {
                        $userToken = $this-&gt;getPut($this-&gt;csrfTokenName);
                    }
                    break;
                case 'PATCH':
                    if (empty($this-&gt;getPatch($this-&gt;csrfTokenName))) {
                        $input = json_decode(file_get_contents('php://input'), true);;
                        $userToken = $input[$this-&gt;csrfTokenName];
                    } else {
                        $userToken = $this-&gt;getPatch($this-&gt;csrfTokenName);
                    }
                    break;
                case 'DELETE':
                    if (empty($this-&gt;getDelete($this-&gt;csrfTokenName))) {
                        $input = json_decode(file_get_contents('php://input'), true);;
                        $userToken = $input[$this-&gt;csrfTokenName];
                    } else {
                        $userToken = $this-&gt;getDelete($this-&gt;csrfTokenName);
                    }
                    break;
            }

            if (!empty($userToken) &amp;&amp; $cookies-&gt;contains($this-&gt;csrfTokenName)) {
                $cookieToken = $cookies-&gt;itemAt($this-&gt;csrfTokenName)-&gt;value;
                $valid = $cookieToken === $userToken;
            } else
                $valid = false;
            if (!$valid)
                throw new CHttpException(400, Yii::t('yii', 'The CSRF token could not be verified.'));
        }
    }
}
</code></pre>