Failed Conditions
Push — tokenauth ( b0ac60 )
by Andreas
11:30 queued 08:14
created

AuthenticationToken::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 5
c 1
b 0
f 0
nc 1
nop 2
dl 0
loc 6
rs 9.4285
1
<?php
2
3
namespace dokuwiki;
4
5
class AuthenticationToken {
6
    /** @var int byte length of the token (non-user part) */
7
    const TOKENLENGTH = 32;
8
9
    /** @var string path to the file */
10
    protected $file;
11
    /** @var string the md5 of the user name */
12
    protected $md5;
13
14
    /** @var string|null the user name */
15
    protected $user;
16
    /** @var string|null the full token */
17
    protected $token;
18
19
    /**
20
     * AuthenticationToken constructor.
21
     *
22
     * @param string $md5
23
     * @param string|null $user
24
     */
25
    protected function __construct($md5, $user = null) {
26
        global $conf;
27
        $this->md5 = $md5;
28
        $this->user = $user;
29
        $this->file = $conf['metadir'] . '/_authtokens/' . $md5 . '.token';
30
    }
31
32
    /**
33
     * Create an instance from a given token
34
     *
35
     * @param string $token
36
     * @return AuthenticationToken
37
     */
38
    static public function fromToken($token) {
39
        list($md5) = explode('-', $token);
40
        if(!preg_match('/^[a-zA-Z0-9]+$/', $md5)) $md5 = 'invalid';
41
        return new self($md5);
42
    }
43
44
    /**
45
     * Create an instance from a given user name
46
     *
47
     * @param string $user
48
     * @return AuthenticationToken
49
     */
50
    static public function fromUser($user) {
51
        /** @var \DokuWiki_Auth_Plugin $auth */
52
        global $auth;
53
        $md5 = md5($auth->cleanUser($user), true);
54
        $md5 = self::tokenchars($md5);
55
        return new self($md5, $user);
56
    }
57
58
    /**
59
     * Check the user supplied token against the stored one
60
     *
61
     * @param string $token the user supplied token
62
     * @return bool
63
     */
64
    public function check($token) {
65
        $known = $this->getToken();
66
        if(!$known) return false;
67
        return hash_equals($known, $token);
68
    }
69
70
    /**
71
     * Reset the user's token
72
     *
73
     * @return string|false the new token if successful
74
     */
75
    public function reset() {
76
        if($this->user === null) throw new \RuntimeException('No user initialized');
77
78
        $token = self::tokenchars(random_bytes(self::TOKENLENGTH));
79
        $token = $this->md5 . '-' . $token;
80
81
        $content = $token . "\n" . $this->user;
82
        if(io_saveFile($this->file, $content)) return $token;
83
        return false;
84
    }
85
86
    /**
87
     * Get the user's current token
88
     *
89
     * @return string|false the token, false if none is set
90
     */
91
    public function getToken() {
92
        if($this->token === null && !$this->load()) return false;
93
        return $this->token;
94
    }
95
96
    /**
97
     * Get the user of this token
98
     *
99
     * @return bool|string
100
     */
101
    public function getUser() {
102
        if($this->user === null && !$this->load()) return false;
103
        return $this->user;
104
    }
105
106
    /**
107
     * Removes the user's token
108
     */
109
    public function clear() {
110
        @unlink($this->file);
111
    }
112
113
    /**
114
     * Load the data
115
     *
116
     * @return bool successfully loaded
117
     */
118
    protected function load() {
119
        if(!file_exists($this->file)) return false;
120
        list($token, $user) = explode("\n", trim(io_readFile($this->file, false)));
121
        $this->user = $user;
122
        $this->token = $token;
123
        return true;
124
    }
125
126
    /**
127
     * Adjusted Base64 method
128
     *
129
     * @param string $bytes
130
     * @return string
131
     */
132
    protected static function tokenchars($bytes) {
133
        $chars = base64_encode($bytes);
134
        $chars = str_replace(['+', '/', '='], ['X', 'Y', ''], $chars);
135
        return $chars;
136
    }
137
138
    /**
139
     * Generate an alphanumeric token of given length
140
     *
141
     * @param int $length
142
     * @return string
143
     */
144
    protected function createToken($length = 30) {
145
        $token = '';
146
        $codeAlphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
147
        $codeAlphabet .= "abcdefghijklmnopqrstuvwxyz";
148
        $codeAlphabet .= "0123456789";
149
        $max = strlen($codeAlphabet);
150
151
        for($i = 0; $i < $length; $i++) {
152
            $token .= $codeAlphabet[random_int(0, $max - 1)];
153
        }
154
155
        return $token;
156
    }
157
158
}
159