Dariusz Sikorski
Dariusz Sikorski

Reputation: 4407

Meteor: How to prevent client from accessing methods

All meteor methods can be called same way from client and server side.

Let's say user knows or can predict all the method names on server, then he is able to call them and use it's result however he want.

example: A method which performs cross domain http request and return response can be used to overload server by calling huge amounts of data Meteor.call(httpLoad, "google.com");, or a method which load data from mongo can be used to access database documents if the client know document _id Meteor.call(getUserData, "_jh9d3nd9sn3js");.

So, how to avoid this situations, may be there is a better way to store server-only functions than in Meteor.methods({...})?

Upvotes: 2

Views: 1800

Answers (4)

tomsp
tomsp

Reputation: 1807

as rightly stated in other answers, your methods will always be accessible from the client (per design). yet, there is a simple workaround to check if the call originates from the client or from the server. if you do a

if ( this.connection == null )

this will return true if the method was called from server. like that you can restrict the method body execution to 'secure' calls.

Upvotes: 4

Michael Mason
Michael Mason

Reputation: 932

Meteor methods are designed to be accessed from the client, if you don't want this, you just need to define a normal javascript function on the server. A really basic example would be:

server/server.js:

someFunction = function(params) {
    console.log('hello');
}

As long as it's in the server folder, the function won't be accessible from the client.


For coffeescript users, each file is technically a separate scope, so you would have to define a global variable with @, e.g.

@someFunction = (params) ->
    console.log 'hello'

or if you want to scope the function to a package:

share.someFunction = (params) ->
    console.log 'hello'

If you have methods that need to be accessible from the client but only for say admin users, you need to add those checks at the start of the meteor method definition:

Meteor.methods({
    'someMethod': function(params) {
        var user = Meteor.user();
        if (user && (user.isAdmin === true)) {
            // Do something
        } else {
            throw new Meteor.Error(403, 'Forbidden');
        }
    }
});

I'm not going to vouch for the security of this example - it's just that, an example - but hopefully it gives you some idea of how you would secure your methods.

EDIT: Noticed the other answers mention using a if (Meteor.isServer) { ... } conditional. Note that if you are doing this inside methods which are also accessible on the client, the user will be still be able to see your server code, even if they can't run it. This may or may not be a security problem for you - basically be careful if you're hardcoding any 3rd-party API credentials or any kind of sensitive data in methods whose code can be accessed from the client. If you don't need the method on the client, it would be better to just use normal JS functions. If you're wrapping the whole Meteor.methods call with a isServer conditional, the code will be on the server only, but can still be called from the client.

Upvotes: 5

Paul
Paul

Reputation: 27413

With proper app design, you shouldn't care whether a request was through the web UI or via something typed in a console window.

Basically, don't put generic, abuse worthy functions in Meteor.methods, implement reasonable access controls, and rate-limit and/or log anything that could be a problem.

Any server-side function defined in Meteor.methods will have access to the current user id through this.userid. This userid is supplied by Meteor, not a client API parameter.

Since that Meteor Method server-side code knows the login status and userid, it can then do all the checking and rate limiting you want before deciding to do that thing that the user asked it to do.

How do you rate limit? I've not looked for a module for this lately. In basic Meteor you would add a Mongo collection for user actions accessible server-side only. Insert timestamped, userid specific data on every request that arrives via a Meteor method. Before fulfilling a request in the server method code, do a Mongo find for how many such actions occurred from this userid in a relevant period. This is a little work and will generates some overhead, but the alternative of rate-limiting via a server-wide underscore-style debounce leaves a function open for both abuse and denial-of-service by an attacker.

Upvotes: 0

akmur
akmur

Reputation: 1635

I think this page explains it: http://meteortips.com/first-meteor-tutorial/methods/

I'm quoting:

"The safer approach is to move these functions to the isServer conditional, which means:

Database code will execute within the trusted environment of the server. Users won’t be able to use these functions from inside the Console, since users don’t have direct access to the server.

Inside the isServer conditional, write the following:

Meteor.methods({
   // methods go here
});

This is the block of code we’ll use to create our methods."

and so on. I hope this helps.

Upvotes: 0

Related Questions