Internet-Draft OASNT July 2026
Thallapelly Expires 22 January 2027 [Page]
Workgroup:
Network Working Group
Internet-Draft:
draft-thallapelly-oasnt-00
Published:
Intended Status:
Standards Track
Expires:
Author:
A. Thallapelly
OmniArx

OASNT: Attested Action Authorization Tokens

Abstract

This document defines the OASNT token, a compact JWS-based credential in which a hardware-bound device key attests that a specific human, on a device whose runtime integrity was assessed, authorized one specific action whose human-readable disclosure is cryptographically bound to the token (What You See Is What You Sign). Tokens are single-use, short-lived, and may additionally be bound to one concrete HTTP request.

Status of This Memo

This Internet-Draft is submitted in full conformance with the provisions of BCP 78 and BCP 79.

Internet-Drafts are working documents of the Internet Engineering Task Force (IETF). Note that other groups may also distribute working documents as Internet-Drafts. The list of current Internet-Drafts is at https://datatracker.ietf.org/drafts/current/.

Internet-Drafts are draft documents valid for a maximum of six months and may be updated, replaced, or obsoleted by other documents at any time. It is inappropriate to use Internet-Drafts as reference material or to cite them other than as "work in progress."

This Internet-Draft will expire on 22 January 2027.

Table of Contents

1. Introduction

Systems increasingly execute consequential actions on a person's behalf without that person present at the moment of execution. Autonomous agents move funds, change access, and modify records, carrying credentials that prove only who issued them and to whom. Such a credential does not record that any human saw the operation it is now being used to perform.

Where a human approval step does exist, it is usually a server-side artifact: a flag on a session, a row in a table, a callback that fired. The approval and the executed operation are connected by application logic rather than by cryptography, so an incident review cannot establish what the approving person actually read. Nor can it establish anything about the device they read it on.

This document defines the OASNT token, which addresses both gaps in a single signed object. A key held in device-resident secure hardware signs a digest of the action to be performed, a digest of the disclosure text as it was rendered to the user, and optionally a fingerprint of the one concrete request the approval authorizes. The signed object also carries the device's own assessment of its runtime integrity at the moment of signing.

Binding the rendered disclosure, rather than only the operation, is the property this document treats as essential and is commonly called What You See Is What You Sign. Its absence is exploitable: a system that binds only the operation will accept a token whose operation digest was recomputed after the human approved something else. Section 7 therefore requires the disclosure binding and forbids falling back to operation binding alone.

OASNT is deliberately narrow. It expresses a single human authorization event as verifiable evidence. It does not describe delegation between components, policy evaluation, or how authority is attenuated as it passes through a system. Frameworks that address those concerns, including remote attestation procedures [RFC9334], can consume an OASNT token as the human-authorization evidence at the root of a chain they otherwise manage.

3. Conventions and Definitions

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, as shown here.

The term "disclosure" refers to the human-readable text presented to a user on a display, in the form in which the user read it, immediately before that user authorized an action.

4. Architecture

Three roles participate.

The minter runs on the user's device. It holds the signing key in secure hardware, renders the disclosure, obtains the user's approval, and produces the token. It is the only role that observes the human.

The enrollment service establishes, once per key, that the key is hardware-bound and belongs to the device it claims to. It records the key's thumbprint. Section 8 specifies this.

The verifier is the party about to execute the action. It holds the set of enrolled thumbprints, recomputes every binding from its own representation of what it is about to do, and accepts or refuses. Section 7 specifies this.

A typical exchange:

   verifier                 minter (device)          enrollment service
      |                           |                          |
      |                           |---- attested key ------->|
      |                           |<--- enrolled ------------|
      |                           |                          |
      | -- action + disclosure -->|                          |
      |                           | renders disclosure       |
      |                           | user approves            |
      |                           | hardware key signs       |
      |<------- token ------------|                          |
      | recompute adg, dsp, rqf   |                          |
      | accept or refuse          |                          |

How the action reaches the device, and how the token returns, are out of scope. The token is self-contained and its verification does not depend on the channel that carried it.

Two properties follow from this arrangement and are relied on throughout.

First, the verifier never trusts the token for anything it can compute itself. Every digest is recomputed from the verifier's own view of the action and request. The token supplies only digests to compare against and a key identifier to look up.

Second, the party that observes the human is the party that holds the key. The disclosure binding is meaningful only because rendering and signing happen inside the same trust boundary. Section 9.2 states the limits of that assumption.

5. Token Format

An OASNT token is a JWS [RFC7515] in compact serialization.

5.1. JOSE Header

The protected header MUST consist of exactly the members alg and typ, with the values shown:

{"alg":"ES256","typ":"oasnt+jwt"}

A verifier MUST reject a token whose alg is not ES256 or whose typ is not oasnt+jwt. Algorithm agility is deliberately not offered; see Section 9.1.

5.2. Signature

