I have been looking for the solution but got no any luck, have searched alot and tried many solutions found on stackoverflow or github issues... but still same error..
Referring to this post I tried, but still no luck..
here is the code I have in my app.
The Gem File
gem 'omniauth', '2.0.4'
gem 'omniauth-oauth2', '1.7.2'
gem 'omniauth-facebook', '9.0'
gem 'omniauth-rails_csrf_protection', '~> 1.0'
User Model:
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable,
:trackable, :async,
:omniauthable, omniauth_providers: %i[facebook]
def self.from_omniauth(auth)
name_split = auth.info.name.split(" ")
user = User.where(email: auth.info.email).first
user ||= User.create!(provider: auth.provider, uid: auth.uid, last_name: name_split[0], first_name: name_split[1], email: auth.info.email, username: auth.info.email, password: Devise.friendly_token[0, 20])
user
end
Devise.rb:
config.omniauth :facebook, "APP_ID", "APP_SECRET", callback_path: "/api/v1/users/auth/facebook/callback"
The Routes File:
devise_for :users, controllers: { registrations: "api/v1/users/registrations", sessions: "api/v1/users/sessions", passwords: "api/v1/users/passwords", omniauth_callbacks: 'api/v1/users/omniauth_callbacks' }
The Omniauth Controller:
# frozen_string_literal: true
class Api::V1::Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
def passthru
Rails.logger.info "PassThru"
Rails.logger.debug request.env['omniauth.auth']
super
end
def facebook
Rails.logger.info "Check out this info!"
#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: "Facebook") if is_navigational_format?
else
session["devise.facebook_data"] = request.env["omniauth.auth"].except(:extra) # Removing extra as it can overflow some session stores
redirect_to new_user_registration_url
end
end
def auth_data
Rails.logger.debug "Auth_DATA"
request.env["omniauth.auth"]
end
def failure
Rails.logger.info "FAIL"
Rails.logger.info root_path
redirect_to root_path
end
def callback
Rails.logger.info "HELLO"
end
end
The Omniauth middleware in initializers dir
Rails.application.config.middleware.use OmniAuth::Builder do
provider :facebook, "APP_ID", "APP_SECRET",
scope: 'email,user_birthday,read_stream', display: 'popup'
end
and in finally the link in the view file:
(link_to "Register with Facebook", user_facebook_omniauth_authorize_path, method: :post)
and this is the log when I click on the link in the view:
| I, [2022-01-24 13:30:12 #1] INFO -- : Started GET "/api/v1/users/auth/facebook" for 172.20.0.1 at 2022-01-24 13:30:12 +0000
| I, [2022-01-24 13:30:12 #1] INFO -- : PassThru
| D, [2022-01-24 13:30:12 #1] DEBUG -- : nil
I have made sure the FB credentials are right (APPID n SECRET) and FB app is not yet live so it can accept my localhost url as redirect url.
but still I can not understand what's the wrong I am doing here..
Kindly give your valuable feedback here... as I am also new to ruby...
I am running ruby#3.1.0 and rails#6.0.4.4
Thanks in advance.
Related
I have configured Facebook via login using this tutorial and it's working fine. I'm able to send a login call at Facebook and after users acknowledgment, it's redirect to my site. However, In the callback URL, only "code" is returning but I required an access token.
Here is my code.
Devise.rb
config.omniauth :facebook, "client_id", "secret", scope: 'public_profile,email,manage_pages,read_insights',:display => 'popup'
User.rb
devise :database_authenticatable,:registerable,:recoverable,
:rememberable, :trackable, :validatable,
:confirmable,:lockable,:timeoutable,
:omniauthable, omniauth_providers: [:facebook]
def self.current
Thread.current[:user]
end
def self.current=(user)
Thread.current[:user] = user
end
def self.create_from_provider_data(provider_data)
where(provider: provider_data.provider, uid: provider_data.uid).first_or_create do | user |
user.email = provider_data.info.email
user.password = Devise.friendly_token[0, 20]
user.skip_confirmation!
end
end
omniauth controller
def facebook
#user = User.create_from_provider_data(request.env['omniauth.auth'])
if #user.persisted?
sign_in_and_redirect #user
set_flash_message(:notice, :success, kind: 'Facebook') if is_navigational_format?
else
user = User.create!(email: auth.info.email,
password: Devise.friendly_token[0,20],
user_name: auth.info.first_name
)
user.authentications.create!(user_id: user.id,
provider: auth.provider,
uid: auth.uid)
flash[:error] = 'There was a problem signing you in through Facebook. Please register or try signing in later.'
redirect_to new_user_registration_url
end
end
def failure
flash[:error] = 'There was a problem signing you in. Please register or try signing in later.'
redirect_to new_user_registration_url
end
CallBack Response:
Parameters: {"code"=>"AQBBtixd3nmIkT_KyKUKmy68hBYt7kdZ0jX1pATNmDCSWmjfoiAC_8C5aOF3P3jKRyhKYX2JfL0gZDWZCTraN_kdZpxIJu8pYWkktr0E9Q2WXk6xjz0Uyz4cS2YeTv0SyqjZbZvQr8roxKCPvZb-6UKbCzMGZsi3-VLXK3suPfs729nR8MilmuatZqQ-TanApTy-8Qh195ntqfD6gIMhbZZMBhAuVSbf6GmyT-anNV0exczDMzKIF6OpZoIFC7Vxez8EH3cR7BUPqc5OldfbDD8j9pY6kDeoc00An9wuGj4hAfne_jeShUZTw_zSQMmxkbMqe2acFPJWE5DLL2QNII54", "state"=>"c231b221dba5bdc33fff6349af5793c0cbb5bdcc69253372"}
As per this documentation, we can get required information from callback response.
How i can update my code to get access token.
You can to send another request with the code to get the access token.
You can fetch email and other details by request.env['omniauth.auth']['info']['email'].
As I can see you are using auth.info.email and auth is not defined due to which error persist.
I am using RoR 5.2, devise and omniauth-trello gem.
I can't sign in with Trello.
I need to create ability to sign in without existing user with returned provider and uid: it should create user if it doesn't exist.
I have already added in config/routes.rb:
devise_for :users, controllers: { omniauth_callbacks: 'omniauth_callbacks' }
config/initializers/devise.rb:
config.omniauth :trello, "#{Rails.application.credentials.trello[:key]}", "#{Rails.application.credentials.trello[:secret]}"
config/initializers/omniauth.rb
Rails.application.config.middleware.use OmniAuth::Builder do
provider :trello, Rails.application.credentials.trello[:key], Rails.application.credentials.trello[:secret],
app_name: "Trello-Rooney", scope: 'read,write,account', expiration: 'never'
end
app/controllers/omniauth_callbacks_controller.rb
class OmniauthCallbacksController < Devise::OmniauthCallbacksController
def trello
#user = User.from_omniauth(request.env['omniauth.auth'])
if #user.persisted?
sign_in_and_redirect #user, event: :authentication
set_flash_message(:notice, :success, kind: 'Trello') if is_navigational_format?
end
end
end
app/models/user.rb
class User < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable, :omniauthable, omniauth_providers: %i[trello]
def self.from_omniauth(auth)
user = User.where(provider: auth.provider, uid: auth.uid.to_s).first
return user if user
email = auth.info[:email]
while email.nil?
generated_email = "#{SecureRandom.base58(10)}#roonyx.trello"
if User.where(email: generated_email).blank?
email = generated_email
end
end
user = User.where(email: email).first
if user
user.update(provider: auth.provider, uid: auth.uid)
else
password = Devise.friendly_token[0, 12]
user = User.create!(email: email, password: password, password_confirmation: password, provider: auth.provider, uid: auth.uid)
end
user
end
end
But when I am trying to sign in with Trello, I see this in console. Looks like it doesn't cause my callback. Can anyone help? Thank you in advance.
E, [2019-05-13T14:10:29.647241 #19958] ERROR -- omniauth: (trello) Authentication failure! service_unavailable: Net::HTTPFatalError, 500 "Internal Server Error"
[2019-05-13 14:10:29] (pida=19958) INFO -- : Processing by OmniauthCallbacksController#failure as HTML
[2019-05-13 14:10:29] (pida=19958) INFO -- : Parameters: {"oauth_token"=>"47215df2b25b4fc089953da32acf0730", "oauth_verifier"=>"8a0b310f2afe98d0aebbd2073efc5b54"}
[2019-05-13 14:10:29] (pida=19958) INFO -- : Redirected to http://localhost:3000/users/sign_in
[2019-05-13 14:10:29] (pida=19958) INFO -- : Completed 302 Found in 1ms (ActiveRecord: 0.0ms)
The error is right there in your log:
Authentication failure! service_unavailable: Net::HTTPFatalError, 500 "Internal Server Error"
Your callback isn't being hit because you've inserted the OmniAuth::Builder middleware. You could try removing that and inspecting the params that are sent along with the callback.
Once you're removed the middleware you can drop a byebug or a binding.pry at the top of your callback action. Once you're in the debugger check the value of request.env['omniauth.auth']. That should give you some insight as to what the problem is. Hard to say more without knowing more about the environment.
I have followed the tutorial from this link and keep ending up with the following log messages:
Started GET "/users/auth/google_oauth2" for 127.0.0.1 at 2019-02-22 20:59:25 +1100
I, [2019-02-22T20:59:25.512091 #11001] INFO -- omniauth: (google_oauth2) Request phase initiated.
Started GET "/users/auth/google_oauth2/callback?state=...
I, [2019-02-22T20:59:29.060352 #11001] INFO -- omniauth: (google_oauth2) Callback phase initiated.
ActionController::RoutingError (uninitialized constant Users::OmniauthCallbacksController):
I've searched online and all the solutions suggest checking the spelling in various files. I've included them below.
Devise _links.html.erb:
<%- if devise_mapping.omniauthable? %>
<%- resource_class.omniauth_providers.each do |provider| %>
<%= link_to "Sign in with #{OmniAuth::Utils.camelize(provider)}", user_google_oauth2_omniauth_authorize_path %><br />
<% end -%>
<% end -%>
devise.rb:
config.omniauth :google_oauth2, client_id, client_secret, {
scope: "contacts.readonly,userinfo.email,userinfo.profile,youtube",
prompt: 'select_account',
image_aspect_ratio: 'square',
image_size: 50
}
User.rb:
class User < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable, :omniauthable, :omniauth_providers => [:google_oauth2]
def self.from_omniauth(auth)
where(provider: auth.provider, uid: auth.uid).first_or_create do |user|
user.token = auth.credentials.token
user.expires = auth.credentials.expires
user.expires_at = auth.credentials.expires_at
user.refresh_token = auth.credentials.refresh_token
end
end
end
/app/controllers/users/omniauth_callbacks_controllers.rb
class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
def google_oauth2
#user = User.from_omniauth(request.env["omniauth.auth"])
if #user.persisted?
sign_in #user, :event => :authentication #this will throw if #user is not activated
set_flash_message(:notice, :success, :kind => "Google") if is_navigational_format?
else
session["devise.google_data"] = request.env["omniauth.auth"]
end
redirect_to '/'
end
end
routes.rb
devise_for :users, controllers: {omniauth_callbacks: "users/omniauth_callbacks"}
google console
I have set up my google console with the following Authorised redirect URLs:
http://localhost:3000/users/auth/google_oauth2/callback
Rails Routes
When I do a rails routes I have:
user_google_oauth2_omniauth_authorize GET|POST /users/auth/google_oauth2(.:format) users/omniauth_callbacks#passthru
user_google_oauth2_omniauth_callback GET|POST /users/auth/google_oauth2/callback(.:format) users/omniauth_callbacks#google_oauth2
Any assistance to know why this isn't working would be greatly appreciated.
/app/controllers/users/omniauth_callbacks_controllers.rb
This is not correct. You have an additional s in your controller name. This is why rails does not manage to find the class. You should rename your controller name to omniauth_callbacks_controller.rb.
I know this has been asked many times, but the answers are never fully acceptable to me.
So I am following Ryan Bates' Railscast about this topic, and mixing that with the official Devise Omniauth guide (that is based on FB), but I am just not getting it to work like I expect, so I would love some help.
I have a Users::OmniauthCallbacksController that looks like this:
class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
def all
#user = User.from_omniauth(request.env["omniauth.auth"])
if #user.persisted?
sign_in_and_redirect root_path, :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")
flash[:notice] = flash[:notice].to_a.concat resource.errors.full_messages
redirect_to new_user_registration_url
end
end
alias_method :twitter, :all
def failure
redirect_to root_path
end
end
Then I also have two methods on my User.rb
def self.from_omniauth(auth)
where(provider: auth.provider, uid: auth.uid).first_or_create do |user|
user.update(
email: auth.info.email,
password: Devise.friendly_token[0,20],
username: auth.info.nickname,
remote_avatar_url: auth.info.image,
token: auth.credentials.token,
secret: auth.credentials.secret
)
end
end
def self.new_with_session(params, session)
super.tap do |user|
if data = session["devise.twitter_data"]
# user.attributes = params
user.update(
email: params[:email],
password: Devise.friendly_token[0,20],
username: data["info"]["nickname"],
remote_avatar_url: data["info"]["image"],
token: data["credentials"]["token"],
secret: data["credentials"]["secret"]
)
end
end
end
I run into a variety of problems. The most immediate is because I am setting the password, the user doesn't know the password when they try to login (and I don't auto sign them in upon confirmation).
But if I don't set the password, it doesn't ask them to set the password...so that's kinda weird too.
These are my devise settings on my User model:
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable,
:confirmable, :omniauthable, :omniauth_providers => [:twitter]
validates :username,
presence: true,
uniqueness: {
case_sensitive: false
}
validate :validate_username
def validate_username
if User.where(email: username).exists?
errors.add(:username, :invalid)
end
end
So my question is this, when someone signs up via Twitter, do they need to enter a password? I automatically send them to the registration/new.html.erb anyway because Twitter doesn't return an email value. But I am trying to just get the process working first, before optimizing it.
How do I deal with the password issue?
Edit 1
For more clarity, I will have to deal with this password_required issue regardless of the OAuth provider.
So how do I override that requirement for all OAuth providers?
You should add the following method to the User class:
def password_required?
(provider.blank? || uid.blank?) && super
end
Since Twitter doesn't return the user's email, you may also want to tweak that email validation, but redirecting the user to registration/new.html.erb like you are already doing seems like the correct approach to me.
I'm using oauth to try and login through venmo based on this guide. This isn't official and venmo docs don't even show code example with ruby.
At first, I couldn't even see the venmo login. I removed the ENV and brackets around the id and secret in the initializer and then I could see the login. When I submit and it hits the call back I get this error: (and I think it retries endlessly...I have to manually shut down server)
{"error": {"message": "Missing argument: client_id.", "code": 241}}
I, [2014-04-16T11:49:48.124423 #47700] INFO -- omniauth: (venmo) Callback phase initiated.
E, [2014-04-16T11:49:48.345202 #47700] ERROR -- omniauth: (venmo) Authentication failure! invalid_credentials: OAuth2::Error, {"message"=>"Missing argument: client_id.", "code"=>241}:
Here is my route:
get 'users/auth/venmo/callback' => 'omniauth_callbacks_controller#create'
Gems:
gem 'devise'
gem 'omniauth'
gem 'omniauth-venmo'
I have this in my initializers/omniauth.rb
Rails.application.config.middleware.use OmniAuth::Builder do
provider :venmo, 'id', 'secret', :scope => 'access_feed,access_profile,access_friends,make_payments'
end
This is my callback controller
class OmniauthCallbacksController < Devise::OmniauthCallbacksController
def venmo
#user = User.find_for_oauth(env["omniauth.auth"], current_user)
raise
if #user.persisted?
sign_in_and_redirect root_path, :event => :authentication
set_flash_message(:notice, :success, :kind => "Venmo") if is_navigational_format?
else
session["devise.venmo_uid"] = env["omniauth.auth"]
redirect_to new_user_registration_url
end
end
protected
def auth_hash
request.env['omniauth.auth']
end
end
and I have initializers/devise.rb
require 'omniauth-venmo'
config.omniauth :venmo, "KEY", "SECRET"
-- with the values filled in of course. I would appreciate the help...
Thank you!!
UPDATE: I've pushed this to a github repository and one of my peers pulled it. He did not get the same error. What would the reason for this be..?
#Peege151... I created a working solution with devise integration as said by you..here is my code below, use it for reference purpose. I don't say this is the exact solution for the raised question but this may help since i got it working
Gems:
gem 'rails 3.2.14' # Important~
gem 'devise'
gem 'omniauth'
gem 'omniauth-venmo'
I have not created omniauth.rb in initializers .... instead i added configuration in devise.rb as u wanted it with devise
my devise.rb :
require "omniauth-venmo"
config.omniauth :venmo, '--Your APP KEY -- ', '-- App Secret--',{:client_options => {:ssl => {:verify => false}}}
above line i have set SSL verification to false,, if u want enable SSL with (:verify => true).
This is my callback controller code:
class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
def venmo
#user = User.find_for_oauth(request.env["omniauth.auth"], current_user)
if #user.persisted?
sign_in_and_redirect #user, :event => :authentication
set_flash_message(:notice, :success, :kind => "Venmo") if is_navigational_format?
else
session["devise.twitter_uid"] = request.env["omniauth.auth"]
redirect_to new_user_registration_url
end
end
end
User.rb code:
class User < ActiveRecord::Base
TEMP_EMAIL = 'change#me.com'
TEMP_EMAIL_REGEX = /change#me.com/
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
# Setup accessible (or protected) attributes for your model
attr_accessible :email, :password, :password_confirmation, :remember_me, :name, :provider , :uid
devise :omniauthable
def self.find_for_oauth(auth, signed_in_resource=nil)
user = User.where(:provider => auth.provider, :uid => auth.uid).first
if user
return user
else
registered_user = User.where(:email => auth.info.email).first
if registered_user
return registered_user
else
user = User.create(name:auth.extra.raw_info.name,
provider:auth.provider,
uid:auth.uid,
email:auth.info.email.blank? ? TEMP_EMAIL : auth.info.email,
password:Devise.friendly_token[0,20],
)
end
end
user
end
end
Here is my for devise and callback routes.rb:
devise_for :users, :controllers => { :omniauth_callbacks => "users/omniauth_callbacks" }
get '/auth/venmo/callback' => 'users/omniauth_callbacks#venmo'
login page link:
<%= link_to "Sign in with Venmo", user_omniauth_authorize_path(:venmo) %>
screenshot:
I'm not sure the exact issue here, but one thing to be cognizant of is it looks you're hitting a naked URL instead of api.venmo.com/v1/, which is our latest version. Try that first, Then we can work from there.