Got: The `authorization` header is improperly encoded

Created on 21 Apr 2020  路  7Comments  路  Source: sindresorhus/got

Describe the bug

Actual behavior

When I use the username/password with got, It seems that the combo 'username:password' is encoded with encodeURI() before to be encode in base64 for the basic auth. This first encoding is not necessary due to the base64 encoding and brings problems. So when the encodeURI() change a value like '@' to '%40', the basic authentification doesn't work.

Expected behavior

Just encode the combo 'username:password' with base64 encoding.

Code to reproduce

const got = require('got');

(async () => {
  const response = await got.head("http://example.com/", {username: "user@", password: "password@"});
  console.info("Response:", response.client._httpMessage._header);
}) ();

We see that the Authorization header is invalid

Checklist

  • [X] I have read the documentation.
  • [X] I have tried my code with the latest version of Node.js and Got.
bug external nodejs bug

Most helpful comment

also nodejs/node#31450

The both issues are still open in Nodejs.

I did this workaround on my side until Nodejs fixes the issue:

  const headers = {
    "Authorization": "Basic " + Buffer.from(`user@:password@`).toString("base64")
  };
  await got(encodeURI("http://example.com/"), { headers });

I built the Authorization header instead of filling username and password members of the options objects.

If Nodejs only fixes it on the new version, maybe Got can fix the issue on their side to avoid the bug on old Nodejs versions.

All 7 comments

It's a Node.js issue:

const https = require('https');
const getStream = require('get-stream');

const url = new URL('https://httpbin.org/anything');
url.username = 'user@';
url.password = 'password';

https.get(url, async response => {
    const body = await getStream(response);
    console.log(JSON.parse(body));
});

I'm not sure whether it's a bug or valid behavior...

Reference: https://tools.ietf.org/html/rfc2617 (haven't looked at it yet)

Took a quick look and found this:

      user-pass   = userid ":" password
      userid      = *<TEXT excluding ":">
      password    = *TEXT

also nodejs/node#31450

The both issues are still open in Nodejs.

I did this workaround on my side until Nodejs fixes the issue:

  const headers = {
    "Authorization": "Basic " + Buffer.from(`user@:password@`).toString("base64")
  };
  await got(encodeURI("http://example.com/"), { headers });

I built the Authorization header instead of filling username and password members of the options objects.

If Nodejs only fixes it on the new version, maybe Got can fix the issue on their side to avoid the bug on old Nodejs versions.

maybe Got can fix the issue on their side

We could implement a workaround, but it's not the proper solution. The bug is not a big one, so I'd rather wait until it's fixed on Node.js side. But if you really need this badly, you can send a PR :)

@szmarczak Let the library encode it properly, internally. I feel this is a major issue since the library has the options.username and options.password option.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

darksabrefr picture darksabrefr  路  3Comments

alvis picture alvis  路  3Comments

joolfe picture joolfe  路  3Comments

lukehorvat picture lukehorvat  路  3Comments

jamestalmage picture jamestalmage  路  3Comments