How to update twitter omniauth access token and access token secret - ruby-on-rails

In my rails 6 app, users have to sign in with twitter omniauth and devise. I have been able to implement it by following this tutorial.
The issue I have is that when a user revokes my app permissions from their twitter account, the omniauth access tokens and access secrets that I previously saved into my database becomes invalid. If the same user decides to re-authenticate, the user gets access to the app but the user's tokens are not updated in the database, rendering the existing tokens invalid.
My question is, how do I continuosly update the user columns in my database so I continue to receive valid access tokens from twitter, especially when the user has access tokens.
This is relevant code from my user model
def self.from_omniauth(auth)
where(provider: auth.provider, uid: auth.uid).first_or_create do |user|
user.email = auth.info.email
user.password = Devise.friendly_token[0, 20]
user.name = auth.info.name
user.username = auth.info.nickname
user.location = auth.info.location
user.access_token = auth.credentials.token
user.access_secret = auth.credentials.secret
end
end
My user controller looks like this
def twitter
#user = User.from_omniauth(request.env["omniauth.auth"])
if #user.persisted?
sign_in_and_redirect #user, event: :authentication #this will throw if #user is not activated
set_flash_message(:notice, :success, kind: "Twitter") if is_navigational_format?
else
session["devise.twitter_data"] = request.env["omniauth.auth"].except("extra")
redirect_to new_user_registration_url
end
end

Find the user.
If no user - create user.
Update user (bothe exisitng and new) with fresh omniauth data
Something like this should do the job:
def self.from_omniauth(auth)
#find from omniauth
user = User.where(email: auth.email).first
#find or create
user ||= User.create(
email: data["email"],
password: Devise.friendly_token[0, 20]
)
#update with fresh data
user.name = auth.info.name
user.image = auth.info.image
user.expires = auth.credentials.expires
user.refresh_token = auth.credentials.refresh_token
end

I got it working with by using find_or_initialize_by
def self.from_omniauth(auth)
user = find_or_initialize_by(provider: auth.provider, uid: auth.uid)
user.email = auth.info.email
user.password = Devise.friendly_token[0, 20]
user.name = auth.info.name
user.username = auth.info.nickname
user.location = auth.info.location
user.access_token = auth.credentials.token
user.access_secret = auth.credentials.secret
user.save!
return user
end

Related

Oauth facebook with ruby on rails 5.2.5

Since two days i tried to make Login with Facebook on ruby on rails using devise but it returns me NULL as email's value. I read many articles on stackoverflow but a lot of them are from years ago and none have worked for me. Thanks you for helping.
Here is the message in my console when i choose my facebook account
def self.from_omniauth(auth)
unless auth.info.email
auth.info.email = "#{auth.info.name.split(' ').join}#facebook.com"
end
user = User.where("email= ?", auth.info.email).first
puts auth.info.picture
puts auth.info.name
puts auth.info.email
if user
return user
else
where(provider: auth.provider, uid: auth.uid).first_or_create do |user|
user.email = auth.info.email
user.password = Devise.friendly_token[0, 20]
user.name = auth.info.name # assuming the user model has a name
# user.image = auth.info.image # assuming the user model has an image
# If you are using confirmable and the provider(s) you use validate emails,
# uncomment the line below to skip the confirmation emails.
user.skip_confirmation!
user.uid = user.uid
user.provider = user.provider
end
end

find_or_create_by not finding, only trying to create

