Magento2: Custom ajax calls with type POST reset customer data on checkout (Magento 2.2.x)

Created on 22 Nov 2017  Â·  20Comments  Â·  Source: magento/magento2

Hi guys,

This issue is created because you've just closed this one - https://github.com/magento/magento2/issues/12312

But the issue can be reproduced not only me. We've created a few env. with magento 2.2.1 and reproduced this bug.
magento_version

added ajax (type: POST) call to vendor/magento/module-checkout/view/frontend/templates/onepage.phtml

onepage

created controller

test_controller

fill address on the first step of checkout and go the second page

checkout

press F5

checkout_after_f5

but any errors in console or in the log, also ajax got 200 response

checkout_after_f5_console

I understand that this is not typical issue. We had to update project from 2.1.9 to 2.2 to fix some critical issue with disappearing products during reindex. But now we stuck with this issue. Because a about 4 important extension uses ajax on the checkout.

I think this is some security issue, because AJAX with GET type works fine instead of AJAX with POST.

Recently we got a patch for popup extension. They also reproduced this issue and changed POST calls with GET.

Thanks,
Alena Tsareva

Clear Description Format is not valid needs update Reproduced on 2.2.x Reproduced on 2.3.x

Most helpful comment

You are also able to reproduce this issue by adding products to cart (effectively another POST Request) and refreshing the checkout page afterwards (without navigating to cart in between!).

Any POST request will lead to the data being lost.
The problem here seems to be Magento\Framework\App\PageCache\Version::process.
It is called by Magento\PageCache\Model\App\FrontController\BuiltinPlugin::aroundDispatch, on almost every request.

    /**
     * Handle private content version cookie
     * Set cookie if it is not set.
     * Increment version on post requests.
     * In all other cases do nothing.
     *
     * @return void
     */
    public function process()
    {
        if ($this->request->isPost()) {
            $publicCookieMetadata = $this->cookieMetadataFactory->createPublicCookieMetadata()
                ->setDuration(self::COOKIE_PERIOD)
                ->setPath('/')
                ->setSecure($this->request->isSecure())
                ->setHttpOnly(false);
            $this->cookieManager->setPublicCookie(self::COOKIE_NAME, $this->generateValue(), $publicCookieMetadata);
        }
    }

I'm unsure if checking for a POST request alone is sufficient to decide if the data should be invalidated at this point.

From what we have tested, not calling the process function at all seemed to fix the issue without creating any visible drawbacks.

All 20 comments

@atsareva, thank you for your report.
We've created internal ticket(s) MAGETWO-84309 to track progress on the issue.

Hello team , any update on this , as i m also facing this issue

You are also able to reproduce this issue by adding products to cart (effectively another POST Request) and refreshing the checkout page afterwards (without navigating to cart in between!).

Any POST request will lead to the data being lost.
The problem here seems to be Magento\Framework\App\PageCache\Version::process.
It is called by Magento\PageCache\Model\App\FrontController\BuiltinPlugin::aroundDispatch, on almost every request.

    /**
     * Handle private content version cookie
     * Set cookie if it is not set.
     * Increment version on post requests.
     * In all other cases do nothing.
     *
     * @return void
     */
    public function process()
    {
        if ($this->request->isPost()) {
            $publicCookieMetadata = $this->cookieMetadataFactory->createPublicCookieMetadata()
                ->setDuration(self::COOKIE_PERIOD)
                ->setPath('/')
                ->setSecure($this->request->isSecure())
                ->setHttpOnly(false);
            $this->cookieManager->setPublicCookie(self::COOKIE_NAME, $this->generateValue(), $publicCookieMetadata);
        }
    }

I'm unsure if checking for a POST request alone is sufficient to decide if the data should be invalidated at this point.

From what we have tested, not calling the process function at all seemed to fix the issue without creating any visible drawbacks.

I can also confirm issues related to AJAX POST calls. After installing extension on clean Magento 2.2.1 that had js with ajax (POST) call (for example mailchimp 1.0.24 / bscommerce popup 1.0.1) we had issues with notifications. For example sending newsletter form (placed in the footer) resulted in showing msg for a few second/no messages. Updating mailchimp to 1.0.29 fixed issues (waiting for update for bscommerce popup).

Confirming this issue on 2.2.5, its keeping customers from completing the checkout.

Preconditions

PHP 7.0.30-0ubuntu0.16.04.1
MySQL 5.7.23
Magento CE 2.2.5 – with min. 1 product, 1 shipping method, 1 payment method

