SSL for *some* routes

324 views
Skip to first unread message

Alex Brown

unread,
Jul 10, 2014, 12:22:30 PM7/10/14
to expre...@googlegroups.com
Is it possible to configure (and force) SSL on only some routes?

For example routes such as:

/
/search
/about
etc.. can all be https

/account* should be SSL

Is that possible?

Ryan Schmidt

unread,
Jul 11, 2014, 6:23:37 AM7/11/14
to expre...@googlegroups.com
Yes, that is possible. You could write code to do that. However, I do not recommend it. Serve all content over SSL all the time. You can find information on Google supporting that position and sites like github and gmail are already following it.



Alex Brown

unread,
Jul 11, 2014, 6:26:18 AM7/11/14
to expre...@googlegroups.com
That's not really a good answer... SSL prevents caching, not only from browsers but also from proxy servers
It's a publicly accessible site-

Example:
ebay - not ssl (until you login)
yell.com - not ssl (until you login)

etc...






--
You received this message because you are subscribed to a topic in the Google Groups "Express" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/express-js/oujexQBKPr4/unsubscribe.
To unsubscribe from this group and all its topics, send an email to express-js+...@googlegroups.com.
To post to this group, send email to expre...@googlegroups.com.
Visit this group at http://groups.google.com/group/express-js.
For more options, visit https://groups.google.com/d/optout.

Ryan Schmidt

unread,
Jul 11, 2014, 6:55:26 AM7/11/14
to expre...@googlegroups.com
On Jul 11, 2014, at 5:25 AM, Alex Brown wrote:

> On 11 July 2014 11:23, Ryan Schmidt wrote:
>
>> On Jul 10, 2014, at 11:22 AM, Alex Brown wrote:
>>
>> > Is it possible to configure (and force) SSL on only some routes?
>> >
>> > For example routes such as:
>> >
>> > /
>> > /search
>> > /about
>> > etc.. can all be https
>> >
>> > /account* should be SSL
>> >
>> > Is that possible?
>>
>> Yes, that is possible. You could write code to do that. However, I do not recommend it. Serve all content over SSL all the time. You can find information on Google supporting that position and sites like github and gmail are already following it.
>
> That's not really a good answer... SSL prevents caching, not only from browsers but also from proxy servers
> It's a publicly accessible site-
>
> Example:
> ebay - not ssl (until you login)
> yell.com - not ssl (until you login)
>
> etc...


In my opinion, my answer is a good answer.

Many various opinions on the matter are given in various places on the Internet, such as

https://stackoverflow.com/questions/2177159/should-all-sites-use-ssl-by-default

In any case, yes, you can write your javascript code to perform any behavior you wish, including permitting and/or enforcing ssl only for certain routes. But if you offer a login function, and then allow logged-in users to view your site via http, you are allowing those users to have their accounts hijacked; see e.g. firesheep. Requiring ssl everywhere prevents that.

Alex Brown

unread,
Jul 11, 2014, 7:01:38 AM7/11/14
to express-js
"SSL prevents caching"

"Overall, putting SSL everywhere looks like a way to get a "warm fuzzy feeling" on security. This is not good. This usually means that by concentrating on the irrelevant, administrators will be more likely to disregard actual security issues. They will also make the system more complex to maintain, making it more difficult to diagnose and correct problems"

Rather than get into a debate about that, do you have an answer for the original problem?



Justin Russell

unread,
Jul 11, 2014, 8:27:23 AM7/11/14
to expre...@googlegroups.com
It is possible.

See the docs for app.listen(), it gives an explicit example of what you should do if you want to use both http and https. Forcing https for some routes only will be up to you - you could, for example create a middleware that checks the incoming request protocol and redirects to https if needed.

However, I'd recommend not worrying about http/https in your express app itself but enforce that in a reverse proxy (if that's an option).


----------------------------------------------------------------


--
You received this message because you are subscribed to the Google Groups "Express" group.
To unsubscribe from this group and stop receiving emails from it, send an email to express-js+...@googlegroups.com.

Matthew Page

