settings->credentials(); if ( null === $credentials ) { return $this->deny( 'storebridge_not_registered', 'This store is not connected to Storebridge.' ); } $key = (string) $request->get_header( Signer::HEADER_KEY ); $timestamp = (string) $request->get_header( Signer::HEADER_TIMESTAMP ); $signature = (string) $request->get_header( Signer::HEADER_SIGNATURE ); if ( '' === $key || '' === $timestamp || '' === $signature ) { return $this->deny( 'storebridge_missing_signature', 'The request is not signed.' ); } if ( ! hash_equals( $credentials['key_id'], $key ) ) { return $this->deny( 'storebridge_unknown_key', 'Unknown Storebridge key.' ); } // The raw request target is signed; sanitizing it would change it. $target = isset( $_SERVER['REQUEST_URI'] ) ? wp_unslash( $_SERVER['REQUEST_URI'] ) : ''; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized $failure = Signer::verify( $credentials['secret'], $timestamp, $signature, $request->get_method(), (string) $target, $request->get_body() ); if ( null !== $failure ) { return $this->deny( 'storebridge_' . $failure, 'The request signature is invalid.' ); } $replay_key = 'storebridge_sig_' . substr( $signature, 0, 40 ); if ( false !== get_transient( $replay_key ) ) { return $this->deny( 'storebridge_replayed', 'This request was already processed.' ); } set_transient( $replay_key, 1, 2 * Signer::WINDOW_SECONDS ); return true; } /** * Build a 401 error. * * @param string $code Error code. * @param string $message Message. */ private function deny( string $code, string $message ): WP_Error { return new WP_Error( $code, $message, array( 'status' => 401 ) ); } }