docusealco / docuseal

Open source DocuSign alternative. Create, fill, and sign digital documents ✍️
https://www.docuseal.co
GNU Affero General Public License v3.0
6.09k stars 428 forks source link

HTTP 422 nginx reverse proxy #22

Closed dib0 closed 1 year ago

dib0 commented 1 year ago

Hi,

I just setup DocuSeal using docker. It is behind a NGinx reverse proxy, doing SSL. But I get a HTTP 422 on signing in or doing the setup. The setup works using the url+port on the local network. Any word of advise? (If you need more info, please let me know):

image

AlexandrToorchyn commented 1 year ago

@dib0 Can you share your logs - it might be because of the CSRF protection Make sure you specity HOST=your-ssl-domain-name env variable when running Docuseal in docker. You can add HOST var in the docuseal/docuseal.env file. Or add it when running your docker container with -e HOST=domain

dib0 commented 1 year ago

Ah.. alright. That helps a bit, I was reading the logs wrong. The HOST variable is set to https://subdomain.domain.com The logs say: ActionController::InvalidAuthenticityToken (HTTP Origin header (https://subdomain.domain.com) didn't match request.base_url (http://subdomain.domain.com)):

So my thoughts are the since the website is running on http internally, it assumes http instead of https? Is there a setting to force it to https?

dib0 commented 1 year ago

All right. You comment allowed me to solve the issue. Just adding it here, maybe it will help someone else.

Looking through the docker-compose (https://github.com/docusealco/docuseal/blob/master/docker-compose.yml) I found the env variable "FORCE_SSL". Setting that to 'true' only resulted in the application being redirected in a loop.

After some searching I found the following post on Ruby on Rails and NGinx as a reverse proxy: https://stackoverflow.com/questions/65688157/why-is-my-http-origin-header-not-matching-request-base-url-and-how-to-fix

This solved the issue. So just needed the right headers. Here's my nginx configuration:

server {
    server_name subdomain.domain.com;
    listen 443 ssl;

    ssl_certificate /path/to/pem;
    ssl_certificate_key /path/to/pem;
    ssl_session_timeout 1d;
    ssl_session_cache shared:SSL:50m;
    ssl_session_tickets off;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers 'EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH';
    ssl_prefer_server_ciphers on;
    ssl_dhparam /path/to/pem;

    proxy_buffering off;

    location / {
        proxy_pass http://internal_ip:exposed_port_docker
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto https;
        proxy_set_header X-Forwarded-Server $host;
        proxy_set_header Upgrade $http_upgrade;

        proxy_hide_header X-Powered-By;
        proxy_hide_header Server;
        add_header X-Frame-Options SAMEORIGIN;
        add_header Permissions-Policy "interest-cohort=(); vibrate=(); geolocation=(); midi=(); notifications=(self); push=(); sync-xhr=(self); microphone=(); camera=(); magnetometer=(); gyroscope=(); speaker=(); fullscreen=(); payment=()";
        add_header X-Xss-Protection "1; mode=block";
        add_header X-Content-Type-Options nosniff;
        add_header Referrer-Policy no-referrer-when-downgrade;
        add_header Expect-CT enforce,max-age=30;
        add_header Strict-Transport-Security "max-age=31536000; includeSubDomains";
        add_header Cross-Origin-Embedder-Policy "(unsafe-none|require-corp); report-to='default'";
        add_header Cross-Origin-Resource-Policy "(same-site|same-origin|cross-origin)";
        add_header Cross-Origin-Opener-Policy "(same-origin|same-origin-allow-popups|unsafe-none); report-to='default'";
        add_header X-Permitted-Cross-Domain-Policies "none;";
    }
}
adamency commented 3 months ago

@dib0 @AlexandrToorchyn There's absolutely no need for the host env var even when using docker, if it's behind a reverse proxy. The only issue causing the 422 is mssing this setting:

proxy_set_header X-Forwarded-Proto https;

For Apache/httpd, it's:

RequestHeader set X-Forwarded-Proto "https"

That's it.

Your CORS settings and other special stuff are useless as long as you don't use externally hosted storage.