unread,
Jul 11, 2014, 10:45:28 AM7/11/14
to expre...@googlegroups.com
You can solve this problem many ways.

I agree with Justin, that the easiest way is to just use a reverse proxy and direct requests appropriately.

To what Justin said about middleware, have a look at: http://stackoverflow.com/questions/10348906/how-to-know-if-a-request-is-http-or-https-in-node-js

Also, don't forget that you can create multiple servers listening on different ports within a single app.
So if you have middleware that checks for encryption on some routes, your ssl server can direct requests to those routes appropriately.

Say, something like:

app.get('/admin', requireEncryption, adminRouter.index); 

darren

unread,
Jul 11, 2014, 9:13:37 PM7/11/14
to expre...@googlegroups.com
Hey Alex. Already some good comments here but it's generally not a problem to serve some routes over HTTP and others over HTTPS per se.  However mixing http/https on the same page is the so-called "mixed content" vulnerability and most browsers will complain about it.  If you just want to serve your About and Search sections over HTTP, but other things over HTTPS, that should be fine.  HTTPS and HTTP run on different ports (typically 443 and 80, respectively) so in any case, you need to have express server listening for HTTP, and another serving HTTPS.  I wouldn't recommend trying instantiate both servers in the same app. Instead, you can divide your routes into separate files under the routes/ directory. The app that serves HTTP can include only the About and Search route modules, and the app that serves HTTPS can include those, plus the Account routes (so they're all available over HTTPS). 

You'll probably want to include a redirect in the HTTP server when a user tries to access one of the secure routes.  If for whatever reason you want to serve both HTTP and HTTPS from the same process, it's possible to create two express apps in the same module (ie. app.js file) but I wouldn't recommend it for performance and reliability reasons (ie. it would be nice to continue serving HTTP if you take HTTPS offline for whatever reason).

As others mentioned, using something like nginx in a production deployment is pretty common and has advantages. It's worth looking into, but not the first solution I'd suggest for starting development.

For a good example of route separation, see https://github.com/visionmedia/express/tree/master/examples/route-separation  Another pattern, which doesn't seem to be in the examples for some reason, is to structure your route modules to accept the express server instance as an argument, to which they can append routes:

// module exports function that accepts an 'app' parameter
module.exports = function (app) {
// routes are attached to the app as usual
app.get("/dashboard", function (req, res) {
if (req.session.user) {
res.render('dashboard.ejs', {'title':'Dashboard'});
} else {
res.redirect('/login');
}
});
};

The app that uses the routes passes itself to the route module to have those routes added to it:

// main app.js example
// require route modules and pass in the app
var app = express();
require('./routes/dashboard.js')(app);
require('./routes/portal.js')(app);

This has been a really handy way to modularize routes; you might find it useful for organizing your routes for inclusion in separate http and https express servers, too.

Serving everything over HTTPS is not a bad recommendation. For me, it's been easier than worrying about two servers. However, in this case you probably want to include a redirect from HTTP to HTTPS. This is easy to do in your main app by simply instantiating another express server, making it listen on the HTTP port, and responding to everything with a redirect to the HTTPS port.  You can even get fancy and grab the request path, and append it to the redirect path so that URLs will forward from http to https and keep their full path.

var redirector = express();
redirector.all("*", function (req, res) {
  res.redirect("https://" + req.host + ":3000" + req.path);
});


Last thing, express apps are often run as a non-privileged user with HTTP on port 8080 and HTTPS on port 3000 (running as root on port 80 and/or 443 is not recommended for security reasons).  To transparently proxy clients from the default HTTP and HTTPS ports to these non-privileged ports, once again you can use nginx, or simply set up forwarding rules using iptables (in linux). See http://proghowto.com/iptables-redirect-port-80-to-port-8080 for an example.

hope this helps,
Darren

Alex Brown

unread,
Aug 6, 2014, 9:23:36 AM8/6/14
to express-js
After much thought, I think you're right - SSL all over is probably the way to go
Thanks


--
Reply all
Reply to author
Forward
0 new messages