Disable Meteor Router.routes on browser console for unauthenticated user - javascript

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

Related

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

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/

how to make sure only my own website (clientside code) can talk to Firebase backend?

I've read about Firebase and it looks awesome for what I want to do.
I've read about authentication and how based on rules certain logged-in users are authorized to do different stuff. Al good.
However, I'm unsure about another type of security: how do I make sure that only my own site (using client-side javascript) can talk to my firebase-backend? I'm asking because afaik there's no way to prevent anyone from looking up my firebase endpoint from the client-side code (url pointing to my specific firebase backend) and start using that for god knows what.
This is especially worrisome in situations in which I want to open up writes to the anonymous user role. (e.g: some analytics perhaps)
Any help in clearing my mind on this much appreciated.
Update (May 2021): Thanks to the new feature called Firebase App Check, it is now actually possible to limit calls to your backend service to only those requests coming from iOS, Android and Web apps that are registered in your Firebase project.
You'll typically want to combine this with the user authentication based security that Kato describes below, so that you have another shield against abusive users that do use your app.
In my opinion, this isn't so much a question about Firebase's security as a general discussion of the internet architecture as it stands today. Since the web is an open platform, you can't prevent anyone from visiting a URL (including to your Firebase) any more than you can prevent someone from driving past your house in the real world. If you could, a visitor could still lie about the site of origin and there is no way to stop this either.
Secure your data with authentication. Use the Authorized Domains in Forge to prevent CSRF. Put security rules in place to prevent users from doing things they should not. Most data writes you would use a server to prevent can be accomplished with security rules alone.
This is actually one of the finer qualities of Firebase and API services in general. The client is completely isolated and thus easily replaced or extended. As long as you can prove you're allowed in, and follow the rules, where you call in from is unimportant.
Regarding anonymous access, if you could make them visit only from your site, that still won't stop malicious writes (I can open my JavaScript debugger and write as many times as I want while sitting on your site). Instead, place tight security rules on the format, content, and length of data writable by anonymous users, or save yourself some time and find an existing service to handle your analytics for you, like the ubiquitous Google Analytics.
You can, of course, use a server as an intermediary as you would with any data store. This is useful for some advanced kinds of logic that can't be enforced by security rules or trusted to an authenticated user (like advanced game mechanics). But even if you hide Firebase (or any database or service) behind a server to prevent access, the server will still have an API and still face all the same challenges of identifying clients' origins, as long as it's on the web.
Another alternative to anonymous access is to use custom login, which would allow a server to create its own Firebase access tokens (a user wouldn't necessarily have to authenticate for this; the signing of the tokens is completely up to you). This is advantageous because, if the anonymous user misbehaves, the access token can then be revoked (by storing a value in Firebase which is used by the security rules to enforce access).
UPDATE
Firebase now has anonymous authentication built into simple login, no need to use custom login for common use cases here.

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.

How to create basic authentication, login system for a web tool made in node.js and socket.io, without using express

I have a web tool developed, which uses node.js and socket.io. it's a one page website and uses node.js for getting data from social media website and display on the same page. I would like to add a site specific login system for the website but don't want to use 'Express' or 'Passport' as it adds lots of overload to the website while it is not needed.
I am newbie with node.js and would like to know if I need to have a login system made with node.js to maintain session of the logged in user?
Note: I need to maintain session to log user data such as login time, search query and may be heatmap.
Thanks in advance. If needed I can explain specific part of the question in detail.
Using something like Express or Passport (or at least some of connect's middleware) will definitely be easier in the long run (if your app grows), but if you want to go the 'manual' route, here are some starting points:
Cookie Parser: You won't want to send the auth details with every request as a parameter, so you'll want to put the session details in a cookie. You can set cookies manually using headers, or with a node module that wraps the API neatly.
Session Storage: You can put all the "login time, queries and heatmap data" in cookies, but it would be neater to just send a session id in the cookie in each request and save the other data server-side in a database. Options are mongoose, redis, etc.
Since reading the source is very educational, go read connect's cookieParser and cookieSession. It's not a lot of code and the API docs include the actual source, so it's very easy to learn from. Enjoy! :)
From how you are phrasing this question, I believe the overhead from using Express modules (Passport or similar) is the least of your worries ;-)
First you need to figure out which mechanisms you want to use.
For authentication, will you use a username/password combo, or will you be using a third party service like Google, Facebook, Twitter etc ("OAuth" like)? Unless you use some third party service, you also need to handle registration (and possibly verification of email address etc). Even for username/password combos, will you roll your own or use the browser based "basic-auth" mechanisms?
After authenticating you need a session mechanism to store some session token to recognize (and verify server side) that you have been authenticated. They are typically stored in browser cookies, which can easily be persisted for as long as you need, and are verified with each relevant request with tokens in a database on the server side.
And finally, you need a logout mechanism and a "I forgot my password" procedure (which may very well be manual initially...).
If all this is fairly new to you, I suggest trying to use something ready-made first (you mention Passport yourself), and then when you've mastered the basics, feel free to replace it with your own. The "upside" of using Passport or Everyauth is that they cover a lot more options that you realistically will be able to write yourself, so once you've adapted your system to use one of those, adding Facebook logins and similar will be a lot easier (somebody already figured out most of the stuff for your).
To be honest, most of the modules that handle such things in the Node ecosystem are fairly thin wrappers on top of whatever solution you decide to use, so the overhead will most likely not be substantial and you will most likely need a good understanding of the issues anyway to use them. At the other end of the spectrum are ready-made-systems like Drupal etc where everything just works, but then you're somewhat boxed in as far as making your own system.
There are use-cases where rolling your own from scratch is absolutely necessary, but there's nothing stopping your from doing this later when/if necessary (and after you've mastered the basics with the help of code that others wrote).
Best of luck!

