4

As described in answer of How to use an authenticated user in a Symfony2 functional test? there is a simple solution with Symfony\Component\Security\Core\User\User.

But I have different User class (some necessary additional fields) and I want to authenticate user with it.

How can I setup providders for it?

Community
  • 1
  • 1
Dmitry
  • 7,457
  • 12
  • 57
  • 83
  • 2
    Take a look at this new [cookbook article](http://symfony.com/doc/current/cookbook/testing/simulating_authentication.html) – Emii Khaos May 14 '13 at 10:12

4 Answers4

10

This is a tricky issue discussed here: https://github.com/symfony/symfony/issues/5228 Though it is 2.1, it still happen to me using 2.2.

Here is how I do the test authentication:

// Create a new client to browse the application
$client = static::createClient();
$client->getCookieJar()->set(new Cookie(session_name(), true));

// dummy call to bypass the hasPreviousSession check
$crawler = $client->request('GET', '/');

$em = $client->getContainer()->get('doctrine')->getEntityManager();
$user = $em->getRepository('MyOwnBundle:User')->findOneByUsername('username');

$token = new UsernamePasswordToken($user, $user->getPassword(), 'main_firewall', $user->getRoles());
self::$kernel->getContainer()->get('security.context')->setToken($token);

$session = $client->getContainer()->get('session');
$session->set('_security_' . 'main_firewall', serialize($token));
$session->save();

$crawler = $client->request('GET', '/login/required/page/');

$this->assertTrue(200 === $client->getResponse()->getStatusCode());

// perform tests in the /login/required/page here..

Oh, and the use statements:

use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
use Symfony\Bundle\FrameworkBundle\Client;
use Symfony\Component\BrowserKit\Cookie;
ihsan
  • 2,279
  • 20
  • 36
  • Actually we use LDAP, not cookies. I found different solution, I'll describe it now in the answer. – Dmitry May 14 '13 at 19:34
  • @DmitryR I don't know about LDAP, and you didn't state it in the question. Do you need to make a dummy call just like session based use? – ihsan May 15 '13 at 01:03
  • 3
    awesome. just remind that in Symfony 3.0.6 the security.context should be security.token_storage ;) –  May 12 '16 at 11:28
1

are u using a form login ? or http security?

when using the form login what i do in my tests is i just simulate a user logging in via the login form ...

    /**
     * test of superuser ingelogd geraakt
     */
    public function testSuperAdminLogin()
    {
        $crawler = $this->client->request('GET', '/login');
        $form = $crawler->selectButton('Sign In')->form();
        $user = $this->em->getRepository('NonoAcademyBundle:User')
            ->findOneByUsername('superadmin');
        $crawler = $this->client
            ->submit($form,
                array('_username' => $user->getUsername(),
                        '_password' => $user->getPassword()));

        $this->assertTrue($this->client->getResponse()->isSuccessful());

        $this
            ->assertRegExp('/\/admin\/notifications/',
                $this->client->getResponse()->getContent());
    }

then just use that client and crawler, as they will act as the logged in user. Hope this helps you

Sam Janssens
  • 1,491
  • 1
  • 12
  • 30
  • Does it mean you store password in plain text? – Wojciech Jasiński Dec 29 '15 at 09:33
  • in this particular case we did, since this particular client actually wanted to be able to re-send existing password, via the pass-forgotten process, instead of starting a resetting procedure, where he is forced to create a new one (we advised him not go go this route, and explained why), but thats what they wanted ... – Sam Janssens Dec 30 '15 at 11:28
1

You might also find these helpful especially if you are using a form login

private function doLogin()
{
    $this->client = static::createClient();
    $username = 'your-username';
    $password = 'your-password';

    $crawler = $this->client->request('GET', '/login');
    $form = $crawler->filter('your-submit-button-classname')->form();

    $crawler = $this->client
        ->submit($form,
            array(
                '_username' => $username,
                '_password' => $password,
            )
       );
}
Olotin Temitope
  • 419
  • 6
  • 13
0

I found a solution.

First we have to create new user provider: FakeUserProvider as described here.
It should implement UserProviderInterface.

Its loadUserByUsername should create necessary user object.

Dmitry
  • 7,457
  • 12
  • 57
  • 83