The signature is ECDSA using P-256 and SHA-256, encoded as the concatenation R || S of two 32-octet big-endian integers (64 octets total), base64url encoded without padding per [RFC7515]. A verifier MUST reject a signature whose decoded length is not exactly 64 octets.

5.3. Claims

The JWS payload is a JSON object [RFC8259] containing the following members. All digest-valued claims are base64url [RFC4648] encoded without padding, over a SHA-256 [RFC6234] digest.

Table 1
Claim Type Presence Binds
sub string REQUIRED the subject the token was issued for
adg string REQUIRED the action to be executed (Section 6.2)
dsp string REQUIRED the disclosure the human read (Section 6.3)
rqf string OPTIONAL one concrete request (Section 6.4)
int string REQUIRED device runtime integrity at signing time
jti string REQUIRED single-use nonce
iat number REQUIRED issuance time, seconds since the epoch
exp number REQUIRED expiry, seconds since the epoch
cnf object REQUIRED key confirmation; contains jkt

cnf.jkt is the JWK thumbprint [RFC7638] of the public key corresponding to the signing key.

int takes exactly one of the values clean, compromised, or unknown. It is asserted by the device, not proven by the token; see Section 9.3.

The payload is signed as serialized. Member order is at the minter's discretion and carries no meaning, because verification recomputes the signature over the octets as received and never re-serializes the payload. An implementation MUST NOT depend on member order.

An OPTIONAL claim that is absent MUST be omitted entirely rather than included with an empty or null value. This distinction is load-bearing: Section 7 requires a verifier to distinguish "not bound to a request" from "bound to a request that does not match".

6. Canonicalization

Three canonical encodings are defined. Each is hashed with SHA-256 and base64url encoded to produce a claim value. None of them is ever parsed; they exist only to be produced deterministically and hashed.

6.1. Key ordering

Wherever this document specifies that parameters are sorted, they MUST be sorted in ascending lexicographic order of the UTF-8 octet sequence of the parameter name.

Implementations MUST NOT sort by UTF-16 code unit, which is the default string ordering in some languages and which differs from UTF-8 octet order for names containing characters outside the Basic Multilingual Plane. Two implementations disagreeing here will produce different digests for the same action and fail to interoperate.

Parameter names MUST be unique within an action. A duplicate name MUST cause the minter to fail rather than resolve the duplicate.

6.2. Canonical action

The canonical action is:

escape(type) "|"
  escape(k1) "=" escape(v1) "&"
  escape(k2) "=" escape(v2) ...

(shown wrapped for width; the canonical string contains no line breaks)

where parameters are ordered per Section 6.1, and escape() prefixes each occurrence of the four octets \, |, =, and & with a single \. Each input octet is classified exactly once; the escape prefix introduced for one octet is never itself re-escaped.

The | separator is emitted even when there are no parameters.

adg is the base64url encoding of the SHA-256 digest of this string.

Escaping is what prevents a parameter value from impersonating a separator. Without it, the parameter pair (a, b&c=d) and the pair set {(a,b), (c,d)} would produce identical canonical strings and thus identical digests.

6.3. Canonical display

The canonical display is the disclosure text, constructed as the type followed, for each parameter in the order of Section 6.1, by a line feed (0x0A), the parameter name, a colon, a space, and the parameter value:

escape(type)
  LF escape(k1) ": " escape(v1)
  LF escape(k2) ": " escape(v2) ...

(shown wrapped for width; LF marks the only line breaks the string contains)

Here escape() replaces each \ with \\ and each line feed with the two characters \n, in that order, and performs no other transformation.

dsp is the base64url encoding of the SHA-256 digest of this string.

This string is what the human reads. A verifier that recomputes dsp is asserting that the octets displayed to the user are the octets the user's key signed. See Section 9.2 for the boundary of that assertion.

6.4. Request fingerprint

The request fingerprint binds a token to one concrete request. It is the base64url encoding of the SHA-256 digest of:

method 0x00 path 0x00 org-id 0x00 scope 0x00 body-digest

where body-digest is the raw 32-octet SHA-256 digest of the request body, and the digest of the empty string is used when there is no body. The four text fields are UTF-8 encoded and MUST NOT contain a NUL octet; a minter or verifier encountering one MUST treat the input as invalid rather than attempt to encode it.

The NUL separators make the encoding unambiguous for fields that may themselves contain any non-NUL octet. body-digest is appended raw rather than hex- or base64-encoded, and is fixed-length, so no separator follows it.

7. Verification Procedure

A verifier MUST perform the following checks. Every failure is terminal: a token that fails any check MUST be refused, and MUST NOT be accepted on weaker terms.

