How is omniauth secure when used for Single Sign On? - ruby-on-rails

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.

Related

How to update twitter omniauth access token and access token secret

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

Missing token endpoint URI. Google API Gmail

I'm trying to list all the emails from inbox in a ruby on rails app I have the login and authentication working with omniauth-google-oauth2 now I want to list all the inbox messages so in my controller:
home_controller.rb I have this:
class HomeController < ApplicationController
def index
if session[:user_id]
client = Signet::OAuth2::Client.new(access_token: session[:access_token])
client.expires_in = Time.now + 1_000_000
service = Google::Apis::GmailV1::GmailService.new
service.authorization = client
#labels_list = service.list_user_labels('me')
else
puts "ERROR !!!"
end
end
end
and in my User model I have this:
class User < ApplicationRecord
def self.from_omniauth(auth)
where(provider: auth.provider, uid: auth.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
I have this error:
Missing token endpoint URI.
I dont know how to resolve this I tried everything in stackoverflow and documentation.
Regards and thanks for your time guys !

Omniauth ArgumentError in SessionsController#create wrong number of arguments (1 for 2) Rails 4

I am following an online tutorial to incorporate facebook omniauth to a sample application before adding it to my ROR application ( http://richonrails.com/articles/facebook-authentication-in-ruby-on-rails and https://coderwall.com/p/bsfitw) but I am getting a wrong number of arguments error when I visit the "log into from facebook link".
ArgumentError in SessionsController#create wrong number of arguments (1 for 2).
Here is my user model (straight from the tutorial) and where the error appears to be coming from, line 3 is highlighted as the source
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
SessionsController
class SessionsController < ApplicationController
def create
user = User.from_omniauth(env["omniauth.auth"])
session[:user_id] = user.id
redirect_to root_url
end
def destroy
session[:user_id] = nil
redirect_to root_url
end
end
I don't have the coffee script from the 2nd tutorial in there, I get a different error when I use it.
Any help would be greatly appreciated.
I down graded the omniauth-facebook gem to '1.4.0' and it worked fine.

Creating 2 records on omniauth-facebook signup

I'm using the omniauth-facebook gem in combination with Devise to enable users to login with their Facebook account. This works fine. The problem now lies in the creation of a new user, when first signing up with Facebook. Each User has one ExtendedProfile with detailed user info. So the email and password are columns in the users table, but location and profile_image are stored in the extended_profiles table.
When signing up for the first time, the following method is executed:
def self.find_for_facebook_oauth(auth)
where(auth.slice(:provider, :uid)).first_or_create do |user|
user.provider = auth.provider
user.uid = auth.uid
user.email = auth.info.email
user.password = Devise.friendly_token[0,20]
end
end
Now this creates a record for the users table, but not an extended_profile. Any idea how I can create a record for extended_profiles with the right user_id and fill it with the information I get back from Facebook? Thanks very much in advance!
So I've found the solution while trying out house9's answer:
def self.find_for_facebook_oauth(auth)
where(auth.slice(:provider, :uid)).first_or_create do |user|
user.provider = auth.provider
user.uid = auth.uid
user.email = auth.info.email
user.password = Devise.friendly_token[0,20]
user.create_extended_profile(
:first_name => auth.info.first_name,
:last_name => auth.info.last_name,
:facebook_avatar => auth.info.image)
end
end
The user.create_extended_profile() line creates a relational record with the auth values filled in! :)
Have you tried setting it in the block? Not sure if this will work
def self.find_for_facebook_oauth(auth)
where(auth.slice(:provider, :uid)).first_or_create do |user|
user.provider = auth.provider
# ....
user.extended_profile.build
end
end
another option is to put an after_create callback on the User to create the record
http://guides.rubyonrails.org/active_record_callbacks.html#available-callbacks
or you can conditionally check if the record exists, change up that code to:
def self.find_for_facebook_oauth(auth)
user = where(auth.slice(:provider, :uid)).first
unless user
user = User.new
user.provider = auth.provider
# ....
user.extended_profile.build
user.save
end
user
end

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