Flask sessions, where are the cookies stored? - python

I'm learning flask and want to understand how sessions work.
Apparently the server stores a signed cookie on the client browser.
I have done this process using
sessions['mycookie'] = 'mycookievalue'
But I'm unable to find the cookie on the browser. I normally list cookies on the browser using chrome developer tools and running the command:
document.cookie
This works when I set a cookie but nothing comes up when I set it through sessions.

The Flask session cookie has the httponly flag set, making it invisible from JavaScript.
It is otherwise a normal, regular cookie so it is still stored in the browser cookie store; you should still be able to see it in your browser's developer tools.
You can set the SESSION_COOKIE_HTTPONLY option to False if you want to be able to access the cookie value from JavaScript code. From the Builtin Configuration Values section:
SESSION_COOKIE_HTTPONLY
controls if the cookie should be set with the httponly flag. Defaults to True.
The cookie contains all your session data, serialised using JSON (with tagging support for a wider range of Python types), together with a cryptographic signature that makes sure the data can't be tampered with securely.
If you disable the httponly protection, any JS code could still decode and read all your session data. Even if it can't change those values, that could still be very interesting to malicious code. Imagine a XSS bug in your site being made worse because the JS code could just read a CSRF token used to protect a web form straight from the session.

I am finding this question 3 years and 8 months later because I have an interest in the event it is modified or spoofed, to ensure my backend is able to tell the difference.
Using chrome, use F12, select Application tab, underneath Storage go to Cookies. Under cookies you'll find the webpage, select it and the right side will populate and assuming you have done something to create your session cookie, it will be there. You will notice that the value is encrypted.
Picture showing the location of session cookie

sessions are meant for server use only. That is why it is hidden and encrypted for the client.
If you want to set a cookie which can be used by client/browser. You can just set a normal cookie instead of a secure cookie (like session).
You can set cookies by modifying response.
def home_page():
resp = make_response(...)
resp.set_cookie('my_cookie', 'cookie_value')
return resp
document.cookie on browser will give you mycookie=cookie_value

Related

Python requests session and cookies

I am a lot confused about cookies.
I am trying to work out scraping with many post/get requests chained
And I notice that every step needs 'Cookie' evaluated in the headers dictionary, because passing the right dictionary is the only way I don't get any access errors.
However, I look always at my cookie jar (via .cookies method) as it was at the previous step, but I cannot find what I need for the current step. And I know that by inspecting the network data in my browser.
So how shall I build up step by step a chain like 1) login, 2) botton interaction for changing dates, 3) file downloading?
My fault is that I am using requests instead of selenium?
I already use requests.Session().... but this means that I don't need to show up Cookie field when sending headers? Either way (showing or not showing Cookie in headers) I get server access error AFTER having correctly logged in...
Thanks,
David
If you cant access your cookies probably the login credentials are stored in an HTTP Only cookies. This is a secure place to store them to prevent CSS attacks.
You should try using a requests session to send this cookies along with your future requests.

why doesn't request lib provide all cookies

I'm not understanding why the python requests library isn't pulling in all cookies. For examples, I am running this code
import requests
a_session = requests.Session()
a_session.get('https://google.com/')
session_cookies = a_session.cookies
cookies_dictionary = session_cookies.get_dict()
print(cookies_dictionary)
But I only get the cookie "1P_JAR" even though there should be several cookies.
list of cookies shown up on inspector pannel
Ultimately I'm trying to figure out why its choosing only that 1 cookie and not the others because I'm trying to build my own application that generates a cookie but when I run this script on my application I get back and empty list even though the inspector shows that I have generated a cookie.
A cookie is set by a server response to a specific request.
Your basic google.com request only sets that cookie, which you can observe by the set-cookie header.
The other cookies are probably set by other requests or even the js code. Requests doesn't evaluate or run js and thus doesn't make any other requests.
If you don't want to completely reverse engeneer every single cookie, the way to go would be to simulate a browser by using Selenium + Chrome Driver or a similar solution.

If Pyramid sessions are one-way hashed and not stored server-side, where is the data coming from?

