Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

403 CSRF Error (AGAIN) #518

Closed
auanasgheps opened this issue Apr 3, 2021 · 29 comments
Closed

403 CSRF Error (AGAIN) #518

auanasgheps opened this issue Apr 3, 2021 · 29 comments
Labels
setup issue possibly or definitely an issue with the user setup

Comments

@auanasgheps
Copy link
Contributor

auanasgheps commented Apr 3, 2021

Issue

Hi, I'm trying to use Recipes with Nginx proxy manager using the following setup:

Nginx Proxy Manager > Recipes Nginx > Recipes Web App

I've configured Recipes Nginx using the provided config file and in fact works good.
When I connect in LAN pointing to Regipes Nginx everything works good (photos included).

However if I configure Nginx Proxy Manager to point to Recipes Nginx, nobody is able to login.
I believe there's something missing in Nginx Proxy Manager, but I can't figure it out. I also tried connecting straight to the Recipes Web app (exposing the port) but still getting the same error.

Enabling debug, the web browser shows

Reason given for failure:

    Referer checking failed - https://recipes.mydomain.cloud:8080/accounts/login/?next=/search/ does not match any trusted origins.

Setup Info

Version: 0.14.5
OS: Synology NAS w/ Docker

Other relevant information regarding your problem (proxies, firewalls, etc.)

.env

Please include your .env config file (make sure to remove/replace all secrets)
I added my domain to ALLOWED_HOSTS

# hosts the application can run under e.g. recipes.mydomain.com,cooking.mydomain.com,...
ALLOWED_HOSTS=recipes.mydomain.cloud

docker-compose.yml

When running with docker compose please provide your docker-compose.yml

version: "2"
services:
  recipes-db:
    restart: unless-stopped
    image: postgres:11-alpine
    container_name: recipes-db
    volumes:
        - /volume2/docker/recipes/db:/var/lib/postgresql/data
    env_file: /data/compose/recipes-env/recipes.env
    networks:
      - rete  

  recipes-app:
    image: vabene1111/recipes
    restart: unless-stopped
    container_name: recipes-app
    env_file: /data/compose/recipes-env/recipes.env
    volumes:
        - /volume2/docker/recipes/staticfiles:/opt/recipes/staticfiles
        - /volume2/docker/recipes/mediafiles:/opt/recipes/mediafiles
    depends_on:
      - recipes-db
    networks:
      - rete  
 
  recipes-nginx:
    image: nginx:mainline-alpine
    restart: always
    container_name: recipes-nginx
    ports:
      - 2310:80
    env_file: /data/compose/recipes-env/recipes.env
    depends_on:
      - recipes-app
    volumes:
      - /volume2/docker/recipes/nginx_config:/etc/nginx/conf.d:ro
      - /volume2/docker/recipes/staticfiles:/static
      - /volume2/docker/recipes/mediafiles:/media
    networks:
      - rete  
  
networks:
    rete:
        external:
            name: rete

Logs

From Docker - Recipes Web App:

