The problem is that by default when the project is running on localhost,
browsers will always send `Origin: null` (correct me if I'm wrong).
[https://github.com/django/django/blob/2f73e5406d54cb8945e187eff302a3a3373350be/django/middleware/csrf.py#L433
if 'HTTP_ORIGIN' in request.META] will always evaluate to `True` on
localhost, even if `Origin: null`.
[https://github.com/django/django/blob/2f73e5406d54cb8945e187eff302a3a3373350be/django/middleware/csrf.py#L281
if request_origin in self.allowed_origins_exact] will never evaluate to
`True` on localhost, as `null` will never be a valid origin as it doesn't
include a scheme.
As a result, it's impossible to POST a form on localhost.
------------------------
- If it's a regression to 16010, I'd propose changing
[https://github.com/django/django/blob/2f73e5406d54cb8945e187eff302a3a3373350be/django/middleware/csrf.py#L433
if 'HTTP_ORIGIN' in request.META]
to
`if request.META.get('HTTP_ORIGIN') is not None`
- If it's a feature, I'd suggest adding the above or a setting
`CSRF_ALLOW_NULL_ORIGIN = False` but it'd require a change in all projects
migrating to v 4
- if I am mistaken and the `Origin` header should be automatically
populated by browsers with a non-null value when POSTing from localhost,
this ticket can be closed (or maybe docs could be improved?)
-----------------------
Sample code that is failing on 4 and is working fine on 3.x
{{{
# settings
from corsheaders.defaults import default_headers
CORS_ALLOWED_ORIGINS = [
"http://localhost:8000",
"http://127.0.0.1:8000",
]
CSRF_TRUSTED_ORIGINS = [
"http://localhost:8000",
"http://127.0.0.1:8000",
]
}}}
{{{
# template
<form method="post">
{% csrf_token %}
</form>
}}}
Error:
> Origin checking failed - null does not match any trusted origins.
Request headers:
{{{
Host: localhost:8000
Origin: null
}}}
Even if I'm wrong, it's worth noting that the standard defines `opaque
origin` when `Origin` will be set to `null` so technically this value
should be supported anyway but I don't understand its definition.
Let me know if there's something to do here. If yes, please assign me.
--
Ticket URL: <https://code.djangoproject.com/ticket/33360>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
Comment (by Tomasz Wójcik):
I don't think I have the power to summon someone, but in 16010 Adam
Johnson has been CCed and he once wrote
[https://github.com/adamchainz/django-cors-
headers/issues/241#issuecomment-315537226 browsers send `Origin: null` for
localhost/127.0.0.1]
(I will try anyway): CC Adam Johnson please confirm if it still holds
true.
--
Ticket URL: <https://code.djangoproject.com/ticket/33360#comment:1>
Old description:
New description:
------------------------
to
-----------------------
should be supported anyway but I don't understand its (`opaque origin`)
definition.
Let me know if there's something to do here. If yes, please assign me.
--
--
Ticket URL: <https://code.djangoproject.com/ticket/33360#comment:2>
* type: Uncategorized => Bug
Comment:
What browser do you see a null origin? On Firefox and Chrome, I see
`http://localhost:8000`.
--
Ticket URL: <https://code.djangoproject.com/ticket/33360#comment:3>
Comment (by Tomasz Wójcik):
Chrome 95.0.4638.54 (Official Build) (64-bit), Mint (Ubuntu), dockerized
env. I find it surprising that no one else run into his issue earlier -
maybe it's just a matter of my setup.
--
Ticket URL: <https://code.djangoproject.com/ticket/33360#comment:4>
Comment (by Tomasz Wójcik):
I'm trying to reproduce in the new minimal repro and also getting the
origin header. I will let you know once I figure out how to reproduce it.
--
Ticket URL: <https://code.djangoproject.com/ticket/33360#comment:5>
Comment (by Tomasz Wójcik):
Oh my... I had
{{{
<meta name="referrer" content="no-referrer">
}}}
in my base template. Sorry for the problem. Please close it.
--
Ticket URL: <https://code.djangoproject.com/ticket/33360#comment:6>
* status: new => closed
* resolution: => invalid
--
Ticket URL: <https://code.djangoproject.com/ticket/33360#comment:7>