Skip to content

LiveQuery WebSocket server ignores enableAnonymousUsers and CLP #2851

Closed
@ruimgoncalves

Description

@ruimgoncalves

LiveQuery WebSocket server ignoresenableAnonymousUsers = false setting and allows an anonymous user to connect and subscribe to queries even if sessionTokenis not passed.

The LiveQuery server should prevent clients from connecting if this setting is turned off, and make both servers work consistently. This also prevents the need of setting ACL on each document if the intent is only check for current logged-in users and thus reducing the servers overhead.

I also unchecked the GameScore class public read and write operations in CLP via the Parse Dashboard, so I expected the server to block read operations from unknown users. Then I read the LiveQuery docs and it does not take into account CLP. I think it could be interesting to have less granular security management in some scenarios, like this one.

Steps to reproduce

  1. Install latest version, git clone https://github.com/ParsePlatform/parse-server-example.git and npm install
  2. Create a GameScore class with some fields, like [playerName, score, cheatMode], goto security (CLP) and uncheck Public Read and Write.
  3. Change the server index.js file
var api = new ParseServer({
  databaseURI: databaseUri || 'mongodb://localhost:27017/dev',
  cloud: process.env.CLOUD_CODE_MAIN || __dirname + '/cloud/main.js',
  appId: process.env.APP_ID || 'myAppId',
  masterKey: process.env.MASTER_KEY || 'masterKey', //Add your master key here. Keep it secret!
  //clientKey: process.env.CLIENT_KEY || 'clientKey',
  serverURL: process.env.SERVER_URL || 'http://localhost:1337/parse',  
  enableAnonymousUsers : process.env.ENABLE_ANON_USERS || false,
  allowClientClassCreation: process.env.CLIENT_CLASS_CREATION || false,
  verbose : process.env.VERBOSE || 1,
  liveQuery: {
    classNames: ["GameScore"] // List of classes to support for query subscriptions
  }
});
  1. Create an empty html file add this javascript script
Parse.initialize("myAppId");
Parse.serverURL = 'http://localhost:1337/parse';
console.log("Current user", Parse.User.current());

let query = new Parse.Query('GameScore');
query.find().then((data, err)=>{
   console.log("Find = ",data, err);
});

let subscription = query.subscribe();
subscription.on('open', () => {
   console.log("Connection Open");
});

Parse.LiveQuery.on('error', (error) => {
   console.error("Connection Error", error);
});

Expected Results

The logs messages should be

Current User, null
Connection Error ...

The connection should be rejected and a console message should be Connection Error. The client should not receive additional messages from the ws server.

Actual Outcome

Instead you get in the browsers console the log message

Current User, null
Connection Open

As proof, open chrome dev tools -> network, filter by WS (websocket) connections and open the row with the parse name, then select the frames tab, you get data frames every time the subscribed data is changed. So to test this open Parse Dashboard and create, delete or edit documents in the GameScore collection.

Environment Setup

  • Server
    • parse-server version : 2.2.22
    • Operating System: Windows 10.0.14393
    • Hardware: Intel i7 64x, 8G ram
    • Localhost with Node 6.7.0
  • Database
    • MongoDB version: 3.0.0
    • Storage engine: { storage: { dbPath: "./db", journal: { enabled: true }, mmapv1: { smallFiles: true } } }

Logs/Trace

verbose: Current clients 0
verbose: Current subscriptions 0
verbose: REQUEST for [GET] /parse/classes/GameScore: {
  "where": {
  },
} method=GET, url=/parse/classes/GameScore, host=localhost:1337, connection=keep-alive, content-length=177, pragma=no-cache, cache-control=no-cache, origin=http://localhost:1337, user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36, content-type=text/plain, accept=*/*, referer=http://localhost:1337/public/test.html, accept-encoding=gzip, deflate, ,pt;q=0.8,en-US;q=0.6,en;q=0.4, 
error: Error generating response. ParseError {
  code: 119,
  message: 'Permission denied for action find on class GameScore.' } code=119, message=Permission denied for action find on class GameScore.
verbose: Request: %j op=connect, applicationId=myAppId
info: Create new client: 1
verbose: Push Response : "{\"op\":\"connected\",\"clientId\":1}"
[object Object]
verbose: Request: %j op=subscribe, requestId=1, className=GameScore, 
verbose: Push Response : "{\"op\":\"subscribed\",\"clientId\":1,\"requestId\":1}"
verbose: Create client 1 new subscription: 1
verbose: Current client number: 1

Metadata

Metadata

Assignees

No one assigned

    Labels

    type:featureNew feature or improvement of existing feature

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions