Node.js express-session what does the proxy option do? - node.js

app.use(session(
{
...
proxy: true,
resave: true,
saveUninitialized: true
}
));
I found a tutorial on express-session and they have an proxy: true option. Can I leave it on true? What does this do? Is it better to include it? I know what a proxy is however I don't really get why this is an option?

The fine manual states:
Trust the reverse proxy when setting secure cookies (via the "X-Forwarded-Proto" header).
This refers to situations where clients don't connect directly to your Node server, but through a reverse proxy. For instance, clients connect to an NGINX webserver, which forwards the requests to a Node server; NGINX, in this situation, is the reverse proxy.
In reverse proxy setups, it's also quite common that the client communicates with the reverse proxy over HTTPS, yet the proxy communicates with the Node server using plain HTTP.
This is an issue when you configure the session middleware to use so-called "secure cookies" (documented here). The session middleware won't allow these cookies being sent over plain HTTP but requires that they are sent over HTTPS. If your reverse proxy communicates with your Node server over HTTP, this would mean you won't be able to use secure cookies.
To solve this problem, the reverse proxy will set the X-Forwarded-Proto header to every request it forwards. It tells the Node server what the original protocol of the request was, regardless of the way the reverse proxy connects to the Node server.
With the proxy option of the session middleware, you're telling it to trust this header and allow secure cookies being sent over plain HTTP, provided that X-Forwarded-Proto is set to https.
If you are exposing your Node server directly (so clients connect to it), you should set this option to false, because otherwise, a client can fool your server (by sending a X-Forwarded-Proto header itself) into thinking that the connection was secure. However, if you're not using secure cookies anyway, it won't really matter.

If your app does not receive requests forwarded through a proxy, you do not need to worry about this option. Proxies are often used to route requests to one of several apps.
A proxy looks like this:
[Client] ==request==> [Proxy] ==forwarded request==> [Server]
Here, the server can't see the original request and relies of the proxy to truthfully relate each request.
From the express-session docs:
proxy
Trust the reverse proxy when setting secure cookies (via the "X-Forwarded-Proto" header).
The default value is undefined.
true The "X-Forwarded-Proto" header will be used.
false All headers are ignored and the connection is considered secure only if there is a direct TLS/SSL connection.
undefined Uses the "trust proxy" setting from express
Looking at the Stack overflow question What does "trust proxy" actually do in express.js, and do I need to use it? (which references "Express behind proxies"), we see that "trust proxy" means whether the app trusts its proxy to accurately report the source of a request. This impacts secure HTTPS-only cookies: it is necessary to trust the proxy that a request genuinely came from an HTTPS source.
[Client] ==HTTPS==> [Proxy] =="I'm forwarding an HTTPS request"==> [Server]
The server can't see the client. If the proxy is lying, and it's not really an HTTPS request from the client, the server shouldn't send secure cookies. Therefore, we can indicate whether we trust the server to truthfully report the HTTP/HTTPS status of forwarded requests.

Related

NodeJS/Express automatic detection of SSL over HTTP (HTTPS) explanation?

