I don't know where comes from this following error message from Devise + omniauth Google:
"Could not authenticate you from GoogleOauth2 because "Invalid credentials".
Is it came from a occurred manipulation with Google API? Or came from a mistake with my code?
Is there a right convention to call API ID and SECRET KEYS in application.yml
I checked numerous tutorials but no answers...
Please could you guide me. Thank you for your clear explanation.
Here is my controller code
def google_oauth2
user = User.find_for_google_oauth2(request.env['omniauth.auth'])
if user.persisted?
sign_in_and_redirect user, event: :authentication
set_flash_message(:notice, :success, kind: 'GoogleOauth2') if is_navigational_format?
else
session['devise.google_oauth2_data'] = request.env['omniauth.auth']
redirect_to new_user_registration_url
end
end
Here is the Model :
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable,
:omniauthable, omniauth_providers: [:facebook, :google_oauth2]
has_and_belongs_to_many :oauth_credentials
def self.find_for_google_oauth2(auth)
where(provider: auth.provider, uid: auth.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] # Fake password for validation
user.first_name = auth.info.name
user.last_name = auth.info.nickname
user.picture = auth.info.image
user.token = auth.credentials.token
end
end
Thank you for your help.
Related
I'm trying use the google login oauth2 in my project, all the codes successfully fixed in right position but I dont want the google oauth2 features to request for email verification just straight to login, I prefer it to get skipped, how do I achieve this without removing the :confirmable devise module? this is my code user.rb in model
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable,
:confirmable, :omniauthable, omniauth_providers: [:github, :google_oauth2]
has_many :friends
def self.from_omniauth(access_token)
data = access_token.info
user = User.where(email: data['email']).first
unless user
user = User.create(
email: data['email'],
password: Devise.friendly_token[0,20]
)
end
user
end
end
This is code for the omniauth callback controller .rb
class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
def google_oauth2
handle_auth "Google"
end
def github
handle_auth "Github"
end
def handle_auth(kind)
# You need to implement the method below in your model (e.g. app/models/user.rb)
#user = User.from_omniauth(request.env['omniauth.auth'])
if #user.persisted?
flash[:notice] = I18n.t 'devise.omniauth_callbacks.success', kind: kind
sign_in_and_redirect #user, event: :authentication
else
session['devise.auth_data'] = request.env['omniauth.auth'].except('extra') # Removing extra as it can overflow some session stores
redirect_to new_user_registration_url, alert: #user.errors.full_messages.join("\n")
end
end
end
The Devise Confirmable Module provides a skip_confirmation! method to do this. In your from_omniauth function, instead of
user = User.create(
email: data['email'],
password: Devise.friendly_token[0,20]
)
Instead do this
user = User.new(
email: data['email'],
password: Devise.friendly_token[0,20]
)
user.skip_confirmation!
user.save!
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'm getting this error:
The action 'github' could not be found for Users::OmniauthCallbacksController
I've looked everywhere and tried the other suggestions on other peoples posts.
This was the post on stack overflow but they had a typo and I didn't have that same error.
Devise OmniauthsController not being used
This recommendation said to check rake routes but my routes match what I'm pointing to.
https://github.com/plataformatec/devise/issues/1566
Most of the other links were all similar issues and I double checked the info with mine, changed stuff and still getting errors.
Info about my code.
gemfile:
gem 'omniauth-github'
config/routes.rb:
devise_for :users, :controllers => { :omniauth_callbacks => 'users/omniauth_callbacks' }
Users::OmniauthCallbacksController:
class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
def github
#user = User.from_omniauth(request.env["omniauth.auth"])
if #user.persisted?
sign_in_and_redirect #user, event: :authentication
set_flash_message(:notice, :success, kind: "Github") if is_navigational_format?
else
redirect_to root_path
end
end
end
User Model:
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable, :omniauthable, :omniauth_providers => [:github]
def self.from_omniauth(auth)
where(provider: auth.provider, uid: auth.uid).first_or_create do |user|
user.email = auth.info.email
user.uid = auth.uid
user.provider = auth.provider
user.password = Devise.friendly_token[0, 20]
user.name = auth.info.name #assuming the user model has a name
user.oauth_token = auth.credentials.token
user.image = auth.info.image #assuming the user model has an image
user.save!
end
end
Devise initializer:
config.omniauth :github, Rails.application.secrets.github_client_id, Rails.application.secrets.github_client_secret, scope: 'user:email'
Not sure what to do since I have the method in the Users::OmniauthCallBacks controller? Am I missing something? I've been combing through for an entire day.
Update: somehow I had 2 users folders in the controller but one was hidden? It must have gotten messed up when I reverted to a previous repo last night. Once I removed the folder all was good!
I'm playing around with the omniauth-facebook gem to log into a devise session through a facebook account. When I click the "Sign in with facebook" link, everything goes well: a new account is created, I'm signed in and bounce back to the homepage with a message confirming my new session (very good!).
Problem: However when an account already exists, upon clicking the link I am redirected to the user/sign_up page. I've been following this documentation from the Devise wiki. There is a good deal of documentation on similar errors here, here, here and here. Each of the solutions, however, are already implemented in my app (as far as I can tell) OR (in the case of the last link) seem to be based on an older configuration model that seems sufficiently different from the wiki that I'm not sure it's applicable.
My best guess is that it has something to do with the callbacks controller, as #user.persisted? seems to be coming up false.This leads me to believe that my definition of #user is not correct. See below:
class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
def facebook
logger.debug "Inside facebook"
# You need to implement the method below in your model (e.g. app/models/user.rb)
#user = User.from_omniauth(request.env["omniauth.auth"])
logger.debug "User is #{#user}"
if #user.persisted?
logger.debug "#user.persisted?"
debugger
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?
logger.debug "user exists"
else
session["devise.facebook_data"] = request.env["omniauth.auth"]
redirect_to new_user_registration_url
end
end
def failure
redirect_to root_path, alert: "Login failed"
end
end
Additionally, my user model is as follows:
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable, :omniauthable, :omniauth_providers => [:facebook]
def self.from_omniauth(auth)
where(provider: auth.provider, uid: auth.uid).first_or_create do |user|
user.provider = Devise.friendly_token[0,20]
user.email = auth.info.email
user.password = Devise.friendly_token[0,20]
user.fname = auth.info.first_name
user.lname = auth.info.last_name
end
end
end
Any suggestions would be certainly welcome! Thanks in advance.
Try Something Like This
class Authentication < ActiveRecord::Base
belongs_to :user
# validates :provider, :uid, :presence => true
def self.from_omniauth(auth)
authenticate = where(provider: auth[:provider], :uid=>auth[:uid]).first_or_initialize
if authenticate.user
authenticate.provider = auth[:provider]
authenticate.uid =auth[:uid]
else
user = User.find_or_initialize_by(:email => email)
authenticate.provider = auth[:provider]
user.email = email
user.first_name = first_name
user.last_name = last_name
user.social_image = image
user.password = Devise.friendly_token.first(8)
user.save(validate: false)
if user.errors.any?
return user
else
authenticate.user_id = user.id
end
end
authenticate.save
authenticate.user
end
end
Try this
def after_sign_in_path_for(resource)
super resource
end
From what i perceived that you are not going to your landing page
from_omniauth never finds an existing facebook user because you are overwriting the provider attribute:
where(provider: auth.provider, uid: auth.uid).first_or_create do |user|
searches for a user with provider 'facebook' in this case, but none can be found:
user.provider = Devise.friendly_token[0,20]
changes the provider to some random token
just remove that line and it should work properly
I am setting up devise with omniauth facebook gem to build a signup system. Users can either register with email or connect with their facebook account.
If an email registered user signs in with the facebook account, I check if the email address is already registered and connect these two accounts, and then log the user in.
This whole scenario works already. The user entry is updated with the new omniauth data of facebook. I get this error, when facebooks sends the callback (data from facebook is saved to db successfully):
RuntimeError in CallbacksController#facebook
Could not find a valid mapping for true
Extracted source (around line #5):
class CallbacksController < Devise::OmniauthCallbacksController
# Define each provider for omniauth here (def twitter...)
def facebook
#user = User.from_omniauth(request.env["omniauth.auth"])
sign_in_and_redirect #user
end
end
user.rb modell looks like this:
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable,
:omniauthable, :omniauth_providers => [:facebook]
def self.from_omniauth(auth)
user = where(provider: auth.provider, uid: auth.uid).first
unless user
user = where(email: auth.info.email).first_or_initialize
user.provider = auth.provider
user.uid = auth.uid
user.email = auth.info.email
user.name = auth.info.name
user.nickname = auth.info.nickname
user.first_name = auth.info.first_name
user.last_name = auth.info.last_name
user.location = auth.info.location
user.description = auth.info.description
user.image = auth.info.image
user.phone = auth.info.phone
user.urls = auth.info.urls
user.password = Devise.friendly_token[0,20]
user.save!
end
end
end
routes.rb
Rails.application.routes.draw do
devise_for :users, :controllers => { :omniauth_callbacks => "callbacks" }
resources :auctions do
resources :comments
end
root 'welcome#index'
get '/', :to => 'welcome#index'
end
Your self.from_omniauth method in your User class is returning true, instead of a User model. It's because the return value of a method in Ruby is the result of the last line evaluated, and in this case user.save! is the last line that runs. The "Could not find a valid mapping for true" error is a result of passing true into sign_in_and_redirect; you can see in the Devise source that the first argument is passed into Devise::Mapping.find_scope!.
The solution's simple - make sure that you're returning your user model in from_omniauth:
def self.from_omniauth(auth)
user = where(provider: auth.provider, uid: auth.uid).first
unless user
user = where(email: auth.info.email).first_or_initialize
user.provider = auth.provider
user.uid = auth.uid
user.email = auth.info.email
user.name = auth.info.name
user.nickname = auth.info.nickname
user.first_name = auth.info.first_name
user.last_name = auth.info.last_name
user.location = auth.info.location
user.description = auth.info.description
user.image = auth.info.image
user.phone = auth.info.phone
user.urls = auth.info.urls
user.password = Devise.friendly_token[0,20]
user.save!
end
user # Make sure we return the user we constructed.
end