dojo web application authentication

I am attempting to develop a pure javascript web application using Dojo. The problem I face is one of restricting access to portions of the application. Authenticated users should be able to access everything, whereas non authenticated users should only be able to access a login screen.
The issue is that nothing (that I am aware of) will stop a user from opening up a browser javascript terminal and entering something like: app.displayRestrictedContent(); and thus gaining access to a screen intended for authenticated users.
I have implemented an ajax based login; all ajax calls are secured with a session. So while the non-authenticated user can load a restricted screen, they wont be able to fetch data for it. But still, It seems wrong for this screen to be arbitrarily accessible.
Am I trying to do the impossible? It seems silly to write code such as if (user.auth) app.displayRestrictedContent(); when it's so easily circumvented. And this leads me to believe I am missing something rather obvious to everybody else. I can't find much information at all on pure javascript based apps and authentication models.
But still, It seems wrong for this screen to be arbitrarily accessible.
Because it's client-side code. Anything you write in js, or get compiled to js, expect it to be readable by the users.
Am I trying to do the impossible?
you can dynamically load js modules after the user authenticates. So at first, just load 1 login module. When the user logins, if successful, the server return a list of js modules to load, if not, return empty list. It also helps improve load time when the users come to your website.
I'm by no means an expert, but here are some thoughts I've made on this. I don't think you've missed anything (if so, I have too) - I think this is a pretty fundamental issue with all client applications, whether it's a compiled executable or a Javascript.
Of course, the compiled executable is not particularly hampered by it, because it's been made into machine code which is very difficult to read or decompile into anything useful. With Javascript however, the application is often served exactly as you wrote it, and so it's easy to modify and reason about.
That brings me to the first semi-solution: obfuscating your Javascript. If you use Dojo's build tool with the shrinksafe parameter, all unnecessary whitespace is removed and all identifiers are shortened, making the code quite difficult to read. I called this a semi-solution, some may say even that is giving it too much credit - I myself still think it's worth doing. After all, the shrunk code downloads faster too!
The second measure I take in my apps is to separate the different parts into "build layers". For example, in my build profile, I'll have something like
dependencies = {
..
layers: [
{ name: "../myApp/Core.js", resourceName: "myApp.Core",
dependencies: ["myApp.Core", "myApp.Foobar"]
},
{ name: "../myApp/modules/Login.js", resourceName: "myApp.modules.Login",
dependencies: ["myApp.modules.Login", "myApp.modules.LoginUi"...],
layerDependencies: ["../myApp/Core.js"]
},
{ name: "../myApp/modules/Secret.js", resourceName: "myApp.modules.Secret",
dependencies: ["myApp.modules.Secret", "myApp.modules.SecretUi"],
layerDependencies: ["../myApp/Core.js"],
authentication: 42
}
]
}
Now, instead of serving the built JS files directly as static files, I let the requests go through a controller in my server-side application, which checks if the JS layer requires authentication and whether or not the user is logged in with the necessary access.
This does have certain cons. The JS files aren't cached, and if I had all my JS in one build layer, the application would probably load slightly faster. There's of course also a limit to how nuanced it's worthwhile to make the layers. More layers mean more hassle, but also more finely grained module access.
I'd be interested to hear others chime in on this as well. It's a good question.
When a user successfully logins the server should provide him with a session token. The Afterwards, whenever the user requests a resource (either via just redirecting the browser or via AJAX) he shows the server his session token (either by storing it in a cookie and sending it automatically on all requests or by explicitely passing it in the body of an AJAX request)
The server can then use session tokens from the users to control authorizations server-side, rejecting any request with an invalid or outdated token.
https://en.wikipedia.org/wiki/HTTP_cookie#Session_management

Categories