I need a very simple form login, so I’m using a Symfony Guard authenticator for this.
My application is multi-domain, for now login is possible on only 3 of them (and 2 are subdomains). But I can’t log in on any of them.
First, here are some resources:
- The authenticator: FormLoginAuthenticator.php
- My security configuration: [https://gist.github.com/Pierstoval/1e29a9badab1cba03e45a306aa658c83#file-security-yaml)
- And in case it’s needed, the session configuration in the framework: config/packages/framework.yaml
I don’t understand why, but to debug this, I tried updating config/packages/dev/web_profiler.yaml
to set intercept_redirects: true
, to debug cookies and security config, and here’s what I have when reproducing the common login scenario:
- When accessing the backend page (that shows the login form) I have the session cookie with a value like
llno5smlmsema5nq02kr30s6m2
. - After I submit the form with correct values, I see the profiler’s redirection page, and the Web Debug Toolbar shows me that I’m
Logged in as Pierstoval
and the session cookie sent by the response changes id and becomesb1vbcnvp7e6p0j0o0vtd7ui7bf
(because by default the Firewall migrates the session when logging in), so this works. I can even see that the token is in the session. I also addeddump()
statements in theSession::save()
method, and dumping session content shows the token. And the token is in the session file when I dump it too (invar/sessions/dev/sess_b1vbcnvp7e6p0j0o0vtd7ui7bf
). - I click on the
http://back.esteren.docker/fr/
link showed by the redirection page, and then I see the session cookie id did not change (it’s the one that have been set after logging in), but this time, the Web Debug Toolbar shows me that I’mLogged in as anon.
.
To me, there’s a problem when the session is saved, so I took a look at the session files in var/sessions/dev/
, after the redirection.
When I cat var/sessions/dev/sess_b1vbcnvp7e6p0j0o0vtd7ui7bf
, I see this:
_sf2_attributes|a:2:{s:18:"_csrf/authenticate";s:43:"bCm23vBGyrq52caehAH9cCTjJkAmdT9j9Z8yygaET78";s:26:"_security.main.target_path";s:30:"http://back.esteren.docker/fr/";}_sf2_meta|a:3:{s:1:"u";i:1538092899;s:1:"c";i:1538092750;s:1:"l";s:5:"86400";}
Which, when unserializing the session attribute bag array, gives this:
array:2 [ "_csrf/authenticate" => "bCm23vBGyrq52caehAH9cCTjJkAmdT9j9Z8yygaET78" "_security.main.target_path" => "http://back.esteren.docker/fr/" ]
This means the token has not been saved in the session after the successful login.
And even worse: since I already debugged the session file before redirecting, I know that it was saved ni the session and at some time it was removed from it before the session being saved another time.
How is this even possible? Did I forget something in my security configuration?
As a side-note, I tested with and without docker (with a plain php-fpm+nginx setup) and none worked, this probably means that it’s not a permission issue from the docker side…
Advertisement
Answer
Finally, thanks to @Lynn and @Wirone on the public Symfony Slack channels, I ended up with a solution.
First, the bug was the fact that my User entity (which is serialized in the session) did not store the password.
And when a token is created, it checks if the “old” (in session) user password is the same as the “new” (refreshed) one, thanks to the Abstractoken::hasUserChanged()
method.
And if the user object has changed, the firewall logs the user out.
To fix this, either serialize the password with the user, or implement EquatableInterface
and use your own checks.
And this is what I did:
- Implement
EquatableInterface
- Serialize only
id
and the timestampable fieldscreatedAt
andupdatedAt
- Make
isEqualTo()
check class and date fields to know if the user has changed.
Hope this helps ð