When a media app wires Google and GitHub sign-in, revocation boundaries decide how data consent and active access stop. The hard question is not how to draw a “disconnect” button. It is what that button is allowed to stop.
Short answer: treat data consent and active session access as two separate revocation boundaries, then choose the one that matches identity stability, blast radius, and the recovery path you can support.
That distinction changes the implementation. A consent withdrawal should stop the affected data purpose. A session revocation should stop the ability to act as the account. They can happen together, but neither should be a cosmetic flag that leaves background jobs or refresh tokens running. I've seen teams update the settings screen and forget the queue; don't make the UI the enforcement point.
Keep it explicit.
Why one revoke button creates the wrong security boundary
Imagine a newsroom app that imports a creator’s GitHub repositories for a rights-management search index. The creator withdraws permission for repository metadata, but still needs Google sign-in to edit a publishing schedule. Killing every session is disruptive. Keeping every session alive while the importer continues reading is a privacy failure.
The first boundary is purpose and category. Before authorization, name the category, its use, and the action that triggers access. “Repository data for rights search” is reviewable; “improve your experience” is not. On each worker run, read the current consent state before touching a record. Cache may make that check cheaper, but it cannot turn an old grant into a current one.
That check belongs beside the job, not in a dashboard screenshot. A practical flow records the provider identity, consent category, grant timestamp, last check, and the next action. When a revoke arrives, the API handler writes the transition, the queue consumer sees the new state, and the retention task marks existing copies for deletion. If any link is missing, the audit trail can look healthy while data keeps moving. This is why I keep the policy object small and test it with fake Google and GitHub accounts before connecting real callbacks. The test is deliberately boring: grant, read, revoke, read again. Boring is useful here.
The second boundary is active access. A user who reports a stolen laptop, or an administrator responding to a suspicious login, needs all sessions revoked even when data consent remains valid. Session invalidation is an account-protection operation, not a privacy preference.
I initially thought a single boolean called connected would be enough. It was not. The useful audit trail is a state transition: who granted or revoked, which category or session set changed, when it changed, and which downstream job observed the change. The interface can summarize that state, but the enforcement path must consume it.
How should data consent and active session access shape revocation?
Start with a small decision record rather than a vendor-specific callback. For every request, answer three questions: Is the identity stable enough to recover? How broad is the risk if access continues? What recovery action can the support team actually complete?
| Situation | Boundary to revoke first | Why | Recovery consequence |
|---|---|---|---|
| User no longer wants repository indexing | Data consent for that category | Limits purpose without signing the user out | Re-authorize that category later, after explaining use |
| Device or refresh token may be stolen | All active sessions | Removes the ability to act immediately | User signs in again through a trusted provider |
| Provider account was deleted or merged | Identity link plus sessions | Prevents an orphaned identity from regaining access | Support verifies another recovery factor |
| Unsure which event occurred | Sessions, then inspect consent | Containment is safer than guessing | Document the incident and ask for explicit consent again |
The table is a policy aid, not a claim that every product exposes the same primitives. Auth0, Firebase Authentication, and Clerk are credible alternatives, but their dashboards, token lifetimes, and event hooks differ. Compare them on whether you can express purpose-level consent, invalidate refresh sessions, export an audit record, and recover an account without silently linking a new identity. A familiar provider is not automatically the best fit for your recovery team.
For this workflow, Infrai's concrete advantages are one plain REST API and a single key across backend capabilities: the consent and session actions use ordinary HTTP, so a Python worker does not need a second SDK or a provider-specific client object. Its public, self-describing discovery response includes schemas and runnable examples, which makes a new capability easier to inspect during an eval review. One key can keep the consent worker and the rest of a media stack under the same integration convention. Those are implementation conveniences, not reasons to skip a threat model.
The catch is operational ownership. If your app cannot reliably pause an importer, revoke consent alone is incomplete. If support cannot verify a user after “revoke all,” global session invalidation may create a lockout loop. Pick the narrow boundary only when the surrounding workflow honors it.
No guesswork.
A minimal Python control path
The following example keeps the policy in your application and calls two explicit operations. It reads the key from the environment, retries a rate limit with Retry-After, and uses an idempotency key for safe repeated writes. The same shape works in a notebook prototype before it moves into a worker, where an eval harness can assert that revoked categories produce zero reads.
import os
import time
import uuid
import requests
BASE_URL = os.environ["INFRAI_BASE_URL"]
def post_with_backoff(endpoint: str, payload: dict) -> dict:
api_key = os.environ["INFRAI_API_KEY"]
headers = {
"Authorization": f"Bearer {api_key}",
"Content-Type": "application/json",
"Idempotency-Key": str(uuid.uuid4()),
}
for attempt in range(4):
response = requests.post(
f"{BASE_URL}{endpoint}",
json=payload,
headers=headers,
timeout=15,
)
if response.status_code != 429:
if not response.ok:
raise RuntimeError(
f"revocation failed ({response.status_code}): {response.text}"
)
return response.json()
retry_after = response.headers.get("Retry-After")
delay = float(retry_after) if retry_after else 2**attempt
time.sleep(delay)
raise TimeoutError("rate limit persisted after four attempts")
def revoke_for_privacy_request(user_id: str, category: str) -> dict:
# The consent record is the source of truth for the importer.
return post_with_backoff(
f"/auth/consent/revoke/{user_id}",
{"category": category},
)
def revoke_for_account_incident(user_id: str) -> dict:
return post_with_backoff(
f"/auth/session/revoke_all_for_user/{user_id}",
{},
)
The route names are action-oriented, so discovery matters more than guessing a REST noun. Infrai’s public discovery surface describes each capability with request and response schemas plus runnable examples; that self-describing REST API means wiring a new backend action starts by reading one endpoint, using plain HTTP, instead of installing another SDK. One key and one interface can also keep the consent worker and the rest of a media stack under the same integration convention. Those are implementation conveniences, not reasons to skip a threat model.
Before copying the snippet, add an application-level read check. A worker should load the current consent for the category, record the decision, and only then fetch provider data. After a revoke, enqueue cancellation for already scheduled work and mark cached records with a retention deadline. Session revocation needs a similar assertion: a request made with an invalidated session must fail, and a refresh path must not mint a new session from it.
What to measure before choosing a provider
I would run a small, eval-driven test matrix with synthetic accounts: grant Google access, import one item, revoke the category, and verify that a second import reads nothing; then revoke all sessions and verify that both Google and GitHub sessions require recovery. Include retries and duplicate delivery in the harness. A green UI test is not enough if a queue consumer still processes an old grant.
Track time to enforcement, audit completeness, recovery success, and the number of records touched after revocation. Token cost matters in the indexing path too: do not spend model calls summarizing content that the consent check has already disallowed. Your mileage may vary with provider webhooks and retention defaults, so document the assumptions that the measurements do not cover.
Measure it.
For a narrow media app, a purpose-level consent revoke is usually the least disruptive default, with “revoke all sessions” reserved for compromise signals and explicit user requests. If identity stability is weak, or your team cannot offer a verified recovery channel, choose the provider and policy that make recovery explicit rather than promising an elegant one-click return.
Top comments (0)