The current example on the AOL/AIM site leaves out details an functions. Here is my quick guide to using open auth with Ruby on Rails.
Step 1: Get a DEVID. For referer use http://yourhost:youport/auth/signin
Step 2: set DEVID in your environment.rb file to the value you were given
Step 3: Copy this controller (setup an index_url map in routes.rb or change references to index_url below)
class AuthController < ApplicationController def signin redirect_to "http://api.screenname.aol.com/auth/login?devId=#{DEVID}&f=xml&succUrl=http://" + request.host + ':' + request.port.to_s + "/auth/signedin"; end # this is where SUCCESSURL points def signedin xml_data = params[:res] if xml_data.empty? # token fetch failed. Try againa # will this work? => redirect_to signin redirect_to "http://api.screenname.aol.com/auth/login?devId=#{DEVID}&f=xml&succUrl=http://" + request.host + ':' + request.port.to_s + "/auth/signedin"; end token="" doc=REXML::Document.new(xml_data) doc.elements.each('response/data/token/a') do |t| token=t.text end session[:aim_token] = token #save in case we need more requests if token.empty? flash[:error] = "We had, ummm, a problem logging you in." redirect_to index_url end # We have the token. Now lets get their loginId url="http://api.screenname.aol.com/auth/getInfo?devId=#{DEVID}&f=xml&referer=#{referer()}&a="+token logger.info("getting " + url) req = handy_get(url,3) info_doc = REXML::Document.new(req[:body]) login_id = "" info_doc.elements.each('response/data/userData/loginId') do |l| login_id = l.text end logger.info("login_id:") logger.info(login_id) if login_id.empty? flash[:error] = "Unable to get your screenname." redirect_to index_url else session[:login_id] = login_id # We have the login Id. Now we can access any # local data we have about the user (Add DB code here if necessary) # if you were using a filter to protect sections of your site use these sessions to send them back if session[:intended_url] redirect_to session[:intended_url] else if session[:intended_action] && session[:intended_controller] redirect_to url_for(:controller => session[:intended_controller], :action => session[:intended_action]) else redirect_to index_url end end end end private def referer return "http://" + request.host + ':' + request.port.to_s + "/auth/signin" end def handy_get(url,timeout=3) uri = URI.parse(url) http = Net::HTTP.new(uri.host,uri.port) path=uri.path if uri.query path=uri.path+"?"+uri.query end logger.info(["combined path:",path]) g = Net::HTTP::Get.new(path) http.read_timeout = timeout begin res = http.start { |web| web.request(g) } rescue Timeout::Error return { :status => "fail", :body => "" } else logger.info(["g:",g]) logger.info(["http:",http]) logger.info(["res:",res]) return { :status => "ok", :body => res.body } end end end
Step 4: goto http://yourhost:yourport/auth/signin you should get a signin screen that redirects back to our site when done.
Step 5: Do something useful. Protect a controller
We'll also leverage the session[:intended_action] and session[:intended_controller] items referenced in the signedin function above.
Here we have an Admin controller that checks if the user is an admin using a filter. Currently it lets anyone who is authenicated in but you can fill in that code. ;-)
class AdminController < ApplicationController before_filter :check_admin_auth def index render :text => 'welcome ' + session[:login_id] end private def check_admin_auth unless session[:login_id] session[:intended_action] = action_name session[:intended_controller] = controller_name redirect_to :controller => 'auth', :action => 'signin' else # add logic here to check the login_id to see if is allowed to access # this area. Where appropriate end end end
Step 6: goto http://yourhost:yourport/admin and you will either get the sign in screen or a welcome message if you are already signed in.
Step 7: Steal this code, make it better and share it