Hi Bhasker, The review is being worked through in GitHub, in issue #8, which links each point to the pull request that addresses it: https://github.com/skyfire-xyz/draft-skyfire-oauth-using-kyapay-tokens/issues/8
One change goes further than the review asked, so I'm calling it out here (S4, https://github.com/skyfire-xyz/draft-skyfire-oauth-kyapay-token/pull/59). In the KYAPay Token draft, `aud` now identifies the combination of identities the issuer holds for the Target, and `tsi`, which identifies the service under it, becomes REQUIRED. A recipient that has onboarded to the issuer checks `aud` and `tsi`; any other recipient checks `tdm`, which names the Target's host. Comments are welcome on the pull request or here. Ankit On Wed, Oct 21, 2026 06:21 PM, Bhasker Allam <[email protected]> wrote: > Hi all, > > Below is a review of "Using KYAPay Tokens" [USING-KYAPAY], > draft-skyfire-oauth-using-kyapay-tokens-01. Claims such as hid, aid > and sti are defined in the KYAPay Token draft [KYAPAY-TOKEN]. > Section numbers refer to [USING-KYAPAY] unless stated otherwise. > > Summary > ======= > > Most of the comments below come down to three high-level issues. > > 1. The bearer token carries personal and payment data. > > The token is a signed JWT, not an encrypted one (Section 4.1). In > [KYAPAY-TOKEN], hid requires email and may carry name and phone, and > sti carries settlement details. Anyone who sees the header during > its lifetime can read the data and replay the token anywhere within > it's aud. Every hop that terminates TLS (CDN, WAF, bot manager, > origin) sees it. Sections 5.1 and 9.3 answer this with "MUST NOT log > or forward", which cannot be enforced or checked. > > 2. Admission without challenge. > > Section 6.3 says a bot manager "SHOULD admit the request ... rather > than subjecting it to bot-blocking challenges." Combined with point > 1, a captured or cheaply obtained token becomes an open gate at the > bot manager. Section 7.2 allows "progressive" verification that > starts with only an email check, so "verified human" can mean very > little. I don't have a good solution here, since the goal of the > draft is easy adoption using the existing OAuth and JWT framework. > > 3. Some things to clarify to avoid implementation divergence. > > a. How intermediaries learn the aud set. Section 6.1 says to check > that the token is "intended for this recipient", but an > intermediary is not the recipient; the Target is. How will the > intermediary know the audience set? > > b. Single-use vs. reusable. Section 8.3 asks for jti replay > detection, while Section 4.3 validates "once (per session)" and > mnr implies multiple requests. > > c. What the human authorized. Section 6.6 treats a valid token as > evidence of a legitimate session, but the token does not name an > account or an action. Is hid meant to equal the account? Nothing > in the draft says so. Again this goes back to proof of > possession. > > Security comments > ================= > > S1. The token does not say which account it is for (Sections 6.6, 6.7, > 8.8) > > Issue. A valid token with hid = attacker@example can be presented while > logging into, or acting on, someone else's account. Section 6.6 says an > ATO protector "SHOULD treat a validated KYAPay token ... as evidence > that a session is a human-initiated agentic session." That is true, but > it can be misread as evidence that the session is legitimate for this > account. The authors have said there is no low-burden way to bind the > token to an account today, and I agree. > > Suggestion. > > - Add a normative statement to 6.6 and 6.7, for example: "A KYAPay > token attests the identity of the principal who authorized the agent. > It does not convey authority over any account at the Target. ATO > protectors and CIAM systems MUST NOT treat a validated token as > authorization to access an account unless the token's principal has > been linked to that account." > > - List account binding as an open item next to step-up (6.5) and > revocation (8.7). > > - One possible path that keeps intermediary burden low is a DPoP change > I proposed on this list [DPOP-PROXY], which lets intermediaries > validate both the token and the sender. > > S2. Admission without challenge should depend on assurance (Sections > 6.2, 6.3, 7.2) > > Issue. Section 6.3 says a bot manager "SHOULD admit the request ... > rather than subjecting it to bot-blocking challenges." Section 7.2 > allows verification to begin with an email check. A bearer token > obtained with a throwaway email then bypasses bot defenses on login, > sign-up and checkout. > > Suggestion. Make the admission SHOULD conditional: "...SHOULD admit the > request when the assurance levels in the token (Section 6.2) meet the > Target's policy for the requested action." Add that per-hid, per-aid > and per-apd rate and abuse limits still apply, and that sensitive > actions MAY still be challenged. > > S3. Say the token is reusable, and drop jti replay detection (Sections > 4.1, 4.3, 8.3) > > Issue. The token is meant to be reused within its roughly 5-minute > lifetime. Section 4.3 validates it "once (per session)" and the payment > claim mnr allows multiple requests. Yet Section 8.3 says verifiers > "SHOULD use the jti claim to detect replay." That can't work in > practice: > > - A Target is usually fronted by many intermediary instances (PoPs, > proxy fleets). Sharing jti state among them within the latency budget > in 6.3 ("no per-request callout") is not realistic. > > - Even a single-use token can't be enforced. Section 3.4 has the bot > manager, fraud manager, ATO protector and CIAM system all validate > the same token on the same request. Each layer would see the others' > use as a replay. > > Suggestion. > > - State in 4.1 that the token is reusable within its lifetime and aud. > > - List in-window replay within the aud set as an accepted risk of the > bearer model. > > - Reword 8.3 so jti is used for correlation, audit and issuer feedback > (6.10), not replay detection. > > - Point to proof of possession (4.3) as the only real fix, subject to > S8 below. > > S4. Define how intermediaries get the aud set (Sections 5.3, 6.1 > step 5) > > Issue. aud works like a store-restricted gift card: the issuer limits > which Targets can accept the token. An intermediary, though, is not the > audience. Section 6.1 step 5 ("intended for this recipient") gives it > no way to know which aud values are valid for the hosts it protects. > Multi-tenant intermediaries front many Targets. How aud relates to tdm > and tsi is also not stated. > > Suggestion. > > - Say that intermediaries obtain the acceptable aud (and tdm/tsi) > values per protected Target through configuration, for example as > part of each trusted issuer's configuration, and check the token > against that set. > > - Define the relationship between aud, tdm and tsi. > > - Say how an agent determines the aud for a given Target. > > S5. Check the issuer before fetching keys (Section 6.1 steps 3 and 4) > > Issue. Step 3 verifies the signature against the issuer's key set > before step 4 checks that the issuer is trusted. Keys are found at > iss + /.well-known/jwks.json, so a literal reading has verifiers > fetching keys from any URL an attacker puts in iss (server-side request > forgery, denial of service). Well-built verifiers already allowlist > issuers, but the text should say so. > > Suggestion. Swap steps 3 and 4. Add: "A verifier MUST NOT retrieve key > material for an issuer that is not in its configured set of trusted > issuers." > > S6. Algorithm rules and token count (Sections 5.1, 6.1, References) > > Issue. The draft sets no algorithm rules. JWT Best Current Practices > [RFC8725] is only an informative reference. > > Suggestion. > > - Make [RFC8725] a normative reference. > > - Require verifiers to use an algorithm allowlist tied to each issuer's > keys, and to reject "none" and symmetric algorithms. > > - In 5.1, let recipients reject a header with more than one token per > typ (at most 3 tokens). This caps verification cost per request. > > S7. Token leakage through the agent's runtime (Section 8) > > Issue. Tokens can leak through LLM transcripts, tool logs, and prompt > injection. Section 7.1 mentions keeping credentials from the LLM, but > Section 8 does not cover the threat. Proposed text is in the "Proposed > text: new Section 8.x" part at the end of this message. > > S8. The planned proof-of-possession path reintroduces the rewriting > problem (Section 4.3) > > The bearer design is right not to depend on end-to-end request signing > such as Web Bot Auth. Signing the request's components is heavy, and > requests are routinely changed on the way to the origin. URL rewriting > is common, and sites deliberately keep external and internal URLs > separate so they don't expose internal architecture. When the signed > request is what the client sent, every proxy that rewrites the request > breaks verification or has to be given special handling. > > Issue. In Section 4.3 the issuer binds the agent's public key into the > token (cnf), and the agent then signs each request, "a signature over > the request (method, path, body digest, timestamp/nonce) using > [RFC9421]", which is verified against cnf. The draft prefers this over > a detached, DPoP-style proof [RFC9449]. Because the signature covers > the path, the same rewriting fragility the bearer model avoids comes > back: an intermediary that rewrites the URL, or an origin that sees > only the internal path, can no longer verify it. Section 4.3 also notes > that stopping replay of the signature "requires either per-Target nonce > caches or binding the signature to the request content". That is the > same shared-state problem across distributed intermediaries described > in S3. > > Suggestion. > > - Make the rationale explicit in 4.2 and 4.3: why whole-request signing > is avoided, including the URL rewriting and internal/external URL > separation points above. > > - For the proof-of-possession path, say which components are covered, > and require a set that survives normal proxying. Alternatively, allow > verification at the first intermediary, before any rewrite. > > - Consider a DPoP-style proof designed for intermediaries as an > alternative. My DPoP proposal on this list [DPOP-PROXY] addresses > exactly this for URI-rewriting reverse proxies. > > Privacy and PCI comments > ======================== > > Sending the JWT in the clear is a reasonable choice: it reuses existing > OAuth/JWT infrastructure and keeps integration simple. The comments > below keep that model. They change what goes in the token, not how it > is carried. > > P1. Replace personal data with a per-Target pseudonymous identifier > (Sections 9.1, 9.3; hid in [KYAPAY-TOKEN]) > > Issue. hid requires email and may carry name and phone. Every > intermediary receives it (9.3), and the same email reaches every > Target, which lets sites track a person across all of them. > Intermediaries don't need this data: bot, fraud and ATO decisions (6.3 > to 6.6) need a stable handle and assurance levels, not a name or email. > > Suggestion. > > - Carry an opaque, pseudonymous principal identifier that differs per > Target (pairwise, derived per aud), plus the verification and > assurance sub-claims. > > - A Target that needs the personal data (for example CIAM account > creation in 6.7) gets it from the issuer out of band, authenticated > as that Target, similar to the UserInfo endpoint in OpenID Connect > Core 1.0 [OIDC], Section 5.3. > > - Intermediaries can still rate-limit per principal, scope mitigations > (6.9) and send feedback (6.10) using the pseudonym. > > - Only the Target makes an issuer call, and only when it needs the > data, so the "no per-request callout" property in 6.3 holds for > intermediaries. > > P2. Keep payment data out of the token (Section 6.4; sti in > [KYAPAY-TOKEN]) > > Issue. If sti can contain card-related data, every hop that sees the > header may fall under PCI rules. Intermediary vendors and CDNs are > unlikely to accept that. > > Suggestion. Apply the P1 pattern: sti carries a reference that the > Target redeems with the issuer or payment processor. Add: "A KYAPay > token MUST NOT contain primary account numbers or other cardholder > data." Amount, currency and limits (amt, cur, mnr) can stay, since > fraud managers use them (6.4). > > P3. Make aid.creation_ip optional ([KYAPAY-TOKEN]) > > Issue. creation_ip is REQUIRED. It is personal data, and Section 6.3 > already says network-origin claims are "a weak corroborating signal > only." > > Suggestion. Make it OPTIONAL. > > Protocol and compatibility comments > =================================== > > C1. Header grammar and Structured Fields disagree (Sections 5.1, 10.1) > > Section 5.1 defines its own ABNF, while 10.1 registers KYAPay-Token as > a Structured Field of type List. Under Structured Field Values for HTTP > [RFC9651], a malformed member makes the whole field fail to parse. That > conflicts with 5.1's "MUST ignore a member it cannot parse ... while > continuing to process the remaining members." Pick one: define the > field as an sf-list of sf-string (or sf-token) and drop the custom > ABNF, or drop the Structured Field registration. > > C2. Header size (Section 5.1) > > Up to three JWTs carrying identity and payment claims can exceed common > header limits (nginx header buffers, load balancer and CDN caps). Give > a recommended maximum field size, or at least a note. The P1 and P2 > changes would shrink tokens considerably. > > C3. Browser agents and CORS (Sections 3.3, 5.1) > > A custom request header on a cross-origin fetch triggers a CORS > preflight. Page scripts can't send it unless the site allows it in > Access-Control-Allow-Headers. Browser-use agents also can't easily add > headers to page navigations. Say which requests carry the token > (top-level navigations, API calls, sub-resources), and qualify the > "zero merchant tech lift" claim for browser-based agents. > > C4. No challenge or error response (Sections 6.5, 8.8) > > A Target cannot signal "token required", "token rejected" or "higher > assurance needed." For step-up, which 6.5 lists as open, consider > reusing OAuth 2.0 Step Up Authentication Challenge Protocol [RFC9470], > which already defines WWW-Authenticate challenges for insufficient > authentication. It would also help to explain why the draft uses a new > header rather than an Authorization scheme (presumably to avoid > clashing with the site's own authentication). > > Proposed text: new Section 8.x, Token Exposure in the Agent Runtime > =================================================================== > > Suggested for insertion after Section 8.5 (Compromised Agent Host). It > complements 8.5: that section covers malware using the agent's key, > while this one covers the token leaving the agent through its own > normal operation. > > 8.x. Token Exposure in the Agent Runtime > > Agents driven by language models process untrusted content and > record their activity in ways that conventional HTTP clients do not. > A KYAPay token can therefore leave the agent through normal > operation, without the agent host being compromised. Examples > include: > > o the token appearing in model context, conversation transcripts, > or tool-call inputs and outputs that are logged, retained, or > sent to a model provider; > > o agent tracing, observability, or debugging systems that record > outbound request headers; > > o prompt injection, where content retrieved from a website or tool > instructs the agent to reveal the token or to include it in a > request to a party other than the intended Target. > > For a bearer token (Section 4.1), anyone who obtains a leaked token > can use it at any audience in its aud until it expires. Audience > binding does not help if the attacker presents the token at a > legitimate Target. > > Agent developers and KYAPay Token Issuers SHOULD mint and attach > tokens in deterministic components (Section 7.1) whose outputs are > not placed in model context. Agents SHOULD attach a token only to > requests whose destination matches the token's audience (aud, and > tdm or tsi where used), and the component that attaches it MUST > make that decision without relying on model output. Agent runtimes > MUST NOT record KYAPay token values in logs, traces, or > transcripts. Agents SHOULD request a new token for each Target and > task rather than reusing one broadly, and SHOULD request the > shortest lifetime that fits the task. Proof of possession (Section > 4.3) reduces this exposure only if the private key is also kept out > of model context. > > References > ========== > > [USING-KYAPAY] > Agarwal, A., Jones, M. B., and S. Thumma, "Using KYAPay Tokens", > draft-skyfire-oauth-using-kyapay-tokens-01, > > https://datatracker.ietf.org/doc/draft-skyfire-oauth-using-kyapay-tokens/ > Editor's copy: > > https://skyfire-xyz.github.io/draft-skyfire-oauth-using-kyapay-tokens/draft-skyfire-oauth-using-kyapay-tokens.html > > [KYAPAY-TOKEN] > Agarwal, A. and M. B. Jones, "KYAPay Token", > draft-skyfire-oauth-kyapay-token-01, > > https://datatracker.ietf.org/doc/html/draft-skyfire-oauth-kyapay-token-01 > > [DPOP-PROXY] > Allam, B., DPoP proposal for URI-rewriting reverse proxies, message > to the OAuth WG mailing list, > > https://mailarchive.ietf.org/arch/msg/oauth/F-UUNUUuZJihx_Qpms6EGsItoyc/ > > [RFC8725] > Sheffer, Y., Hardt, D., and M. Jones, "JSON Web Token Best Current > Practices", BCP 225, RFC 8725, > https://www.rfc-editor.org/rfc/rfc8725 > > [RFC9421] > Backman, A., Ed., Richer, J., Ed., and M. Sporny, "HTTP Message > Signatures", RFC 9421, > https://www.rfc-editor.org/rfc/rfc9421 > > [RFC9449] > Fett, D., Campbell, B., Bradley, J., Lodderstedt, T., Jones, M., and > D. Waite, "OAuth 2.0 Demonstrating Proof of Possession (DPoP)", > RFC 9449, > https://www.rfc-editor.org/rfc/rfc9449 > > [RFC9470] > Bertocci, V. and B. Campbell, "OAuth 2.0 Step Up Authentication > Challenge Protocol", RFC 9470, > https://www.rfc-editor.org/rfc/rfc9470 > > [RFC9651] > Nottingham, M. and P-H. Kamp, "Structured Field Values for HTTP", > RFC 9651, > https://www.rfc-editor.org/rfc/rfc9651 > > [OIDC] > Sakimura, N., Bradley, J., Jones, M., de Medeiros, B., and C. > Mortimore, "OpenID Connect Core 1.0", > https://openid.net/specs/openid-connect-core-1_0.html > > Thanks, > Bhasker Allam > _______________________________________________ > OAuth mailing list -- [email protected] > To unsubscribe send an email to [email protected] >
_______________________________________________ OAuth mailing list -- [email protected] To unsubscribe send an email to [email protected]
