ChrisChris is quite correctcorrect – CSRF does not work with GET requests (see this answer by Brad Bellthis answer by Brad Bell for an explanation). I'm posting my workaround as an additional answer in case anyone else ever needs to have CSRF validation for GET requests working.
To get around the issue, I set up a custom config key in /config/general.php
called tokenGetParam
. This is because you can't use the native tokenParam
config setting for GET requests – Craft's CSRF validation will hijack the request and throw a 404 exception as soon as it sees the token in the URL, if it's a GET request. Obviously, the tokenGetParam
setting needs to have a different value than tokenParam
, as well – I went with "t"
. A custom config value isn't really necessary – you can just hard code along the way – but it's helpful to have if you ever need to change it in a pinch.
Of course, not being able to use the native tokenParam
config value also means that you can't use the various built-in methods for dealing with CSRF tokens, e.g. $this->requireToken()
for the Controller or UrlHelper::getUrlWithToken()
, etc.
In my case, my needs were very simple. I simply needed to include a valid CSRF token in a GET variable tokenGetParam
(i.e. "t"
) in the callback URL to the external API, so that whenever the external API calls that URL after authenticating stuff on their end, I'd be able to accept or reject the request based on the contents of the "t"
query parameter.
Here's how I generate the callback URL before calling the external webservice:
$callbackUrl = UrlHelper::getSiteUrl('actions/myplugin/mycontroller/authCallback').'?'.craft()->config->get('tokenGetParam').'='.craft()->request->getCsrfToken();
When the actionAuthCallback
is called, I validate the token like this:
$requestToken = craft()->request->getQuery(craft()->config->get('tokenGetParam'));
if ($requestToken !== craft()->request->getCsrfToken()) {
// Token is not valid
throw new HttpException(400);
}
Works.