[2021-04-03 15:16:33 +0000] [14] [INFO] Booting worker with pid: 14
Forbidden (Referer checking failed - https://recipes.mydomain.cloud:8080/accounts/login/?next=/search/ does not match any trusted origins.): /accounts/login/

@auanasgheps auanasgheps added the setup issue possibly or definitely an issue with the user setup label Apr 3, 2021
@vabene1111
Copy link
Collaborator

please try setting * as a ALLOWED_HOSTS. I am not entirely sure how those proxies work but from what i remember i have other applications installed that use * for their host if run behind a proxy.

Other than that the issue is most likely related to certain headers not being forwarded by nginx-proxy manager but i dont really know which ones that would be.

Please try * and tell me if it works, if not we will have to further investigate this issue.

@auanasgheps
Copy link
Contributor Author

Thanks, will test soon.

I have the same theory, the nginx proxy manager is surely missing some headers.

The funny thing is I have another working setup which is standard nginx > Recipes web app

This nginx container is using the standard config from Linux server SWAG and such config does not add any header, it's a simple config + /media mapping for images.

I'll keep you posted, I've also tested some headers but I can't remember which.

@chrisklpp
Copy link

chrisklpp commented Apr 4, 2021

Hey,
i have the same issue, accessing via the local ip with the exposed port works fine.
I found out, that using the standard https port (443) it seems to work, but for my local nginx installation i use 444 as a public port. With the 444 port it doesn't work and I receive the CSRF verification failed error. This might be related since @auanasgheps uses 8080 as a port with https?
I can provide my configuration files as well if it helps.

Thanks!

@vabene1111
Copy link
Collaborator

what does the broken image show as an url ? (right click copy address)

The image url is determined by django by the URL the application is running under. This itself is received trough the headers from the proxy (as far as i know).

Sadly there are just so many ways to configure this application to run that i cant tell you for each specific one why its not working.

@chrisklpp have you tried using * for allowed hosts ?

@chrisklpp
Copy link

@chrisklpp have you tried using * for allowed hosts ?

I tried * as well as the real, used domain name.

@vabene1111
Copy link
Collaborator

and both options give you a CSRF error ?

Could you please provide a structured explanation of you setup with the different services and configurations used for each service ?

@chrisklpp
Copy link

chrisklpp commented Apr 5, 2021

and both options give you a CSRF error ?

Could you please provide a structured explanation of you setup with the different services and configurations used for each service ?

Yes both options return the CSRF error in Chrome, Firefox and Safari, the following error message is shown:
csrf_error.txt
Between all my tests i deleted the browser cookies.

As said it works when the port 443 is used and when I access it locally on 192.168.X.X:8005.

The nginx installation is used for multiple selfhosted services, that all work fine on the 444 port (e.g. Seafile, Bitwarden via docker-compose, home-assistant). This is the used configuration for the recipes subdomain:
recipes.conf.txt
On my router i have port forwarding from 444 (external) to 443 on the server, where nginx is listening.

I installed it following the guide in the documentation with docker-compose with the following configuration files:
docker-compose.yml.txt
dotenv.txt

I tried it with multiple variations for the lines
VIRTUAL_HOST="recipes.[mydomainname].org"
VIRTUAL_PROTO="https"
VIRTUAL_PORT="444"
(completly removed, just the VIRTUAL_HOST, etc) without success.

Thanks for looking into it.

@vabene1111
Copy link
Collaborator

ok thanks for the info. I will try to look into this in the next few days, maybe it is time to add some kind of variable to define the application URL or something

@Nicras
Copy link

Nicras commented Apr 7, 2021

Hi, I had the same issue and fixed it.

Look into your nginx config if you have something like:

proxy_set_header Host $host:$server_port;

change it to:

proxy_set_header Host $http_host;

and it will work

@vabene1111
Copy link
Collaborator

Thanks for the feedback @Nicras if @chrisklpp and @auanasgheps could quickly report back if this worked after testing that would be great

@chrisklpp
Copy link

Thank you @Nicras, the solution works for me!

And thank you @vabene1111 for the help and the amazing software.

@DaFlowah
Copy link

DaFlowah commented Apr 7, 2021

Me and @auanasgheps should be able to try tomorrow.
Cheers guys!

@auanasgheps
Copy link
Contributor Author

auanasgheps commented Apr 8, 2021

Hi guys,

Adding proxy_set_header Host $http_host; to the Nginx Proxy Manager advanced config does not have any effect.

I believe this happens because by default it applies proxy_set_header Host $host; and I don't know how to change it. This file is inside a docker container which we cannot touch (it's running on Home Assistant).

So we're hitting a "limit" of this application and don't really know how to proceed. Any help is appreciated.

EDIT: I managed to temporarily edit the file and the config works resolving the issue, but it's not persistent since it's not an exposed file.
If somebody uses Nginx Proxy Manager it would be great to have a hint.

Either way this value should be added to the docs!

@vabene1111
Copy link
Collaborator

thanks for the feedback. I have never worked with nginx proxy manager and i am interested to see what the people who maintain it, who most likely know a lot more about this stuff than i do, have to say to this issue.

How do you think would this best fit into the docs ? Should we add a section for nginx proxy manager specifically or maybe some FAQ with CSRF errors 🤔

The problem here for me is that i do not fully understand how this works yet so a little uncertain right now.

@chrisklpp
Copy link

I could imagine a nginx sites-available/recipes.conf template could be useful as a part of the installation docs. I would assume many users have a seperate nginx installation managing the different selfhosted services with subdomains.
But as a start a FAQ entry that helps when someone searches the CSRF error would be helpful for sure.

@auanasgheps
Copy link
Contributor Author