Using google oauth for a project. Had it working, but wanted to pull the profile picture to display in my app. Once I was able to display the picture, I logged out and tried to relog back in with the oauth. It is now telling me that the name and email have already been taken. I am using a find_or_create_by in my User model to find or create by the oauth credentials. I don't know what is causing this as it was working just a bit ago. And now, when I go back to how my code first was, it is not working period. Just giving me the errors bc of validations(trying to create a record instead of finding the record in the database.)
sessions#create
def create
if params[:provider].present?
#user = User.find_or_create_from_auth(request.env['omniauth.auth'])
if #user
session[:user_id] = #user.id
flash[:notice] = "Logged in as #{#user.name}"
redirect_to dashboard_path
end
Users model-
def self.find_or_create_from_auth(auth)
find_or_create_by!(provider: auth.provider, uid: auth.uid, password_digest: 'N/A') do |user|
user.provider = auth.provider
user.uid = auth.uid
user.name = auth.info.name
user.email = auth.info.email
user.address = "123 ABC St"
user.password = 'n/a'
user.oauth_token = auth.credentials.token
user.oauth_expires_at = Time.at(auth.credentials.expires_at)
user.save
end
end
Appreciate any help, just not seeing the disconnect here.
This line:
find_or_create_by!(provider: auth.provider, uid: auth.uid, password_digest: 'N/A') do |user|
You only are considering the uid, provider and password_digest. But as your error says the name and email have already been taken. Which means that at your users database you have a unique constraint in both. So even when the uid and provider are different, you can't persist a new instance at DB if it matches with another existing record.
So you can remove the unique constraint or add that validation to find_or_create_by

How is omniauth secure when used for Single Sign On?

I have been using omniauth, based off of tutorials similar to this: https://coderwall.com/p/bsfitw#
In this tutorial, and many others, you are instructed to find a user matching what you get back from omniauth, usually like so
class SessionsController < ApplicationController
def create
user = User.from_omniauth(env["omniauth.auth"])
session[:user_id] = user.id
redirect_to root_url
end
end
class User < ActiveRecord::Base
def self.from_omniauth(auth)
where(auth.slice(:provider, :uid)).first_or_initialize.tap do |user|
user.provider = auth.provider
user.uid = auth.uid
user.name = auth.info.name
user.oauth_token = auth.credentials.token
user.oauth_expires_at = Time.at(auth.credentials.expires_at)
user.save!
end
end
end
So... what is to stop someone else from just posting :provider => "twitter", :uid => "Someone elses uid" to log in as them?
So after talking to a couple people, it appears the reason is because the omniauth.auth variables are passed via environment variables set by the omniauth middleware, not passed in directly from the request.

best omniauth gem for rails

I am using Omniauth-facebook gem from Github from Ruby on Rails. I have several questions regarding the omniauth-facebook gem.
I am using the following function get the data from Facebook, but this function is called every time the user signs in and in registration.
def self.from_omniauth(auth)
where(auth.slice(:provider, :uid)).first_or_initialize.tap do |user|
user.provider = auth.provider
user.id = auth.uid
user.uid = auth.uid
user.name = auth.info.name
user.username = auth.info.nickname
user.email = auth.info.email
user.gender = auth.extra.raw_info.gender
user.is_admin = false
user.picture = "http://graph.facebook.com/#{auth.uid}/picture?type=large&height=324&width=580"
user.updated_at = auth.extra.raw_info.updated_time
user.oauth_token = auth.credentials.token
user.oauth_expires_at = Time.at(auth.credentials.expires_at)
user.save!
end
end
How can I differ the registration and login function from each other?
On the other hand, I want to post the user's wall something when the user signs in, or posts something. How can I do it in Omniauth-facebook gem?
Thank you.
Omniauth-facebook gem is best if want to add any post on users wall u can refer this link
facebook share

How to retrieve fb's user relationship status through koala gem?

I ve installed the gem koala and omniauth.
In my user model
class User < ActiveRecord::Base
def self.from_omniauth(auth)
where(auth.slice(:provider, :uid)).first_or_initialize.tap do |user|
user.provider = auth.provider
user.uid = auth.uid
user.name = auth.info.name
user.image = auth.info.image
user.oauth_token = auth.credentials.token
user.oauth_expires_at = Time.at(auth.credentials.expires_at)
user.save!
end
end
def facebook
#facebook ||= Koala::Facebook::API.new(oauth_token)
end
end
Ive the permission from the facebook but still i am not being able to get the relationship status?
Try this
#facebook.get_object('me',:fields=>"name,gender,relationship_status")

Resources