I am trying to add login through gmail feature to my application.
I used 'omniauth' and 'omniauth-google-oauth2' gems,Here is my code
User.rb
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(:provider => access_token.provider, :uid => access_token.uid ).first
if user
return user
else
registered_user = User.where(:email => access_token.info.email).first
if registered_user
return registered_user
else
user = User.create(name: data["name"],
provider:access_token.provider,
email: data["email"],
uid: access_token.uid ,
password: Devise.friendly_token[0,20],
)
end
end
end
devise.rb
require 'omniauth-google-oauth2'
config.omniauth :google_oauth2, "APP_ID", "APP_SECRET", { access_type: "offline", approval_prompt: "" }
replaced APP_ID with my client_id and APP_SECRET with my client_secret
routes.rb
devise_for :users, :controllers => { : omniauth_callbacks => "omniauth_callbacks" }
omniauth_callbacks_controller.rb
class 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
authorised redirect URI
http://localhost:3000/users/auth/google_oauth2/callback
When I try to login it gives
Started GET "/users/auth/google_oauth2/callback?state=fb1921cc2fd051c677bb0058e21e17fbaa028fce2e7eb669&code=4/g2xXVC2arLfYzWGqnswcIuwkDarfdW1ZzPSJRIcdUqw" for 127.0.0.1 at 2015-10-27 16:11:31 +0530
I, [2015-10-27T16:11:31.311428 #8223] INFO -- omniauth: (google_oauth2) Callback phase initiated.
Processing by OmniauthCallbacksController#google_oauth2 as HTML
Parameters: {"state"=>"fb1921cc2fd051c677bb0058e21e17fbaa028fce2e7eb669", "code"=>"4/g2xXVC2arLfYzWGqnswcIuwkDarfdW1ZzPSJRIcdUqw"}
Completed 401 Unauthorized in 0ms
Is there anything wrong in my code,Thanks in advance.
In Omniauth Call Back Controller , try the below code:
class 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, bypass => true
else
session["devise.google_data"] = request.env["omniauth.auth"]
redirect_to new_user_registration_url
end
end
I just added bypass => true
Related
Trying to implement Stripe Connect, and am getting the following error when I click the "connect to stripe" button.
The action 'passthru' could not be found for OmniauthCallbacksController
users/omniauth_callbacks_controller.rb
class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
def stripe_connect
#user = current_user
if #user.update_attributes({
provider: request.env["omniauth.auth"].provider,
uid: request.env["omniauth.auth"].uid,
access_code: request.env["omniauth.auth"].credentials.token,
publishable_key: request.env["omniauth.auth"].info.stripe_publishable_key
})
# anything else you need to do in response..
sign_in_and_redirect #user, :event => :authentication
set_flash_message(:notice, :success, :kind => "Stripe") if is_navigational_format?
else
session["devise.stripe_connect_data"] = request.env["omniauth.auth"]
redirect_to new_user_registration_url
end
end
end
models/user.rb
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable, :omniauthable, :omniauth_providers => [:stripe_connect]
routes.rb
devise_for :users, controllers: { registrations: 'users/registrations', :omniauth_callbacks => "users/omniauth_callbacks" }
gemfile.rb
gem 'omniauth-stripe-connect'
initializers/stripe.rb
Rails.configuration.stripe = {
:publishable_key => ENV['PUBLISHABLE_KEY'],
:secret_key => ENV['SECRET_KEY']
}
Stripe.api_key = Rails.configuration.stripe[:secret_key]
initializers/devise.rb
config.omniauth :stripe_connect,
ENV['STRIPE_CONNECT_CLIENT_ID'],
ENV['STRIPE_SECRET_KEY'],
:scope => 'read_write',
:stripe_landing => 'register'
button link:
<%= link_to image_tag('blue-on-light.png'), user_stripe_connect_omniauth_authorize_path(:stripe_connect) %>
As I understand it with my noob Ruby mind, I need to define 'passthru'? how do I define it though? when I enter:
def passthru
end
the link doesn't work / the page reloads itself. Haven't been able to find a solution on here. What am I missing?
EDIT:
Changed my connect to stripe link to:
<%= link_to image_tag('blue-on-light.png'), "/users/auth/stripe_connect" %>
The link takes me to the connect to stripe page, but when I click the "connect to stripe" button, the page cant be found, and doesn't load or redirect.
Can you try changing
# app/controllers/omniauth_callbacks_controller.rb
class OmniauthCallbacksController < ApplicationController
def stripe_connect
....
to
class OmniauthCallbacksController < Devise::OmniauthCallbacksController
def stripe_connect
#user = User.find_for_stripe_connect(request.env['omniauth.auth'], current_user)
set_notice_and_redirect
end
private
def set_notice_and_redirect
if #user.persisted?
flash[:notice] = 'Successfully signed in'
set_flash_message(:notice, :success, :kind => "Stripe") if is_navigational_format?
else
session["devise.stripe_connect_data"] = request.env["omniauth.auth"]
redirect_to new_user_registration_url
end
end
end
and in your user model
# Checks if user exists, otherwise create it
def self.find_for_stripe_connect(access_token, _ = nil)
data = access_token.info
user = User.where(email: data['email']).first_or_create(
email: data['email'],
password: Devise.friendly_token[0, 20],
provider: request.env["omniauth.auth"].provider,
uid: request.env["omniauth.auth"].uid,
access_code: request.env["omniauth.auth"].credentials.token,
publishable_key: request.env["omniauth.auth"].info.stripe_publishable_key
)
user
end
and also sing in path
<%= link_to image_tag('blue-on-light.png'), user_stripe_connect_omniauth_authorize %>
I think you don't need to define a passthru action. If you see the below two in the routes it can work. Authorize path is for redirecting user to stripe and callback is for redirecting user from stripe back to your site
$ rake routes
user_stripe_connect_omniauth_authorize /auth/stripe_connect(.:format) ....
user_stripe_connect_omniauth_callback /auth/stripe_connect/callback(.:format) ....
So I'm trying to integrate Google OAuth2 with devise in my app but after signing in and allowing access to the app I get redirected back to the sign in page for some reason. I'm using the following tutorial:
https://www.digitalocean.com/community/tutorials/how-to-configure-devise-and-omniauth-for-your-rails-application
Here are my files:
callbacks_controller.rb
class CallbacksController < Devise::OmniauthCallbacksController
def google_oauth2
# 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 => "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
route.rb:
devise_for :users, :controllers => { :omniauth_callbacks => "callbacks" }
users.rb:
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
devise.rb:
config.omniauth :google_oauth2, ENV['GOOGLE_CLIENT_ID'], ENV['GOOGLE_CLIENT_SECRET'], callback_url: ENV['GOOGLE_CALLBACK_URL']
What am I doing wrong? Thanks
Try this:
class ApplicationController < ActionController::Base
def after_sign_in_path_for(resource)
# return path you want to go to...
end
end
When I try to authenticate, I get the message:
"Not found. Authentication passthru."
I added an action_missing method to get a clue: when it's called, it logs:
Parameters: {"provider"=>"google_oauth2"}
So it would appear that I'm getting a complaint that I'm missing the very method that I've defined. Why is my action missing when it's defined?
class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
def google_oauth2
#user = User.from_omniauth(request.env["omniauth.auth"])
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
def action_missing(provider)
logger.debug provider
end
end
devise.rb:
config.omniauth :google_oauth2,
'my',
'secret',
{
:name => "google",
:scope => 'email, profile',
:prompt => 'select_account',
:image_aspect_ratio => 'square',
:image_size => 50
}
User.rb:
class User < ActiveRecord::Base
devise :omniauthable, :omniauth_providers => [:google_oauth2]
def self.from_omniauth(access_token)
data = access_token.info
user = User.where(:email => data["email"]).first
# Uncomment the section below if you want users to be created if they don't exist
# unless user
# user = User.create(name: data["name"],
# email: data["email"],
# password: Devise.friendly_token[0,20]
# )
# end
user
end
end
If you provide :name to your config settings you have to call it from the given name. Also your Authorized redirect URIs will have the name "google" as you specify here.
I found my mistake, someone else may find it edifying:
in devise.rb, I had:
{
:name => 'google', <====== BAD IDEA!
:scope => 'email, profile',
:prompt => 'select_account',
:image_aspect_ratio => 'square',
:image_size => 50
}
the first item, the :name, was copied from another omniauth tutorial. It seems to be a very bad idea. Removing it made things go.
I followed the instructions exactly as in http://sourcey.com/rails-4-omniauth-using-devise-with-twitter-facebook-and-linkedin/#changes
To implement Devise Omniauth Linkedin in my app, I did the following,
In devise.rb
config.omniauth :linked_in, "*******", "**********"
And in my user model which is user.rb , I had this
class User < ActiveRecord::Base
# Include default devise modules. Others available are:
# :lockable, :confirmable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable, :confirmable, :omniauthable
TEMP_EMAIL_PREFIX = 'change#me'
TEMP_EMAIL_REGEX = /\Achange#me/
validates_format_of :email, :without => TEMP_EMAIL_REGEX, on: :update
def self.find_for_oauth(auth, signed_in_resource = nil)
# Get the identity and user if they exist
identity = Identity.find_for_oauth(auth)
# If a signed_in_resource is provided it always overrides the existing user
# to prevent the identity being locked with accidentally created accounts.
# Note that this may leave zombie accounts (with no associated identity) which
# can be cleaned up at a later date.
user = signed_in_resource ? signed_in_resource : identity.user
# Create the user if needed
if user.nil?
# Get the existing user by email if the provider gives us a verified email.
# If no verified email was provided we assign a temporary email and ask the
# user to verify it on the next step via UsersController.finish_signup
email_is_verified = auth.info.email && (auth.info.verified || auth.info.verified_email)
email = auth.info.email if email_is_verified
user = User.where(:email => email).first if email
# Create the user if it's a new registration
if user.nil?
user = User.new(
name: auth.extra.raw_info.name,
#username: auth.info.nickname || auth.uid,
email: email ? email : "#{TEMP_EMAIL_PREFIX}-#{auth.uid}-#{auth.provider}.com",
password: Devise.friendly_token[0,20]
)
user.skip_confirmation!
user.save!
end
end
# Associate the identity with the user if needed
if identity.user != user
identity.user = user
identity.save!
end
user
end
def email_verified?
self.email && self.email !~ TEMP_EMAIL_REGEX
end
end
My routes.db file looks like this
devise_for :users, :controllers => { omniauth_callbacks: 'omniauth_callbacks' }
match '/users/:id/finish_signup' => 'users#finish_signup', via: [:get, :patch], :as => :finish_signup
controllers/omniauth_callbacks_controller.rb
class OmniauthCallbacksController < Devise::OmniauthCallbacksController
def self.provides_callback_for(provider)
class_eval %Q{
def #{provider}
#user = User.find_for_oauth(env["omniauth.auth"], current_user)
if #user.persisted?
sign_in_and_redirect #user, event: :authentication
set_flash_message(:notice, :success, kind: "#{provider}".capitalize) if is_navigational_format?
else
session["devise.#{provider}_data"] = env["omniauth.auth"]
redirect_to new_user_registration_url
end
end
}
end
[:linked_in].each do |provider|
provides_callback_for provider
end
def after_sign_in_path_for(resource)
if resource.email_verified?
super resource
else
finish_signup_path(resource)
end
end
def linkedin
# You need to implement the method below in your model (e.g. app/models/user.rb)
#user = User.find_for_facebook_oauth(request.env["omniauth.auth"], current_user)
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 action_missing(provider)
# Set up authentication/authorizations here, and distribute tasks
# that are provider specific to other methods, leaving only tasks
# that work across all providers in this method.
end
end
When I click on the link to sign in with Linkedin the below error appears:
Not found. Authentication passthru.
Please help me.I don't undeerstand what is wrong, tried time and again but same error appears, Thank you!
This problem is due to the url that is requesting http://localhost:3000/users/auth/linked_in/ instead of http://localhost:3000/users/auth/linkedin/
To fix this you need to change in your app/config/initializers/devise.rb this:
config.omniauth :linked_in, LINKEDIN_CONFIG['APP_KEY'], LINKEDIN_CONFIG['APP_SECRET']
by this:
config.omniauth :linkedin, LINKEDIN_CONFIG['APP_KEY'], LINKEDIN_CONFIG['APP_SECRET']
I'm getting the following error when trying to sign in through google+ using the google_oauth2 gem.
undefined method `find_for_google_oauth2' for #<Class:0x007ff70a337148>
Here's the three files I've altered for sign up.
user.rb
def google_oauth2
user = User.from_omniauth(request.env["omniauth.auth"])
if user.persisted?
flash.notice = "Signed in Through Google!"
sign_in_and_redirect user
else
session["devise.user_attributes"] = user.attributes
flash.notice = "You are almost Done! Please provide a password to finish setting up your account"
redirect_to new_user_registration_url
end
end
omniauth_callbacks_controller.rb
def google_oauth2
# You need to implement the method below in your model (e.g. app/models/user.rb)
#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
and I've added config.omniauth :google_oauth2 in my devise.rb file.
routes.rb
devise_for :users, :controllers => { :registrations => "registrations", :sessions => "sessions", :omniauth_callbacks => "users/omniauth_callbacks" }
You are calling find_for_google_oauth2 from the omniauth_callbacks_controller, but you are using the wrong method name google_oauth2. You should replace google_oauth2 with find_for_google_oauth2.
And it seems like the code in user.rb is incorrect because it contains the controller code. Do you see it looks exactly the same like your controller code? :)
Correct code for user.rb
def self.find_for_google_oauth2(access_token, signed_in_resource=nil)
data = access_token.info
user = User.where(:email => data["email"]).first
# Uncomment the section below if you want users to be created if they don't exist
# unless user
# user = User.create(name: data["name"],
# email: data["email"],
# password: Devise.friendly_token[0,20]
# )
# end
user
end
Read more here: https://github.com/zquestz/omniauth-google-oauth2#devise