parse-community / parse-community/parse-server

LiveQuery role cache is not invalidated for all users affected by a role write or delete

Open
#10,628 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
JavaScript
Stars
21.4k
Forks
4.8k
Avg merge
7h 45m
Merged PRs (30d)
11

Description

New Issue Checklist
Issue Description

LiveQueryController.clearCachedRoles(user) invalidates the LiveQuery server's cached auth for a single user, and only when a user is present on the request. Both call sites pass the acting user:

  • src/RestWrite.js (runDatabaseOperation, role create and update)
  • src/rest.js (del, role delete, added in #10620)

That leaves two cases where a role change does not invalidate LiveQuery's cached role closures:

  1. No user on the request. clearCachedRoles returns early when user is falsy, so a master key write or delete publishes nothing at all. Managing roles with the master key, from admin tooling or cloud code, is the common case.
  2. Users other than the actor. ParseCloudCodePublisher#onClearCachedRoles publishes a single { userId }, and ParseLiveQueryServer#_clearCachedRoles(userId) resolves _Session rows for that one user. Adding or removing a member, or deleting a role that other roles inherit from, changes the effective closure for users who are never signalled.

The blast radius is bounded, which is why this is filed separately rather than as a security report. The REST and auth side is already correct: cacheController.role.clear() is global and drops the cached closure for every user. ParseLiveQueryServer's authCache is an LRU bounded by cacheTimeout, so stale entries expire on their own. The gap is confined to LiveQuery event delivery being decided from a stale role closure until that TTL elapses.

This predates #10620 and applies equally to the role write path, which has behaved this way since #8026 introduced clearCachedRoles.

Steps to reproduce
  1. Start Parse Server with LiveQuery enabled for a class whose ACL grants read access to role:Editors.
  2. Log in as a user who is a member of Editors and subscribe to a query on that class.
  3. Using the master key, delete the Editors role (or remove the subscribed user from it).
  4. Save an object matching the subscription.
Actual Outcome

The subscriber keeps receiving events for objects it can no longer read, until its authCache entry expires after cacheTimeout. With the master key, no clearCache message is published at all. With a session-authenticated request, only the acting user's sessions are invalidated, so other members of the role see the same staleness.

Expected Outcome

A role write or delete invalidates the LiveQuery auth cache for every session whose effective role closure changed, including when the request carries no user.

Environment

This is a code path report from review of #10620, not a runtime bug report, so the client and hosting fields are not meaningful.

Server

  • Parse Server version: 9.10.1-alpha.6 (present on alpha, and on every release since #8026)
  • Operating system: n/a
  • Local or remote host: n/a

Database

  • System (MongoDB or Postgres): n/a
  • Database version: n/a
  • Local or remote host: n/a

Client

  • SDK (iOS, Android, JavaScript, PHP, Unity, etc): n/a
  • SDK version: n/a
Logs

None. The failure is silent by construction: clearCachedRoles returns early without logging when there is no user.

Notes on possible directions

Not a proposal, just the options that came up in review, both of which change the shape of the clearCache pub/sub message that is shared between LiveQuery server instances and therefore needs a back compat story for mixed-version deployments:

  • Broadcast a clear-all when no specific user can be identified, accepting that it flushes every connection's auth cache on every role write.
  • Publish the affected role id and let the LiveQuery server resolve the sessions to invalidate, which keeps the blast radius small but requires the server to expand the role closure.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by tracing the role write and delete call sites in src/RestWrite.js and src/rest.js, then read LiveQueryController.clearCachedRoles, ParseCloudCodePublisher#onClearCachedRoles, and ParseLiveQueryServer#_clearCachedRoles. Reproduce the master-key and non-acting-member cases from the issue. Done means affected sessions, including users reached through role membership or inheritance, stop receiving unauthorized events without breaking mixed-version clearCache messages.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript, node.js
Domain
authentication, authorization, backend
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
38/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.