Accessing Yahoo Contacts Using the Ruby OAuth Gem
Posted by on March 30, 2011 in Technical DevelopmentRecently I implemented a feature for our up and coming referral program that lets you refer people using your Yahoo and Google contacts. As part of this I needed to work with Yahoo’s own implementation of the OAuth standard. This interaction caused me quite a bit of pain, so I decided to write up a little tutorial to help out other struggling with this problem.
In order to access a Yahoo contact your first order of business will be to get an application key and an application secret from https://developer.apps.yahoo.com/projects.
Yahoo verifies the callback url you provide to be from the same domain as what you registered for (you can’t register with localhost). Because of this you will need to override your hosts file to match your domain, in my case I had an entry like
127.0.0.1 www.sparqcode.com
With all that in place, you will need two oauth consumers: one to authenticate and one to actually consume the data from Yahoo.
def yahoo_oauth_consumer
OAuth::Consumer.new(YahooOauthCredentials::KEY,
YahooOauthCredentials::SECRET, {
:site => 'https://api.login.yahoo.com',
:scheme => :query_string,
:request_token_path => '/oauth/v2/get_request_token',
:access_token_path => '/oauth/v2/get_token',
:authorize_path => '/oauth/v2/request_auth'
})
end
def yahoo_calendar_consumer
OAuth::Consumer.new(YahooOauthCredentials::KEY,
YahooOauthCredentials::SECRET,
{
:site => 'http://social.yahooapis.com'
})
end
In your initial view, you need to redirect to Yahoo’s authorization URL.
request_token = yahoo_oauth_consumer.get_request_token(:oauth_callback => yahoo_callback_contact_import_url)
redirect_to request_token.authorize_url
Once your user has granted your application access to her contact list, you need to actually parse the response.
def yahoo_callback
if(params[:oauth_token] && params[:oauth_verifier])
request_token = OAuth::RequestToken.new(yahoo_oauth_consumer, session['request_token'], session['request_secret'])
access_token = request_token.get_access_token(:oauth_verifier => params[:oauth_verifier])
access_token.consumer = yahoo_calendar_consumer
yahoo_guid = access_token.params[:xoauth_yahoo_guid]
response = access_token.get("/v1/user/#{yahoo_guid}/contacts?format=json&count=max")
json = ActiveSupport::JSON.decode(response.body)
@name_email_map = parse_yahoo_contacts_response(json)
end
end
def parse_yahoo_contacts_response(json)
name_email_map = {}
return name_email_map if json['contacts']['contact'].nil?
json['contacts']['contact'].each do |contact|
name = nil
email = nil
contact['fields'].each do |field|
field['type']
if field['type'] == 'name'
name = "#{field['value']['givenName']} #{field['value']['familyName']}"
end
if field['type'] == 'email'
email = field['value']
end
end
if(email)
name ||= email
name_email_map[name] = email
end
end
name_email_map
end
Any questions please leave a comment and I’ll do my best to answer.
Full code for handling storing session variables and redirecting
def yahoo_import
request_token = yahoo_oauth_consumer.get_request_token(:oauth_callback => yahoo_callback_contact_import_url)
session['request_token'] = request_token.token
session['request_secret'] = request_token.secret
redirect_to request_token.authorize_url
end
def yahoo_callback
if(params[:oauth_token] && params[:oauth_verifier])
request_token = OAuth::RequestToken.new(yahoo_oauth_consumer, session['request_token'], session['request_secret'])
access_token = request_token.get_access_token(:oauth_verifier => params[:oauth_verifier])
yahoo_guid = access_token.params[:xoauth_yahoo_guid]
access_token.consumer = yahoo_calendar_consumer
yahoo_guid = access_token.params[:xoauth_yahoo_guid]
response = access_token.get("/v1/user/#{yahoo_guid}/contacts?format=json&count=max")
json = ActiveSupport::JSON.decode(response.body)
@name_email_map = parse_yahoo_contacts_response(json)
end
end
You can follow any responses to this entry through the RSS 2.0 You can leave a response, or trackback.

Hi!
Thanks for the great post. I have spent like 6-7 hours fixing oauth issues with yahoo and I must say yahoo has a really bad implementation of oauth. I googled my way to your post but unfortunately i couldn’t get it to work.
I have couple of questions will be great if you could answer.
you use session['request_token'], session['request_secret'] .. but you never put those things in the session..
also currently i am getting the error invalid signature.. can you help me out with this.
thanks
This is how we handle storing of session variables. Hope this helps.
def yahoo_import
request_token = yahoo_oauth_consumer.get_request_token(:oauth_callback => yahoo_callback_contact_import_url)
session['request_token'] = request_token.token
session['request_secret'] = request_token.secret
redirect_to request_token.authorize_url
end
def yahoo_callback
if(params[:oauth_token] && params[:oauth_verifier])
request_token = OAuth::RequestToken.new(yahoo_oauth_consumer, session['request_token'], session['request_secret'])
access_token = request_token.get_access_token(:oauth_verifier => params[:oauth_verifier])
yahoo_guid = access_token.params[:xoauth_yahoo_guid]
access_token.consumer = yahoo_calendar_consumer
yahoo_guid = access_token.params[:xoauth_yahoo_guid]
response = access_token.get(“/v1/user/#{yahoo_guid}/contacts?format=json&count=max”)
json = ActiveSupport::JSON.decode(response.body)
@name_email_map = parse_yahoo_contacts_response(json)
end
end