Search code examples
nginxruby-on-rails-5digital-oceanpumanginx-config

'The change you wanted was rejected' error on all 'Devise' actions after installing SSL certificate


I configured nginx to use SSL certificate(got it from sslforfree.com) but a weird behavior is happening after that. Site is running fine but I'm unable to do any Devise action, e.g. If someone was logged in before using SSL, they can't logout and others can't login/register.

I'm configuring this on Digital-Ocean one-click rails droplet. Following observations may help:

Nginx.error.log

1 - client closed connection while SSL handshaking

2 - SSL_do_handshake() failed (SSL: error:1408F10B:SSL routines:ssl3_get_record:wrong version number) - I researched and found out it is happening due to problem in SSL configurations, I tried using Mozilla's generated ones but no success.

Rails Server Log

1 - 422 Unprocessable Entity

2 - ActionController::InvalidAuthenticityToken (ActionController::InvalidAuthenticityToken)

nginx.conf

upstream puma {
  server unix:///home/rails/apps/calwinkle/shared/tmp/sockets/calwinkle-puma.sock;
}

server {
  listen 80 default_server;
  listen [::]:80 default_server;

  server_name calwinkle.com www.calwinkle.com;

  # Redirect all HTTP requests to HTTPS with a 301 Moved Permanently response.
  return 301 https://$host$request_uri;
}

server {
  # listen   80;
  listen 443 ssl default_server;
  listen [::]:443 ssl default_server;

  server_name calwinkle.com www.calwinkle.com;
  ssl_certificate /etc/nginx/ssl/nginx.crt;
  ssl_certificate_key /etc/nginx/ssl/nginx.key;

  # intermediate configuration. tweak to your needs.
  ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
  ssl_ciphers 'ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS';
  ssl_prefer_server_ciphers on;

  root /home/rails/apps/calwinkle/current/public;
  access_log /home/rails/apps/calwinkle/current/log/nginx.access.log;
  error_log /home/rails/apps/calwinkle/current/log/nginx.error.log info;

  location ^~ /assets/ {
    gzip_static on;
    expires max;
    add_header Cache-Control public;
  }

  try_files $uri/index.html $uri @puma;
  location @puma {
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
    proxy_redirect off;
    proxy_pass http://puma;
  }

  error_page 500 502 503 504 /500.html;
  client_max_body_size 10M;
  keepalive_timeout 10;
}

What I think is, somehow my devise controller is still trying to access using http and I've redirected all http requests to https with 301 and this is causing authenticity token to expire.

I've tried to remove redirection and accept both http and https but that caused an error in nginx configuration.


Solution

  • Given your situation, it looks like you are setting wrong headers. So cookies/sessions are being saved on http. Can you try and add following two lines in your /etc/nginx/sites-available/* and /etc/nginx/sites-enabled/*

    proxy_set_header Host $http_host;
    proxy_set_header X-Forwarded-Proto https;
    

    After doing that run:

    sudo service nginx restart
    

    Additionally, clear your sessions and cookies in browser.

    If your site is live with users(which I don't think should be without https), you may need to destroy existing sessions of users.

    Hope it helps.