AuthenticationManager::__construct()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 9
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
eloc 5
dl 0
loc 9
ccs 0
cts 5
cp 0
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 3
crap 2
1
<?php
2
/******************************************************************************
3
 * Wikipedia Account Creation Assistance tool                                 *
4
 * ACC Development Team. Please see team.json for a list of contributors.     *
5
 *                                                                            *
6
 * This is free and unencumbered software released into the public domain.    *
7
 * Please see LICENSE.md for the full licencing statement.                    *
8
 ******************************************************************************/
9
10
namespace Waca\Security;
11
12
use PDO;
13
use Waca\DataObjects\User;
14
use Waca\Helpers\HttpHelper;
15
use Waca\PdoDatabase;
16
use Waca\Security\CredentialProviders\ICredentialProvider;
17
use Waca\Security\CredentialProviders\PasswordCredentialProvider;
18
use Waca\Security\CredentialProviders\ScratchTokenCredentialProvider;
19
use Waca\Security\CredentialProviders\TotpCredentialProvider;
20
use Waca\Security\CredentialProviders\YubikeyOtpCredentialProvider;
21
use Waca\SiteConfiguration;
22
23
class AuthenticationManager
24
{
25
    const AUTH_OK = 1;
26
    const AUTH_FAIL = 2;
27
    const AUTH_REQUIRE_NEXT_STAGE = 3;
28
    private $typeMap = array();
29
    /**
30
     * @var PdoDatabase
31
     */
32
    private $database;
33
34
    /**
35
     * AuthenticationManager constructor.
36
     *
37
     * @param PdoDatabase       $database
38
     * @param SiteConfiguration $siteConfiguration
39
     * @param HttpHelper        $httpHelper
40
     */
41
    public function __construct(PdoDatabase $database, SiteConfiguration $siteConfiguration, HttpHelper $httpHelper)
42
    {
43
        // setup providers
44
        // note on type map: this *must* be the value in the database, as this is what it maps.
45
        $this->typeMap['password'] = new PasswordCredentialProvider($database, $siteConfiguration);
46
        $this->typeMap['yubikeyotp'] = new YubikeyOtpCredentialProvider($database, $siteConfiguration, $httpHelper);
47
        $this->typeMap['totp'] = new TotpCredentialProvider($database, $siteConfiguration);
48
        $this->typeMap['scratch'] = new ScratchTokenCredentialProvider($database, $siteConfiguration);
49
        $this->database = $database;
50
    }
51
52
    public function authenticate(User $user, $data, $stage)
53
    {
54
        $sql = 'SELECT type FROM credential WHERE user = :user AND factor = :stage AND disabled = 0 ORDER BY priority ASC';
55
        $statement = $this->database->prepare($sql);
56
        $statement->execute(array(':user' => $user->getId(), ':stage' => $stage));
57
        $options = $statement->fetchAll(PDO::FETCH_COLUMN);
58
59
        $sql = 'SELECT count(DISTINCT factor) FROM credential WHERE user = :user AND factor > :stage AND disabled = 0 AND type <> :scratch';
60
        $statement = $this->database->prepare($sql);
61
        $statement->execute(array(':user' => $user->getId(), ':stage' => $stage, ':scratch' => 'scratch'));
62
        $requiredFactors = $statement->fetchColumn();
63
64
        // prep the correct OK response based on how many factors are ahead of this one
65
        $success = self::AUTH_OK;
66
        if ($requiredFactors > 0) {
67
            $success = self::AUTH_REQUIRE_NEXT_STAGE;
68
        }
69
70
        foreach ($options as $type) {
71
            if (!isset($this->typeMap[$type])) {
72
                // does this type have a credentialProvider registered?
73
                continue;
74
            }
75
76
            /** @var ICredentialProvider $credentialProvider */
77
            $credentialProvider = $this->typeMap[$type];
78
            if ($credentialProvider->authenticate($user, $data)) {
79
                return $success;
80
            }
81
        }
82
83
        // We've iterated over all the available providers for this stage.
84
        // They all hate you.
85
        return self::AUTH_FAIL;
86
    }
87
}