auanasgheps commented Apr 8, 2021

I think you should add something like this, please adjust the wording since I'm writing from mobile

If you plan to access Recipes via an additional Nginx reverse proxy (e.g. You have a main nginx proxy exposed to the internet)

  • point it to the dedicated nginx that serves Recipes
  • add the following to the site config of the main nginx
    proxy_set_header Host $http_host;

Nginx Proxy Manager apparently does not allow for this change, therefore it doesn't work (link to this issue)

@vabene1111
Copy link
Collaborator

there are many different reverse proxy systems, when using the jwidler nginx proxy or traefik this change is NOT required so we need to list it as only required for Nginx Proxy manger right ?

@chrisklpp are you using just a default nginx as the reverse proxy ? Then the docs should probably say something like "when using any other nginx based proxy (not jwidler/traefik which i both tested) make sure to set proxy_set_header Host $http_host; to prevent CSRF isses" (rough idea)

@auanasgheps
Copy link
Contributor Author

auanasgheps commented Apr 8, 2021

I think this configuration is required with swag by linuxserver as well. Let me check my other setup.

@vabene1111
Copy link
Collaborator

yes that is likely, i remember people had problems there as well

@chrisklpp
Copy link

@chrisklpp are you using just a default nginx as the reverse proxy ? Then the docs should probably say something like "when using any other nginx based proxy (not jwidler/traefik which i both tested) make sure to set proxy_set_header Host $http_host; to prevent CSRF isses" (rough idea)

Yes, I use the default nginx that comes with Ubuntu Server (or is installed with aptitude)

@auanasgheps
Copy link
Contributor Author

auanasgheps commented Apr 9, 2021

Uhm, swag by linuserver requires a different config, which is
proxy_set_header X-Forwarded-Proto $scheme;

If I use proxy_set_header Host $http_host; I get a 400 error.

If I don't use any of those, I get a CSRF error.

@vabene1111
Copy link
Collaborator

i have added some information about this in the new faq section of the docs (not yet pushed)

@FlorentLM
Copy link

FlorentLM commented Apr 3, 2023

Hi,
Been having the issue with a Traefik v2 revserse proxy. The reason was my use of referrerPolicy: "no-referrer" header. Does this mean Django/Recipes uses the referrerPolicy header to check for CSRF? - if yes this is not ideal.

Setting the value to origin fixed the issue in Recipes btw.

@johndoe0815
Copy link

I think you should add something like this, please adjust the wording since I'm writing from mobile

If you plan to access Recipes via an additional Nginx reverse proxy (e.g. You have a main nginx proxy exposed to the internet)

* point it to the dedicated nginx that serves Recipes

* add the following to the site config of the main nginx
  `proxy_set_header Host $http_host;`

Nginx Proxy Manager apparently does not allow for this change, therefore it doesn't work (link to this issue)

I am a bit puzzled with that. I use Cloudflare->NGINX Proxy Manager->Local Service for many services, but for Tandoor I get the CSRF error after logging in. Now I get that I cannot solve that issue in NGINX Proxy Manager, but where and how in my docker stack would I now add this proxy_set_header statement? Can I just add this as an environment variable or how is it to be done?
Thanks for some more newbie friendly instructions :-)

@auanasgheps
Copy link
Contributor Author

As I said:

Nginx Proxy Manager apparently does not allow for this change

I do not use this software so I can't provide more instructions.

I posted this on behalf of a friend, he ended up using the nginx version I use (swag by linuxserver) with the modifications I mentioned.

@johndoe0815
Copy link

johndoe0815 commented Aug 11, 2023

As I am not able to resolve tha with my current capabilities:
@vabene1111 As far as I understand from my error message that appears after logging in

Verboten (403)

CSRF-Verifizierung fehlgeschlagen. Anfrage abgebrochen.
Help

Reason given for failure:

    Origin checking failed - https://recipes.mydomain.com 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:

this is the CSRF mechanisam from Django. As per https://docs.djangoproject.com/en/4.1/ref/settings/#std-setting-CSRF_TRUSTED_ORIGINS or https://stackoverflow.com/questions/75704235/django-csrf-verification-failed-request-aborted-in-production-without-domain I understand that it probably is necessary to put my origin domain as CSRF_TRUSTED_ORIGINS or completely disable the CSRF check. Would it be possible to have both options via environment variables?

@smilerz
Copy link
Collaborator

