1 | <?php declare(strict_types=1); |
||
2 | |||
3 | namespace SilverStripe\MFA\BackupCode; |
||
4 | |||
5 | use Exception; |
||
6 | use SilverStripe\Control\HTTPRequest; |
||
7 | use SilverStripe\Core\Config\Configurable; |
||
8 | use SilverStripe\Core\Extensible; |
||
9 | use SilverStripe\Core\Injector\Injector; |
||
10 | use SilverStripe\MFA\Method\Handler\RegisterHandlerInterface; |
||
11 | use SilverStripe\MFA\Method\MethodInterface; |
||
12 | use SilverStripe\MFA\Service\BackupCodeGeneratorInterface; |
||
13 | use SilverStripe\MFA\Service\RegisteredMethodManager; |
||
14 | use SilverStripe\MFA\State\BackupCode; |
||
15 | use SilverStripe\MFA\State\Result; |
||
16 | use SilverStripe\MFA\Store\StoreInterface; |
||
17 | |||
18 | class RegisterHandler implements RegisterHandlerInterface |
||
19 | { |
||
20 | use Extensible; |
||
21 | use Configurable; |
||
22 | |||
23 | /** |
||
24 | * Provide a user help link that will be available when registering backup codes |
||
25 | * TODO Will this have a user help link as a default? |
||
26 | * |
||
27 | * @config |
||
28 | * @var string |
||
29 | */ |
||
30 | private static $user_help_link; |
||
0 ignored issues
–
show
introduced
by
Loading history...
|
|||
31 | |||
32 | /** |
||
33 | * Stores any data required to handle a registration process with a method, and returns relevant state to be applied |
||
34 | * to the front-end application managing the process. |
||
35 | * |
||
36 | * @param StoreInterface $store An object that hold session data (and the Member) that can be mutated |
||
37 | * @return array Props to be passed to a front-end component |
||
38 | * @throws Exception When there is no valid source of CSPRNG |
||
39 | */ |
||
40 | public function start(StoreInterface $store): array |
||
41 | { |
||
42 | // Create or update the RegisteredMethod on the member. This breaks the normal flow as it's created on "start" |
||
43 | // instead of after receiving a response from the user |
||
44 | |||
45 | /** @var MethodInterface $method */ |
||
46 | $method = Injector::inst()->get(Method::class); |
||
47 | |||
48 | /** @var BackupCodeGeneratorInterface $generator */ |
||
49 | $generator = Injector::inst()->get(BackupCodeGeneratorInterface::class); |
||
50 | $codes = $generator->generate(); |
||
51 | |||
52 | RegisteredMethodManager::singleton()->registerForMember( |
||
53 | $store->getMember(), |
||
54 | $method, |
||
55 | array_map(function (BackupCode $backupCode) { |
||
56 | return json_encode($backupCode); |
||
57 | }, $codes) |
||
58 | ); |
||
59 | |||
60 | // Return un-hashed codes for the front-end UI |
||
61 | return [ |
||
62 | 'codes' => array_map(function (BackupCode $backupCode) { |
||
63 | return $backupCode->getCode(); |
||
64 | }, $codes), |
||
65 | ]; |
||
66 | } |
||
67 | |||
68 | /** |
||
69 | * Confirm that the provided details are valid, and create a new RegisteredMethod against the member. |
||
70 | * |
||
71 | * @param HTTPRequest $request |
||
72 | * @param StoreInterface $store |
||
73 | * @return array |
||
74 | */ |
||
75 | public function register(HTTPRequest $request, StoreInterface $store): Result |
||
76 | { |
||
77 | // Backup codes are unique where no confirmation or user input is required. The method is registered on "start" |
||
78 | return Result::create(); |
||
79 | } |
||
80 | |||
81 | /** |
||
82 | * Provide a localised description of this MFA Method. |
||
83 | * |
||
84 | * eg. "Verification codes are created by an app on your phone" |
||
85 | * |
||
86 | * @return string |
||
87 | */ |
||
88 | public function getDescription(): string |
||
89 | { |
||
90 | return _t( |
||
91 | __CLASS__ . '.DESCRIPTION', |
||
92 | 'Recovery codes enable you to log into your account in the event your primary authentication is not ' |
||
93 | . 'available. Each code can only be used once. Store these codes somewhere safe, as they will not be ' |
||
94 | . 'viewable after this leaving this page.' |
||
95 | ); |
||
96 | } |
||
97 | |||
98 | /** |
||
99 | * Provide a localised URL to a support article about the registration process for this MFA Method. |
||
100 | * |
||
101 | * @return string |
||
102 | */ |
||
103 | public function getSupportLink(): string |
||
104 | { |
||
105 | return (string) $this->config()->get('user_help_link'); |
||
106 | } |
||
107 | |||
108 | /** |
||
109 | * Provide a localised string to describe the support link {@see getSupportLink} about this MFA Method. |
||
110 | * |
||
111 | * @return string |
||
112 | */ |
||
113 | public function getSupportText(): string |
||
114 | { |
||
115 | return _t(__CLASS__ . '.SUPPORT_LINK_DESCRIPTION', 'Learn about recovery codes.'); |
||
116 | } |
||
117 | |||
118 | /** |
||
119 | * Get the key that a React UI component is registered under (with @silverstripe/react-injector on the front-end) |
||
120 | * |
||
121 | * @return string |
||
122 | */ |
||
123 | public function getComponent(): string |
||
124 | { |
||
125 | return 'BackupCodeRegister'; |
||
126 | } |
||
127 | } |
||
128 |