Magento2: 2.3.0 - Custom Payment Method - Invalid Form Key. Please refresh the page.

Created on 11 Dec 2018  路  18Comments  路  Source: magento/magento2

Summary (*)

I have a custom payment method that uses the cc-form to take debit/credit card payments.

After the user has entered their card details, they are re-directed to my controller with a hidden form, then to the 3dsecure page. After 3dsecure, they are re-directed to the same controller and various logic is checked.

After the logic is valid, they are re-directed to the checkout success page.

This was working with Magento 2.2, but in 2.3.0 this is not working.

After placing order, I am re-directed to 3dsecure as normal, but on returning from 3dsecure, I am re-directed to the home page with "Invalid Form Key. Please refresh the page."

Examples (*)

Has anything changed in terms of the cc-form to do with form validation or payment method examples? Do I need to add anything to my templates, JS or controller?

Proposed solution

I have no idea!

Format is valid

Most helpful comment

OK I found the "bodge" that other core payment methods are using.

Controller must implement CsrfAwareActionInterface

Additional methods required in controller:

   /**
     * @inheritDoc
     */
    public function createCsrfValidationException(
        RequestInterface $request
    ): ?InvalidRequestException {
        return null;
    }

    /**
     * @inheritDoc
     */
    public function validateForCsrf(RequestInterface $request): ?bool
    {
        return true;
    }

All 18 comments

Hi @craigcarnell. Thank you for your report.
To help us process this issue please make sure that you provided the following information:

  • [ ] Summary of the issue
  • [ ] Information on your environment
  • [ ] Steps to reproduce
  • [ ] Expected and actual results

Please make sure that the issue is reproducible on the vanilla Magento instance following Steps to reproduce. To deploy vanilla Magento instance on our environment, please, add a comment to the issue:

@magento-engcom-team give me $VERSION instance

where $VERSION is version tags (starting from 2.2.0+) or develop branches (for example: 2.3-develop).
For more details, please, review the Magento Contributor Assistant documentation.

@craigcarnell do you confirm that you was able to reproduce the issue on vanilla Magento instance following steps to reproduce?

  • [ ] yes
  • [ ] no

@craigcarnell you need either to provide a minimalistic code which reproduces a problem or do a deeper debug on your side to locate core code which seems not implemented correctly.

Also, I believe some builtin payment methods are involving 3DSecure as well, you can try to play with them to see how their implementation differs from your one.

Hi Team, @orlangur @magento-engcom-team
I am facing the same issue after upgrade to Magento 2.3. I am using the Moneris Payment Method provided by collinsharper which was working fine on Magento 2.2.

