0

Here is my setup:

localhost (Windows 11)
  - Nginx
      listening on port 80 and 443, 80 is NOT automatically redirected to 443
      each proxy_passed to http://wsgi-server where wsgi-server=127.0.0.1:8080
  - waitress_wsgi running as a service on port 8080

Here is Django config:

<!-- email_test.html -->
<!-- ... -->
<form action="{% url 'identity:email_test' %}" method="post">
  {% csrf_token %}
  {{ email_form }}
  {% translate 'Send email' as submit_translated %}
  <!-- I use django_bootstrap5 -->
  {% bootstrap_button button_type="submit" content=submit_translated extra_classes='w-100'%}
</form>
# settings.py ----------
MIDDLEWARE = {
  # ...
  'django.middleware.csrf.CsrfViewMiddleware',
  # ...
}

# forms.py -------------
class EmailTestForm(forms.Form):
  email = forms.EmailField(
    # help_text=password_validation.password_validators_help_text_html(),
    label=_('Email'),
    max_length=128,
  )

# views.py -------------
def email_test(request):
  context = {}
  context.update(template_globals())
  if request.method == "POST":
    email_form = EmailTestForm(request.POST)
    if email_form.is_valid():
      email_obj = EmailMessage(subject='Hello', body='Email body',
                               from_email='[email protected]',
                               to=[email_form.cleaned_data.get('email')])
      email_obj.send(fail_silently=False)
  else:
    email_form = EmailTestForm()

  context['email_form'] = email_form
  return render(request, "identity/email_test.html", context)

Here are my test resuts when I visit the URL on browser:

  1. py manage.py runserver (default port 8000), browser http://127.0.0.1:8000, empty settings.CSRF_TRUSTED_ORIGINS: Works fine.
  2. Browser http://localhost or http://127.0.0.1 or https://localhost or https://127.0.0.1 with individual entry not in settings.CSRF_TRUSTED_ORIGINS: CSRF error.
  3. Browser http://localhost or http://127.0.0.1 or https://localhost or https://127.0.0.1 with individual entry not settings.CSRF_TRUSTED_ORIGINS: Works fine.
  4. Browser https://mymachine.net with this entry in etc/hosts resolving to 127.0.0.1 and not in settings.CSRF_TRUSTED_ORIGINS: CSRF error.
  5. Browser https://mymachine.net with this entry in etc/hosts resolving to 127.0.0.1 and in settings.CSRF_TRUSTED_ORIGINS: Works fine.
  6. Browser http://localhost:8080 or http://localhost or http://mymachine.net:8080: Works fine.

Does this mean that for (2-5), since the actual server the Django app runs on is the WSGI server on port 8080, request forwarded from the web server is not considered same site?

1 Answer 1

0

I was able to solve this. With this solution, I did not have to add any entries in settings.CSRF_TRUSTED_ORIGINS.

  1. Nginx config:
  upstream wsgi-server {
    server 127.0.0.1:8080;
  }
  server {
    # ...
    location / {
      proxy_pass http://wsgi-server/;
      # These resolved CSRF error
      proxy_set_header X-Forwarded-Proto $scheme;
      proxy_set_header X-Forwarded-Host $host;
      proxy_set_header X-Forwarded-Port $server_port;
    }
  }
  1. Waitress WSGI config (to let X-Forwarded-* pass through to Django):
# waitress_wsgi.py
  serve(application,
        trusted_proxy='proxy-ip',
        trusted_proxy_headers=('x-forwarded-host', 'x-forwarded-proto',
                               'x-forwarded-port'))

With this, http|https, localhost|127.0.0.1|mymachine.net, anyport, started working with no errors.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.