Magento 2.3 – How to Bypass CSRF Validation for Payment Gateway Webhook

csrfdependency-injectionmagento2.3magento2.3.0payment-gateway

I am trying to integrate CC avenue payment method with Magento 2.3 however once payment is processed, user is navigated back to website with error "Invalid Form Key. Please refresh the page."

Upon debugging, I found that CSRF validation fails when CC avenue posts response on return URL. While I also tried solution mentioned on the post : Magento 2.3 upgrade breaks HTTP POST requests to custom module endpoint, still the error persists. Possible reason could be that interface mentioned in above post is not being used rather it gets into Magento\Framework\App\Request\CsrfValidator class which implements Magento\Framework\App\Request\ValidatorInterface.

Possible workaround is to override class – Magento\Framework\App\Request\CsrfValidator as follows:

public function validate(
        RequestInterface $request,
        ActionInterface $action
    ): void {
        try {
            $areaCode = $this->appState->getAreaCode();
        } catch (LocalizedException $exception) {
            $areaCode = null;
        }
        if ($request instanceof HttpRequest
            && in_array(
                $areaCode,
                [Area::AREA_FRONTEND, Area::AREA_ADMINHTML],
                true
            )
        ) {
            //Custom code
            if ($request->getRequestUri() == 'custom/uri')
            {
                $valid = true;
            }
            else {
                $valid = $this->validateRequest($request, $action);
            }
            if (!$valid) {
                    throw $this->createException($request, $action);
                }
            }
    }

Question is – how do I override this class? I tried writing dependency injection but did not work!

Best Answer

You can add a formKey to your request.

Magento checks in the validateRequest function at Magento\Framework\App\Request\CsrfValidator if the request is intance of CsrfAwareActionInterface, not a post request, ajax or has a valide formKey:

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;
    }

You can inject Magento\Framework\Data\Form\FormKey and add to your request, something like this:

 $requestUrl .= '?form_key=' . $this->formKey->getFormKey();
Related Topic