fix: allow SD-JWT+kb key binding in checkout_mandate pattern#496
fix: allow SD-JWT+kb key binding in checkout_mandate pattern#496sakinaroufid wants to merge 6 commits into
Conversation
checkout_mandate is an SD-JWT+kb credential, serialized as <issuer-JWT>~<disclosure>...~<KB-JWT>. The key-binding JWT contains dots, but the pattern only allowed dot-free segments after the issuer JWT, so it rejected every key-bound mandate and accepted only the unbound form. AP2 verification (ap2-mandates.md) requires verifying the key binding, so a conformant value could not pass validation. Add an optional trailing ~<KB-JWT> group. Strict superset of the old pattern, so nothing that validates today breaks. Add a regression test that reads the pattern from the schema and checks the key-bound form.
kmcduffie
left a comment
There was a problem hiding this comment.
Thank you for updating this regex!
|
@sakinaroufid This change makes sense. Can you add tests to ensure this regex is correct for the expanded use case? |
5f78847 to
e33c2b9
Compare
|
@kmcduffie Thanks for your review! I've just added tests to ensure this regex is correct for the expanded use case. |
|
|
||
| for value, why in [ | ||
| ("not a credential", "free text"), | ||
| (f"{j}~{j}~{j}", "two KB-JWTs"), |
There was a problem hiding this comment.
We also want to support delegate sd-jwts which will allow for chaining kb-jwts (for the autonomous use case: see https://datatracker.ietf.org/doc/html/draft-gco-oauth-delegate-sd-jwt.
This is of the form:
<issuer-jwt>~[disclosures]~~<kb-sd-jwt>~[disclosures]~<kb-jwt>
and could potentially chain further.
IMO we'd be better off not trying to enforce this at the schema level, instead in the application-layer when it goes to validation. That'll also make it easier for us to further extend this to other credential formats without modifications to AP2 (e.g. mDocs credentials, or zkp proofs.)
Description
I was reading through the AP2 mandate schema and realized
checkout_mandatecan't actually hold the value it's documented to hold.The field is described as an SD-JWT+kb credential, and the business verification steps in
ap2-mandates.mdrequire the business to verify the key binding. The issue is the regex. An SD-JWT+kb is serialized as<issuer-JWT>~<disclosure>...~<KB-JWT>, and that final piece, the key-binding JWT, is itself a JWT, so it has dots in it. The current pattern only allows dot-free segments after the issuer JWT:So anything carrying a real key binding gets rejected, and the only value that passes is an SD-JWT with the key binding stripped off. That's the opposite of what we want here. The key binding is the part that proves the holder actually presented the mandate, so the schema is effectively forcing implementations to drop the property that makes the mandate trustworthy. A conformant response that includes it fails validation today.
The reason nobody hit this yet is that every
checkout_mandateexample in the docs elides its value, so a real one never gets run through the pattern.The fix is to allow an optional trailing
~<KB-JWT>:It's a strict superset of the old one, so nothing that validates today stops validating. I checked against ucp-schema 1.1.0: a key-bound mandate now passes, the unbound form still passes,
ucp-schema lint source/is clean, and the full example corpus is still green. I also added a regression test that reads the pattern straight from the schema and checks the key-bound case, so if the pattern gets reverted later the test fails.Category (Required)
Related Issues
None.
Checklist
!for breaking changes). Not breaking: the pattern is a strict superset.checkout_mandateexamples stay elided.