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