ExpressJS restricting access to public files - javascript

Is there a way to hide files that are being served by the Node server? I have tried to reroute certain files and directories, but nothing is working in Express 4.X. I have also tried to send 4XX HTTP responses when certain files are requested, but this only works for directory paths. No matter what I do, if there is a file that is being served by Node, then the user is going to be able to see the source code. Is this just how Express works? Is it meant to be a development framework over a production framework?
Right now I am trying to send bad responses.
full server.js
var path = require('path'),
express = require('express'),
var app = express();
app.use('/', express.static(__dirname));
app.use('/', express.static('dist'));
// not working
app.get('/client/config/app.js', function(req, res) {
res.sendStatus(400);
});
app.listen(3001, function() {
console.log('listening');
});
I am able to send a response if I specify a directory path, but not if I specify a full file path. This works:
app.get('/client/config/', function(req, res) {
res.sendStatus(400);
});
And this doesn't:
app.get('/client/config/app.js', function(req, res) {
res.sendStatus(400);
});
I've also tried routing with app.use. That didn't work either.
The best thing I can do right now to "hide" the source code is to uglify it with Gulp, but I imagine it's easy to unravel it with a JS prettifier.

one line culprit
app.use('/', express.static(__dirname));
That line is saying its ok to pull anything. You could replace it with:
app.use('/', express.static(__dirname + '/public'));
Then put stuff in the public directory you want viewed. For routes you want to have as priority, place them before the other declarations. So you would place:
app.get('/client/config/app.js', function(req, res) {
res.sendStatus(400);
});
above all else. However, seems like you may not need it if you just fix the first problem, then you are good. Also, see HTTP status codes. You would probably want 404 or 403 for that type of file.
http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html

Related

Socket.io - Don't allow client to view files with the main.js file

I am currently working on a project which uses socket.io with NodeJS to control something else. This is my code so far:
var express = require('express');
var app = express();
var http = require('http').Server(app);
var io = require('socket.io')(http);
var fs = require('fs');
var contents = fs.readFileSync("data.json");
var remoteLayout = JSON.parse(contents);
app.get('/', function(req, res) {
res.sendFile(__dirname + '/index.html');
});
app.get('/edit', function(req, res) {
res.sendFile(__dirname + '/edit.html');
});
app.use(express.static(__dirname));
io.on('connection', function(socket) {
console.log('a user connected');
socket.on('disconnect', function() {
console.log('user disconnected');
});
});
http.listen(8080, function() {
console.log('listening on *:8080');
});
It is my code shortened to the parts which are relevant.
So my question is, when I run this code in node, and I open the page [myIPAddress]:8080 it opens up index.html like it should and at the top of Chrome, it says [myIPAddress]:8080. Now if I to the bar which shows the page's URL at the top, and change that to [myIPAddress]:8080/handler.js it opens a page with my js script printed out on it. How do I make it so that the person cannot go to that [myIPAddress]:8080/handler.js page?
I'm not sure if it matters, but the folder with the main.js file has also index.html, edit.html, and handler.js.
The problem is this:
app.use(express.static(__dirname));
When you do that, you've exposed all files in the __dirname directory for anyone to see including your server files that are located in that directory. Instead, you should move your static files that you intend for the public to have access to to some other directory and then use:
app.use(express.static(someOtherPath));
This will keep your server files in __dirname private and expose only the files you intend to be public that you have located in someOtherPath.
If handler.js is actually intended for use in your web pages and thus must be made available to the browser, then you cannot prevent anyone from looking at it. If your webpage needs to use it, then the browser must be able to download it and if the browser must be able to download it, then you cannot prevent a person from seeing it. You can do all sorts of things like obscure it to make it less intelligible to a person, but to any determined hacker, the logic will still all be there and you can't hide any Javascript intended to run in a browser.
Logic that you want to protect MUST be only on your server, perhaps usable via Ajax calls. You can't keep code secret that must run in a browser.

Node is not finding js files included in html

