Class: Portage::Ucp::Rack::SignatureVerification
- Inherits:
-
Object
- Object
- Portage::Ucp::Rack::SignatureVerification
- Defined in:
- lib/portage/ucp/rack/signature_verification.rb
Overview
Generic Rack middleware wrapping an inbound MCP/UCP endpoint (however the consumer mounts it, §7.3 — this gem stays deployment-agnostic): verifies the RFC 9421 HTTP Message Signature over the request (Security::Signature, §22) before the wrapped app ever sees it.
Verify-before-parse (same posture as Rack::WebhookEndpoint): the body is read and handed to Signature.verify! as raw bytes, never parsed as JSON here. Only on success is it rewound for the wrapped app to read and parse (as JSON-RPC) itself.
Instance Method Summary collapse
- #call(env) ⇒ Object
-
#initialize(app, trusted_keys:, required_components: %w[@method @authority @path idempotency-key],, max_age: 300, logger: Portage::Ucp.configuration.logger) ⇒ SignatureVerification
constructor
A new instance of SignatureVerification.
Constructor Details
#initialize(app, trusted_keys:, required_components: %w[@method @authority @path idempotency-key],, max_age: 300, logger: Portage::Ucp.configuration.logger) ⇒ SignatureVerification
Returns a new instance of SignatureVerification.
24 25 26 27 28 29 30 31 |
# File 'lib/portage/ucp/rack/signature_verification.rb', line 24 def initialize(app, trusted_keys:, required_components: %w[@method @authority @path idempotency-key], max_age: 300, logger: Portage::Ucp.configuration.logger) @app = app @trusted_keys = trusted_keys @required_components = required_components @max_age = max_age @logger = logger end |
Instance Method Details
#call(env) ⇒ Object
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
# File 'lib/portage/ucp/rack/signature_verification.rb', line 33 def call(env) request = ::Rack::Request.new(env) body = request.body.read request.body.rewind Portage::Ucp::Security::Signature.verify!( method: request.request_method, authority: request.host_with_port, path: request.path, query: request.query_string.empty? ? nil : "?#{request.query_string}", headers: headers_from(env), body: body, trusted_keys: @trusted_keys, required_components: @required_components, max_age: @max_age ) @app.call(env) rescue Portage::Ucp::Security::SignatureError => e reject(e) end |