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.