recipes
recipes copied to clipboard
CSRF issue using Traefik
Tandoor Version
1.5.6
Setup
Docker / Docker-Compose
Reverse Proxy
Traefik
Other
No response
Bug description
Issue:
Forbidden (403)
CSRF verification failed. Request aborted.
Help
Reason given for failure:
Origin checking failed - null 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](https://docs.djangoproject.com/en/4.1/ref/csrf/) 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](https://docs.djangoproject.com/en/dev/topics/templates/#django.template.backends.base.Template.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.
recipe.conf
server {
listen 80;
server_name localhost;
client_max_body_size 128M;
# serve media files
location /media/ {
alias /media/;
}
# pass requests for dynamic content to gunicorn
location / {
#proxy_set_header Host $host;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass http://tandoor:8080;
#proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
#proxy_set_header X-XSRF-TOKEN $http_x_xsrf_token;
#proxy_set_header Host $host;
proxy_redirect http://127.0.0.1:8080 <website redacted>;
error_page 502 /errors/http502.html;
}
location /errors/ {
alias /etc/nginx/conf.d/errorpages/;
internal;
}
}
.env file
DEBUG=1
SQL_DEBUG=0
DEBUG_TOOLBAR=0
TANDOOR_PORT=8080
ALLOWED_HOSTS=*
SECRET_KEY=<redacted>
TIMEZONE=<redacted>
DB_ENGINE=django.db.backends.postgresql
POSTGRES_HOST=tandoor_db
POSTGRES_PORT=5432
POSTGRES_USER=ThatUser
POSTGRES_PASSWORD=ThatPassword
POSTGRES_DB=ThatDB
FRACTION_PREF_DEFAULT=0
COMMENT_PREF_DEFAULT=1
SHOPPING_MIN_AUTOSYNC_INTERVAL=5
REVERSE_PROXY_AUTH=0
ENABLE_PDF_EXPORT=1
nginx container: tandoor_web recipes container: tandoor postgres container: tandoor_db
Its fairly obvious that I've tried a few different options in the Recipes.conf file, but I'm still getting the CSRF issue. Any suggestions?
Relevant logs
No response
Can you please share the header details provided at /system/
which container?
Tandoor
That directory does not exist.
Here's a screenie
Sorry for the confusion. It's a webpage at the root of you Tandoor url.
Oh right, sorry.
I'm not logged in, so I can't view that page; and I can't log in due to the CSRF issue
can you connect bypassing traefik?
Not really; I've too many services on the machine. The things I've tried, I haven't had much luck.
What else did you want me to try?
The problem is probably with your traefik setup. Your options are:
- start with a known working configuration and incrementally add capabilities to identify which one is causing the issue
- search the forums for working traefik configs to see if you spot any differences
- use traefik or django support channels to get assistance on how to troubleshoot traefik and django
Seriously doubt that it is an issue with Traefik, as mentioned earlier the machine runs several services (all of which are behind Traefik); I appreciate your candor, though.
Most of my research points to django, and its Cross Site Request Forgery Protection, which would point to the structure of Tandoor.. hence I opened this issue. What makes you say that Traefik is the issue?
django is extremely opinionated about the headers that are provided. Unless you are serving django apps behind traefik the fact that other services are working isn't an indication that you have set it up correctly.
Most probably a duplicate of https://github.com/TandoorRecipes/recipes/issues/518. What solved it for me is defining the CSRF_TRUSTED_ORIGINS env var on my container. Hope it works for you too.
Hi @alecgerona, thanks for the suggestion, probably not a duplicate of that issue.. my reasoning here, is that it concerns nginx proxy manager and not traefik..
Can you give some examples on your fix? I've been playing with the env file, and mine reads (similar to) as follows:
CSRF_TRUSTED_ORIGINS="https://recipes.domain.tld","http://recipes.domain.tld"
@voryzen Hi, reason I mentioned it is because I'm also using Nginx Proxy Manager and ran into your problem. My env var is just CSRF_TRUSTED_ORIGINS="https://recipes.domain.tld". I only need to whitelist one. I think if you have multiple you just have to use space as a delimiter.
CSRF_TRUSTED_ORIGINS="https://recipes.domain.tld http://recipes.domain.tld"
As an extra warning, while I got past the CSRF error, I ran into the Mixed Content issue since my https is being provided by Cloudflare and Tandoor still thinks it's being served by http so I can't use it still. I haven't put in the time to solve it yet.
Might be helpful to you.
Hi @alecgerona, thanks for the suggestion, probably not a duplicate of that issue.. my reasoning here, is that it concerns nginx proxy manager and not traefik..
@alecgerona sorry, that was my fault; I wasn't clear there. When I referenced 'that' earlier, I was referring to the cited issue, not my own.
To be clearer, I'm having this issue with Traefik, not with Nginx Proxy Manager.
If I manage to get past this error (I've been looking at adamchainz cors module) I'll keep an eye out for that mixed content issue.
Thank you
Yeah no worries had a mindfart of my own back then. Hope you solve this. The env var should be enough.
@voryzen A few things I noticed in your config:
- I think the
X-Forwarded-Protoin your nginx configuration cannot work. It will always be http from the perspective of nginx. The default config works fine in my traefik setup. Nginx should forward allX-Forwarded-*headers by default. - It is weird that you get
null does not match any trusted origins. You should try to runtcpdumpinside the nginx container to see which headers come from traefik. You should seeHostandX-Forwarded-Hostwith a value matching your domain.
Hi @swnf
Thank you very much for your input into this issue. I've done as you asked, and I've pasted the output to pastebin (redacting personal information) for your perusal. https://pastebin.com/PJsPz3sR
I can verify that the Host and X-Forwarded-Host does point to the correct domain.
I look forward to hearing your opinion on the matter, hope you're well.
I don't see anything wrong with your headers. If this is a new deployment, you should probably try to reset tandoor by deleting all containers/volumes and recreating them.
@swnf yea, new deployment. deleting and recreating did not yield results. I had a look through the tandoor code, and I'm fairly convinced now that its an issue with nginx.
I'll have some more time to work on this over the weekend
@voryzen were you able to figure this out? I have a similar issue where only Chrome gives me this error, but Firefox and Edge work fine.
"There was an error updating a resource! {"detail":"CSRF Failed: CSRF token missing."}"
I have added CSRF_TRUSTED_ORIGINS = "https://exmaple.com" but it makes no difference to Chrome.
No, haven't had an luck.
TBH, I've moved on to other programs, due to the lack of help. Sorta been made feel like it's an issue with something I've done; so I'm a little unwilling to approach the devs or their posse.
Good luck though, I would love to see a fix for it.
Just for reference, here is a complete config with traefik that works perfectly fine for me. You can try to remove any additional configuration you made to the environment/nginx/traefik to figure out what triggers this behaviour. It might also help to delete the website's data in your browser because Edge and Chrome are nearly identical.
version: '3.8'
services:
db_recipes:
image: postgres:16-alpine
environment:
POSTGRES_USER: "djangouser"
POSTGRES_PASSWORD: "djangpassword"
POSTGRES_DB: "djangodb"
volumes:
- postgresql:/var/lib/postgresql/data
web_recipes:
image: vabene1111/recipes:1
environment:
SECRET_KEY: "myverysecretkey"
DB_ENGINE: "django.db.backends.postgresql"
POSTGRES_HOST: "db_recipes"
POSTGRES_PORT: "5432"
POSTGRES_USER: "djangouser"
POSTGRES_PASSWORD: "djangpassword"
POSTGRES_DB: "djangodb"
volumes:
- staticfiles:/opt/recipes/staticfiles
- nginx_config:/opt/recipes/nginx/conf.d
- mediafiles:/opt/recipes/mediafiles
depends_on:
- db_recipes
nginx_recipes:
image: nginx:mainline-alpine
volumes:
- nginx_config:/etc/nginx/conf.d:ro
- staticfiles:/static
- mediafiles:/media
depends_on:
- web_recipes
labels:
traefik.enable: "true"
traefik.http.routers.recipes.rule: "Host(`tandoor.example.com`)"
traefik:
image: traefik:2.10
command: --providers.docker --providers.docker.exposedByDefault=false
ports:
- '80:80'
volumes:
- /var/run/docker.sock:/var/run/docker.sock
volumes:
postgresql:
staticfiles:
nginx_config:
mediafiles:
Thanks for sharing, as of the most recent version "1.5.10" I no longer have this issue with Chrome so long as I have the following in my .env file. Granted I am not using Taefik but an Apache reverse proxy.
CSRF_TRUSTED_ORIGINS = "https://exmaple.com/"
@alecgerona did you ever solve the Cloudflare Mixed Content issue? I just hit it and was hoping for an easy fix.
Anyone else that comes across this and has the Cloudflare Mixed Content issue. You will need a custom Recipes.conf and add the two lines below.
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Forwarded-Scheme https;
@tasmith039 thank you for this tip! I have added your changes to Recipes.conf and restarted the container, but I'm still getting errors from Axios (still using HTTP instead of HTTPS, like http://tandoor.domain.com/api/space/1/).
Context: I'm using Traefik + Docker (Traefik config through Docker labels) + Cloudflare.
My config looks like below:
server {
listen 80;
server_name localhost;
client_max_body_size 128M;
# serve media files
location /media/ {
alias /media/;
}
# pass requests for dynamic content to gunicorn
location / {
proxy_set_header Host $http_host;
proxy_pass http://web_recipes:8080;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Forwarded-Scheme https;
error_page 502 /errors/http502.html;
}
location /errors/ {
alias /etc/nginx/conf.d/errorpages/;
internal;
}
}
Do yours look different?
Hey @goniszewski I am also using Traefik + Docker + Cloudflare. I will say I did have some weird issues where dont always work quite right. For example I always get the error below on startup which gives a cloudflare error. I also had had to make sure to clear our my old volumes from initial setup. Are you only getting the Mixed Content issue but the page loads fine otherwise?
2024-01-15 11:47:49 2024/01/15 16:47:49 [error] 21#21: *1 connect() failed (111: Connection refused) while connecting to upstream, client: 172.25.0.2, server: localhost, request: "GET /view/recipe/1 HTTP/1.1", upstream: "http://172.23.0.3:8080/view/recipe/1", host: "tandoor.mydomain.com"
Below is my docker compose config
version: "3.9"
services:
db_recipes:
restart: always
image: postgres:15-alpine
volumes:
- ./config/tandoor/postgresql:/var/lib/postgresql/data
env_file:
- ./config/tandoor/.env
networks:
- tandoor
web_recipes:
restart: always
container_name: "web_recipes"
image: vabene1111/recipes
env_file:
- ./config/tandoor/.env
volumes:
- staticfiles:/opt/recipes/staticfiles
# Do not make this a bind mount, see https://docs.tandoor.dev/install/docker/#volumes-vs-bind-mounts
- ./config/tandoor/nginx:/opt/recipes/nginx/conf.d
- ./config/tandoor/mediafiles:/opt/recipes/mediafiles
depends_on:
- db_recipes
networks:
- tandoor
nginx_recipes:
image: nginx:mainline-alpine
container_name: "nginx_recipes"
restart: always
env_file:
- ./config/tandoor/.env
volumes:
- ./config/tandoor/nginx:/etc/nginx/conf.d:ro
- staticfiles:/static:ro
- ./config/tandoor/mediafiles:/media:ro
labels:
- "traefik.enable=true"
- "traefik.http.routers.tandoornginx.rule=Host(`tandoor.mydomain.com`)"
- 'traefik.http.services.tandoornginx.loadBalancer.server.port=80'
depends_on:
- web_recipes
ports:
- "8086:80"
networks:
- tandoor
- frontend
Below is my Recipes.conf
server {
listen 80;
server_name localhost;
client_max_body_size 128M;
# serve media files
location /media/ {
alias /media/;
}
# pass requests for dynamic content to gunicorn
location / {
proxy_set_header Host $http_host;
proxy_pass http://web_recipes:8080;
error_page 502 /errors/http502.html;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Forwarded-Scheme https;
# proxy_redirect http://127.0.0.1:8080 https://tandoor.mydomain.com; # replace port and domain
}
location /errors/ {
alias /etc/nginx/conf.d/errorpages/;
internal;
}
}
Thank you for your reply @tasmith039 :) Yes, the page loads fine otherwise, but is unable to fetch any data from the API. I have tried to create override rules in CF, but didn't succeed.
I will try again later with the proxy_redirect option you have commented out. Meanwhile, the other app I tried worked right away with my setup. I only needed it to show my wife the possibilities, so I'll just explore it for now and see how it compares to Tandoor.
@goniszewski good luck man. Let me know if there is anything else I can do to help. We can jump On a zoom or something if you want. I hope you get it working.