Issues (13)

tests/unit/YubikeyMemberAuthenticatorTest.php (2 issues)

Severity
1
<?php
2
3
namespace Firesphere\YubiAuth\Tests;
4
5
use Firesphere\BootstrapMFA\Authenticators\BootstrapMFAAuthenticator;
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
        Injector::inst()->registerService($validator, Validate::class);
46
        $this->authenticator = Injector::inst()->get(YubikeyMemberAuthenticator::class);
47
        $this->handler = Injector::inst()->createWithArgs(
48
            YubikeyLoginHandler::class,
49
            [Security::login_url(), $this->authenticator]
50
        );
51
        $this->form = Injector::inst()->get(
52
            YubikeyLoginForm::class,
53
            true,
54
            [$this->handler, YubikeyMemberAuthenticator::class, '']
55
        );
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, (int)$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
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
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
    public function testYubikeyAfterSuccess()
175
    {
176
        $request = new HTTPRequest('POST', '/');
177
        $request->setSession(new Session(['hi' => 'bye']));
178
        $this->handler->setRequest($request);
179
        $member = Member::get()->filter(['Email' => '[email protected]'])->first();
180
        $member->MFAEnabled = true;
181
        $member->Yubikey = 'ccccccfinfgr';
182
        $member->NoYubikeyCount = 50;
183
        $member->write();
184
        Injector::inst()->get(IdentityStore::class)->logOut();
185
        $failedLoginCount = $member->FailedLoginCount;
186
        $this->handler->doLogin(
187
            [
188
189
                'Email'    => '[email protected]',
190
                'Password' => 'password',
191
            ],
192
            $this->form,
193
            $request
194
        );
195
        $this->handler->validateToken(['yubiauth' => ''], YubikeyForm::create($this->handler), $request);
196
        $resultNoYubi = Security::getCurrentUser();
197
        $this->assertEquals(null, $resultNoYubi);
198
        $member = Member::get()->filter(array('Email' => '[email protected]'))->first();
199
        $this->assertGreaterThan($failedLoginCount, $member->FailedLoginCount);
200
    }
201
202
    public function testYubikey()
203
    {
204
        $request = new HTTPRequest('POST', '/');
205
        $request->setSession(new Session(['hi' => 'bye']));
206
        $this->handler->setRequest($request);
207
        $this->handler->doLogin(
208
            [
209
210
                'Email'    => '[email protected]',
211
                'Password' => 'password',
212
            ],
213
            $this->form,
214
            $request
215
        );
216
        $this->handler->validateToken(
217
            [
218
                // This OTP is _not_ valid in real situations
219
                'yubiauth' => 'jjjjjjucbuipyhde.cybcpnbiixcjkbbyd.ydenhnjkn'
220
            ],
221
            YubikeyForm::create($this->handler),
222
            $request
223
        );
224
225
        $result = Security::getCurrentUser();
226
        $this->assertEquals(Member::class, $result->ClassName);
227
        $this->assertEquals('ccccccfinfgr', $result->Yubikey);
228
        $this->assertEquals(1, $result->MFAEnabled);
229
        $this->assertEquals('[email protected]', $result->Email);
230
    }
231
232
    public function testName()
233
    {
234
        $this->assertEquals('Yubikey 2 factor login', YubikeyMemberAuthenticator::get_name());
235
    }
236
237
    public function testGetLoginHandler()
238
    {
239
        $authenticator = new YubikeyMemberAuthenticator();
240
241
        $handler = $authenticator->getLoginHandler(Security::login_url());
242
243
        $this->assertInstanceOf(YubikeyLoginHandler::class, $handler);
244
    }
245
246
    public function testGetSetProvider()
247
    {
248
        /** @var YubikeyMemberAuthenticator $authenticator */
249
        $authenticator = new YubikeyMemberAuthenticator();
250
251
        /** @var YubikeyAuthProvider $provider */
252
        $provider = Injector::inst()->get(YubikeyAuthProvider::class);
253
254
        $authenticator->setProvider($provider);
255
256
        $this->assertInstanceOf(YubikeyAuthProvider::class, $authenticator->getProvider());
257
    }
258
259
    public function testSupportedServices()
260
    {
261
        /** @var YubikeyMemberAuthenticator $authenticator */
262
        $authenticator = new YubikeyMemberAuthenticator();
263
264
        $this->assertEquals(47, $authenticator->supportedServices());
265
    }
266
267
    public function testUnknownMember()
268
    {
269
        $request = new HTTPRequest('POST', '/');
270
        $request->setSession(new Session(['hi' => 'bye']));
271
        $this->handler->setRequest($request);
272
273
        $this->handler->doLogin(
274
            [
275
                'Email'    => '[email protected]',
276
                'Password' => 'password',
277
            ],
278
            $this->form,
279
            $request
280
        );
281
        $session = $request->getSession();
282
        $session->set(BootstrapMFAAuthenticator::SESSION_KEY . '.MemberID', -100);
283
        $request->setSession($session);
284
285
        $this->authenticator->validateToken(
286
            [],
287
            $request,
288
            $result
289
        );
290
291
        $this->assertFalse($result->isValid());
292
    }
293
}
294