Skip to content

Honor Payment-Authorization in mpp pay - #263

Open
raubrey-stripe wants to merge 26 commits into
mainfrom
raubrey/mpp-pay-payment-authorization
Open

Honor Payment-Authorization in mpp pay#263
raubrey-stripe wants to merge 26 commits into
mainfrom
raubrey/mpp-pay-payment-authorization

Conversation

@raubrey-stripe

@raubrey-stripe raubrey-stripe commented Aug 25, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds support for alternate MPP headers to be used in mpp pay when indicated by the server that Payment-Authorization should be used instead.

The MPP spec is being updated to support servers indicating a separate header should be used from the default Authorization header, so as to not conflict with existing authorization (i.e. Bearer auth) in case an MPP server uses both traditional auth and payment in the same endpoint. Spec update draft: tempoxyz/mpp-specs#328

Test plan

  • vitest run src/commands/mpp/credential-header.test.ts src/commands/mpp/decode.test.ts
  • vitest run src/__tests__/cli.test.ts -t "mpp pay" after pnpm build
  • link-cli mpp pay against a 402 that omits header still retries with Authorization: Payment …
  • link-cli mpp pay -H 'Authorization: Bearer …' against a 402 with header="Payment-Authorization" keeps the Bearer token and puts the Payment credential on Payment-Authorization

Made with Cursor

@raubrey-stripe
raubrey-stripe requested a review from a team as a code owner August 25, 2026 03:45
raubrey-stripe and others added 6 commits August 25, 2026 18:53
Expose Blind RSA token pooling through the SDK and CLI while enforcing trusted issuer discovery and verifying every unblinded signature.

Co-authored-by: Cursor <cursoragent@cursor.com>
Committed-By-Agent: cursor
The backend no longer requires aap:represent, so keep default login grants minimal and remove the obsolete requirement from command guidance.

Co-authored-by: Cursor <cursoragent@cursor.com>
Committed-By-Agent: cursor
Keep AAP command guidance in README and CLAUDE.md so the published payment skill can change independently.

Co-authored-by: Cursor <cursoragent@cursor.com>
Committed-By-Agent: cursor
Keep issuer well-known paths as wire identifiers; describe the flow in terms of attestations and Privacy Pass instead.

Co-authored-by: Cursor <cursoragent@cursor.com>
Committed-By-Agent: cursor
Incur can hide a command from MCP with mcp: false, but --help and --llms still advertise it. Gate registration so agents do not discover the command.

Co-authored-by: Cursor <cursoragent@cursor.com>
Committed-By-Agent: cursor
Expose the command as `identity attestations request` and describe it as a privacy-preserving token that shows Link attests to your agent.

Co-authored-by: Cursor <cursoragent@cursor.com>
Committed-By-Agent: cursor

@bensandler-stripe bensandler-stripe left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

Comment thread packages/cli/src/commands/mpp/credential-header.ts Outdated
@raubrey-stripe

Copy link
Copy Markdown
Contributor Author

Follow-up: dropped the custom WWW-Authenticate scheme scanner and bumped mppx to 0.9.1 so we can read challenge.header from the official parser.

CI is expected to fail pnpm install until that version clears the 7-day minimumReleaseAge gate (~Sep 4). No exclude added — merge once install is unblocked.

raubrey-stripe and others added 14 commits September 1, 2026 15:28
Committed-By-Agent: codex
Co-authored-by: codex <noreply@openai.com>
Provision SD-JWT credentials through the issuer's discovered credential endpoint while keeping private holder keys local to the CLI.

Co-authored-by: Cursor <cursoragent@cursor.com>
Committed-By-Agent: cursor
Avoid breaking unrelated SDK resources when local HTTP API overrides are configured; enforce AAP issuer constraints only when credential issuance begins.

Co-authored-by: Cursor <cursoragent@cursor.com>
Committed-By-Agent: cursor
Use AAP_ACCESS_TOKEN only for attestation minting while credential issuance follows its documented flag-or-stored-session authentication path.

