Should I declare my collections in the "both" folder? - javascript

I would like to confirm something:
If I declare my collection in the both folder and my allow and deny rules in the server folder, does it mean that, as long as it fits into allow and deny rules, the user can change the collection using the console?
Then does that mean that my publications and server methods (who are fine tuned in order to enforce confidentiality of the data) are useless, from a security point of view? (i.e. the user can still bypass them by accessing directly the collection with a console)
If I'm right, what would you advise me to do? >
Only declare collections I can fully disclose in the both folder. Declare the rest in the server folder and only provide publications + methods.
transfer my collection methods into allow/deny rules. How would I do then to filter the collection.find() queries (i.e. formerly my publications)?

The collection should be declared in both folder so that you can use it on client and server side.
Yes, user can write (insert/update/remove) to your collection using browser console as long as it match allow and deny rule.
I strongly suggest you ditch allow / deny rule approach and use Meteor.methods and Meteor.call instead where you can have greater control like validation etc. To filter data available to client, use Meteor.publish.

Yes and no. As long as it matches allow/deny rules, clients can update documents via the _id field and the _id field only. Your server publications still control what documents the client has access to see (via the browser console or in code). However, if appropriate allow/deny rules are not set, the client could still potentially update a document via _id (if it somehow gained access to the _id) or insert new documents into the collection.
It sounds like you've mostly got it right already - your Meteor.methods and publications are still useful. You (hopefully) have your client read permissions set up via the publications, and the client write permissions via the Meteor.methods.
There are a couple ways forward from here:
If you want insert/update ability from client-side code, set your allow/deny rules accordingly. There are some advantages to doing this - client-side inserts and updates are essentially a Meteor.method that runs both on the client and server, so the client gets the advantage of seeing near-instantaneous updates, and then the server will check to confirm it's okay. If it's not, no harm no foul - the server says "that's not allowed" and the update is rolled back on the client as well.
Do all of your inserts and updates in Meteor.methods, and just tell Meteor to deny all updates and inserts on the collection. This means the client can't insert or update without calling a Meteor.method, and you build your security into the methods.
This post probably explains it a bit better:
https://www.discovermeteor.com/blog/meteor-methods-client-side-operations/

Related

Disable Meteor Router.routes on browser console for unauthenticated user

I am working on a Meteor application that uses Iron Router. We have a login page in our application. Even when the user is not logged in, if I call the below code on developer console as un-authenticated user:
Router.routes
It gives all the routes and the respective paths. Is there a way to disable access to these paths or do I need to push these end points in the server code ?
Everything you define on the client is visible on the client. So is all the routes definitions and routes logic, too. In production code this will be obfuscated but it's still there.
If you are concerned, that clients can read your routes, then you should be more concerned about the fact that it concerns you. Sounds a bit confusing but the point is: you should double check each data published to client via publications or manipulated / created via methods on server. If your backend is robust and secured as much as possible (100% will never be possible), then you don't need to care, if clients can see which routes exist and get access to them.
An example:
Bob found the route /admin and disabled the router's triggers to redirect him if he is not Admin.
Now Bob could see all data, that Admins can see. To prevent this, you may check in the publication if Bob has the role 'admin' on don't publish to him if he's not admin.
Ada also found this way to the Admin panel and wants to create a new user. Because your server method for creating new users is a ValidatedMedthod that checks if Ava has the 'admin' role it will fail to create a new user, because Ava is not an admin.
Conclusion:
Preventing access on the client side is just UI Magic bot not secure at all. Simple tweaks, however on the server side will help you to sleep better.
More help:
A good way to get started is to read the Meteor Security Guide:
https://guide.meteor.com/security.html
There is also at the end a security checklist, which I just cite for completeness and SEO reasons here:
Make sure your app doesn’t have the insecure or autopublish packages.
Validate all Method and publication arguments, and include the audit-argument-checks to check this automatically.
Deny writes to the profile field on user documents.
Use Methods instead of client-side insert/update/remove and allow/deny.
Use specific selectors and filter fields in publications.
Don’t use raw HTML inclusion in Blaze unless you really know what you are doing.
Make sure secret API keys and passwords aren’t in your source code.
Secure the data, not the UI - redirecting away from a client-side route does nothing for security, it’s just a nice UX feature.
Don’t ever trust user IDs passed from the client. Use this.userId inside Methods and publications.
Set up browser policy, but know that not all browsers support it so it just provides an extra layer of security to users with modern
browsers.
Useful packages mentioned in the answer:
mdg:validated-method
alanning:roles
audit-argument-checks

How do I handle communication between multiple Node.js servers for each user?

I'm trying to make a user log in just once, and have his information on all the servers. Any changes made to the user's information will instantly be available for all servers. Is this possible to do without having each user "log in" separately for each server?
Sort of like the $_SESSION for php, but for Node.js
Design 1 -
What I think would be best to do, but don't know how to share socket data between servers, perhaps using something like PHP's $_SESSION?
Design 2 -
What I'm currently doing:
User uses socket.emit to main.js
main.js adds user information onto the emit
main.js emits to the appropriate server
Appropriate server emits back to main.js
main.js finally emits back to user
This seems awfully inefficient and feels wrong
If your information is primarily static, you can try something similar to JWT. These are cryptographically signed tokens that your authenticating server can provide and the user can carry around. This token may contain information about the user that you want each server to have available without having the user accessing it.
If it's not, you may be looking into sharing a database across all servers, and have that be the point of synchronization between them.
Updates based on our comments (so they can be removed later):
If you decide to use auto-contained JWT tokens, you don't need to be making trips to the database at all. These tokens will contain all the information required, but it will be transparent to the end user that won't have insight into their contents.
Also, once you understand the JWT standard, you don't necessarily have to work with JSON objects, since it is just the serialization approach that you can switch by another one.
You'd provide one of these tokens to your user on authentication (or whenever required), and then you'd require that user to provide that token to the other servers when requesting information or behavior from them. The token will become your synchronization approach.

