Automatic logout in python web app - python

I have a web application in python wherein the user submits their email and password. These values are compared to values stored in a mysql database. If successful, the script generates a session id, stores it next to the email in the database and sets a cookie with the session id, with allows the user to interact with other parts of the sight.
When the user clicks logout, the script erases the session id from the database and deletes the cookie. The cookie expires after 5 hours. My concern is that if the user doesnt log out, and the cookie expires, the script will force him to login, but if he has copied the session id from before, it can still be validated.
How do i automatically delete the session id from the mysql database after 5 hours?

You can encode the expiration time as part of your session id.
Then when you validate the session id, you can also check if it has expired, and if so force the user to log-in again.
You can also clean your database periodically, removing expired sessions.

You'd have to add a timestamp to the session ID in the database to know when it ran out.
Better, make the timestamp part of the session ID itself, eg.:
Set-Cookie: session=1272672000-(random_number);expires=Sat, 01-May-2010 00:00:00 GMT
so that your script can see just by looking at the number at the front whether it's still a valid session ID.
Better still, make both the expiry timestamp and the user ID part of the session ID, and make the bit at the end a cryptographic hash of the user ID, expiry time and a secret key. Then you can validate the ID and know which user it belongs to without having to store anything in the database. (Related PHP example.)

Related

Flask session expiration and CSRF

I would like to have a Flask session where the session cookie expires after 2 weeks regardless of activity.
I can get this to work without CSRF by setting:
SESSION_REFRESH_EACH_REQUEST=False
but this doesn't work when I enable CSRF.
With CSRF, the CSRF token is updated in the session for each request which causes the session expiration to be reset.
It seems that the only way to make the session expire after 2 weeks is to do it yourself (e.g., store the login date in the session or user database and deleting the session when the login date is more than 2 weeks old).
This seems like a common requirement so just curious if I am missing something?
The only way is to store date somewhere and then every day check if it has been >= 2 weeks since the stored date

flask-security make user always signed in

Im trying to make it so a specific user is always logged in using the flask security extension.
I cant find any docs on this.
Can someone point me in the right direction to start.
https://flask-login.readthedocs.io/en/latest/#cookie-settings
“Remember Me” functionality can be tricky to implement. However, Flask-Login makes it nearly transparent - just pass remember=True to
the login_user call. A cookie will be saved on the user’s computer,
and then Flask-Login will automatically restore the user ID from that
cookie if it is not in the session. The cookie is tamper-proof, so if
the user tampers with it (i.e. inserts someone else’s user ID in place
of their own), the cookie will merely be rejected, as if it was not
there.
REMEMBER_COOKIE_DURATION
The amount of time before the cookie expires, as a datetime.timedelta
object. Default: 365 days (1 non-leap Gregorian year)

flask Set Cookie for every response

I use flask session in my app. In one of my handler I set session value and no session set in other handlers. But I found that in every response there is a http header: Set Cookie exists. Why does that happen?
app = Flask(__name__)
app.secret_key = r"A0Zr98j/3yX R~XHH!jmN'LWX/,?RT"
#app.route('/auth/login', methods=['POST'])
#crossdomain(origin='*')
def authlogin():
user = User(username=username, registered_at=sqlnow())
user.accounts = [Account(provider='weibo', access_token=access_token, uid=uid)]
account = user.accounts[0]
session['user_id'] = account.user_id
return jsonify({
'status': 'success',
'data': {
'user_id': account.user_id,
'uid': account.uid
}
})
#app.route('/api/movies/<movie_type>')
def moviescoming(movie_type):
if movie_type == 'coming':
return getmovies(MOVIE_TYPE_PLAYING, offset, limit)
else:
return getmovies(MOVIE_TYPE_COMING, offset, limit)
app.run(host='0.0.0.0', debug=True)
Code shows here:
https://github.com/aisensiy/dianying/blob/master/index.py
The Short Answer:
This is by design, but a recent change in Flask allows you to change this behavior through use of the SESSION_REFRESH_EACH_REQUEST option. As of the posting of this answer, that option is not yet in a stable release of Flask.
The Long Answer
Let's back up and discuss how cookies are supposed to work to begin with:
Cookies as a Standard
RFC 6265 defines that a cookie should expire when the agent (the browser) declares the session closed (typically, when the browser is closed), unless there was provided some mechanism to tell the browser when the cookie should actually expire:
Unless the cookie's attributes indicate otherwise, the cookie [...]
expires at the end of the current session (as defined by the user
agent).
[...]
If a cookie has neither the Max-Age nor the Expires attribute, the
user agent will retain the cookie until "the current session is over"
(as defined by the user agent).
If the server wishes a cookie to survive an agent restart, they need to set an expiration. Note that the Expires attribute is typically preferred due to the fact that Internet Explorer has a history of poor support for max-age.
Creating Permanent Cookies
So, it's impossible to say that a cookie should be "permanent". When people talk about a "permanent" cookie, what they really are talking about is a cookie that survives a browser restart. There are two strategies that I know of for creating this "permanent" cookie:
Set the cookie's expiration to something that is good enough to be considered permanent (such as the year 9999).
Set the cookie's expiration to something relatively recent in the future (e.g., 31 days), but every time the cookie is used update the expiration again. For example, on January 1st we will set the cookie to expire on February 1st, but then when the user uses the cookie on January 2nd we are updating the cookie (by using Set-Cookie) to have it expire on February 2nd.
The first method requires the Set-Cookie header to only be set to the client once (unless the cookie contents need to change).
The second method would require the Set-Cookie header to be sent with every update so that the expiration is constantly "pushed off" as the user continues to use the service. Note that it also isn't really "permanent", as a user that does not use your site for over 31 days will have their cookie expire.
RFC 6265 does have a bit to say on defining the expiration date:
Although servers can set the expiration date for cookies to the
distant future, most user agents do not actually retain cookies for
multiple decades. Rather than choosing gratuitously long expiration
periods, servers SHOULD promote user privacy by selecting reasonable
cookie expiration periods based on the purpose of the cookie. For
example, a typical session identifier might reasonably be set to
expire in two weeks.
So, while it doesn't explicitly say whether or not to be constantly updating the expiration date, it does seem to say that using a far-future date should NOT be considered a good practice.
Flask's Implementation of "Permanent Cookies"
Flask uses the second method (constantly updating the cookie expiration with Set-Cookie) by design. By default, the expiration of the cookie will be 31 days in the future (configurable by PERMANENT_SESSION_LIFETIME). With every request, Flask will use another Set-Cookie to push the expiration out another 31 days (or whatever you set your permanent session lifetime value to). Therefore, the Set-Cookie on every request you see is expected, even if the session has not changed.
Recently, however, there has been a discussion in a pull request regarding using Set-Cookie only when the cookie changes. This resulted in a new feature that allows the user to change how this works. Flask will continue to work as it has, but the user can set a new SESSION_REFRESH_EACH_REQUEST option to False, which will cause the Set-Cookie header to only be sent when the cookie changes.
The new item is documented as:
this flag controls how permanent sessions are refresh [sic]. If set to
True (which is the default) then the cookie is refreshed each
request which automatically bumps the lifetime. If set to False a
set-cookie header is only sent if the session is modified. Non
permanent sessions are not affected by this.
This new option, together with the existing PERMANENT_SESSION_LIFETIME, allows Flask developers to better tune exactly how their "permanent" cookies will be set to expire.
As of this answer's posting date (December 24th, 2013), the SESSION_REFRESH_EACH_REQUEST option has not been part of any Flask release, and therefore users wishing to use it will need to wait for a future Flask release.

Is cookie a common and secure implementation of session?

I'm using pyramid web framework. I was confused by the relationship between the cookie and session. After looked up in wikipedia, did I know that session is an abstract concept and cookie may just be an kind of approach (on the client side).
So, my question is, what's the most common implementation (on both the client and server)? Can somebody give some example (maybe just description) codes? (I wouldn't like to use the provided session support inside the pyramid in order to learn)
The most common implementation of sessions is to use a cookie.
A cookie provides a way to store an arbitrary piece of text, which is usually used as a session identifier. When the cookie gets sent along with a HTTP request, the server (technically the code running on it) can use the cookie text (if it exists) to recognise that it has seen a client before. Text in a cookie usually provides enough information to retrieve extra information from the database about this client.
For example, a very naive implementation might store the primary key to the shopping_cart table in a database, so that when the server receives the cookie text it can directly use it to access the appropriate shopping cart for that particular client.
(And it's a naive approach because a user can do something like change their own cookie to a different primary key and access someone else's cart that way. Choosing a proper session id isn't as simple as it seems, which is why it's almost always better to use an existing implementation of sessions.)
An alternate approach is to store a session identifier is to use a GET parameter in the url (for example, in something like http://example.com/some/page?sid=4s6da4sdasd48, then the sid GET param serves the same function as the cookie string). In this approach, all links to other pages on the site have the GET param appended to them.
In general, the cookie stored with the client is just a long, hard-to-guess hash code string that can be used as a key into a database. On the server side, you have a table mapping those session hashes to primary keys (a session hash should never be a primary key) and expiration timestamps.
So when you get a request, first thing you do is look for the cookie. If there isn't one, create a session entry (cookie + expiration timestamp) in the database table. If there is one, look it up and make sure it hasn't expired; if it has, make a new one. In either case, if you made a new cookie, you might want to pass that fact down to later code so it knows if it needs to ask for a login or something. If you didn't need to make a new cookie, reset the expiration timestamp so you don't expire the session too soon.
While handling the view code and generating a response, you can use that session primary key to index into other tables that have data associated with the session. Finally, in the response sent back to the client, set the cookie to the session key hash.
If someone has cookies disabled, then their session cookie will always be new, and any session-based features won't work.
A session is (usually) a cookie that has a unique value. This value maps to a value in a database or held in memory that then tells you what session to load. PHP has an alternate method where it appends a unique value to the end of every URL (if you've ever seen PHPSESSID in a URL you now know why) but that has security implications (in theory).
Of course, since cookies are sent back and forth with every request unless you're talking over HTTPS you are sending the only way to know (reliably) that the client you are talking to now is the same one you logged in ten seconds ago to anyone on the same wireless network. See programs like Firesheep for reasons why switching to HTTPS is a good idea.
Finally, if you do want to build your own I, was given some advice on the matter by a university professor. Give out a new token on every page load and invalidate all a users tokens if an invalid token is used. This just means that if an attacker does get a token and logs in to it whilst it is still valid when the victim clicks a link both parties get logged out.

What is the best way to implement a 'last seen' function in a django web app?

I have a running django/apache2 + memcached app (ubuntu) and would like to keep track of logged in users that are online.
What would be the best way to track this?
I would prefer not writing to the database each time a logged in user loads a page; but what other options are there?
An approach might be:
you create a middleware that does the following on process_response:
check for a cookie called 'online', but only if the user is authenticated
if the cookie is not there,
set a cookie called 'online' with value '1'
set the lifespan of the cookie to 10 minutes
update the 'last_login' field of auth.User for this user with the current datetime
now you have all currently logged in users in your auth.User table. All Users that have a last_login newer than datetime.now()-interval(15minutes) might be considered "online".
The database will be written for every logged in user about every 10 minutes. Adjust the values "10" and "15" to your needs.
The advantage here is that database writes are rare (according to your two numeric settings 10/15). And for speed optimization make sure that last_login is indexed, so a filter on this field including Count is really fast.
Hope this helps.
A hashmap or a queue in memory with a task running every hour or so to persist it.
You need to persist the info server-side, integrity isn't critical, throughput and latency are important. That means you should use some sort of key-value store.
Memcached and redis have keys that expire. You probably have memcached already installed, so use that.
You can reset expiry time of the user:last-seen:$username key every visit, or you can use mawimawi's cookie technique and have expiry = 4 * cookie-lifetime.
You can't do that in django without using a database/persistent-storage because of the same reason why django sessions are stored in database: There can be multiple instances of your applications running and the must synchronize their states+data through a single persistence source [1]
Alternatively, you might want to write this information in a folder in a file named with user id and then check its create/modified date to find the required information.

Categories

Resources