58 /** |
58 /** |
59 * Creates a new application password. |
59 * Creates a new application password. |
60 * |
60 * |
61 * @since 5.6.0 |
61 * @since 5.6.0 |
62 * @since 5.7.0 Returns WP_Error if application name already exists. |
62 * @since 5.7.0 Returns WP_Error if application name already exists. |
|
63 * @since 6.8.0 The hashed password value now uses wp_fast_hash() instead of phpass. |
63 * |
64 * |
64 * @param int $user_id User ID. |
65 * @param int $user_id User ID. |
65 * @param array $args { |
66 * @param array $args { |
66 * Arguments used to create the application password. |
67 * Arguments used to create the application password. |
67 * |
68 * |
69 * @type string $app_id A UUID provided by the application to uniquely identify it. |
70 * @type string $app_id A UUID provided by the application to uniquely identify it. |
70 * } |
71 * } |
71 * @return array|WP_Error { |
72 * @return array|WP_Error { |
72 * Application password details, or a WP_Error instance if an error occurs. |
73 * Application password details, or a WP_Error instance if an error occurs. |
73 * |
74 * |
74 * @type string $0 The unhashed generated application password. |
75 * @type string $0 The generated application password in plain text. |
75 * @type array $1 { |
76 * @type array $1 { |
76 * The details about the created password. |
77 * The details about the created password. |
77 * |
78 * |
78 * @type string $uuid The unique identifier for the application password. |
79 * @type string $uuid The unique identifier for the application password. |
79 * @type string $app_id A UUID provided by the application to uniquely identify it. |
80 * @type string $app_id A UUID provided by the application to uniquely identify it. |
92 |
93 |
93 if ( empty( $args['name'] ) ) { |
94 if ( empty( $args['name'] ) ) { |
94 return new WP_Error( 'application_password_empty_name', __( 'An application name is required to create an application password.' ), array( 'status' => 400 ) ); |
95 return new WP_Error( 'application_password_empty_name', __( 'An application name is required to create an application password.' ), array( 'status' => 400 ) ); |
95 } |
96 } |
96 |
97 |
97 if ( self::application_name_exists_for_user( $user_id, $args['name'] ) ) { |
|
98 return new WP_Error( 'application_password_duplicate_name', __( 'Each application name should be unique.' ), array( 'status' => 409 ) ); |
|
99 } |
|
100 |
|
101 $new_password = wp_generate_password( static::PW_LENGTH, false ); |
98 $new_password = wp_generate_password( static::PW_LENGTH, false ); |
102 $hashed_password = wp_hash_password( $new_password ); |
99 $hashed_password = self::hash_password( $new_password ); |
103 |
100 |
104 $new_item = array( |
101 $new_item = array( |
105 'uuid' => wp_generate_uuid4(), |
102 'uuid' => wp_generate_uuid4(), |
106 'app_id' => empty( $args['app_id'] ) ? '' : $args['app_id'], |
103 'app_id' => empty( $args['app_id'] ) ? '' : $args['app_id'], |
107 'name' => $args['name'], |
104 'name' => $args['name'], |
139 * @type string $password A one-way hash of the password. |
137 * @type string $password A one-way hash of the password. |
140 * @type int $created Unix timestamp of when the password was created. |
138 * @type int $created Unix timestamp of when the password was created. |
141 * @type null $last_used Null. |
139 * @type null $last_used Null. |
142 * @type null $last_ip Null. |
140 * @type null $last_ip Null. |
143 * } |
141 * } |
144 * @param string $new_password The unhashed generated application password. |
142 * @param string $new_password The generated application password in plain text. |
145 * @param array $args { |
143 * @param array $args { |
146 * Arguments used to create the application password. |
144 * Arguments used to create the application password. |
147 * |
145 * |
148 * @type string $name The name of the application password. |
146 * @type string $name The name of the application password. |
149 * @type string $app_id A UUID provided by the application to uniquely identify it. |
147 * @type string $app_id A UUID provided by the application to uniquely identify it. |
159 * |
157 * |
160 * @since 5.6.0 |
158 * @since 5.6.0 |
161 * |
159 * |
162 * @param int $user_id User ID. |
160 * @param int $user_id User ID. |
163 * @return array { |
161 * @return array { |
164 * The list of app passwords. |
162 * The list of application passwords. |
165 * |
163 * |
166 * @type array ...$0 { |
164 * @type array ...$0 { |
167 * @type string $uuid The unique identifier for the application password. |
165 * @type string $uuid The unique identifier for the application password. |
168 * @type string $app_id A UUID provided by the application to uniquely identify it. |
166 * @type string $app_id A UUID provided by the application to uniquely identify it. |
169 * @type string $name The name of the application password. |
167 * @type string $name The name of the application password. |
202 * |
200 * |
203 * @since 5.6.0 |
201 * @since 5.6.0 |
204 * |
202 * |
205 * @param int $user_id User ID. |
203 * @param int $user_id User ID. |
206 * @param string $uuid The password's UUID. |
204 * @param string $uuid The password's UUID. |
207 * @return array|null The application password if found, null otherwise. |
205 * @return array|null { |
|
206 * The application password if found, null otherwise. |
|
207 * |
|
208 * @type string $uuid The unique identifier for the application password. |
|
209 * @type string $app_id A UUID provided by the application to uniquely identify it. |
|
210 * @type string $name The name of the application password. |
|
211 * @type string $password A one-way hash of the password. |
|
212 * @type int $created Unix timestamp of when the password was created. |
|
213 * @type int|null $last_used The Unix timestamp of the GMT date the application password was last used. |
|
214 * @type string|null $last_ip The IP address the application password was last used by. |
|
215 * } |
208 */ |
216 */ |
209 public static function get_user_application_password( $user_id, $uuid ) { |
217 public static function get_user_application_password( $user_id, $uuid ) { |
210 $passwords = static::get_user_application_passwords( $user_id ); |
218 $passwords = static::get_user_application_passwords( $user_id ); |
211 |
219 |
212 foreach ( $passwords as $password ) { |
220 foreach ( $passwords as $password ) { |
241 |
249 |
242 /** |
250 /** |
243 * Updates an application password. |
251 * Updates an application password. |
244 * |
252 * |
245 * @since 5.6.0 |
253 * @since 5.6.0 |
|
254 * @since 6.8.0 The actual password should now be hashed using wp_fast_hash(). |
246 * |
255 * |
247 * @param int $user_id User ID. |
256 * @param int $user_id User ID. |
248 * @param string $uuid The password's UUID. |
257 * @param string $uuid The password's UUID. |
249 * @param array $update Information about the application password to update. |
258 * @param array $update { |
|
259 * Information about the application password to update. |
|
260 * |
|
261 * @type string $uuid The unique identifier for the application password. |
|
262 * @type string $app_id A UUID provided by the application to uniquely identify it. |
|
263 * @type string $name The name of the application password. |
|
264 * @type string $password A one-way hash of the password. |
|
265 * @type int $created Unix timestamp of when the password was created. |
|
266 * @type int|null $last_used The Unix timestamp of the GMT date the application password was last used. |
|
267 * @type string|null $last_ip The IP address the application password was last used by. |
|
268 * } |
250 * @return true|WP_Error True if successful, otherwise a WP_Error instance is returned on error. |
269 * @return true|WP_Error True if successful, otherwise a WP_Error instance is returned on error. |
251 */ |
270 */ |
252 public static function update_application_password( $user_id, $uuid, $update = array() ) { |
271 public static function update_application_password( $user_id, $uuid, $update = array() ) { |
253 $passwords = static::get_user_application_passwords( $user_id ); |
272 $passwords = static::get_user_application_passwords( $user_id ); |
254 |
273 |
278 |
297 |
279 /** |
298 /** |
280 * Fires when an application password is updated. |
299 * Fires when an application password is updated. |
281 * |
300 * |
282 * @since 5.6.0 |
301 * @since 5.6.0 |
|
302 * @since 6.8.0 The password is now hashed using wp_fast_hash() instead of phpass. |
|
303 * Existing passwords may still be hashed using phpass. |
283 * |
304 * |
284 * @param int $user_id The user ID. |
305 * @param int $user_id The user ID. |
285 * @param array $item The updated app password details. |
306 * @param array $item { |
|
307 * The updated application password details. |
|
308 * |
|
309 * @type string $uuid The unique identifier for the application password. |
|
310 * @type string $app_id A UUID provided by the application to uniquely identify it. |
|
311 * @type string $name The name of the application password. |
|
312 * @type string $password A one-way hash of the password. |
|
313 * @type int $created Unix timestamp of when the password was created. |
|
314 * @type int|null $last_used The Unix timestamp of the GMT date the application password was last used. |
|
315 * @type string|null $last_ip The IP address the application password was last used by. |
|
316 * } |
286 * @param array $update The information to update. |
317 * @param array $update The information to update. |
287 */ |
318 */ |
288 do_action( 'wp_update_application_password', $user_id, $item, $update ); |
319 do_action( 'wp_update_application_password', $user_id, $item, $update ); |
289 |
320 |
290 return true; |
321 return true; |
402 * Sets a user's application passwords. |
433 * Sets a user's application passwords. |
403 * |
434 * |
404 * @since 5.6.0 |
435 * @since 5.6.0 |
405 * |
436 * |
406 * @param int $user_id User ID. |
437 * @param int $user_id User ID. |
407 * @param array $passwords Application passwords. |
438 * @param array $passwords { |
408 * |
439 * The list of application passwords. |
409 * @return bool |
440 * |
|
441 * @type array ...$0 { |
|
442 * @type string $uuid The unique identifier for the application password. |
|
443 * @type string $app_id A UUID provided by the application to uniquely identify it. |
|
444 * @type string $name The name of the application password. |
|
445 * @type string $password A one-way hash of the password. |
|
446 * @type int $created Unix timestamp of when the password was created. |
|
447 * @type int|null $last_used The Unix timestamp of the GMT date the application password was last used. |
|
448 * @type string|null $last_ip The IP address the application password was last used by. |
|
449 * } |
|
450 * } |
|
451 * @return int|bool User meta ID if the key didn't exist (ie. this is the first time that an application password |
|
452 * has been saved for the user), true on successful update, false on failure or if the value passed |
|
453 * is the same as the one that is already in the database. |
410 */ |
454 */ |
411 protected static function set_user_application_passwords( $user_id, $passwords ) { |
455 protected static function set_user_application_passwords( $user_id, $passwords ) { |
412 return update_user_meta( $user_id, static::USERMETA_KEY_APPLICATION_PASSWORDS, $passwords ); |
456 return update_user_meta( $user_id, static::USERMETA_KEY_APPLICATION_PASSWORDS, $passwords ); |
413 } |
457 } |
414 |
458 |
418 * @since 5.6.0 |
462 * @since 5.6.0 |
419 * |
463 * |
420 * @param string $raw_password The raw application password. |
464 * @param string $raw_password The raw application password. |
421 * @return string The chunked password. |
465 * @return string The chunked password. |
422 */ |
466 */ |
423 public static function chunk_password( $raw_password ) { |
467 public static function chunk_password( |
|
468 #[\SensitiveParameter] |
|
469 $raw_password |
|
470 ) { |
424 $raw_password = preg_replace( '/[^a-z\d]/i', '', $raw_password ); |
471 $raw_password = preg_replace( '/[^a-z\d]/i', '', $raw_password ); |
425 |
472 |
426 return trim( chunk_split( $raw_password, 4, ' ' ) ); |
473 return trim( chunk_split( $raw_password, 4, ' ' ) ); |
427 } |
474 } |
|
475 |
|
476 /** |
|
477 * Hashes a plaintext application password. |
|
478 * |
|
479 * @since 6.8.0 |
|
480 * |
|
481 * @param string $password Plaintext password. |
|
482 * @return string Hashed password. |
|
483 */ |
|
484 public static function hash_password( |
|
485 #[\SensitiveParameter] |
|
486 string $password |
|
487 ): string { |
|
488 return wp_fast_hash( $password ); |
|
489 } |
|
490 |
|
491 /** |
|
492 * Checks a plaintext application password against a hashed password. |
|
493 * |
|
494 * @since 6.8.0 |
|
495 * |
|
496 * @param string $password Plaintext password. |
|
497 * @param string $hash Hash of the password to check against. |
|
498 * @return bool Whether the password matches the hashed password. |
|
499 */ |
|
500 public static function check_password( |
|
501 #[\SensitiveParameter] |
|
502 string $password, |
|
503 string $hash |
|
504 ): bool { |
|
505 if ( ! str_starts_with( $hash, '$generic$' ) ) { |
|
506 /* |
|
507 * If the hash doesn't start with `$generic$`, it is a hash created with `wp_hash_password()`. |
|
508 * This is the case for application passwords created before 6.8.0. |
|
509 */ |
|
510 return wp_check_password( $password, $hash ); |
|
511 } |
|
512 |
|
513 return wp_verify_fast_hash( $password, $hash ); |
|
514 } |
428 } |
515 } |