Skip to content

Commit 54dd3df

Browse files
Lew Gordondanielleadams
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 2129ad6 commit 54dd3df

File tree

4 files changed

+60
-2
lines changed

4 files changed

+60
-2
lines changed

doc/api/http.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2829,7 +2829,13 @@ This can be overridden for servers and client requests by passing the
28292829
<!-- YAML
28302830
added: v0.3.6
28312831
changes:
2832-
- version: v15.3.0
2832+
- version: REPLACEME
2833+
pr-url: https://github.com/nodejs/node/pull/39310
2834+
description: When using a `URL` object parsed username and
2835+
password will now be properly URI decoded.
2836+
- version:
2837+
- v15.3.0
2838+
- v14.17.0
28332839
pr-url: https://github.com/nodejs/node/pull/36048
28342840
description: It is possible to abort a request with an AbortSignal.
28352841
- version:

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:
255259
- v14.1.0
256260
- v13.14.0

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)