Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unable to verify your data submission #16295

Open
cluwong opened this issue May 18, 2018 · 25 comments
Open

Unable to verify your data submission #16295

cluwong opened this issue May 18, 2018 · 25 comments
Labels

Comments

@cluwong
Copy link

cluwong commented May 18, 2018

What steps will reproduce the problem?

Posting a form or post a link where data-method="POST"

What is the expected result?

For or link is submitted

What do you get instead?

yii\web\BadRequestHttpException: Unable to verify your data submission. in /var/www/my.uhub.biz/vendor/yiisoft/yii2/web/Controller.php:166

Additional info

Not sure if this is related to a previously submitted issue (#15783) or it's new. Since that issue was fixed and the project was updated to V2.0.15.1, I still get this error sometimes. The problem is it's not always reproducible and it's hard to pinpoint the problem.

Some scenerios:

  1. Submit form gets 'Unable to verify your data submission'. But if you reload the form again, the form is submitted.
  2. Sometimes if you get the error, no matter how many times you reload the form you still get the same error.
  3. My dev and prod sites uses the same domain (eg dev.domain.com, prod.domain.com) and uses SSO with cookie set in domain.com. If a form is submitted in one site, then when working on the other site and submit a form (can be same or different form) you get the error, but if you reload the form and submit again, it's either 1) or 2) above.

I have checked data in cookies, sesseions and post and can't spot anything. Let me know if you need more info or what else to check.

Q A
Yii version 2.0.15.1
PHP version 7.0.28-0ubuntu0.16.04.1
Operating system Ubuntu 16.04
@SamMousa
Copy link
Contributor

The csrf token is different for the environments, could you confirm that the csrf cookie is not shared between those domains?

@cluwong
Copy link
Author

cluwong commented May 18, 2018

The csrf cookie is not shared. It's stored in the subdomain.

@SamMousa
Copy link
Contributor

You share sessions right? Could it be that one site is updating the csrf in the session, thereby invalidating the value for the other domain? (I don't remember if csrf uses the session)

@SamMousa
Copy link
Contributor

Hmm, it doesn't by default...

@yii-bot
Copy link

yii-bot commented May 20, 2018

Thanks for posting in our issue tracker.
In order to properly assist you, we need additional information:

  • When does the issue occur?
  • What do you see?
  • What was the expected result?
  • Can you supply us with a stacktrace? (optional)
  • Do you have exact code to reproduce it? Maybe a PHPUnit tests that fails? (optional)

Thanks!

This is an automated comment, triggered by adding the label status:need more info.

@cluwong
Copy link
Author

cluwong commented May 21, 2018

I went back to V2.0.13.3 and tested, I don't see this problem - don't get the random 'Unable to verify your data submission error', and tested switched between posting data in dev and prod site, no problem.

V2.0.14.2 and V2.0.15.1 gets random error. Switching site also gets the error.

The switch site problem can be reproduced: simply display a form with single field, and post the form. Then go to the other site and go to the same form, you get the error, then reload the form and post again, the data is posted (only quite rarely the form can't be posted.)

But for the random problem that happens within the same site, it's very random, sometimes the the form can't be post no matter how many time you reload it, then suddenly it's posted.

I have compare session and cookies for V2.0.15 and V2.0.13 but can't spot what's wrong, unless it's hidden behind the random generated strings.

If more info required, can you point me towards the right direction what to look for?

It seems the previous ticket (#15783) is not entirely fixed. There must be some change to V2.0.14 causing this.

@lubosdz
Copy link
Contributor

lubosdz commented May 22, 2018

Do you know what's the reason of Unable to verify your data submission somehow via debugging?

  • Is it because CSRF token from cookie and submitted HTML form hidden CSRF field differ?
  • Or is CSRF token empty?
  • Do you have Request::enableCsrfCookie = true or false ?

I am experiencing similar issue which occurs right after I logout and instantly try to login back - I also get Unbale to verify submission data. It seems that cookie CSRF token won't get refreshed after user identity reneval, but I have to investigate more to confirm.

@kartik-v
Copy link
Contributor

kartik-v commented Jun 15, 2018

Not sure if it is related... I find that this issue occurs for AJAX Requests on latest jQuery releases like 3.2.x. Probably the $.ajaxPrefilter used by yii.js does not seem to be executed properly - as the X-CSRF-TOKEN does not seem to be passed with the ajax request headers.

I included this JS hack (without any jquery dependency) on my main layout view file to get the ajax requests properly send the X-CSRF-TOKEN and avoid the 400 submission error.

// layouts/main.php

$js = <<< JS
(function() {
    var send = XMLHttpRequest.prototype.send,
        token = document.getElementsByTagName('meta')['csrf-token'].content;
    XMLHttpRequest.prototype.send = function() {
        this.setRequestHeader('X-CSRF-Token', token);
        return send.apply(this, arguments);
    };
}());
JS;
$this->register($js, \yii\web\View::POS_HEAD);

@samdark samdark added the type:bug Bug label Jun 17, 2018
@samdark samdark added this to the 2.0.17 milestone Jun 17, 2018
@samdark
Copy link
Member

samdark commented Jun 17, 2018

Still unable to figure it :(

@cluwong
Copy link
Author

cluwong commented Jul 4, 2018

I think I've found the root of the problem but don't know how to fix it.

Since V2.0.14, csrf token is regenerated in login() function, hence I'm getting this problem since this version.

As mentioned both are in subdomain and uses SSO login. When site A is loaded, the identity cookie for Site B is lost (it's still in $_COOKIE but not in Yii::$app->request->cookies) and vice versa - hence it tries to login again and got a new csrf token, which results in 'Unable to verify your data submission' error when posting the data.

In this particular test scenario, one site is dev and one site is prod hence the configs are the same.

In component section of config:

    'user'      => [        
            'class'             => 'common\components\SsoUser',
            'identityClass'     => 'common\models\User',
            'enableAutoLogin'   => true,
            'enableSession'     => true,
            'identityCookie'    => [
                'name'      => '_identity',
                'httpOnly'  => true,
                'domain'    => '.xxxx.com',
            ],
        ],
        'session'   => [
            'name' => 'session-frontend',
            'cookieParams' => [
                'domain'    => '.xxxx.com',
                'httpOnly'  => true,
            ],
        ],

In SsoUser.php, which extends yii\web\User, I have extended login() and set the default duration to 3600. How come the cookie didn't persist but lost? Is it a bug or something wrong with my config?

@samdark
Copy link
Member

samdark commented Jul 4, 2018

How come the cookie didn't persist but lost?

Session cookie is meant to expire. You need "remember me" in order to keep logged in state. Chrome does weird things with persisting cookies but it's even against RFCs. But that's not your case.

When site A is loaded, the identity cookie for Site B is lost (it's still in $_COOKIE but not in Yii::$app->request->cookies) and vice versa

That means that A uses same cookie name as B and overwrites it. You need to separate these cookies via config.

@cluwong
Copy link
Author

cluwong commented Jul 5, 2018

Isn't setting the duration in login() = remember me?

I have a different Yii2 project under different subdomain, with different cookie names is causing the same issue.

I did a test on my dev and prod site. Display a page which displays the content of Yii::$app->request->cookies. Changed cookie names for crsf, identity and session with suffiix '-dev' for the dev site.

Open chrome. Clear all cookies. Open a tab to the login site to login.
Open a new tab to go to dev site and to the cookies page. On first load, no identity cookie. On subsequent reloads, identity cookie is displayed.
Open another tab to go to prod site, display any pages.
Go back to the dev tab. Reload. Identity cookie is lost. Reload, it's back, and continue be there until I reload the page in prod tab.

Now they have different cookie names. Overwrite shouldn't happen here?

@malsatin
Copy link

malsatin commented Jul 6, 2018

Facing same issue "Не удалось проверить переданные данные."
Althogh, in logs I can see, that both CSRF cookie and CSRF Header has been sent by user

@malsatin
Copy link

malsatin commented Jul 6, 2018

I think that this may happen due to session expiration.
User's session is expired, he relogins on one page, but other page is cached in browser and contains old session data.
Then user have invalid csrf token on cached page

@samdark
Copy link
Member

samdark commented Jul 6, 2018

@cluwong no, it should not. That's super-weird. Am I right that these two website are totally not connected? Separate databases, separate domains (not sub-domains of same domain), separate session storage?

@lubosdz
Copy link
Contributor

lubosdz commented Jul 7, 2018

@samdark Would it not be better to revert the commit which caused these issues (csrf token is regenerated in login() function), until better solution found? Already confirmed by multiple users ...

@samdark
Copy link
Member

samdark commented Jul 7, 2018

No. It fixes security issue.

@cluwong
Copy link
Author

cluwong commented Jul 10, 2018

Sorry my bad. I forgot to run the console command to apply the changes and wasn't paying attention to the cookie names. Identity cookie persists when switching between sites when they have different names.

I thought with SSO, by setting the domain, the cookie is available for all subdomains, hence the same cookie name was used so they have the same identity info shared by the subdomains.

So with cookie names, should all 3 cookies have different names? (Although my tests show that only identity cookie needs to be different to prevent this error). Will there be any adverse hidden effects if csrf and session cookies are the same?

Perhaps docs should also be updated about different cookie names too.

@samdark
Copy link
Member

samdark commented Jul 10, 2018

If you want no interference — yes. They all should have different names. You may want these to have same cookies if your intent is to be authenticated at subdomains automatically.

@DmLapin
Copy link

DmLapin commented Oct 25, 2018

I think that this may happen due to session expiration.
User's session is expired, he relogins on one page, but other page is cached in browser and contains old session data.
Then user have invalid csrf token on cached page

I confirm this type of problem. Typical scenario:

  1. User sets browser option "Restore previous session after startup" (or like this)
  2. Logins to web application, works, opens many tabs with different forms
  3. Close browser
  4. Open it on next day. Browser can refresh tabs on this step.
  5. User see login form, submit it. // <-- csrf regenerated!
  6. Goes to another tab, submit form. For example, "second" login form, if browser refresh tabs after startup (step 4).
  7. Bad Request because of invalid csrf-token.

@lubosdz
Copy link
Contributor

lubosdz commented Oct 25, 2018

@DmLapin It's a side effect of fixing security issue.

@samdark
Copy link
Member

samdark commented Mar 15, 2019

Digging into it with @machour.

@samdark
Copy link
Member

samdark commented Mar 15, 2019

Were able to reproduce his case as a user.

@samdark
Copy link
Member

samdark commented Mar 15, 2019

It's XMLHttpRequest on a particular page.

@machour
Copy link
Member

machour commented Mar 15, 2019

Welp, in my case, I was using PageCache which was caching a csrf value..
Oddly enough, I never experienced the problem on my end, with pages not cached by me.
Disabled the cache and waiting for more logs to confirm that I'm a 🤡

@samdark samdark removed this from the 2.0.17 milestone Mar 20, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

9 participants