django posts receive CSRF verification failed after switching to load balancer - django

I have a working login template that does a post and looks like:
<form action="" method="post">
{% csrf_token %}
<br>
{{form.email}}
<div class="text-center">
<button type="submit">Login</i></button>
</div>
</form>
My SSL settings look like:
ssl
SECURE_SSL_REDIRECT = False
SECURE_HSTS_SECONDS = 3600
SESSION_COOKIE_SECURE = False
SECURE_PROXY_SSL_HEADER = None
CSRF_COOKIE_SECURE = False
I made two changes. I switched to an aws ec2 elastic load balancer and from https to http.
Now I am getting an error:
Forbidden (403) CSRF verification failed. Request aborted.
You are seeing this message because this site requires a CSRF cookie
when submitting forms. This cookie is required for security reasons,
to ensure that your browser is not being hijacked by third parties.
If you have configured your browser to disable cookies, please
re-enable them, at least for this site, or for 'same-origin' requests.
Does anyone know why this is occurring?

I must have a stale cookie. When I go to Chrome incognito mode, all works as would expect with a 200 response.

Forbidden (403)
CSRF verification failed. Request aborted.
You are seeing this message because this site requires a CSRF cookie when submitting forms. This cookie is required for security reasons, to ensure that your browser is not being hijacked by third parties.
If you have configured your browser to disable cookies, please re-enable them, at least for this site, or for 'same-origin' requests.
More information is available with DEBUG=True.

Related

CSRF 403 in default Django login

I'm fairly new to Django. Here's what I need insight on:
After updating from Django 3 to 4:
On the local dev server, no issue.
On production: CSRF 403 error on login.
There's a cookie loaded on the login page containing
csrftoken: pAFeeUI8YFXZ2PKRYxOTX1qz4Xgto42WVNi7FFvBlZDqcFLwQ2rdQvVeZBHFSpLW
(Local and Session storage are empty)
In the FORM element:
<input type="hidden" name="csrfmiddlewaretoken" value="Vz4FiujD4qkLpxCwWNJU0HCWs4u0Qf4RrMHyJf66rK0cznDbOimeTb7BnIVckANR">
Notice they don't match.
I tried manually deleting the cookie and also running ./migrate.py clearsessions.
The first time, yesterday, it seemed that the error did not occur in an Incognito Window, but today it persists even in an incognito window, as well as a different browser.
One additional piece of information
allauth had been previously installed, but was causing infinite redirect loop on login, so removed. The login page url is /login/?next=/.
Thanks much.
At least in Django 4.0, you can–and possibly must–specify CSRF trusted origins in your settings.py file:
CSRF_TRUSTED_ORIGINS = ["https://yourdomain.com", "https://www.yourdomain.com"]
Note www and non-www as well as no trailing /.
At any rate, it solved the issue for me.
See Docs.
You should add {% csrf_token %}:
{% csrf_token %}
<input type="hidden" name="csrfmiddlewaretoken" value="Vz4FiujD4qkLpxCwWNJU0HCWs4u0Qf4RrMHyJf66rK0cznDbOimeTb7BnIVckANR">

django CSRF token cookie not set for some users

I have been getting sporadic CSRF errors in an app that is mostly working ok. I do everything as I'm supposed to do: I use {% csrf_token %} in my template for normal forms and in my ajax POSTs I set the X-CSRFToken header:
$.ajaxSetup({
beforeSend: function(xhr, settings) {
xhr.setRequestHeader("X-CSRFToken", $.cookie('csrftoken'));
},
});
I'm even forcing the cookie to be set in all views by writing a custom Middleware that calls get_token
def CSRFForceCookieMiddleware(get_response):
def middleware(request):
response = get_response(request)
get_token(request) # Force to set cookie in all responses
return response
return middleware
Everything works OK in my localhost and in production for most users. But for some users I get 403 CSRF validation error.
I added a lot of debug info. Turns out that even if CsrfViewMiddleware is setting the csrftoken is setting the cookie in the response, in the actual browser the cookie is not set ($.cookie('csrftoken') is null). So when the ajax call is made, there is no cookie present in the request.
So, I guess this pretty much means that some users' browsers are blocking this cookie? Anyone else had this experience?
Most browsers have an option to "block all cookies". You may want to detect that in javascript and give your users a warning that some functional cookies are required for the site to work correctly. There's another SO question that shows how to do that.
Alternatively, grab the token from a hidden input field ({% csrf_token %} will add that field in your template). That should always work.

CRSF cookie not set in iframed Django View within another site

