2

I have set up an application with a registration homepage and a few internal pages requiring a login. I used Node with Express.js to set up the server and controlling the routes and authentication works fine: if I try to access localhost:port/clientPage I get the desired page if I previously logged in and an error message otherwise.

The problem is that if I try to access localhost:port/clientPage.html I get the clientPage even when I have no active session. How can I ensure the same - desired - behaviour previously described also in this case? I attach the code of my GET route to clientPage:

router.get('/clientPage', function (req, res, next) {
  User.findById(req.session.userId)
    .exec(function (error, user) {
      if (error) {
        return next(error);
      } else {
        if (user === null) {
          var err = new Error('Not authorized! Go back!');
          err.status = 400;
          return next(err);
        } else {
          return res.sendFile(path.join(__dirname + '/../views/clientPage.html'));
        }
      }
    });
});
Alex
  • 203
  • 1
  • 2
  • 8
  • Try router.get('/clientPage*', in first line. Hope this helps. – Nutan Nov 27 '17 at 14:50
  • Unfortunately the behaviour doesn't change – Alex Nov 27 '17 at 14:57
  • What's the value of user when you have no active session? (Are you sure it is `null` and not `undefined` or something?) – Cody G Nov 27 '17 at 15:01
  • @CodyG.it is null – Alex Nov 27 '17 at 15:04
  • Okay, so your question is really about how to detect a timed-out session? Does req.session not include some sort of timestamp (client-side cookie)? What are you using to store your session? If it's server-side why don't you look up the session and then once again check if it's timed out? – Cody G Nov 27 '17 at 15:07
  • No, I already controlled authentication and it works fine, until I add a ".html" to the URL. This results in the requested page disregarding the session state. – Alex Nov 27 '17 at 15:09
  • You should get a `404` if you are just adding `.html`.. (unless you do some sort of other `Not found` handling) Can you verify that this route (the one you posted) is the one being fired and that no subsequent routes (any routes following it) are being fired? – Cody G Nov 27 '17 at 15:14
  • In my router.js file the only subsequent routes are adminPage and logout and I can assert that none of them is called. In app.js I have only a 404 catcher and then a generic error handler. – Alex Nov 27 '17 at 15:24
  • I tried also to add console logs in every route I have defined: when I access to URL (localhost:port/clientPage.html) none of them is called, but the page appears anyway. – Alex Nov 27 '17 at 15:29
  • Hmmm. Browser cache? Is the page actually served when you go to `.html`? (Now I'm questioning why it doesn't 404) – Cody G Nov 27 '17 at 15:30
  • It's not the cache because route should in any case control the behaviour on the requested URL. Anyway I tried it with a never used before browser and I had the same issue: cache is definitely not the answer to the problem. – Alex Nov 27 '17 at 15:32
  • Remove your /clientPage route and check that both /clientPage and /clientPage.html `404` --- Also, have you tried setting a debug breakpoint on that route and look at what it is returning such that the conditional statement for the user is not null when using `.html`? – Cody G Nov 27 '17 at 15:36
  • Also, what express/node version are you running? – Cody G Nov 27 '17 at 15:38
  • have you tried clearing cache to rule out that it was indeed not a cache? – Zanko Nov 27 '17 at 15:50
  • 1
    did you use any kind of `express.static(path.join(__dirname, "public")` possbily serving your `views`? – Zanko Nov 27 '17 at 15:53
  • Conferming my last comment, removing the /clientPage route results in a 404 if I access /clientPage, while still shows the entire page when accessing /clientPage.html. I'm using Express 4.16.2 and Node 8.8.1 – Alex Nov 27 '17 at 15:54
  • 1
    Ooo. Yes, I agree with Zanko at this point. – Cody G Nov 27 '17 at 15:58
  • 1
    @Zanko yes, in app.js {app.use(express.static(__dirname + '/views'));} I understand now that this was the problem - and it seems a very stupid one, but If you want to provide an answer I'll accept it - but why this overrided all the specified routes showing the html files? – Alex Nov 27 '17 at 16:01
  • Moreover, dropping that line I can't access neither the root anymore – Alex Nov 27 '17 at 16:03
  • @alex what were you using views publically for previously? Normally we do `app.use(express.static(__dirname + '/public'));` to serve static content like images, css. javascript file. – Zanko Nov 27 '17 at 16:07
  • So you suggest to put in /public all the javascript utilities, css, images AND index.html and in /views all the other .html which should not be directly accessible, right? – Alex Nov 27 '17 at 16:16
  • 2
    index.html could go in /views too – Cody G Nov 27 '17 at 16:19

1 Answers1

2

Since the problem is caused by adding .html to the end of the route that somehow bypassed the authentication route. I think it is highly possible that you have

express.static(path.join(__dirname, "views") at the beginning of your application publicly serving your folder.

Why is it overriding your route?

Express is running middleware sequentially through app.use(...). The statement app.use(express.static...) is placed before app.use(// your router) and the response was resolved to client early.

Using this knowledge you can easily restrict other route by placing an authentication middleware before your route instead of embedding your database call inside each specific route.

app.use(require("./middleware/auth"));
app.use("/homepage", require("./routes/homepage"));
app.use("/clientPage", require("./routes/clientPage"));
Zanko
  • 4,298
  • 4
  • 31
  • 54
  • It's a very good idea, I should try this kind of implementation. However, some points are not clear to me and for the sake of clarity I'll post a separate question. If you don't mind I'd be glad to read your answer there. – Alex Nov 27 '17 at 16:36
  • 1
    @Alex sure I am happy to clarify – Zanko Nov 27 '17 at 16:41
  • Thank you, here it is: https://stackoverflow.com/questions/47515991/how-to-setup-an-authentication-middleware-in-express-js – Alex Nov 27 '17 at 16:51