Module: BSV::Auth::AuthHeaders

Defined in:
lib/bsv/auth/auth_headers.rb

Overview

BRC-104 HTTP header name constants and filtering helpers.

Provides the canonical header names used in BSV auth HTTP transport, matching the Go SDK’s brc104/auth_http_headers.go exactly.

Header filtering:

  • Requests: content-type (normalised), authorization, x-bsv-* (excl. x-bsv-auth-*)

  • Responses: authorization, x-bsv-* (excl. x-bsv-auth-*) — content-type is NOT signed

Both AuthHeaders.filter_request_headers and AuthHeaders.filter_response_headers return sorted

key, value

pairs ready for payload serialisation.

Constant Summary collapse

AUTH_PREFIX =

Common prefix for all BSV auth headers.

'x-bsv-auth'
PAYMENT_PREFIX =

Prefix for BSV payment headers (excluded from signed payload).

'x-bsv-payment'
BSV_PREFIX =

Prefix for all BSV custom headers (non-auth).

'x-bsv-'
VERSION =

Protocol version header.

'x-bsv-auth-version'
IDENTITY_KEY =

Sender’s identity public key (compressed hex).

'x-bsv-auth-identity-key'
NONCE =

Sender’s nonce.

'x-bsv-auth-nonce'
YOUR_NONCE =

Recipient’s nonce (echoed back for mutual verification).

'x-bsv-auth-your-nonce'
REQUEST_ID =

Request ID for correlation (base64-encoded 32 bytes).

'x-bsv-auth-request-id'
MESSAGE_TYPE =

Message type string (e.g. ‘general’, ‘initialRequest’).

'x-bsv-auth-message-type'
SIGNATURE =

ECDSA/Schnorr signature (hex-encoded).

'x-bsv-auth-signature'
REQUESTED_CERTIFICATES =

Requested certificate set (JSON-encoded).

'x-bsv-auth-requested-certificates'
PAYMENT_VERSION =

Payment protocol version.

'x-bsv-payment-version'
PAYMENT_SATOSHIS_REQUIRED =

Number of satoshis required for payment.

'x-bsv-payment-satoshis-required'
PAYMENT_DERIVATION_PREFIX =

BIP-32 derivation prefix for payment key.

'x-bsv-payment-derivation-prefix'
PAYMENT =

Raw payment transaction (hex or base64).

'x-bsv-payment'

Class Method Summary collapse

Class Method Details

.extract_auth_headers(headers) ⇒ Hash

Extracts x-bsv-auth-* headers from a hash and returns a structured hash with symbolised keys derived from the header name suffix.

For example, x-bsv-auth-identity-key becomes :identity_key.

Parameters:

  • headers (Hash)

    incoming headers hash (keys may be mixed case)

Returns:

  • (Hash)

    symbolised auth header values; only present keys are included



135
136
137
138
139
140
141
142
143
144
145
146
147
# File 'lib/bsv/auth/auth_headers.rb', line 135

def extract_auth_headers(headers)
  prefix = "#{AUTH_PREFIX}-"
  result = {}
  headers.each do |k, v|
    key = k.to_s.downcase
    next unless key.start_with?(prefix)

    suffix = key[prefix.length..]
    symbol_key = suffix.tr('-', '_').to_sym
    result[symbol_key] = v
  end
  result
end

.filter_request_headers(headers) ⇒ Array<Array(String, String)>

Filters request headers to the set that is signed in the payload.

Includes (matching TS/Go SDK behaviour):

  • content-type — normalised by stripping “; charset=…” params

  • authorization

  • x-bsv-* headers, excluding any that start with x-bsv-auth

Raises ArgumentError if any header does not fall into the above categories (matching TS SDK strictness — an unsupported header that the caller expects to be signed is a security concern).

Parameters:

  • headers (Hash)

    header key/value pairs (keys need not be lowercased)

Returns:

  • (Array<Array(String, String)>)

    sorted [key, value] pairs, keys lowercased

Raises:

  • (ArgumentError)

    if an unsupported header is present



78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
# File 'lib/bsv/auth/auth_headers.rb', line 78

def filter_request_headers(headers)
  result = []
  headers.each do |k, v|
    key = k.to_s.downcase
    if key.start_with?(BSV_PREFIX)
      raise ArgumentError, "BSV auth headers are not allowed in the request payload: #{key}" if key.start_with?(AUTH_PREFIX)
      next if key.start_with?(PAYMENT_PREFIX) # payment headers are transport-level, not signed

      result << [key, v.to_s]
    elsif key == 'authorization'
      result << [key, v.to_s]
    elsif key == 'content-type'
      # Normalise: strip parameters like "; charset=utf-8"
      normalised = v.to_s.split(';').first.to_s.strip
      result << [key, normalised]
    else
      raise ArgumentError,
            'Unsupported header in the simplified fetch implementation. ' \
            "Only content-type, authorization, and x-bsv-* headers are supported. Got: #{key}"
    end
  end
  result.sort_by { |key, _| key }
end

.filter_response_headers(headers) ⇒ Array<Array(String, String)>

Filters response headers to the set that is signed in the payload.

Includes (matching TS/Go SDK behaviour):

  • authorization

  • x-bsv-* headers, excluding any that start with x-bsv-auth

Note: content-type is intentionally excluded from response signing (matches both Go and TS SDK behaviour).

Parameters:

  • headers (Hash)

    header key/value pairs

Returns:

  • (Array<Array(String, String)>)

    sorted [key, value] pairs, keys lowercased



113
114
115
116
117
118
119
120
121
122
123
124
125
126
# File 'lib/bsv/auth/auth_headers.rb', line 113

def filter_response_headers(headers)
  result = []
  headers.each do |k, v|
    key = k.to_s.downcase
    if key.start_with?(BSV_PREFIX)
      next if key.start_with?(AUTH_PREFIX)

      result << [key, v.to_s]
    elsif key == 'authorization'
      result << [key, v.to_s]
    end
  end
  result.sort_by { |key, _| key }
end