No error message shown when cookies are disabled
When the client doesn't have cookies disabled no warning message is shown. Expected message: https://github.com/symfony/symfony/blob/master/src/Symfony/Component/Security/Http/Firewall/AbstractAuthenticationListener.php#L142
Some assumptions i've made: No session can be started without cookie support. Redirect serves a fresh page, so the only way to show this error message is to do a forward.
My setup
firewalls:
main:
pattern: ^/
form_login:
provider: fos_userbundle
csrf_provider: form.csrf_provider
default_target_path: /%locale%/saved-reports
login_path: /%locale%/
check_path: fos_user_security_check
failure_forward: true
failure_path: /%locale%/
logout:
path: fos_user_security_logout
target: /
anonymous: true
In my own controller:
<?php
public function homeAction(Request $request) {
$error = $request->attributes->get('_security.last_error');
if (is_object($error)) {
$error = $error->getMessage();
} else {
$error = var_export($error, true);
}
// .. some more stuff
}
The error is available in this controller!
In base.html.twig: {{ render(controller('FOSUserBundle:Security:Login')) }}
FOS User Bundle tries to grab the error from the request here https://github.com/FriendsOfSymfony/FOSUserBundle/blob/master/Controller/SecurityController.php#L27 but since i render from base.html.twig it's not the right request anymore but a sub-request??
I placed debug points all over (like HttpKernel) but i don't understand why this doesn't work. Perhaps the process can be simplified with the RequestStack.
Also as alternative i tried passing the error variable like this {{ render(controller('FOSUserBundle:Security:Login', {'error' : error})) }} and then catching it in the SecurityController like this public function loginAction(Request $request, $error) { but that didn't relay the error either.
well, if you cannot start a session, you won't be able to use a form login anyway. Using a form requires a stateful authentication to remember the user, and so requires starting the session. Using forward will not help you at all.
and the login action is not meant to be embedded as a subrequest. If you want to do it, you have to take care to forward the right attributes to the subrequest (I don't remember the exact syntax as I'm not using this)
@stof what do you mean with "use a form login". Do you mean the user wont be able to login with the form? This is totally acceptable! Or do you mean "the error message can not be displayed because you are using a form login"?
Also the login box needs to be available on every page (it's in the header of the layout). I thought it was the right way to embed it as a subrequest, as the securityController::loginAction provides the values needed for the template https://github.com/FriendsOfSymfony/FOSUserBundle/blob/master/Controller/SecurityController.php#L47-L49
Should i search the solution in forwarding the right attributes, or do i have to revise my overall approach and maybe not embed the login action as a subrequest?
@flip111 if you are unable to start a session, you won't be able to use form login.
If your issue is simply that you haven't started a session previously, the fix is simpler: make sure a session is started before the user goes to login-check or disable require_previous_session
@stof "if you are unable to start a session, you won't be able to use form login." I will assume here that you mean actually logging in with a form. Yes like i said it's acceptable that this doesn't work, as i'm only trying to display the message that cookies have been disabled.
So the use case here is a client who does not have cookies enabled (thus i can not create a session). I don't think setting the require_previous_session to false makes any difference because i DO want it to error on "not having a session before" AKA "client does not have any cookies support enabled".
The problem i run into is that the with the forward the exception (which is tied to the request) is lost.
There some different scenario that can happen as described here http://symfony.com/doc/current/components/security/firewall.html#flow-firewall-authentication-authorization
(a) authenticate a user (b) throw an AuthenticationException (c) do nothing (because there is no authentication information on the request)
I assume that in all cases the new sub-request is made here https://github.com/UserScape/symfony-component-bundle/blob/master/Security/Http/EntryPoint/FormAuthenticationEntryPoint.php#L53-L57
But i don't know if i am on the right track here, as i originally thought FOS User Bundle was not passing error messages along correctly when the client does not have cookie support enabled.
EDIT: Adding sketch of the scenario
FrontPage (main-request) -> embedded login (sub-request) --- User login now and request new page --- login to /login_check (main-request) -> forward Frontpage (sub-request) -> embedded login (sub-request)
So the information is available in the forward, but not anymore in the embedded sub-request. I noticed the FormAuthenticationEntryPoint use HttpUtils:createRequest() to put the message in the forwarded sub-request See: https://github.com/symfony/symfony/blob/master/src/Symfony/Component/Security/Http/HttpUtils.php#L73
So perhaps a custom twig method instead of controller() could help not sure.
Also i'm not sure if FOS User Bundle could facility better support for embedding the login controller or if that's the responsibility of the programmer (me). I will leave the issue open until this is clear.
if you forward to the FOSUserBundle controller, the error should not be lost. We have some logic in place to support it. The issue is that you use a subrequest to embed the login controller, which means you are responsible to forward the right info to the subrequest:
{{ render(controller('FOSUserBundle:Security:Login', {
'_security.403_error' : app.request.attributes.get('_security.403_error'),
'_security.last_error' : app.request.attributes.get('_security.last_error'),
'_security.last_username' : app.request.attributes.get('_security.last_username'),
})) }}
these 3 names correspond to the 3 attributes set by the HttpUtils when forwarding the request in case you use forward