Completed
Push — master ( 696c56...a8c737 )
by André
259:23 queued 232:42
created

SessionTest::removeCsrfHeader()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 11
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 6
c 0
b 0
f 0
nc 3
nop 1
dl 0
loc 11
rs 9.4285
1
<?php
2
/**
3
 * @copyright Copyright (C) eZ Systems AS. All rights reserved.
4
 * @license For full copyright and license information view LICENSE file distributed with this source code.
5
 */
6
namespace eZ\Bundle\EzPublishRestBundle\Tests\Functional;
7
8
use Buzz\Browser;
9
use DOMDocument;
10
use DOMXPath;
11
use Psr\Http\Message\RequestInterface;
12
use Psr\Http\Message\ResponseInterface;
13
use stdClass;
14
15
class SessionTest extends TestCase
16
{
17
    public function setUp()
18
    {
19
        $this->autoLogin = false;
20
        parent::setUp();
21
    }
22
23
    public function testCreateSessionBadCredentials()
24
    {
25
        $request = $this->createAuthenticationHttpRequest('admin', 'bad_password');
26
        $response = $this->sendHttpRequest($request);
27
        self::assertHttpResponseCodeEquals($response, 401);
28
    }
29
30
    /**
31
     * @return \stdClass The login request's response
32
     */
33
    public function testCreateSession()
34
    {
35
        return $this->login();
36
    }
37
38
    /**
39
     * @depends testCreateSession
40
     *
41
     * @param \stdClass $session
42
     */
43
    public function testRefreshSession(stdClass $session)
44
    {
45
        $response = $this->sendHttpRequest($this->createRefreshRequest($session));
46
        self::assertHttpResponseCodeEquals($response, 200);
47
    }
48
49
    public function testRefreshSessionExpired()
50
    {
51
        $session = $this->login();
52
53
        $response = $this->sendHttpRequest($this->createDeleteRequest($session));
54
        self::assertHttpResponseCodeEquals($response, 204);
55
56
        $response = $this->sendHttpRequest($this->createRefreshRequest($session));
57
        self::assertHttpResponseCodeEquals($response, 404);
58
59
        self::assertHttpResponseDeletesSessionCookie($session, $response);
60
    }
61
62 View Code Duplication
    public function testRefreshSessionMissingCsrfToken()
63
    {
64
        $session = $this->login();
65
66
        $refreshRequest = $this
67
            ->createRefreshRequest($session)
68
            ->withoutHeader('X-CSRF-Token');
69
        $response = $this->sendHttpRequest($refreshRequest);
70
        self::assertHttpResponseCodeEquals($response, 401);
71
    }
72
73
    public function testDeleteSession()
74
    {
75
        $session = $this->login();
76
        $response = $this->sendHttpRequest($this->createDeleteRequest($session));
77
        self::assertHttpResponseCodeEquals($response, 204);
78
        self::assertHttpResponseDeletesSessionCookie($session, $response);
79
80
        return $session;
81
    }
82
83
    /**
84
     * CSRF needs to be tested as session handling bypasses the CsrfListener.
85
     */
86 View Code Duplication
    public function testDeleteSessionMissingCsrfToken()
87
    {
88
        $session = $this->login();
89
        $request = $this
90
            ->createDeleteRequest($session)
91
            ->withoutHeader('X-CSRF-Token');
92
        $response = $this->sendHttpRequest($request);
93
        self::assertHttpResponseCodeEquals($response, 401);
94
    }
95
96
    public function testLoginWithExistingFrontendSession()
97
    {
98
        $baseURI = $this->getBaseURI();
99
        $browser = new Browser();
100
101
        $response = $browser->get("{$baseURI}/login");
102
        self::assertHttpResponseCodeEquals($response, 200);
103
104
        $domDocument = new DOMDocument();
105
        // load HTML, suppress error reporting due to buggy Sf toolbar code in dev/behat ENVs
106
        $domDocument->loadHTML($response->getBody(), LIBXML_NOERROR);
107
        $xpath = new DOMXPath($domDocument);
108
109
        $csrfDomElements = $xpath->query("//input[@name='_csrf_token']/@value");
110
        self::assertGreaterThan(0, $csrfDomElements->length);
111
        $csrfTokenValue = $csrfDomElements->item(0)->nodeValue;
112
113
        $loginResponse = $browser->submitForm(
114
            "{$baseURI}/login_check",
115
            [
116
                '_username' => $this->getLoginUsername(),
117
                '_password' => $this->getLoginPassword(),
118
                '_csrf_token' => $csrfTokenValue,
119
            ]
120
        );
121
        self::assertHttpResponseHasHeader($loginResponse, 'set-cookie');
122
123
        $request = $this->createAuthenticationHttpRequest(
124
            $this->getLoginUsername(),
125
            $this->getLoginPassword(),
126
            ['Cookie' => $loginResponse->getHeader('set-cookie')[0]]
127
        );
128
        $response = $this->sendHttpRequest($request);
129
130
        // Since Session is reused, not created, expect 200 instead of 201
131
        self::assertHttpResponseCodeEquals($response, 200);
132
    }
133
134
    /**
135
     * @depends testDeleteSession
136
     */
137
    public function testDeleteSessionExpired($session)
138
    {
139
        $response = $this->sendHttpRequest($this->createDeleteRequest($session));
140
        self::assertHttpResponseCodeEquals($response, 404);
141
        self::assertHttpResponseDeletesSessionCookie($session, $response);
142
    }
143
144
    /**
145
     * @param \stdClass $session
146
     *
147
     * @return \Psr\Http\Message\RequestInterface
148
     */
149 View Code Duplication
    protected function createRefreshRequest(stdClass $session): RequestInterface
150
    {
151
        $request = $this->createHttpRequest(
152
            'POST',
153
            sprintf('/api/ezp/v2/user/sessions/%s/refresh', $session->identifier),
154
            '',
155
            'Session+json',
156
            '',
157
            [
158
                'Cookie' => sprintf('%s=%s', $session->name, $session->identifier),
159
                'X-CSRF-Token' => $session->csrfToken,
160
            ]
161
        );
162
163
        return $request;
164
    }
165
166
    /**
167
     * @param \stdClass $session
168
     *
169
     * @return \Psr\Http\Message\RequestInterface
170
     */
171 View Code Duplication
    protected function createDeleteRequest(stdClass $session): RequestInterface
172
    {
173
        $deleteRequest = $this->createHttpRequest(
174
            'DELETE',
175
            $session->_href,
176
            '',
177
            '',
178
            '',
179
            [
180
                'Cookie' => sprintf('%s=%s', $session->name, $session->identifier),
181
                'X-CSRF-Token' => $session->csrfToken,
182
            ]
183
        );
184
185
        return $deleteRequest;
186
    }
187
188
    private static function assertHttpResponseDeletesSessionCookie($session, ResponseInterface $response)
189
    {
190
        self::assertStringStartsWith("{$session->name}=deleted;", $response->getHeader('set-cookie')[0]);
191
    }
192
}
193