Skip to content

Commit 5744688

Browse files
author
Lew Gordon
committed
fix: 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
1 parent c6d9d8a commit 5744688

File tree

4 files changed

+42
-1
lines changed

4 files changed

+42
-1
lines changed

doc/api/http.md

+4
Original file line numberDiff line numberDiff line change
@@ -2803,6 +2803,10 @@ This can be overridden for servers and client requests by passing the
28032803
<!-- YAML
28042804
added: v0.3.6
28052805
changes:
2806+
- version: REPLACEME
2807+
pr-url: https://github.com/nodejs/node/pull/39310
2808+
description: When using a `URL` object parsed username and
2809+
password will now be properly URI decoded.
28062810
- version:
28072811
- v15.3.0
28082812
- v14.17.0

doc/api/https.md

+4
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

+1-1
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
}
+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
'use strict';
2+
require('../common');
3+
const assert = require('assert');
4+
const http = require('http');
5+
6+
const testCases = [
7+
{username: 'test@test"', password: '123456^', expected: 'dGVzdEB0ZXN0IjoxMjM0NTZe'},
8+
{username: 'test%40test', password: '123456', expected: 'dGVzdEB0ZXN0OjEyMzQ1Ng=='},
9+
{username: 'not%3Agood', password: 'god', expected: 'bm90Omdvb2Q6Z29k'},
10+
{username: 'not%22good', password: 'g%5Eod', expected: 'bm90Imdvb2Q6Z15vZA=='},
11+
{username: 'test1234::::', password: 'mypass', expected: 'dGVzdDEyMzQ6Ojo6Om15cGFzcw=='}
12+
]
13+
14+
for (const testCase of testCases) {
15+
function check(request) {
16+
// The correct authorization header is be passed
17+
assert.strictEqual(request.headers.authorization, `Basic ${testCase.expected}`);
18+
}
19+
20+
const server = http.createServer(function(request, response) {
21+
// Run the check function
22+
check(request);
23+
response.writeHead(200, {});
24+
response.end('ok');
25+
server.close();
26+
});
27+
28+
server.listen(0, function() {
29+
// make the request
30+
const url = new URL(`http://${testCase.username}:${testCase.password}@localhost:${this.address().port}`);
31+
http.request(url).end();
32+
});
33+
}

0 commit comments

Comments
 (0)