barrel_mcp_request_state (barrel_mcp v3.0.1)
View SourceOpaque, integrity-protected request state for MRTR.
Under Multi Round-Trip Requests a server that needs more input answers with an InputRequiredResult and finishes the request. The client then retries, echoing back a requestState string. That is how the server picks up where it left off without keeping anything server-side, which is what lets a retry land on a different node.
The catch is that the state travels through the client, so it is attacker-controlled input by construction. The spec requires integrity protection and rejection of state that fails verification. This module seals a term into a blob authenticated with HMAC-SHA256, bound to:
- the authenticated principal, so one caller cannot present another's state;
- an expiry, so a captured blob is not useful indefinitely;
- the originating method and its salient parameters, so state from one call cannot be replayed onto a different one.
These bound the replay window and stop cross-user and cross-request reuse. They do not make a blob single-use: a server that needs that (a one-time redemption, say) has to enforce it itself.
The signing key
From the request_state_key environment variable. Without one, an ephemeral key is generated per node, which is fine for a single node and wrong for a cluster: a retry landing on another node fails verification. A warning is logged once so that is not discovered in production.
Summary
Functions
Describe what a piece of state is allowed to be replayed onto.
Return the signing key, generating an ephemeral one if none is configured. Called at application start so that generation cannot race between concurrent requests.
Seal a term into an opaque blob for the client to echo back.
Recover a sealed term, or say why it cannot be trusted.
Types
Functions
Describe what a piece of state is allowed to be replayed onto.
Params is the request's params as they arrived. The fields a retry legitimately adds are excluded from the digest, so echoing state back with inputResponses filled in still matches.
-spec ensure_key() -> binary().
Return the signing key, generating an ephemeral one if none is configured. Called at application start so that generation cannot race between concurrent requests.
Seal a term into an opaque blob for the client to echo back.
Recover a sealed term, or say why it cannot be trusted.
The MAC is checked before anything is deserialised, so a forged blob never reaches binary_to_term/2.