How to get access to an http-only cookie using Meteor - cookies

Some background:
my site: site.domain.com
http-only cookie set by domain.com.
I can see the cookie in the resources view in Chrome & in the network traffic
I really need read access to an http-only (domain) cookie from either meteor client or server (doesnt matter to me)
http-only renders any technique that uses "document.cookie" useless unfortunately.
I can see the cookie details being passed back to Meteor inside the various sockjs GET requests, what i probably need is a way to get at that raw request info so i can tease out the cookie value.
Anyone have any ideas?
Thanks in advance

Have a look at trying to access the headers via req or using connect's cookieparser:
Server Js
__meteor_bootstrap__.app.use(connect.cookieParser()).use(function(req, res, next) {
Fiber(function () {
console.log(JSON.stringify(req.cookies));
}).run();
});
Have a look at : https://groups.google.com/forum/?fromgroups=#!topic/meteor-talk/xLGOcruZ4c4 for more info about this

Related

Keystone session cookie only working on localhost

Edit:
After investigating this further, it seems cookies are sent correctly on most API requests. However something happens in the specific request that checks if the user is logged in and it always returns null. When refreshing the browser a successful preflight request is sent and nothing else, even though there is a session and a valid session cookie.
Original question:
I have a NextJS frontend authenticating against a Keystone backend.
When running on localhost, I can log in and then refresh the browser without getting logged out, i.e. the browser reads the cookie correctly.
When the application is deployed on an external server, I can still log in, but when refreshing the browser it seems no cookie is found and it is as if I'm logged out. However if I then go to the Keystone admin UI, I am still logged in.
In the browser settings, I can see that for localhost there is a "keystonejs-session" cookie being created. This is not the case for the external server.
Here are the session settings from the Keystone config file.
The value of process.env.DOMAIN on the external server would be for example example.com when Keystone is deployed to admin.example.com. I have also tried .example.com, with a leading dot, with the same result. (I believe the leading dot is ignored in newer specifications.)
const sessionConfig = {
maxAge: 60 * 60 * 24 * 30,
secret: process.env.COOKIE_SECRET,
sameSite: 'lax',
secure: true,
domain: process.env.DOMAIN,
path: "/",
};
const session = statelessSessions(sessionConfig);
(The session object is then passed to the config function from #keystone-6/core.)
Current workaround:
I'm currently using a workaround which involves routing all API requests to '/api/graphql' and rewriting that request to the real URL using Next's own rewrites. Someone recommended this might work and it does, sort of. When refreshing the browser window the application is still in a logged-out state, but after a second or two the session is validated.
To use this workaround, add the following rewrite directive to next.config.js
rewrites: () => [
{
source: '/api/graphql',
destination:
process.env.NODE_ENV === 'development'
? `http://localhost:3000/api/graphql`
: process.env.NEXT_PUBLIC_BACKEND_ENDPOINT,
},
],
Then make sure you use this URL for queries. In my case that's the URL I feed to createUploadLink().
This workaround still means constant error messages in the logs since relative URLs are not supposed to work. I would love to see a proper solution!
It's hard to know what's happening for sure without knowing more about your setup. Inspecting the requests and responses your browser is making may help figure this out. Look in the "network" tab in your browser dev tools. When you make make the request to sign in, you should see the cookie being set in the headers of the response.
Some educated guesses:
Are you accessing your external server over HTTPS?
They Keystone docs for the session API mention that, when setting secure to true...
[...] the cookie is only sent to the server when a request is made with the https: scheme (except on localhost)
So, if you're running your deployed env over plain HTTP, the cookie is never set, creating the behaviour you're describing. Somewhat confusingly, in development the flag is ignored, allowing it to work.
A similar thing can happen if you're deploying behind a proxy, like nginx:
In this scenario, a lot of people choose to have the proxy terminate the TLS connection, so requests are forwarded to the backend over HTTP (but on a private network, so still relatively secure). In that case, you need to do two things:
Ensure the proxy is configured to forward the X-Forwarded-Proto header, which informs the backend which protocol was used originally request
Tell express to trust what the proxy is saying by configuring the trust proxy setting
I did a write up of this proxy issue a while back. It's for Keystone 5 (so some of the details are off) but, if you're using a reverse proxy, most of it's still relevant.
Update
From Simons comment, the above guesses missed the mark 😭 but I'll leave them here in case they help others.
Since posting about this issue a month ago I was actually able to work around it by routing API requests via a relative path like '/api/graphql' and then forwarding that request to the real API on a separate subdomain. For some mysterious reason it works this way.
This is starting to sound like a CORS or issue
If you want to serve your front end from a different origin (domain) than the API, the API needs to return a specific header to allow this. Read up on CORS and the Access-Control-Allow-Origin header. You can configure this setting the cors option in the Keystone server config which Keystone uses to configure the cors package.
Alternatively, the solution of proxying API requests via the Next app should also work. It's not obvious to me why your proxying "workaround" is experiencing problems.

JMeter 5.4.1 Cookie Manager - User-Defined Cookie not added to request's cookies

Firstly, I did add the line CookieManager.check.cookies=false to jmeter.properties.
What I'm Trying to Do
I want to add a cookie to a request's existing cookies.
For example, I see the request has [edited]:
Cookie Data:
c1=sfasfsfsfsfs; c2=erqwerqwrr; c3=poiuopiupoi
Expected Results
I would like it to have:
Cookie Data:
c1=sfasfsfsfsfs; c2=erqwerqwrr; c3=poiuopiupoi; partner=favicon.ico
Here is what I tried:
BASE_URL_2 is a variable defined in the form qa.company.com.
Actual Results
Whatever I have tried so far has not made any change in the cookies.
What else shall I try?
Underlying Motivation
Recorded a Web session and played it back.
Added a RegEx Extractor to pull out a token and then added it to subsequent requests. That helped.
However, certain requests failed with an custom application exception Security violation, please refresh.
Probably session login state is not being passed, so the website thinks the call is "stale".
I've seen this on the GUI when the session expires and you try to click a button on the site.
On comparing the cookies seem in JMeter with what I saw in the Chrome Debugger, it was clear that there were more cookies in the running application than what I had in JMeter.
Are you sure you're using HTTPS protocol because if you have secure flag and using HTTP protocol - the cookie will not be sent.
Also remove = from partner= otherwise you will end up with partner==favicon.ico
Demo:
More information:
Using HTTP cookies
HTTP Cookie Manager Advanced Usage - A Guide

Why am I getting "Indicate whether to send a cookie in a cross-site request by specifying its SameSite attribute"?

In a Chrome warning, it says:
Specify SameSite=None and Secure if the cookie should be sent in cross-site requests. This enables third-party use.
How do I do this correctly using express-session?
app.use(
cors({
credentials: true,
origin: ["http://localhost:3000", "https://elated-jackson-28b73e.netlify.app"] //Swap this with the client url
})
);
var sess = {
secret: 'keyboard cat',
cookie: {}
}
if (app.get('env') === 'production') {
app.set('trust proxy', 1) // trust first proxy
sess.cookie.secure = true // serve secure cookies
sess.cookie.sameSite = 'none'
}
app.use(session(sess))
you are getting this because you are using a resource from another site and that server is attempting to set a "cookie" but, it does not have the SameSite attribute set, which is being reported in newer versions of browsers.
this (may) also be shown if you are trying to access the server page from local computer (xampp), which generally doesn't has SSL installed;
set the header line in your server page (if in PHP) as below:
header("Set-Cookie: cross-site-cookie=whatever; SameSite=None; Secure");
(remember: this must be solved from the server side.)
i got the same issue when run my code in localhost. The affected resource is _ga, _gid, _utma, _utmz. All of them from unpkg.com
and i got marker image leaflet failed request but doesnt affect the page.
since i dont understand what the specific problem so i just delete the affected resource cookies in inspect element and the code will run without notif again.
thought i know if it's better to not answer based by personal experience. just tell me if it's not help at all.
If you are using Google login button or any other identity service add this:
<GoogleLogin onSuccess={() =>()} onError={() => ()} cookiePolicy='single-host-origin'/>

send a cookie with XMLHTTPRequest (TVMLJS)

I am developing an application for my AppleTV. The App will read movies from an online website that hasn't developed any API for this kind of thing.
I use XMLHTTPRequest to get the different URLs and have the user search for his movie, etc... Everything is working fine, except for a single request. To get the movie URL, I have to send a get request to a specific address (let's say http://example.com/getmovie.html) with a constant cookie (let's say mycookie=cookie).
I've tried using setRequestHeader:
var xhr = new XMLHttpRequest();
xhr.open("GET", url, false);
xhr.withCredentials = true;
xhr.setRequestHeader('Cookie', 'mycookie=cookie');
xhr.send();
But no cookie seems to be sent.
I also tried setting the cookie with Document.cookie like I would have probably done in a "normal" js script (running in my browser) but no luck either.
This is extremely frustrating, especially since I'm stuck so close to the end of my app.
I guess cross-origin might be the issue but I'm able to get URLs without issues if I don't have to set cookies, so I am a bit lost there.
Please let me know how I can get http://example.com/getmovie.html with a specific cookie header.
Thanks for your help
im sorry to inform you but the xmlHTTPRequest function of javascript does not allow a cookie header to be set for security reasons as shown here: Why cookies and set-cookie headers can't be set while making xmlhttprequest using setRequestHeader? the best way i could see you making that get request would be to a proxy server that you would be running. I believe that it is built this way to prevent you from setting cookies on domains that you do not own, furthermore i do not see an alternate resolution to this problem as no were in the docs i looked at was cookie persistence or management mentioned
In case someone has the same issue:
I didn't find a solution to sending a cookie with javascript. However, in my situation, the origin of the request didn't matter, only the cookie did. My solution was then to create a PHP file receiving the destination URL and the cookie content as parameters, and then sending the get request with the cookie as a request header. (more information about how to do so here: PHP GET Request, sending headers).
In my javascript I then use XMLHttpRequest to connect to my PHP file (hosted online) with simple get parameters and I then receive the response from the PHP. That trick of course won't work if the origin of the request matters (except if you host your file at home I guess, but in my case I want my application to work even if my WAMP isn't on).
Well... the problem here is the line xhr.setRequestHeader('Cookie', 'mycookie=cookie'); line just because the 'Cookie' header is reserved for the client browser to send the stored cookies. This means you are trying to do what the browser already does. When you send a any request, the client browser automatlycally will take all the cookies related to the site you are requesting and put them on the 'Cookie' header, you don't need to do anything else, if your cookie exist in your browser, it will be send.
Cordova how to send session cookie, allow credentials with XMLhttprequest:
// JS
var xhr = new XMLHttpRequest();
xhr.open('GET', 'http://example.com/ajax.php', true);
xhr.withCredentials = true;
xhr.onreadystatechange = function() {
if(xhr.readyState == 4 && xhr.status == 200) {
// alert(xhr.responseText);
// Get header from php server request if you want for something
var cookie = xhr.getResponseHeader("Cookie");
// alert("Cookie: " + cookie);
}
}
xhr.send();
// Php
// You can add cookie to header and get with (session works without it)
header('Cookie: PHPSESSID='.$_COOKIE['PHPSESSID']);
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET, POST, OPTIONS');
header('Access-Control-Allow-Headers: Origin, Content-Type, Accept, Authorization, X-Request-With, Set-Cookie, Cookie, Bearer');
header('Access-Control-Allow-Credentials: true');
header('Access-Control-Max-Age: 86400');

Setting cookies for subdomain

i'm making a web app in a restful way.
For my client side i'm using angularJs, the same is hosted at - lets say -
https://domain.com
My backend is built on spring boot and i call all the resources from a subdomain - lets say -
https://xyz.domain.com
Now when a user logs in , the backend sends an http only cookie to the client.
I can see the cookie in response header but its not being set in the browsers cookie.
After a bit of research, i have tried sending cookie with domain = .domain.com
but that didnt work either.
Is there a way i can set cookie coming from xyz.domain.com for my client side at domain.com
(Note - i'm not using www.domain.com )
Any help or clue would be great.
Thank you for going through my question.
The problem you're describing is related to cross domain cookie policies. I don't know your exact use-case, but looking at CORS and P3P headers should give you a good start. As an option, you can try setting your cookie manually via Javascript.
Making CORS working isn't enough, you also need to enable withCredentials in angular.
https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/withCredentials
Example:
angular.module('example', []).config(function ($httpProvider) {
$httpProvider.defaults.withCredentials = true;
});