Steps to Reproduce

  1. Put product into cart
  2. Go to checkout
  3. Fill out shipping address
  4. Continue to billing step
  5. Select a payment method
  6. Open another browser tab with the same website/store/shop
  7. In the second browser tab, add a product to cart
  8. Go to first browser tab and refresh the page

Actual Result

Checkout lost the shipping address; is not showing the shipping address
(In my case zip code and country will be taken from the stores address)

Expected Result

Checkout keeps the shipping address like before the add to cart was done

Some caches disabled while I was testing

"full_page" and "block_html" caches disabled, but it makes no difference if these are enabled or diabled

I can reproduce this simply by refreshing the checkout / payment page on 2.2.3.
This is a major issue. Any progress?

I can also confirm issues related to AJAX POST calls. After installing extension on clean Magento 2.2.1 that had js with ajax (POST) call (for example mailchimp 1.0.24 / bscommerce popup 1.0.1) we had issues with notifications. For example sending newsletter form (placed in the footer) resulted in showing msg for a few second/no messages. Updating mailchimp to 1.0.29 fixed issues (waiting for update for bscommerce popup).

This might have to do with the following CSRF protection function:

/**
     * @param HttpRequest $request
     * @param ActionInterface  $action
     *
     * @return bool
     */
    private function validateRequest(
        HttpRequest $request,
        ActionInterface $action
    ): bool {
        $valid = null;
        if ($action instanceof CsrfAwareActionInterface) {
            $valid = $action->validateForCsrf($request);
        }
        if ($valid === null) {
            $valid = !$request->isPost()
                || $request->isAjax()
                || $this->formKeyValidator->validate($request);
        }

        return $valid;
    }

A request is marked as invalid if the request \:

  1. Comes from an external domain
  2. Is a POST request
  3. Doesn't contain the parameter "isAjax"

This didn't seem to be the case in earlier Magento 2 versions and it actually breaks some payment gateways' webhooks as well. For example Mollie (a Dutch payment provider) makes a POST request to a webhook URL, but this webhook URL doesn't include the "isAjax" parameter.

any Update on this? I can reproduce on 2.2.7

So Magento also does POST requests in checkout, but they are all done using REST which doesn't invalidate. (example: guest-carts/totals-information).

I guess we should be using REST in checkout instead of controllers or only use controllers for GET requests.

Fix mentioned here by @ManiMaran A:
https://magento.stackexchange.com/questions/148454/shipping-address-missing-on-payment-page-refresh
Worked perfectly for me.
Although we are in need of a best solution.

Is there any update on this issue? Reproduced on 2.3.0

The post request updates the cookie private_content_version and in vendor\magento\module-customer\view\frontend\web\js\controller-data.js that is compared on line } else if (localPrivateContent !== privateContent) { and forces the localStorage to clear.

What would be the knock on / security effect it as a resolution, simply put
$.cookieStorage.set(privateContentVersion, privateContent);
before the line
needVersion = 'need_version',

hence negation the check , until a better logic in Magento\Framework\App\PageCache\Version::process.
comes along?

@magento-engcom-team We are seeing this on 2.2.9 any update on this issue?

@magento give me 2.4-develop instance

Hi @krzksz. Thank you for your request. I'm working on Magento 2.4-develop instance for you

@magento give me 2.4-develop instance

Hi @krzksz. Thank you for your request. I'm working on Magento 2.4-develop instance for you

Hi @engcom-Delta. Thank you for working on this issue.
Looks like this issue is already verified and confirmed. But if you want to validate it one more time, please, go though the following instruction:

  • [ ] 1. Add/Edit Component: XXXXX label(s) to the ticket, indicating the components it may be related to.
  • [ ] 2. Verify that the issue is reproducible on 2.4-develop branch

    Details- Add the comment @magento give me 2.4-develop instance to deploy test instance on Magento infrastructure.
    - If the issue is reproducible on 2.4-develop branch, please, add the label Reproduced on 2.4.x.
    - If the issue is not reproducible, add your comment that issue is not reproducible and close the issue and _stop verification process here_!

  • [ ] 3. If the issue is not relevant or is not reproducible any more, feel free to close it.


@WinstonN @J-SM @serucee Unfortunately, I am not able to reproduce issue on 2.4-develop

Case 1: https://github.com/magento/magento2/issues/12390#issue-275994177
:heavy_check_mark: Result:
image

Case 2: https://github.com/magento/magento2/issues/12390#issuecomment-414638348
:heavy_check_mark: Result:
#12390issue

Are you still facing this issue on the latest 2.4-develop?

@WinstonN @J-SM @serucee , we are closing this issue due to inactivity. If you'd like to update it, please reopen the issue.

Was this page helpful?
0 / 5 - 0 ratings