I'm trying to build a simple chat app using node and socket.io. I am following the tutorial listed here: http://socket.io/get-started/chat/
My issues is that the tutorial has some javascript that is placed in a script tag directly in the html. I would like to move this code into it's own js file.
I made a file called chat.js, that is in the same directory as my index.html and index.js. In my html I put the following code in the header (I also tried right before the ending body tag too)
<script type="text/javascript" src="chat.js"></script>
However, when I run node index.js in terminal and go to localhost, I get a 400 for chat.js. I've tried placing "/chat.js" as well as "./chat.js" with no luck. All three files are in the same directory.
Any clues to what I am doing wrong will be appreciated.
My index.js
var app = require('express')();
var http = require('http').Server(app);
var io = require('socket.io')(http);
app.get('/', function(req, res){
res.sendFile(__dirname + '/index.html');
});
io.on('connection', function(socket){
socket.on('chat message', function(msg){
io.emit('chat message', msg);
});
});
http.listen(3000, function(){
console.log('listening on *:3000');
});
node.js does not automatically serve any files like other web servers do. If you want it to send chat.js when the browser requests it, you will have to create a route for it in your node.js code so that the web server will send it.
If you use something like the Express framework, this can be done in perhaps one line of code with app.use(express.static(...)).
Notice how in the demo you linked to, there's a specific route for the / path. You need a similar route for /chat.js or you could use app.use(express.static(...)) to configure the automatic serving of a whole directory of files.
In the future, if you show your actual server code, then we could help more specifically with actual code that fits into your server.
Now that you've shown your code, you could add a specific route for /chat.js:
app.get('/chat.js', function(req, res){
res.sendFile(__dirname + '/chat.js');
});
Or, if you move chat.js to be in a public sub-directory under your app code, then you could serve all files in that directory automatically with this:
app.use(express.static('public'));
When Express gets a request for a route that doesn't have a specific handler, it will check the public sub-directory to see if a file matches the request name. If so, it will automatically serve that file.

Express.js route for html imports

I'm a PHP developer attempting node.js using express.js libraries for the first time. I've gotten a simple node.js static server running using express.staticand am now trying to move on to routing.
I have this routing rule:
app.get('/', function (req, res){
res.sendFile('index.html', {root: path.join(__dirname, '/finished')});
});
which returns index.html (url:localhost:port) fine, my problems are when I attempt to import from other directories in index.html's folder. I always get a 404 error.
Do I have to write rules for every file requested? Is there anyway to make a folder, or group of folders public?
Example (this works):
app.get('/components/webcomponentsjs/webcomponents.js', function (req, res){
res.sendFile('./components/webcomponentsjs/webcomponents.js');
});
There must be a way better way to do this. Any assistance and documentation appreciated, can't seem to connect the dots.
EDIT
express.static usage:
app.use(express.static(__dirname + '/root'));

How to do I get at my frontend on Heroku? The backend is up & running

I finally got my node/express & mongodb running on Heroku...but how do I get at my frontend?
I am most familiar with a localHost setup, where I simply open my index.html, running localHost servers with MAMP..
When I load myapp.herokuapp.com, I see a JSON of my MongoDB docs (currently empty)
{
"docs": []
}
And when I go to myapp.heroku.com/index.html I get my 404 error..
Where.. 404
This all makes sense, according to my express code:
app.get('/', function (req, res) {
getAll(res);
});
app.get('*', function (req, res) {
res.send("Where.. 404", 404);
});
How do I get to my index.html frontend? Is there any more code that would be helpful to see..
what app.use() calls do you have?
In particular, if you want to serve static .html files you need to add something along these lines (assuming your static file are located in the ./public sub-dir):
app.use(express.static(__dirname + '/public'));
Further details: http://expressjs.com/api.html#app.use

Node.js / Expess.js. Static router not recognized if used with wildcard router

When I use only this route with my all other routes, that static files served well:
var public_dir = path.join(__dirname, 'public');
app.use('/public', express.static(public_dir));
But when I add below these lines - all requests are catch with this router (not the previous one):
app.get('/*', function(req, res){
res.redirect('/#!' + req.path);
});
It's strange to me, because /public definition comes first. But all request goes to last defined /* request handler.
Now, if I try to open page http://127.0.0.1:3000/public/website/application.js I become redirected to http://127.0.0.1:3000/#!/public/website/application.js. Why it happens, and how to solve this situation in the best manner?
Thank you a lot!
Solution is simple. I have not working statement in list of middlewares.
app.use(app.router);
This is creates a problem of url routing. But it's strange that node.js did not tell me about "incorrect setup" of middleware.
There is nothing wrong with your code but keep in mind that any request on something that doesn't exist will be catch by your get('/*', ...).
This said, you load public_dir on /public that's mean if public_dir is defined as public/website/ you have to do http://127.0.0.1:3000/public/application.js in order to access a file locate at /public/website/application.js

Categories