Repository navigation
Consent withdrawal must trigger token revocation + subscription cleanup #138
Description
Background
PR #137 (#122 PR B1) reworked Subscription ↔ Authorization to N:1 with Authorization as the aggregate root:
Authorization@OneToMany(cascade=ALL, orphanRemoval=true)→Subscriptionsubscriptions.authorization_idisNOT NULLwith DB-levelON DELETE CASCADE
That makes the mechanism correct: deleting an Authorization cascades to its Subscription(s); dropping the customer-PII child from the collection removes only the customerResourceURI subscription via orphanRemoval.
The gap
The policy / trigger is still missing. Two cases:
-
Token expiration / revocation → today this does not propagate to the
Authorizationaggregate. An expired or revoked access token leaves theAuthorizationrow (and itsSubscriptionchildren) sitting in the DB as stale state. -
Customer withdraws consent (via the utility's customer portal) → today this does not automatically revoke the OAuth access token. The token remains valid until natural expiry, so the TP keeps pulling data the customer has withdrawn consent for.
These are the two halves of the same invariant: authorization lifecycle and token lifecycle must move together.
Proposed direction (for discussion, not this issue's scope)
- Token-revoked / token-expired → Authorization removal: hook the AS revocation endpoint and an expiry sweep to delete the corresponding
Authorization. With B1's cascade, theSubscription(s) go with it. - Consent-withdrawn → token revocation: when the customer portal removes (or narrows) consent, call the AS revocation endpoint (RFC 7009) — or, for PII-narrowing, mutate the
Authorization.subscriptionslist to drop thecustomerResourceURIchild (relies onorphanRemovalfrom B1) and re-mint the token with the reduced scope (since opaque tokens encode scope at mint time).
Out of scope here
- PR B1 (refactor(common): subscription↔authorization N:1, authorization as aggregate root (#122 PR B1) #137) — done, mechanism only.
- PR B2 — DC subscription-create back-channel (separate, in flight).
Acceptance criteria (when this issue is worked)
- Revoking an access token (RFC 7009) removes the corresponding
Authorizationrow and cascades to itsSubscription(s). - Natural token expiration triggers the same cleanup (sweep job or lazy-on-introspect).
- Customer portal "withdraw consent" path calls the AS revocation endpoint.
- Customer portal "narrow consent to drop PII" path removes the
customerResourceURIsubscription from the aggregate and re-mints the token with the reduced scope. - Integration test covering each of the four paths above against the 3-DB matrix.
Activity