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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With