Securely Handling User IDs?

I understand that it is a security error to pass the user ID as an argument to a function on the client.

Let’s say I have a chat function. Both clients need to be aware of the user id of the client they are talking to. What is the correct way to communicate the user ids to the client functions that need them in this case?

It’s fine to pass the user id from the client, as long as you validate all of the security requirements on the server. The main issue is when you simply trust that someone who has access to a user’s ID can do stuff with it.

2 Likes

Very good. Currently I have the user id of the user I am sending a chat to, as a url segment. Is that also acceptable?

Yes, but you may want to check for example whether it’s a “friend” so people cannot spam others.

3 Likes

Put simple:

  • Meteor.call(“name”, whataremyrights, otherstuff) - BAD.
  • Meteor.call(“name”, otherstuff), user-rights validated on server - GOOD.

userID itself has no value, unless you have insecure methods.

I totally get that-- the server needs to determine what rights the user has.

However, when you say userID has no value unless you have insecure methods, I don’t quite get that yet. It appears that out of the box Meteor provides Meteor.userID(), which does give you the _id of the logged-in user. Also, in a chat function, you need an ID of the user you have chosen to send a chat too. What would be the way you would recommend for the client to determine the ID of that user?

Well, you may just use methods and publications.

As soon as you enter a username(or a part of it), you may request list of matching user-objects(ofcourse only fields like profile, username and id) as return of method or via publication(that’s just for UX). You may then match any field, like username or group(if you have groups), userID just insures there’s only one user record matching it.

So when you know id/name/group of a user you wanted to chat with, you may pass it as method parameter and make a successful user/data validation and new chat record insertion. Obviously, you should make checks to insure that user(that calls method) has matching rights. That’s where you need to insure that you are checking things like admin status securely.
So you don’t pass things like Meteor.call('chat", {admin: true, myUserID: whateveriwant})
and check his userID on server via Meteor.userID() inside method itself.

To make sure I follow what you are saying, I’d like to ask, how can the client search for previous chat messages from the user he or she is chatting with, without having the client capture and expose the userID of that user? The client must have some way to identify that userID, yes?

As I said, there’s no use of userID by itself.
Any document inside mongodb contains ID field, user documents are not an exception.
Whenever you send data via reactive publications, you always expose IDs, there’s nothing wrong about it.

If you don’t understand concept of data links and ids inside mongodb,
I advice you reading One-To-Many articles of official mongodb documentation. Its not really meteor-related.