Create symfony2, remember me cookie manually (FOSUserBundle)

Can someone explain how you can manually create a cookie to remember me in the controller?

I want users to remain on the system after they click the "register" button, without having to log in with their credentials.

I tried to create a cookie manually, but I assume that the cookie value is incorrect, and therefore the โ€œremember meโ€ function does not work. A cookie with the correct name is set. I checked it out.

Remember that functionality works as expected; when using normal, log in with user credentials.

security.yml security.yml remember me

security: firewalls: main: remember_me: lifetime: 86400 domain: ~ path: / key: myKey 

This is what I have now, even if the cookie is set, it does not work.

 $um = $this->get('fos_user.user_manager'); $member = $um->createUser(); โ€ฆ Form stuff with bindRequest etc. $um->updatePassword($member); $um->updateUser($member); $providerKey = $this->container->getParameter('fos_user.firewall_name'); $securityKey = 'myKey'; $token = new RememberMeToken($member, $providerKey, $securityKey, $member->getRoles()); $this->container->get('security.context')->setToken($token); $redirectResponse = new RedirectResponse($url); $redirectResponse->headers->setCookie( new \Symfony\Component\HttpFoundation\Cookie( 'REMEMBERME', base64_encode(implode(':', array($member->getUsername(), $member->getPassword()))), time() + 60*60*24 ) ); return $redirectResponse; 

Update:

I also tried working with the PersistentTokenBasedRememberMeServices class with reflection, but it does not work. cookie is set, but it does not work

 $token = $this->container->get('security.context')->getToken(); $providerKey = $this->container->getParameter('fos_user.firewall_name'); $securityKey = 'myKey'; $persistenService = new PersistentTokenBasedRememberMeServices(array($um), $providerKey, $securityKey, array('path' => '/', 'name' => 'REMEMBERME', 'domain' => null, 'secure' => false, 'httponly' => true, 'lifetime' => 86400)); $persistenService->setTokenProvider(new InMemoryTokenProvider()); $method = new \ReflectionMethod('Symfony\Component\Security\Http\RememberMe\PersistentTokenBasedRememberMeServices', 'onLoginSuccess'); $method->setAccessible(true); $method->invoke($persistenService, $request, $redirectResponse, $token); 

I am using Symfony v2.0.5 and FOSUserBundle 1.0

UPDATE 2:

I tried the third way. Same as above, but without reflection:

 $token = $this->container->get('security.context')->getToken(); $providerKey = $this->container->getParameter('fos_user.firewall_name'); $securityKey = 'myKey'; $persistenService = new PersistentTokenBasedRememberMeServices(array($um), $providerKey, $securityKey, array('path' => '/', 'name' => 'REMEMBERME', 'domain' => null, 'secure' => false, 'httponly' => true, 'lifetime' => 31536000, 'always_remember_me' => true, 'remember_me_parameter' => '_remember_me')); $persistenService->setTokenProvider(new InMemoryTokenProvider()); $persistenService->loginSuccess($request, $redirectResponse, $token); 
+8
symfony remember-me fosuserbundle
source share
4 answers

If you set the memme cookie directly, you should use the following format:

 base64_encode(<classname>:base64_encode(<username>):<expiry-timestamp>:<hash>) 

where the hash will be:

 sha256(<classname> . <username> . <expiry-timestamp> . <password> . <key>) 

The key is the key entered into your security (.xml / .yml) in the remember_me section.

This is taken from the processAutoLoginCookie() method in the Symfony / Component / Security / Http / RememberMe / TokenBasedRememberMeService.php file .

All this is done with the generateCookieValue() method in the same class.

However, I would not recommend using this directly, but try to find out if you can call the TokenBasedRememberMeService::onLoginSuccess() method, which sets this cookie for you to make the code more reliable and portable.

+10
source share

