OpenID makes sense. Dr. Nick’s multi-OpenIDs per user example app makes even more sense.
In the middle of integrating it into my project, gem-1.0.1 came out and broke ruby-openid-1.1.4. Dr. Nick’s great example no longer worked!
A little digging and I found Dr. Nick’s example uses the standard open_id_authentication. That has a patch to work on ruby-openid-2.0.2 and rails 2 which can be found here.
So in a nutshell, I grabbed openidauth_multiopenid-0.3.2 from Dr. Nick, removed a bunch of stuff from vendor plugins. Updated Rakefile, config/boot.rb, and config/environment.rb for rails 2.0.2. Patched vendor/plugins/open_id_authentication for ruby-openid-2.0.2. Regenerated db/migration/002_add_open_id_authentication_tables.rb. And installed ruby-openid-2.0.2 as a system gem.
As a little code is worth more than a thousand words, here is Dr. Nick’s example application fully ported to rails 2.0.2 in ZIP and TAR.gz.
For my port of Dr. Nick’s example above to work, you will need rails-2.0.2 and ruby-openid-2.0.2 installed as a gems.
Security Update: January 4th, 2007 I noticed the example adds edit, update, and destroy to users_controller.rb usingparams[:id]
thus allowing any logged in user to edit, update, and destroy any user of the system. To fix, simply change the first line of edit, update, and destroy to use the current logged in user (i.e. @user = User.find(self.current_user.id)
).
Another Update:February 27th, 2007 One of my clients noticed the user_openids_controller’s index method finds all openids for all users if you surf to user_openids URL. To fix, change the find in user_openids_controller.index to be
@user_openids = UserOpenid.find_all_by_user_id(@user.id)
. I think it’s time I put this example under SVN and apply these security upates…
It should look something like this under rails 2.0.2:
http://drnicwilliams.com/2007/07/26/sample-app-rails-multiple-openids-per-user/
http://dev.rubyonrails.org/ticket/10604
http://openidenabled.com/ruby-openid/
http://svn.rubyonrails.org/rails/plugins/open_id_authentication/
http://openid.net/
Got me stumped…I suspect it is Yahoo’s problem though.
I looked at the ruby code it all looks OpenID 2.0…
The example consumer from ruby-openid exhibits the same problem for me: http://openidenabled.com/ruby-openid/trunk/examples/consumer
I’ll investigate this further next week when Yahoo has an open beta.
-Thanks
Great job…I didn’t want to start a project with openid unless I could get openid 2.0 to work and this is just what I needed.
If you have a space before or after the openid url inside the login box, it craps out. Spaces need to be “strip”ed out.
Has anyobdy figured anything else out about yahoo openid and ruby-openid? I implemented the 2.0 patched plugin on our system and both Yahoo and Flickr openid fails.
I have gotten the signin part to work, but not simple registration attribute exchange.
You are most likely running into the extra security hoops Yahoo makes you run through. For example, localhost:3000 will not work while http://myutil.com/ will work. This is from the Yahoo OpenID developers FAQ:
-face
Yeah. I figured that out shortly after I commented earlier. Now I am running into a problem with normalize_url throwing an exception:
{{{ OpenIdAuthentication::InvalidOpenId (bad URI: http://): /vendor/plugins/open_id_authentication/lib/open_id_authentication.rb:69:in `normalize_url’ /vendor/plugins/open_id_authentication/lib/open_id_authentication.rb:74:in `normalize_url’ /vendor/plugins/open_id_authentication/lib/open_id_authentication.rb:85:in `authenticate_with_open_id’ /app/helpers/open_ids_helper.rb:7:in `open_id_authentication’ }}}
The redirect to yahoo still completes so I am not real sure what is going on here.
I can’t reproduce the problem from the console either. Wrapping the two calls to URI.parse in begin/rescue blocks it seems that the exception is being thrown from line 65:
{{{ uri = URI.parse(“http://#{uri}”) unless uri.scheme }}}
Ok, so after digging through my logs and adding some debug statements, it looks like the Yahoo OpenId API is calling the return_to url with an HTTP GET and no parameters as it processes the initial request. So, since there are no params, :open_id_complete isn’t set so begin_open_id_authentication and normalize_url get called with a null identity_url which causes an error in normalize_url at line 65.
I’m adding:
as the first line in authenticate_with_open_id.
I’ll blog this and submit a patch to the plugin tomorrow.
You also might need to handle OpenIdsHelper#open_id_authentication returning false.
Thanks Jesse. The algorithm should tack on open_id_complete=1 to your return URL before it goes out to Yahoo.
begin_open_id_authentication calls open_id_redirect_url which tacks on open_id_request.return_to_args[‘open_id_complete’] = ‘1’.
So, as your return URL already has the open_id_completed = 1, you should get it back from Yahoo.
At least this is what happens in Dr. Nicks example that I ported to OpenID 2 (attached)...
Hope this helps, -face
It does tack the open_id_complete param on when it redirects AFTER openid authentication completes. What I’m saying is that Yahoo pings the return_to url once BEFORE authenticating without ANY parameters. No identity_url, no open_id_complete no nothing. This was leading to the bug I described in my previous comment.
-jesse
Thanks for clarifying…..You are correct. I missed this because Yahoo pings my root index, which doesn’t require authentication and hence doesn’t trigger an exception for me.
Where you get an exception, I get something like:Thanks again Jesse,
-face
hi,
i left my project before rails 2 was released, when i tried to make it work again under rails 2.0 i got stuck at this OpenID bit.
i had rails 2.0.2 and openid gem 2.0.4 installed, when i tried to run your example app, i’ve got this on the console, is there anything that i missed? thanks.
c:/ruby/lib/ruby/gems/1.8/gems/activesupport-2.0.2/lib/active_support/dependencies.rb:263:in `load_missing_constant’: uninitialized constant OpenID::OpenIDError (NameError) from c:/ruby/lib/ruby/gems/1.8/gems/activesupport-2.0.2/lib/active_support/dependencies.rb:453:in `const_missing’ from c:/ruby/lib/ruby/gems/1.8/gems/ruby-openid-2.0.4/lib/openid/protocolerror.rb:6 from c:/ruby/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:27:in `gem_original_require’ from c:/ruby/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:27:in `require’ from c:/ruby/lib/ruby/gems/1.8/gems/activesupport-2.0.2/lib/active_support/dependencies.rb:496:in `require’ from c:/ruby/lib/ruby/gems/1.8/gems/activesupport-2.0.2/lib/active_support/dependencies.rb:342:in `new_constants_in’ from c:/ruby/lib/ruby/gems/1.8/gems/activesupport-2.0.2/lib/active_support/dependencies.rb:496:in `require’ from c:/ruby/lib/ruby/gems/1.8/gems/ruby-openid-2.0.4/lib/openid/consumer/idres.rb:2 ... 43 levels… from c:/ruby/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:27:in `require’ from ./script/server:3 from -e:2:in `load’ from -e:2
The year on security updates is incorrect, should be Security Update: January 4th, 2008 instead of Security Update: January 4th, 2007
I’m putting together a rails project based on your code, and a minor bug bit me. Thought I’d share it :-)
In the test data, user “quentin” has both an activation_code and an activated_at field. The code in /app/models/user.rb assumes that a user has either one or the other, but not both. You could fix this assumption in user.rb by changing the function “activated?” to use the activated_at field instead of the activation_code field. Or you could fix user “quentin” to only have “activated_at” (and maybe make a new test user who isn’t activated?). Or both.
Hm. Or you can just remove the activation code from the “quentin” test data. So maybe the simple solution will work just fine :-)
Also: local site users, the ones who just create an account, require activation to log in. While the activation code stuff is mostly there, it looks like config/routes.rb doesn’t bother to install the necessary route to make it work. The route should look like:
map.connect ‘activate/:activation_code’, :controller => “users”, :action => “activate”
I don’t have email set up properly on my machine, but if I pull the activation code out of the database and use the URL the email should send, this works for me.
And in case anybody is also using this code and still reading comments… The UserObserver class needs to be registered in config/environment.rb for the registration code to work, and the registration code needs to work for site accounts to work beyond the initial login. There’s a line to register it there already, but it’s commented out.
downloaded the code, i have rails 2.0.2 when i “gem list” i see i have “ruby-openid (2.0.4)” yet when i try to start the server running your code compliation i get ”`require’: no such file to load—openid/extensions/sreg (MissingSourceFile)” while my console also tells me to “Install the ruby-openid gem to enable OpenID support”. I can CD to the folder and see the file it claims i’m missing. Could there be a broken path or link somewhere or a way i can point my application to the correct folder??
multi-OpenID is not working anymore after I upgrade to Rails 2.2.2. It was working still at Rails 2.1. Something about the relative_url_root being deprecated after 2.1. Anyone has any solutions? I googled for a night but couldn’t find one.