How to handle users in `_users` database with many applications in the same CouchDB instance?

According to Matt Woodward's Blog, in The Definitive Guide to CouchDB Authentication and Security he points out some things about CouchDB that I'm not sure I understand completly.
He says:
"Basically the way security works in CouchDB is that users are stored in the _users database (or elsewhere if you like; this can be changed in the config file)...".
So, all users of the whole CouchDB are stored in a single database, right? Which means that if I have more than one application running in different databases within the same CouchDB I'd have to handle users who want to access both application, correct?
He also says
"Database readers can only read documents and views on a specific database, and have no other permissions".
Then, he adds
"By default all databases are read/write enabled for anonymous users, even if you define database admins on a database".
So anonymous users can or can't read documents in a specific database?
I'll start out by saying that those articles, while still informative, are several years old and possibly outdated. I would recommend reading through the official documentation if you are trying to learn about CouchDB.
Now to answer your question. (more information about security here and here)
In CouchDB, security is something you can incrementally build up as you are developing your application. The default is very open, and you lock things down by adding configuration. (in what I think is a pretty intuitive fashion)
By default, CouchDB is in "Admin Party" mode, which means anyone can read and write anything. (because every user, including anonymous users, are treated as admins)
Once you add any admin users to your server, (via configuration, not the _users database) the party is over. What this means is that some actions can now only be performed by the admin's you've explicitly defined. (such as creating databases, setting config, etc)
In this state, anonymous users can still read/write normal documents in any database that has been created. (design documents can only be modified by admins) If you are ready to start locking down individual databases, you can do that by specifying users/roles in the security object for a given database.
When people use the term "database reader", they mean that a user has been added as a "member" in the security object. (either by their username, or their role) By specifying any members or admins in the security object for a database, then only those users will have permissions inside the database, all others will be disallowed.
To summarize, anonymous users can read/write anything by default. Once an admin is designated, security tightens and certain actions can only be done by that admin. If you specify database members/admins, the security for a database tightens even more, only allowing those users to even read the database.

Client Side JavaScript and database interaction

I have been working on a large project for about 4 months.
We have a "lead" that I constantly question.
The rules of the project (from the customer who has no background in IT) are
Only JavaScript will be used (Kendo UI package for CRUD).
It is to be "secured" with SSO - ADFSv2/ACS
It must have use Odata to interact with the database.
Please correct me if I am wrong, but does this not mean
A. This is clearly insecure. (after the initial login)
B. How can Kendo even handle database interaction (correctly) if it must update multiple tables?
There is another programmer currently working on a similar project and he is using Node.js for a web app that interacts with a Database.
Doesn't this suffer from a similar issue?
How does this client side CRUD work security and accurately?
Correct me if I am wrong, but it seem to me that you think that javascript directly access the database.
For that I see, Javascript is only used to manage the UI, and to contact (with Ajax ?) the server to update/create/delete entities.
It isn't insecure, but developers must ensure that the requested user's action is permitted (on server side).
Example : For a DELETE requested URL like https://myServer/myApp/Person/1, an user can modify this URL like https://myServer/myApp/Person/6 or https://myServer/myApp/Work/1.
So it must be verify that the user can delete a Person with id=6, or a Work with id=1.

Storing auth data on the client side

I have an application which uses Backbone JS to render its views (among other things like models etc.).
Parts of my application should only be displayed to admin users, but the only way for Backbone templates to know this is for some JS variable/localStorage/Cookie to be set to indicate such.
The first worry here would, of course, be security. I am only really storing things like User.id, User.isAdmin etc. in here. Furthermore, since the only things limited to administrators would involve server-side involvement, changing User.isAdmin = true on the client side will just give them the interface options, but none of the power.
I know that using Cookies for this sort of thing is probably frowned upon, and with good reason, since Cookies are sent to and fro across all HTTP requests creating unnecessary overheads.
Therefore my question is, how best should I tell my client-side application about User authentication data. I am using jStorage (http://www.jstorage.info) for localStorage access, but it does not use SessionStorage. Would the latter be more appropriate than the former?
Speaking generally, you need roles and possibly privileges on the server. This way, even if a nefarious user tweaks the client, user cannot actually access or modify restricted data, because if they try, they still havent modified the role on the server. If you audit log access, you will know fairly quickly if a user tries something for which they don't have privileges.
The worst that can happen under a scheme like this is the user could see what the admin screens look like. This still might be a breach, since they might see buttons that could inform them how the system works.
If you need to protect that, you could delay the loading of the templates for the "Admin Section" of your app until after a users role has been verified. So all restricted sections are almost loaded as a separate app (or an actual separate app). That way, even if the user tries to fool the client to load the admin section, when the request goes to the server you don't return the module, since the server will not show the user as having admin privileges.

Categories