9

After upgrading to Magento 2.4.3 Community Edition I am getting Invalid security or form key. Please refresh the page. on the admin dashboard site after logging in.

Reloading the page makes the error disappear.

Things I tried so far without any luck:

  • increasing max_input_vars
  • making sure file permissions are correct
  • testing setting max_session_size_admin to 0 and 512000
  • disabled all third party modules
  • recompiling, setup:upgrade, removing static, generated files and so on

I don't know if this is a Magento 2.4.3 bug or faulty server configuration or if something in my database is broken.

2

6 Answers 6

19

This is a new bug when using another URL than admin.

You need to make changes to the following file:

\vendor\magento\module-backend\App\Action\Plugin\Authentication.php

See the code changes over at https://github.com/magento/magento2/issues/33749#issuecomment-908145941

This issue will be resolved in 2.4.4.

2
  • This file doesn't even exist in 2.4.3-p1 Any tipes? File: \vendor\magento\module-backend\App\Action\Plugin\Authentication.php Mar 15 at 6:51
  • Yes , you saved my day Apr 6 at 7:17
8

For those who use composer to patch to save you all some time

composer require cweagans/composer-patches

./patches/composer/invalid.key.patch

diff --git a/vendor/magento/module-backend/App/Action/Plugin/Authentication.php b/vendor/magento/module-backend/App/Action/Plugin/Authentication.php
index 8227966..cc32c36 100644
--- a/vendor/magento/module-backend/App/Action/Plugin/Authentication.php
+++ b/vendor/magento/module-backend/App/Action/Plugin/Authentication.php
@@ -225,10 +225,9 @@ class Authentication
 
         // Checks, whether secret key is required for admin access or request uri is explicitly set
         if ($this->_url->useSecretKey()) {
-            $requestParts = explode('/', trim($request->getRequestUri(), '/'), 3);
-            $baseUrlPath = trim(parse_url($this->backendUrl->getBaseUrl(), PHP_URL_PATH), '/');
-            $routeIndex = empty($baseUrlPath) ? 0 : 1;
-            $requestUri = $this->_url->getUrl($requestParts[$routeIndex]);
+            // The requested URL has an invalid secret key and therefore redirecting to this URL
+            // will cause a security vulnerability.
+            $requestUri = $this->_url->getUrl($this->_url->getStartupPageUrl());
         } elseif ($request) {
             $requestUri = $request->getRequestUri();
         }

composer.json

"extra": {
        "magento-force": "override",
        "composer-exit-on-patch-failure": true,
        "patches": {
            "magento/module-backend": {
                "Invalid key error": "patches/composer/invalid.key.patch"
            }
        }
    }

Then run

composer install

3
  • 1
    Yes, I would also recommend this answer Dec 10, 2021 at 7:20
  • +1 for this. Highly recommended answer Mar 15 at 6:14
  • Thanks for posting the patch. Works perfect on 2.4.3-p2
    – Logic4Life
    May 23 at 19:12
4

Since the Magento 2.4.4 update will be released at March 2022 it make sense to create a little bugfix module, here is the code:

Create a basic module nutshell:
Vendor_InvalidSecurityFormKeyBugFix/registration.php

<?php

\Magento\Framework\Component\ComponentRegistrar::register(
    \Magento\Framework\Component\ComponentRegistrar::MODULE,
    'Vendor_InvalidSecurityFormKeyBugFix',
    __DIR__
);

Adding a sequence for loading our module after the Magento_Backend module
Vendor_InvalidSecurityFormKeyBugFix/etc/module.xml

<?xml version="1.0" ?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
    <module name="Vendor_InvalidSecurityFormKeyBugFix">
        <sequence>
            <module name="Magento_Backend"/>
        </sequence>
    </module>
</config>

Vendor_InvalidSecurityFormKeyBugFix/composer.json

{
  "name": "vendor/invalid-security-form-key-bug-fix",
  "type": "magento2-module",
  "description": "This Module is a bug fix for the error message in the dashboard after login into the backend",
  "minimum-stability": "dev",
  "require": {
    "php": ">=7.3.0"
  },
  "autoload": {
    "files": [
      "registration.php"
    ],
    "psr-4": {
      "Vendor\\InvalidSecurityFormKeyBugFix\\": ""
    }
  }
}

Now adding a di preference for overriding the Authentication.php with our AuthenticationOverride.php
Vendor_InvalidSecurityFormKeyBugFix/etc/di.xml

<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <preference for="Magento\Backend\App\Action\Plugin\Authentication" type="Vendor\InvalidSecurityFormKeyBugFix\App\Action\Plugin\AuthenticationOverride" />
</config>

And finally the replacement of the method _redirectIfNeededAfterLogin from the github issue https://github.com/magento/magento2/issues/33749#issuecomment-908145941 of the above comment.
Vendor_InvalidSecurityFormKeyBugFix/App/Action/Plugin/AuthenticationOverride.php

<?php

namespace Vendor\InvalidSecurityFormKeyBugFix\App\Action\Plugin;

