I am trying to read and display activities of a G+ user. Using Google oauth2 I could able to recieve the access_token of a user after authorization has completed.
I use google_plus gem to make calls to G+, i could able to recieve user information using below code
#person = GooglePlus::Person.get("user_id_goes_here", :key => "google_api_key_here")
but when i try to get the activities using below
activity = GooglePlus::Activity.get("user_id_goes_here")
i could able to see the below error,
i tried searching the web for a solution, and some suggest that the api call limit exceeded. (10,000 hits/day is default). But i am sure i have used this only with 20-30 calls today.
Any suggestions for this issue is appreciated.
FYI : I have just added config code for google_oauth2 in /config/initializers/omniauth.rb file as below provider :google_oauth2,Rails.application.config.client_id , Rails.application.config.client_secret
Note: Below is the screenshot when i try to authenticate with Oauth2.
I hope this doesnot include Google plus scope, to make it i know i should add {:scope => "REQUIRED_URL_HERE_GOOGLE_PLUS_RELATED"} in omniauth.rb. But not sure what url should i give in there.
Thanks,
Balan
The Google_Plus gem requires you to pass your app key with every request. You can either do this inline:
GooglePlus::Activity.get("user_id_goes_here", key: "api_key_goes_here")
Or set up a global variable in an initializer
GooglePlus.api_key = 'api_key_goes_here'
The examples in the gem spec assume you have included a global variable, and hence don't show the key: strings. This may be what is causing you problems?
In answer to your second question, you will need to specify a scope with your oauth requests. A list of scopes is given here https://developers.google.com/gdata/faq#AuthScopes, but it is worth noting that the url format seems to have changed from that published. Try https://www.googleapis.com/auth/xxxxx instead, where xxx is the service you require.
I could able to find a solution for my question..
1) Used {:scope => "https://www.googleapis.com/auth/plus.me"} in /config/initializers/omniauth.rb file
2) Used the code
activities = GooglePlus::Activity.for_person("user_id", :key => "GOOGLE_API_KEY").items
Hope someone will find this useful.
Related
I have a project where I am setting up a Rails API with Graphql and React/Apollo. I've purpled all the google links looking for the best authentication solution, but it seems I haven't been able to find a clear answer.
I settled on using the graphql_devise gem, which leverages devise & devise_token_auth. I would have preferred to find a JWT solution, but just couldn't. (If you have any obvious suggestions please tell me!)
First I mounted a separate auth route, but ran into problems with multiple endpoints when I was setting up ApolloClient. I couldn't figure out how to direct auth related requests to my auth endpoint, while letting the rest go through to my graphql one. (If figuring this out is the easiest solution, please tell me!) Instead, I mounted the auth routes in my own schema, as instructed by the docs:
class MyApiSchema < GraphQL::Schema
use GraphqlDevise::SchemaPlugin.new(
query: Types::QueryType,
mutation: Types::MutationType,
resource_loaders: [
GraphqlDevise::ResourceLoader.new('User', only: [:login, :logout])
]
)
mutation(Types::MutationType)
query(Types::QueryType)
And edited the execute line in graphql_controller.rb:
result = MyApiSchema.execute(query, variables: variables, context: graphql_context(:user), operation_name: operation_name)
At this point, running a test query in postman is successful. I can access the graphql route with a userLogin mutation without any headers set, and get a successful response with client, uid & token. Authentication of my other queries also works—success with headers, denied without.
But when I try to perform the same queries using useQuery in react, it doesn't work. In the Apollo Client Developer Tools plugin in Chrome, it doesn't work either, returning only [Object object]. By looking at the request in my Network tab, I can see that this is the result of the same error: "photo field requires authentication".
When I pry into the rails server, I can see that the headers are being received. I can even authenticate the user manually in my graphql_controller before the execute method is called, so I don't think that it is a CORS issue. I have set up the rack-cors gem in Rails to expose the required headers.
When I drill into the code, it seems that the graphql_devise method set_current_resource is failing to return my user. This seems to stem from the devise method set_user_by_token, but I have not been able to figure out why it is failing.
If anyone has any experience with implementing this gem & stack, I would very much appreciate your input! If you have a better way of approaching authentication, I'd love to know what your strategy is. If you can help me solve this ... field requires authentication error, I will love you forever.
Apologies if I've provided too much/too little info, or if my question is too vague. Please let me know if there's something specific I should know to ask/show in my code. Hope you can help! Thanks.
I've managed to find the issue, and I thought I'd explain.
Having traced the problem to the set_user_by_token method in the devise_token_auth gem, I bundle open devise_token_auth'd, and put a byebug inside. This revealed that #token.token was not being extracted correctly from the headers.
The problem was that my header access-token was somehow being converted to accessToken, so when devise tried to set the token info from the request headers using this key, it returned nil.
I do not know why or where this conversion takes place. I suspect it originates from Apollo/React rather than Rails, since the headers on my postman query were not altered. In react, when I set the headers they are set with access-token, as below, but it seems that at some point in the life of my request they are changed.
How I have set the headers in React:
const client = new ApolloClient({
cache,
link: new HttpLink({
uri: 'http://localhost:3000/graphql',
headers: {
accessToken: localStorage.getItem('access-token'),
client: localStorage.getItem('client'),
uid: localStorage.getItem('uid')
},
}),
});
The keys that devise_token_auth uses to select the headers from the request can be changed in the initializers/devise_token_auth.rb file.
I edited them as follows:
config.headers_names = {:'access-token' => 'accessToken',
:'client' => 'client',
:'expiry' => 'expiry',
:'uid' => 'uid',
:'token-type' => 'token-type' }
This means that my front-end is now working smoothly, and I can perform queries/mutations with authentication. However, now in my postman queries I have to change the header to accessToken if I want them to work.
It would be great to know exactly at what point my header from React is changed to camelCase, but for now, it's working. Hope this helps if anyone goes through the same frustrations!
I am completely new to salesforce and its API(s). I have rails application with an existing users table. I need to start synchronizing data over to our new salesforce account.
Currently, I am trying to convert existing 'Leads' to 'Accounts'. As I understand it, this can only be accomplished with the old SOAP API. I am trying to use the rforce gem.
I am able to authenticate according to the documentation, like this:
binding = RForce::Binding.new \
'https://www.salesforce.com/services/Soap/u/20.0'
binding.login \
'email', 'password' + 'token'
Then I try to call the convert lead action like this:
binding.convertLead "leadId" => lead_id
but I get the error:
:errors=>{:message=>"valid leadId is required", :statusCode=>"INVALID_CROSS_REFERENCE_KEY"}
I know for sure that the leadId I am using is indeed valid, because I have actually retrieved it just prior to this call (using the REST API).
I believe that the problem may be that the rforce gem is not structuring the underlying SOAP call properly -- which I think is being described in this SO post.
I appreciate any additional information anyone can provide.
Thanks very much,
Matt
Try using lead.Id instead of lead_Id.
The input hash needs to have the key 'leadConverts':
binding.convertLead 'leadConverts' => { 'leadId' => lead_id, 'convertedStatus' => 'Status' }
You may need to add other arguments depending on what is required to convert a Lead on your Salesforce platform.
I'm trying to set up the linkedin api in a rails 3 app using the linkedin gem. I don't want the user to have to authenticate my app in order for the API to get their info. I only need one piece of their public profile (the headline). So, maybe I should just be using xml or json to pull this off (not exactly sure how to get that with linkedin either).
I have the following in a helper so that I can call linkedin_header() in a loop of users. I only have 'client' as the last line of the following code while debugging. It outputs as expected (#). It seems like I am only a step away from success. How can I access a given users headline? I have tried using "client = client.profile(:url => 'linkedin_user_url')", but that return "Call must be made on behalf of a member".
def linkedin_header(account_user)
user = User.find(account_user)
account = Account.where(:user_id => user, :external_id => 1)
api_key = 'aaaaaaaa'
api_secret = 'bbbbbbbb'
client = LinkedIn::Client.new(api_key, api_secret)
rtoken = client.request_token.token # this returns correctly
rsecret = client.request_token.secret # this returns correctly
client
# client = client.profile(:url => 'linkedin_user_url')
end
So, I guess I have two questions. Is my request (public headline of any user) too simple for the above...should I be using XML or JSON. And, if Im close...can I make the API work for me without the user having to authenticate via linkedin.
Based off of what I read from the LinkedIn API reference (http://developer.linkedin.com/documents/authentication)
You have to make requests to their API only after being authenticated. (Using OAuth Keys) Rather than just grabbing the publicly available information.
It seems like since you want a small piece of information (the public headline of any user) you'd want some sort of implementation like Facebook's OpenGraph. After looking around on LinkedIn, I don't see any sort of public implementation like that.
I would suggest checking out this gem:
https://github.com/yatishmehta27/linkedin-scraper
It seems to be the type of solution you're looking for.
I want to play around with the Yahoo Fantasy Sports API. I have no idea where to start. What do I need to do in order to start playing with the API in IRB and start calling and retrieving different players or stats? This is my first attempt at tackling an API that does not have a readily available Ruby gem.
Yahoo Fantasy Sports API: http://developer.yahoo.com/fantasysports/guide/
I've followed the steps detailed in the dev guide and set up my developer Consumer key and Secret key. Not sure what to do with this information though.
I'm using Rails 3.2.2 and Ruby 1.9.2
I've been spending many hours the past couple weeks trying to get a site to tie in with the Yahoo fantasysports API and only recently got over the hurdle of being able to get authenticated through OAuth, make valid requests, and refresh access tokens indefinitely. Here are the steps you need to take to be able to mess around in IRB:
Gem stuff
Include oauth-plugin in your Gemfile. This will also install the OAuth/OAuth2 ruby gems as dependencies. This will handle the request/access tokens needed, but won't be fully compatible right out of the box.
The oauth-plugin requires an authentication system to be in place for your app. I would highly recommend devise both for its ease of use and the fact that the oauth-plugin pretty much works along with it with very little setup. I found it easier to connect the two if I first generate 'User' through devise before I generated a consumer with the oauth-plugin. There are tons of guides for devise if you run into issues.
Migration stuff
A quirk of the Yahoo version of OAuth is that you need to store a 'session_handle' for a user in order to refresh the access token when it expires after 60 minutes. I just edited the existing OauthConsumerToken migration to include t.string :session_handle. I'm not sure what the issue was with MYSQL when I did this, but I had to also specify a limit of 190 for the consumer_tokens index that oauth created. So my full add index is add_index :consumer_tokens, :token, :unique => true, :length => 190. I would recommend also adding a :guid string column to the users table, since that is what Yahoo uses as a unique identifier.
To accommodate the two extra columns we are tracking that oauth doesn't know about (session handle and guid), you need to override some of the oauth-plugin default behaviour. I've already forked the project and made the necessary changes if you want to just use my version (https://github.com/JamesSwift/oauth-plugin). The three dependencies for my version are a session_handle column in the ConsumerTokens table, a yahoo_guid column in the Users table, and set the variable CB_URL in your development.rb to be the url that you registered your app under with Yahoo. Also remember that if you use my version of the plugin you need to specify the path/github url depending on how you want to include it.
Configuration stuff
You need to set the :key and :secret in config/intializers/oauth_consumers.rb. I call my consumer a YahooToken, so mine looks like this:
OAUTH_CREDENTIALS={
:yahoo => {
:key => "the key given to me by yahoo"
:secret => "the secret given to me by yahoo"
}
}
load 'oauth/models/consumers/service_loader.rb'
You also need to specify the global yahoo settings in the custom token class you created. Again, mine is a YahooToken, so in app/models/yahoo_token.rb my first few lines are:
class YahooToken < ConsumerToken
YAHOO_SETTINGS={
:site=>"http://fantasysports.yahooapis.com/fantasy/v2",
:authorize_url =>"https://api.login.yahoo.com/oauth/v2/request_auth",
:request_token_url => "https://api.login.yahoo.com/oauth/v2/get_request_token",
:access_token_url => "https://api.login.yahoo.com/oauth/v2/get_token",
:oauth_version=>"1.0"
}
Tell your user model it has a token:
has_one :yahoo, :class_name=>"YahooToken", :dependent=>:destroy
Actually doing stuff, stuff
Now you can load up your server, create a user, and go to http://localhost:3000/oauth_consumers/yahoo to get your token. Yahoo refuses to redirect you back to localhost, so you will end up getting redirected to CB_URL/parameters-that-yahoo-returns. Copy the parameter string and go to http://localhost:3000/oauth_consumers/yahoo/callback/paste-the-string-here. This should successfully complete the initial retrieval of the access token. Don't worry, you only need to do this once per local user while developing locally. It automatically redirects in production environments.
Now that you have a token you can use it in IRB for the next hour as much as you want. Here is an example of using the token from the console:
t = User.first.yahoo
resp = t.client.get("http://fantasysports.yahooapis.com/fantasy/v2/users;use_login=1")
puts resp.body
You can also put &format=json at the end to get it in json instead of xml
After 60 minutes you need to get a new access token. I have a refresh function in my YahooToken:
def refresh!
old_one = self
request_token = OAuth::RequestToken.new(YahooToken.consumer, self.token, self.secret)
options={}
options[:oauth_session_handle]=self.session_handle
access_token = request_token.get_access_token options
new_one = YahooToken.find_or_create_from_access_token self.user, access_token
if new_one
old_one.delete
return new_one
end
return nil
end
Whenever my token expires I just t = t.refresh!. I would also recommend an age method on your tokens which will facilitate creating a rake task that will refresh tokens every hour for you automatically.
All the available fantasysports related resources are listed here:(http://developer.yahoo.com/fantasysports/guide/)
To get started, I would suggest you familiarize yourself with OAuth, which the Yahoo Fantasy Sports API uses for authentication. You will also need to know how to make HTTP requests in Ruby. Most of the rest of work will be in reading the API documentation and experimenting.
If you're looking for Ruby libraries for using OAuth or making HTTP requests, or anything else you run into, you may find The Ruby Toolbox helpful.
I prefer pelle/oauth-plugin save session_handle in refresh! rather then fork it.
consumer wrapper
model/YahooToken.rb inspired by #JamesSwift.
Migration
I authorizate with omniauth-yahoo, so the guid save in Authorization model and you need to add session_handle(:string) and change token(:text) column in consumer_tokens.
enjoy.
I'm playing with the authlogic-example-app and I'm failing to get the email address from the OpenID provider (in my case: Google and Yahoo) when I register a user, resp. I get an empty response instead of an email address (check the comments in code below).
This is how my user model looks like (everything else looks like the "with_openid"-branch of the authlogic-example-app mentioned above). Besides the missing 'email', the openid-authentication-process works as expected:
class User < ActiveRecord::Base
acts_as_authentic do |c|
# not needed because I use OpenID
c.validate_login_field = false
# avoid failed validation before OpenID request
c.validate_email_field = false
# this one sets 'openid.sreg.required=email'
c.required_fields = [:email]
end
private
# overwriting the existing method in '/lib/authlogic_openid/acts_as_authentic.rb'
def map_openid_registration(registration)
# this is my problem: 'registration' is an empty hash
self.email ||= registration[:email] if respond_to?(:email) && !registration[:email].blank?
end
end
Any idea how to solve this? Has anyone here done this before using authlogic? Or even better: Do you have a working example?
Update: I checked the Google Account Authentication API and compared the request submitted by authlogic (using ruby-openid-gem and openid-authentication-plugin) with the example requests on the Google Account Authentication API docs:
Example request to authenticate and fetch email address by Google:
https://www.google.com/accounts/o8/ud
?openid.ns=http%3A%2F%2Fspecs.openid.net%2Fauth%2F2.0
&openid.claimed_id=http%3A%2F%2Fspecs.openid.net%2Fauth%2F2.0%2Fidentifier_select
&openid.identity=http%3A%2F%2Fspecs.openid.net%2Fauth%2F2.0%2Fidentifier_select
&openid.return_to=http%3A%2F%2Fwww.example.com%2Fcheckauth
&openid.realm=http%3A%2F%2Fwww.example.com%2F
&openid.assoc_handle=ABSmpf6DNMw
&openid.mode=checkid_setup
&openid.ns.ext1=http%3A%2F%2Fopenid.net%2Fsrv%2Fax%2F1.0
&openid.ext1.mode=fetch_request
&openid.ext1.type.email=http%3A%2F%2Faxschema.org%2Fcontact%2Femail
&openid.ext1.required=email
Request submitted by my appliation:
https://www.google.com/accounts/o8/ud
?openid.assoc_handle=AOQobUcdICerEyK6SXJfukaz8ygXiBqF_gKXv68OBtPXmeafBSdZ6576
&openid.ax.mode=fetch_request
&openid.claimed_id=http%3A%2F%2Fspecs.openid.net%2Fauth%2F2.0%2Fidentifier_select
&openid.identity=http%3A%2F%2Fspecs.openid.net%2Fauth%2F2.0%2Fidentifier_select
&openid.mode=checkid_setup
&openid.ns=http%3A%2F%2Fspecs.openid.net%2Fauth%2F2.0
&openid.ns.ax=http%3A%2F%2Fopenid.net%2Fsrv%2Fax%2F1.0
&openid.ns.sreg=http%3A%2F%2Fopenid.net%2Fextensions%2Fsreg%2F1.1
&openid.realm=http%3A%2F%2Flocalhost%3A3000%2F
&openid.return_to=http%3A%2F%2Flocalhost%3A3000%2Faccount%3Ffor_model%3D1%26_method%3Dpost%26open_id_complete%3D1
&openid.sreg.required=email
While debugging the whole setup, I've found out that the openid-authentication-plugin never receives an email in the response it receives from the openid provider, this at least explains why the registration hash in my user-model is empty...
UPDATE: If you're playing around with authlogic and openid, don't forget to check out the latest railscast on this subject!
As nobody could help me, I helped myself. :-)
The short answer to my question is:
c.required_fields = [:email,"http://axschema.org/contact/email"]
Using this line, the application requests the email-address using sreg and ax (request-type supported by Google).
You can find a more detailed answer and a working implementation of authlogic-openid with the Javascript OpenID-Selector right here:
http://github.com/vazqujav/authlogic_openid_selector_example/
While this pointed me in the right direction, what I needed was:
c.openid_required_fields = [:email,"http://axschema.org/contact/email"]
This pulled in the email and set it.
# fetch email by ax
c.openid_required_fields = [
"http://axschema.org/contact/email",
"http://axschema.org/namePerson/first",
"http://axschema.org/namePerson/last",
"http://axschema.org/contact/country/home",
"http://axschema.org/pref/language"
]
This fetches in multiple values as specified # http://code.google.com/apis/accounts/docs/OpenID.html#Parameters
Though I'm still unable to fetch in the country name... name, email, language works perfectly!
Test against an OpenID server you control, since it'll let you debug every part of the OpenID sequence. There are no guarantees that Google's OpenID provider is doing the right thing. Try checking against Verisign's server, since I'm pretty sure that one at least should do the right thing with the openid.sreg.required=email field.
Your code snippet looks right to me.
the thing is i am able to fetch the parameters from the provider but am not able to extract them from the response...
i have used OpenID::AX::FetchResponse.from_success_response(open_id_response)
as the object to hold the response... what method do i use to extract email,nickname,country,etc...