mirror of
https://github.com/tenrok/axios.git
synced 2026-06-17 19:21:29 +03:00
fix(http): decode URL basic auth credentials (#10825)
* fix(http): decode URL basic auth credentials * fix(http): guard URL credential decode * chore: apply small nits --------- Co-authored-by: Jay <jasonsaayman@gmail.com>
This commit is contained in:
+18
-2
@@ -57,6 +57,22 @@ const supportedProtocols = platform.protocols.map((protocol) => {
|
||||
return protocol + ':';
|
||||
});
|
||||
|
||||
// Node's WHATWG URL parser returns `username` and `password` percent-encoded.
|
||||
// Decode before composing the `auth` option so credentials such as
|
||||
// `my%40email.com:pass` are sent as `my@email.com:pass`. Falls back to the
|
||||
// original value for malformed input so a bad encoding never throws.
|
||||
const decodeURIComponentSafe = (value) => {
|
||||
if (!utils.isString(value)) {
|
||||
return value;
|
||||
}
|
||||
|
||||
try {
|
||||
return decodeURIComponent(value);
|
||||
} catch (error) {
|
||||
return value;
|
||||
}
|
||||
};
|
||||
|
||||
const flushOnFinish = (stream, [throttled, flush]) => {
|
||||
stream.on('end', flush).on('error', flush);
|
||||
|
||||
@@ -650,8 +666,8 @@ export default isHttpAdapterSupported &&
|
||||
}
|
||||
|
||||
if (!auth && parsed.username) {
|
||||
const urlUsername = parsed.username;
|
||||
const urlPassword = parsed.password;
|
||||
const urlUsername = decodeURIComponentSafe(parsed.username);
|
||||
const urlPassword = decodeURIComponentSafe(parsed.password);
|
||||
auth = urlUsername + ':' + urlPassword;
|
||||
}
|
||||
|
||||
|
||||
@@ -890,6 +890,44 @@ describe('supports http with nodejs', () => {
|
||||
}
|
||||
});
|
||||
|
||||
it('should decode basic auth credentials from the request URL', async () => {
|
||||
const server = await startHTTPServer(
|
||||
(req, res) => {
|
||||
res.end(req.headers.authorization);
|
||||
},
|
||||
{ port: SERVER_PORT }
|
||||
);
|
||||
|
||||
try {
|
||||
const response = await axios.get(
|
||||
`http://my%40email.com:pa%24ss@localhost:${server.address().port}/`
|
||||
);
|
||||
const base64 = Buffer.from('my@email.com:pa$ss', 'utf8').toString('base64');
|
||||
assert.strictEqual(response.data, `Basic ${base64}`);
|
||||
} finally {
|
||||
await stopHTTPServer(server);
|
||||
}
|
||||
});
|
||||
|
||||
it('keeps malformed URL credentials percent-encoding and does not throw', async () => {
|
||||
const server = await startHTTPServer(
|
||||
(req, res) => {
|
||||
res.end(req.headers.authorization);
|
||||
},
|
||||
{ port: SERVER_PORT }
|
||||
);
|
||||
|
||||
try {
|
||||
const response = await axios.get(
|
||||
`http://user%:foo%zz@localhost:${server.address().port}/`
|
||||
);
|
||||
const base64 = Buffer.from('user%:foo%zz', 'utf8').toString('base64');
|
||||
assert.strictEqual(response.data, `Basic ${base64}`);
|
||||
} finally {
|
||||
await stopHTTPServer(server);
|
||||
}
|
||||
});
|
||||
|
||||
it('should support basic auth with a header', async () => {
|
||||
const server = await startHTTPServer(
|
||||
(req, res) => {
|
||||
|
||||
Reference in New Issue
Block a user