Cookies
- At a high level, a cookie is simply a piece of state (key/value pair) that the server asks the browser to store
- Browser returns that key/value pair upon next visit to that site
- Can be as simple/trivial as remembering a color/language preference.
- Today cookies form the foundation of sessions. (More on that later.)
- Also used for tracking :(
- Background: The web was originally designed to be stateless; but, that can (obviously) be inconvenient.
- HTTP itself is stateless. Any necessary state must be maintained by either the browser or the server.
- Client has to remember something. Even if most data is on the server, we need a way for the server to
know who is “talking” to it.
- Cookies are sent in request and response headers
- Run
BasicHTTPSTransaction
(which connects to wwww.gvsu.edu
) and notice the Set-Cookie
header
- Open Incognito window in Chrome.
- Visit
wwww.gvsu.edu
; Watch response headers
- Reload the page. Notice request
Cookie
header.
- Check out https://faculty.computing.gvsu.edu/kurmasz/simpleCookie.php
- Cookie properties: https://www.php.net/manual/en/function.setcookie.php
name
: The key in the key/value pair
value
: The value in the key/value pair
expires
: When the cookie expires (i.e., when the browser deletes it)
- Sent as a UNIX timestamp (e.g.,
Thu, 20-Feb-2020 16:03:58 GMT
)
- Most frameworks will generate this string for you.
- If no expires value is given, cookie expires when the browser session ends.
- This is one reason some web sites suggest you close your browser when finished.
- But some browsers now restore sessions. When in doubt, set up an explicit expiration.
path
: The path on the server where the cookie is available.
- If set to
/Teaching/Courses/CIS371
, then cookie only visible to files in that directory or below.
- Defaults to
/
(at least in Express) which means all files on server see cookie
domain
: The (sub)domain that the cookie is available to.
- For example, should a cookie set on
cis.gvsu.edu
be available to www.gvsu.edu
?
secure
: Only return cookie over HTTPS
.
- This affects browser only. It is the server’s responsibility to decide whether to send a cookie.
- “secure” cookies will be sent to localhost over http.
httponly
: When true
cookie is not accessible through JavaScript.
- To “delete” a cookie, just give it an expiration time in the past.
- Rails interface to cookies: https://api.rubyonrails.org/v6.0.2/classes/ActionDispatch/Cookies.html
- TLDR: Treat an object named
cookies
as a hash within a controller.
- Express interface to cookies: https://expressjs.com/en/api.html#res.cookie
- Walk through https://github.com/kurmasz-SampleCode/CIS371-SampleCode/tree/master/Cookies
- listCookies
- setCookies
- set/list with path
- Show expiration
- Paths are especially important in a shared system (e.g., web pages like
~kurmasz
where my cookies could interfere with another student/professor)
- Remember:
- Browsers don’t have to accept cookies. Avoid using them for “mission critical” features.
- Browsers can also “lie” about cookie values. You can’t trust them.
- For example, if you set a product price as a cookie, the client might lower that price when visiting the site again.
- Tracking:
- How do cookies get abused?
- Remember, cookies are stored by domain. Suppose both
cutekittens.com
and petlife.com
both contain an image tag with a source of eviltracker.com
. Then any cookies set when visiting site will be returned when visiting the second. The tracker than then tell that a single user visited both sites. (This is how you can shop for something on Amazon then have ads pop up elsewhere.)
- This is what is meant by “third-party cookies”: You visit
a.com
and get asked to save/send a cookie from b.com
that has some kind of embedded content.
- Remember: Cookies sent to/from address in the request (i.e.,
eviltracker.com
). This is not
influenced by the address of the page that contains the link (e.g., cutekittens.com
or petlife.com
).
- Client side:
CookieStore
is a new JavaScript that allows you to access cookies in the browser
Session
- HTTP itself is stateless; but the server doesn’t have to be.
- Clear example: Servers that store data in a database.
- The server can remember a user’s data; but still needs some way of reliably knowing who the user is
during each request.
- Don’t want users to be able to easily fake their identity.
- Basic idea:
- Server sends a cookie with a long random string.
- That long, random string is a key to a set of data for that particular user.
- When the user visits another page, the cookie is returned and matched up with the data.
- Make sure string is long and random enough that it can’t be guessed.
- String is often encrypted/hashed data to detect tampering.
- Rails automatically sets up a session for you (whether you need one or not)
- Session data is stored in a special hash named
session
- For example, you can save the current user’s ID once she has logged in.
- By default, this data is sent in an encrypted cookie with every page.
- Because data is encrypted, you can trust that it hasn’t been modified
- call
reset_session
when necessary.
- Storing the session in the cookie is easiest (make sure it is “tamper-resistant”), but you can also
- To use sessions in Express, install the
express-session
package
- https://www.npmjs.com/package/express-session
- This package stores session data on the server not in a cookie.
- For production applications, read the documentation about session storage carefully.
- If you do store session data in a cookie (which you shouldn’t), make sure the
cookie is secure (i.e., encrypted) so that it is obvious if a user modifies it.
- Give session cookies a short expiration time.