In my Yii2 application there is a form that users submit. The site has CSRF validation turned but if the user has cookies disabled, an error is thrown. What is the best way to handle a situation like this? I don't really want to disable CSRF validation to be sure that the form is only submitted from my site. There is no login process involved. It is simply a one-time use situation for the user. Thanks.
2 Answers
One more thing you can try is you can check whether a user has cookies enabled or not? Now it is your preference, whether you want to check this on the starting of your website or when a user will fill a form.
As I have seen on many websites, that they ask us to enable the cookies to proceed. You can check the following link to check whether the cookie is enabled or disabled. https://www.dummies.com/programming/php/check-whether-php-cookies-are-enabled/
If you are more of a JavaScript person, you can also check the following link.
I would suggest you show an alert on the opening of the Form Page that cookies are not enabled.
Thank You!! I hope it helps.
You can force your application to store the CSRF token in session instead of cookie by setting enableCsrfCookie
property of yii\web\Request
component to false
.
You can do that in your web.php config:
$config = [
// ...
'components' => [
'request' => [
'enableCsrfCookie' => false,
],
// ...
],
// ...
];
But this will cause app to start the session for every request. Also sessions by default uses cookies for storing session id so in the end it might not be much improvement if you want to avoid using any cookies.
You can also extend the yii\web\Request
and override its methods generateCsrfToken()
and loadCsrfToken()
to use different storage for token. But rembeber that by default there is no way to recognize which requests came from same session. You have to save some sort of sessionId in client and then send it back to server in order to be able to pair the request that submits form with CSRF token and the request that generated the CSRF token.
Another posibility is to turn off the standard CSRF protection and implement your own protection for form. For example you can have some secret key stored in app config.
Then when generating form, you will use yii\base\Security::hashData()
method to add the timestamp to your form:
$timestamp = Yii::$app->security->hashData(time(), $yourSecurityKey);
Html::hiddenInput('my-csrf', $timestamp);
Then you can validate it in your controller action:
$timestamp = Yii::$app->security->validateData(
Yii::$app->request->post('my-csrf'),
$yourSecurityKey
);
if ($timestamp === false || $timestamp < (time() - $timeLimitInSeconds)) {
//Do something when CSRF validation is not valid (for example throw bad request exception)
}
// continue form processing
Warning: the protection in example is not as safe as the standard CSRF protection because someone can request the form from your application to get the generated token than use the token from it for limited time in the form submitted from their site.