Co-authored-by: Cursor <cursoragent@cursor.com>
Committed-By-Agent: cursor
Credential issuance no longer requires aap:represent, so document only the remaining user and payment-method scopes.

Co-authored-by: Cursor <cursoragent@cursor.com>
Committed-By-Agent: cursor
Rename issuer-origin helpers and describe discovery without the protocol acronym. Keep the well-known metadata path as a wire identifier.

Co-authored-by: Cursor <cursoragent@cursor.com>
Committed-By-Agent: cursor
Same discovery gate as attestations: register only when opted in, and keep the command out of MCP tool lists.

Co-authored-by: Cursor <cursoragent@cursor.com>
Committed-By-Agent: cursor
Use `identity credentials get` and describe it as signed user info from Link rather than SD-JWT terminology.

Co-authored-by: Cursor <cursoragent@cursor.com>
Committed-By-Agent: cursor
Committed-By-Agent: codex
Co-authored-by: codex <noreply@openai.com>
Satisfy validated AAP claims challenges with selective SD-JWT disclosure and a fail-closed request-specific Web Bot Auth signature.

Co-authored-by: Cursor <cursoragent@cursor.com>
Committed-By-Agent: cursor
Describe identity-claims challenges in plain language. Keep claims-required URNs as wire identifiers.

Co-authored-by: Cursor <cursoragent@cursor.com>
Committed-By-Agent: cursor
Same discovery gate as attestations and credentials so identity-aware HTTP requests stay off --help, --llms, and MCP by default.

Co-authored-by: Cursor <cursoragent@cursor.com>
Committed-By-Agent: cursor
Expose it as `identity request` and describe presenting signed Link user info instead of protocol jargon.

Co-authored-by: Cursor <cursoragent@cursor.com>
Committed-By-Agent: cursor
Spend a local AAT on PrivateToken challenges, sign the retry with Web Bot Auth, and answer combined identity-presentation challenges in the same round.

Co-authored-by: Cursor <cursoragent@cursor.com>
Committed-By-Agent: cursor
@raubrey-stripe
raubrey-stripe force-pushed the raubrey/mpp-pay-payment-authorization branch from 1994840 to 23a4d58 Compare September 2, 2026 00:18
Comment on lines +40 to +43
const { publicKey, privateKey } = generateKeyPairSync('rsa', {
modulusLength: 1024,
publicExponent: 0x10001,
});
Comment on lines +79 to +82
const { publicKey } = generateKeyPairSync('rsa', {
modulusLength: 1024,
publicExponent: 0x10001,
});
Comment on lines +143 to +146
const { publicKey } = generateKeyPairSync('rsa', {
modulusLength: 1024,
publicExponent: 0x10001,
});
raubrey-stripe and others added 5 commits September 1, 2026 20:20
Committed-By-Agent: codex
Co-authored-by: codex <noreply@openai.com>
Committed-By-Agent: codex
Co-authored-by: codex <noreply@openai.com>
When a 402 challenge advertises header="Payment-Authorization", send the Payment credential in that field so ordinary Authorization can coexist.

Co-authored-by: Cursor <cursoragent@cursor.com>
Committed-By-Agent: cursor
The protocol no longer allows arbitrary credential header names, so send and echo only those two fields.

Co-authored-by: Cursor <cursoragent@cursor.com>
Committed-By-Agent: cursor
Quoted auth-params like description="Payment required" were treated as a
new scheme start, which could drop header="Payment-Authorization".

Co-authored-by: Cursor <cursoragent@cursor.com>
Committed-By-Agent: cursor
mppx now keeps challenge.header, so mpp pay no longer re-parses
WWW-Authenticate scheme boundaries itself.

Co-authored-by: Cursor <cursoragent@cursor.com>
Committed-By-Agent: cursor
@raubrey-stripe
raubrey-stripe force-pushed the raubrey/mpp-pay-payment-authorization branch from 23a4d58 to 577da36 Compare September 2, 2026 00:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants