PluginProbe
WCPOS – Point of Sale (POS) plugin for WooCommerce / 1.10.21
WCPOS – Point of Sale (POS) plugin for WooCommerce v1.10.21
1.10.22 1.10.21 1.10.20 1.10.19 1.10.18 1.10.17 1.10.16 1.10.15 1.10.13 1.10.14 1.10.12 1.10.11 1.10.10 1.10.9 1.10.8 untagged-3d9b7ccddc54df87c672 1.10.7 1.10.6 1.10.5 1.10.3 1.10.4 1.10.2 1.10.1 1.10.0 1.9.17 All 166 releases
← All changes | includes/Services/Auth.php +56 -7 1.10.20 → 1.10.21 View file →
@@ -85,8 +85,46 @@
85 85 return self::$instance;
86 86 }
87 87
88 88 /**
89 + * On `wp_logout`: end the web POS session named by this browser's cookie.
90 + *
91 + * Sessions of native apps and other browsers stay live. The cookie itself is left alone.
92 + *
93 + * @param mixed $user_id ID of the user logging out.
94 + */
95 + public static function revoke_web_session_on_logout( $user_id ): void {
96 + if ( absint( $user_id ) > 0 ) {
97 + self::instance()->cleanup_previous_web_session( absint( $user_id ) );
98 + }
99 + }
100 +
101 + /**
102 + * On `password_reset`: end every POS session of the user.
103 + *
104 + * @param mixed $user User whose password is being reset.
105 + */
106 + public static function revoke_sessions_on_password_reset( $user ): void {
107 + if ( $user instanceof WP_User ) {
108 + self::instance()->revoke_all_refresh_tokens( $user->ID );
109 + }
110 + }
111 +
112 + /**
113 + * On `profile_update`: end every POS session of the user when the password changed.
114 + *
115 + * @param mixed $user_id ID of the updated user.
116 + * @param mixed $old_user_data User data before the update.
117 + */
118 + public static function revoke_sessions_on_password_change( $user_id, $old_user_data = null ): void {
119 + $user = get_userdata( absint( $user_id ) );
120 +
121 + if ( $old_user_data instanceof WP_User && $user instanceof WP_User && $old_user_data->user_pass !== $user->user_pass ) {
122 + self::instance()->revoke_all_refresh_tokens( $user->ID );
123 + }
124 + }
125 +
126 + /**
89 127 * Extract a WCPOS token from an authorization value.
90 128 *
91 129 * @param mixed $auth_value Authorization value.
92 130 *
@@ -250,15 +288,24 @@
250 288 array( 'status' => 403 )
251 289 );
252 290 }
253 291
254 - // The session is live: record that, so eviction can tell a device that is
255 - // working right now from one that has not been seen in a week.
292 + // The session registry is authoritative; the blacklist transient above is only a
293 + // fast path that can be evicted or purged. Once the session is live, record that,
294 + // so eviction can tell a device working right now from one unseen for a week.
256 295 if ( isset( $decoded_token->refresh_jti ) ) {
257 - $this->sessions->touch(
258 - absint( $decoded_token->data->user->id ),
259 - (string) $decoded_token->refresh_jti
260 - );
296 + $user_id = absint( $decoded_token->data->user->id );
297 + $refresh_jti = (string) $decoded_token->refresh_jti;
298 +
299 + if ( ! $this->sessions->is_live( $user_id, $refresh_jti ) ) {
300 + return new WP_Error(
301 + 'woocommerce_pos_auth_session_revoked',
302 + 'Session has been revoked',
303 + array( 'status' => 403 )
304 + );
305 + }
306 +
307 + $this->sessions->touch( $user_id, $refresh_jti );
261 308 }
262 309 }
263 310
264 311 // Everything looks good return the decoded token.
@@ -591,9 +638,11 @@
591 638 /*
592 639 * Before the first row read on this path. A refresh loads the whole session row —
593 640 * `is_live()` below, then `refresh_activity()` — so it needs
594 641 * the same protection a login has against a row too large to read (#1776).
595 - * Validating an ACCESS token needs no such guard: it no longer touches the row.
642 + * Validating an ACCESS token READS the row through `is_live()` but never writes it,
643 + * and runs no guard because `guard_row()` can write; the read primes the user meta
644 + * cache that WordPress fills anyway to read the user's capabilities, so it adds no query.
596 645 */
597 646 $this->sessions->guard_row( absint( $decoded->data->user->id ) );
598 647
599 648 // Check if refresh token is still valid (not revoked).