@@ -6,143 +6,12 @@ How to Simulate HTTP Authentication in a Functional Test
66
77.. caution ::
88
9- Starting from Symfony 5.1, the methods explained in this article are no
10- longer recommended to logging in users in your tests. Instead, use
11- :ref: ` the loginUser() method < testing_logging_in_users >` .
9+ Starting from Symfony 5.1, a `` loginUser() `` method was introduced to
10+ ease testing secured applications. See :ref: ` testing_logging_in_users `
11+ for more information about this .
1212
13- Authenticating requests in functional tests can slow down the entire test suite.
14- This could become an issue especially when the tests reproduce the same steps
15- that users follow to authenticate, such as submitting a login form or using
16- OAuth authentication services.
13+ If you are still using an older version of Symfony, view
14+ `previous versions of this article `_ for information on how to simulate
15+ HTTP authentication.
1716
18- This article explains the two most popular techniques to avoid these issues and
19- create fast tests when using authentication.
20-
21- Using a Faster Authentication Mechanism Only for Tests
22- ------------------------------------------------------
23-
24- When your application is using a ``form_login `` authentication, you can make
25- your tests faster by allowing them to use HTTP authentication. This way your
26- tests authenticate with the simple and fast HTTP Basic method whilst your real
27- users still log in via the normal login form.
28-
29- The trick is to use the ``http_basic `` authentication in your application
30- firewall, but only in the configuration file used by tests:
31-
32- .. configuration-block ::
33-
34- .. code-block :: yaml
35-
36- # config/packages/test/security.yaml
37- security :
38- firewalls :
39- # replace 'main' by the name of your own firewall
40- main :
41- http_basic : ~
42-
43- .. code-block :: xml
44-
45- <!-- config/packages/test/security.xml -->
46- <?xml version =" 1.0" encoding =" UTF-8" ?>
47- <container xmlns =" http://symfony.com/schema/dic/services"
48- xmlns : xsi =" http://www.w3.org/2001/XMLSchema-instance"
49- xmlns : security =" http://symfony.com/schema/dic/security"
50- xsi : schemaLocation =" http://symfony.com/schema/dic/security
51- https://symfony.com/schema/dic/security/security-1.0.xsd
52- http://symfony.com/schema/dic/security
53- https://symfony.com/schema/dic/security/security-1.0.xsd" >
54-
55- <security : config >
56- <!-- replace 'main' by the name of your own firewall -->
57- <security : firewall name =" main" >
58- <security : http-basic />
59- </security : firewall >
60- </security : config >
61-
62- .. code-block :: php
63-
64- // config/packages/test/security.php
65- $container->loadFromExtension('security', [
66- 'firewalls' => [
67- // replace 'main' by the name of your own firewall
68- 'main' => [
69- 'http_basic' => [],
70- ],
71- ],
72- ]);
73-
74- Tests can now authenticate via HTTP passing the username and password as server
75- variables using the second argument of ``createClient() ``::
76-
77- $client = static::createClient([], [
78- 'PHP_AUTH_USER' => 'username',
79- 'PHP_AUTH_PW' => 'pa$$word',
80- ]);
81-
82- The username and password can also be passed on a per request basis::
83-
84- $client->request('DELETE', '/post/12', [], [], [
85- 'PHP_AUTH_USER' => 'username',
86- 'PHP_AUTH_PW' => 'pa$$word',
87- ]);
88-
89- Creating the Authentication Token
90- ---------------------------------
91-
92- If your application uses a more advanced authentication mechanism, you can't
93- use the previous trick, but it's still possible to make tests faster. The trick
94- now is to bypass the authentication process, create the *authentication token *
95- yourself and store it in the session.
96-
97- This technique requires some knowledge of the Security component internals,
98- but the following example shows a complete example that you can adapt to your
99- needs::
100-
101- // tests/Controller/DefaultControllerTest.php
102- namespace App\Tests\Controller;
103-
104- use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
105- use Symfony\Component\BrowserKit\Cookie;
106- use Symfony\Component\HttpFoundation\Response;
107- use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
108-
109- class DefaultControllerTest extends WebTestCase
110- {
111- private $client = null;
112-
113- public function setUp()
114- {
115- $this->client = static::createClient();
116- }
117-
118- public function testSecuredHello()
119- {
120- $this->logIn();
121- $crawler = $this->client->request('GET', '/admin');
122-
123- $this->assertSame(Response::HTTP_OK, $this->client->getResponse()->getStatusCode());
124- $this->assertSame('Admin Dashboard', $crawler->filter('h1')->text());
125- }
126-
127- private function logIn()
128- {
129- $session = self::$container->get('session');
130-
131- // somehow fetch the user (e.g. using the user repository)
132- $user = ...;
133-
134- $firewallName = 'secure_area';
135- // if you don't define multiple connected firewalls, the context defaults to the firewall name
136- // See https://symfony.com/doc/current/reference/configuration/security.html#firewall-context
137- $firewallContext = 'secured_area';
138-
139- // you may need to use a different token class depending on your application.
140- // for example, when using Guard authentication you must instantiate PostAuthenticationGuardToken
141- $token = new UsernamePasswordToken($user, null, $firewallName, $user->getRoles());
142- $session->set('_security_'.$firewallContext, serialize($token));
143- $session->save();
144-
145- $cookie = new Cookie($session->getName(), $session->getId());
146- $this->client->getCookieJar()->set($cookie);
147- }
148- }
17+ .. _previous versions of this article : https://symfony.com/doc/5.0/testing/http_authentication.html
0 commit comments