How to fetch fields that require access token using fbgraph - ruby-on-rails

I am trying to fields that require access token, fields like age_range, here are the list of fields
https://developers.facebook.com/docs/reference/api/user/
user = FbGraph::User.new('me', :access_token => access_token).fetch
I am trying
user.age_range #=> nil
Where as when i am trying in facebook graph api explorer using http://developers.facebook.com/tools/explorer
facebook_id?fields=age_range
It shows the Json data for the same user.

Did it using omniauth ,Added info_fields with scope
provider :facebook, facebook_app_id, facebook_secret_key, { :info_fields => 'age_range', :scope => 'email,offline_access' }

Related

how to properly authenticate user with devise_token_auth rails gem?

I am trying to write a simple test for a URL which should be visible only to logged in user (I use before_action :authenticate_user! to achieve this).
Even though I (think) that I properly assign all the headers I always get JSON response {"errors":["Authorized users only."]}
My test looks like this (Login (to get header info) then visit protected URL with all the headers needed)
post "/api/v1/auth/sign_in", {:email => user.email, password: 'password'}
header_hash = {
'access-token' => response.headers['access-token'],
'uid' => response.headers['uid'],
'client' => response.headers['client'],
'expiry' => response.headers['expiry']
}
get "/api/v1/subscription_status", nil , header_hash
What am I doing wrong?
I didn't know that authentication token is changing on each request by default.
conf/device_token_auth.rb
config.change_headers_on_each_request = false
I set this setting to false and afterwards I got responses which I expected.

How do I insert X-PAYPAL headers with Rails Invoice SDK?

I'm using the paypal SDK for invoicing located here:
https://github.com/paypal/invoice-sdk-ruby
This works great.
I integrated the paypal permissions SDK for rails:
https://github.com/paypal/permissions-sdk-ruby
The authorization workflow is working great.
So now I need to put them together. The documentation for the permissions sdk leaves off after you get your token. It doesn't explain how to use it with the other paypal SDKs (at least not so I could understand :D ) The invoice sdk tells you to see the Auth sdk.
Paypal tells me:
# Third-party Auth headers
-H "X-PAYPAL-SECURITY-SUBJECT:<receiverEdress>" # Merchant's PayPal e-mail
-H "X-PAYPAL-AUTHENTICATION:<OAuthSig>" # Generated OAuth Signature
Don't know how to insert that. The request is generated here in my model:
#create_and_send_invoice = api.build_create_and_send_invoice(paypalized || default_api_value)
The data itself is assembled in the invoice model like so:
paypalized = {
:access_token => self.user.paypal_token,
:invoice => {
:merchantEmail => self.user.paypal_email || self.user.email,
:payerEmail => self.client.email,
:itemList => #itemlist,
:currencyCode => "USD",
:paymentTerms => "DueOnReceipt",
:invoiceDate => self.updated_at,
:number => self.name,
:note => self.description,
:merchantInfo => #businessinfo
# project / Invoice title?
} # end invoice
} # end paypalized
return paypalized
This implementation is not working and the access_token field is being rejected. I looked through the gems associated with the sdks but can't see where the headers themselves are built or how to interact with that.
UPDATE: Found this which gives me a clue...
INVOICE_HTTP_HEADER = { "X-PAYPAL-REQUEST-SOURCE" => "invoice-ruby-sdk-#{VERSION}" }
This seems to be used here during calls in the paypal-sdk-invoice gem:
# Service Call: CreateAndSendInvoice
# #param CreateAndSendInvoiceRequest
# #return CreateAndSendInvoiceResponse
def CreateAndSendInvoice(options = {} , http_header = {})
request_object = BuildCreateAndSendInvoice(options)
request_hash = request_object.to_hash
...
I notice that there's two arguments: options and http_header. It's possible I can modify the http_header argument and pass it this way in my controller:
#create_and_send_invoice_response = api.create_and_send_invoice(#create_and_send_invoice, #cutsom_header)
or maybe
#create_and_send_invoice = api.build_create_and_send_invoice(data, custom_header)
I'll keep this updated since I googled around a lot and couldn't find any clear answers on how to do this...
You have to pass the token and token_secret while creating API object for third-party authentication.
#api = PayPal::SDK::Invoice::API.new({
:token => "replace with token",
:token_secret => "replace with token-secret" })

