Skip to content

Commit 2e1eaf0

Browse files
committed
Keep Authorization header on subdomain redirects.
Closes #173
1 parent 2ad9e82 commit 2e1eaf0

2 files changed

Lines changed: 63 additions & 2 deletions

File tree

‎index.js‎

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -376,8 +376,8 @@ RedirectableRequest.prototype._processResponse = function (response) {
376376
var redirectUrlParts = url.parse(redirectUrl);
377377
Object.assign(this._options, redirectUrlParts);
378378

379-
// Drop the Authorization header if redirecting to another host
380-
if (redirectUrlParts.host !== currentHost) {
379+
// Drop the Authorization header if redirecting to another domain
380+
if (!(redirectUrlParts.host === currentHost || isSubdomainOf(redirectUrlParts.host, currentHost))) {
381381
removeMatchingHeaders(/^authorization$/i, this._options.headers);
382382
}
383383

@@ -538,6 +538,11 @@ function abortRequest(request) {
538538
request.abort();
539539
}
540540

541+
function isSubdomainOf(subdomain, domain) {
542+
const dot = subdomain.length - domain.length - 1;
543+
return dot > 0 && subdomain[dot] === "." && subdomain.endsWith(domain);
544+
}
545+
541546
// Exports
542547
module.exports = wrap({ http: http, https: https });
543548
module.exports.wrap = wrap;

‎test/test.js‎

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1344,6 +1344,62 @@ describe("follow-redirects", function () {
13441344
});
13451345
});
13461346

1347+
it("keeps the header when redirected to the same host via header", function () {
1348+
app.get("/a", redirectsTo(302, "http://localhost:3600/b"));
1349+
app.get("/b", function (req, res) {
1350+
res.end(JSON.stringify(req.headers));
1351+
});
1352+
1353+
var opts = url.parse("http://127.0.0.1:3600/a");
1354+
opts.headers = {
1355+
host: "localhost:3600",
1356+
authorization: "bearer my-token-1234",
1357+
};
1358+
1359+
return server.start(app)
1360+
.then(asPromise(function (resolve, reject) {
1361+
http.get(opts, resolve).on("error", reject);
1362+
}))
1363+
.then(asPromise(function (resolve, reject, res) {
1364+
res.pipe(concat({ encoding: "string" }, resolve)).on("error", reject);
1365+
}))
1366+
.then(function (str) {
1367+
var body = JSON.parse(str);
1368+
assert.equal(body.host, "localhost:3600");
1369+
assert.equal(body.authorization, "bearer my-token-1234");
1370+
});
1371+
});
1372+
1373+
it("keeps the header when redirected to a subdomain", function () {
1374+
app.get("/a", redirectsTo(302, "http://sub.localhost:3600/b"));
1375+
app.get("/b", function (req, res) {
1376+
res.end(JSON.stringify(req.headers));
1377+
});
1378+
1379+
var opts = url.parse("http://localhost:3600/a");
1380+
opts.headers = {
1381+
authorization: "bearer my-token-1234",
1382+
};
1383+
// Intercept the hostname, as no DNS entry is defined for it
1384+
opts.beforeRedirect = function (options) {
1385+
assert.equal(options.hostname, "sub.localhost");
1386+
options.hostname = "localhost";
1387+
};
1388+
1389+
return server.start(app)
1390+
.then(asPromise(function (resolve, reject) {
1391+
http.get(opts, resolve).on("error", reject);
1392+
}))
1393+
.then(asPromise(function (resolve, reject, res) {
1394+
res.pipe(concat({ encoding: "string" }, resolve)).on("error", reject);
1395+
}))
1396+
.then(function (str) {
1397+
var body = JSON.parse(str);
1398+
assert.equal(body.host, "localhost:3600");
1399+
assert.equal(body.authorization, "bearer my-token-1234");
1400+
});
1401+
});
1402+
13471403
it("drops the header when redirected to a different host (same hostname and different port)", function () {
13481404
app.get("/a", redirectsTo(302, "http://localhost:3600/b"));
13491405
app.get("/b", function (req, res) {

0 commit comments

Comments
 (0)