use Magento\Framework\Exception\AuthenticationException;

/**
 * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
 */
class AuthenticationOverride
{
    /**
     * @var \Magento\Backend\Model\Auth
     */
    protected $_auth;

    /**
     * @var string[]
     */
    protected $_openActions = [
        'forgotpassword',
        'resetpassword',
        'resetpasswordpost',
        'logout',
        'refresh', // captcha refresh
    ];

    /**
     * @var \Magento\Backend\Model\UrlInterface
     */
    protected $_url;

    /**
     * @var \Magento\Framework\App\ResponseInterface
     */
    protected $_response;

    /**
     * @var \Magento\Framework\App\ActionFlag
     */
    protected $_actionFlag;

    /**
     * @var \Magento\Framework\Message\ManagerInterface
     */
    protected $messageManager;

    /**
     * @var \Magento\Backend\Model\UrlInterface
     */
    protected $backendUrl;

    /**
     * @var \Magento\Backend\App\BackendAppList
     */
    protected $backendAppList;

    /**
     * @var \Magento\Framework\Controller\Result\RedirectFactory
     */
    protected $resultRedirectFactory;

    /**
     * @var \Magento\Framework\Data\Form\FormKey\Validator
     */
    protected $formKeyValidator;

    /**
     * @param \Magento\Backend\Model\Auth $auth
     * @param \Magento\Backend\Model\UrlInterface $url
     * @param \Magento\Framework\App\ResponseInterface $response
     * @param \Magento\Framework\App\ActionFlag $actionFlag
     * @param \Magento\Framework\Message\ManagerInterface $messageManager
     * @param \Magento\Backend\Model\UrlInterface $backendUrl
     * @param \Magento\Framework\Controller\Result\RedirectFactory $resultRedirectFactory
     * @param \Magento\Backend\App\BackendAppList $backendAppList
     * @param \Magento\Framework\Data\Form\FormKey\Validator $formKeyValidator
     */
    public function __construct(
        \Magento\Backend\Model\Auth $auth,
        \Magento\Backend\Model\UrlInterface $url,
        \Magento\Framework\App\ResponseInterface $response,
        \Magento\Framework\App\ActionFlag $actionFlag,
        \Magento\Framework\Message\ManagerInterface $messageManager,
        \Magento\Backend\Model\UrlInterface $backendUrl,
        \Magento\Framework\Controller\Result\RedirectFactory $resultRedirectFactory,
        \Magento\Backend\App\BackendAppList $backendAppList,
        \Magento\Framework\Data\Form\FormKey\Validator $formKeyValidator
    ) {
        $this->_auth = $auth;
        $this->_url = $url;
        $this->_response = $response;
        $this->_actionFlag = $actionFlag;
        $this->messageManager = $messageManager;
        $this->backendUrl = $backendUrl;
        $this->resultRedirectFactory = $resultRedirectFactory;
        $this->backendAppList = $backendAppList;
        $this->formKeyValidator = $formKeyValidator;
    }

    /**
     * @param \Magento\Backend\App\AbstractAction $subject
     * @param \Closure $proceed
     * @param \Magento\Framework\App\RequestInterface $request
     *
     * @return mixed
     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
     */
    public function aroundDispatch(
        \Magento\Backend\App\AbstractAction $subject,
        \Closure $proceed,
        \Magento\Framework\App\RequestInterface $request
    ) {
        $requestedActionName = $request->getActionName();
        if (in_array($requestedActionName, $this->_openActions)) {
            $request->setDispatched(true);
        } else {
            if ($this->_auth->getUser()) {
                $this->_auth->getUser()->reload();
            }
            if (!$this->_auth->isLoggedIn()) {
                $this->_processNotLoggedInUser($request);
            } else {
                $this->_auth->getAuthStorage()->prolong();

                $backendApp = null;
                if ($request->getParam('app')) {
                    $backendApp = $this->backendAppList->getCurrentApp();
                }

                if ($backendApp) {
                    $resultRedirect = $this->resultRedirectFactory->create();
                    $baseUrl = \Magento\Framework\App\Request\Http::getUrlNoScript($this->backendUrl->getBaseUrl());
                    $baseUrl = $baseUrl . $backendApp->getStartupPage();
                    return $resultRedirect->setUrl($baseUrl);
                }
            }
        }
        $this->_auth->getAuthStorage()->refreshAcl();
        return $proceed($request);
    }

