08.
Logging out & Pre-filling the Email on Failure
Keep on Learning!
If you liked what you've learned so far, dive in! Subscribe to get access to this tutorial plus video, code and script downloads.
If you liked what you've learned so far, dive in! Subscribe to get access to this tutorial plus video, code and script downloads.
Whoops, an error! Please, try again later.
61 Comments
hm... I get
Undefined class constant 'LAST_USERNAME'
on the line:
$request->getSession()->set(Security::LAST_USERNAME, $data['_username']);
Yo Yang!
Make sure you have the use statement for the Security class at the top of your file - it should be:
I'm going to update our code blocks on this page - it wasn't highlighting that this was needed :).
Cheers!
ok, that solved the problem. Found out that when I autocompleted Security, I accidently added the use statement
Sensio\Bundle\FrameworkExtraBundle\Configuration\Security
thx
Already solved. Sorry for disturbance. Your course is amazing!
Cheers! :)
Hi
Firstly, thank you for this amazing course.
Secondly, for some reason
$request->getSession()->set(
Security::LAST_USERNAME,
$data['_username']
);
is not prefilling _username after an invalid login attempt. All else seems to be working fine. Any ideas? I am running Symfony 3.1.4
Hey Imogen,
Hm, are you sure the
$data['_username']doesn't empty when you set it into session? Could you make sure withdump($data['_username']);before setting it? Also ensure you print the last username in Twig template of your login form.AFAIK, since Symfony 2.6 a new security error helper was added - check the example how to use it: http://symfony.com/blog/new-in-symfony-2-6-security-component-improvements#added-a-security-error-helper
Does it help you?
Cheers!
Hi...
If I do either of these
$data = $form->getData();
$request->getSession()->set(
Security::LAST_USERNAME,
$data['_username']
);
dump($data['_username']); die;
return $data;
OR
$data = $form->getData();
$request->getSession()->set(
Security::LAST_USERNAME,
$data['_username']
);
dump($request->getSession()->get(
Security::LAST_USERNAME
));die;
return $data;
I get the username dumped to the screen... No idea how to debug beyond this... Any help would be much appreciated. Thank you.
FYI, Found the problem - simple type in SecurityController. Thank you for comments.
$form = $this->createForm(LoginForm::class,[
'username' => $lastUsername,
]);
SHOULD BE
$form = $this->createForm(LoginForm::class,[
'_username' => $lastUsername,
]);
NOTE '_username' NOT 'username'
Good catch! Glad you got it working.
Cheers!
Oh man was enjoying this. Seems the next load of videos are not ready????
Hey, Matthew!
Yes, you're right, it's not ready yet. But it will be very soon!
Hey there!
New videos are added!
Hmm. I'm a little creeped out by AuthenticationUtils.php
How did getLastUsername() get in there? What am I missing or forgetting? Was it there all along? Did something we've done up to this point cause Symfony or PHPStorm to put it in there? If so...what is that behind-the-scenes code generation process, and what do I need to be aware of to make sure it behaves properly, i.e. I decide to call my user identifiers 'aquanautname', instead of username?
"Automagic" stuff like that is usually what gives me headaches in Rails.
Hey Adam!
Sorry for the late response, for some reason this message went directly to the spam folder =S
At the beginning it migh look's like magic, but it's not, all that `AuthenticationUtils::getLastUsername()` does, is fetch a value from the session, in this case it's empty because Symfony doesn't know how to fill it, thats why we manually set it with the value of the username input. Maybe if you rewatch the very first and half minute you will get it.
Cheers!
Small thing, but I'm just curious... Is there any way to not hard code the "/logout" route in "security.yml"? Can you pull in the "security_logout" route name somehow so that if you later change the url of the logout, you don't have to change it in both the SecurityController and security.yml?
Hey Terry!
It's an interesting question, and actually, yes, you can!
You just have to write the route's name instead of the path e.g.
Of course, if you have to change the route's name, well you need to change it in here too, but that's less likely to happen.
Have a nice day!
How do you control which page the user is redirected to after being logged out by the system?
Hey Terry Caliendo
You can specify to which path you want to redirect them by setting up the target key in your security.yml, by default it's set to "/"
But, if you want something more dynamic, you will have to create your own "LogoutHandlerListener", it's almost a regular listener but it has to implement "LogoutHandlerInterface", you can follow what this guy did here: http://stackoverflow.com/a/39293401
Have a nice day!
Thanks for the response and the reference.
I had previously overlooked this page, but I also now see the key in here.
http://symfony.com/doc/curr...
Thanks again!
Terry
NP man, it has been fun replying to your questions :)
Cheers!
when a user is logged in, I want to show something like "username loggout-button" in the navbar. But since
<li>< a href="{{ path('security_logout') }}">Logout</li>
is in the base.html.twig, I have no idea how to access the username.
I tried modify loginAction():
return $this->render(
'security/login.html.twig',
[
'form' => $form->createView(),
'error' => $error,
'username' =>$lastUsername,
]
);
and in bast.html.twig:
{{ username }}<li>Logout</li>
but like I thought, this gives me the message:
Variable "username" does not exist in base.html.twig at line 26
so how can I do this? I was thinking about making blocks in base.html.twig and move the line to security/login.html.twig where I CAN access the username property, but doesn't seem to be the right way either...
Hey Yang,
Use global
appvariable to access user object, i.e. {{ app.user.username }}. But ensure your user is authenticated, otherwise you'll get an error:Cheers!
Hey, great job on these tutorials, you're really helping me a lot. I'm having a problem with this one. When I try logging in, it automatically logs me out. However, if I remove code that checks if the user is logged in base.html.twig everything goes smoothly. Do you have any idea why this might be happening?
Hey Jovana Gajic
How are you checking that you are logged in, in your template?
Can you check at your profiler bar if it says "anon." after logging in?
Cheers!
if I type this {% if is_granted('ROLE_USER') %} it redirects me back to the login page. If I omit this part, I get logged in, and profile bar shows my username. When I'm redirected to login page it shows anon in profile bar
Ohh, this is interesting. I believe the
is_granted()function is doing something nasty. Can you tell me which version of Symfony are you using?Try changing your if statement to this:
And let me know if it works ;)
Hey, I've finally made some progress. I figured out that I was logged in but wasn't authenticated. At one moment I've made my model implement the Serializable, as described in Symfony documentation, and once I removed it, along with the serialize and the unserialize methods it worked. I suppose those methods for serializing, unserializing weren't good for this case
Hey Jovana,
If you were logged in but were not authenticated - probably you have some misconfiguration of your firewall. If you still have a problem, could you show us your "security.firewalls" section in app/config/security.yml ? Or also there could be a problem in your serialize()/unserialize() methods implementations, probably you unserialize incorrectly (incorrect fields order, etc.), but it's difficult to say without seeing your implementation of those methods.
Cheers!
when a user is logged in, I want to show something like "username loggout-button" in the navbar. But since this is in the base.html.twig:
<li>< a href="{{path('security_logout') }}>Logout</li>
I have no idea how to access the username
First attempt: I tried to modify loginAction():
return $this->render(
'security/login.html.twig',
[
'form' => $form->createView(),
'error' => $error,
'username' =>$lastUsername,
]
);
and in bast.html.twig:
{{ username }}<li>Logout</li>
but like I expect, I got the following error message when I try to login:
Variable "username" does not exist in base.html.twig at line 26
then I thought of using block in base.html.twig and move the {{username}} part to the login.html.twig, but it doesn't seems to be the right solution either cause I will have to use it everywhere...
so, can you help me with this?
edit: just realized that what I tried couldn't have worked because login.html.twig is only the loginform, and has nothing to do with the pages after I logged in. So, now I have absolutly no idea how to solve this^^
Hey Yang,
It's easy enough! You have access to the global context in Twig templates which allows to get currently logged in user with
app.user. So just use:Cheers!
that was fast!! good to know, thx, I modify the original code and added {{ app.user.username }}, it works nicely. thx
Be careful! You can failed with error when user IS null if you just checking
app.user.usernameUse extra check in if statement like:{% if app.user and app.user.username %}But probably
if app.userwill be enough here, because for some weird reasons user could have no username but could be logged in. I mean, that app.user return an object <i>only</i> if a user is logged in. So you don't need username extra check here.Cheers!
I think theres a small missunderstanding here, I want to output the username, not to check. because the original <li> codes are wrapped in a if-block already {% if is_granted('ROLE_USER') %}. I thought users only get a role if they are logged in, so this already check if user is logged in. So if it's true, I can output the username by simplying adding {{app.user.username }} in front of the logout-button.
Ah, then it makes sense! Yes, you're definitely right here! :)
Good evening! Can you help me, please! I can't login. I enter the correct information nothing happens, I enter incorrect information - the same thing
Hey Julia Shishik!
I can definitely help :). So if you're seeing nothing - like no errors in any situation - then it's possible that your authenticator is not being called at all! Here's what you can do to check. First, put
var_dump('here!');die;at the top of yourgetCredentials()method. Is this being called? If not, check your services.yml and security.yml setup. If you configure your authenticator correctly, thegetCredentials()method should be called on every request. If the method IS being called, check your logic ingetCredentials()to make sure you're checking the current URL correctly. Also, verify thatgetUser()is being called when you submit. IfgetUser()is called, then, at the very least, you should definitely see an error message when you type in a wrong user/pass. So, the problem is probably somewhere before this.Let me know what you find out!
Cheers!
Good morning!
getCredentials() method is being called.
getUser() is NOT called((
Logged in asanon.
AuthenticatedYes
Token classAnonymousToken
Firewall namemain
and 2 missing translation, and log message
INFO
21:51:37
request Matched route "security_login".
Show context
INFO
21:51:37
security Populated the TokenStorage with an anonymous Token.
WARNING
21:51:37
translation Translation not found.
Show context
WARNING
21:51:37
translation Translation not found.
Show context
Last 10
Hey Julia,
Good investigation! getCredentials() called on every request and your job is to read the credentials from the request and return it. If you return null, the rest of the authentication process is skipped, i.e. getUser() won't be called. Otherwise, getUser() will be called and the return value is passed as the first argument.
So make sure you *return* credentials in getCredentials() method.
Cheers!
Oh, thank you very much! Yes, I had an error in the method getCredentials. I missed the exclamation mark befor $isLoginSubmit! Oh yeah. It is sad! But now everything is fine
I ran into the problem where the last_user value wasn't saved into the session. This was due to the logic that I adjusted.
Tutorial logic:
$isLoginSubmit = $request->getPathInfo() == '/login' && $request->isMethod('POST');
if (!$isLoginSubmit) {
return;
}
My Logic:
if (!$request->getPathInfo() == '/login' && !$request->isMethod('POST')) {
return;
}
So I didn't see what went wrong and Ryan had a look at it. He pointed out that I *slightly* reversed the logic. Then he added:
"For example, if you go to /login with a GET request (e.g. you submit the form, then symfony redirects you back to /login), I think it will skip your if statement. In this case, you call handleRequest(), but since there is no login information, $form->getData() is blank. This is then being set into the session, clearing out any LAST_USERNAME from the previous POST request. Later on the request, your controller is rendered and this is blank!"
I think this helps anyone that run into the same issue :P
Hey Stan!
Ah, great question! So, let me say a few things:
A) We didn't redirect from POST /login to GET /login for any special reason - this has always been Symfony's default behavior (but I can't think of any advantage to doing this).
B) So, you don't need to redirect - you could allow the request to continue like normal (you would simply not request a Response from onAuthenticationException). If you did this, then you could just read the last username off of the request.
If you use Symfony's built-in
form_loginfunctionality, they actually allow for both, and it's configurable. So, do whatever you want - you're definitely thinking about the situation correctly: there is no special reason for redirecting versus just allowing the request to continue that I can think of.Cheers!
Hello,
Thank you for all your effort.
When I am logged in, I type /login in the address bar, it rendered the login page. I think it should not appear, instead another page ( hompepage) should. How to do this ??
Hey Mehdi,
Good questions! There're a few possible solutions:
if ($this->getUser()) {
}
Hello,
I am sorry for the late reply.
I used the first solution and it worked for me.
Thank you Victor
Hey Mehdi,
No problem! I'm glad you got it working for you ;)
Cheers!
How can I redirect every visitor which is not logged in to the login page?
And how can I than make exceptions to this rule (for a page like "About this website")?
Hey Markus B.
One way of achieving it is via an "Access control list", you can configure your own inside the security.yml file
You can find more detailed information here: https://symfony.com/doc/current/security/access_control.html
This is a basic example of securing all pages but login
Have a nice day :)
I have the following behavior : after logging out, I hit the back button... and then I am logged again.
That seems pretty annoying, but I think this is a quite common issue that has a solution.
What is the best way to fix this ?
Hey Moudug!
Hmm. So it's not exactly what you're saying :). Actually, when you hit back, you are still logged out - but your browser is showing your the previous page, as it looked when you were there a moment ago. If you try to click on any links that require login, you'll go to the login page (because you're not actually logged in).
If you google the issue, there are some solutions - but it's just not something that's super well supported. One decent solution might be to run some JavaScript on an interval (e.g. every 30 seconds + on page load). In that JS, make an AJAX call to your server to see if the user is logged in. If they are not, redirect to the login page. Then, even if the user has 10 browser tabs open, if you logout in one of them, the other tabs will go to the login page after a few seconds.
Cheers!
"Houston: no signs of life"
Start the conversation!