Carlos, One correction to my earlier message: a recipient that hasn't onboarded to the issuer checks at least that `tdm` names the Target's domain, not its host. Your point on comparing the host and path is tracked in an issue and addressed in PR #59: https://github.com/skyfire-xyz/draft-skyfire-oauth-kyapay-token/issues/66
Ankit On Sun, Nov 01, 2026 10:29 AM, "[email protected]" < [email protected]> wrote: > Hi Ankit, > > Thanks for calling this out. I left a comment on PR #59 about path-based > tenants, and here is a short version for the list. > > Your note says a recipient that has not onboarded checks that tdm names > the Target's host. The text in the PR says it checks that tdm names the > domain, which means the registrable domain from the PSL. For Targets that > keep tenants on paths under one host, that difference matters. Our API is > at app.beel.es/api/v1/companies/{id}/.. > <http://app.beel.es/api/v1/companies/%7Bid%7D/..>., and marketplaces with > seller pages under one host are in the same spot. As written, a token with > tdm app.beel.es/api passes for any intermediary in front of anything > under beel.es. > > It would help if step 6 said how a recipient that cares about host and > path compares them, for example an exact host match plus a path-prefix > match on segment boundaries. If the path is only informational for > intermediaries, saying so would let Targets know they have to check it > themselves. > > Carlos MartÃnez > BeeL. > > El 1 nov 2026, a las 19:12, Ankit Agarwal <ankit= > [email protected]> escribió: > > 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] > > >
_______________________________________________ OAuth mailing list -- [email protected] To unsubscribe send an email to [email protected]