Steps to reproduce-
1- After choose Moneris Payment method it redirect to Moneris Hosted payment website
2- Done transaction and it redirect to magento store with url in browser (https://magentostore/moneriscc/api/hosted)
3- After redirect to store home page, it gives error "Invalid Form Key, Please refresh the page"

Expected Result- It calls Module success method and success page.

Debug Info -
After debug I found, the POST Response array returned by Moneris reached at index.php but after that it fails to send data to module controller method which results the error "Invalid form Key, Please refresh the page".

Hope this helps to debug the issue.

@pravinagham, this GitHub repository is intended for bug reports in core Magento modules, in case of problems with some third party extensions/themes their respective vendors should be contacted instead.

Hi @engcom-backlog-nazar. Thank you for working on this issue.
In order to make sure that issue has enough information and ready for development, please read and check the following instruction: :point_down:

  • [x] 1. Verify that issue has all the required information. (Preconditions, Steps to reproduce, Expected result, Actual result).
    DetailsIf the issue has a valid description, the label Issue: Format is valid will be added to the issue automatically. Please, edit issue description if needed, until label Issue: Format is valid appears.
  • [x] 2. Verify that issue has a meaningful description and provides enough information to reproduce the issue. If the report is valid, add Issue: Clear Description label to the issue by yourself.

  • [ ] 3. Add Component: XXXXX label(s) to the ticket, indicating the components it may be related to.

  • [ ] 4. Verify that the issue is reproducible on 2.3-develop branch

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

  • [ ] 5. Verify that the issue is reproducible on 2.2-develop branch.

    Details- Add the comment @magento-engcom-team give me 2.2-develop instance to deploy test instance on Magento infrastructure.
    - If the issue is reproducible on 2.2-develop branch, please add the label Reproduced on 2.2.x

  • [ ] 6. Add label Issue: Confirmed once verification is complete.

  • [ ] 7. Make sure that automatic system confirms that report has been added to the backlog.

Hi @craigcarnell thank you for you report,
The GitHub issue tracker is intended for Magento Core technical issues only.
Please refer to the Community Forums or the Magento Stack Exchange site for advice or general discussion about this issue.

@orlangur This appears to be a backwards incompatible change, not noted anywhere in the release notes. I will try and do some digging.

@pravinagham have you contacted the original author? interested in what the fix is.

OK I found the "bodge" that other core payment methods are using.

Controller must implement CsrfAwareActionInterface

Additional methods required in controller:

   /**
     * @inheritDoc
     */
    public function createCsrfValidationException(
        RequestInterface $request
    ): ?InvalidRequestException {
        return null;
    }

    /**
     * @inheritDoc
     */
    public function validateForCsrf(RequestInterface $request): ?bool
    {
        return true;
    }

@craigcarnell,

This appears to be a backwards incompatible change, not noted anywhere in the release notes. I will try and do some digging.

Not really. Before using any extension with 2.3 it should be thoroughly tested by its vendor first.

@pravinagham, this GitHub repository is intended for bug reports in core Magento modules, in case of problems with some third party extensions/themes their respective vendors should be contacted instead.

Had also mailed them but not got any feedback from them. Thanks

Ok, we have workaround for this, but is it safe? @orlangur @magento-engcom-team ?
I understand, that we disable csrf validation, so it always passes, but how should we protect in such case? How to work for example with some payment provider? For example we should build it some custom hash on server side send it with our request to external site and receive it back with coming-back request?

Thank you for the direction @craigcarnell . I found the usage of the interface application in 2.3.3 of PayPal's Payflow Silent Post controller . Applied the same interface and payment module works as expected.

@dchaykas It works, but it seems workaround not a custom validation for csrf.

@orlangur @magento-engcom-team

Ok, we have workaround for this, but is it safe? @orlangur @magento-engcom-team ?
I understand, that we disable csrf validation, so it always passes, but how should we protect in such case? How to work for example with some payment provider? For example we should build it some custom hash on server side send it with our request to external site and receive it back with coming-back request?

@magento-engcom-team this is still happening on M2.3.5-p1

Is it or not safe to use this workaround to skip csrf validation?

Bypass CSRF Validation work and solve the original issue but another issue we are facing is, if we add code to bypass CSRF validation then it clears customer session and customer logged out automatically when we come back from the hosted payment page.

Does anyone face a similar issue? if yes then it will be much appropriated if you shared a possible solution with us.

@Vishrootways can you provide a code reference where bypassing CSRF clears customer session? One of my projects was faced with customer session being cleared and I know we've bypassed CSRF because there's custom validation implemented.

@dchaykas Below is that file in which we are bypassing CSRF and our payment method sending POST data.
NOTE: If our payment method sends GET data instead of POST then the customer session is not clearing so the issue is only with POST data and might be we only have to bypass CSRF if POST data is sending.

Also, you said that you are getting the same issue, cloud you please let us know how did you solve it?

namespace Vendor\Module\Controller\HostedPayment;

use Magento\Framework\App\Action\Action;
use Magento\Framework\App\Action\Context;
use Magento\Sales\Model\Order;
use Magento\Framework\App\Request\InvalidRequestException;
use Magento\Framework\App\RequestInterface;
use Magento\Framework\Controller\ResultFactory;
use Magento\Framework\Controller\ResultInterface;
use Magento\Sales\Api\OrderRepositoryInterface;

class Approved extends Action implements \Magento\Framework\App\CsrfAwareActionInterface
{
    /**
     * @var \Magento\Checkout\Model\Session
     */
    protected $checkoutSession;

    /**
     *  @param Context $context
     *  @param \Magento\Checkout\Model\Session $checkoutSession
     */
    public function __construct(
        Context $context,
        \Magento\Checkout\Model\Session $checkoutSession
    ) {
        parent::__construct($context);
        $this->_checkoutSession = $checkoutSession;
    }

    /**
     * @return ResultInterface
     * @throws \Exception
     */
    public function execute()
    {
        $responseData = $this->getRequest()->getParams();

        /*
            Here few codes to load order and add few details to payment.
        */

        $this->_checkoutSession->setLastOrderId($order->getId());
        $this->_checkoutSession->setLastRealOrderId($order->getIncrementId());
        $this->_checkoutSession->setLastQuoteId($order->getQuoteId());
        $this->_checkoutSession->setLastSuccessQuoteId($order->getQuoteId());

        $this->_redirect('checkout/onepage/success');
    }

    /**
     * @param RequestInterface $request
     *
     * @return bool|null
     */
    public function validateForCsrf(RequestInterface $request): ?bool
    {
        return true;
    }

    /**
     * @param RequestInterface $request
     *
     * @return InvalidRequestException|null
     */
    public function createCsrfValidationException(RequestInterface $request): ?InvalidRequestException
    {
        return null;
    }
}
Was this page helpful?
0 / 5 - 0 ratings