Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Meteor.userId is changeable

Tags:

Playing around with Meteor, I have found that even with the insecure package removed, the client can change the Meteor.userId function. For example,

Meteor.userId=function() {return "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee"} 

as can be done with Meteor.default_connection.userId() (the redirected function). How do I secure this?

like image 506
Zwade Avatar asked Nov 11 '12 14:11

Zwade


People also ask

How to get the user ID of a user in Meteor?

Once a user is logged into your app with one of the methods described above, it is useful to be able to identify which user is logged in, and get the data provided during the registration process. For code that runs on the client, the global Meteor.userId () reactive function will give you the ID of the currently logged in user.

What is the meteor accounts system?

The Meteor Accounts system builds on top of the userId support in publish and methods. The core packages add the concept of user documents stored in the database, and additional packages add secure password authentication, integration with third party login services, and a pre-built user interface.

What is the User Package in Meteor?

This package is the core of Meteor’s developer-facing user accounts functionality. This includes: A users collection with a standard schema, accessed through Meteor.users, and the client-side singletons Meteor.userId () and Meteor.user (), which represent the login state on the client.

Does Meteor know which user fields are needed by callbacks?

Nor does Meteor know which user fields are needed by callbacks registered with Accounts.onLogin (), Accounts.onLogout (), Accounts.onLoginFailure () and Accounts.validateLoginAttempt (). To solve this problem Meteor 1.10 also introduced a new Accounts.config ( {defaultFieldSelector: {...}) option to include or omit specific user fields by default.


1 Answers

This is a great question because it shows how the Meteor security model works.

There's no security issue here because Meteor never trusts the client code.

In Meteor, only the server decides what data each client has access to (see Meteor.publish) and what data each client is allowed to change (see Meteor.allow). When a client authenticates to the server, the server stores the user's ID. Until that client logs out, it provides that ID to your Meteor.publish and Meteor.allow functions on the server as userId.

Meteor also sends the user ID down on the client, because of course you want to change how the client behaves and what's on the screen based on who is logged in. And as you say, we can't stop a rogue client from arbitrarily changing any of its JavaScript code to change what it thinks the user ID is! But doing that doesn't give the client any new permissions, because it's still only the server code that makes the security decisions.

You can try this out using the secure parties application:

  1. Make a parties app with $ meteor create --example parties
  2. Create a user account and double click on the map to create a party. Check the box to make it a private party.
  3. Open the JavaScript console and type Meteor.userId() to get your user`s ID.
  4. Log out. The party will disappear from the screen because the server won't publish it to any other user.
  5. Now, go into the console and overwrite Meteor.userId() with a new function that returns the ID you want.

So now you've faked the client to think that it's your user. But the server knows better. There still won't be a party on the screen, and you can't update the Parties collection to change that party information.

In fact, it's completely safe to set the client user ID to anything you want! You can reach right into the accounts system and call Meteor.default_connection.setUserId("aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee");. Try it, and you'll see that the login button in the upper right corner turns into an animation. That's because the client is calling Meteor.user() to show the email address of the logged in user you just set. But because you haven't logged into the server as that user, it's not publishing any information about that user and you just get the spinny.

This is a very strong security model. You don't have to worry about any of the client code, even though in most apps that's where most of the code lives! As long as you write secure server methods, publish functions, and allow/deny rules, you're completely locked down no matter what the client tries to do.

like image 148
debergalis Avatar answered Dec 20 '22 17:12

debergalis