Home > Enterprise >  How to send cookies in websocket connection from extension's background script?
How to send cookies in websocket connection from extension's background script?

Time:09-22

I am trying to open an authenticated websocket connection to my backend from a chrome extension, for that I am using session cookies. This is my manifest file:

{
    "manifest_version": 2,
    "background": {
        "scripts": ["extension.js"],
        "persistent": true
    },
    "permissions": [
        "tabs",
        "storage",
        "http://localhost:8000/",
        "ws://localhost:8000/"
    ],
    "icons": {
        "16": "img/icon16.png",
        "48": "img/icon48.png",
        "128": "img/icon128.png"
    }
}

there I asked permission to access localhost:8000 on both HTTP and websocket schemes, but Chrome send cookies only for AJAX requests. If I try

await fetch('http://localhost:8000/checklogin', {
    method: 'GET',
    credentials: 'include'
});

from background script cookies are sent, but if I try

const ws = new WebSocket('ws://localhost:8000/');

no cookies are sent at all.

Is not that same domain, why Chrome is not sending cookies for websocket?

CodePudding user response:

From my research I concluded CORS with credentials for websocket is not supported in chrome extensions, so Chrome won't inject credentials in websocket upgrade requests. A workaround for that is to use chrome.webRequest to intercept websocket upgrade request and inject the Cookie header:

class WebsocketCookie {

    constructor(websocketUrl, name, value) {
        this.name = name;
        this.value = value;
        chrome.webRequest.onBeforeSendHeaders.addListener(
            ({ requestHeaders }) => {
                requestHeaders.push({name: 'Cookie', value: `${this.name}=${this.value}`});
                return {requestHeaders};
            },
            {types: ['websocket'], urls: [websocketUrl]},
            ['blocking', 'requestHeaders', 'extraHeaders']
        );
    }
}

// you can change this cookie later by changing cookie.name or cookie.value
const cookie = new WebsocketCookie('ws://localhost:8000/', 'sessionid', 'my_session_id');
const ws = new WebSocket('ws://localhost:8000/'); // sessionid cookie will be injected

that requires websocket URL, webRequest and the webRequestBlocking permissions to be added to manifest file. Use chrome.cookies to get cookies you need to inject in websocket upgrade request.

If you would like to improve security, onBeforeSendHeaders callback takes the origin of that request as initiator member, use that to check if origin is your own extension. You can get your extension's origin using chrome.management API.

  • Related