Django CSRF_Trusted and Allowed Hosts issues

I just managed to get to the very last chapter of Django for beginners. On that last chapter the book talks about deploying the website using fly.io. I test my code locally using python manage.py runserver and it works fine there are no errors. When I deploy it to fly launch however it says CSRF verification failed. Request aborted when I deploy it on fly.io.

The error message in full: Reason given for failure: Origin checking failed - https://djangonews.fly.dev/ does not match any trusted origins. In general, this can occur when there is a genuine Cross Site Request Forgery, or when Django’s CSRF mechanism has not been used correctly. For POST forms, you need to ensure: Your browser is accepting cookies. The view function passes a request to the template’s render method. In the template, there is a {% csrf_token %} template tag inside each POST form that targets an internal URL. If you are not using CsrfViewMiddleware, then you must use csrf_protect on any views that use the csrf_token template tag, as well as those that accept the POST data. The form has a valid CSRF token. After logging in in another browser tab or hitting the back button after a login, you may need to reload the page with the form, because the token is rotated after a login. You’re seeing the help section of this page because you have DEBUG = True in your Django settings file. Change that to False, and only the initial error message will be displayed. You can customize this page using the CSRF_FAILURE_VIEW setting.

Here is my settings.py file. Any advice?

It’s exactly what it says. You don’t have an entry in CSRF_TRUSTED_ORIGINS that matches that url.

CSRF_TRUSTED_ORIGINS = ["djangonews27.fly.dev/", "https://*.djangonews27.fly.com", "https://*.fly.dev/", "https://fly.io/apps/djangonews27/"]

Here you need to add https://djangonews.fly.dev/ this url but you have given the url https://*.djangonews27.fly.com in CSRF_TRUSTED_ORIGINS is different.

I am now getting a bad request message 400. William says to input the hostname into CSRF_TRUSTED_ORIGINS and ALLOWED_HOSTS.

I am certain I have followed his instructions.

https://newsapp27.fly.dev/
ALLOWED_HOSTS = [
“https://newsapp27.fly.dev/”,
“localhost”,
“127.0.0.1”,
]
CSRF_TRUSTED_ORIGINS = [“https://newsapp27.fly.dev/”, “https://*.fly.dev”]

Notice the different in format for the entries in ALLOWED_HOSTS vs CSRF_TRUSTED_ORIGINS. You don’t specify the scheme for the entries in ALLOWED_HOSTS.

Also remember that when asking for assistance with any error that you should post the complete error and traceback from the console where you’re running runserver. Just posting:

may not be sufficient information to diagnose the problem.

1 Like

I will try to post the full error message going forward. Thank you Ken.

According to Django For Beginners:

ALLOWED_HOSTS and CSRF_TRUSTED_ORIGINS
ALLOWED_HOSTS lists all of the host/domain names our Django website can serve, while CSRF_-
TRUSTED_ORIGINS is a list of trusted origins for unsafe requests like POSTs. Both need to be
explicitly set now and once we have our production URLs from Fly, we can lock them down
properly.

Williams Code

# django_project/settings.py
ALLOWED_HOSTS = [".fly.dev", "localhost", "127.0.0.1"] # new
CSRF_TRUSTED_ORIGINS = ["https://*.fly.dev"] # new

My hostname here is dfb-ch17-news.fly.dev, but your hostname will naturally differ. Add your
hostname to the ALLOWED_HOSTS and CSRF_TRUSTED_ORIGINS settings.

# django_project/settings.py
ALLOWED_HOSTS = ["dfb-ch17-news.fly.dev", "localhost", "127.0.0.1"] # new
CSRF_TRUSTED_ORIGINS = ["https://dfb-ch17-news.fly.dev"] # new

So I do so:

But Ken you are saying that I do not specify a format for allowed_hosts. How does one specify the format? By keeping all of the entries consistent? I copied the host name and placed it in CSRF_Trusted_ORIGINS, but than I got an error saying as of Django 4.0 all entries need to have https:// format. I do not have access to the full error message anymore
or I would post it. So I make the change and I get bad request. Are you saying I need them all to have https://?

Django Documentation:

Your formatting suggestion worked when I had “.fly.dev” in the front

ALLOWED_HOSTS = [".fly.dev","https://newsapp27-db.fly.dev/","https://newsapp27.fly.dev", "localhost", "127.0.0.1",
]
CSRF_TRUSTED_ORIGINS = ["https://*.fly.dev","https://newsapp27.fly.dev", "https://newsapp27-db.fly.dev/"]
1 Like

This is part of what you posted above:

Compare the first two elements of each list.

In ALLOWED_HOSTS:
"dfb-ch17-news.fly.dev"

In CSRF_TRUSTED_ORIGINS:
"https://dfb-ch17-news.fly.dev"

What is different between these two entries?

Allowed hosts does not have

https::// at the start of the url.

Correct.

In a url, the “http://” (or “https://”) is called the scheme.

You use the scheme in entries for CSRF_TRUSTED_ORIGINS.

You do not use the scheme for entries in ALLOWED_HOSTS.

2 Likes

can you give him the correct format then explain? I have been looking through solutions for my django+docker+gcp project and I’m frustrated see a comment marked as solution but I can’t understand.
ALLOWED_HOSTS = [“dfb-ch17-news.fly.dev”, “localhost”, “127.0.0.1”] # he’s not using scheme
CSRF_TRUSTED_ORIGINS = [“https://dfb-ch17-news.fly.dev”] # he is using scheme
but this doesn’t solve his issue, right?