beckn / beckn/protocol-specifications-v2
Normative gap in AckSignature — undefined behaviour when inbound Authorization is absent
- Dominant language
- No language data
- Stars
- 15
- Forks
- 13
- PR merge metrics
- No merged PRs in 30d
Description
In the draft branch-
---
**Summary**
PR #155 mandates that all synchronous responses MUST use the 4-line `AckSignature` signing string (CON-004-23), but provides no guidance for the case where the inbound request carries no parseable `Authorization` header — the exact condition that triggers a 401 NackUnauthorized response. The `request-signature` field has no value to be populated from, leaving the spec silent on what the responder must do.
---
**Description**
### Background
PR #155 introduces `AckSignature` — a fourth line `request-signature` is added to the Ack response signing string, binding the response cryptographically to the specific inbound request:
```
(created): {unix_timestamp}
(expires): {unix_timestamp}
digest: BLAKE2b-512={response_body_hash}
request-signature: {inbound_request_raw_base64_signature}
```
CON-004-23 states this is a MUST for all synchronous responses, with no exceptions listed.
### The problem
A 401 NackUnauthorized response is returned when the inbound request's `Authorization` header is:
- Absent entirely
- Present but structurally malformed (unparseable)
- Present but with an expired or invalid signature
In all three sub-cases the responder either has no signature value to extract, or has a signature value that has already failed verification. The spec does not say what value — if any — populates `request-signature` in the AckSignature signing string for the 401 response.
Without a normative rule here, two compliant implementations will behave differently:
- Implementation A uses a 3-line signing string (drops `request-signature` and the `headers` attribute becomes `"(created) (expires) digest"`)
- Implementation B uses a 4-line signing string with an empty string or placeholder for `request-signature`
- Implementation C uses the raw (unverified) value extracted from the malformed header
None of these is correct or incorrect per the current spec text. They will fail to interoperate when one party verifies the other's 401 response.
### Why this matters
The 401 case is not a rare edge. It is the primary response when a new network participant misconfigures their key, when clock skew causes signature expiry, or when an attack probe hits the endpoint. These are operationally frequent. Implementers will hit this on day one of integration.
### Proposed resolution
Two options for the spec team to choose between:
**Option A — Exception to CON-004-23 for absent Authorization**
When the inbound request carries no `Authorization` header or a structurally unparseable one, the responder MUST use the 3-line standard signing string (§3.2) with `headers="(created) (expires) digest"`. The `AckSignature` requirement applies only when a well-formed Authorization header was received, regardless of whether signature verification passed.
**Option B — Sentinel value for absent Authorization**
Define a normative sentinel string (e.g. empty string, or the literal `"none"`) to be used as `request-signature` when no Authorization value is available. Specify that the verifier MUST accept this sentinel and MUST NOT fail verification on a 401 response that uses it.
Option A is recommended — it is the simpler rule, requires no sentinel definition, and is consistent with the existing callback spec which has a similar exception for provider-initiated notifications (§6, §10.3).
### References
- PR #155 — Add AckSignature as third signature type
- CON-004-23 (introduced in PR #155)
- §3.4 Ack Response Signing String (introduced in PR #155)
- §6 Callback Signing — BPP to BAP (existing exception for provider-initiated notifications)
- Issue #141 — original non-repudiation discussion
Contributor guide
Assessment
This issue has not been assessed yet.