Problem/Motivation

An error message displayed while using in conjuction with the mail_login module.

TypeError:
Drupal\mail_login\AuthDecorator::__construct(): Argument #1
($user_auth) must be of type Drupal\user\UserAuthenticationInterface,
Drupal\tfa\TfaUserAuth given

Steps to reproduce

Use latest version of TFA (2.0.0-alpha4)
Use latest version of mail_login module (4.0.3)
Enable both modules using Drupal core 10.3.10.

Proposed resolution

Drupal core has two (very similarly named auth interfaces):
Drupal\user\UserAuthInterface
https://git.drupalcode.org/project/drupal/-/blob/10.3.x/core/modules/use...
Drupal\user\UserAuthenticationInterface
https://git.drupalcode.org/project/drupal/-/blob/10.3.x/core/modules/use...

TFA implements the former, meanwhile mail_login relies on the latter one.

I've found the solution therefore I attached a patch.

Issue fork tfa-3497020

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

imre.horjan created an issue. See original summary.

imre.horjan’s picture

Issue summary: View changes
cmlara’s picture

Category: Bug report » Task
Status: Needs review » Needs work
Related issues: +#3456738: BC break in login auth changes from #3444978

Until Drupal 12 is released contrib modules need to accept both interfaces and test which they have been provided. See #3456738: BC break in login auth changes from #3444978 comments #22 and #24.

Mail_login should indicate it is only compatible with Drupal12+ if it accepts only the newer interface, otherwise it needs to accept both. You likely will want to raise a bug report in mail_login to inform them of this issue.

Setting to a task as we will eventually need to do this. Moving to needs-work as D.O. has fully moved over to an MR only workflow, patches can not be tested only MR’s can be tested/reviewed.

Edit: to note that accepting only the older Interface is acceptable in Drupal < 12.

imre.horjan’s picture

Assigned: Unassigned » imre.horjan
Issue tags: +Drupal 12 compatibility

Thanks for your quick reply and detailed summary on the topic.

I assign the ticket to myself, and I will create an MR soon.
I will take a look what else can be done in mail_login and will create the corresponding ticket if necessary.

imre.horjan’s picture

I tried to address the same issue in mail_login.

Unfortunately the old interface works like a wrapper for the new interface, therefore without applying this patch I got an other error:
Error: Call to undefined method Drupal\tfa\TfaUserAuth::authenticateAccount() in Drupal\mail_login\AuthDecorator->authenticateAccount() (line 137 of modules/contrib/mail_login/src/AuthDecorator.php).

I created the MR.

In addition to implementing the interface, I also refactored the authentication logic into the new method, because at some point the old method is going to be removed.

imre.horjan’s picture

Assigned: imre.horjan » Unassigned
Status: Needs work » Needs review

I Unassign and set status to Needs review.

cmlara’s picture

Status: Needs review » Needs work

From the MR

UserAuthenticationInterface::lookupAccount() does not exist in decorators not implementing UserAuthenticationInterface.

Core's user login form assumes that if the User Auth service implements UserAuthenticationInterface it is safe to call lookupAccount.
This works fine when you have only the two sceanrios:

  • Core Login Form -> Core UserAuth service (implements UserAuthenticationInterface)
  • Core Login Form -> Decorator1(UserAuthenticationInterface) -> Core UserAuth(UserAuthenticationInterface)
  • Core Login Form -> Decorator1(UserAuthenticationInterface) -> Decorator2(UserAuthenticationInterface) -> Core UserAuth(UserAuthenticationInterface)

This logic however fails when you have

  • Core Login Form -> Decorator1(UserAuthenticationInterface) -> Decorator2(UserAuthInterface) -> Core UserAuth(UserAuthenticationInterface)
  • Core Login Form -> Decorator1(UserAuthenticationInterface) -> Decorator2(UserAuthInterface) -> Decorator3(UserAuthenticationInterface) -> Core UserAuth(UserAuthenticationInterface)

The outcomes in this scenario are that core calls Decorator1 and:

  • Decorator 1 calls non-existent method on Decorator2 (throws an exception) or
  • Decorator 1 attempts to resolve the data itself using Cores logic ( this is a breach of decorator design, and would mask that Decorator3 is being ignored)

I will note the first scenario is essentialy what you describe in #6, where mail_login was re-written to (incorrectly) assume every decorator will already implement UserAuthenticationInterface prior to D12, possibly because core made the same assumption.

On a cursory glance I believe the only way we can use UserAuthenticationInterface is if we are on D12, OR we have a setting that manually enables the use of a new class when a site owner ensures 100% of their stack supports the UserAuthenticationInterface (in which case it is safe for exceptions to be thrown).

Drupal Core tried to do this in a manner to retain BC with minimal immediate contrib breakage and ended up creating a scenario that the probability of site breakage increased each day the commit remained in the repository by pushing design failures onto the contrib ecosystem. When we look at the entire issue as a whole we are essentially left with a non BC capable API addition that would have been easier to implement if it was mandatory.

imre.horjan’s picture

I solved the issue in mail_login code as you suggested, and created the ticket for it as well.
https://www.drupal.org/project/mail_login/issues/3497643

vzamko’s picture

But log in works only with username, if TFA is enabled and I try to log in via email, it's not working.

cmlara’s picture

But log in works only with username, if TFA is enabled and I try to log in via email, it's not working.

Assuming this is related to this interface, see #8 and the associated MR comment.

Essentially, until D12 any Core or Contrib code needs to assume that lookupAccount() doesn't exist and code around it to implement their features Some Contrib or Core may not have properly done this, you would want to check with whatever module is providing Email address support as the root cause.