Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Special Characters in WS Authorization #1831

Closed
1 task done
netrexfrost opened this issue Jan 6, 2021 · 4 comments
Closed
1 task done

Special Characters in WS Authorization #1831

netrexfrost opened this issue Jan 6, 2021 · 4 comments

Comments

@netrexfrost
Copy link

netrexfrost commented Jan 6, 2021

  • I've searched for any related issues and avoided creating a duplicate
    issue.

Description

There seems to be no way to pass authorization details containing special characters such as '#'.

Reproducible in:

  • version: 7.2.1
  • Node.js version(s): 10.19.0

Steps to reproduce:

On creating new WebSocket(adress,[porotocols]) pass as address either raw URL ws://usr:pass#@host:port/path or the properly encoded URL ws://usr:pass%23@host:port/path.

Expected result:

In the case of raw URL error would be expected. (which is what happens now)
In the case of encoded URL I'd however expect for the WebSocket authorization to be set as usr:pass#.

Actual result:

In case of encoded URL the WebSocket authorization is set as usr:pass%23 and is seemingly never decoded. Thus it seems there is no way to establish connection with any device using special characters in its authorization.

Attachments:

@lpinca
Copy link
Member

lpinca commented Jan 6, 2021

This is not a ws issue, see nodejs/node#31450.

You can use the auth option:

const WebSocket = require('ws');

const wss = new WebSocket.Server({ port: 0 }, function () {
  const ws = new WebSocket(`ws://localhost:${wss.address().port}`, {
    auth: 'usr:pass#'
  });

  ws.on('close', function () {
    wss.close();
  });
});

wss.on('connection', function (ws, req) {
  console.log(
    Buffer.from(req.headers.authorization.slice(6), 'base64').toString()
  );
  ws.close();
});

or compute the Authorization header yourself:

const WebSocket = require('ws');

const wss = new WebSocket.Server({ port: 0 }, function () {
  const ws = new WebSocket(`ws://localhost:${wss.address().port}`, {
    headers: {
      Authorization: 'Basic dXNyOnBhc3Mj'
    }
  });

  ws.on('close', function () {
    wss.close();
  });
});

wss.on('connection', function (ws, req) {
  console.log(
    Buffer.from(req.headers.authorization.slice(6), 'base64').toString()
  );
  ws.close();
});

@lpinca
Copy link
Member

lpinca commented Jan 7, 2021

I'm closing this as answered. Discussion can continue if needed.

@lpinca lpinca closed this as completed Jan 7, 2021
@netrexfrost
Copy link
Author

Thank you for letting me know the issue is being worked on.
However it seems the fixes you suggest are not fixing the problem in my actual code.

ad 1) I am probably missing something here but nothing in WebSocket constructor seems to suggests the first one would work and sure enough it doesn't. options.auth seems to be overriden right here with undefined:

function initAsClient(websocket, address, protocols, options) {
  const opts = {
    protocolVersion: protocolVersions[1],
    maxPayload: 100 * 1024 * 1024,
    perMessageDeflate: true,
    followRedirects: false,
    maxRedirects: 10,
    ...options,
    createConnection: undefined,
    socketPath: undefined,
    hostname: undefined,
    protocol: undefined,
    timeout: undefined,
    method: undefined,
    auth: undefined,
    host: undefined,
    path: undefined,
    port: undefined
  };

when i fixed it to

function initAsClient(websocket, address, protocols, options) {
const opts = {
  protocolVersion: protocolVersions[1],
  maxPayload: 100 * 1024 * 1024,
  perMessageDeflate: true,
  followRedirects: false,
  maxRedirects: 10,
  createConnection: undefined,
  socketPath: undefined,
  hostname: undefined,
  protocol: undefined,
  timeout: undefined,
  method: undefined,
  auth: undefined,
  host: undefined,
  path: undefined,
  port: undefined,
  ...options
};

it worked...

ad 2) I have this problem on legacy code that I haven't written and there was already calculated Digest header even when I tried passing authorization through URL and it doesn't help much. Hopefully not for similar reason as 1). I'll try experimenting with this more, thank you.

@lpinca
Copy link
Member

lpinca commented Jan 7, 2021

You need ws@>=7.2.4 for option 1. Both options work, try running the above examples.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants