"Refresh" Django session variables to avoid session timeouts? - django

I have a multi-page Django signup process in which a user goes through the following steps:
Create an account (username, password)
Create a profile
Upload a photo
Review and approve/change profile and photo
Pass username and user ID to payment processor
Receive "Payment OK or Payment not OK" signal from payment processor
Log user in if "Payment OK" and display website's "home" page.
In step 1 above, the user's ID and a couple of other pieces of information are stored in a session. They're then examined when necessary during steps 2 through 4. The user ID and username will also be passed to the payment processor in step 5. I'm thinking of setting the session timeout period to either 30 minutes or an hour. Here's my question. Should I read and re-assign the session variables when the user GETs each of the above pages in order to help the user avoid having their session timed out? The Django documentation says Django only saves a session when the session has been modified (i.e. when any of the dictionary values have been assigned or deleted). I'm thinking that if I "refresh" the user's session as they move from page to page, it will be less likely that they'll be timed out and will thus experience a smoother signup process.
Any advice? Thanks.

There's SESSION_SAVE_EVERY_REQUEST setting that saves session and sends session cookie with every request, effectively turning session into sliding expiration session (btw, it's a widespread name for what you want to achieve)
Refer to session docs for details

Related

Flask + Stripe - how can I prevent people from accessing my successful checkout page without making a payment?

Basically I understand how to integrate Stripe payment into Flask, I'm using the official website (https://stripe.com/docs/payments/accept-a-payment?integration=elements) as a guide. In the guide the user is taken to a success page after the payment is successful. What I want to do upon a successful payment is collect the user's email, create a randomized password, and then email that password to the user. I've learned how to grab information from the session id using this page (https://stripe.com/docs/payments/checkout/custom-success-page). What I'm concerned about is that a user might go to the success page, get an account, and bypass the required payment.
My idea to solve that is to get the session info using this line:
session = stripe.checkout.Session.retrieve(request.args.get('session_id'))
and then before doing anything else check if it's none. If it's none, it will display an error page, if it is not none then it will create an account for the user. Would that work? Or would people just be able to change the session_id in the url until they find a number that is a valid session?
If that doesn't work, all I really want to do is upon successful payment create an account for the user using their email and a randomized password. How do I do that?
You're on the right track. Generally the flow is:
Customer is redirected to Checkout
Customer pays
Checkout redirects customer back to your success_url
You fetch the Checkout Session using the ID in the URL to confirm a valid payment
For #4 you can do various things to make sure people can't guess a Checkout Session ID (which would be unlikely due to their length and complexity). I suggest checking to see if the successful payment happened within a certain timeframe, like the past hour or past day, for example.

What happens if a user turns off Cookie within a GA session

I am curious what happens if a user starts a GA session and let's say 1 minute later, the user turns off the Cookie, how is the information of that Session being recorded on GA?
I am curious if this would be the reason for the observation shown as the last record below:
As for the last record, I have 1 user but 0 session or 0 pageviews.
The first column is a user level customer dimension which indicates the user's Business Persona. The Persona information is passed from GTM via a data layer variable.
Any insight on the Cookie question as well as the abnormality observed above?
Thanks!
Yao
If the user has already entered on your site, then the session has started, because page view hit was sent to GA. Hit can't be recalled. Turning off the Cookie can affect only on next hits.
What about events? Events without page view don't start session. Sessions will be 0, but user will be counted.

How to force logout when Knox created token has expired?

I developed my Django based webapp with token authentication by following this tutorial of Brad Traversy (https://www.youtube.com/watch?v=0d7cIfiydAc) using Knox for authentication and React/Redux for the frontend. Login/logout works fine (here is Brad's code: https://github.com/bradtraversy/lead_manager_react_django/blob/master/leadmanager/frontend/src/actions/auth.js --> logout using a POST request), besides one issue: When the user stays away from the computer for a long time, the token expires in the meanwhile. So when the user returns he is still in the logged in zone of the website, but as soon as he opens a React component with data loading from the DB a 401 error is thrown in the console ("Failed to load resource: the server responded with a status of 401 (Unauthorized)"). Then the user has to go on "logout" and login again.
This is not optimal, I would prefer that after the user returns, the system realizes the token expiry and logs the user automatically out. I have thought of the following approaches, but I am not sure how to implement it or which one is best:
1) For every API request: if the answer is 401 --> logout (this might also log the user out in case the token has not expired, but if there is some other permission problem) - seems not optimal to me.
2) Instead one could also create a testing route e.g. api/auth/check with a Django view including the typical check
permission_classes = [permissions.IsAuthenticated]
and if 401 returned --> logout. So that would mean for every database request I have another rather unspecific database request before.
3) Check at every API request specifically if the token has expired --> how to do it? In the docs (https://james1345.github.io/django-rest-knox/) I couldn't find a method to check token validity. I see in the database table "knox_authtoken" an expiry date and a huge code in the column "digest", but this is obviously encrypted data and cannot be compared with the token value that one has in the browser under local storage.
I would be glad to receive recommendations on how to best implement this!
This can be done in multiple ways.
I dont see the reason kicking a user out automatically, but if you want to do that you can either:
Create an URL which will be only for checking if the authentication is valid every 5 secs or so
Use web sockets to send a realtime message once the token has expired.
Put the logic in the frontend, for example store how long the token is valid, and run a timeout, after the timeout is finished relocate him to login.
Jazzy's answer - option 3 - brought me on the right way (thank you!), but working with timers on the frontend side, was initially not successful, since starting a timer within a React component would only run as long as this component is visible. I have no component that is visible all the time of the user session. I changed the expiry duration of the token within Django settings from default value of 8 hours to 72 hours and implemented an idle check on the frontend with this package: https://www.npmjs.com/package/react-idle-timer . So as soon as my application is not used for 2 hours I call the logout action (api/auth/logout). With this approach I don't need to care about the expiry time of the token on Django side, since no user will be active throughout 72 hours. As soon as he logs in again, he will receive a new token.
New solution:
I decided to not bother users too often with logging in and found this nice strategy:
we choose to never expire Knox tokens
we set expiry date for Django session to 90 days from last login
if user does not log in for > 90 days, he will make at some point a request to the backend (e.g. data requests), there we include a check if the session data is available
if 'some_session_variable' in request.session:
# whatever logic you need
else:
return HttpResponse("logout")
Since session variable will not be available after the expiry the 'logout' string is returned. On the frontend we check every response for 'logout' string. If it is being returned we initiate the logout process. The idle timer is not used anymore (as it is not so reliable in my experience).

Python Flask Session with Login

Is it possible to create Flask Sessions without Login Fields, For Example user can enter only Email address in User Name Field, which will create Session with certain expiration time, till the session is active, User2 cannot create session with same name.
Any help is highly appreciated.
At first flask by default do not store session on server - only safe cookies.
If you want use email as id (user.get_id() method) you can't. But you can create special cache (dict or etc) on server with active sessions and use unique keys as id and do not login users with exist email.

Detecting user logout on browser close in Django

we have a web service for some numerical computing. It has a registered mode, in which a user has to register to have its results sent by mail.
We would like to keep track of how long the user stays logged. The login time is written in the database upon successful registration. Registration in not permanent, it's just for the purpose of single session and is used for acquiring the user email.
There are a few situations possible:
User logs out normally via the logout button.
Simplest solution. Write the time and logout in the database, and delete session.
User logs out by session expiry.
I'm planning on having a script which would check all the database entries which don't have a set logout time and if current time - login time > expiry time write logout time in a database as login time + expiry time.
User logs out by browser close.
The sessions have a get_expire_at_browser_close() set to True. But i don't know how can the server detect browser closure.
Ideas, critics, comments?
In django session middleware these lines control session expiration if we want that SESSION_EXPIRE_AT_BROWSER_CLOSE:
if settings.SESSION_EXPIRE_AT_BROWSER_CLOSE:
max_age = None
expires = None
Server doesn't have to do detect anything as cookie that has no max_age or expires set should be deleted on the client side, according to this page:
By setting either of these, the cookie will persist until its time runs out, otherwise—if you set neither—the cookie will last until you close your browser (a “session cookie”).
Edit:
One way of tracking how long user was online is by using javascript that will ping server every now and then. It will happen only as long as the user has page opened in browser and on every ping server should update last seen online value for the user.
When user closes browser session is over. Next time user logs in server can calculate duration of his last visit as last seen online - last login time.
Simpler solution without using any javascript: last seen online could be updated on every user request using simple custom middleware.