smilerz commented Aug 11, 2023

this is the CSRF mechanisam from Django. As per https://docs.djangoproject.com/en/4.1/ref/settings/#std-setting-CSRF_TRUSTED_ORIGINS or https://stackoverflow.com/questions/75704235/django-csrf-verification-failed-request-aborted-in-production-without-domain I understand that it probably is necessary to put my origin domain as CSRF_TRUSTED_ORIGINS or completely disable the CSRF check. Would it be possible to have both options via environment variables?

You can set CSRF_TRUSTED_ORIGINS env variable and Tandoor will use it.
Disabling CSRF won’t be added, it’s insecure and one should never disable security features as a shortcut to getting something working.

However, it is very unlikely that this is the root of your issue. Tandoor isn't doing anything that would trigger cross site scripting. Can you please share the headers that are listed on the 'system' page?

@johndoe0815
Copy link

johndoe0815 commented Aug 11, 2023

Thanks for pointing that out, I did not know that this env variable is considered (not included in the .env template, and in an old post I read that it is not implemented yet #409 (comment)).

Putting my exact URL into the CSRF_TRUSTED_ORIGINS allows login without any CRF error anymore! :-)
Probably this should be also mentioned somewhere in the docs, as it seems to be the only way for people using NPM in e.g. Home Assistant OS, like also a previous poster here in this thread.

But now the next problem occurs. After logging in, no recipes are displayed, just placeholders (I do see the recipes when I access via internal IP address):
grafik

This is what I see in the debug log:
`Gunicorn Media: False
Sqlite: False
Debug: True

SERVER_PROTOCOL:HTTP/1.0
REMOTE_ADDR:172.11.1.4
SERVER_PORT:8080

HTTP_HOST:rezepte.mydomain.de
HTTP_CONNECTION:close
HTTP_X_FORWARDED_SCHEME:http
HTTP_X_FORWARDED_PROTO:http
HTTP_X_FORWARDED_FOR:147.155.254.155, 172.20.22.10
HTTP_X_REAL_IP:172.20.22.10
HTTP_USER_AGENT:Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:109.0) Gecko/20100101 Firefox/116.0
HTTP_ACCEPT:text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,/;q=0.8
HTTP_ACCEPT_ENCODING:gzip
HTTP_ACCEPT_LANGUAGE:de,en-US;q=0.7,en;q=0.3
HTTP_CDN_LOOP:cloudflare
HTTP_CF_CONNECTING_IP:147.155.254.155
HTTP_CF_IPCOUNTRY:DE
HTTP_CF_RAY:7fer0daseer12bc5-FRA
HTTP_CF_VISITOR:{"scheme":"https"}
HTTP_CF_WARP_TAG_ID:3282c120-4999-484d-9999-d0fcaff28558
HTTP_COOKIE:cf_clearance=XXX; csrftoken=XXX
HTTP_DNT:1
HTTP_REFERER:https://rezepte.mydomain.de/search/
HTTP_SEC_FETCH_DEST:document
HTTP_SEC_FETCH_MODE:navigate
HTTP_SEC_FETCH_SITE:same-origin
HTTP_SEC_FETCH_USER:?1
HTTP_SEC_GPC:1
HTTP_UPGRADE_INSECURE_REQUESTS:1

wsgi.errors:<gunicorn.http.wsgi.WSGIErrorsWrapper object at 0x7f43ea926680>
wsgi.version:(1, 0)
wsgi.multithread:True
wsgi.multiprocess:True
wsgi.run_once:False
wsgi.file_wrapper:
wsgi.input_terminated:True
wsgi.input:<gunicorn.http.body.Body object at 0x7f43ea7111e0>
wsgi.url_scheme:http`

Is this an http/https problem?
If so, how is https being handled by tandoor?
I do not see any settings on this, the standard config also only uses port 80.
Cloudflared is set to force https and the login also works with that.

@smilerz
Copy link
Collaborator

smilerz commented Aug 11, 2023

HTTP_X_FORWARDED_SCHEME:http
HTTP_X_FORWARDED_PROTO:http
HTTP_REFERER:https://rezepte.mydomain.de/search/

Can you please open a new issue- your issue is different than the original.
This mismatch is likely the root cause of both of your issues.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
setup issue possibly or definitely an issue with the user setup
Projects
None yet
Development

No branches or pull requests

8 participants