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

Filling in getLogUrl()

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.

No problem: return $this->router->generate('app_login').

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 sense.

The other common place where your authenticator can fail is in the checkCredentials() method. Try returning false here for a second. Then, login with a legitimate user. Nice!

Invalid credentials.

Anyways, go change that back to true.

How Authentication Errors are Stored

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 AbstractFormLoginAuthenticator.

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 getLoginUrl() method and redirect there.

Filling in the Last Email

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 getLastUsername() method and passing that into the template. Oh, but I forgot to render it! Add value= and print last_username.

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 of our LoginFormAuthenticator. But, it's super easy. Inside getCredentials(), instead of returning, add $credentials = . Now, set the email onto the session with $request->getSession()->set(). Use a special key: Security - the one from the Security component - ::LAST_USERNAME and set this to $credentials['email'].

Then, at the bottom, return $credentials.

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.

Leave a comment!

  • 2018-09-17 Victor Bocharsky

    Hey Axel,

    We count progress on video watching, so it's impossible to get a certificate for an unfinished course, since since it does not have all the videos. Moreover, the chapters that are not released yet is just a draft, that can be changed. But yeah, most of the time it does not change or we do very minor changes in it. So, if you won't want to watch the new videos when they are released - ping us again when this course is completely released and we'll give you the certificate.


  • 2018-09-17 Axel Verdruye

    Hi, im completing the course without the videos (as they are not yet implemented). But how do i complete the certificate? As the course % depends on the amount of videos you viewed.

    Thanks !