The order below is normative only where a later step depends on an earlier one having established its precondition. Implementations are RECOMMENDED to evaluate all applicable checks and report the complete set of failures, as this materially assists integration; see Section 7.2.

  1. Structure. The token MUST consist of exactly three base64url segments separated by two . characters, and the first two MUST decode to well-formed JSON objects.

  2. Header. alg MUST equal ES256 and typ MUST equal oasnt+jwt.

  3. Key lookup. The verifier MUST look up cnf.jkt among keys that have completed enrollment (Section 8). A thumbprint that is absent, malformed, or not enrolled MUST be refused. The verifier MUST NOT accept a key supplied by the token itself.

  4. Signature. The signature MUST verify under the enrolled public key over the octets BASE64URL(header) "." BASE64URL(payload) exactly as received.

  5. Thumbprint confirmation. The verifier MUST recompute the JWK thumbprint of the enrolled key and confirm it equals cnf.jkt.

  6. Expiry. exp MUST be a number and MUST be greater than or equal to the current time.

  7. Issuance. iat MUST be a number and MUST NOT be more than a small tolerance in the future. Implementations SHOULD use 5 seconds.

  8. Replay. jti MUST be present and MUST NOT have been seen before. See step 12 for when it is recorded.

  9. Action binding. adg MUST equal the digest recomputed per Section 6.2 over the action the verifier is about to execute. The verifier MUST recompute this from its own representation of that action and MUST NOT use any value carried in the token.

  10. Intent binding. dsp MUST be present and MUST equal the digest recomputed per Section 6.3 over that same action. A token lacking dsp MUST be refused rather than accepted as action-bound only.

  11. Request binding. If the verifier is authorizing a concrete request, then rqf MUST be present and MUST equal the fingerprint recomputed per Section 6.4 over that request. A token lacking rqf MUST be refused in this case. If the verifier is not authorizing a concrete request, rqf is ignored.

  12. Integrity. int MUST equal clean.

  13. Commit. Only if every preceding check passed, the verifier MUST record jti as seen.

7.1. Reserve and commit

Step 13 is deliberately last. A verifier that records jti when it first observes the claim can be induced to consume the nonce of a legitimate token: an attacker who observes a token in flight may alter any octet and submit the result, which fails signature verification but, under a record-on-sight implementation, has already burned the nonce. The genuine token is then refused as a replay when it arrives.

Recording the nonce only after full validation removes this. A token that fails any check leaves no trace, so an unforgeable copy cannot deny service to the token it was copied from.

7.2. Reporting refusal reasons

Refusals are not interchangeable, and an integrator debugging a deployment needs to distinguish a clock problem from a replay from a downgrade attempt. Implementations are RECOMMENDED to return a distinguishable reason per failed check.

Reasons SHOULD NOT be returned to an untrusted caller where doing so would reveal whether a given key is enrolled or whether a given nonce has been seen.

8. Enrollment and Key Attestation

A verifier accepts a token only if cnf.jkt names a key that completed enrollment. Enrollment establishes, once, that the key is resident in device secure hardware and that the party presenting it controls it.

8.1. Challenge

The enrollment service MUST issue a random challenge of at least 32 octets, bound to the subject enrolling, with a bounded lifetime. Implementations SHOULD use 300 seconds.

A challenge MUST be single-use. It MUST be consumed on first presentation whether or not enrollment subsequently succeeds, so that a failed attempt cannot be retried against the same challenge. A challenge that is unknown, already consumed, or expired MUST cause enrollment to fail.

8.2. Platform attestation

The enrolling party presents a platform attestation over the challenge. The service MUST verify, at minimum:

  1. that the attestation chains to a trusted root for the claimed platform;

  2. that the challenge inside the attestation equals the challenge issued;

  3. that the attested key is hardware-backed;

  4. that the attested public key equals the key being enrolled.

Check 4 is what prevents an attacker from presenting a genuine attestation obtained elsewhere while enrolling a key they control. The service MUST compare the thumbprint of the attested key with the thumbprint of the presented key and MUST refuse on any difference.

For Android Key Attestation, the security level recorded in the attestation extension MUST indicate a trusted execution environment or a dedicated secure element. An attestation reporting a software-only security level MUST be refused.

For Apple App Attest, the service MUST verify the attestation object's certificate chain to the Apple root, that the nonce extension equals SHA-256(authenticatorData || SHA-256(challenge)), and that the relying-party identifier hash in the authenticator data equals SHA-256 of the expected application identifier.

8.3. Storage

On success the service records the subject, the public key, and its thumbprint [RFC7638]. Verifiers look up keys by thumbprint alone.

8.4. Deployment without attestation

A deployment may record a key without verifying a platform attestation, for example where an enrollment service has not been configured with trusted roots. Such a deployment does not provide the properties this document describes. Every guarantee here reduces to the enrollment check, and a key admitted without attestation is not known to be hardware-bound. Implementations SHOULD make this mode impossible to enable in a production configuration.

9. Security Considerations

9.1. Signature algorithm

ES256 is mandated rather than negotiated. The signing key is required to be hardware-bound (Section 8), and P-256 is the curve available across the mobile secure elements this document targets. In particular, at the time of writing, the iOS Secure Enclave supports P-256 and does not support Ed25519, so a specification mandating Ed25519 for this purpose could not be satisfied by a hardware-bound key on that platform.

