Rails fetch oauth token and extra fields - ruby-on-rails

I am trying to fetch oauth token but unable to do so. I am using omniauth for login using facebook.I am able to login in but i want to fetch functionalities like profile data of user.So thats why i want to fetch token Here is my code
[omniauth.rb]
OmniAuth.config.logger = Rails.logger
Rails.application.config.middleware.use OmniAuth::Builder do
provider :facebook, 'my-app-key', 'my-app-id', {:client_options => {:ssl => {:ca_file => Rails.root.join("cacert.pem").to_s}}}
end
[user.rb]
class User < ActiveRecord::Base
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.name = auth.info.name
user
user.save
end
end
end
[application_controller]
class ApplicationController < ActionController::Base
# Prevent CSRF attacks by raising an exception.
# For APIs, you may want to use :null_session instead.
protect_from_forgery with: :exception
helper_method :current_user
def current_user
#current_user ||= User.find(session[:user_id]) if session[:user_id]
end
end
[session_controller]
class SessionsController < ApplicationController
def create
user = User.from_omniauth(env["omniauth.auth"])
session[:user_id] = user.id
redirect_to root_path
end
def destroy
session[:user_id] = nil
redirect_to root_path
end
end

You should add the desired parameters in the initializer. Please see scope in the docs for more details
config/initializers/omniauth.rb
Rails.application.config.middleware.use OmniAuth::Builder do
provider :facebook,ENV["FACEBOOK_APP_ID"], ENV["FACEBOOK_SECRET_ID"],
{:scope => 'email, public_profile, user_friends',
:secure_image_url => true}
end

Related

Omniauth redirects back to signin page

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

Devise omniauth(oauth) sign_in, and sign_up path setting

I want to separate my oauth redirect paths. One is for facebook and google(register/info1), the other is for twitter(register/info2).
My users go to register/info(1/2) pages, when they sign up first time.
After users sign up and sign in next time, they go to home/main, instead of register/info(1/2)
But after_sign_up_path_for method does not working in omniauth_callback_controller. So, Users always go to register/info(1/2).
Currently, I set my omniauth_callback_controllers.rb like this.
class User::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
else
session["devise.#{provider}_data"] = env["omniauth.auth"]
redirect_to new_user_registration_url
end
end
}
end
[:twitter, :facebook, :google_oauth2].each do |provider|
provides_callback_for provider
end
def after_sign_in_path_for(resource)
auth = request.env['omniauth.auth']
#identity = Identity.find_for_oauth(auth)
#user = User.find(current_user.id)
if #user.persisted?
if #identity.provider == "twitter"
register_info2_path
else
register_info1_path
end
else
home_main_path
end
end
If you have any ideas or related documents, please let me know. Thanks.
you can set the callback path per strategy in the omniauth.rb initializer:
for example:
Rails.application.config.middleware.use OmniAuth::Builder do
provider :facebook, "app_id", "password",
scope: 'public_profile', info_fields: 'id,name,link', display: 'popup', callback_path: '/stores/facebook_callback'
end

Validation failed: Password can't be blank

I have an app, build on Rails 4.2 and tried to do twitter authentication, using RailsCasts #241 Simple OmniAuth.
But have this issue: Validation failed: Password can't be blank!
I searched answer everywhere, but did not find the solution!
user.rb
class User < ActiveRecord::Base
has_secure_password
validates :password, length: { minimum: 6 }, allow_blank: true
def self.create_with_omniauth(auth)
create! do |user|
user.provider = auth.provider
user.uid = auth.uid
user.name = auth.info.name
end
end
end
sessions_controller.rb
class SessionsController < ApplicationController
def login
end
def create
#user = User.find_by_email(params[:email])
if #user && #user.authenticate(params[:password])
session[:user_id] = #user.id
redirect_to root_path
else
redirect_to :back
end
end
def create_session
auth = request.env['omniauth.auth']
user = User.find_by_provider_and_uid(auth['provider'], auth['uid']) || User.create_with_omniauth(auth)
session[:user_id] = user.id
redirect_to root_url, notice: 'Signed in!'
end
def logout
reset_session
redirect_to root_path
end
end
routes.rb
get 'sessions/login'
get 'sessions/logout'
post 'sessions' => 'sessions#create'
get '/auth/:provider/callback' => 'sessions#create_session'
post '/auth/:provider/callback' => 'sessions#create_session'
get 'registration' => 'users#new', as: 'registration'
Solution
After editing user.rb model looks like:
class User < ActiveRecord::Base
has_secure_password
validates :password, length: { minimum: 6 }
require 'securerandom'
def self.create_with_omniauth(auth)
create! do |user|
user.provider = auth.provider
user.uid = auth.uid
user.name = auth.info.name
user.password = SecureRandom.urlsafe_base64
end
end
end
An alternative approach is to enter a random password on user creation. For example as shown in the omniauth-google-oauth2 readme. So you could alter your code to this:
require 'securerandom'
def self.create_with_omniauth(auth)
create! do |user|
user.provider = auth.provider
user.uid = auth.uid
user.name = auth.info.name
user.password = SecureRandom.urlsafe_base64
end
end
I think it's problem with
has_secure_password
try commenting it, and you can override the has_secure_password Or
has_secure_password(validations: false)
This is happening as it automatically adds
validates_presence_of :password_digest
So when specify allow_blank or allow_null it will not work