Here is how I did it. I do not use FOSUserBundle, and I use the User Entity User Provider, but this should be trivial to adapt to your needs. Here is a general solution:

 // after registration and persisting the user object to DB, I'm logging the user in automatically $token = new UsernamePasswordToken($user, null, 'main', $user->getRoles()); // but you can also get the token directly, if you're user is already logged in $token = $this->container->get('security.context')->getToken(); // write cookie for persistent session storing $providerKey = 'main'; // defined in security.yml $securityKey = 'MySecret'; // defined in security.yml $userProvider = new EntityUserProvider($this->getDoctrine()->getEntityManager(), 'MyCompany\MyBundle\Entity\User', 'username'); $rememberMeService = new TokenBasedRememberMeServices(array($userProvider), $securityKey, $providerKey, array( 'path' => '/', 'name' => 'MyRememberMeCookie', 'domain' => null, 'secure' => false, 'httponly' => true, 'lifetime' => 1209600, // 14 days 'always_remember_me' => true, 'remember_me_parameter' => '_remember_me') ); $response = new Response(); $rememberMeService->loginSuccess($request, $response, $token); // further modify the response // ........ return $response; 

Just remember that you need to set the always_remember_me option to true (for example, I did it in the code above) or somehow in the $ _POST parameters, otherwise the isRememberMeRequested of AbstractRememberMeServices method will return false and the cookie will not be saved.

You were pretty close to making the right decision, though :) What you did wrong (in the third attempt) was that you changed the order of the parameters here:

 $persistenService = new PersistentTokenBasedRememberMeServices(array($um), $providerKey, $securityKey, array('path' => '/', 'name' => 'REMEMBERME', 'domain' => null, 'secure' => false, 'httponly' => true, 'lifetime' => 31536000, 'always_remember_me' => true, 'remember_me_parameter' => '_remember_me')); 

Take a look at __construct() in AbstractRememberMeServices.php . You should pass $securityKey as the second argument and $providerKey as the third argument, and not vice versa, as you mistakenly;)

I do not yet know how to get the parameters from security.yml directly in the controller so as not to duplicate it. Using $this->container->getParameter() , I can get the parameters stored in parameters in the config.yml file, but not the ones above in the configuration tree. Any thoughts on this?

+12
source share

For me, the easiest solution was the BaseTokenBasedRememberMeServices extension and the ability to handle

 namespace AppBundke\Security\Http; use Symfony\Component\HttpFoundation\Cookie; use Symfony\Component\Security\Http\RememberMe\TokenBasedRememberMeServices as BaseTokenBasedRememberMeServices; class TokenBasedRememberMeServices extends BaseTokenBasedRememberMeServices { protected $options_new = array('name' => 'REMEMBERME', 'domain' => null, 'path' => '/'); public function __construct($userProvider, $secret, $providerKey, array $options = array(), LoggerInterface $logger = null) { return parent::__construct(array($userProvider), $secret, $providerKey, array_merge($this->options_new, $options)); } public function generateCookie($user, $username, $expires, $password) { $cookie = new Cookie( $this->options['name'], parent::generateCookieValue(get_class($user), $username, $expires, $password), $expires, $this->options['path'], $this->options['domain'], $this->options['secure'], $this->options['httponly'] ); return $cookie; } } 

and in the controller;

 $user = $this->getUser(); $providerKey = $this->getParameter('fos_user.firewall_name'); $secret = $this->getParameter('secret'); $cookie_life_time = $this->getParameter('cookie_life_time'); $remember_me_service = new TokenBasedRememberMeServices($user, $secret, $providerKey ); $remember_me_cookie = $remember_me_service->generateCookie($user, $user->getUsername(),(time() + $cookie_life_time), $user->getPassword()); 

then the response cookie will set to $ remember_me_cookie

I hope this works with you.

0
source share

I had the same problem when I tried to set a REMEMBERME cookie on a user after connecting with a token using Guard Authentication .

In this situation, I did not have a Response object to be able to use $ response-> headers-> setCookie (), and it needs to use setcookie (). And in this situation, creating a RedirectResponse is not suitable.

It needs to be refactored, but I'm sending the original procedure on which I based my service

 $expires = time() + 2628000; $hash = hash_hmac( 'sha256', get_class($user).$user->getUsername().$expires.$user->getPassword(), 'secret in parameters.yml' ); $value = base64_encode(implode(':', [get_class($user), base64_encode($user->getUsername()), $expires, $hash])); setcookie( 'REMEMBERME', $value, $expires, '/', 'host', 'ssl boolean', true ); 
0
source share

All Articles