I have a server over HTTPS on NodeJS with Express.
When uploading a file, I have used the req.protocol directive in the controller to get either the HTTP or HTTPS "part" of the URL, so that I can save the file with the absolute URL. The problem is that without enabling the "trust proxy" setting of express (http://expressjs.com/en/api.html#trust.proxy.options.table), HTTPS doesn't get detected.
I thought this setting was used in the case of the actual redirect (when using the HTTP URL and the server doing the 301 redirect to HTTPS).
So this is more of an explanation question, rather than a solution one:
Why doesn't the HTTPS get detected when calling the URL through that?
trust proxy has nothing to do with 301 redirects.
That settings is important when running your node server behind a proxy:
+----------HTTPS--------+---HTTP---+
| | |
client --> internet --> proxy --> node.js
It is typical that you have some sort of proxy between the internet and your node server; for example a CDN server, a load balancer, or simply an nginx instance or such. The HTTPS connection is established between the client and that proxy. The proxy cares about the necessary wrangling of the SSL certificate and encrypting the connection and doesn't burden your application server (node) with those details. It is then forwarding only the relevant details of the request via plain HTTP to your node server. Your server only sees the proxy as the origin of the request, not the client.
Since the node server didn't itself handle the HTTPS connection, how could it know whether the connection between the client and the proxy was HTTPS? It can't. The proxy needs to voluntarily forward that information too. It does so in the X-Forwarded-* HTTP headers. The information whether it was specifically HTTP or HTTPS is sent in the X-Forwarded-Proto header.
The thing is, those are just HTTP headers. Anyone can set those headers. The client itself could set those headers. That's why you need to explicitly opt into using those headers with the trust proxy setting, iif and when you know your app will be running behind a proxy which sets those headers. When you're not running behind a proxy but your node server is directly exposed to the internet, you must switch that setting off; otherwise anyone could set those headers, your server would obey those headers and be lead to use false information.

Submitting HTTPs from node socket with no certificate

A web application i developed is sitting on a server that serves it under https, some of my js code requires to open a socket to another server (nodejs) who is currently not set for https. and thus browser wont allow it to run.
all i want is a simple way without getting involved with certificates just to initiate a https socket connection, i don't mind the lack of security,
just need app to run.
The certificates are not your problem. Your problem is CORS. You need to configure your server to answer with a header allows foreign-origin
res.header('Access-Control-Allow-Origin', 'example.com');
because in your case the technical difference between http (port 80) and https (443) is the port.
EDIT: ... I mean from the browsers point of view

Is possible to run http and https server with same port no in node.js using express?

I have two server HTTP and HTTPS with key.Once I authenticated then I need to change Http to HTTPS at the same port..
var httpsoptions={
key:fs.readFileSync('./keys/twc-key.pem'),
cert:fs.readFileSync('./keys/twc-cert.pem')
};
var webServer = express();
var websecure = express(httpoptions);
Here I need to maintain same port for both Http and Https how is possible?
Use Nginx as a reverse proxy
You can enable HTTPs on nginx, and proxy your node application through nginx.
Use the express-vhost middleware
Use express-vhost and host https on a subdomain
eg. https://secure.url.com
or https://login.url.com
Use port 443
Easier yet!
443 is accepted as a default port for https by basically all browsers. Some call it deprecated, but I've seen nothing supporting this claim.
443 is still accepted as the default port for https.
Host everything over https
Many sites do this already
Prevents session hijacking
Prevents token hijacking
Prevents MITM attacks
Even if you just have the log in secure, afterward your cookies are in plain text in your http header. An attacker could steal the session cookie and hijack the users session.

node http proxy SSL transparent

In my setup, I have 2 layers of transparent proxies. When a client makes an SSL request, I wish to have the first proxy it meets simply forward the traffic to another one without attempting to do the handshake with the client.
The setup seems funny, but it is justified in my case - the 2nd proxy registers itself to the first one (through some other service) only occassionally. It tells the first: "I'm interested in some traffic that looks like___". In most cases, the 1st proxy simply does the work.
Can an httpProxy (in node-proxy) proxy SSL requests? Must I use an httpsProxy (which will then do the handshake with the client)?
You could do all of this with the existing httpsProxy if you wanted to. Unless you are wanting to use a non-Node proxy or proxy to a different server, I can't see what you would gain by having two.
Simply add the required the logging/signing logic to the existing httpsProxy.
Typically, I use https on the proxy to both restrict the number of open ports and to remove the need to do https on all of the Node servers running. You can also add Basic Auth using http-basic library too.
See my example code: https://github.com/TotallyInformation/node-proxy-https-example/blob/master/proxy.js
EDIT 2012-05-15: Hmm, after some thought, I wonder if you shouldn't be looking at something like stunnel to do what you want rather than Node?
(For reference, I've already made some of those points in my answer to your similar question on ServerFault.)
If you are after a MITM proxy (that is, a proxy that can look inside the SSL content by using its own certificates, which can work provided the clients are configured to trust them), it will hardly be fully transparent, since you will at least have to configure its clients to trust its certificates.
In addition, unless all your client use the server name indication extension, the proxy itself will be unable to determine reliably which host to issue its certificate for (something that a normal HTTPS proxy would have been able to know by looking at the CONNECT request issued by the client).
If you're not after a MITM proxy, then you might as well let the initial connection through via your router. If you want to record that traffic, your router might be able to log the encrypted packets.
Having your router catch the SSL/TLS packets to send them transparently to a proxy that will merely end up relaying that traffic untouched anyway to the target server doesn't make much sense. (By nature, the transparent proxy will imply the client isn't configured to know about it, so it won't even send its CONNECT method with which you could have had the requested host and port. Here, you'll really have nothing more than what the router can do.)
EDIT: Once again, you simply won't be able to use an HTTP proxy to analyse the content of the connection transparently. Even when using a normal proxy, an HTTPS connection is relayed straight through to the target server. The SSL/TLS connection itself is established between the original client and the target server. The point of using SSL/TLS is to protect this connection, and to make the client notice if something is trying to look inside the connection.
Plain HTTP transparent proxy servers work because (a) the traffic can be seen (in particular, the request line and the HTTP Host header are visible so that the proxy can know which request to make itself) and (b) the traffic can be altered transparently so that the initial client doesn't notice that the request wasn't direct and works as if it was.
Neither of these conditions are true with HTTPS. HTTPS connections that go through an HTTP proxy are simply tunnel, after explicit request from the client, which has sent a CONNECT command and was configured to make use of such a proxy.
To do something close to what you're after, you'd need an SSL/TLS server that accepts the SSL/TLS connection and deciphers it (perhaps something like STunnel) before your HTTP proxy. However, this won't be transparent, because it won't be able to generate the right certificates.

How to enable windows authentication through a reverse proxy?

Sorry if it is a duplicate, as I am not a security nor network expert I may have missed the correct lingo to find information.
I am working on an application to intercept and modify HTTP requests and responses between a web browser and a web server (see how to intercept and modify HTTP responses on server side? for the background). I decided to implement a reverse proxy in ASP.Net which forwards client requests to the back-end HTTP server, translates links and headers from the response to the properly "proxified" URL, and sends the response to the client after having extracted relevant information from the response.
It is working as expected, except for the authentication part: the web server uses NTLM authentication by default, and just forwarding requests and responses through the reverse proxy does not allow the user to be authenticated on the remote application. Both the reverse proxy and the web application are on the same physical machine and are executed in the same IIS server (Windows server 2008/IIS 7 if that matters). I tried both enabling and disabling authentication on the reverse proxy app with no luck.
I have looked for information about it, and it seems to be related to the "double-hop problem", which I do not understand. My question is: is there a way to authenticate the user on the remote application through the reverse proxy using NTLM? If there is none, are there alternative authentication methods I could use?
Even if you don't have a solution to my problem, just pointing me to relevant information about it to help me get out of the confusion would be great!
I found what the problem was (and it is NTLM): in order to have the browser asks the user for its credentials, the response must have a 401 status code. My reverse proxy was forwarding the response to the browser, so IIS was adding a standard HTML code to explain the requested page cannot be accessed thus preventing the browser from asking credentials.
The problem was solved by removing the response content when the status code is a 401.
With all due respect I have for the one that answered that some years ago, I must admit this is plainly false. The problem was indeed solved AFTER removing the response content when the status code is a 401, but it had none to do with the initial problem..
The truth is that windows authentication was made to authenticate people over local windows networks, where no proxy server is present or even needed.
The main problem with NTLM authentication is that this protocol does not authenticate the HTTP session but the underlying TCP connection, and as far as I know there is no way to access it from asp code.
Every proxy server I tried broke NTLM authentication.
Windows authentication is comfortable for an user because he won't ever need to enter your password to whatever application may lie in your intranet, frightening for a security guy because there is an auto-login without even a prompt if the site domain is trusted by IE, shocking for a network administrator because it melts the application, transport and network layer into some "windows ball of mug" instead of just plain http traffic.
NTLM won't work if the TCP packets are not forwarded exactly as the reverse proxy received > them. And that's why many reverse proxy doesn't work with NTLM authentication. (like nginx) > They forward HTTP requests correcty but not the TCP packets.
Nginx has the functionality to work with NTLM authentication. Keepalive needs to be enabled which is only available trough the http_upstream_module. Additionally in the location block you need to specify that you will be using HTTP/1.1 and that the "Connection" header field should be cleared for each proxied request. Nginx config should look something like:
upstream http_backend {
server 1.1.1.1:80;
keepalive 16;
}
server {
...
location / {
proxy_pass http://http_backend/;
proxy_http_version 1.1;
proxy_set_header Connection "";
...
}
}
I scratched my head for quite some time with this issue but the above works for me. Note that if you need to proxy HTTPS traffic, a separate upstream block is deemed necessary. To clarify a bit more, "keepalive 16;" specifies the number of simultaneous connections to the upstream your proxy is allowed to keep. Adjust the number as per the expected number of simultaneous visitors on the site.
Although this is an old post, I just want to report that it works for me quite well with an Apache2.2 reverse proxy and the keepalive=on option. Obviously, this keeps the connection between the proxy and the SharePoint host open and "pinned" to the client<>proxy connection. I don't exactly know the mechanisms behind this, but it works fairly well.
But: Sometimes, my users encounter the issue that they're logged in as another user. So there seems to be some mixing-up through sessions. I will have to give this some further testing.
Solution for everything (in case you have a valid, signed SSL certificate): Switch IIS to Basic Auth. This works absolutely fine, and even Windows (i.e. Office with SharePoint connection, all WebClient-based processes etc.) won't complain at all.
But they will when you're just using http without SSL/TLS, and also with self-signed certificates.
I confirm that it works with "keep-alive=on" on apache2.2
I examined frames with Wireshark, and I know why it doesn't work. NTLM won't work if the TCP packets are not forwarded exactly as the reverse proxy received them. That's why many reverse proxies, like nginx, don't work with NTLM authentication. Reverse proxies forward HTTP requests correctly but not the TCP packets.
NTLM requires a TCP reverse proxy.

Resources