I have some trouble working with cookies via chrome extension from popup script.
popup.js content:
document.addEventListener('DOMContentLoaded', () => {
function cookieinfo() {
chrome.cookies.getAll({url: 'http://localhost:8080'}, function(cookie) {
console.log('Found cookie: ', cookie)
if (cookie == null)
return;
fetch('http://localhost:8080', {credentials: 'include'}).then((response) => {
// do some stuff
return response;
});
});
}
window.onload=cookieinfo;
}, false);
Steps that I perform:
Maybe someone knows what I'm doing wrong?
Edit:
It seems that the reason is that my cookie has parameters HttpOnly=true
and SameSite=Lax
( related link ). I can see another cookies in the server log. But due to this thread all cookies will be sent if credentials
parameter is set to include
, even httpOnly cookies. Also I tried to send it to 127.0.0.1 instead of localhost due to this answer with the same result.
I can't set httpOnly
to false. This is forced by framework. Somebody know how to fix it?
Edit2:
I finally installed Cookie editor and found out that the SameSite=Lax
is the reason. If I set it to No Restriction
then I will see it on the server side. Unfortunately, the framework I'm using only allows Lax
and Strict
options (Chrome extension fails with both). Does anyone know how to send Lax cookies from the Chrome extension?
This was the issue with extensions in Chromium till version 77. When cross-site cookie was set to SameSite=Lax
or SameSite=Strict
, the cookie was not sent with the cross-site request.
This has been fixed in version 78 in all platforms. Now chrome extension sends cookies when SameSite=Lax
or SameSite=Strict
.
References:
https://bugs.chromium.org/p/chromium/issues/detail?id=1007973
https://chromium-review.googlesource.com/c/chromium/src/+/1827503
https://bugs.chromium.org/p/chromium/issues/detail?id=617198
The content script is 100% the solution.
You basically have two individual browsers, the regular browser and also the extension popup browser. But they are entirely separate and can only send messages back and forth. So what you need to do is have the extension context send a message to the browser context that instructs some code in that context to get the document.cookies
and send them back to the extension context.
Here's an example of me getting cookies from each separate browser context.
manifest.json
{
"manifest_version": 2,
"name": "Cookie Monster",
"description": "Nom nom nom nom",
"version": "1.0",
"browser_action": {
"default_popup": "html/extension.html",
"default_title":"Cookie Monster"
},
"permissions": [
"activeTab",
"tabs",
"http://*/*",
"https://*/*"
],
"content_scripts": [{
"js":["/js/client.js"],
"matches":["http://*/*","https://*/*"]
}]
}
extension.html
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<title>Cookies</title>
<style>
body {
display: block;
min-height: 250px;
width: 250px;
padding: 5px;
}
button {
display: block;
margin: 0 0 10px 0;
}
</style>
</head>
<body class="container">
<h1>Cookies</h1>
<button id="extension_cookies" type="button">Get PopUp Cookies</button>
<button id="browser_cookies" type="button">Get Browser Cookies</button>
<p id="result"></p>
<script src="/js/extension.js" type="text/javascript"></script>
</body>
</html>
extension.js
'use strict';
(function(){
// cache import DOM elements
const extension_btn = document.querySelector('#extension_cookies');
const browser_btn = document.querySelector('#browser_cookies');
const result = document.querySelector('#result');
// runs in the popup window of the extension,
// which is it's own browser context
// and has it's own set of cookies
extension_btn.addEventListener('click', () => {
if (document.cookie === ''){
result.innerText = 'No Cookies...';
} else {
result.innerText = document.cookie;
}
})
// send message to browser context
// message will inform browser client of what to do
// the browser then needs to pass data to the callback function
// then we can display results
browser_btn.addEventListener('click', () => {
chrome.tabs.query({active: true, currentWindow: true}, (tabs) => {
chrome.tabs.sendMessage(tabs[0].id, {message: 'GET_COOKIES'}, (data) => {
result.innerText = data.cookies
});
});
})
}());
client.js
'use strict';
(function(){
// receive a callback function so I can pass data to extension
// get document cookies, put into an object
// use callback to send response to extension
const get_browser_cookies = (sendResponse) => {
const cookies = document.cookie;
console.clear();
console.log(cookies);
sendResponse({ cookies: cookies });
}
// listen for messages from extension
// a switch statement can help run only the correct function
// must pass the function a reference to the sendResponse function
// so I can pass data back to extension
chrome.runtime.onMessage.addListener(function(data_from_extension, sender, sendResponse){
switch (data_from_extension.message){
case 'GET_COOKIES': {
get_browser_cookies(sendResponse);
break;
}
default: null;
}
});
}())
What I found out is the cookie's path
is crucial. Any mismatch results in misleading behaviour.
This is my setup:
localhost:8081
"http://localhost:8081/"
path=/
, eg. this is a sample response header Set-Cookie: refresh_token=bar; Path=/; SameSite=Lax; HttpOnly
Set-Cookie: refresh_token=bar; Path=/; SameSite=Lax; HttpOnly
chrome.cookies.get({ url: 'http://localhost:8081/', name: 'refresh_token' }...
localhost:8081
, eg: fetch('http://localhost:8081/v1/meh').then((response) => { console.log(response); })
Server side will see the refresh_token
cookie. To summarise: a cookie set at path /a
won't be sent to a url at path /b
; a cookie set at path /
will be sent to all urls under same domain.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.