Authenticating OpenID’s
Some of the best web apps around don’t make you login to use them, but then, some do. Lets not mess about writing endless code to create and manage and delete and administrate and recover accounts! We can just pop in some OpenID code and make someone else do all the hard work!
For this you'll need to install JanRain’s OpenID gem: “gem install openid”
module Camping::Controllers
include Camping::Sessions
class Login < R '/login'
def get
require 'openid'
this_url = 'http:' + URL('/login').to_s
unless input.finish.to_s == '1'
# start doing the auth here
begin
request_state = Hash.new
oid_request = OpenID::Consumer.new(request_state, nil).begin(input.openid_identifier)
oid_request.return_to_args['finish'] = '1'
@state.openid_request = Marshal.dump(request_state)
redirect(oid_request.redirect_url('http:' + URL('/').to_s, this_url))
rescue OpenID::DiscoveryFailure
return 'Couldn\'t find an OpenID at that address, are you sure it is one?'
end
else
# finish the auth here
request_state = Marshal.restore(@state.openid_request)
response = OpenID::Consumer.new(request_state, nil).complete(input, this_url)
@state.delete('openid_request')
case response.status
when OpenID::Consumer::SUCCESS
@state.identity = response.identity_url.to_s
return redirect(R(HomeScreen))
when OpenID::Consumer::FAILURE
'The OpenID thing doesn\'t think you really are that person, they said: ' + response.message
end
end
end
end
end
You’ll need to change this code up a bit for your app. Near the end where it say’s “return redirect(R(HomeScreen))” go right ahead and change that up for where ever you want your user’s to go when they're logged in. You could also make the error messages more fancy than a lump of text outputted to the browser if you like. Finally you’ll need to make a form some place with it's action pointing at the Login class, and an input with the name 'openid_identifier', and a submit button would be nice too.
Oh, one more thing! Go get an ID Selector and pop the code in to your layout too, it will make it easier for user's to login to your website who’ve never even heard of OpenID!
Checking if they logged in
Okay, so now you have a login system, you'll be wanting to make some of your controllers only accessible to people logged in, and maybe even do different stuff depending on who it is. @state.identity is who it is. It's a string containing a URL (or maybe an ‘XRI’, just to confuse you). That’s how OpenID works folks, URL’s like usernames. So to make sure someone is logged in inside one of your controllers...
module Camping::Controllers
include Camping::Sessions
class SuperSecret < R('/super-secret')
def get
return redirect('/login') unless @state.identity
"You’re logged in so you get to know the secret, here it is: Jack Russell Terriers are secretly running America via an underground system of tubes that all lead in to a little room where they vote democratically on world issues inside the earth’s core! It’s hot in there, and if you listen really carefully while sitting on the edge of an active volcano, sometimes you can hear their panting."
end
end
end
Oh great astute pony, tell me how I can know who my user's are!
Aha! Something more than anonymity you want? Go right ahead and ask their OpenID provider. I haven't done this, but it's totally possible using something called "Attribute Exchange". Check out the docs for the library and read the source code in their rails consumer example to see how you request that information, and how you access it when the user has logged in. The user will be asked if they’d like to send you that information when they log in, but be aware that some ‘Identity Providers’ like AOL and Yahoo! don't send this information at all, so it is probably best used only to pre-fill forms when it's available. If you have any trouble while setting up, I recommend you get an account over at myopenid.com and login with that because their service gives out really useful error messages whenever anything is wrong.
