Open davepacheco opened 7 years ago
The bunyan issue is node-bunyan#504.
The fix I suggested above doesn't make any sense. We don't control the Host header sent on the subsequent request -- the user in this case could have given this signed URL to curl or some other user agent that may or may not decide to provide the port number in the Host header.
One option may be to fix this on the server by saying if the signature fails to match, and the Host header has the default port, then we try the signature again assume that the default port had been passed in the Host header.
Here's a working example of using
msign
to create a signature for a HEAD request:Now if I tack on port 443 explicitly, it doesn't work:
With a GET, we can see the actual error message:
This problem applies to all signed URLs, whether created with
msign
or the client's JavaScript interface.I believe what's going on here is that the signature includes the "Host" header, and when we create the signature, we assume the "host" header will contain the port, but when Node goes to actually construct the Host header, it sees that the port is the default one and leaves it out. As a result, we sign a different Host header than we send, and the signature doesn't match.
The header we sign
To construct the signed url, msign invokes client.signURL. That function assembles a host and passes that to node-smartdc-auth's
signUrl
, which uses whatever it's given as the host header for the signature. So the header we ultimately sign is the one assembled inclient.signURL
, which is:Now,
self._url
generally comes from MANTA_URL. We can easily evaluate this and see that we get a different result depending on whether the port is explicitly specified in the URL, even though the URLs are semantically equivalent:The header we send
This took me a long time to root out because of a bunyan CLI issue (to be filed shortly). By modifying the code in restify-clients, I worked out that by the time we call Node's
http.request()
to make the request, we have not set a Host header. Node's default behavior is to add a Host header if it doesn't exist, based on the host to which you're sending the request. And it includes the port number if and only if it's not the default one:I confirmed that requests sent using the default port have a "Host" header with no port included, but requests sent with a different port have the port number in the "Host" header. (I confirmed this by using
nc -l
to set up a little server and running "mls" against it with different "http" URLs.)Fix?
Edit: this is wrong -- see comment below.
It seems we could either:
If we do (1), we're still subject to implicit behavior: Node could change its behavior here and that would break us again. If we do (2), then we're changing the over-the-wire behavior of the client. I don't know if this matters, but it's normally unusual to have a port in the Host header, and we'd now be sending that for every request.
We could do both (1) and (2): leave the port out of the header if it's the default port and pass the resulting host header down to the restify client.