Rails, OmniAuth, google_oauth2, google-api-client, Moments.insert... 401 unauthorized... why?

I haven't been able to find an answer to this online -- aside from using the Google+ Sign In button, which I don't want to use at this point because I don't want to get into Javascript if I don't have to.
I have a Ruby on Rails application (ruby v1.9.3, rails v3.2.13) in which I've hooked up OmniAuth and I'm using the google_oauth2 gem to integrate with Google+.
My simple goal is to allow a user to authenticate with Google+, grant access to my Google API project, and then be able to post a moment to the Google+ user's vault using the google-api-client gem.
I have already setup my Google API Project, created the OAuth 2.0 for Web Applications, and enabled Google+ API service.
I have OmniAuth setup with the following provider and I've added the request_visible_actions option to allow me to post (I think this is correct but haven't seen this used from any code examples I've looked at online...):
provider :google_oauth2, CLIENT_ID, CLIENT_SECRET, {
access_type: 'offline',
scope: 'userinfo.email,userinfo.profile,plus.me,https://www.googleapis.com/auth/plus.login',
request_visible_actions: 'http://schemas.google.com/AddActivity',
redirect_uri: 'http://localhost/auth/google_oauth2/callback'
}
When I redirect my user to /auth/google_oauth2, it sends the user to Google+ to authorize my app and when the user approves, it returns to my callback where I can access the request.env["omniauth.auth"] and it has all the information I would expect, including tokens, email address, etc. I'm storing the access_token from auth["credentials"]["token"].
So far so good, right?
When I try to post the moment using the following code, I encounter an exception indicating a 401 unauthorized error.
client = Google::APIClient.new
client.authorization.access_token = self.access_token
plus = client.discovered_api('plus', 'v1')
moment = {
:type => 'http://schemas.google.com/AddActivity',
:target => { :id => Time.now.to_i.to_s,
:description => message,
:name => message
}
}
# post a moment/activity to the vault/profile
req_opts = { :api_method => plus.moments.insert,
:parameters => { :collection => 'vault', :userId => 'me', },
:body_object => moment
}
response = client.execute!(req_opts).body
I have also tried replacing
client.authorization.access_token = self.access_token
with
credentials = Hash.new
credentials[:access_token] = self.access_token
credentials[:refresh_token] = self.refresh_token
credentials[:expires_at] = self.expires_at
client.authorization.update_token!(credentials)
But no luck.
I think the issue either has to do with:
OmniAuth not issuing the request_visible_actions to Google correctly
Me not setting the token in the Google::APIClient object properly
I've gotten this far using the following resources, but I'm officially stuck:
http://blog.baugues.com/google-calendar-api-oauth2-and-ruby-on-rails
https://developers.google.com/+/api/latest/moments/insert
Any ideas would be appreciated!
Here is my working code from web app using 'omniauth-google-oauth2' along with 'google-api-client'. This sample code uses calendar API, but I guess it will work for you.
require 'google/api_client'
class Calendar
def initialize(user)
#user = user
end
def events
result = api_client.execute(:api_method => calendar.events.list,
:parameters => {'calendarId' => 'primary'},
:authorization => user_credentials)
result.data
end
private
def api_client
#client ||= begin
client = Google::APIClient.new(application_name: 'xxx', application_version: '0.0.1')
client.authorization.client_id = ENV["GOOGLE_KEY"]
client.authorization.client_secret = ENV["GOOGLE_SECRET"]
client.authorization.scope = 'https://www.googleapis.com/auth/calendar'
client
end
end
def calendar
#calendar ||= api_client.discovered_api('calendar', 'v3')
end
def user_credentials
auth = api_client.authorization.dup
# #user.credentials is an OmniAuth::AuthHash cerated from request.env['omniauth.auth']['credentials']
auth.update_token!(access_token: #user.credentials.token)
auth
end
end
In the API console, did you register as a Web application or installed application?
I think for your case you must choose the installed application, so that the token is valid if user is not online.
Try changing https://www.googleapis.com/auth/plus.login with just plus.login. Its working for me with the same setup.

New LinkedIn Permissions Problems (Rails omniauth-linkedin gem)

I'm using the omniauth-linkedin gem for my rails application:
https://github.com/skorks/omniauth-linkedin
It should be taking into account new LinkedIn permissions request procedures and scopes, but I am not having success obtaining either email addresses or full profiles (anything other than the default profile overviews).
Here is my omniauth.rb file:
Rails.application.config.middleware.use OmniAuth::Builder do
provider :linkedin, ENV['LINKEDIN_KEY'], ENV['LINKEDIN_SECRET'], :scope => 'r_fullprofile r_emailaddress'
end
The full profile and email address request are going through to LinkedIn initially, before the user enters her/his credentials. However, the scope requests are lost once the user signs in, and only the default profile overview information is accessible.
I think my problem has something to do with having to specifically request those fields within the scopes that I want, as is mentioned on the gem page (https://github.com/skorks/omniauth-linkedin). Still, I have tried adding specific field requests to my omniauth.rb file with no success (email field request below):
Rails.application.config.middleware.use OmniAuth::Builder do
provider :linkedin, ENV['LINKEDIN_KEY'], ENV['LINKEDIN_SECRET'], :scope => 'r_fullprofile+r_emailaddress',
:fields => ["id", "email-address", "first-name", "last-name", "headline", "industry", "picture-url", "public-profile-url", "location", "positions", "educations"]
end
Apparently, I am supposed to request the default fields of the profile overview in addition to the non-default fields like email-address, positions, and educations in order to access these latter non-default fields.
LinkedIn email-address should be straightforward, as it is not a structured object like positions or educations are, and I believe I am missing code for specific fields within positions and educations that I want (not sure how i would write that and would love some input on that as well). I am using my new API keys, so I'm not sure what the problem may be. Do I need some kind of special permission from LinkedIn? Help is appreciated! Thank you.
Also, here is the relevant code for my auth controller:
require 'linkedin'
class AuthController < ApplicationController
def auth
client = LinkedIn::Client.new(ENV['LINKEDIN_KEY'], ENV['LINKEDIN_SECRET'])
request_token = client.request_token(:oauth_callback =>
"http://#{request.host_with_port}/callback")
session[:rtoken] = request_token.token
session[:rsecret] = request_token.secret
redirect_to client.request_token.authorize_url
end
def callback
client = LinkedIn::Client.new(ENV['LINKEDIN_KEY'], ENV['LINKEDIN_SECRET'])
if current_user.atoken.nil? && current_user.asecret.nil?
pin = params[:oauth_verifier]
atoken, asecret = client.authorize_from_request(session[:rtoken], session[:rsecret], pin)
current_user.atoken = atoken
current_user.asecret = asecret
current_user.uid = client.profile(:fields => ["id"]).id
flash.now[:success] = 'Signed in with LinkedIn.'
elsif current_user.atoken && current_user.asecret
client.authorize_from_access(current_user.atoken, current_user.asecret)
flash.now[:success] = 'Signed in with LinkedIn.'
end
Not sure if this is the most elegant solution, but this worked for me
I just added the config with the scope passed in the request_token_path
LINKEDIN_CONFIGURATION = { :site => 'https://api.linkedin.com',
:authorize_path => '/uas/oauth/authenticate',
:request_token_path =>'/uas/oauth/requestToken?scope=r_basicprofile+r_emailaddress+r_network+r_contactinfo',
:access_token_path => '/uas/oauth/accessToken' }
client = LinkedIn::Client.new(LINKEDIN_API_KEY, LINKEDIN_SECRET_KEY, LINKEDIN_CONFIGURATION )
and the rest of the code is the same.
Be sure to change the client constructor in the callback method as well.

Reply tweets - set in_reply_to_in using twitter_oauth

I am not able to reply to tweets usign twitter_oauth.
Here is my code
#twitter_client = TwitterOAuth::Client.new(
:consumer_key => 'key ',
:consumer_secret => 'secret',
:token => token,
:secret => secret
)
response = #twitter_client.update(response_description, {"in_reply_to_status_id" => tweet_id})
logger.info response.inspect
It posts the tweet but not as a reply.
Had the same problem. You need to include the twitter username of the tweet to which you are replying.
Note:: This parameter will be ignored unless the author of the tweet this parameter references is mentioned within the status text. Therefore, you must include #username, where username is the author of the referenced tweet, within the update.
Found this at https://dev.twitter.com/docs/api/1/post/statuses/update stated in relation to in_reply_to_status_id param.

Resources