Offering algorithm agility in the header would also reintroduce the algorithm-substitution attacks that a fixed alg forecloses.

9.2. The display trust boundary

The dsp claim binds the octets that were rendered. It does not, and cannot, prove that a human read them, that the rendering was legible, or that the operating system's display path was honest. WYSIWYS holds only to the extent that the platform's rendering and input path is intact, which is precisely what the runtime integrity assessment behind int exists to assess.

A verifier MUST NOT interpret a valid dsp as proof of comprehension or consent in any legal sense. It proves that the signing key signed a digest of specific displayed octets.

9.3. Device-asserted integrity

int is asserted by software on the device. A device whose runtime is fully compromised may assert clean. The claim raises the cost of an attack and records a verdict for audit; it is not a proof.

Relying parties SHOULD treat int as one input to a risk decision rather than as a guarantee, and SHOULD prefer platform attestation (Section 8) as the stronger signal.

9.4. Canonicalization ambiguity

Both hashed encodings are injective over their inputs only because of the escaping rules in Section 6. An implementation that omits escaping, or that escapes in a different order, will admit distinct actions with identical digests, which defeats action binding entirely.

The ordering requirement in Section 6.1 is a correctness requirement, not a style preference. Two implementations that disagree will fail to interoperate; because verification is fail-closed, they will refuse valid tokens rather than accept invalid ones, but the deployment will be broken.

9.5. Verifier-side recomputation

A verifier MUST recompute every digest from its own representation of the action and request. Using any plaintext carried alongside the token, or reflecting values from the token into the recomputation, reduces the binding to a self-consistency check and provides no security.

9.6. Compromise of the enrollment path

The security of every token reduces to the enrollment of its key. A verifier that accepts an unattested key, or that admits a key whose attestation chains to an untrusted root, gains nothing from the remaining machinery.

10. IANA Considerations

10.1. JSON Web Token Claims

IANA is requested to register the following in the "JSON Web Token Claims" registry established by [RFC7519].

Table 2
Claim Name Description Change Controller Reference
adg Action digest IETF Section 6.2 of this document
dsp Disclosure digest IETF Section 6.3 of this document
rqf Request fingerprint IETF Section 6.4 of this document
int Device runtime integrity IETF Section 5.3 of this document

None of these four names appears in the registry at the time of writing.

10.2. On the choice of adg

The action digest is named adg, for action digest, rather than the more obvious act. act is unavailable: [RFC8693] Section 4.1 registers it as the "Actor" claim, a JSON object identifying the acting party in a delegation chain.

The conflict would have been substantive rather than cosmetic. The registered claim is an object and this one is a string, so a general-purpose JWT implementation that understands [RFC8693] could mis-handle a token defined by this document, and a relying party processing both could not disambiguate them.

A nested object holding all three digests under one registered name was also considered. Three top-level claims were chosen instead because rqf is OPTIONAL, and its presence or absence is load-bearing in Section 7: an absent top-level claim is unambiguous in a way that an absent member of a present object is not.

10.3. Media Types

IANA is requested to register the following in the "Media Types" registry.

Table 3
Field Value
Type name application
Subtype name oasnt+jwt
Required parameters N/A
Optional parameters N/A
Encoding considerations binary; a JWS in compact serialization
Security considerations See the Security Considerations of this document
Interoperability considerations N/A
Published specification This document
Applications that use this media type Applications requiring evidence that a human authorized a specific action
Change controller IETF

The typ header parameter value oasnt+jwt is the subtype of this media type, following the convention [RFC9068] establishes with at+jwt.

11. References

11.1. Normative References

[RFC2119]
Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, DOI 10.17487/RFC2119, , <https://www.rfc-editor.org/rfc/rfc2119>.
[RFC4648]
Josefsson, S., "The Base16, Base32, and Base64 Data Encodings", RFC 4648, DOI 10.17487/RFC4648, , <https://www.rfc-editor.org/rfc/rfc4648>.
[RFC6234]
Eastlake 3rd, D. and T. Hansen, "US Secure Hash Algorithms (SHA and SHA-based HMAC and HKDF)", RFC 6234, DOI 10.17487/RFC6234, , <https://www.rfc-editor.org/rfc/rfc6234>.
[RFC7515]
Jones, M., Bradley, J., and N. Sakimura, "JSON Web Signature (JWS)", RFC 7515, DOI 10.17487/RFC7515, , <https://www.rfc-editor.org/rfc/rfc7515>.
[RFC7519]
Jones, M., Bradley, J., and N. Sakimura, "JSON Web Token (JWT)", RFC 7519, DOI 10.17487/RFC7519, , <https://www.rfc-editor.org/rfc/rfc7519>.
[RFC7638]
Jones, M. and N. Sakimura, "JSON Web Key (JWK) Thumbprint", RFC 7638, DOI 10.17487/RFC7638, , <https://www.rfc-editor.org/rfc/rfc7638>.
[RFC8174]
Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174, , <https://www.rfc-editor.org/rfc/rfc8174>.
[RFC8259]
Bray, T., Ed., "The JavaScript Object Notation (JSON) Data Interchange Format", STD 90, RFC 8259, DOI 10.17487/RFC8259, , <https://www.rfc-editor.org/rfc/rfc8259>.