I have a Django app with about a dozen views that I am currently hosting on Heroku. I can do POST requests just fine to the app when directly going to the app url, and I have the 'django.middleware.csrf.CsrfViewMiddleware' enabled. I am running Django 2.1
I am currently having an issue where I am trying to embed this Django app within an iframe, on another site that I host on Weebly. I always get a 403 error when trying to do a post on any of the Django forms. The reason is "CSRF cookie not set."
I am doing this through Chrome on Ubuntu. I checked the Applications tab in the Developer console, and do see the csrftoken key-value pair set in the cookie for the Heroku domain. The Weebly domain does not contain the csrftoken key-value pair. I figured it would just use the cookie from the Heroku app domain and use the csrftoken, but that doesn't appear to be the case.
In Django, here are my settings regarding CSRF:
CSRF_COOKIE_SECURE = False
CSRF_TRUSTED_ORIGINS = ['example123.herokuapp.com',
'app123.weebly.com']
I REALLY don't want to disable security or use the csrf_exempt decorator, as that feels like a hack. I am pulling my hair out on this one!
EDIT:
{% csrf_token %} is in the form, and I can see the hidden field "csrfmiddlewaretoken":
<input type="hidden" name="csrfmiddlewaretoken" value="XXXXXXXXXXXXXXXXXXXXXXywkFTfTC9ttYiOTD0O8uF49SvRjaUWgWeLU0h2PjP2">
There are two different things with csrf in django
1. Csrfmiddlewaretoken : {% csrf_token %}
example of set-token header
2. CSRFcookie : I don't think that you did this one.
example of same request giving different csrf-token
here the images shown are both the examples of one of my app for a specific request
We do often confuse second with the first one. In the second case, the server sets a cookie in the first get request with a csrf token (this is a cookie and not the csrfmiddlewaretoken ), it needs to be sent every-time for csrf cookie verification. This is done by the browser itself and we mostly don't notice it. However the problem arises with using CORS (different origins of request like android/angular app etc).

CSRF verification failed. Request aborted - Shopping cart configuration

I'm trying to enable Payment module for courses and when I'm clicking checkout, I'm getting "CSRF verification failed. Request aborted." . I've tried adding my domain to "Home › Cors_Csrf › X domain proxy configurations › XDomainProxyConfiguration()" in Django admin panel. Even modified lms.env.json to add "ENABLE_CROSS_DOMAIN_CSRF_COOKIE": true, " ... still facing the issue. Can anyone please help.
Google group message link : https://groups.google.com/d/msg/edx-code/4VnLJG-raPE/llF1PDG9AQAJ
Possibly you're not including the CSRF token in your form. In your template, it should look like:
<form action="post">
{% csrf_token %}
{{form.as_p}}
</form>
I don't know the library you're using, that was just general Django commentary. Hopefully it's helpful.

What is the difference between local and remote machine cookie delivery for the Django development server?

I have a Django 1.2.5 (stable release) site that is being developed and tested on a Ubuntu 10.10 machine. The dev box is on a LAN with some Windows machines that need to be able to view and test the site as well. So far, it is just the admin that I am trying to share.
The site works great on the dev box and can be run on 127.0.0.1:8080/admin or 192.168.17.165:8080/admin (the dev box's LAN IP) when starting the development server with the commands ./manage.py runserver and ./manage.py runserver 192.168.17.165:8080 respectively. However, when the windows machine tries to reach the server at 192.168.17.165:8080/admin the admin login page loads just fine, so things are almost set up correctly, but when the verified username and password are entered and the submit button is pressed, the post fails and the following error is returned:
Forbidden (403) CSRF verification failed. Request aborted.
Reason given for failure:
No CSRF or session cookie.
(very similar to #thomallen's post)
Here are some things that I have already checked that don't seem to have any effect:
I know that the login.html template has the {% csrf_token %} token added. When I view the source of the page, the tag
{% block content %}
{% if error_message %}
<p class="errornote">{{ error_message }}</p>
{% endif %}
<div id="content-main">
<form action="{{ app_path }}" method="post" id="login-form">{% csrf_token %}
<div class="form-row">
<label for="id_username">{% trans 'Username:' %}</label> <input type="text" name="username" id="id_username" />
</div>
is present. (stock admin login.html)
I have messed with the order of all the Middleware lines as seen here http://josh.gourneau.com/blog/2010/02/17/django-12-csrf-verification-failed/. Nothing.
Here is what I have:
MIDDLEWARE_CLASSES = (
'django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.middleware.csrf.CsrfResponseMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware', )
I thought maybe I should mess with these but it didn't seem to help
SESSION_COOKIE_DOMAIN = '192.168.17.165'
CSRF_COOKIE_DOMAIN = '192.168.17.165'
Cleared out all other cookies and web history. Turned off firewall.
My current suspicion:
On the dev box (the one that works), Firefox shows 2 cookies present, sessionid and csrftoken. The windows boxes do not seem to be getting these tokens. I looked into the HTTP headers using the Firefox Live HTTP headers plugin on both machines. The linux box (same as server) gets:
Set-Cookie: csrftoken=83bae579460e9d123d9d904f4e2ef4d5; Max-Age=31449600; Path=/
Set-Cookie: sessionid=ec2b472837318347f6e6c8243f9e0afd; expires=Sat, 02-Apr-2011 04:29:46 GMT; Max-Age=1209600; Path=/
The windows box gets very similar info, but the Max-Age of the cookie is set to 0 (Max-Age=0). After this, the windows machines don't store the cookies. This apparently kills the session immediately according to ietf.org/rfc/rfc2109.txt. I did try setting SESSION_COOKIE_AGE to 10000 but it didn't take.
What do I need to do to get the stock Django development server to send valid cookies to a remote machine? I can't be the only one...
Other similar stackoverflow posts and links that seemed promising but didn't work:
Why is Django admin login giving me 403 CSRF error?
Django outputs CSRF token as object instead of value
I have read all the documentation and had a couple people help me look at it and I have no clue what could be causing this. I am sure there are ways to disable CSRF as a workaround, but shouldn't this be working?
It turned out to be a secondary piece of software that was not turned off. CA Anti Virus had a separate process running that was blocking cookies after the fact.