Rails koala getting omniauth user's groups - ruby-on-rails

I want to get a visitor groups. It works just fine when I am connected with my account (the administrator of the app) but when I connect with another account the groups.count == 0
def index
if (#current_visitor)
#graph = Koala::Facebook::API.new(#current_visitor.oauth_token)
groups = #graph.get_connections("me", "groups").select
puts groups.count
end
end
end

You need to ask user for groups permission.
In case you're using omniauth-facebook, just add :scope => 'user_groups' to your configuration, besides app id and app secret.
Detail of permission with facebook login can be found here https://developers.facebook.com/docs/facebook-login/permissions/v2.2

Related

Rails twitter-api get acces token without "sign-in" and store it in a different model than user

I have a rails app and I want to use the twitter api with the account of a user (to make favs, tweets, etc ...).
Here is my problem, I want the user to be able to create several "Project" with one different twitter account by project.
That is why I want to get the access_token and the access_token_secret but store them in my Project model and not in my User model.
I don't understand how I can do that. All the stuffs I found explain every time the way to do it with Omniauth and a "sign up"/"Sign in" of the User.
I'm very new to this Oauth / callback / API stuff so I'm a bit lost.
Is there an easy way to just get the access_token and the access_token_secret and store it where I want ?
I managed to do it with saving information i needed in the session.
def ask_twitter_authorisation
session[:info] = #project
redirect_to "/auth/twitter"
end
and then use it in my callback
def twitter_callback
session_hash = session[:info]
#project = Project.find(session_hash["id"])
#project.t_access_token = auth_hash.credentials.token
#project.t_access_token_secret = auth_hash.credentials.secret
#project.save
end

Custom Devise/Warden strategy that requires intermediate step with user interaction

I have a Spree application and I’m trying to implement a custom authentication strategy with Devise/Warden. The idea is that users are mapped to one or more companies. The first step in authenticating a user is to hit an external api endpoint that returns a list of associated companies. If no companies are returned, the user is invalid and I call fail!. However, if one or more companies are returned, my goal is to require the user to select an active company to use before they are authenticated and can continue to the site. Here is what I've got so far:
def valid?
params[:email]
end
def authenticate!
email = params[:email]
companies = get_user_companies(email)
if (companies.length > 0)
user = User.find_by :email => email
# have user select the active company here
success!(user)
else
fail!("User has no companies")
end
end
def get_user_companies(email)
url = "http://localhost/user/#{email}/companies"
JSON.parse(RestClient.get url, :content_type => :json, :accept => :json)
end
A user is not valid without a company, and the active company cannot be changed during a session. Is this possible? How would I go about implementing this? Would this step make more sense outside of an auth strategy? If so, where? Thanks!

How to get Facebook user's email using the Koala gem

I'm trying to use FB Open Graph to let my app update a user's attribute. I have Koala installed and using facebook-omniauth for my authentication. Simply I would like query my database looking for a user that matches his fb id and if that user does not exist then I would like to update the user model's attributes with data from the facebook API. Also I'm using mongoid as oppose to active record for my database.
In my user model I have this method.
def facebook
#facebook ||= Koala::Facebook::API.new(oauth_token)
end
Within my controller I have these lines of code within one of my methods.
#user = User.where(facebook_uid: params[:auth_id])
if #user.empty?
User.create(
first_name: User.facebook.get_object("name"),
last_name: User.facebook.get_object("email"),
facebook_uid: params[:auth_id],
facebook_oauth_token: params[:auth_token])
else
User.update_attributes(
facebook_oauth_token: params[:auth_token]
end
User.facebook.get_object("email") does not return me a user's email when I play around in my console. Does anybody have any idea how to do so?
Thanks!
This should work:
graph = Koala::Facebook::API.new(oauth_access_token)
profile = graph.get_object('me', fields:'email')
Now profile['email'] will get you the email of the user.
Try this:
facebook = Koala::Facebook::API.new(oauth_token)
public_attributes = facebook.get_object("me")
if public_attributes does not return email, this means that the user has not authorized the email for your App. check that you add "email" scope to the OAuth authorization process. If you use devise, this is the config:
config.omniauth :facebook, "facebook_app_key", "facebook_app_secret", {scope: "email"}

Rails - Facebook with Omniauth and Koala: How to renew an expired token

I have an application where users can link their Facebook accounts. They can log in using their email, but they can link their Facebook account.
In the view where I show the linked social networks (Facebook and others), I have something like this:
<%= image_tag #facebook.get_facebook_picture %>
This will call an instance method like this:
def get_facebook_picture
unless self.token.nil?
facebook_graph = Koala::Facebook::GraphAPI.new(self.token)
fb_picture = facebook_graph.get_picture("me", { :type => "small" })
end
end
This will work well unless the Facebook token that I have stored in my DB is expired. So I have added this exception handler in the mentioned controller:
def facebook_exception_handler exception
if exception.fb_error_type.eql? 'OAuthException'
# Let's get a new auth token... How?
else
logger.debug "Damn it. We don't know what error is coming from FB"
raise exception
end
end
I catch the exception correctly, but I fail to see how would I renew the access token that I have in my database. Notice that the access token that I have has been inserted using OmniAuth. So my question is:
Given that I have an OAuthException, how can I renew the access token of a particular user (UID) using Omniauth?
The simple case is that you re-auth the user with FB, exactly as you authorized them in the first place. To get the token in the first place, i'm assuming you're using omniauth (and onmiauth-facebook) to authenticate against FB. That means you've got a route and a controller action to handle the auth callback, and a function that inserts the token into the db.
The access token you originally got with omniauth can become invalid for various reasons - expiry, or because the user changed their FB password, and possibly others. In those cases, another OAuth call will return a valid token. Just call again (as you did when you first authorized the user) and replace the invalid token with the new one, in your DB, and you're good.
This gist (my own answer to a related question i asked here) has some code covering that, but it sounds like you've already got this covered. Save enough state to then re-attempt whatever triggered the exception and you're good.
It's also possible that the token is now invalid because the user has changed their FB app settings to de-authorize your app. In that case, the user will see the FB permissions dialog as if they were a new user authenticating against FB for the first time. (FB)
Does that make sense?
You can change the RailsCasts koala tutorial connection with this:
def facebook
if self.facebook_expires_at < Time.now
oauth = Koala::Facebook::OAuth.new(ENV["FACEBOOK_KEY"], ENV["FACEBOOK_SECRET"])
new_access_info = oauth.exchange_access_token_info self.facebook_token
new_access_token = new_access_info["access_token"]
new_access_expires_at = DateTime.now + new_access_info["expires"].to_i.seconds
self.update_attributes!(:facebook_token => new_access_token,
:facebook_expires_at => new_access_expires_at )
end
#facebook ||= Koala::Facebook::API.new(self.facebook_token)
block_given? ? yield(#facebook) : #facebook
rescue Koala::Facebook::APIError => e
logger.info e.to_s
nil
end

How do I fetch the access token for a user using the Twitter gem and the Omniauth gem when the users is already logged in?

Currently I authenticate the user using omniauth. This looks like this in my sessions controller and works well:
def create
auth = request.env['omniauth.auth']
unless #auth = Authentication.find_from_hash(auth)
# Create a new user or add an auth to existing user, depending on
# whether there is already a user signed in.
#auth = Authentication.create_from_hash(auth, current_user)
end
# Log the authorizing user in.
self.current_user = #auth.user
redirect_to authentications_url, :notice => "You've signed in!"
end
After this, I've stored the twitter uid in my authentications table (I also use linkedin, facebook) and I think that the twitter sessions has been closed.
How do I now authenticate so that I can use the Twitter gem? I think it should be something like this if I was calling it right after the omniauth callback.
token = auth['credentials']['token'],
secret = auth['credentials']['secret']
Twitter.oauth_token = token
Twitter.oauth_token_secret = secret
I clearly need to restart the session and put the token and secret in the right place. How can I create a method to do this?
You need to store both the token and the secret provided by Twitter in your authentications table (Authentication.create_from_hash). As long as you're doing that, this should work:
twitter_credentials = current_user.authorizations.find_by_provider(:twitter)
Twitter.oauth_token = twitter_credentials.token
Twitter.oauth_token_secret = twitter_credentials.token_secret
That's assuming that in your authentications table you store the Twitter token and secret as token and token_secret, as well as storing the provider as twitter

Resources