How to prevent secret business logic to be sent to client?


#1

Hi,

I’m working on a Meteor app with a lot of code to handle various task.
In order to organize my project, I split the code in two parts :

  • api/ : Defining collections, methods, publications and such
  • module/ : Defining business logic such as post processing, logging and so on.

I followed the guideline specified here to keep some business logic hidden from client, but it doesn’t seem to be working as it should.

For example, I have a collection defined on the client and on the server, named UserAvatar (based on ostrio:files.
I have the following code in a part of the collection :

if (Meteor.isServer)
{
    let callback = Meteor.bindEnvironment(function()
    {
        user.avatar = avatar.link();
        user.save();
    });

    let { ImagePostprocessing } = require("../../modules/postprocessing/ImagePostprocessing.js");
    ImagePostprocessing.avatar(file.path, AVATAR.MAX_WIDTH, AVATAR.MAX_HEIGHT, callback);
}

Altough I understand this block of code is still sent to the client because the actual whole UserAvatar.js file is imported on the client, why is the ImagePostProcessing module visible in the debugger of my browser (the content of the file, not the related line in the code)?
Isn’t this supposed to be hidden as explained in the guide ?

Note that even though the file is visible client side (I can read the source), it is not loaded otherwise my application would crash because I’m loading gm which cannot work client side.

Thanks for your answer,


#2

From said docs:

Keep in mind that code inside if (Meteor.isServer) blocks is still sent to the client, it is just not executed. So don’t put any secret code in there.

Any code you’d like to hide from the frontend, put in a folder called ‘server’.

As far as I know, the ‘require’ part is still evaluated, so Meteor can then include any dependencies at build time. Which then makes said dependencies available for later execution. This is likely why you can see it in the browser.

Personally, I think that you should completely forget about Meteor.isClient and Meteor.isServer, which are mostly useful in a small codebase, and instead employ ‘client’ and ‘server’ folders.


#3

I get your point about Meteor.isClient and Meteor.isServer and I try to avoid them massively.

In this case though, my Collection is available on the client and on the server (which is perfectly fine), but the file which defined the module is located on the imports directory.
I only need it loaded on the server, which is why I assumed requiring it inside the block wouldn’t make it visible on the client as well as not evaluated (which is the case, at least for the evaluation).

Now, I see that making things like this imports/modules/server/postprocessing make the module being invisible on client. I assume the correct way of doing it is this one, right ?
Meaning I have to put server only module on a server/ directory, no matter where they are located in my project, right ?

Is that so, I assume that if my module is currently available both in client and server, I just have to put the server part of the code in a server/ directory as well to make it invisible when the module is imported client side right ?


#4

I agree that that’s a fair assumption, and one can easily make this mistake.

Yes. Here’s more about the Meteor special directories.

That’s right.


#5

Okay, sorry for bothering you with this, I should have figured it myself.
I was really hoping I could avoid refactoring code again, but seems there is no other way in this case if I don’t want my code exposed and a security leak.

Thanks for your answer, gonna mark this as answered :slight_smile:


#6

No bother, really :slight_smile:

Glad I could help.