Scroll down to the script below, click on any sentence (including terminal blocks!) to jump to that spot in the video!Cool, got it! Show me the script!
This Chapter isn't quite ready yet
Rest assured, the gnomes are hard at work on completing this video
Go back to the login page. I wonder what happens if we fail the login... which, is only possible right now if we use a non-existent email address. Oh!
Cannot redirect to an empty URL
Hmm: this is coming from
AbstractFormLoginAuthenticator our authenticator's
base class. If you dug a bit, you'd find out that, on failure, that authenticator
class is calling
getLoginUrl() and trying to redirect there. And, yea, that makes
sense: if we fail login, the user should be redirected back to the login page.
To make this actually work, all we need to do is fill in this method.
Ok, try it again: refresh and... perfect! Hey! You can even see an error message on top:
Username could not be found.
We get that exact error because of where the authenticator fails: we failed
to return a user from
getUser(). In a little while, we'll learn how to customize
this message because... probably saying "Email" could not be found would make more
The other common place where your authenticator can fail is in the
method. Try returning
false here for a second. Then, login with a legitimate
Anyways, go change that back to
What I really want to find out is: where are these errors coming from? In
SecurityController, we're getting the error by calling some
$authenticationUtils->getLastAuthenticationError() method. We're passing that
into the template and rendering its
messageKey property... with some translation
magic we'll talk about soon too.
The point is: we magically fetch the "error" from... somewhere and render it. Let's
demystify that. Go back to the top of your authenticator and hold command
or control to click into
In reality, when authentication fails, this
onAuthenticationFailure method is
called. It's a bit technical, but when authentication fails, internally, it's because
something threw an
AuthenticationException, which is passed to this method. And,
ah: this method stores that exception onto a special key in the session! Then,
back in the controller, the
lastAuthenticationError() method is just a shortcut
to read that key off of the session!
So, it's simple: our authenticator stores the error in the session and then we read the error from the session in our controller and render it.
The last thing
onAuthenticationFailure() does is call our
and redirect there.
Go back to the login form and fail authentication again with a fake email. We see the error... but the email field is empty - that's not ideal. For convenience, it should pre-fill with the email I just entered.
Look at the controller again. Hmm: we are calling a
and passing that into the template. Oh, but I forgot to render it! Add
But... we're not quite done. Unlike the error message, the last user name is not
automatically stored to the session. This is something that we need to do inside
LoginFormAuthenticator. But, it's super easy. Inside
instead of returning, add
$credentials = . Now, set the email onto the session
$request->getSession()->set(). Use a special key:
Security - the one
from the Security component -
::LAST_USERNAME and set this to
Then, at the bottom, return
Try it! Go back, login with that same email address and... nice! Both the error and the last email are read from the session and displayed.
Next: let's learn how to customize these error messages. And, we really need a way to logout.