testValidateMFAWrongSecurityID()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 29
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 18
nc 1
nop 0
dl 0
loc 29
rs 9.6666
c 0
b 0
f 0
1
<?php
2
3
namespace Firesphere\BootstrapMFA\Tests;
4
5
use Firesphere\BootstrapMFA\Authenticators\BootstrapMFAAuthenticator;
6
use Firesphere\BootstrapMFA\Forms\BootstrapMFALoginForm;
7
use Firesphere\BootstrapMFA\Handlers\BootstrapMFALoginHandler;
8
use Firesphere\BootstrapMFA\Tests\Mocks\MockAuthenticator;
9
use SilverStripe\Control\Controller;
10
use SilverStripe\Control\HTTPRequest;
11
use SilverStripe\Control\HTTPResponse;
12
use SilverStripe\Control\Session;
13
use SilverStripe\Core\Injector\Injector;
14
use SilverStripe\Dev\SapphireTest;
15
use SilverStripe\Forms\FormField;
16
use SilverStripe\Security\Member;
17
use SilverStripe\Security\SecurityToken;
18
19
class BootstrapMFALoginHandlerTest extends SapphireTest
20
{
21
    protected static $fixture_file = '../fixtures/member.yml';
22
23
    /**
24
     * @var HTTPRequest
25
     */
26
    protected $request;
27
28
    /**
29
     * @var Member
30
     */
31
    protected $member;
32
33
    /**
34
     * @var BootstrapMFAAuthenticator
35
     */
36
    protected $authenticator;
37
38
    /**
39
     * @var BootstrapMFALoginForm
40
     */
41
    protected $form;
42
43
    /**
44
     * @var BootstrapMFALoginHandler
45
     */
46
    protected $handler;
47
48
    public function testLoginForm()
49
    {
50
        $form = $this->handler->LoginForm();
51
52
        $this->assertInstanceOf(BootstrapMFALoginForm::class, $form);
53
    }
54
55
    public function testDoLogin()
56
    {
57
        $data = [
58
            'Email'    => '[email protected]',
59
            'Password' => 'password1'
60
        ];
61
62
        $request = Controller::curr()->getRequest();
63
64
        $session = new Session(['key' => 'value']);
65
        $session->init($request);
66
67
        $request->setSession($session);
68
69
        $response = $this->handler->doLogin($data, $this->form, $request);
70
71
        $this->assertInstanceOf(HTTPResponse::class, $response);
72
        $this->assertEquals(302, $response->getStatusCode());
73
        $this->assertContains('verify', $response->getHeader('location'));
74
75
        $member = $this->objFromFixture(Member::class, 'member1');
76
77
        $session = $request->getSession();
78
        $expected = [
79
            'MemberID' => $member->ID,
80
            'Data'     =>
81
                [
82
                    'Email'    => '[email protected]',
83
                    'Password' => 'password1',
84
                ]
85
        ];
86
        $this->assertEquals($expected, $session->get(BootstrapMFAAuthenticator::SESSION_KEY));
87
88
        $session = new Session(['key' => 'value']);
89
        $session->init($request);
90
91
        $request->setSession($session);
92
93
        $data = [
94
            'Email'    => '[email protected]',
95
            'Password' => 'password'
96
        ];
97
98
        $this->handler->setRequest($request);
99
        $response = $this->handler->doLogin($data, $this->form, $request);
100
101
        $this->assertEquals(302, $response->getStatusCode());
102
        // We don't have a backURL, so expect to go back to '/login'
103
        $this->assertContains('login', $response->getHeader('location'));
104
    }
105
106
    public function testBackURLLogin()
107
    {
108
        $data = [
109
            'Email'    => '[email protected]',
110
            'Password' => 'password1',
111
            'BackURL'  => '/memberlocation'
112
        ];
113
114
        $request = Controller::curr()->getRequest();
115
116
        $session = new Session(['key' => 'value']);
117
        $session->init($request);
118
119
        $request->setSession($session);
120
121
        $response = $this->handler->doLogin($data, $this->form, $request);
122
123
        $this->assertInstanceOf(HTTPResponse::class, $response);
124
        $this->assertEquals(302, $response->getStatusCode());
125
        $this->assertContains('verify', $response->getHeader('location'));
126
127
        $member = $this->objFromFixture(Member::class, 'member1');
128
129
        $session = $request->getSession();
130
        $expected = [
131
            'MemberID' => $member->ID,
132
            'BackURL'  => '/memberlocation',
133
            'Data'     =>
134
                [
135
                    'Email'    => '[email protected]',
136
                    'Password' => 'password1',
137
                    'BackURL'  => '/memberlocation',
138
                ],
139
        ];
140
        $this->assertEquals($expected, $session->get(BootstrapMFAAuthenticator::SESSION_KEY));
141
    }
142
143
    public function testDoWrongLogin()
144
    {
145
        $data = [
146
            'Email'    => '[email protected]',
147
            'Password' => 'wrongpassword'
148
        ];
149
150
        $response = $this->handler->doLogin($data, $this->form, $this->request);
151
152
        $this->assertInstanceOf(HTTPResponse::class, $response);
153
        $this->assertEquals(302, $response->getStatusCode());
154
        $this->assertContains('login', $response->getHeader('location'));
155
    }
156
157
    public function testSecondFactor()
158
    {
159
        $result = $this->handler->secondFactor($this->request);
160
161
        $this->assertArrayHasKey('Form', $result);
162
        /** @var BootstrapMFALoginForm $form */
163
        $form = $result['Forms'][0];
164
        /** @var FormField $field */
165
        $field = $form->Fields()->dataFieldByName('AuthenticationMethod');
166
        $this->assertEquals(MockAuthenticator::class, $field->Value());
167
    }
168
169
    public function testValidateMFA()
170
    {
171
        $request = Controller::curr()->getRequest();
172
173
        $session = new Session(['key' => 'value']);
174
        $session->init($request);
175
176
        $request->setSession($session);
177
        $data = [
178
            'Email'    => '[email protected]',
179
            'Password' => 'password1',
180
            'BackURL'  => '/memberlocation',
181
        ];
182
183
        $this->handler->doLogin($data, $this->form, $request);
184
185
        $session = $request->getSession();
186
        $data = [
187
            'AuthenticationMethod' => MockAuthenticator::class,
188
            'token'                => 'success',
189
            'SecurityID'           => SecurityToken::inst()->getValue(),
190
            'BackURL'              => '/memberlocation',
191
192
        ];
193
194
        $request = new HTTPRequest('POST', 'Security/default/validateMFA', [], $data);
195
        $request->setSession($session);
196
197
        $this->handler->setRequest($request);
198
199
        $verification = $this->handler->validateMFA($request);
200
201
        $this->assertEquals(302, $verification->getStatusCode());
202
        $this->assertContains('memberlocation', $verification->getHeader('location'));
203
204
        $data = [
205
            'AuthenticationMethod' => MockAuthenticator::class,
206
            'token'                => 'error',
207
            'SecurityID'           => SecurityToken::inst()->getValue()
208
        ];
209
210
        $request = new HTTPRequest('POST', 'Security/default/validateMFA', [], $data);
211
        $request->setSession($session);
212
213
        $this->handler->setRequest($request);
214
215
        $verification = $this->handler->validateMFA($request);
216
217
        $this->assertEquals(302, $verification->getStatusCode());
218
        $this->assertNotContains('memberlocation', $verification->getHeader('location'));
219
        $this->assertContains('login', $verification->getHeader('location'));
220
        $session = $request->getSession();
221
        $this->assertEmpty($session->get(BootstrapMFAAuthenticator::SESSION_KEY));
222
    }
223
224
    /**
225
     * @expectedException \Exception
226
     */
227
    public function testValidateMFAWrongSecurityID()
228
    {
229
        $request = Controller::curr()->getRequest();
230
231
        $session = new Session(['key' => 'value']);
232
        $session->init($request);
233
234
        $request->setSession($session);
235
        $data = [
236
            'Email'    => '[email protected]',
237
            'Password' => 'password1',
238
            'BackURL'  => '/memberlocation',
239
        ];
240
241
        $this->handler->doLogin($data, $this->form, $request);
242
243
        $data = [
244
            'AuthenticationMethod' => MockAuthenticator::class,
245
            'token'                => 'error',
246
            'SecurityID'           => 'thisisnotavalidtoken'
247
        ];
248
249
        $request = new HTTPRequest('POST', 'Security/default/validateMFA', [], $data);
250
        $request->setSession($session);
251
252
        $this->handler->setRequest($request);
253
254
        $this->handler->validateMFA($request);
255
        $this->assertEmpty($session->get(BootstrapMFAAuthenticator::SESSION_KEY));
256
    }
257
258
    /**
259
     * @expectedException \Exception
260
     */
261
    public function testValidateMFAWrongAuthenticator()
262
    {
263
        $request = Controller::curr()->getRequest();
264
265
        $session = new Session(['key' => 'value']);
266
        $session->init($request);
267
268
        $request->setSession($session);
269
        $data = [
270
            'Email'    => '[email protected]',
271
            'Password' => 'password1',
272
            'BackURL'  => '/memberlocation',
273
        ];
274
275
        $this->handler->doLogin($data, $this->form, $request);
276
277
        $data = [
278
            'AuthenticationMethod' => 'nonexisting\\class',
279
            'token'                => 'error',
280
            'SecurityID'           => SecurityToken::inst()->getValue()
281
        ];
282
283
        $request = new HTTPRequest('POST', 'Security/default/validateMFA', [], $data);
284
        $request->setSession($session);
285
286
        $this->handler->setRequest($request);
287
288
        $this->handler->validateMFA($request);
289
        $this->assertEmpty($session->get(BootstrapMFAAuthenticator::SESSION_KEY));
290
    }
291
292
    protected function setUp()
293
    {
294
        parent::setUp();
295
        $this->request = Controller::curr()->getRequest();
296
        $this->member = $this->objFromFixture(Member::class, 'member1');
297
298
        $session = new Session([]);
299
        $session->set(BootstrapMFAAuthenticator::SESSION_KEY . '.MemberID', $this->member->ID);
300
        $this->request->setSession($session);
301
302
        $this->authenticator = Injector::inst()->create(BootstrapMFAAuthenticator::class);
303
        $this->form = Injector::inst()->createWithArgs(
304
            BootstrapMFALoginForm::class,
305
            [Controller::curr(), $this->authenticator, 'test']
306
        );
307
        $this->handler = Injector::inst()->createWithArgs(
308
            BootstrapMFALoginHandler::class,
309
            ['login', $this->authenticator]
310
        );
311
    }
312
}
313