11.2. Informative References

[I-D.ietf-wimse-arch]
Salowey, J. A., Rosomakho, Y., and H. Tschofenig, "Workload Identity in a Multi System Environment (WIMSE) Architecture", Work in Progress, Internet-Draft, draft-ietf-wimse-arch-08, , <https://datatracker.ietf.org/doc/html/draft-ietf-wimse-arch-08>.
[I-D.mcguinness-oauth-actor-proofs]
McGuinness, K., "OAuth Actor-Signed Hop Proofs", Work in Progress, Internet-Draft, draft-mcguinness-oauth-actor-proofs-00, , <https://datatracker.ietf.org/doc/html/draft-mcguinness-oauth-actor-proofs-00>.
[I-D.mishra-oauth-agent-grants]
Kumar, S., "Delegated Agent Authorization Protocol (DAAP)", Work in Progress, Internet-Draft, draft-mishra-oauth-agent-grants-01, , <https://datatracker.ietf.org/doc/html/draft-mishra-oauth-agent-grants-01>.
[I-D.ni-wimse-ai-agent-identity]
Yuan, N. and P. C. Liu, "WIMSE Applicability for AI Agents", Work in Progress, Internet-Draft, draft-ni-wimse-ai-agent-identity-02, , <https://datatracker.ietf.org/doc/html/draft-ni-wimse-ai-agent-identity-02>.
[I-D.nivalto-agentroa-route-authorization]
Michalak, J., "Agent Route Origin Authorization (AgentROA): A Cryptographic Policy Enforcement Framework for AI Agent Actions", Work in Progress, Internet-Draft, draft-nivalto-agentroa-route-authorization-01, , <https://datatracker.ietf.org/doc/html/draft-nivalto-agentroa-route-authorization-01>.
[I-D.rampalli-cross-org-delegation-mapping]
Karthik, R., "A Layered Requirements Mapping for Cross-Organization Agent Delegation", Work in Progress, Internet-Draft, draft-rampalli-cross-org-delegation-mapping-05, , <https://datatracker.ietf.org/doc/html/draft-rampalli-cross-org-delegation-mapping-05>.
[I-D.schrock-ep-action-evidence-graph]
Schrock, I., "Action Evidence Graphs and Evidence Policy Replay for High-Risk Agent Actions (EP-AEG)", Work in Progress, Internet-Draft, draft-schrock-ep-action-evidence-graph-00, , <https://datatracker.ietf.org/doc/html/draft-schrock-ep-action-evidence-graph-00>.
[I-D.schrock-ep-authorization-receipts]
Schrock, I., "Authorization Receipts for High-Risk Agent Actions", Work in Progress, Internet-Draft, draft-schrock-ep-authorization-receipts-07, , <https://datatracker.ietf.org/doc/html/draft-schrock-ep-authorization-receipts-07>.
[PSD2-RTS]
European Commission, "Commission Delegated Regulation (EU) 2018/389, regulatory technical standards for strong customer authentication and common and secure open standards of communication", , <https://eur-lex.europa.eu/eli/reg_del/2018/389/oj>.
[RFC8693]
Jones, M., Nadalin, A., Campbell, B., Ed., Bradley, J., and C. Mortimore, "OAuth 2.0 Token Exchange", RFC 8693, DOI 10.17487/RFC8693, , <https://www.rfc-editor.org/rfc/rfc8693>.
[RFC9068]
Bertocci, V., "JSON Web Token (JWT) Profile for OAuth 2.0 Access Tokens", RFC 9068, DOI 10.17487/RFC9068, , <https://www.rfc-editor.org/rfc/rfc9068>.
[RFC9334]
Birkholz, H., Thaler, D., Richardson, M., Smith, N., and W. Pan, "Remote ATtestation procedureS (RATS) Architecture", RFC 9334, DOI 10.17487/RFC9334, , <https://www.rfc-editor.org/rfc/rfc9334>.
[WEBAUTHN]
W3C, "Web Authentication: An API for accessing Public Key Credentials", , <https://www.w3.org/TR/webauthn-3/>.

Appendix A. Test Vectors

The key, clock and nonce used below are fixed (iat = 1800000000), so every canonical string, digest and signing input here is byte-reproducible. An implementation that agrees with this document computes exactly these values.

The signatures are not reproducible. ECDSA draws a fresh random value for each signature, so signing an identical input again yields a different and equally valid signature. Verify the signatures in these vectors; do not compare them octet-wise against your own output.

