I am trying to configure remember me feature of symfony using their default mechanism as described here; but couldn't make it work.
Cookie named REMEMBERME is created, but is set to deleted and its expire date is 1970. This is why I suppose remember me function is not working. However, when I use (always_remember_me: true) in security.yml, the code works nicely but it doesn't suite my purpose. Using (always_remember_me: true) even if user doesn't check REMEMBER ME checkbox in UI the cookie gets created.
Any help is highly appreciated
I am using the version 2.3.7
This is my complete security.yml file:
security:
firewalls:
main:
pattern: ^/
anonymous: ~
remember_me:
key: "%secret%"
lifetime: 31536000 # a year
domain: ~
path: /
remember_me_parameter: _remember_me
#always_remember_me: true
form_login:
login_path: _my_login
check_path: _my_login_check
always_use_default_target_path: true
default_target_path: /out/homepage
remember_me: true
logout:
path: _my_logout
target: _my_login
access_control:
- { path: ^/admin, roles: ROLE_ADMIN }
- { path: ^/login$, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/, roles: IS_AUTHENTICATED_REMEMBERED }
providers:
chain_provider:
chain:
providers: [in_memory, user_db]
in_memory:
memory:
users:
user: { password: user, roles: 'ROLE_USER' }
admin: { password: admin, roles: ['ROLE_ADMIN', 'ROLE_USER'] }
user_db:
entity: {class: ProjectName\StoreBundle\Entity\User, property: username}
encoders:
ProjectName\StoreBundle\Entity\User:
algorithm: sha1
iterations: 1
encode_as_base64: false
Symfony\Component\Security\Core\User\User: plaintext
LoginController.php
class LoginController extends Controller
{
/**
* #Route("/login", name="_my_login")
* #Template()
*/
public function loginAction()
{
$request = $this->getRequest();
$session = $request->getSession();
// get the login error if there is one
if ($request->attributes->has(SecurityContext::AUTHENTICATION_ERROR)) {
$error = $request->attributes->get(
SecurityContext::AUTHENTICATION_ERROR
);
} else {
$error = $session->get(SecurityContext::AUTHENTICATION_ERROR);
$session->remove(SecurityContext::AUTHENTICATION_ERROR);
}
return array(
// last username entered by the user
'last_username' => $session->get(SecurityContext::LAST_USERNAME),
'error' => $error,
);
}
/**
* #Route("/login_check", name="_my_login_check")
*/
public function loginCheckAction()
{
}
I added the value attribute inside the input tag. After removing it, it worked for now. :)
<input type="checkbox" id="remember_me" name="_remember_me" checked /> Remember me
I suppose the checkbox is named incorrectly. It should have the 'name' attribute set to '_remember_me' to make the magic happen. Can you post the content of the form template?
Related
If I call / and am not logged in, I get the error ERR_TOO_MANY_REDIRECTS.
Actually, I should be redirected to the login page. Where’s the mistake?
security.yaml:
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
main:
lazy: true
provider: app_user_provider
logout:
path: app_logout
form_login:
login_path: app_login
check_path: app_login
access_control:
- { path: ^/login, role: IS_AUTHENTICATED_ANONYMOUSLY }
role_hierarchy:
ROLE_USER: ROLE_USER
ROLE_ADMIN: [ROLE_USER, ROLE_ALLOWED_TO_SWITCH]
Controller:
/**
* #Route("/{id}",defaults={"id" = null} , name="app_dashboard")
*/
public function index(PositiveTimeRepository $positiveTimeRepository, $id): Response
{
return $this->render('dashboard/index.html.twig', [
'positiveData' => $positiveTimeRepository->findBy([
'user' => $this->getUser()]),
'issetGetID' => $id
]);
}
SecurityController:
/**
* #Route("/login", name="app_login")
*/
public function login(AuthenticationUtils $authenticationUtils): Response
{
$error = $authenticationUtils->getLastAuthenticationError();
$lastUsername = $authenticationUtils->getLastUsername();
return $this->render('login/login.html.twig', [
'last_username' => $lastUsername,
'error' => $error
]);
}
I updated my controllers and security.yaml
You don’t have to check for the roles in your controller yourself the security package does that with the firewall you defined, but you would have to define your login url:
firewalls:
main:
# ...
form_login:
# "login" is the name of the route created previously
login_path: login
check_path: login
I am trying to use multiple authenticators (for each user role). They were working fine until the last one, which redirects unauthenticated users to URL /dashboard/ to login, but requests to /dashboard are thrown AccessDeniedHttpException:
This is my security.yaml file, which have all the firewalls:
security:
encoders:
App\Entity\User:
algorithm: sha512
providers:
app_user_provider:
entity:
class: App\Entity\User
property: email
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
main:
pattern: ^/admin/
anonymous: lazy
provider: app_user_provider
guard:
authenticators:
- App\Security\AdminAuthenticator
logout:
path: admin_logout
expert:
pattern: ^/dashboard/
anonymous: lazy
provider: app_user_provider
guard:
authenticators:
- App\Security\ExpertAuthenticator
logout:
path: expert_logout
user:
anonymous: lazy
provider: app_user_provider
guard:
authenticators:
- App\Security\UserAuthenticator
logout:
path: user_logout
access_control:
- { path: ^/$, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/admin/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/admin, roles: ROLE_ADMIN }
- { path: ^/ask, roles: ROLE_USER }
- { path: ^/dashboard/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/dashboard, roles: ROLE_EXPERT }
I think it is not necessary to paste here the authenticator since it is the Symfony 5 make:auth maker command default which I copied and pasted for all the three authenticators while changing only public const LOGIN_ROUTE = 'user_login'; and onAuthenticationSuccess() function's redirect response path.
I also used the default SecurityController:
namespace App\Controller\Expert;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Security\Http\Authentication\AuthenticationUtils;
/**
* Class SecurityController
* #package App\Controller\Expert
* #Route("/dashboard")
*/
class SecurityController extends AbstractController
{
/**
* #Route("/login", name="expert_login")
*/
public function login(AuthenticationUtils $authenticationUtils): Response
{
if ($this->getUser()) {
return $this->redirectToRoute('expert_index');
}
// get the login error if there is one
$error = $authenticationUtils->getLastAuthenticationError();
// last username entered by the user
$lastUsername = $authenticationUtils->getLastUsername();
return $this->render('expert/security/login.html.twig', ['last_username' => $lastUsername, 'error' => $error]);
}
/**
* #Route("/logout", name="expert_logout")
*/
public function logout()
{
$this->addFlash('success', 'Session closed');
return $this->redirectToRoute('expert_index');
}
}
Whenever I access to /admin, /admin/whatever or /ask, /ask/whatever I am redirected to its respective login form (/admin/login and /ask/dashboard).
I can access directly to /dashboard/login if I am not logged from another authenticator or if I am logged with ROLE_EXPERT. If not, I am getting the mentioned exception.
Well, do you see what is going on?
You should move - { path: ^/$, roles: IS_AUTHENTICATED_ANONYMOUSLY } as last access_control entry.
That's because Symfony parses it as you're writing it (think about it like it's a FIFO queue) and, as / could be accessed in anonymous way, associated token will be anonymous (it won't try to read from session or whatever).
I made the Login-Action Tutorial from the symfony site: http://symfony.com/doc/current/cookbook/security/form_login_setup.html
When I do my Login in the form, I get the following error:
The controller must return a response (null given). Did you forget to add a return statement somewhere in your controller?
Here is my security.yml
security:
encoders:
Symfony\Component\Security\Core\User\User: plaintext
role_hierarchy:
ROLE_USER: ROLE_USER
ROLE_ADMIN: ROLE_USER
ROLE_SUPER_ADMIN: [ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH]
providers:
in_memory:
memory:
users:
user: { password: userpass, roles: [ 'ROLE_USER' ] }
admin: { password: adminpass, roles: [ 'ROLE_ADMIN' ] }
access_denied_url: no_access
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
login:
pattern: ^/login
security: false
secured_area:
pattern: ^/
anonymous: ~
form_login:
login_path: /login
check_path: /login_check
default_target_path: home
logout:
path: /logout
target: /login
access_control:
- { path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY, requires_channel: https }
- { path: ^/, roles: ROLE_USER }
My Security Controller:
class SecurityController extends Controller
{
/**
* #Route("/login", name="login_route")
* #Template()
*/
public function loginAction()
{
$authenticationUtils = $this->get('security.authentication_utils');
// get the login error if there is one
$error = $authenticationUtils->getLastAuthenticationError();
// last username entered by the user
$lastUsername = $authenticationUtils->getLastUsername();
return $this->render(
'TripAdminBundle:Main:login.html.twig',
array(
// last username entered by the user
'last_username' => $lastUsername,
'error' => $error,
)
);
}
/**
* #Route("/login_check", name="login_check")
*/
public function loginCheckAction()
{
// this controller will not be executed,
// as the route is handled by the Security system
}
}
The redirect after Click on the submit Button is to login_check but there is no code in it because symfony says: the route is handled by the Security system
Bute I get this error. Can someone help me with this please?
return array directly , don't use render method and twig file name .
return array(
// last username entered by the user
'last_username' => $lastUsername,
'error' => $error,
)
);
I use UserBundle and HWIO for social network, but If user have not socials I create custom registration, when user have email and password for email I try authentication but have many error last error:
Error: User account is disabled.
I don’t know how to be tune service.yml and HWIO still work and standart authentication help please
And know not working enter with HWIO:
Unable to find the controller for path "/login/check-vkontakte". The route is wrongly configured.
with this work fine security:
security:
encoders:
FOS\UserBundle\Model\UserInterface: sha512
role_hierarchy:
ROLE_ADMIN: ROLE_USER
ROLE_SUPER_ADMIN: ROLE_ADMIN
providers:
fos_userbundle:
id: fos_user.user_provider.username
my_custom_hwi_provider:
id: app.provider.user_provider
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
main:
pattern: ^/
form_login:
provider: fos_userbundle
csrf_provider: form.csrf_provider
oauth:
resource_owners:
facebook: "/login/check-facebook"
vkontakte: "/login/check-vkontakte"
login_path: /login
failure_path: /login
oauth_user_provider:
#this is my custom user provider, created from FOSUBUserProvider - will manage the
#automatic user registration on your site, with data from the provider (facebook. google, etc.)
service: app.provider.user_provider
logout: true
anonymous: true
login:
pattern: ^/login$
security: false
remember_me:
key: "%secret%"
lifetime: 60 # 365 days in seconds
path: /
domain: ~ # Defaults to the current domain from $_SERVER
access_control:
- { path: ^/login$, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/register, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/resetting, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/admin/, role: ROLE_ADMIN }
this my security
security:
encoders:
FOS\UserBundle\Model\UserInterface: sha512
PillsBundle\Entity\User:
algorithm: sha1
encode_as_base64: false
iterations: 1
Symfony\Component\Security\Core\User\User: plaintext
role_hierarchy:
ROLE_ADMIN: ROLE_USER
ROLE_SUPER_ADMIN: ROLE_ADMIN
providers:
fos_userbundle:
id: fos_user.user_provider.username
my_custom_hwi_provider:
id: app.provider.user_provider
chain_provider:
chain:
providers: [user_db, in_memory]
user_db:
entity: { class: UserBundle\Entity\User, property: email }
in_memory:
memory:
users:
admin_tyty: { password: adminpass_tyty, roles: [ 'ROLE_ADMIN' ] }
firewalls:
admin_secured_area:
pattern: /(.*)
anonymous: ~
form_login:
provider: chain_provider
login_path: /auth/login
check_path: /auth/login_check
always_use_default_target_path: true
default_target_path: /?r=db
logout:
path: /auth/logout
target: /
invalidate_session: false
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
main:
pattern: ^/
form_login:
provider: fos_userbundle
#csrf_provider: form.csrf_provider
oauth:
resource_owners:
facebook: "/login/check-facebook"
vkontakte: "/login/check-vkontakte"
login_path: /login
failure_path: /login
oauth_user_provider:
#this is my custom user provider, created from FOSUBUserProvider - will manage the
#automatic user registration on your site, with data from the provider (facebook. google, etc.)
service: app.provider.user_provider
logout: true
anonymous: true
login:
pattern: ^/login$
security: false
remember_me:
key: "%secret%"
lifetime: 60 # 365 days in seconds
path: /
domain: ~ # Defaults to the current domain from $_SERVER
access_control:
- { path: ^/login$, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/register, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/resetting, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/admin/, role: ROLE_ADMIN }
and my SecurityController Controller
/**
* #Route("/auth")
*/
class SecurityController extends Controller
{
/**
* #Route("/login", name="login_route")
* #Template()
*/
public function loginAction()
{
$request = $this->getRequest();
$session = $request->getSession();
$securityContext = $this->container->get('security.context');
if ( $securityContext->isGranted('IS_AUTHENTICATED_FULLY') ) {
return $this->redirect($this->generateUrl('get_all_posts'));
}
if ($request->attributes->has(SecurityContext::AUTHENTICATION_ERROR)) {
$error = $request->attributes->get(SecurityContext::AUTHENTICATION_ERROR);
} else {
$error = $session->get(SecurityContext::AUTHENTICATION_ERROR);
$session->remove(SecurityContext::AUTHENTICATION_ERROR);
}
return array(
'_last' => $session->get(SecurityContext::LAST_USERNAME),
'error' => $error,
);
}
If you have override the registration controller then Just enable the user in FOSUserBundle > RegistrationController class
If not then have a look in to this doc.
http://symfony.com/doc/current/bundles/FOSUserBundle/overriding_controllers.html
RegistrationController extends BaseController
{
public function registerAction(Request $request)
{
/** #var $formFactory \FOS\UserBundle\Form\Factory\FactoryInterface */
$formFactory = $this->get('fos_user.registration.form.factory');
/** #var $userManager \FOS\UserBundle\Model\UserManagerInterface */
$userManager = $this->get('fos_user.user_manager');
/** #var $dispatcher \Symfony\Component\EventDispatcher\EventDispatcherInterface */
$dispatcher = $this->get('event_dispatcher');
$user = $userManager->createUser();
$user->setEnabled(true);
}
After login, I want to access to the same page. But I have a redirect loop of death
security.yml
login:
pattern: ^/admin/login
security: false
anonymous: true
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
secured_area:
pattern: ^/admin
form_login:
check_path: _login_check
login_path: _admin_login
default_target_path: _admin_dashboard
always_use_default_target_path: true
logout:
path: _admin_logout
target: _admin_login
anonymous: ~
access_control:
- { path: ^/admin/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/admin, roles: [ROLE_USER, ROLE_ADMIN] }
routing.yml :
_admin_secured:
resource: "#TestBackBundle/Controller/SecuredController.php"
type: annotation
_admin_home:
resource: "#TestBackBundle/Controller/DashboardController.php"
type: annotation
DashboardController.php :
...
/**
* #Route("/admin/dashboard")
*/
class DashboardController extends Controller
{
/**
* #Route("/", name="_admin_dashboard")
* #Template()
*/
public function indexAction()
{
return array();
}
}
and SecuredController.php :
...
/**
* #Route("/admin")
*/
class SecuredController extends Controller
{
/**
* #Route("/login", name="_admin_login")
* #Template()
*/
public function loginAction(Request $request)
{
if ($request->attributes->has(SecurityContext::AUTHENTICATION_ERROR)) {
$error = $request->attributes->get(SecurityContext::AUTHENTICATION_ERROR);
} else {
$error = $request->getSession()->get(SecurityContext::AUTHENTICATION_ERROR);
}
return array(
'last_username' => $request->getSession()->get(SecurityContext::LAST_USERNAME),
'error' => $error,
);
}
/**
* #Route("/login_check", name="_login_check")
*/
public function securityCheckAction()
{
// The security layer will intercept this request
}
/**
* #Route("/logout", name="_admin_logout")
*/
public function logoutAction()
{
// The security layer will intercept this request
}
}
What I did wrong ?
This worked for me, the main difference is that your secured area is ^/admin, and mine it is ^/
There is a lot of redundant code, but I was tired to figure to make it works, and when it worked I just don't want to touch it anymore
(that it is in my case, I wanted to protect ^/ but anonymously access to /login, you are protecting /admin but want to access /admin/login)
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
free:
pattern: ^/$
security: false
free2:
pattern: ^/login$
security: false
secured_area:
pattern: ^/
form_login:
login_path: login
check_path: login_check
always_use_default_target_path: true
default_target_path: /borsa/ofertes
logout:
path: /logout
target: /
login:
pattern: ^/
security: false
anonymous: ~
access_control:
- { path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY}
#- { path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY, requires_channel: https }
- { path: ^/admin, roles: ROLE_ADMIN }
Add below section to your firewall before secured_area
my_login:
pattern: ^/admin/login$
security: false
anonymous: true
You need to make the login page security off before defining the secured area
You also need to return a response not just array in your indexAction
/**
* #Route("/admin")
*/
class DashboardController extends Controller
{
/**
* #Route("/dashboard", name="_admin_dashboard")
* #Template()
*/
public function indexAction()
{
$response = new Response();
$response->setContent(json_encode(array());
return $response;
}
}
Check the following link which has same issue (Google Group Question)
I think you need to use the full path for login_check and login_path in your security.yml
check_path: ^/admin/login_check
login_path: ^/admin/login
I have found the issue : Should be added $ after login path in login firewall and access_control:
login:
pattern: ^/admin/login$
security: false
anonymous: true
access_control:
- { path: ^/admin/login$, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/admin, roles: [ROLE_USER, ROLE_ADMIN] }
I hope this will help other people !