PluginProbe ʕ •ᴥ•ʔ
WP STAGING – WordPress Backup, Restore, Migration & Clone / 4.8.0
WP STAGING – WordPress Backup, Restore, Migration & Clone v4.8.0
4.9.1 4.9.0 4.8.1 trunk 3.0.0 3.0.1 3.0.2 3.0.3 3.0.4 3.0.5 3.0.6 3.1.0 3.1.1 3.1.2 3.1.3 3.1.4 3.10.0 3.2.0 3.3.1 3.3.2 3.3.3 3.4.1 3.4.3 3.5.0 3.6.0 3.7.1 3.8.0 3.8.1 3.8.2 3.8.3 3.8.4 3.8.5 3.8.6 3.8.7 3.9.0 3.9.1 3.9.2 3.9.3 3.9.4 4.0.0 4.1.0 4.1.1 4.1.2 4.1.3 4.1.4 4.2.0 4.2.1 4.3.0 4.3.1 4.3.2 4.4.0 4.5.0 4.6.0 4.7.0 4.7.1 4.7.2 4.7.3 4.8.0
wp-staging / Framework / Security / AccessToken.php
wp-staging / Framework / Security Last commit date
Otp 6 months ago AccessToken.php 11 months ago Auth.php 2 years ago Capabilities.php 1 year ago DataEncryption.php 1 month ago EncryptionNoticeService.php 1 month ago Nonce.php 3 years ago UniqueIdentifier.php 3 years ago
AccessToken.php
149 lines
1 <?php
2
3 namespace WPStaging\Framework\Security;
4
5 /**
6 * Class AccessToken
7 *
8 * WPSTAGING own implementation of a WordPress nonce,
9 * with the difference that it's generated and invalidated
10 * under our own criteria.
11 *
12 * @package WPStaging\Framework\Security
13 */
14 class AccessToken
15 {
16 /**
17 * The key in $_REQUEST that AccessToken expects to find a token.
18 */
19 const REQUEST_KEY = 'accessToken';
20
21 /**
22 * The option_name that is stored in the database.
23 */
24 const OPTION_NAME = 'wpstg_access_token';
25
26 /**
27 * @var bool
28 */
29 private $isCheckCapabilities = true;
30
31 /**
32 * @param bool $isCheckCapabilities
33 * @return void
34 */
35 public function setIsCheckCapabilities(bool $isCheckCapabilities = true)
36 {
37 $this->isCheckCapabilities = $isCheckCapabilities;
38 }
39
40 /**
41 * @return bool Whether the current $_REQUEST has a valid token.
42 */
43 public function requestHasValidToken()
44 {
45 return isset($_REQUEST[self::REQUEST_KEY]) && $this->isValidToken(sanitize_text_field($_REQUEST[self::REQUEST_KEY]));
46 }
47
48 /**
49 * @return string The new access token
50 * @return string|bool Returns False if user has no cap to generate a new token,
51 * or the generated token does not comply with the standards.
52 */
53 public function generateNewToken()
54 {
55 // Early bail: Not enough privilege to generate a token. Todo: Remove "new" once we have DI
56 if ($this->isCheckCapabilities && !$this->currentUserCanManageWPSTG()) {
57 return false;
58 }
59
60 $newToken = wp_generate_password(64, false);
61
62 // Early bail: A token is always a 64-character random string.
63 if (strlen($newToken) !== 64) {
64 return false;
65 }
66
67 /* literals that start with 0x are hexadecimal integers (base 16) and can lead to blocked requests by mod_security
68 * Issue: https://github.com/wp-staging/wp-staging-pro/issues/1650
69 */
70 $sanitizedToken = str_ireplace('0x', 'ax', $newToken);
71
72 update_option(static::OPTION_NAME, $sanitizedToken);
73
74 return $sanitizedToken;
75 }
76
77 /**
78 * @param string $newToken The new token, a 64-char string.
79 *
80 * @return false|mixed
81 */
82 public function setToken($newToken)
83 {
84 // Early bail: Not enough privilege to generate a token.
85 if ($this->isCheckCapabilities && !$this->currentUserCanManageWPSTG()) {
86 return false;
87 }
88
89 // Early bail: A token is always a 64-character random string.
90 if (strlen($newToken) !== 64) {
91 return false;
92 }
93
94 update_option(static::OPTION_NAME, $newToken);
95
96 return $newToken;
97 }
98
99 /**
100 * Gets the token. Requires user to be logged-in.
101 *
102 * @return string The access token or an empty string if no token exists.
103 * @return string|bool Returns False if user has no cap to read the token.
104 */
105 public function getToken()
106 {
107 // Early bail: Not enough privilege to get a token. Todo: Remove "new" once we have DI
108 if ($this->isCheckCapabilities && !$this->currentUserCanManageWPSTG()) {
109 return false;
110 }
111
112 return (string)get_option(static::OPTION_NAME, null);
113 }
114
115 /**
116 * Check if given token is valid. Does not require user to be logged-in.
117 *
118 * @param string $tokenToValidate A token to compare with the saved token.
119 *
120 * @return bool Whether given token is valid.
121 */
122 public function isValidToken($tokenToValidate)
123 {
124 $tokenToValidate = (string)$tokenToValidate;
125
126 // Early bail: A token is always a 64-character random string.
127 if (empty($tokenToValidate) || strlen($tokenToValidate) !== 64) {
128 return false;
129 }
130
131 $savedToken = (string)get_option(static::OPTION_NAME, null);
132
133 // Early bail: We can't validate a token because at least one of the parts are empty.
134 if (empty($savedToken)) {
135 return false;
136 }
137
138 return $tokenToValidate === $savedToken;
139 }
140
141 /**
142 * @return bool
143 */
144 private function currentUserCanManageWPSTG()
145 {
146 return current_user_can((new Capabilities())->manageWPSTG());
147 }
148 }
149