Passed
Pull Request — master (#38)
by Simon
04:06
created

BootstrapMFAAuthenticator::supportedServices()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 0
dl 0
loc 5
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Firesphere\BootstrapMFA\Authenticators;
4
5
use Firesphere\BootstrapMFA\Handlers\BootstrapMFALoginHandler;
6
use Firesphere\BootstrapMFA\Providers\BootstrapMFAProvider;
7
use SilverStripe\Core\Injector\Injector;
8
use SilverStripe\ORM\ValidationException;
9
use SilverStripe\ORM\ValidationResult;
10
use SilverStripe\Security\Authenticator;
11
use SilverStripe\Security\Member;
12
use SilverStripe\Security\MemberAuthenticator\MemberAuthenticator;
13
use SilverStripe\Security\PasswordEncryptor_NotFoundException;
14
15
/**
16
 * Class BootstrapMFAAuthenticator
17
 * It needs to be instantiable, therefore it can't be an Abstract.
18
 *
19
 * @package Firesphere\BootstrapMFA\Authenticators
20
 * @method string getTokenField() Stub for child implementations
21
 */
22
class BootstrapMFAAuthenticator extends MemberAuthenticator
23
{
24
    /**
25
     * Key for array to be stored in between steps in the session
26
     */
27
    const SESSION_KEY = 'MFALogin';
28
29
    /**
30
     * @return int
31
     */
32
    public function supportedServices()
33
    {
34
        // Bitwise-OR of all the supported services in this Authenticator, to make a bitmask
35
        return Authenticator::LOGIN | Authenticator::LOGOUT | Authenticator::CHANGE_PASSWORD
36
            | Authenticator::RESET_PASSWORD | Authenticator::CHECK_PASSWORD;
37
    }
38
39
    /**
40
     * @param Member $member
41
     * @param string $token
42
     * @param ValidationResult|null $result
43
     * @return bool|Member
44
     * @throws ValidationException
45
     * @throws PasswordEncryptor_NotFoundException
46
     */
47
    public function validateBackupCode($member, $token, &$result = null)
48
    {
49
        if (!$result) {
50
            $result = new ValidationResult();
51
        }
52
        $token = $member->encryptWithUserSettings($token);
53
54
        /** @var BootstrapMFAProvider $provider */
55
        $provider = Injector::inst()->get(BootstrapMFAProvider::class);
56
        $provider->setMember($member);
57
58
        $backupCode = $provider->fetchToken($token);
59
60
        if ($backupCode && $backupCode->exists()) {
61
            $backupCode->expire();
62
            // Reset the subclass authenticator results
63
            $result = Injector::inst()->get(ValidationResult::class, false);
64
65
            /** @var Member $member */
66
            return $member;
67
        }
68
69
        $member->registerFailedLogin();
70
        $result->addError(_t(self::class . '.INVALIDTOKEN', 'Invalid token'));
71
72
        return false;
73
    }
74
75
    /**
76
     * @param string $link
77
     * @return BootstrapMFALoginHandler|static
78
     */
79
    public function getLoginHandler($link)
80
    {
81
        return BootstrapMFALoginHandler::create($link, $this);
82
    }
83
}
84