Skip to main content
replaced http://craftcms.stackexchange.com/ with https://craftcms.stackexchange.com/
Source Link

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.

Chris is quite correct – CSRF does not work with GET requests (see this 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.

Chris is quite correct – CSRF does not work with GET requests (see this 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.

Source Link

Chris is quite correct – CSRF does not work with GET requests (see this 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.