Repository navigation
AS↔DC token/introspection wire format diverges from ESPI standard (Batch URI forms + non-standard *_id claims) #160
Description
Defect (live bug, surfaced while scoping the #150 contract)
The C4 token-response / introspection augmentation (merged in #147) does not match the ESPI 4.0 standard token-response format (REQ.21, verified against the standard's own example: "resourceURI":".../resource/Batch/Subscription/1dfa07c5740a_118328", "scope":"FB=...;...", no *_id fields, "customerResourceURI":"" allowed).
Producer divergence — openespi-common SubscriptionProvisioningServiceImpl
subscriptionUri(id) = resourceBaseUri + "/Subscription/" + id // line ~195 -> MISSING "/Batch/"
authorizationUri(id) = resourceBaseUri + "/Authorization/" + id // line ~199 -> OK| Field | ESPI standard | Current | Status |
|---|---|---|---|
resourceURI |
.../resource/Batch/Subscription/{id} |
.../resource/Subscription/{id} |
❌ missing /Batch/ |
authorizationURI |
.../resource/Authorization/{id} |
same | ✓ |
customerResourceURI |
.../resource/Batch/RetailCustomer/{rc} or "" |
pass-through from AS handoff (unverified) | |
authorization_id, resource_subscription_id, customer_subscription_id |
not in the standard | AS GrantBackchannelTokenCustomizer adds all three |
❌ drop |
scope |
FB=... grammar only |
granted scope | verify no OIDC leak |
Smoking gun: producer already contradicts DC's own consumer
DC's ResourceValidationFilter reads resourceURI off the token and expects the /resource/Batch/Subscription/{id} form (uri.contains("/resource/Batch/Subscription")). The producer emits /resource/Subscription/{id} — so a real token's resourceURI already fails DC's own resource validation. The two halves were written against different assumptions; the consumer was right, the producer wrong.
Root-cause fix (not a string patch)
The drift exists because producer and consumers each encode the ESPI URL format independently. Introduce one canonical ESPI Batch-URI builder + parser in openespi-common, and route the producer (SubscriptionProvisioningServiceImpl) and consumers (ResourceValidationFilter, the DC introspector URI parsing) through it — same code builds and parses, so drift becomes structurally impossible.
Then:
- Correct
customerResourceURItoBatch/RetailCustomer/{rc}(and""when no PII). - Drop the three non-standard
*_idclaims (AS customizer + DTOs); the URIs are the contract, DC parses ids from them. (Verifyopenespi-thirdpartydoesn't read the*_idfields.) - Verify
scopeis FB-grammar only and that the URI claims actually reach/oauth2/introspect.
Verification / lock
ESPI-standard contract fixtures (Subscription + Bulk) + producer/consumer contract tests (#150). Test-first red→green.
Acceptance
- Producer emits standard
Batch/{Subscription|Bulk|RetailCustomer}URIs via the canonical builder -
ResourceValidationFilter+ introspector parse via the same canonical parser -
*_idclaims removed;scopeFB-grammar only verified - Contract fixtures + tests pin both sides (CI-enforced where the module runs in CI)
Activity
fix(#160): correct AS↔DC token/introspection wire format to the ESPI …
chore(#160): introspection-claim verification + remove vestigial cust…
feat(#158): DC→TP notification contract + TP-receiver stub (#163)
feat(#150): AS↔DC back-channel request/response wire contract (#165)