mirror of
https://github.com/tenrok/axios.git
synced 2026-06-20 20:00:40 +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 + ':';
|
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]) => {
|
const flushOnFinish = (stream, [throttled, flush]) => {
|
||||||
stream.on('end', flush).on('error', flush);
|
stream.on('end', flush).on('error', flush);
|
||||||
|
|
||||||
@@ -650,8 +666,8 @@ export default isHttpAdapterSupported &&
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!auth && parsed.username) {
|
if (!auth && parsed.username) {
|
||||||
const urlUsername = parsed.username;
|
const urlUsername = decodeURIComponentSafe(parsed.username);
|
||||||
const urlPassword = parsed.password;
|
const urlPassword = decodeURIComponentSafe(parsed.password);
|
||||||
auth = urlUsername + ':' + urlPassword;
|
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 () => {
|
it('should support basic auth with a header', async () => {
|
||||||
const server = await startHTTPServer(
|
const server = await startHTTPServer(
|
||||||
(req, res) => {
|
(req, res) => {
|
||||||
|
|||||||
Reference in New Issue
Block a user