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!
Related
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 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've been using Devise + OmniAuth Twitter to authenticate the user to my portal. I am currently facing two issues.
When the user is accessing /users/sign_up, the form is publicly visible. Instead, I want to redirect him to the Twitter authentication page.
When the user is accessing /users/sign_up, the email form is visible. I'm using this form to get the email address of the users after he signs up successfully from Twitter.
Can someone please help me solve this issue from people accessing the forms directly?
Adding Code Snippets:
#config/routes.rb
devise_for :users, :controllers => { :omniauth_callbacks => "users/omniauth_callbacks" }
devise_scope :user do
get "skcript1625" => "devise/sessions#new", as: :login
get "logout", to: "devise/sessions#destroy", as: :logout
end
# app/models/user.rb
devise :database_authenticatable, :registerable, :rememberable, :trackable, :validatable
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.profileimg = auth.info.profileimg # assuming the user model has an image
end
end
You have to redirect the user with the following link
<%= link_to "Sign in with Twitter", user_omniauth_authorize_path(:twitter) %>
Make sure you told your model (usually 'user') that it is 'omniauthable'
devise :omniauthable, :omniauth_providers => [:twitter]
When the user authorized twitter to share your info with the app, all the user's information is available in a hash request.env["omniauth.auth"].
See the documentation for more detail about this hash.
Edit: Everything is well explained here
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"]
I followed Railscasts(ASCII versions) #235 and and part of #236 to setup creating user authentications using OmniAuth & Devise: OmniAuth Part 1 OmniAuth Part 2
I am at the stage where I just modified the create method of the authentications controller to allow user's not signed in to the site to sign in directly via twitter. The code for the create method is as follows:
def create
omniauth = request.env["omniauth.auth"]
authentication = Authentication.find_by_provider_and_uid(omniauth['provider'], omniauth['uid'])
if authentication
flash[:notice] = "Signed in successfully."
logger.info("AUTHENTICATION: #{authentication.inspect}")
#logger.info("AUTHENTICATION METHODS: #{authentication.methods.sort}")
logger.info("authentication.user: #{authentication.user}")
#logger.info("authentication.user.nil?: #{authentication.user.nil?}")
#logger.info("authentication.user.id: #{authentication.user.id}")
sign_in_and_redirect(:user, authentication.user)
else
current_user.authentications.create(:provider => omniauth['provider'], :uid => omniauth['uid'])
flash[:notice] = "Authentication successful."
redirect_to authentications_url
end
end
Now when I go to /auth/twitter, I get this error:
No route matches "/auth/failure"
This is because authentication.user is nil. The code for the create method is exactly as per the Railscast, and I don't see why authentication.user is nil.
This is the output of the authentication.inspect:
#<Authentication id: 1, user_id: 1, provider: "twitter", uid: "319521616", created_at: "2011-08-01 10:32:48", updated_at: "2011-08-01 10:32:48">
Does anyone have any insight as to whyauthentication.user would be nil, even tough the inspect method returns valid data.
Here is the code from my user model:
class User < ActiveRecord::Base
has_many :authentications
# Include default devise modules. Others available are:
# :token_authenticatable, :encryptable, :confirmable, :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable,
:lockable, :confirmable #Added lockable and confirmable
# Setup accessible (or protected) attributes for your model
attr_accessible :email, :password, :password_confirmation, :remember_me
end
Do you have any validations in your user model? This caused a silent fail on saving the user model, for me, which led to the error message you describe, when I did the same set up. Just one idea.