Rails: ActiveModel::ForbiddenAttributesError - ruby-on-rails

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

Related

Devise Wrong number of arguments (13 for 2) upon Omniauthable

Trying to follow this tutorial to implement Google Sign In With Devise into my rails app: https://github.com/plataformatec/devise/wiki/OmniAuth:-Overview
Getting this error:
My routes:
devise_for :users, controllers: { sessions: 'users/sessions', registrations: 'users/registrations', omniauth_callbacks: 'users/omniauth_callbacks' }
Omniauthable controller: app/controllers/users/omniauth_callbacks_controller.rb
class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
def google_oauth2
#user = User.from_omniauth(request.env["omniauth.auth"])
puts #user
if #user.persisted?
sign_in_and_redirect #user
set_flash_message(:notice, :success, kind: "Google") if is_navigational_format?
else
puts "WENT INTO HERE---------"
session["devise.google_data"] = request.env["omniauth.auth"]
redirect_to root_path
end
end
def failure
redirect_to root_path
end
end
User.rb
class User < ApplicationRecord
devise :rememberable, :trackable,
:omniauthable, omniauth_providers: %i[google_oauth2]
# rubocop:disable Metrics/AbcSize
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
user.last_name = auth.info.last_name
user.image_url = auth.info.image # assuming the user model has an image
end
end
end
I have identified the 13 arguments that the app is referring to, from the session dump:
warden.user.user.key: {"id"=>204, "uid"=>"*******", "first_name"=>"First name", "last_name"=>"last name", "provider"=>"google_oauth2", "image_url"=>"*****", "email"=>"***", "has_logged_in"=>false, "created_at"=>"2018-03-17T21:26:24.782Z", "updated_at"=>"2018-03-17T23:31:38.220Z", "admin"=>false}
But I don't know where this came from or how to solve it
Not sure what the issue was but after closing my browser, the problem was fixed. So it probably had something to do with my cache.

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

ForbiddenAttributesError ruby on rails

I have this model in Ruby but it throws a ActiveModel::ForbiddenAttributesError
class User < ActiveRecord::Base
def self.from_omniauth(auth)
where(auth.slice("uid", "nickname", "image")).first || create_from_omniauth(auth)
end
def self.create_from_omniauth(auth)
create! do |user|
user.uid = auth["uid"]
user.name = auth["info"]["nickname"]
user.image = auth["info"]["image"]
end
end
end
when i run this action
def auth_callback
user = User.from_omniauth(env["omniauth.auth"])
session[:user_id] = user.id
redirect_to root_url, notice: "signed in!"
end
end
on ruby 2.2.1p85 (2015-02-26 revision 49769) [x86_64-linux]
Can you please tell me how to get rid of this error?
Thanks in advance.
I think that the slice method it no longer available to bypass strong parameters.
Try this code, which tries to be more specific for auth options:
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.save
end
end
You may probably need to use auth[:provider] instead of auth.provider.
Let me know in the comments if this works for you.
You can also browse this question that helped me out.

Rails fetch oauth token and extra fields

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

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

Resources