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.
Related
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.
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'm trying to do OmniAuth in rails 4 for spotify. I almost have it but for some reason, the redirect URI isn't working. I am using Devise with omniauth These are my files:
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 => [:spotify]
def self.from_omniauth(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]
end
end
end
My Callbacks controller to handle callbacks
class CallbacksController < Devise::OmniauthCallbacksController
def spotify
#user = User.from_omniauth(request.env["omniauth.auth"])
sign_in_and_redirect #user
end
end
My Devise.rb snippet:
config.omniauth :spotify, client_id, client_secret,scope: 'playlist-read-private user-read-private user-read-email'
My Routes.rb
Rails.application.routes.draw do
devise_for :users, :controllers => { :omniauth_callbacks => 'callbacks' }
get '/users/auth/callback', to: 'callbacks#spotify'
end
And lastly, the link leading up to the login:
<%= link_to 'Sign in with Spotify', user_omniauth_authorize_path(:spotify) %>
But for some reason, whenever I try to log into spotify, it says invalid redirect URI
OK, I figured out a solution to my particular problem:
When it was giving me the error of "invalid redirect URI", I looked at the URI it was trying to go to and I simply used that.
Then I got a second error which gave me a SSL Cert error so I used "gem certified" to fix that. THEN, it gave me a third problem of unauthorized access (the callback returned a failed request). What was happening was that I was trying to use OmniAuth twice. I had two files:
A) OmniAuth.rb
and B) Devise.rb
Both of these files were making API calls and it was messing it up. So to anyone having this problem- don't use both omniauth and devise. Honestly, after the first initial hiccup, I found devise to be way more useful than making your own User model and applying omniauth to that. Devise is more comprehensive!
I have problem with authentication through devise + google. I have local application written in Ruby on Rails 3.2. I was following devise docs to make this authentication to works:
https://github.com/plataformatec/devise/wiki/OmniAuth:-Overview
So here is my users omniauth controller located in app/controllers/users
class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
def google_oauth2
#user = User.find_for_google_oauth2(request.env["omniauth.auth"], current_user)
if #user.persisted?
flash[:notice] = I18n.t "devise.omniauth_callbacks.success", :kind => "Google"
sign_in_and_redirect #user, :event => :authentication
else
session["devise.google_data"] = request.env["omniauth.auth"]
redirect_to new_user_registration_url
end
end
end
My routes:
devise_for :users, :controllers => { :omniauth_callbacks => "users/omniauth_callbacks" }
in my devise.rb initializer:
require "omniauth-google-oauth2"
config.omniauth :google_oauth2, "ClientID", "SecretId", { access_type: "offline", approval_prompt: "" }
My user model:
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable, :omniauthable
def self.find_for_google_oauth2(access_token, signed_in_resource=nil)
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
I don't know why this is not working. Maybe I'm doing something wrong with generating oauth clientid in google?
I generate my google app clientid and secret like in the following tutorial:
http://richonrails.com/articles/google-authentication-in-ruby-on-rails
Edit: I forgot to show what error I have:
when i click my link:
<%= link_to "Login via Google account", user_omniauth_authorize_path(:google_oauth2), :class => "btn btn-inverse btn-large" %>
i have the following addres in browser :
https://accounts.google.com/o/oauth2/auth?response_type=code&client_id=487629202871.apps.googleusercontent.com&redirect_uri=http%3A%2F%2Flocalhost%3A3000%2Fusers%2Fauth%2Fgoogle_oauth2%2Fcallback&state=68a65048cca9ccb61a31d2a048bf9ef03d25ebe4a11d77ca&access_type=offline&scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.profile
and my error looks like this:
I have been pulling my hair out because of this.
My cucumber step clicks on a login for facebook. I have mocked omniauth by following the following article:
http://pivotallabs.com/users/mgehard/blog/articles/1595-testing-omniauth-based-login-via-cucumber
My omniauth_callbacks_controller.rb has the following code:
class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
def my_logger
##my_logger = Logger.new("#{Rails.root}/log/my.log")
end
def facebook
#user = User.find_for_facebook_oauth(env["omniauth.auth"], current_user)
if #user.persisted?
flash[:notice] = I18n.t "devise.omniauth_callbacks.success", :kind => "Facebook"
sign_in_and_redirect #user, :event => :authentication
else
session["devise.facebook_data"] = env["omniauth.auth"]
redirect_to new_user_registration_url
end
end
end
I however, get the following error:
When I follow "facebook_login_button" # features/step_definitions/basic.rb:14
undefined method `extra' for #<Hash:0x007fda6d7cd950> (NoMethodError)
./app/models/user.rb:13:in `find_for_facebook_oauth'
./app/controllers/users/omniauth_callbacks_controller.rb:8:in `facebook'
(eval):2:in `click_link'
./features/step_definitions/basic.rb:15:in `/^(?:|I )follow "([^"]*)"$/'
features/homepage.feature:30:in `When I follow "facebook_login_button"'
Other articles I have read:
Devise 1.5 + Omniauth 1.0 + Facebook: undefined method `extra` - problem: this is mocking out omniauth using rspec I think - not sure if it can be applied for cucumber
https://github.com/intridea/omniauth/issues/558 --post by benjamintanweihao works - but its hacking the code to work differently with tests - the git branches suggested dont work either
EDIT: my model/user.rb
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :token_authenticatable, :lockable, :timeoutable, :confirmable and :activatable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
devise :omniauthable
# Setup accessible (or protected) attributes for your model
attr_accessible :email, :password, :password_confirmation, :remember_me
def self.find_for_facebook_oauth(access_token, signed_in_resource=nil)
data = access_token.extra.raw_info
if user = User.where(:email => data.email).first
user
else
User.create!(:email => data.email, :password => Devise.friendly_token[0,20])
end
end
end
This hapens due do this issue: https://github.com/intridea/omniauth/issues/558
It is not your fault, it is a small bug in omniauth.
you can use methods like access_token.extra in production and development mode, but in order to make it work in test mode you should change it to access_token["extra"]