Trying to get all cookies from the page, using chrome extension.
For example the page os https://ya.ru.
Here is my code:
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
var domain = getDomain(tabs[0].url);
chrome.cookies.getAll({
domain: domain
}, function(cookies) {
console.log(cookies);
});
});
This code will return all cookies (8) for domain ya.ru.
But the problem is when I'm opening the browser console I see cookies not only for ya.ru domain:
Same situation is on google and other sites. So I'm having multiple domain cookies on one page. How to get ALL cookies on the page?
Thank for your time.
Devtools shows cookies for all resource URLs requested by the page (source code) so we can do the same by accessing Performance API in the content script code that we'll execute in the page:
chrome.tabs.executeScript({
code: 'performance.getEntriesByType("resource").map(e => e.name)',
}, data => {
if (chrome.runtime.lastError || !data || !data[0]) return;
const urls = data[0].map(url => url.split(/[#?]/)[0]);
const uniqueUrls = [...new Set(urls).values()].filter(Boolean);
Promise.all(
uniqueUrls.map(url =>
new Promise(resolve => {
chrome.cookies.getAll({url}, resolve);
})
)
).then(results => {
// convert the array of arrays into a deduplicated flat array of cookies
const cookies = [
...new Map(
[].concat(...results)
.map(c => [JSON.stringify(c), c])
).values()
];
// do something with the cookies here
console.log(uniqueUrls, cookies);
});
});
Important notes:
Your manifest.json should have "<all_urls>" in "permissions" or an explicit list of URL match patterns that will allow the corresponding results in chrome.cookies.getAll.
Cookie deduplication code above may be slow when there are thousands of cookies.
We're reading cookies for an URL, not domain, because it's the only reliable way to get an encompassing cookie (imgur.com) for something like i.stack.imgur.com
Related
I have an ASP.NET Core 3.1 SPA application that use Microsoft.AspDotNetCore.Antiforgery.
I add the Antiforgery service in ConfigureServices method like this:
_ = services.AddAntiforgery((o) =>
{
o.HeaderName = "X-XSRF-TOKEN";
});
In Configure method, the middleware is added to add antiforgery cookie to http response:
app.Use(async (context, next) =>
{
var tokens = antiForgery.GetAndStoreTokens(context);
context.Response.Cookies.Append("XSRF-TOKEN",
tokens.RequestToken, new CookieOptions
{
HttpOnly = false,
Secure = false,
IsEssential = true
SameSite = Microsoft.AspNetCore.Http.SameSiteMode.Strict
}
);
await next();
});
I have single domain where runs two application (e.g. https://example.com/test and https://example.com/master). When I open both applications in browser I get randomly 400 BadRequest response. When I open only one application in browser, it works great.
I think both application affect single antiforgery cookie, but I don't know how and why.
Is there any solution to my problem? Thanks
I'm building an api with api platform and a front with react (using the react template of apiplatform). I configured authentification and a return to client with httponly cookie which contains the jwt. But when my front does a request, it does not send this cookie... And I absolutly don't know why, I thought it was automaticaly done by browser till it's on same domain.
Here is an example of the network history from my client :
my app is running on https://localhost:3000/
Do you see something wrong in theses request ? Or does anyone has an idea of what it could come from ?
My app and api are using https and have a valid certificate...
If you need any additional info, feel free to ask, and thanks all !!!
I assume you work with either xhr or fetch.
Cookies ignore ports, but cross origin policy does not.
You work with two urls (http://localhost:8443 and http://localhost:3000). So your app is making cross origin request because ports differ.
xhr requires to set its withCredentials property to true in order to send cookies with cross-origin request.
fetch requires its credentials parameter to be set to include.
Server side, set the Access-Control-Allow-Credentials to true.
Also note that your cookie is samesite=strict. In production, if you use two domains for your app and your api, it will never be sent.
The real question here is why using a cookie instead of Authorization header ?
Ok, I didn't know... I've found nothing on it when I was trying to solve my prob.
I'm using cookie httponly because :
I want to try it :D
Lot of security articles says that it's more secure because client api can't access theses cookies, browser manages it. It seems to counter xss and stealth of cookies, but if my cookie is stored with localforage, I think I do not have this problem, but with localStorage I do, no ?
It's cool no ! I've done too many project with classic bearer auth, I can improve it now
A big thanks for your nice answer rugolinifr !
Okay, I'm still having my issue finally... My browser is not sending the cookie...
My auth request returning bearer cookie (valid, tested with postman)
My cookie received from auth request
My GET request without that auth cookie
I'm missing something but I don't find it...
I've set credentials, Access-Control-Allow-Credentials, samesite is 'none' for sending it everywhere. Is there something else to do ? Or maybe I'm doing a stupid little thing that is wrong ?
I can't answer in comment because there's code...
So, It's managed by the react admin base of api-platform (https://api-platform.com/docs/admin/), but my config is like this :
const fetchHeaders = {
credentials: 'include',
};
const fetchHydra = (url, options = {}) =>
baseFetchHydra(url, {
...options,
headers: new Headers(fetchHeaders),
});
const apiDocumentationParser = (entrypoint) =>
parseHydraDocumentation(entrypoint, { headers: new Headers(fetchHeaders) }).then(
({ api }) => ({ api }),
(result) => {
...
},
);
const dataProvider = baseHydraDataProvider(entrypoint, fetchHydra, apiDocumentationParser, true);
So, all get, post etc request for datas are based on this conf
But my first call for authentication is done like that :
login: ({ username, password }) => {
const request = new Request(`${entrypoint}/authentication_token`, {
method: 'POST',
body: JSON.stringify({ username, password }),
headers: new Headers({ 'Content-Type': 'application/json' }),
});
return fetch(request).then((response) => {
if (response.status < 200 || response.status >= 300) {
localStorage.removeItem('isAuthenticated');
throw new Error(response.statusText);
}
localStorage.setItem('isAuthenticated', 'true');
});
},
ok, I've found solution :
add credentials to the auth request, if header is not added, cookie won't be stored by browser.
And second point :
const fetchHydra = (url, options = {}) =>
baseFetchHydra(url, {
...options,
credentials: 'include',
});
credentials: 'include' is not in headers option... Nice !
Faced the same problem.Tried out many solutions but didn't work.At last found out it was the cors configuration of node backend that was causing the problem. Configured cors like the following way to solve the problem.
const corsConfig = {
origin: true,
credentials: true,
};
app.use(cors(corsConfig));
app.options('*', cors(corsConfig));
I am building a simple Progressive Web Application with Python Django and django-pwa package. I have set up everything but offline functionality is not working. At this point, service workers (SW) are installed and dev tools recognize application as PWA. But when I check "offline" in devtools->Application and reload the web page there is a "No internet connection" error.
Here are my SW settings:
var staticCacheName = 'djangopwa-v1';
var filesToCache = [
'/',
'/x_offline/',
'/static/x_django_pwa/images/my_app_icon.jpg',
'/media/images/bfly1.2e16d0ba.fill-320x240.jpg',
];
// Cache on install
self.addEventListener("install", event => {
this.skipWaiting();
event.waitUntil(
caches.open(staticCacheName)
.then(cache => {
return cache.addAll(filesToCache);
})
)
});
// Clear cache on activate
self.addEventListener('activate', event => {
event.waitUntil(
caches.keys().then(cacheNames => {
return Promise.all(
cacheNames
.filter(cacheName => (cacheName.startsWith("djangopwa-v1")))
.filter(cacheName => (cacheName !== staticCacheName))
.map(cacheName => caches.delete(cacheName))
);
})
);
});
// Serve from Cache
self.addEventListener("fetch", event => {
event.respondWith(
caches.match(event.request)
.then(response => {
return response || fetch(event.request);
})
.catch(() => {
return caches.match('x_offline');
})
)
});
Listed settings are almost the same as default one from django-pwa repo
When I load the page for the first time I see that requests are also made for the urls listed in SW and all of them have status 200. In the cache storage I see cache with paths set in SW. So I don't understand what I do wrong.
Not sure if this additional info is useful, but: when I set SW to offline and reload the web page the cache storage is empty.
The issue is in the settings that django-pwa repo provided.
They accidentally added sign , at the end of the scope variable and so if you copy settings you copy with incorrect scope setting (PWA_APP_SCOPE = '/',) and it brakes offline mode. I am going to contact with repo admins so that to fix the issue for the next users.
Using ASPNETCORE OpenId authentication middleware and Cookie middleware. I always see that cookies from OpenId authentication are set to expire at 1969-12-31 (in Chrome debugger). I assume this means the cookies are SESSION cookies; I want to make them persistent cookies so the user will be prompted to login less frequently. So I added the ExpireTimeSpan and IsPersistent=true as suggested in other posts, but I still see that my cookie Expires is 1969-12-31.
What am I doing wrong?
services.AddAuthentication(options =>
{
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
})
.AddAzureAd(options =>
{
Configuration.Bind("AzureAd", options);
})
.AddCookie(p =>
{
p.ExpireTimeSpan = TimeSpan.FromDays(30);
p.SlidingExpiration = true;
});
services.Configure<AuthenticationProperties>(props =>
{
props.IsPersistent = true;
props.ExpiresUtc = new DateTimeOffset(DateTime.Now, TimeSpan.FromDays(30));
});
Got helped on the aspnetcore security forum, and arrived at the following solution:
.AddCookie(p =>
{
p.SlidingExpiration = true;
p.Events.OnSigningIn = (context) =>
{
context.CookieOptions.Expires = DateTimeOffset.UtcNow.AddDays(30);
return Task.CompletedTask;
};
});
I also implemented a Logout page (call to AuthenticationHttpContextExtensions.SignOutAsync(HttpContext)) to give the user more control over cookie lifetimes.
I am trying out the new Fetch API but is having trouble with Cookies. Specifically, after a successful login, there is a Cookie header in future requests, but Fetch seems to ignore that headers, and all my requests made with Fetch is unauthorized.
Is it because Fetch is still not ready or Fetch does not work with Cookies?
I build my app with Webpack. I also use Fetch in React Native, which does not have the same issue.
Fetch does not use cookie by default. To enable cookie, do this:
fetch(url, {
credentials: "same-origin"
}).then(...).catch(...);
In addition to #Khanetor's answer, for those who are working with cross-origin requests: credentials: 'include'
Sample JSON fetch request:
fetch(url, {
method: 'GET',
credentials: 'include'
})
.then((response) => response.json())
.then((json) => {
console.log('Gotcha');
}).catch((err) => {
console.log(err);
});
https://developer.mozilla.org/en-US/docs/Web/API/Request/credentials
Have just solved. Just two f. days of brutforce
For me the secret was in following:
I called POST /api/auth and see that cookies were successfully received.
Then calling GET /api/users/ with credentials: 'include' and got 401 unauth, because of no cookies were sent with the request.
The KEY is to set credentials: 'include' for the first /api/auth call too.
If you are reading this in 2019, credentials: "same-origin" is the default value.
fetch(url).then
Programmatically overwriting Cookie header in browser side won't work.
In fetch documentation, Note that some names are forbidden. is mentioned. And Cookie happens to be one of the forbidden header names, which cannot be modified programmatically. Take the following code for example:
Executed in the Chrome DevTools console of page https://httpbin.org/, Cookie: 'xxx=yyy' will be ignored, and the browser will always send the value of document.cookie as the cookie if there is one.
If executed on a different origin, no cookie is sent.
fetch('https://httpbin.org/cookies', {
headers: {
Cookie: 'xxx=yyy'
}
}).then(response => response.json())
.then(data => console.log(JSON.stringify(data, null, 2)));
P.S. You can create a sample cookie foo=bar by opening https://httpbin.org/cookies/set/foo/bar in the chrome browser.
See Forbidden header name for details.
Just adding to the correct answers here for .net webapi2 users.
If you are using cors because your client site is served from a different address as your webapi then you need to also include SupportsCredentials=true on the server side configuration.
// Access-Control-Allow-Origin
// https://learn.microsoft.com/en-us/aspnet/web-api/overview/security/enabling-cross-origin-requests-in-web-api
var cors = new EnableCorsAttribute(Settings.CORSSites,"*", "*");
cors.SupportsCredentials = true;
config.EnableCors(cors);
This works for me:
import Cookies from 'universal-cookie';
const cookies = new Cookies();
function headers(set_cookie=false) {
let headers = {
'Accept': 'application/json',
'Content-Type': 'application/json',
'X-CSRF-Token': $('meta[name="csrf-token"]').attr('content')
};
if (set_cookie) {
headers['Authorization'] = "Bearer " + cookies.get('remember_user_token');
}
return headers;
}
Then build your call:
export function fetchTests(user_id) {
return function (dispatch) {
let data = {
method: 'POST',
credentials: 'same-origin',
mode: 'same-origin',
body: JSON.stringify({
user_id: user_id
}),
headers: headers(true)
};
return fetch('/api/v1/tests/listing/', data)
.then(response => response.json())
.then(json => dispatch(receiveTests(json)));
};
}
My issue was my cookie was set on a specific URL path (e.g., /auth), but I was fetching to a different path. I needed to set my cookie's path to /.
If it still doesn't work for you after fixing the credentials.
I also was using the :
credentials: "same-origin"
and it used to work, then it didn't anymore suddenly, after digging much I realized that I had change my website url to http://192.168.1.100 to test it in LAN, and that was the url which was being used to send the request, even though I was on http://localhost:3000.
So in conclusion, be sure that the domain of the page matches the domain of the fetch url.