Rails: ActiveModel::ForbiddenAttributesError

I'm trying to use OmniAuth to integrate Facebook with my website, and I think I'm getting a few errors here. Right now when I click "Sign in with Facebook" it does bring me to Facebook, but soon as I sign in I get an error saying ActiveModel::ForbiddenAttributesError. Also, I think there might be an issue my routes as well but I'm not sure.
Also, I followed this RailsCasts tutorial: http://railscasts.com/episodes/360-facebook-authentication?autoplay=true
Edit: The error is on this line here, where(auth.slice(:provider, :uid)).first_or_initialize.tap do |user|
omniauth.rb
OmniAuth.config.logger = Rails.logger
Rails.application.config.middleware.use OmniAuth::Builder do
provider :facebook, ENV['FACEBOOK_APP_ID'], ENV['FACEBOOK_SECRET']
end
user.rb
class User < ActiveRecord::Base
def self.from_omniauth(auth)
where(auth.slice(:provider, :uid)).first_or_initialize.tap do |user|
user.provider = auth.provider
user.uid = auth.uid
user.name = auth.info.name
user.oauth_token = auth.credentials.token
user.oauth_expires_at = Time.at(auth.credentials.expires_at)
user.save!
end
end
end
routes.rb
Rails.application.routes.draw do
get 'auth/:provider/callback', to: 'sessions#create'
get 'auth/failure', ('/posts/index')
get 'signout', to: 'sessions#destroy', as: 'signout'
resources :welcome
resources :posts
root "welcome#index"
sessions_controller.rb
class SessionsController < ApplicationController
def create
user = User.from_omniauth(env["omniauth.auth"])
session[:user_id] = user.id
redirect_to root_url
end
def destroy
session[:user_id] = nil
redirect_to root_url
end
end
application_controller.rb
class ApplicationController < ActionController::Base
# Prevent CSRF attacks by raising an exception.
# For APIs, you may want to use :null_session instead.
protect_from_forgery with: :exception
private
def current_user
#current_user ||= User.find(session[:user_id]) if session[:user_id]
end
helper_method :current_user
end
Modify your finder like so:
class User < ActiveRecord::Base
def self.from_omniauth(auth)
where(provider: auth.provider, uid: auth.uid).first_or_initialize do |user|
user.provider = auth.provider
user.uid = auth.uid
user.name = auth.info.name
user.oauth_token = auth.credentials.token
user.oauth_expires_at = Time.at(auth.credentials.expires_at)
user.save!
end
end
end

Displaying Facebook info of logged out user

Creating a Rails app that interacts heavily with Facebook. I want to users to be able to look at profiles of other users and see information on those users that has been pulled in from Facebook.
I'm using the omniauth-facebook and koala gems. I followed Ryan Bates' Railscasts on Facebook authentication and Facebook Graph API to get where I'm at.
I would prefer not to have to store a user's Facebook info in my database, but that seems to be the only way of doing it, because otherwise, when I try to view the profile page of another user who may have logged out, I get: "Koala::Facebook::AuthenticationError in Profiles#show"
type: OAuthException, code: 190, error_subcode: 467, message: Error validating access token: The session is invalid because the user logged out. [HTTP 400].
Is there a way to bring in this data from Facebook, even if that user has logged out?
Here's the necessary code:
user.rb:
class User < ActiveRecord::Base
def self.from_omniauth(auth)
where(auth.slice(:provider, :uid)).first_or_initialize.tap do |user|
user.provider = auth.provider
user.uid = auth.uid
user.name = auth.info.name
user.image = auth.info.image
user.oauth_token = auth.credentials.token
user.oauth_expires_at = Time.at(auth.credentials.expires_at)
user.save!
end
end
def facebook
#facebook ||= Koala::Facebook::API.new(oauth_token)
block_given? ? yield(#facebook) : #facebook
rescue Koala::Facebook::APIError
logger.info e.to_s
nil
end
end
sessions_controller.rb
class SessionsController < ApplicationController
def create
user = User.from_omniauth(env["omniauth.auth"])
session[:user_id] = user.id
redirect_to feed_path
end
def destroy
session[:user_id] = nil
redirect_to root_url
end
end
application_controller.rb
class ApplicationController < ActionController::Base
protect_from_forgery
private
def current_user
#current_user ||= User.find(session[:user_id]) if session[:user_id]
rescue ActiveRecord::RecordNotFound
end
helper_method :current_user
end
profiles_controller.rb
class ProfilesController < ApplicationController
def show
#user = User.find(params[:id])
end
end
profiles_helper.rb:
module ProfilesHelper
def facebook_profile_info
#user.facebook.get_object("#{#user.uid}",fields:'gender, locale, bio, birthday,
picture, relationship_status')
end
end
Also, if you have suggestions on better ways to accomplish these tasks than the trajectory I'm headed in, I welcome your suggestions.

Resources