1 | <?php |
||||
2 | |||||
3 | declare(strict_types=1); |
||||
4 | |||||
5 | namespace SilverStripe\TOTP; |
||||
6 | |||||
7 | use Exception; |
||||
8 | use Psr\Log\LoggerInterface; |
||||
9 | use RuntimeException; |
||||
10 | use SilverStripe\Control\HTTPRequest; |
||||
11 | use SilverStripe\Core\Injector\Injectable; |
||||
12 | use SilverStripe\Core\Injector\Injector; |
||||
13 | use SilverStripe\MFA\Exception\AuthenticationFailedException; |
||||
14 | use SilverStripe\MFA\Method\Handler\VerifyHandlerInterface; |
||||
15 | use SilverStripe\MFA\Model\RegisteredMethod; |
||||
16 | use SilverStripe\MFA\Service\EncryptionAdapterInterface; |
||||
17 | use SilverStripe\MFA\State\Result; |
||||
18 | use SilverStripe\MFA\Store\StoreInterface; |
||||
19 | |||||
20 | /** |
||||
21 | * Handles verification requests using a time-based one-time password (TOTP) with the silverstripe/mfa module. |
||||
22 | */ |
||||
23 | class VerifyHandler implements VerifyHandlerInterface |
||||
24 | { |
||||
25 | use Injectable; |
||||
26 | use TOTPAware; |
||||
27 | |||||
28 | /** |
||||
29 | * @var string[] |
||||
30 | */ |
||||
31 | private static $dependencies = [ |
||||
0 ignored issues
–
show
introduced
by
Loading history...
|
|||||
32 | 'Logger' => '%$' . LoggerInterface::class . '.mfa', |
||||
33 | ]; |
||||
34 | |||||
35 | /** |
||||
36 | * @var LoggerInterface |
||||
37 | */ |
||||
38 | protected $logger; |
||||
39 | |||||
40 | public function start(StoreInterface $store, RegisteredMethod $method): array |
||||
41 | { |
||||
42 | try { |
||||
43 | $data = json_decode((string) $method->Data, true); |
||||
44 | if (!$data || !isset($data['secret'])) { |
||||
45 | throw new RuntimeException('TOTP secret is not available in the registered method data'); |
||||
46 | } |
||||
47 | |||||
48 | $key = $this->getEncryptionKey(); |
||||
49 | if (empty($key)) { |
||||
50 | throw new AuthenticationFailedException( |
||||
51 | 'Please define a SS_MFA_SECRET_KEY environment variable for encryption' |
||||
52 | ); |
||||
53 | } |
||||
54 | |||||
55 | // Decrypt the TOTP secret from the registered method |
||||
56 | $secret = Injector::inst()->get(EncryptionAdapterInterface::class)->decrypt($data['secret'], $key); |
||||
57 | |||||
58 | $store->setState([ |
||||
59 | 'secret' => $secret, |
||||
60 | ]); |
||||
61 | |||||
62 | $enabled = true; |
||||
63 | } catch (Exception $ex) { |
||||
64 | // noop: encryption may not be defined, so method should be disabled rather than application error |
||||
65 | $enabled = false; |
||||
66 | |||||
67 | $this->getLogger()->debug($ex->getMessage(), $ex->getTrace()); |
||||
68 | } |
||||
69 | |||||
70 | return [ |
||||
71 | 'enabled' => $enabled, |
||||
72 | 'codeLength' => $method->getMethod()->getCodeLength(), |
||||
0 ignored issues
–
show
The method
getCodeLength() does not exist on SilverStripe\MFA\Method\MethodInterface . It seems like you code against a sub-type of SilverStripe\MFA\Method\MethodInterface such as SilverStripe\TOTP\Method .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
Loading history...
|
|||||
73 | ]; |
||||
74 | } |
||||
75 | |||||
76 | public function verify(HTTPRequest $request, StoreInterface $store, RegisteredMethod $registeredMethod): Result |
||||
77 | { |
||||
78 | $data = json_decode($request->getBody(), true); |
||||
79 | if (!$this->getTotp($store)->verify($data['code'] ?? '')) { |
||||
80 | return Result::create(false, _t(__CLASS__ . '.INVALID_CODE', 'Invalid code')); |
||||
81 | } |
||||
82 | return Result::create(); |
||||
83 | } |
||||
84 | |||||
85 | public function getComponent(): string |
||||
86 | { |
||||
87 | return 'TOTPVerify'; |
||||
88 | } |
||||
89 | |||||
90 | /** |
||||
91 | * @return LoggerInterface |
||||
92 | */ |
||||
93 | public function getLogger(): ?LoggerInterface |
||||
94 | { |
||||
95 | return $this->logger; |
||||
96 | } |
||||
97 | |||||
98 | /** |
||||
99 | * @param LoggerInterface $logger |
||||
100 | * @return VerifyHandler |
||||
101 | */ |
||||
102 | public function setLogger(LoggerInterface $logger): VerifyHandler |
||||
103 | { |
||||
104 | $this->logger = $logger; |
||||
105 | return $this; |
||||
106 | } |
||||
107 | } |
||||
108 |