| @@ -170,9 +170,9 @@ | ||
| 170 | 170 | // Single, fixed error code for every failure mode — never echo a |
| 171 | 171 | // code that distinguishes a valid username from an invalid one. |
| 172 | 172 | $this->errors['authentication'] = $user->get_error_code(); |
| 173 | 173 | } else { |
| 174 | - $this->data['nonce'] = $this->plugin->auth->create_nonce( 'pd_api' ); | |
| 174 | + $this->data['nonce'] = $this->plugin->auth->create_nonce( 'pd_api', $user->ID ); | |
| 175 | 175 | } |
| 176 | 176 | |
| 177 | 177 | $this->return_response(); |
| 178 | 178 | } |
| @@ -183,10 +183,19 @@ | ||
| 183 | 183 | $this->errors['nonce'] = 'Required for authenticated requests'; |
| 184 | 184 | $this->return_response(); |
| 185 | 185 | } |
| 186 | 186 | |
| 187 | - if ( ! $this->plugin->auth->verify_nonce( $this->params['nonce'], 'pd_api' ) ) { | |
| 187 | + $nonce_user_id = $this->plugin->auth->verify_nonce( $this->params['nonce'], 'pd_api' ); | |
| 188 | + if ( empty( $nonce_user_id ) ) { | |
| 188 | 189 | $this->errors['nonce'] = 'Invalid'; |
| 190 | + $this->return_response(); | |
| 191 | + } | |
| 192 | + | |
| 193 | + // The nonce is bound to the user it was issued for. Re-check that user still | |
| 194 | + // has plugin-management rights so a token can never authorize more than its | |
| 195 | + // owner, even if it leaks or the user's role is later downgraded. | |
| 196 | + if ( ! user_can( $nonce_user_id, 'activate_plugins' ) ) { | |
| 197 | + $this->errors['permission'] = 'You do not have permission to perform this action'; | |
| 189 | 198 | $this->return_response(); |
| 190 | 199 | } |
| 191 | 200 | |
| 192 | 201 | |