Symfony
sponsored by SensioLabs
Menu
  • About
  • Documentation
  • Screencasts
  • Cloud
  • Certification
  • Community
  • Businesses
  • News
  • Download
  1. Home
  2. Documentation
  3. Testing
  4. How to Simulate HTTP Authentication in a Functional Test
  • Documentation
  • Book
  • Reference
  • Bundles
  • Cloud
Search by Algolia

Table of Contents

  • Using a Faster Authentication Mechanism Only for Tests
  • Creating the Authentication Token

How to Simulate HTTP Authentication in a Functional Test

Edit this page

Warning: You are browsing the documentation for Symfony 3.4, which is no longer maintained.

Read the updated version of this page for Symfony 6.2 (the current stable version).

How to Simulate HTTP Authentication in a Functional Test

Authenticating requests in functional tests can slow down the entire test suite. This could become an issue especially when the tests reproduce the same steps that users follow to authenticate, such as submitting a login form or using OAuth authentication services.

This article explains the two most popular techniques to avoid these issues and create fast tests when using authentication.

Using a Faster Authentication Mechanism Only for Tests

When your application is using a form_login authentication, you can make your tests faster by allowing them to use HTTP authentication. This way your tests authenticate with the simple and fast HTTP Basic method whilst your real users still log in via the normal login form.

The trick is to use the http_basic authentication in your application firewall, but only in the configuration file used by tests:

  • YAML
  • XML
  • PHP
1
2
3
4
5
6
# app/config/config_test.yml
security:
    firewalls:
        # replace 'main' by the name of your own firewall
        main:
            http_basic: ~
1
2
3
4
5
6
7
<!-- app/config/config_test.xml -->
<security:config>
    <!-- replace 'main' by the name of your own firewall -->
    <security:firewall name="main">
        <security:http-basic/>
    </security:firewall>
</security:config>
1
2
3
4
5
6
7
8
9
// app/config/config_test.php
$container->loadFromExtension('security', [
    'firewalls' => [
        // replace 'main' by the name of your own firewall
        'main' => [
            'http_basic' => [],
        ],
    ],
]);

Tests can now authenticate via HTTP passing the username and password as server variables using the second argument of createClient():

1
2
3
4
$client = static::createClient([], [
    'PHP_AUTH_USER' => 'username',
    'PHP_AUTH_PW'   => 'pa$$word',
]);

The username and password can also be passed on a per request basis:

1
2
3
4
$client->request('DELETE', '/post/12', [], [], [
    'PHP_AUTH_USER' => 'username',
    'PHP_AUTH_PW'   => 'pa$$word',
]);

Creating the Authentication Token

If your application uses a more advanced authentication mechanism, you can't use the previous trick, but it's still possible to make tests faster. The trick now is to bypass the authentication process, create the authentication token yourself and store it in the session.

This technique requires some knowledge of the Security component internals, but the following example shows a complete example that you can adapt to your needs:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
// tests/AppBundle/Controller/DefaultControllerTest.php
namespace Tests\AppBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
use Symfony\Component\BrowserKit\Cookie;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;

class DefaultControllerTest extends WebTestCase
{
    private $client = null;

    public function setUp()
    {
        $this->client = static::createClient();
    }

    public function testSecuredHello()
    {
        $this->logIn();
        $crawler = $this->client->request('GET', '/admin');

        $this->assertSame(Response::HTTP_OK, $this->client->getResponse()->getStatusCode());
        $this->assertSame('Admin Dashboard', $crawler->filter('h1')->text());
    }

    private function logIn()
    {
        $session = $this->client->getContainer()->get('session');

        $firewallName = 'secure_area';
        // if you don't define multiple connected firewalls, the context defaults to the firewall name
        // See https://symfony.com/doc/current/reference/configuration/security.html#firewall-context
        $firewallContext = 'secured_area';

        // you may need to use a different token class depending on your application.
        // for example, when using Guard authentication you must instantiate PostAuthenticationGuardToken
        $token = new UsernamePasswordToken('admin', null, $firewallName, ['ROLE_ADMIN']);
        $session->set('_security_'.$firewallContext, serialize($token));
        $session->save();

        $cookie = new Cookie($session->getName(), $session->getId());
        $this->client->getCookieJar()->set($cookie);
    }
}
This work, including the code samples, is licensed under a Creative Commons BY-SA 3.0 license.
We stand with Ukraine.
Version:
Check Code Performance in Dev, Test, Staging & Production

Check Code Performance in Dev, Test, Staging & Production

Peruse our complete Symfony & PHP solutions catalog for your web development needs.

Peruse our complete Symfony & PHP solutions catalog for your web development needs.

↓ Our footer now uses the colors of the Ukrainian flag because Symfony stands with the people of Ukraine.

Avatar of Daniel Werner, a Symfony contributor

Thanks Daniel Werner (@powerdan) for being a Symfony contributor

5 commits • 23 lines changed

View all contributors that help us make Symfony

Become a Symfony contributor

Be an active part of the community and contribute ideas, code and bug fixes. Both experts and newcomers are welcome.

Learn how to contribute

Symfony™ is a trademark of Symfony SAS. All rights reserved.

  • What is Symfony?
    • Symfony at a Glance
    • Symfony Components
    • Case Studies
    • Symfony Releases
    • Security Policy
    • Logo & Screenshots
    • Trademark & Licenses
    • symfony1 Legacy
  • Learn Symfony
    • Symfony Docs
    • Symfony Book
    • Reference
    • Bundles
    • Best Practices
    • Training
    • eLearning Platform
    • Certification
  • Screencasts
    • Learn Symfony
    • Learn PHP
    • Learn JavaScript
    • Learn Drupal
    • Learn RESTful APIs
  • Community
    • SymfonyConnect
    • Support
    • How to be Involved
    • Code of Conduct
    • Events & Meetups
    • Projects using Symfony
    • Downloads Stats
    • Contributors
    • Backers
  • Blog
    • Events & Meetups
    • A week of symfony
    • Case studies
    • Cloud
    • Community
    • Conferences
    • Diversity
    • Documentation
    • Living on the edge
    • Releases
    • Security Advisories
    • SymfonyInsight
    • Twig
    • SensioLabs
  • Services
    • SensioLabs services
    • Train developers
    • Manage your project quality
    • Improve your project performance
    • Host Symfony projects
    Deployed on
Follow Symfony
Search by Algolia