How to capture exception message in my LoginController that was thrown by UserProvider::refreshUser()?

Viewed 141

I've got an app that uses a slightly modified AbstractFormLoginAuthenticator to provide authentication, so I've got custom \App\Security\UserProvider and \App\Security\Authenticator classes. These are both currently working fine and I now want to add a new feature. In the UserProvider::refreshUser() method, I want to add a check that might immediately invalidate the session. For example, perhaps the user record has a boolean active field and if that field has been toggled to false during a user's session, I want to immediately log the user out. I've got something like this:

public function refreshUser(UserInterface $user)
{
    if ($someCondition) {
        throw new UsernameNotFoundException('You have been logged out for reasons.');
    }
    return $user;
}

This works as desired -- when the user makes a new request, the condition triggers, the authentication is cleared, and the user is immediately redirected to the login controller. However, I have one lingering issue. I would like to present the user with an indication of what happened. I.e., the user should see, "You have been logged out for reasons."

However, the exception that was thrown is not available via the AuthenticationUtils::getLastAuthenticationError() method like the exceptions thrown in \App\Security\Authenticator are. Thus, I seem to have no means to grab that message text in the controller and pass it to the view.

I've tried throwing CustomUserMessageAuthenticationException, which also did not propagate. I've inspected the session data and verified that no reference to the exception is stored there. Do I need to just manually add it to the session myself, and then pull it back out in the controller? Or does Symfony have some built-in mechanism that I'm missing?

TL;DR If I throw an Exception in my Authenticator, I can grab it from the subsequent login controller by calling getLastAuthenticationError(). How do do the same for an Exception thrown in my UserProvider?

[UPDATE] I was able to accomplish what I wanted by using a CustomUserMessageAuthenticationException and then manually inserting it into the session with the key that getLastAuthenticationError() looks for:

public function refreshUser(UserInterface $user)
{
    if ($someCondition) {
        $e = new CustomUserMessageAuthenticationException('You have been logged out for reasons.');
        $this->session->set(Security::AUTHENTICATION_ERROR, $e);
        throw $e;
    }
    return $user;
}

I'm not sure if this is ideal, I'm happy to entertain alternatives if anybody has one.

0 Answers
Related