]> BookStack Code Mirror - bookstack/blob - app/Auth/Access/Mfa/BackupCodeService.php
Added Backup code verification logic
[bookstack] / app / Auth / Access / Mfa / BackupCodeService.php
1 <?php
2
3 namespace BookStack\Auth\Access\Mfa;
4
5 use Illuminate\Support\Str;
6
7 class BackupCodeService
8 {
9     /**
10      * Generate a new set of 16 backup codes.
11      */
12     public function generateNewSet(): array
13     {
14         $codes = [];
15         while (count($codes) < 16) {
16             $code = Str::random(5) . '-' . Str::random(5);
17             if (!in_array($code, $codes)) {
18                 $codes[] = strtolower($code);
19             }
20         }
21
22         return $codes;
23     }
24
25     /**
26      * Check if the given code matches one of the available options.
27      */
28     public function inputCodeExistsInSet(string $code, string $codeSet): bool
29     {
30         $cleanCode = $this->cleanInputCode($code);
31         $codes = json_decode($codeSet);
32         return in_array($cleanCode, $codes);
33     }
34
35     /**
36      * Remove the given input code from the given available options.
37      * Will return null if no codes remain otherwise will be a JSON string to contain
38      * the codes.
39      */
40     public function removeInputCodeFromSet(string $code, string $codeSet): ?string
41     {
42         $cleanCode = $this->cleanInputCode($code);
43         $codes = json_decode($codeSet);
44         $pos = array_search($cleanCode, $codes, true);
45         array_splice($codes, $pos, 1);
46
47         if (count($codes) === 0) {
48             return null;
49         }
50
51         return json_encode($codes);
52     }
53
54     /**
55      * Count the number of codes in the given set.
56      */
57     public function countCodesInSet(string $codeSet): int
58     {
59         return count(json_decode($codeSet));
60     }
61
62     protected function cleanInputCode(string $code): string
63     {
64         return strtolower(str_replace(' ', '-', trim($code)));
65     }
66 }