Skip to content

[6.2] getLastAuthenticationError(): Return value must be of type ?AuthenticationException, string returned #49166

@AdamReece-WebBox

Description

@AdamReece-WebBox

Symfony version(s) affected

6.2.5

Description

In an authenticator handler, e.g. \App\Security\AppAuthenticator::authenticate(), throwing an exception does not set the session correctly. This is based on the guide How to Write a Custom Authenticator.

For example if you throw a bad credentials exception because a user identifier is not found:

/** @var User|null $user Local user entity. */
if (!($user = $this->userRepository->loadUserByIdentifier($username))) {
    throw new BadCredentialsException();
}

Then in your authenticate controller you grab that error from the AuthenticationUtils service:

$error = $authenticationUtils->getLastAuthenticationError();

This will cause an internal error because \Symfony\Component\Security\Http\Authentication\AuthenticationUtils::getLastAuthenticationError() has a return type hint of ?AuthenticationException, however when the thrown exception is read from the session here:

$authenticationException = $session->get(SecurityRequestAttributes::AUTHENTICATION_ERROR);

The content of $authenticationException will be string instead of the original exception instance thrown, thus invalid for the return type hint. This results with a fatal error:

Symfony\Component\Security\Http\Authentication\AuthenticationUtils::getLastAuthenticationError(): Return value must be of type ?Symfony\Component\Security\Core\Exception\AuthenticationException, string returned

Logging in successfully won't produce a problem because the $error will be null.

How to reproduce

  1. Build a custom authenticator as per this guide, even if it's a classic Doctrine entity username/password based authenticator.
  2. Fetch the last authentication error in your authentication controller.
  3. Submit some bad credentials to your login form so that an exception is thrown.

Possible Solution

The session would need to contain a serialised instance of the authentication exception thrown, or the getLastAuthenticationError() would need to permit the return of a string as part of a union type with AuthenticationException and null.

Additional Context

I don't recall getting this problem in Symfony 6.1 or earlier though I could be wrong, we've only noticed it since 6.2.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions