Cookies are not saved. Set cookie in views - django

def myview(request):
item = Item.objects.all().count()
if not request.COOKIES.get('mycookie', None):
response.set_cookie('mycookie', item)
n = request.COOKIES.get('mycookie')
return render_to_response('index.html', {'n': n}, context_instance=RequestContext(request))
It seems that my cookies are not saved. What am I doing wrong?

When you set a cookie, this is a request for the client (the browser) to store this information in its cookie storage.
Highly simplified, it works like this:
You tell your code, set a cookie.
Your code tells the browser, hey set this cookie.
Browser says, okay its set.
On the next request, browser will send the cookie back to you.
It will be available for reading on any requests after the request where you set it. So when you refresh the page, the cookie will be "readable" by your code.

Related

flask-login reusable cookies

I am using Flask-login with remember=False (the only cookie is the session cookie). When copy-pasting the session cookie after logging out, for some reason the session is still valid and the user is logged in. Even though the logged out session was deleted properly in the flask logout_user() function - meaning that the ["user_id"] was deleted from the session dictionary. It seems like the session is restored from the old cookie. can someone explain?
I do not really have a right answer for this yet, as I am investigating it myself, but there are a couple of points I would like to make here:
the logout_user() from Flask-login does not really seem to be invalidating the session. It just changes the 'session' cookie's value in the client (the browser). While in the backend this session is still alive.
An experiment to prove this would be: (a simple browser plugin like CookieManager can be used to perform this exercise)
login to the app
take a note of the 'session' cookie's value post successful login
now logout
now observer the 'session' cookie's value again. And you would
notice that it has now changed.
Replace this value with the 'session'cookie's value previously noted
in step 1 above.
Try visiting an internal authenticated page again.
Result : You would successfully be able to view an internal page without re-logging in, proving that the logout_user() never really invalidated the session but just changed the 'session' cookie in the client.
Howeverm, I am myself still taking a look into flask-login logout_user() definition and trying to make sense of it.
I had This issue too. After diagnosing what i found is the decorator #login_required *does not invalidate the User in server side after logout*, which is a security threat. This will be a cake walk for a Hacker to hack your application since they can easily extract all the request and header data from developer tool of your browser and can again send request to you server from outside of the application.For ex: If you have used any API in your application the it will be very easy for Hacker to get all the request data and resend a request using POSTMAN.
I solved this issue by creating a separate decorator "#authentication_required" and used in place of "#login_required". then it worked for me,though #login_required is supposed to do the same.
So basically while logging in i generated a random string(token) and sent to database and same string(token) is added to session of flask i.e session["token"]="akhfkjdbfnd334fndf" use any random string generator function.(session object is globally available if u r using flask . u can very well add any field to session). and while logout i again generate a string(token) and update the old token with newly generated token in database. So what #authentication_required will do is it will get the token from session object and the token which is present in database and try to compare the value. if both are same then only #authentication_required will let the client access api.and dont forget to do session.clear() after logout_user().
#---------------------------------------------------------------#
##authentication_required definition
def authentication_required(f):
#wraps(f)
def wrap(*args, **kwargs):
try:
user_id=session['user_id'] #assigning "user_id" from flask session object to a variable "user_id"
user=User_table.find_first(_id=user_id)#couhdb query syntax
#comparing api_token sent to session object at the login time with api_token in sent to database at login time. If both doesn't matches then user is redirected to login page.
if not session["token"]==user.token:
return redirect(url_for('login'))
else:
return f(*args, **kwargs)
except:
app.logger.info(Response('Request Did not came through header !', 401, {'WWW-Authenticate': 'Login failed'}))
return redirect(url_for('login_to system'))
return wrap
#---------------------------------------------------------------#
-------------------------------------------------------
login api code
#app.route('/login_to_system', methods=['GET', 'POST'])
def login_to_system():
form = LoginForm()
user = User_table.find_first(username=form.username.data)
login_user(user, remember=False)
try:
#Generating an random api_token at login time and will send to db
token_string=''.join(random.choices(string.ascii_uppercase + string.digits, k=14))
user.token=token_string #assigning token_string value to field api_token in database.
user.save() #saving the value in user table(using couch Db You can follow syntax as per you DB)
except Exception as error:
app.logger.error(str(error))
app.logger.info("before setting api_token in session")
session["token"]= token_string #adding a "token" to session object
#app.logger.info("Rendering login form")
return render_template('login.html', title='Sign In', form=form)
#-------------------------------------------------------#
#-----------------------------------#
#logout api code
#app.route('/logout')
def logout():
try:
user=User_table.find_first(_id=user_id)
#Generating a random token while logging out and will overwrite eariler token sent at login time send to database.
user.token=token_string=''.join(random.choices(string.ascii_uppercase + string.digits, k=17))
user.save()
except Exception as error:
app.logger.error(str(error))
logout_user()
session.clear()#clearing session
return redirect(url_for('Home page'))
#-----------------------------------#
Note: Seems like login_required is not working fine for me thats why i had to create another decorator but login_required also does the same thing but its strange that it not working for me.

How to find out if cookie expired in Flask app

I'm using session expiration in Flask. Ideally I would like to flash appropriate message after session expires and redirect to login page. It seems like there is no way to get expiry information from the cookie to test for that or am I missing something?
If the session has expired, the session cookie is no longer present in the browser.
From the docs, session is a python dictionary.
The session object works pretty much like an ordinary dict...
For, example, You set the session by: session['username'] = 'xxxxxx'.
To check if that cookie is still available, use session.get('username'). If it returns None, the cookie is absent, else, the cookie is present.
The check becomes:
if not session.get('user'):
flash('Not so fast! Kindly login to view that page')
return redirect(url_for('login'))
else:
#...Do something with logged-in user
Flask-Login and Flask-Session are two extensions that handle user login and sessions very well for you.

How do I make cookie sessions?

I'm trying to make a cookie session and can't find anything thats resembles clear documentation. The django docs on this are very weak!
Alls I found was this guys video on cookies: http://www.youtube.com/watch?v=U_dDY7TvJ4E
Can someone show me how to make a cookie when a visitor goes to my site?
I want be able to save that cookie in my database, so that when they make another request I can associate changes with them server side.
Thanks!
Here is the link for where in the Django Docs on how to make cookies:
https://docs.djangoproject.com/en/dev/topics/http/sessions/
A short example of how to do so would be like so. You can use the built in Session table as a dictionary like so:
def myView(request):
request.session['foo'] = 'bar'
# other view code
render(request, 'mypage.html')
UPDATE:
This is how you would redirect a User based on if they have a Cookie or not
def myViewTwo(request):
id = request.session['UUID1']
# verify the UUID1 exists
if id == 'UUID1:
return render(request, 'cookie.html')
# if not, send them to a normal view
return render(request, 'no_cookie.html')

django does not send csrf token again after browser cookies has been cleared

In normal situation, django will send csrf token via cookie which can be used by ajax post method later. However when I clear cookies in the browser(Chrome or Firefox), the csrf token is not sent to browser anymore, the session id is still sending but no csrf token. Does anyone know what's going wrong?
I solved this issue by adding {% csrf_token %} to my template and the SET-COOKIE header appears along with that page request. it turns out that you have to put the {%csrf-token%} in the template in order to make the server send the token via SET-COOKIE header
Look at django/middleware/csrf.py in which CsrfViewMiddleware class is declared. As you can see in def process_response(self, request, response) there are three conditions that prevent cookie setup:
def process_response(self, request, response):
if getattr(response, 'csrf_processing_done', False):
return response
# If CSRF_COOKIE is unset, then CsrfViewMiddleware.process_view was
# never called, probaby because a request middleware returned a response
# (for example, contrib.auth redirecting to a login page).
if request.META.get("CSRF_COOKIE") is None:
return response
if not request.META.get("CSRF_COOKIE_USED", False):
return response
# Set the CSRF cookie even if it's already set, so we renew
# the expiry timer.
response.set_cookie(settings.CSRF_COOKIE_NAME,
request.META["CSRF_COOKIE"],
max_age = 60 * 60 * 24 * 7 * 52,
domain=settings.CSRF_COOKIE_DOMAIN,
path=settings.CSRF_COOKIE_PATH,
secure=settings.CSRF_COOKIE_SECURE
)
# Content varies with the CSRF cookie, so set the Vary header.
patch_vary_headers(response, ('Cookie',))
response.csrf_processing_done = True
return response
Check which is applied for you.
I had the same problem. After debugging against django source, the reason is:
If your view is not rendering a template containing the csrf_token
template tag, Django might not set the CSRF token cookie.
Two solutions:
Add {% csrf_token %} in your template
Use #ensure_csrf_cookie decorator for your view
For detail your can refer django doc.
In my case, the problem was VSCode debugger.
I turned on server via VSCode debug mode, then open new incognito window (obviously there were no cookies), and django stopped setting missing cookie.
When I started server as normal, the problem has gone.
In most cases issue caused by second check mentioned in a previous answer
if not request.META.get("CSRF_COOKIE_USED", False):
return response
This can be solved by using #ensure_csrf_cookie decorator for the view. If used - check is passed and cookie is set/renewed each time view is rendered.
See also related topic: Using ajax request in Django without form element

Django logout(redirect to home page) .. Delete cookie?

I redirect the user to the home page after logout. In between I would like to delete all/or specific client cookies (I have previously set).
def logoutuser(request):
logout(request)
return redirect('app.home.views.home')
To call response.delete_cookie('user_location'), there is no response object. How do I do this?
Like jobscry said, logout() cleans session data, but it looks like you have set your own cookies too.
You could wrap auth logout view, which will return a HttpResponse:
def logout_user(request):
response = logout(request, next_page=reverse('app.home.views.home'))
response.delete_cookie('user_location')
return response
Or if you're just using the logout method as opposed to the view, you can use the return value for the redirect() method you have (which I assume returns a HttpResponse too).
def logout_user(request):
logout(request)
response = redirect('app.home.views.home')
response.delete_cookie('user_location')
return response
according to http://docs.djangoproject.com/en/dev/topics/auth/#django.contrib.auth.logout
Changed in Django 1.0: Calling logout() now cleans session data.
Hope this helps:
delete cookie when caling "/clear-cookies"
location.href = '/clear-cookies';
Define a method in views.py:
def clear_cookies(request):
response = HttpResponseRedirect('/')
response.delete_cookie('_gat', domain='example.com')
response.delete_cookie('_ga', domain='example.com')
response.delete_cookie('_gid', domain='example.com')
return response
Add the path and method to your urls.py:
url(r'^clear-cookies', clear_cookies),
This is slightly tangential, but maybe helpful to others in a similar situation.
If you are setting cookies that need to be deleted when the user logs out, maybe you shouldn't be using cookies in the first place. For that use case, it's much better to use session data instead. Like:
request.session['myKey'] = myValue
retrievedValue = request.session.get('myKey')
From the docs: "The session framework lets you store and retrieve arbitrary data on a per-site-visitor basis. It stores data on the server side and abstracts the sending and receiving of cookies".
Using session data is more secure and more performant than setting cookies, because the data stays on the server side.
The only use case where I would recommend setting your own cookies is if you need to store information that persists beyond a session (say you want to store preferences across sessions for a visitor who does not sign in).