|WP_Error WP_Error if the connection is not found. */ public function create_auth_headers( int $connection_id, string $method, string $route_path, string $body = '' ): array|WP_Error { $connection = $this->connections->find_by_id( $connection_id ); if ( null === $connection ) { return new WP_Error( 'shiftora_connection_not_found', "Connection {$connection_id} not found." ); } return $this->create_auth_headers_for_connection( $connection, $method, $route_path, $body ); } /** * Auth headers for an already-loaded connection row. * * `$method`, `$route_path` and `$body` are unused and kept for call-site compatibility. * * @return array */ public function create_auth_headers_for_connection( object $connection, string $method = 'GET', string $route_path = '', string $body = '' ): array { $secret = $this->connections->get_remote_token( $connection ); $timestamp = (string) time(); $body_hash = '' === $body ? '' : hash( 'sha256', $body, false ); $payload = strtoupper( $method ) . "\n" . $route_path . "\n" . $timestamp . "\n" . $body_hash; $signature = hash_hmac( 'sha256', $payload, (string) $secret, false ); $signing = [ 'X-Shiftora-Timestamp' => $timestamp, 'X-Shiftora-Body-Hash' => $body_hash, 'X-Shiftora-Signature' => $signature, ]; // The secret signs every request, so it need not travel. A peer that accepts the // key id is named by the hash; one that predates it still has to be sent the token. $remote_url = (string) ( $connection->remote_url ?? '' ); if ( '' !== $remote_url && HttpClient::peer_accepts_key_id( $remote_url ) ) { $key_id = Hasher::hash_token( (string) $secret ); HttpClient::remember_secret( $key_id, (string) $secret ); return [ 'X-Shiftora-Key-Id' => $key_id ] + $signing; } self::note_token_on_wire( $remote_url ); return [ 'X-Shiftora-Token' => (string) $secret ] + $signing; } /** Said once per request: the other site is on a build that needs the token on the wire. */ private static function note_token_on_wire( string $remote_url ): void { static $noted = []; if ( isset( $noted[ $remote_url ] ) ) { return; } $noted[ $remote_url ] = true; ServerLog::write( '[Shiftora] ' . $remote_url . ' has not said it accepts a key id, so its token is sent in the request. Update Shiftora there.' ); } }