Backslash and line feed are shown escaped as \\ and \n so the exact octets are unambiguous on the page.

A.1. Key

{
  "kty": "EC",
  "crv": "P-256",
  "x": "P7Vp3OZi4XYii2VHo4T08zkjKrKhCt-gY-oAATkXaao",
  "y": "QNEaWqPG2EI5-2AdT8oX-S4odj8TH9wj_JW2I2ILBoc"
}

Thumbprint (RFC 7638), used as cnf.jkt:

xcDbc2-MsRIENQynAYGtJ0Vc0xPTBdfj_1iAeI9MMFo

The private component is d = Y2j9oKoLsw3p24brNicuYCjBxv0LVUWLHSYc9Wzvy5A. It is published here so that implementers can reproduce signatures; it MUST NOT be used for anything else.

A.2. V1: canonical action and adg

Action type payment.transfer, parameters:

{
  "amount": "100.00",
  "payee": "acct_9"
}

Canonical action string:

payment.transfer|amount=100.00&payee=acct_9

adg = YlHp3M4JIWFPPZIVAwAmYOBOMfUyb2bjE6ve3AD2iaQ

A.3. V2: canonical display and dsp

Canonical display string (line feeds shown as \n):

payment.transfer\namount: 100.00\npayee: acct_9

The same string as it appears to the user:

payment.transfer
amount: 100.00
payee: acct_9

dsp = uSEgOG9UC1IWGxzBalJv5cIbfxE8kxmoKF25yrRl1fs

A.4. V3: escaping

A parameter value containing every canonical-action delimiter, demonstrating that escaping prevents a value from impersonating a separator.

{
  "note": "a=b&c|d\\e"
}

Canonical action string:

payment.transfer|note=a\\=b\\&c\\|d\\\\e

adg = 3R0-FrNwSzXzvWmcFyDrQipdaJZmDUULlpX87bXParo

A.5. V4: request fingerprint and rqf

{
  "method": "POST",
  "path": "/v1/transfers",
  "orgId": "org_acme",
  "scope": "payments:write",
  "body": "{\"amount\":\"100.00\",\"payee\":\"acct_9\"}"
}

SHA-256 of the body, hex:

05be0ab936cd56cf971cc8b57f7132a690d4ed3bf63b37ac3cb81d6e289f847a

Fingerprint pre-image, with <NUL> marking a single 0x00 octet and the trailing 32 octets being the raw body digest above:

POST<NUL>/v1/transfers<NUL>org_acme<NUL>payments:write<NUL><body-digest>

rqf = 1GL7CIg1JkKGaGfHgdF5_93rVx4FqfjoY0lYZ6xbjQ0

A.6. V5: a complete token that verifies

Protected header:

{"alg":"ES256","typ":"oasnt+jwt"}

Payload:

{
  "sub": "agent-1",
  "adg": "YlHp3M4JIWFPPZIVAwAmYOBOMfUyb2bjE6ve3AD2iaQ",
  "dsp": "uSEgOG9UC1IWGxzBalJv5cIbfxE8kxmoKF25yrRl1fs",
  "rqf": "1GL7CIg1JkKGaGfHgdF5_93rVx4FqfjoY0lYZ6xbjQ0",
  "int": "clean",
  "jti": "0123456789abcdef0123456789abcdef",
  "iat": 1800000000,
  "exp": 1800000060,
  "cnf": {
    "jkt": "xcDbc2-MsRIENQynAYGtJ0Vc0xPTBdfj_1iAeI9MMFo"
  }
}

Compact serialization:

eyJhbGciOiJFUzI1NiIsInR5cCI6Im9hc250K2p3dCJ9.eyJzdWIiOiJhZ2VudC0
xIiwiYWRnIjoiWWxIcDNNNEpJV0ZQUFpJVkF3QW1ZT0JPTWZVeWIyYmpFNnZlM0F
EMmlhUSIsImRzcCI6InVTRWdPRzlVQzFJV0d4ekJhbEp2NWNJYmZ4RThreG1vS0Y
yNXlyUmwxZnMiLCJycWYiOiIxR0w3Q0lnMUprS0dhR2ZIZ2RGNV85M3JWeDRGcWZ
qb1kwbFlaNnhialEwIiwiaW50IjoiY2xlYW4iLCJqdGkiOiIwMTIzNDU2Nzg5YWJ
jZGVmMDEyMzQ1Njc4OWFiY2RlZiIsImlhdCI6MTgwMDAwMDAwMCwiZXhwIjoxODA
wMDAwMDYwLCJjbmYiOnsiamt0IjoieGNEYmMyLU1zUklFTlF5bkFZR3RKMFZjMHh
QVEJkZmpfMWlBZUk5TU1GbyJ9fQ.1rS6k1Yz9ZsYWpk51vTv0GDJX4VJ9vp3Qb9v
4ZNG1VjQQwvVvUpUjNao7ZA0hxmBqEOHPLv8NY5C_Jqjl-SJzA