    /**
     * Process not logged in user data
     *
     * @param \Magento\Framework\App\RequestInterface $request
     * @return void
     */
    protected function _processNotLoggedInUser(\Magento\Framework\App\RequestInterface $request)
    {
        $isRedirectNeeded = false;
        if ($request->getPost('login')) {
            if ($this->formKeyValidator->validate($request)) {
                if ($this->_performLogin($request)) {
                    $isRedirectNeeded = $this->_redirectIfNeededAfterLogin($request);
                }
            } else {
                $this->_actionFlag->set('', \Magento\Framework\App\ActionInterface::FLAG_NO_DISPATCH, true);
                $this->_response->setRedirect($this->_url->getCurrentUrl());
                $this->messageManager->addErrorMessage(__('Invalid Form Key. Please refresh the page.'));
                $isRedirectNeeded = true;
            }
        }
        if (!$isRedirectNeeded && !$request->isForwarded()) {
            if ($request->getParam('isIframe')) {
                $request->setForwarded(true)
                    ->setRouteName('adminhtml')
                    ->setControllerName('auth')
                    ->setActionName('deniedIframe')
                    ->setDispatched(false);
            } elseif ($request->getParam('isAjax')) {
                $request->setForwarded(true)
                    ->setRouteName('adminhtml')
                    ->setControllerName('auth')
                    ->setActionName('deniedJson')
                    ->setDispatched(false);
            } else {
                $request->setForwarded(true)
                    ->setRouteName('adminhtml')
                    ->setControllerName('auth')
                    ->setActionName('login')
                    ->setDispatched(false);
            }
        }
    }

    /**
     * Performs login, if user submitted login form
     *
     * @param \Magento\Framework\App\RequestInterface $request
     * @return bool
     */
    protected function _performLogin(\Magento\Framework\App\RequestInterface $request)
    {
        $outputValue = true;
        $postLogin = $request->getPost('login');
        $username = isset($postLogin['username']) ? $postLogin['username'] : '';
        $password = isset($postLogin['password']) ? $postLogin['password'] : '';
        $request->setPostValue('login', null);

        try {
            $this->_auth->login($username, $password);
        } catch (AuthenticationException $e) {
            if (!$request->getParam('messageSent')) {
                $this->messageManager->addErrorMessage($e->getMessage());
                $request->setParam('messageSent', true);
                $outputValue = false;
            }
        }
        return $outputValue;
    }

    /**
     * Checks, whether Magento requires redirection after successful admin login, and redirects user, if needed
     *
     * @param \Magento\Framework\App\RequestInterface $request
     * @return bool
     */
    protected function _redirectIfNeededAfterLogin(\Magento\Framework\App\RequestInterface $request)
    {
        $requestUri = null;

        // Checks, whether secret key is required for admin access or request uri is explicitly set
        if ($this->_url->useSecretKey()) {
            $requestParts = strpos(trim($request->getRequestUri(),'/'), $request->getFrontName()) === 0 ?
                explode('/', trim($request->getRequestUri(), '/'), 4) :
                explode('/', trim($request->getRequestUri(), '/'), 3);
            if (($key = array_search($request->getFrontName(), $requestParts)) !== false) {
                unset($requestParts[$key]);
            }
            $requestParams = $request->getParams();
            unset($requestParams['key'], $requestParams['form_key']);
            $requestUri = $this->_url->getUrl(implode('/', $requestParts), $requestParams);
        } elseif ($request) {
            $requestUri = $request->getRequestUri();
        }

        if (!$requestUri) {
            return false;
        }

        $this->_response->setRedirect($requestUri);
        $this->_actionFlag->set('', \Magento\Framework\App\ActionInterface::FLAG_NO_DISPATCH, true);
        return true;
    }
}

Install the module and register it in DB

bin/magento setup:upgrade

Now, the error message should not come anymore after login in the backend
Hope this helps and do not forget to remove the bugfix after update to Magento 2.4.4 :-)

1
  • Instead of overwriting the complete Authentication class I would always prefer to extend from the Magento Authentication class and overwrite only the _redirectIfNeededAfterLogin method.
    – Sebastian
    May 5 at 14:42
1

That is ok to have a low limit for session size to prevent DDOS attacks, value can be changed via the admin panel if needed. Another problem that should be addressed is - suppressed problem, without any error notification to the user and a solution for the issue should be provided.

Magento 2.4, when we log into the backend (admin panel), every page hangs/is loading for about 30 seconds.

In logs we see exceptions: The session size of 276672 exceeded the allowed session max size of 256000.

We are using Redis for sessions.

Does anybody else have a similar issue after upgrading to Magento 2.4.3?

From redis-cli monitor we see that in each second is repeated: 1628681344.757076 [3 127.0.0.1:34310] "hincrby" "sess_1g2sgh25saul85a424puad785d" "lock" "1"

Steps to reproduce (*)

Upgrade Magento 2.4.2-p1 to 2.4.3 Configured Magento to use Redis for session storage

Stores -> Configuration -> Advanced -> System -> Security - Max Session Size in Admin and Max Session Size in Storefront set to 100 and Saved Navigate to any page from Admin -

Actual result (*)

Page load time is increased to more than 30 sec

1

This fix is also added to Magento Quality Patches Tool (QPT)

If Magento Quality Patches Tool is not already installed then install using composer

composer require magento/quality-patches

Apply patch MDVA-40311

./vendor/bin/magento-patches apply MDVA-40311

See

0

This is a new bug when using another URL than admin.

You will need to change below file.

\vendor\magento\module-backend\App\Action\Plugin\Authentication.php

enter image description here

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.