Skip to content
This repository has been archived by the owner on Aug 30, 2022. It is now read-only.

Basic auth and websocket #158

Closed
parente opened this issue Jun 29, 2016 · 4 comments
Closed

Basic auth and websocket #158

parente opened this issue Jun 29, 2016 · 4 comments

Comments

@parente
Copy link
Member

parente commented Jun 29, 2016

Not sure if this can or should be addressed here, but worth a quick convo. I'm running a notebook or kernel gateway server behind nginx with basic auth configured.

location /jupyter/v1/some-unique-id {
      auth_basic           "Authentication required";
      auth_basic_user_file /etc/nginx/htpasswd;

      proxy_pass http://kernel_gateway/;

      proxy_set_header Host $host;
      proxy_set_header X-Real-IP $remote_addr;
      proxy_set_header X-Scheme https;
      proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
      proxy_set_header X-NginX-Proxy true;

      # WebSocket support
      proxy_http_version 1.1;
      proxy_set_header Upgrade $http_upgrade;
      proxy_set_header Connection "upgrade";
      proxy_read_timeout 86400;
    }

I can tell programmatically auth HTTP requests made by jupyter-js-services using the ajaxSettings. But the parameters don't apply to Websocket connections (in NodeJS ws at least, and browser behavior seems ill defined).

var ajaxSettings = {
    user: 'fakeuser',
    password: 'fakepass',
}

// get info about the available kernels
jupyter.getKernelSpecs({ 
    baseUrl: gatewayUrl,
    ajaxSettings: ajaxSettings
}).then((kernelSpecs) => {
    console.log('Available kernelspecs:', kernelSpecs);

    // request a new kernel
    console.log('Starting kernel:', demoLang)
    jupyter.startNewKernel({
        baseUrl: gatewayUrl,
        name: demoInfo.kernelName,
        ajaxSettings: ajaxSettings
    }).then((kernel) => {
        // code execution fails; websocket disconnects and reconnects repeatedly because of 401 errors
        console.log('Executing sample code');
        var future = kernel.execute({ code: demoSrc } );
    });
    ...
}

I can hack around this problem by passing a wsUrl parameter containing the auth parameters in the canonical URL format:

jupyter.startNewKernel({
        baseUrl: gatewayUrl,
        wsUrl: 'ws://fakeuser:fakepass@nginx/jupyter/v1/some-unique-id',
        name: demoInfo.kernelName,
        ajaxSettings: ajaxSettings
    })

This works, but the the client log message about the websocket starting contains my password:

client_1          | Starting WebSocket: ws://fakeuser:fakepass@nginx/jupyter/v1/some-unique-id

Simple fix: don't log the whole websocket URL in case there are creds in it. Harder fix (but less hacky): figure out how to map appropriate ajaxSettings (headers? basic auth?) to the equivalent parameters supported by the environment's Websocket API.

@blink1073
Copy link
Contributor

Wow, that is indeed a glaring hole in the WebSocket spec from what I can tell. Does this problem go away if using wss:? Either way, I agree it would be wise to treat a password in a URL as **** characters when printing to the terminal.

@blink1073
Copy link
Contributor

Here's a code snippet that strips the authorization: https://github.com/sindresorhus/strip-url-auth/blob/master/index.js

@parente
Copy link
Member Author

parente commented Jul 6, 2016

Would it make sense to perform that stripping logic here and anywhere else a URL is logged in the client?

https://github.com/jupyter/jupyter-js-services/blob/f9c6c009b7d0aad649b33c5548ba405b7a53fc7f/src/kernel.ts#L848

@blink1073
Copy link
Contributor

Sounds good to me.

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

No branches or pull requests

2 participants