Skip to content

Commit 2bc301d

Browse files
Lew Gordontargos
authored andcommitted
http: decodes url.username and url.password for authorization header
This change properly decodes the url.username and url.password for the authorization header constructed from the URL object for http(s) requests. Fixes: #31439 PR-URL: #39310 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Robert Nagy <ronagy@icloud.com> Reviewed-By: James M Snell <jasnell@gmail.com>
1 parent a437de3 commit 2bc301d

File tree

4 files changed

+57
-1
lines changed

4 files changed

+57
-1
lines changed

doc/api/http.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2767,6 +2767,10 @@ This can be overridden for servers and client requests by passing the
27672767
<!-- YAML
27682768
added: v0.3.6
27692769
changes:
2770+
- version: REPLACEME
2771+
pr-url: https://github.com/nodejs/node/pull/39310
2772+
description: When using a `URL` object parsed username and
2773+
password will now be properly URI decoded.
27702774
- version: v14.17.0
27712775
pr-url: https://github.com/nodejs/node/pull/36048
27722776
description: It is possible to abort a request with an AbortSignal.

doc/api/https.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,10 @@ Global instance of [`https.Agent`][] for all HTTPS client requests.
251251
<!-- YAML
252252
added: v0.3.6
253253
changes:
254+
- version: REPLACEME
255+
pr-url: https://github.com/nodejs/node/pull/39310
256+
description: When using a `URL` object parsed username
257+
and password will now be properly URI decoded.
254258
- version: v14.1.0
255259
pr-url: https://github.com/nodejs/node/pull/32786
256260
description: The `highWaterMark` option is accepted now.

lib/internal/url.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1303,7 +1303,7 @@ function urlToHttpOptions(url) {
13031303
options.port = Number(url.port);
13041304
}
13051305
if (url.username || url.password) {
1306-
options.auth = `${url.username}:${url.password}`;
1306+
options.auth = `${decodeURIComponent(url.username)}:${decodeURIComponent(url.password)}`;
13071307
}
13081308
return options;
13091309
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
'use strict';
2+
require('../common');
3+
const assert = require('assert');
4+
const http = require('http');
5+
6+
const testCases = [
7+
{
8+
username: 'test@test"',
9+
password: '123456^',
10+
expected: 'dGVzdEB0ZXN0IjoxMjM0NTZe'
11+
},
12+
{
13+
username: 'test%40test',
14+
password: '123456',
15+
expected: 'dGVzdEB0ZXN0OjEyMzQ1Ng=='
16+
},
17+
{
18+
username: 'not%3Agood',
19+
password: 'god',
20+
expected: 'bm90Omdvb2Q6Z29k'
21+
},
22+
{
23+
username: 'not%22good',
24+
password: 'g%5Eod',
25+
expected: 'bm90Imdvb2Q6Z15vZA=='
26+
},
27+
{
28+
username: 'test1234::::',
29+
password: 'mypass',
30+
expected: 'dGVzdDEyMzQ6Ojo6Om15cGFzcw=='
31+
},
32+
];
33+
34+
for (const testCase of testCases) {
35+
const server = http.createServer(function(request, response) {
36+
// The correct authorization header is be passed
37+
assert.strictEqual(request.headers.authorization, `Basic ${testCase.expected}`);
38+
response.writeHead(200, {});
39+
response.end('ok');
40+
server.close();
41+
});
42+
43+
server.listen(0, function() {
44+
// make the request
45+
const url = new URL(`http://${testCase.username}:${testCase.password}@localhost:${this.address().port}`);
46+
http.request(url).end();
47+
});
48+
}

0 commit comments

Comments
 (0)