BCrypt::Errors::InvalidHash error in Rails In production - ruby-on-rails

I am unable to register a user via LinkedIn on my production site. Its showing an error like this :
Completed 500 Internal Server Error in 202ms (ActiveRecord: 3.8ms)
[f842309d-189a-4edc-bafb-a6a567ea8fcd]
[f842309d-189a-4edc-bafb-a6a567ea8fcd] BCrypt::Errors::InvalidHash (invalid hash):
[f842309d-189a-4edc-bafb-a6a567ea8fcd]
[f842309d-189a-4edc-bafb-a6a567ea8fcd] app/models/user.rb:82:in `from_omniauth'
[f842309d-189a-4edc-bafb-a6a567ea8fcd] app/controllers/users/omniauth_callbacks_controller.rb:9:in `linkedin'
It's working fine in my local machine.
class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
def linkedin
#user = User.from_omniauth(auth_hash, current_user, session)
remember_me(#user)
session[:user_id] = #user.id
if !(#user.img_url == auth_hash.info.picture_url)
#user.update_attributes(:img_url => auth_hash.info.picture_url)
end
if not #user.persisted?
session["devise.linkedin_data"] = auth_hash
render body: session.to_json
end
sign_in_and_redirect(:user, #user)
end
end
User Model
def self.from_omniauth(auth, signed_in=nil, session)
user.password = Devise.friendly_token unless user.encrypted_password.present?
end
Can someone help me understand this error and how I may be able to fix it, please?

Have you tried upgrading your bcrypt to 3.1.12?
Here is the link to GITHUB ISSUE

Have you set all devise config secrets correctly? Check your devise initializer and your ENV variables on your production server. I think the server is missing a ENV variablee to tell bcrypt what salt to use to store the password

Related

User fetching with Rails, BCrypt, Mongoid, and MongoLab fails in deployment

I'm a first-time poster trying to wade through making MongoDB play nice with Rails and Heroku. Right now, I'm getting errors that make me think there is a problem comparing user passwords (that are supposed to be obscured with Bcrypt) during log in. Eager for more advanced eyes, or a better idea of how to troubleshoot this problem.
In the app, I find and create Users like so:
def create
password_key = BCrypt::Password.create(params[:user][:password])
params[:user][:password] = password_key
newUser = User.create(params[:user])
flash[:message] = "Account created! Please log in:"
redirect_to controller: "users", action: "login"
end
def login
end
def find
username = params[:user][:username]
#user = User.where( username: username )[0]
if #user
if BCrypt::Password.new(#user.password) == params[:user][:password]
session[:user_id] = #user.id
redirect_to controller: "application", action: "home"
else
flash[:message] = "Wrong password. Try again."
redirect_to controller: "users", action: "login"
end
else
flash[:message] = "We didn't recognize that username."
redirect_to controller: "users", action: "login"
end
end
This worked fine for me in local dev. When I first deployed to Heroku, I received a "Something went wrong." error instantly upon trying to create a new user, which indicated that I didn't have my production environment configured correctly.
After more reading, I decided to use MongoLab to host my production database. I set that up with an add-on to my heroku repository following this tutorial.
Then I set my heroku env. variable MONGOLAB_URI to the appropriate URI, and included the following in my mongoid.yml file:
production:
sessions:
default:
uri: <%= ENV['MONGOLAB_URI'] %>
options:
consistency: :strong
safe: true
skip_version_check: true
Now, when I access the live app, I no longer get an error when I try to create a user! I am redirected as I would expect and receive my "Account created! Please log in:" flash message.
HOWEVEVER, when I try to login with the credentials I just saved to the database, I'm redirected and my "Wrong password. Try again." flash message fires -- which to me indicates that there is some kind of issue with how passwords are being stored or compared with the combination of BCrypt/Mongoid/MongoLab.
Help, please! Is there something I'm missing about how to use BCrypt with Mongoid? This is only happening to me in production and I'm not sure how to troubleshoot.
Thanks in advance.

Omniauth Callback

Im using devise with my rails 4 app. I authenticate with Facebook, LinkedIn and email.
I've just started to use Figaro and the only change I have made to my code is to swap the password that I use for my email account out of the production.rb into my application.yml file.
Now, when I test the LinkedIn registration link, I get an error saying that something went wrong (after pressing "Register with LinkedIn"). I get the same error when I try to authenticate with the other options.
I have a callback error in my omniauth callback controller for linkedin. The line with the problem is the '#user.send_admin_email' below:
def linkedin
#user = User.find_for_linkedin_oauth(request.env["omniauth.auth"])
if #user.persisted?
#user.send_admin_mail
redirect_to root_path, :event => :authentication
# sign_in_and_redirect #user, :event => :authentication #this will throw if #user is not activated
# set_flash_message(:notice, :success, :kind => "LinkedIn") if is_navigational_format?
else
session["devise.linkedin_data"] = request.env["omniauth.auth"]
redirect_to root_path
end
end
I have a mailer set up which sends me an email to tell me when there is a new registration. It uses the email address for which I moved the password from production.rb to application.yml
Does anyone know how to resolve this error?
Thank you very much
It is possible that the problem is the text-encoding of your application.yml file, especially if your email password has non-standard characters in it. Try firing up the console, and just output your password as it looks with to_s
p ENV['your_figaro_key'].to_s
See if this returns what you would expect
Hmm, it seems a "strong parameter" problem to me. Check your "send_admin_mail" to see if there is a "update_atributes" (or a "save").
My guess is that your user.rb is something like:
class User < ActiveRecord::Base
...
attr_accessor :extras
def self.find_for_linkedin_oauth(access_token, signed_in_resource=nil)
...
user = User.where(...)
...
user.extras = access_token.extras
...
end
def send_admin_mail
...
self.update_attributes(some_attribute: extras["some_attribute"])
...
end
If you are doing this, "save" will try to do an UPDATE with a non-permitted parameter. The correct version must be something this:
self.update_attributes(some_attribute: extras.permit(:some_attribute))
If I'm not wrong, the first implementation worked in the previous versions of strong parameters, but not anymore.

devise + omniauth facebook : current_user nil after sign_in

We have registration and login via facebook using rails, devise, and omniauth. We're hosted on Heroku, running two web dynos.
sometimes login with facebook is failing. The actual handshake between our app and facebook is fine. In fact, in the code below #user is an actual User model instance, the omniauth data Hash contains all of the data from FB, sign_in seems successful AND the current_user is set.
class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
def facebook
#user = User.find_for_facebook(env["omniauth.auth"].extra.raw_info, current_user)
logger.info ">>>>>> OMNIAUTH FB BEGIN >>>>>>"
logger.info env["omniauth.auth"].inspect
logger.info "User is: #{#user.inspect}"
session["devise.facebook_data"] = request.env["omniauth.auth"].except("extra")
flash[:notice] = I18n.t "devise.omniauth_callbacks.success", :kind => "Facebook"
res = sign_in(:user, #user)
logger.info "Sign In Result: #{res.inspect}"
logger.info "CURRENT_USER: #{current_user.inspect}"
logger.info "<<<<<< OMNIAUTH FB END <<<<<<"
respond_to do |format|
format.json
end
end
end
The client-side does a redirect (different actions based on login context) to another URL on our site upon successful login. At that URL, we check for current_user... but current_user is returning nil. If the login process is repeated a few times, eventually it works.
We're on
Rails 3.2
Devise 2.1.2
Omniauth-facebook 1.4.0
Ruby 1.9.3 p194
I don't know whether this is really the solution to what you've described, but I wonder whether this:
#user = User.find_for_facebook(env["omniauth.auth"].extra.raw_info, current_user)
should read as this?
#user = User.find_for_facebook(request.env["omniauth.auth"].extra.raw_info, current_user)
that's how mine is anyways. NOt really sure that would explain why your app is arbitrarily letting the user sign in however.

pulling email from omniauth hash to validate user model

I'm using omniauth and devise to log users in with their facebook acounts, everything works however when I try to pull their email out of the hash I get this error:
NoMethodError in AuthenticationsController#create
undefined method `id' for "/":String
Here's the full log of the error : http://pastie.org/1698569
The error goes away and it lets me log in just fine after I refresh!
EDIT: It turns out that its line 22 in my authentications controller
sign_in_and_redirect_to(:user, root_path)
For some reason after running this method I can't sign_in the :user
def apply_facebook(omniauth)
if (extra = omniauth['extra']['user_hash'] rescue false)
self.email = (extra['email'] rescue '')
end
end
However, if I don't run that method, then it can sign_in_and_redirect_to just fine
Here's my controllers/model http://pastie.org/1698453
Really appreciate any help
You can't use root_path as the second parameter for sign_in_and_redirect . Here are some available ways you can use it:
sign_in_and_redirect :user, #user # sign_in(scope, resource)
sign_in_and_redirect #user # sign_in(resource)
sign_in_and_redirect #user, :event => :authentication # sign_in(resource, options)
sign_in_and_redirect #user, :bypass => true # sign_in(resource, options)
Since your second parameter isn't either a resource or options (it's a string), you're getting an error. You need to change it to:
sign_in_and_redirect(:user, user) # based on your pastie
If you want to customize the return path to force it to go to a different URL after sign-in, you can do something like this in your ApplicationController:
def after_sign_in_path_for(resource)
"/go/to/this/path"
end

OmniAuth / Rails - You have a nil object when you didn't expect it

I'm getting the following error in my Rails application and I have no idea how to go about debugging or fixing it:
NoMethodError in
AuthenticationsController#create
You have a nil object when you didn't
expect it! You might have expected an
instance of ActiveRecord::Base. The
error occurred while evaluating nil.[]
Rails.root:
/Users/phil/Sites/travlrapp.com
Application Trace | Framework Trace |
Full Trace
app/controllers/authentications_controller.rb:15:in
`create'
The controller is this:
class AuthenticationsController < ApplicationController
def index
#authentications = current_user.authentications if current_user
end
def create
omniauth = request.env["omniauth.auth"]
unless omniauth
redirect_to authentications_url
flash[:notice] = "Could not authenticate via #{params['provider']}."
end
authentication = Authentication.find_by_provider_and_uid(omniauth['provider'], omniauth['uid'])
if authentication
flash[:notice] = "Signed in successfully."
sign_in_and_redirect(:user, authentication.user)
elsif current_user
current_user.authentications.create!(:provider => omniauth['provider'], :uid => omniauth['uid'], :token => omniauth['credentials']['token'], :secret => omniauth['credentials']['secret'])
flash[:notice] = "Authentication successful."
redirect_to authentications_url
else
user = User.new
user.apply_omniauth(omniauth)
if user.save
flash[:notice] = "Signed in successfully."
sign_in_and_redirect(:user, user)
else
session[:omniauth] = omniauth.except('extra')
redirect_to new_user_registration_url
end
end
end
def destroy
#authentication = current_user.authentications.find(params[:id])
#authentication.destroy
flash[:notice] = "Successfully destroyed authentication."
redirect_to authentications_url
end
end
OmniAuth used to work fine, then I mashed it up trying to swap to a fork by pchilton which supported flickr. I did this by setting :git => in the gemfile and trying to reinstall but im not confident I ever did it right.
I have now manually removed all omniauth and oa- foo gem files and installed first the current stable (0.1.6) and the git master copy but all errors are the same.
Really at a loss here, nobody I know has any idea what the problem is.
It's probable that omniauth is nil. While you are checking for nil with unless onmniauth, the redirect_to doesn't actually stop the controller code below from executing.
You probably want something like this:
unless omniauth
redirect_to authentications_url
flash[:notice] = "Could not authenticate via #{params['provider']}."
return
end
Now, you still need to figure out why omniauth is nil. For that, make sure you are using OmniAuth correctly by looking at the README. Is /auth/provider/callback routed to AuthenticationsController#create ?
I apologize in advance if you already know this method (you are a php developer after all).
Does rails support php style debugging similar to die() ? I have encountered weird incomprehensible error like this in both yii and kohana php frameworks.
What I do is put a die('AAAAA') at the end of the controller acion, and gradually move it up until IT gets triggered before the error does, that way I know exactly on what line the error was.
Then i move it into whatever function is called on that line and start again.
I don't know if rails supports this kind of raw debug style. Also it would help if the source code for those gems are in noncompiled code so you can insert die() all over the place like that.
You could do something like the equivalent of echo 'AAA'; exit; or something similar.
Also there is also the 'check if a function gets called: die('BBBBB'); :P
If you want to go really advanced there is also
die("AAAAA ".' '.__FILE__.'::Line:'.__LINE__);
This seemed to randomly fix itself. Go Rails!

Resources