Verified at time 1800000000 against the action of V1 and the request of V4, with the key above enrolled, this token is accepted.

A.7. V6: refusal vectors

Each vector below alters exactly one thing relative to V5 and is refused. The reasons shown are those an implementation of this document produces. The names are not normative; the fact of refusal is.

A.7.1. R1: action mismatch

The token is minted for a different amount than the verifier is about to execute.

Compact serialization:

eyJhbGciOiJFUzI1NiIsInR5cCI6Im9hc250K2p3dCJ9.eyJzdWIiOiJhZ2VudC0
xIiwiYWRnIjoiZHNNUHRxVkJHYjg5MHNfWEVNUDZ3XzZ6QVg2a1lEQ0JqYlo5Y3N
HYkVYTSIsImRzcCI6InVTRWdPRzlVQzFJV0d4ekJhbEp2NWNJYmZ4RThreG1vS0Y
yNXlyUmwxZnMiLCJycWYiOiIxR0w3Q0lnMUprS0dhR2ZIZ2RGNV85M3JWeDRGcWZ
qb1kwbFlaNnhialEwIiwiaW50IjoiY2xlYW4iLCJqdGkiOiIwMTIzNDU2Nzg5YWJ
jZGVmMDEyMzQ1Njc4OWFiY2RlZiIsImlhdCI6MTgwMDAwMDAwMCwiZXhwIjoxODA
wMDAwMDYwLCJjbmYiOnsiamt0IjoieGNEYmMyLU1zUklFTlF5bkFZR3RKMFZjMHh
QVEJkZmpfMWlBZUk5TU1GbyJ9fQ.jd0B7NW38g3hBK0YceD2eGRqgd0ApCm6eU_8
QlouotpXwLtOx9H9EB3bq8Dd1XJUybHr2Bheqwj_G_Pt2LPBLg

Refused: action-mismatch

A.7.2. R2: display mismatch

adg binds the executing action, so action binding alone would accept. dsp carries the digest of a different disclosure, which is what the human read.

Compact serialization:

eyJhbGciOiJFUzI1NiIsInR5cCI6Im9hc250K2p3dCJ9.eyJzdWIiOiJhZ2VudC0
xIiwiYWRnIjoiWWxIcDNNNEpJV0ZQUFpJVkF3QW1ZT0JPTWZVeWIyYmpFNnZlM0F
EMmlhUSIsImRzcCI6Ilg0OEc4THhNRUZwWlR3NjduWUw5dEh0OW9SSDV5YXI5RVR
3RVNkaWtZT1UiLCJycWYiOiIxR0w3Q0lnMUprS0dhR2ZIZ2RGNV85M3JWeDRGcWZ
qb1kwbFlaNnhialEwIiwiaW50IjoiY2xlYW4iLCJqdGkiOiIwMTIzNDU2Nzg5YWJ
jZGVmMDEyMzQ1Njc4OWFiY2RlZiIsImlhdCI6MTgwMDAwMDAwMCwiZXhwIjoxODA
wMDAwMDYwLCJjbmYiOnsiamt0IjoieGNEYmMyLU1zUklFTlF5bkFZR3RKMFZjMHh
QVEJkZmpfMWlBZUk5TU1GbyJ9fQ.ybY-_yQxFfEoqxvXdRkBnhnNxLup39qmHv6T
aznUIoHKt3RTmeuIDc8ebQqMsL4dbIhFGgdI3Og-2GEf0HuVmQ

Refused: display-mismatch

A.7.3. R3: request mismatch

Same action, aimed at a different request path.

Compact serialization:

eyJhbGciOiJFUzI1NiIsInR5cCI6Im9hc250K2p3dCJ9.eyJzdWIiOiJhZ2VudC0
xIiwiYWRnIjoiWWxIcDNNNEpJV0ZQUFpJVkF3QW1ZT0JPTWZVeWIyYmpFNnZlM0F
EMmlhUSIsImRzcCI6InVTRWdPRzlVQzFJV0d4ekJhbEp2NWNJYmZ4RThreG1vS0Y
yNXlyUmwxZnMiLCJycWYiOiJWbDZfTV90RUJ3RXBOcExNbFo4WENDM0M3dHRCYWF
pbElEWjZPWllEZnhJIiwiaW50IjoiY2xlYW4iLCJqdGkiOiIwMTIzNDU2Nzg5YWJ
jZGVmMDEyMzQ1Njc4OWFiY2RlZiIsImlhdCI6MTgwMDAwMDAwMCwiZXhwIjoxODA
wMDAwMDYwLCJjbmYiOnsiamt0IjoieGNEYmMyLU1zUklFTlF5bkFZR3RKMFZjMHh
QVEJkZmpfMWlBZUk5TU1GbyJ9fQ.ULJRBLA8zNugzy10VkRcIyh3GrL2naYG9mD4
LMChGuwxg1dYhAHHT1NEHIYvhEASJrX-sFs0hjk-pQVWdMG_Mw

