Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Omniauth and open_id with Google broken when running behind nginx in SSL mode

Rails 3.0.12, newest omniauth, I can connect to Google and get the user's email address just fine. But then I run that same rails app behind nginx in SSL mode, and it fails with the Google page:

"The page you requested is invalid."

Is it my nginx config? My omniauth setup?

I know the X-Forwarded-Proto: https is the special sauce here, is there anything else I need to do to get openid happy behind an SSL web server?

Here's the full example code: you can clone this repo, bundle install, and run rails s to see it work just fine, then run rake server to see it fail. https://github.com/jjulian/open_id_ssl

nginx.conf:

worker_processes  2;
pid        tmp/nginx.pid;
error_log  log/error.log;
daemon     off;

events {
}

http {
  client_body_temp_path tmp/body;
  proxy_temp_path       tmp/proxy;
  fastcgi_temp_path     tmp/fastcgi;
  uwsgi_temp_path       tmp/uwsgi;
  scgi_temp_path        tmp/scgi;

  server {
    listen 3000 ssl;
    ssl_certificate      development.crt;
    ssl_certificate_key  development.key;
    ssl_verify_depth     6;

    access_log log/access.log;
    proxy_buffering off;
    location / {
      proxy_pass        http://127.0.0.1:3300;
      proxy_set_header  X-Real-IP        $remote_addr;
      proxy_set_header  X-Forwarded-For  $proxy_add_x_forwarded_for;
      proxy_set_header  Host             $http_host;
      proxy_redirect    off;
      proxy_set_header  X-Forwarded-Proto https;
    }
  }
}

omniauth.rb initializer:

require 'openid/store/filesystem'

Rails.application.config.middleware.use OmniAuth::Builder do
  provider :open_id, :identifier => 'https://www.google.com/accounts/o8/id'
end

routes.rb:

OpenIdSsl::Application.routes.draw do
  match '/auth/open_id/callback' => 'accounts#update'
  match '/auth/failure' => 'accounts#failure'
  root :to => 'accounts#show'
end

UPDATE: This example used Rails 3.1.12 and OmniAuth 1.0.3. Upgrading to Rails 3.1.4 and OmniAuth 1.1.0 fixes the issue.

like image 370
Jonathan Julian Avatar asked Apr 05 '12 16:04

Jonathan Julian


1 Answers

Found your problem, I am still trying to find something cleaner but here is the quick & dirty fix:

add this in your config/initializers/omniauth.rb:

class Rack::OpenID
  def realm_url(req)
    'https://localhost:3000'
  end
end

And now for the explanation: when the rack-openid gem builds the request to send to the google openid server it fails in one spot using the rails application access url and not the nginx one (wich uses ssl) resulting in this being sent to the openid server:

openid.realm:http://localhost:3001
openid.return_to:https://localhost:3001/auth/open_id/callback

The realm use the http url (rails url) while the return_to points to the right https url (nginx), when the openid server sees this it stops and return an error.

PS: I will edit the answer if I manage to find a cleaner way.

like image 136
Schmurfy Avatar answered Oct 23 '22 02:10

Schmurfy