Passed
Branch master (1ad6c0)
by Simon
03:19
created

testSupportedServices()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 0
dl 0
loc 6
rs 9.4285
c 0
b 0
f 0
1
<?php
2
3
namespace Firesphere\YubiAuth\Tests;
4
5
use Firesphere\BootstrapMFA\Handlers\BootstrapMFALoginHandler;
0 ignored issues
show
Bug introduced by
The type Firesphere\BootstrapMFA\...ootstrapMFALoginHandler was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
6
use Firesphere\YubiAuth\Authenticators\YubikeyMemberAuthenticator;
7
use Firesphere\YubiAuth\Forms\YubikeyForm;
8
use Firesphere\YubiAuth\Forms\YubikeyLoginForm;
9
use Firesphere\YubiAuth\Handlers\YubikeyLoginHandler;
10
use Firesphere\YubiAuth\Providers\YubikeyAuthProvider;
11
use SilverStripe\Control\HTTPRequest;
12
use SilverStripe\Control\Session;
13
use SilverStripe\Core\Injector\Injector;
14
use SilverStripe\Dev\SapphireTest;
15
use SilverStripe\Security\IdentityStore;
16
use SilverStripe\Security\Member;
17
use SilverStripe\Security\Security;
18
use Yubikey\Validate;
19
20
class YubikeyMemberAuthenticatorTest extends SapphireTest
21
{
22
    protected static $fixture_file = '../fixtures/Member.yml';
23
24
    /**
25
     * @var YubikeyLoginHandler
26
     */
27
    protected $handler;
28
    /**
29
     * @var YubikeyLoginForm
30
     */
31
    protected $form;
32
33
    /**
34
     * @var YubikeyMemberAuthenticator
35
     */
36
    protected $authenticator;
37
38
    protected $request;
39
40
    public function setUp()
41
    {
42
        parent::setUp();
43
        $this->objFromFixture(Member::class, 'admin');
44
        $validator = new MockYubiValidate('apikey', '1234');
45
        $this->authenticator = Injector::inst()->get(YubikeyMemberAuthenticator::class);
46
        $this->handler = Injector::inst()->createWithArgs(
47
            YubikeyLoginHandler::class,
48
            [Security::login_url(), $this->authenticator]
49
        );
50
        $this->form = Injector::inst()->get(
51
            YubikeyLoginForm::class,
52
            true,
53
            [$this->handler, YubikeyMemberAuthenticator::class, '']
54
        );
55
        Injector::inst()->registerService($validator, Validate::class);
56
    }
57
58
    public function tearDown()
59
    {
60
        parent::tearDown();
61
    }
62
63
    public function testNoYubikey()
64
    {
65
        $request = new HTTPRequest('POST', '/');
66
        $request->setSession(new Session(['hi' => 'bye']));
67
        $this->handler->setRequest($request);
68
69
        $this->handler->doLogin(
70
            [
71
                'Email'    => '[email protected]',
72
                'Password' => 'password',
73
            ],
74
            $this->form,
75
            $request
76
        );
77
        $this->handler->validateToken(
78
            ['yubiauth' => ''],
79
            YubikeyForm::create($this->handler),
80
            $request
81
        );
82
        $member = Member::get()->filter(['Email' => '[email protected]'])->first();
83
        $this->assertGreaterThan(0, $member->NoYubikeyCount);
84
        $this->assertEquals(null, $member->Yubikey);
85
    }
86
87
    public function testNoYubikeySuccess()
88
    {
89
        /** @var Member $member */
90
        $member = Member::get()->filter(['Email' => '[email protected]'])->first();
91
        $member->NoYubikeyCount = 0;
92
        $member->MFAEnabled = false;
93
        $member->write();
94
        $request = new HTTPRequest('POST', '/');
95
        $request->setSession(new Session(['hi' => 'bye']));
96
        $this->handler->setRequest($request);
97
        $this->handler->doLogin(
98
            [
99
100
                'Email'    => '[email protected]',
101
                'Password' => 'password',
102
            ],
103
            $this->form,
104
            $request
105
        );
106
        $this->handler->validateToken(
107
            ['yubiauth' => ''],
108
            YubikeyForm::create($this->handler),
109
            $request
110
        );
111
        $member = Member::get()->filter(['Email' => '[email protected]'])->first();
112
        $this->assertEquals(0, $member->FailedLoginCount);
113
    }
114
115
    public function testNoYubikeyLockout()
116
    {
117
        /** @var Member $member */
118
        $member = Member::get()->filter(['Email' => '[email protected]'])->first();
119
        $failedCount = $member->FailedLoginCount;
120
        $member->NoYubikeyCount = 25;
121
        $member->MFAEnabled = false;
122
        $member->write();
123
        $request = new HTTPRequest('POST', '/');
124
        $request->setSession(new Session(['hi' => 'bye']));
125
        $this->handler->setRequest($request);
126
        $this->handler->doLogin(
127
            [
128
129
                'Email'    => '[email protected]',
130
                'Password' => 'password',
131
            ],
132
            $this->form,
133
            $request
134
        );
135
        $result = $this->handler->validateToken(
0 ignored issues
show
Unused Code introduced by
The assignment to $result is dead and can be removed.
Loading history...
136
            ['yubiauth' => ''],
137
            YubikeyForm::create($this->handler),
138
            $request
139
        );
140
        $member = Member::get()->filter(['Email' => '[email protected]'])->first();
141
        $this->assertGreaterThan($failedCount, $member->FailedLoginCount);
142
    }
143
144
    public function testNoYubikeyDays()
145
    {
146
        /** @var Member $member */
147
        $member = Member::get()->filter(['Email' => '[email protected]'])->first();
148
        $failedCount = $member->FailedLoginCount;
149
        $member->NoYubikeyCount = 26;
150
        $member->Created = date('Y-m-d', strtotime('-1 year'));
151
        $member->MFAEnabled = false;
152
        $member->write();
153
        $request = new HTTPRequest('POST', '/');
154
        $request->setSession(new Session(['hi' => 'bye']));
155
        $this->handler->setRequest($request);
156
        $this->handler->doLogin(
157
            [
158
159
                'Email'    => '[email protected]',
160
                'Password' => 'password',
161
            ],
162
            $this->form,
163
            $request
164
        );
165
        $result = $this->handler->validateToken(
0 ignored issues
show
Unused Code introduced by
The assignment to $result is dead and can be removed.
Loading history...
166
            ['yubiauth' => ''],
167
            YubikeyForm::create($this->handler),
168
            $request
169
        );
170
        $member = Member::get()->filter(['Email' => '[email protected]'])->first();
171
        $this->assertGreaterThan($failedCount, $member->FailedLoginCount);
172
    }
173
174
    /**
175
     * @todo The mock currently always returns success
176
     *
177
     * public function testDifferentYubikey()
178
     * {
179
     * $newMember = Member::create([
180
     * 'FirstName'       => 'Pete',
181
     * 'Surname'         => 'Lister',
182
     * 'Password'        => 'IronMan2005!',
183
     * 'MFAEnabled' => true,
184
     * 'Yubikey'         => '1234567890abcdef'
185
     * ]);
186
     * $newMember->write();
187
     *
188
     * $member = Member::get()->filter(['Email' => '[email protected]'])->first();
189
     * $failedCount = $member->FailedLoginCount;
190
     * $member->MFAEnabled = true;
191
     * $member->write();
192
     *
193
     * $request = new HTTPRequest('POST', '/');
194
     * $request->setSession(new Session(['hi' => 'bye']));
195
     * $this->handler->setRequest($request);
196
     * $this->handler->doLogin(
197
     * [
198
     *
199
     * 'Email'    => '[email protected]',
200
     * 'Password' => 'password',
201
     * ],
202
     * $this->form,
203
     * $request
204
     * );
205
     * $this->handler->validateToken(
206
     * ['yubiauth' => '1234567890abcdefyhde.cybcpnbiixcjkbbyd.ydenhnjkn'],
207
     * YubikeyForm::create($this->handler),
208
     * $request
209
     * );
210
     * $member = Member::get()->filter(['Email' => '[email protected]'])->first();
211
     * $this->assertGreaterThan($failedCount, $member->FailedLoginCount);
212
     * }
213
     */
214
215
    public function testYubikeyAfterSuccess()
216
    {
217
        $request = new HTTPRequest('POST', '/');
218
        $request->setSession(new Session(['hi' => 'bye']));
219
        $this->handler->setRequest($request);
220
        $member = Member::get()->filter(['Email' => '[email protected]'])->first();
221
        $member->MFAEnabled = true;
222
        $member->Yubikey = 'ccccccfinfgr';
223
        $member->NoYubikeyCount = 50;
224
        $member->write();
225
        Injector::inst()->get(IdentityStore::class)->logOut();
226
        $failedLoginCount = $member->FailedLoginCount;
227
        $this->handler->doLogin(
228
            [
229
230
                'Email'    => '[email protected]',
231
                'Password' => 'password',
232
            ],
233
            $this->form,
234
            $request
235
        );
236
        $this->handler->validateToken(['yubiauth' => ''], YubikeyForm::create($this->handler), $request);
237
        $resultNoYubi = Security::getCurrentUser();
238
        $this->assertEquals(null, $resultNoYubi);
239
        $member = Member::get()->filter(array('Email' => '[email protected]'))->first();
240
        $this->assertGreaterThan($failedLoginCount, $member->FailedLoginCount);
241
    }
242
243
    public function testYubikey()
244
    {
245
        $request = new HTTPRequest('POST', '/');
246
        $request->setSession(new Session(['hi' => 'bye']));
247
        $this->handler->setRequest($request);
248
        $this->handler->doLogin(
249
            [
250
251
                'Email'    => '[email protected]',
252
                'Password' => 'password',
253
            ],
254
            $this->form,
255
            $request
256
        );
257
        $this->handler->validateToken(
258
            [
259
                // This OTP is _not_ valid in real situations
260
                'yubiauth' => 'jjjjjjucbuipyhde.cybcpnbiixcjkbbyd.ydenhnjkn'
261
            ],
262
            YubikeyForm::create($this->handler),
263
            $request
264
        );
265
        $result = Security::getCurrentUser();
266
        $this->assertEquals(Member::class, $result->ClassName);
267
        $this->assertEquals('ccccccfinfgr', $result->Yubikey);
268
        $this->assertEquals(1, $result->MFAEnabled);
269
        $this->assertEquals('[email protected]', $result->Email);
270
    }
271
272
    public function testName()
273
    {
274
        $this->assertEquals('Yubikey 2 factor login', YubikeyMemberAuthenticator::get_name());
275
    }
276
277
    public function testGetLoginHandler()
278
    {
279
        $authenticator = new YubikeyMemberAuthenticator();
280
281
        $handler = $authenticator->getLoginHandler(Security::login_url());
282
283
        $this->assertInstanceOf(YubikeyLoginHandler::class, $handler);
284
    }
285
286
    public function testGetSetProvider()
287
    {
288
        /** @var YubikeyMemberAuthenticator $authenticator */
289
        $authenticator = new YubikeyMemberAuthenticator();
290
291
        /** @var YubikeyAuthProvider $provider */
292
        $provider = Injector::inst()->get(YubikeyAuthProvider::class);
293
294
        $authenticator->setProvider($provider);
295
296
        $this->assertInstanceOf(YubikeyAuthProvider::class, $authenticator->getProvider());
297
    }
298
299
    public function testSupportedServices()
300
    {
301
        /** @var YubikeyMemberAuthenticator $authenticator */
302
        $authenticator = new YubikeyMemberAuthenticator();
303
304
        $this->assertEquals(47, $authenticator->supportedServices());
305
    }
306
307
    public function testUnknownMember()
308
    {
309
        $request = new HTTPRequest('POST', '/');
310
        $request->setSession(new Session(['hi' => 'bye']));
311
        $this->handler->setRequest($request);
312
313
        $this->handler->doLogin(
314
            [
315
                'Email'    => '[email protected]',
316
                'Password' => 'password',
317
            ],
318
            $this->form,
319
            $request
320
        );
321
        $session = $request->getSession();
322
        $session->set(BootstrapMFALoginHandler::SESSION_KEY . '.MemberID', -100);
323
        $request->setSession($session);
324
325
        $result = $this->authenticator->validateToken(
326
            [],
327
            $request,
328
            $result
329
        );
330
331
        $this->assertFalse($result->isValid());
332
    }
333
}
334