Refused: rqf-mismatch

A.7.4. R4: request binding absent

The rqf claim is omitted entirely while the verifier is pinning a request. The token MUST be refused rather than accepted as action-bound only.

Compact serialization:

eyJhbGciOiJFUzI1NiIsInR5cCI6Im9hc250K2p3dCJ9.eyJzdWIiOiJhZ2VudC0
xIiwiYWRnIjoiWWxIcDNNNEpJV0ZQUFpJVkF3QW1ZT0JPTWZVeWIyYmpFNnZlM0F
EMmlhUSIsImRzcCI6InVTRWdPRzlVQzFJV0d4ekJhbEp2NWNJYmZ4RThreG1vS0Y
yNXlyUmwxZnMiLCJpbnQiOiJjbGVhbiIsImp0aSI6IjAxMjM0NTY3ODlhYmNkZWY
wMTIzNDU2Nzg5YWJjZGVmIiwiaWF0IjoxODAwMDAwMDAwLCJleHAiOjE4MDAwMDA
wNjAsImNuZiI6eyJqa3QiOiJ4Y0RiYzItTXNSSUVOUXluQVlHdEowVmMweFBUQmR
mal8xaUFlSTlNTUZvIn19.Cf08Diz2lvF-jncola2wVEwf40xC-lxnAMw6SjoewE
ekr-s0q_p1pV98VrNzgZ1Eb7MhzojNGmIRBWT65DOLqw

Refused: rqf-missing

A.7.5. R5: expired

Verified one second after exp.

Compact serialization:

eyJhbGciOiJFUzI1NiIsInR5cCI6Im9hc250K2p3dCJ9.eyJzdWIiOiJhZ2VudC0
xIiwiYWRnIjoiWWxIcDNNNEpJV0ZQUFpJVkF3QW1ZT0JPTWZVeWIyYmpFNnZlM0F
EMmlhUSIsImRzcCI6InVTRWdPRzlVQzFJV0d4ekJhbEp2NWNJYmZ4RThreG1vS0Y
yNXlyUmwxZnMiLCJycWYiOiIxR0w3Q0lnMUprS0dhR2ZIZ2RGNV85M3JWeDRGcWZ
qb1kwbFlaNnhialEwIiwiaW50IjoiY2xlYW4iLCJqdGkiOiIwMTIzNDU2Nzg5YWJ
jZGVmMDEyMzQ1Njc4OWFiY2RlZiIsImlhdCI6MTgwMDAwMDAwMCwiZXhwIjoxODA
wMDAwMDYwLCJjbmYiOnsiamt0IjoieGNEYmMyLU1zUklFTlF5bkFZR3RKMFZjMHh
QVEJkZmpfMWlBZUk5TU1GbyJ9fQ.5WJUcmpcgNE3GrVIMFIFxcyla40xvxn6tdUE
prKYJvEGIXy_lCPu6xS0MM7Nz6bJbeZCysc1M3_wPzeZdZ5zTA

Refused: expired

A.7.6. R6: replay

The jti has already been recorded by this verifier.

Compact serialization:

eyJhbGciOiJFUzI1NiIsInR5cCI6Im9hc250K2p3dCJ9.eyJzdWIiOiJhZ2VudC0
xIiwiYWRnIjoiWWxIcDNNNEpJV0ZQUFpJVkF3QW1ZT0JPTWZVeWIyYmpFNnZlM0F
EMmlhUSIsImRzcCI6InVTRWdPRzlVQzFJV0d4ekJhbEp2NWNJYmZ4RThreG1vS0Y
yNXlyUmwxZnMiLCJycWYiOiIxR0w3Q0lnMUprS0dhR2ZIZ2RGNV85M3JWeDRGcWZ
qb1kwbFlaNnhialEwIiwiaW50IjoiY2xlYW4iLCJqdGkiOiIwMTIzNDU2Nzg5YWJ
jZGVmMDEyMzQ1Njc4OWFiY2RlZiIsImlhdCI6MTgwMDAwMDAwMCwiZXhwIjoxODA
wMDAwMDYwLCJjbmYiOnsiamt0IjoieGNEYmMyLU1zUklFTlF5bkFZR3RKMFZjMHh
QVEJkZmpfMWlBZUk5TU1GbyJ9fQ.oEHHulmYbnSkZEyh8MYr4N_Qim6bxJL2JtB1
6V1CarsOf12wx77w_krvPz9CWajNoXrqUyTWz8WKplhaHi4xPw

Refused: replay

Acknowledgments

The request-fingerprint construction in Section 6.4 was shaped by published work on per-request, action-bound authentication for autonomous agents, and by discussion of human-authorization binding on the WIMSE mailing list.

Author's Address

Arun Thallapelly
OmniArx