So I am trying to set up environment for local development to pull data from my dev server at dev.mydomain.com.
The tornado REST server serving data uses a cookie-based authentication.
To obtain the cookie I sent an AJAX post login request to the server (from the website at localhost), and the secure cookie comes back in a response. I can see that in the chrome console (network->cookies). It has the proper name, value, domain (dev.mydomain.com) and everything.
Yet, the cookie doesn't get set and the REST requests that follow fail. It is not cross-origin related. If I go to dev.mydomain.com and log in manually in another tab the cookie gets set correctly and all my subsequent requests sent from local domain work fine (since they grab the now-existent cookie).
All my requests contain this:
xhrFields: {
'withCredentials': true
}
And this is how my tornado server sets the cookie:
self.set_secure_cookie(
COOKIE_NAME, tornado.escape.url_escape(str(COOKIE_VALUE)),
expires_days=1, domain="dev.mydomain.com"
)
Any idea why the cookie doesn't get set if the login request comes from localhost?
I tried mapping 127.0.0.1 to foo.mydomain.com (for whatever that's worth) but this doesn't help.
Also, I cannot grab the cookie with javascript. Tried xhr.getResponseHeader('Set-Cookie');, yields null.
Somehow it makes sense to me that if you set the cookie for dev.mydomain.com that it does neither work for foo.mydomain.com nor for localhost.
What happens if you do something like this:
self.set_secure_cookie(
COOKIE_NAME, tornado.escape.url_escape(str(COOKIE_VALUE)),
expires_days=1, domain=".mydomain.com"
)
*.mydomain.com might work then.
EDIT:
Actually, I checked over and over again, and I can't find an example where people used the argument 'domain' for set_secure_cookie() but instead this argument exists for 'set_cookie()', as stated in the docs:
Additional keyword arguments are set on the Cookie.Morsel directly.
See http://docs.python.org/library/cookie.html#morsel-objects for
available attributes.
If you are sure about using secure cookies, you should first get sure to use a cookie secret in your application settings
class Main(web.Application):
def __init__(self):
settings = dict(
cookie_secret = "xxxx",
)
then try to set the secure cookie, without specifying the domain
self.set_secure_cookie(
COOKIE_NAME, tornado.escape.url_escape(str(COOKIE_VALUE)),
expires_days=1
)
Related
I am inheriting a backend Express API and a front end React app.
Currently I am using cookie-parser in my POST /login API like so:
res.cookie('something', 'abc123', {
maxAge: COOKIE_MAX_AGE
});
on my front end app, there is a function for checking if an auth token exists:
export function isAuthCookiePresent() {
console.log('ALL COOKIES:', cookies.get());
return (
cookies.get(AUTH_COOKIE_NAME) && cookies.get(AUTH_COOKIE_NAME) !== null
);
}
And as expected I see { something: 'abc123' } in my console logs.
However, when I try logging in this using autodeployed branches in Vercel (https://vercel.com/), the cookie is missing.
I was under the impression that cookies were supposed to be set on the front end? But in the code the cookie is being set on the backend. And I don't see anything in the code that passes it to the front end. I thought I would find something on the front end like that would have a "upon successful login, execute cookies.set("x-auth-token", res.body.token)"
It's odd to me that it works locally at all. Would someone mind explaining how this works? I thought cookies were stored in the browser on the client side. But if that was true, why does cookie-parser even exist in express and why is it being used server side?
However, when I try logging in this using autodeployed branches in Vercel (https://vercel.com/), the cookie is missing.
This is because it appears you are setting the cookie server side, and as far as I know vercel only handles client side and will not let you use express.
I was under the impression that cookies were supposed to be set on the front end? But in the code the cookie is being set on the backend. And I don't see anything in the code that passes it to the front end. I thought I would find something on the front end like that would have a "upon successful login, execute cookies.set("x-auth-token", res.body.token)"
Cookies can actually be set through headers (Set-Cookie: <cookie-name>=<cookie-value>), which is what express's res.cookie does. MDN's article on the Set-Cookie header says:
The Set-Cookie HTTP response header is used to send a cookie from the server to the user agent, so the user agent can send it back to the server later. To send multiple cookies, multiple Set-Cookie headers should be sent in the same response.
It's odd to me that it works locally at all. Would someone mind explaining how this works? I thought cookies were stored in the browser on the client side. But if that was true, why does cookie-parser even exist in express and why is it being used server side?
Cookies are, in fact, stored client-side. They are accessible through client side javascript and backend with the cookie header. The cookie-parser module is needed to parse the name=value syntax sent by the Cookie header (Cookie - HTTP | MDN). It's being used server-side becuase validating cookies in the frontend can let any user give a false "true" value to your if statement that you use to validate cookies.
As an answer to the question: I recommend backend because JWTs have to be signed, and setting and signing them client-side will let anyone sign an arbitrary payload.
I have a server that stores session cookies and you can log onto it using a page (foo.com/login.html) that runs in the browser. The browser then stores a session cookie for this domain.
Now I want another page (bar.com) upon initialization to make a GET request using JavaScript to the first page (foo.com/authenticate) which should check if a session cookie exists in the browser and validate it, if correct he should respond with the session's username (however this is retrieved from the cookie). Of course I cannot check in bar.com's JavaScript if there exists a session cookie for foo.com.
Trying to solve this I ran into a few problems, one of which is of course CORS. I managed to avoid this problem by placing a reverse proxy in front of foo.com that adds all required CORS headers to the response. besides adding the headers, the proxy only tunnels requests through (eg. rev-proxy.com/authenticate -> foo.com/authenticate)
Now when I call the handler through the rev proxy from just another browser window directly (eg. rev-proxy.com/authenticate), I get the correct response. The handler from foo.com's backend finds the session cookie, reads out the username and passes it back. BUT when I try to make the same call from JavaScript inside bar.com (fetch("rev-proxy.com/authenticate")), I receive null, meaning he did not find the cookie (note that the request itself has status 200, meaning it did reach the backend of foo.com).
I have the feeling I am missing a crucial point in how cookies are used by browsers but I cannot find any useful information on my specific problem since I believe it is a rather unusual one.
See the MDN documentation:
fetch won’t send cookies, unless you set the credentials init option. (Since Aug 25, 2017. The spec changed the default credentials policy to same-origin. Firefox changed since 61.0b13.)
I'm using document.cookie go get cookie value of website, but it cannot get all cookie values.
Example session cookie sid, I can see it in Google Chrome Cookie Manager, but cannot get value by javascript.
How I can set cookie by javascript but it does not display in document.cookie (still send these value to server in request header)?
Answer copied from github: https://github.com/expressjs/session/issues/274#issuecomment-185308426
Your cookie is likely set to httponly: true. This is the default value. If you, or anyone else reading this doesn't already know, it can be unnecessary and a bad decision to set this value to false.
Search for "httponly cookie" and you'll find some good explanations of why you wouldn't want Javascript to have access to cookies.
Also make sure that the cookie you are trying to access is in the scope of the document from where you are trying to access the cookie.
The Domain and Path directives define thescope of the cookie: what URLs the cookies should be sent to.
Domain specifies allowed hosts to receive the cookie. If unspecified, it defaults to the host of the current document location, excluding subdomains. If Domain is specified, then subdomains are always included.
For example, if Domain=mozilla.org is set, then cookies are included on subdomains like developer.mozilla.org.
Path indicates a URL path that must exist in the requested URL in order to send the Cookie header. The %x2F ("/") character is considered a directory separator, and subdirectories will match as well.
For example, if Path=/docs is set, these paths will match:
/docs
/docs/Web/
/docs/Web/HTTP
source: https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies#Scope_of_cookies
I am going crazy with cookies and ajax call.
My configuration is simple. I run a website on 8282 port, (localhost.com:8282). My website calls some webservices on 8080 port (localhost.com:8080). Of course I add a line in my hosts file to avoid localhost trouble :
127.0.0.1 localhost.com
I try to set a cookie when the webservice is called with ajax. Here is my response header that I can see with Chrome debugger :
Set-Cookie:token=Custom eyJ0aW1lc3RhbXAiOiIxNDI0NzE5Mzc5ODY3IiwgImlkIjoiNTRlNzZkZGU2ZDk3ZGM1MjYxZjQzMzFlIiwgInNpZ25hdHVyZSI6Im5tZnFGeEEvYlc0TFJGNFJNb3dBZXJZOUw0aWw0aEorcFh1YUt5b3VFK0k9In0=;domain=.localhost.com;path=/;
The cookie is never stored by Chrome. However, when I use Rest client extension and I call the same webservice, the cookie is stored by Chrome ! So my cookie is well formed but is not stored with ajax call.
It's likely an issue with CORS (Cross Origin Resource Sharing, i.e the fact that the domain of the client and of the target of the AJAX call are not the same). For cookies to work well in a CORS configuration, you need to set the withCredentials flag to true. How to do so varies depending on you AJAX library (if you're using one).
See here: http://www.html5rocks.com/en/tutorials/cors/
In your close reponse of ajax you can set your cookie
document.cookie = "token=Custom eyJ0aW1lc3RhbXAiOiIxNDI0NzE5Mzc5ODY3IiwgImlkIjoiNTRlNzZkZGU2ZDk3ZGM1MjYxZjQzMzFlIiwgInNpZ25hdHVyZSI6Im5tZnFGeEEvYlc0TFJGNFJNb3dBZXJZOUw0aWw0aEorcFh1YUt5b3VFK0k9In0=;domain=.localhost.com;path=/";
Can an AJAX response set a cookie?
Looking for an accepted practice for setting browser cookies within a JSON and Ajax based web application.
The browser seems to not accept cookies from the server for JSON requests. This leaves me with two options that I can see:
When doing operations that need to involve cookies, do not use JSON requests, but rather evaluate the JSON after the text gets to the client using JSON.parse()
Send the cookie information from the server to the client via JSON, then use the browser to set the cookie instead of through server heads. Does this also mean that the cookie information will have to be read on the client and sent back to the server via JSON because the browser will not send cookie information via AJAX JSON requests as well?
My inclination is to go with option #1, but these both seem pretty crappy options. Am I missing something here?
Thanks!
Cookies are sent only if the Domain property matches the domain you are on.
So for example you set a coockie with the domain '.domain.com'. Any requests made to domain.com or any subdomain will contain the cookie, but only that.
For request to other domains you need the coockie set serverside or if the user interacts with a page that sets a cookie for that domain.
2 simple ways to set the cookie that came to mind are:
Obviously, make a ajax call to a script to set the cookie
Do something like this:
HTML:
<script type="text/javascript" src="http://domain2.com/cookie_login_page.php?username=johnsmith&hash=1614aasdfgh213g"></script>
PHP:
<?php
// ... setCookie stuff
echo 'var cookie_set = true;';
?>