29 March 2022

The Joomla 4.1.1 and 3.10.7 updates introduce a badly implemented feature called “Preferred authentication method” which locks people out of their sites.

We have already reported this issue for Joomla 4 and Joomla 3. We expect Joomla to address this issue promptly. They'd better. This is a massive issue.

Yes, we are aware that they are marked as “security” releases. However, the major bug it introduces is far more serious than the low priority security issues it addresses.

If you really want to install this security update do the following:

  • Set your site off-line
  • Update your site
  • Follow the instructions below under “Fix what is broken” for your CMS version.

Fix what is broken

If you have already updated your site to Joomla 3 you will find that you can no longer log into the site using a password if your first login after the update took place without using a password such as:

  • You were logged in by the Remember Me (a.k.a. cookie authentication) plugin.
  • You used SocialLogin or any other non-password third party authentication method.
  • You used WebAuthn in Joomla 4.
  • You were logged in by third party software, e.g. as part of the process of making a purchase with an e-commerce component.
  • You logged in with a Single Sign-On plugin.
  • You logged in with a forum bridge or any other authentication plugin providing a bridge to another application installed on your site or remotely.
  • You were logged in with a Joomla authentication plugin other than the default “Authentication - Joomla” such as but not limited to LDAP, Gmail and so on — including any third party authentication plugins.

This also applies to all of your site's users. So, yes, this is serious. If you had people logged in on your site whose session expired they will be next logged in by the Remember Me plugin. Once they log out they will be FOREVER locked out of your site. This can be detrimental for any site.

You can fix that problem by surgically removing two small pieces of code which cause the login issues. Luckily, we are very familiar with Joomla, we understand how it works, we spotted this problem first and have come up with a fairly simple solution.

Unfortunately, it requires editing files which is a major pain if you have dozens or hundreds of sites to update. That's why we reported this issue to the Joomla project before publishing a workaround. Yes, there's a way to work around this issue with a fairly convoluted plugin but we'd rather see it fixed in Joomla itself than create Yet Another Plugin to work around Yet Another Joomla Bug...

Without further ado, let's see how to fix this mess.

Fixing Joomla 4

Edit the file plugins/user/joomla/joomla.php.

Find the following lines (lines 408–419):

		if ($id)
		{
			$instance->load($id);

			// Add auth provider constraint if not set yet
			if (!$instance->authProvider)
			{
				$instance->setAuthProvider($user['type']);
			}

			return $instance;
		}

Change them to read

		if ($id)
		{
			$instance->load($id);

			return $instance;
		}

Edit the file libraries/src/Authentication/Authentication.php.

Find the following lines (lines 187–194):

			// Check auth provider constraint
			if ($pluginConstraint
				&& $plugin instanceof ProviderAwareAuthenticationPluginInterface
				&& $plugin::isPrimaryProvider()
				&& $plugin::getProviderName() !== $pluginConstraint)
			{
				continue;
			}

Change them to read

			// Check auth provider constraint
			if ($pluginConstraint
				&& $plugin instanceof ProviderAwareAuthenticationPluginInterface
				&& $plugin::isPrimaryProvider()
				&& $plugin::getProviderName() !== $pluginConstraint)
			{
				//continue;
			}

Joomla 3

Edit the file plugins/user/joomla/joomla.php.

Find the following lines (lines 388–399):

		if ($id)
		{
			$instance->load($id);

			// Add auth provider constraint if not set yet
			if (!$instance->authProvider)
			{
				$instance->setAuthProvider($user['type']);
			}

			return $instance;
		}

Change them to read

		if ($id)
		{
			$instance->load($id);

			return $instance;
		}

Edit the file libraries/src/Authentication/Authentication.php.

Find the following lines (lines 304–310):

			// Check auth provider constraint
			if ($pluginConstraint
				&& $plugin instanceof ProviderAwareAuthenticationPluginInterface
				&& $plugin::isPrimaryProvider()
				&& $plugin::getProviderName() !== $pluginConstraint)
			{
				continue;
			}

Change them to read

			// Check auth provider constraint
			if ($pluginConstraint
				&& $plugin instanceof ProviderAwareAuthenticationPluginInterface
				&& $plugin::isPrimaryProvider()
				&& $plugin::getProviderName() !== $pluginConstraint)
			{
				//continue;
			}