Im using devise in my rails application and everything is working fine, what Im trying to do now is to allow users to login to my app using their github account and create a profile.
User.rb
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
has_one :profile
after_create :build_profile
def build_profile
self.create_profile
end
def self.create_with_omniauth(auth)
user = 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
end
routes.rb
devise_for :users, :controllers => { :omniauth_callbacks => "callbacks" }
callbacks_controller.rb
class CallbacksController < Devise::OmniauthCallbacksController
def github
#user = User.from_omniauth(request.env["omniauth.auth"])
sign_in_and_redirect #user
end
end
I also ran the correct migration to add provider and uid column to the users table
rails g migration AddColumnsToUsers provider uid
def change
add_column :users, :provider, :string
add_column :users, :uid, :string
end
config/initializers/devise.rb
config.omniauth :github, 'CLIENT_ID', 'APP_SECRET', :scope => 'user:email'
When i create a user using devise it all works fine and users are created, but when i click sign in with github on my registration page it merges the devise account and github account together leaving me with one account, its not creating an account with user github credentials. Even if i try and login using 2 different github accounts, it still for some reason only uses the first github account.
problem is github user can login but they are not being created as users, using their github credentials, i need users to login and create a profile with me.
Did you give the credentials in config/initializers/omniauth.rb
Rails.application.config.middleware.use OmniAuth::Builder do
provider :github, ENV['GITHUB_KEY'], ENV['GITHUB_SECRET'], scope:"user:email,user:follow"
end
you can go through by Link
In the Devise's wiki it is said:
where(provider: auth.provider, uid: auth.uid).first_or_create do |user|
But I removed that where method. What happens now is you literally take THE FIRST record from the database and update it.
If no records are present in the database, a record will be created, but on subsequest registrations you will still fetch the first record and modify it. So i changed:
my User.rb to:
def self.from_omniauth(auth)
user = where(provider: auth.provider, uid: auth.uid).first_or_create do |user|
user.email = auth.info.email
user.password = Devise.friendly_token[0,20]
end
end
and callbacks controller to:
#user = User.from_omniauth(request.env["omniauth.auth"])
Related
When I sign in my app with facebook I am getting the error "Invalid App ID" even I verified my app id and it is correct.
what am I doing wrong in my code?
Here is my code:
devise.rb
config.omniauth :facebook, 'xxxxxxxxxxxx', 'xxxxxxxxxxxxxxxxxxxxx', token_params: { parse: :json }
omniauth.rb
Rails.application.config.middleware.use OmniAuth::Builder do
provider :developer unless Rails.env.production?
provider :facebook, ENV['FACEBOOK_APP_ID'], ENV['FACEBOOK_APP_SECRET']
end
routes.rb
Rails.application.routes.draw do
root to: 'surveys#index'
resources :surveys
devise_for :users, controllers: {
sessions: 'users/sessions',
confirmations: 'confirmations',
omniauth_callbacks: "users/omniauth_callbacks"
}
end
omniauth_callbacks_controller.rb
class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
def facebook
#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"]
redirect_to new_user_registration_url
end
end
def failure
redirect_to root_path
end
end
user.rb
class User < ApplicationRecord
has_many :surveys
mount_uploader :avatar, AvatarUploader
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable, :confirmable,
:omniauthable, omniauth_providers: %i[facebook]
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.first_name = auth.info.first_name # assuming the user model has a name
# 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!
end
end
def self.new_with_session(params, session)
super.tap do |user|
if data = session["devise.facebook_data"] && session["devise.facebook_data"]["extra"]["raw_info"]
user.email = data["email"] if user.email.blank?
end
end
end
end
Thanks in advance
I think you are configuring omniauth two times. You should remove omniauth.rb under config/initializers folder.
Remember that config.omniauth adds omniauth provider middleware to your application. This means you should not add this provider middleware again in config/initializers/omniauth.rb as they'll clash with each other and result in always-failing authentication.
Check Devise wiki on Facebook omniauth for Facebook integration.
Im trying to set up Facebook login on my app with devise...however I have run into a problem.
The site redirects the user to Facebook then says:
"Can't Load URL: The domain of this URL isn't included in the app's domains. To be able to load this URL, add all domains and subdomains of your app to the App Domains field in your app settings.
It returns to app and says:
Could not authenticate you from Facebook because "No authorization code".
Here is my code, Users model:
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: [:facebook]
def self.from_omniauth(auth)
where(provider: auth.provider, uid: auth.uid).first_or_create do |user|
user.email = auth.info.email
user.provider = auth.provider
user.uid = auth.uid
user.password = Devise.friendly_token[0,20]
end
end
end
My devise.rb:
config.omniauth :facebook, ENV['FACEBOOK_APP_ID'], ENV['FACEBOOK_APP_SECRET'],
scope: 'email, public_profile', info_fields: 'email, first_name, last_name'
routes:
Rails.application.routes.draw do
devise_for :users, controllers: {omniauth_callbacks: 'users/omniauth_callbacks' }
authenticated :user do
root 'home#index', as: 'authenticated_root'
end
devise_scope :user do
root 'devise/sessions#new'
end
end
My omniauth controller:
class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
def facebook
#user = User.from_omniauth(request.env["omniauth.auth"])
sign_in_and_redirect #user
end
end
Thanks
I will add I'm running this on local host and in the developer section on Facebook I have added 'http://localhost:3000/' in the app domain section.
In the Facebook console in the top left corner, click on your app name then create a test app for your website.
Then replace your main Facebook secret keys with the test keys.
Also make sure your 'Valid OAuth redirect URIs' is set to
http://localhost:3000/users/auth/facebook/callback
This Is what sorted for me.
Good luck
I have Devise user auth included in my site and it is working well. I'm now trying to add Facebook authentication.
I'm able to login with FB, and the user is redirected back to my site ok. When I check the connected apps in FB settings I can see my site is there listed.
The problem is that the FB is not added to my user table. When I check the db, the provider and uid fields are blank, and site is still asking for the user to sign in.
user.rb
class User < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :validatable,
has_many :comments
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :omniauthable, :omniauth_providers => [:facebook]
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 # 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!
end
end
def self.new_with_session(params, session)
super.tap do |user|
if data = session["devise.facebook_data"] && session["devise.facebook_data"]["extra"]["raw_info"]
user.email = data["email"] if user.email.blank?
end
end
end
end
Callback Controller
class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
def 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"])
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"]
redirect_to new_user_registration_url
end
end
def failure
redirect_to root_path
end
routes.rb
#authentication
devise_for :users, path: "auth", controllers: {
sessions: 'users/sessions',
registrations: 'users/registrations',
unlocks: 'users/unlocks',
omniauth_callbacks: 'users/omniauth_callbacks'
}
User Session Controller
class Users::SessionsController < Devise::SessionsController
respond_to :js
before_action :configure_permitted_parameters, :if => :devise_controller?
protected
# If you have extra params to permit, append them to the sanitizer.
def configure_sign_in_params
devise_parameter_sanitizer.permit(:sign_in, keys: [:attribute])
end
end
devise.rb
config.omniauth :facebook, '******', '*************', scope: "email", info_fields: 'email'
Update
Just caught the fact I have fname and lname fields in my user table, so have adjusted user.rb to reflect that:
user.fname = auth.info.fname
After spending 30+ hours trying to get a solution to this and searching all corners of the earth, I am posting my first question here ever.
No matter what I try, I get
'The parameter app_id is required'
I've followed the docs to a T from https://github.com/plataformatec/devise/wiki/OmniAuth:-Overview
Here are the pieces I thought were most important...any ideas what I could be missing?
config/initializers/devise.rb
config.omniauth :facebook, ENV["FACEBOOK_APP_ID"], ENV["FACEBOOK_APP_SECRET"], scope: 'user'
I've checked that the env params are correct on my system.
user.rb
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.new_with_session(params, session)
super.tap do |user|
if data = session["devise.facebook_data"] && session["devise.facebook_data"]["extra"]["raw_info"]
user.email = data["email"] if user.email.blank?
end
end
end
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 # assuming the user model has a name
# user.image = auth.info.image # assuming the user model has an image
end
end
end
Try this instead :
config.omniauth :facebook, "xxxxx", "xxxx"
Using the actual values inside config/initializers/devise.rb worked for me.
I am in the process of trying to integrate Omniauth Facebook login with Devise for a Rails application that I'm currently in the early stages of developing. I'm a (very) junior developer, and I've hit a roadblock which I'm unsure how to resolve.
So far, I have managed to install the Devise gem successfully, and have managed to get the Omniauth Facebook working up to the point of logging into the app with Facebook (by following the documentation at https://github.com/plataformatec/devise/wiki/OmniAuth:-Overview) - however, on the redirect back to my app, the following error message displays:
NoMethodError in Users::OmniauthCallbacksController#facebook
undefined method `name=' for #
user.name = auth.info.name # assuming the user model has a name
The code snippets that I think would be helpful to resolve the issue are as follows:
My user model:
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.new_with_session(params, session)
super.tap do |user|
if data = session["devise.facebook_data"] && session["devise.facebook_data"]["extra"]["raw_info"]
user.email = data["email"] if user.email.blank?
end
end
end
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 # assuming the user model has a name
user.image = auth.info.image # assuming the user model has an image
end
end
end
My routes file:
Rails.application.routes.draw do
devise_for :users, :controllers => { :omniauth_callbacks => "users/omniauth_callbacks" }
root to: "restaurants#index"
devise_scope :user do
get 'sign_out', :to => 'devise/sessions#destroy', only: :destroy_user_session
end
resources :restaurants do
resources :reviews
end
end
I hope that this is enough to help me diagnose the problem, though please do let me know if any further code is required. Huge thanks in advance!
Does your user model have a name and image? Try removing these two lines:
user.name = auth.info.name # assuming the user model has a name
user.image = auth.info.image # assuming the user model has an image