When using the SignedCookieSessionFactory, the documentation states that the sha512 HMAC digest algorithm is used. As a result of this, once session data is serialised, it is signed and sent to the user's client under the session cookie.
There is no mention in Pyramid's documentation that sessions are also cached server-side (under this SessionFactory).
This presents a contradiction and has also led to authentication confusion when paired with SessionAuthenticationPolicy. If session data cannot be retrieved from the client's session cookie (as it is one-way hashed), how is it that the following is possible?
Authenticate with the application such that reading Request.authenticated_userid does not return None.
Copy the session cookie to the clipboard.
Logout by accessing a view whereby the headers from forget(request) are returned in the Response.
Replace the session cookie with the copied value.
The user is now logged back in.
I understand that simply deleting the cookie client-side is insufficient to completely invalidate the session (without blacklisting), but this then poses the following questions:
How is it possible to remain secure with browser-scoped sessions unless every session cookie the user has recently been issued is somehow remembered and blacklisted/invalidated?
Is the session cookie actually a key/session ID that's being used to lookup a session in memory? As it's one-way signed, surely this is the only explanation?
Is it possible then to invalidate sessions server-side, a little more robust than just the headers=forget(request) pattern?
Ultimately, I imagine the answer is something along the lines of:
"Maintain server-side sessions using an include such as pyramid_redis_sessions"
Any explanation would be appreciated.
The cookie contains all of the data. The session content itself is stored in the cookie, alongside an hmac signature of that content. This means that a client may view the content if they try hard enough, but they cannot change it as they cannot create trusted signatures without the server-side secret.
How is it possible to remain secure with browser-scoped sessions unless every session cookie the user has recently been issued is somehow remembered and blacklisted/invalidated?
It depends what you're using the session for - you need to take these issues into consideration before putting data into a session object.
Is it possible then to invalidate sessions server-side, a little more robust than just the headers=forget(request) pattern?
Not unless you store some sort of id in the session and then a server-side table of blacklisted ids. If you did this then you could write your own wrapper session-factory that opened the session, checked the id, and returned an empty one if it was blacklisted. Of course then you might just want to use a server-side session library like pyramid_redis_sessions or pyramid_beaker with one of its server-side-storage backends.

Python + Flask - Removing key from session too fast

I have and API service that make this:
session[parent].pop(child)
But, when I call this service more than one time and at the same time in Browser, this seems too fast for Flask (or Python, or I don't know). Just one 'child' is removed. I tried to use
del session[parent][child]
but the problem was the same. I can get a list of values in my API Service to resolve that, but, I want to understand why this is happening.
I don't know if it is a Flask problem, a Python problem, a 'Web Stuff' problem...
It's a 'Web Stuff' problem.
What happens is that the browser stores the last version it received. But if it receives responses out of order, or you abort a request before it is completed, the browser won't be storing that version.
Flask stores the data for session entirely in a cookie. There is nothing stored on the server side other than the server-side secret used to encrypt and decrypt the contents.
A response with that cookie is sent to the browser, and the browser stores the cookie. This is an entirely opaque piece of data to the browser, it cannot do anything with it as it is compressed and cryptographically signed.
The browser will then send that cookie as is back to the Flask server every time a request is made. If the response to that request contains a new version of the cookie, then that'll be stored in the browser cookie storage. Any new request started after storing will then use the new cookie.
If however, you start a request before a response has been fully processed, or did not complete handling the response, then an older cookie could be used and your server decodes that older version with the changes not made.
Just set session.modified = True each time you modify your session.
This tells flask to update session after request.

Google app engine suas cookies not expiring

When using suas in GAE and setting the flash_msg, for some reason the cookie does not expire. The symptom is that no mater how many times I refresh the page the flash message is always there. When I debugged with chrome I can see that the expiration the flash_msg cookies was set to session. Even more troubling I found that all cookies expiry are set to session. Any idea? The only change I made to the SUAS code was removing the error raising in
def __ParseString(self, str, patt=Cookie._CookiePattern):
Also note that the flash_msg cookie has a domain other then "/".
Update:
All the variables being session-ed are because they were meant to. SUAS has a persist variable that sets if the cookies will be session cookies or persist. As a work around for the flash messages I use the jQuery plug in for cookies and just delete the guys after I display them.
Those cookies do not expire on page load. They expire when the browser closes. What you need to do is at every page load, if flash is in session, display it and then force remove it from the session (on the server side).

Categories