in devise rails gem, what is the difference between these two?
I have seen the :encrypted_password field in the generated schema but not :password field.
Any explanations if these two are interconnected with each other?
Devise::Models::DatabaseAuthenticatable has a setter for that:
def password=(new_password)
#password = new_password
self.encrypted_password = password_digest(#password) if #password.present?
end
So you should set the password as if there was a password field, devise will take care of encrypting it.
As #spickermann already pointed out - plain text password should never be stored anywhere and should filtered out from logs/error messages and so on, because this produces a huge security risk: the encrypted password leak is not totally harmless, but not dangerous that much.
password is the plain text the user set as his password (and plain text password should never be stored anywhere). encrypted_password this the encrypted version of this password.
You might want to read SecurePassword.
:password is the password that a user sets through a form.
:encrypted_password is what is stored in your database and retrieved to create a user session.
Essentially, :encrypted_password is a hashed and salted version of :password that can be safely stored in your database. See this answer if you need more information on why you shouldn't store plain text passwords in your database.
Related
I'm using the attr_encrypted gem and I got also devise installed in my environment.
I got a user model this is handled by devise and the database column is:
encrypted_password
Users can save clients and I want to encrypt the clients name and age with the users password.
my client.rb file looks like this:
Here the data gets encrypted successfully.
class Client < ActiveRecord::Base
attr_accessor :name :age
attr_encrypted :name, :age, key: "test1234"
But I'd like to encrypt the data with the Users.password.
Something like so:
class Client < ActiveRecord::Base
attr_accessor :name :age
attr_encrypted :name, :age, key: current_user.encrypted_password
The current_user is the Devise helper method but since this is from a session I can't access it in a model.
Basically I'd like to encrypt all the clients stuff with users password.
But If I do that with the encrypted_password then I already got the password to decrypt the whole field.
I want to provide security to my users and I don't want to know or be able to view their data.
So the only way to do this is by encrypting all the data with the prehashed devise users password?
edit:
The user.encrypted_password is already hashed and whenever I access the db - I can use this to decrypt all the data right?
So I should request the users password -> hash it like devise does - compare it with the users.encrypted_password?
Do I have a logic error somewhere ?
How would you solve this?
attr_encrypted provides a way to specify an instance method to provide the key.
class Client < ActiveRecord::Base
attr_encrypted :name, :age, key: :client_key
def client_key
# just assuming relation between Client and User
self.user.encrypted_password
end
end
Source: https://github.com/attr-encrypted/attr_encrypted#symbols-representing-instance-methods-as-keys
As you using Devise it uses bcrypt algorithm to encrypt your password which is one way encryption
ie this process is not reversible, there's no way to go from the hash back to the password.
so you can use that hash for encrypting the whole data.
But my suggestion would be you use bcrypt algorithm for encrypting your data rather than using user password,reason why i am suggesting bcrypt rather than using your password a hash to encrypt your data
You will have re-encrypt you data each and every time when the user
changes his password If you fail to do so in any occasion you wont
be able to retrive you data back.
The overhead will more ie each time re-encrypting the data on
password change
The encrypted_password will be very tightly coupled with the user
data. I feel that the user data should be independent of password
related to access and there should be a different independent
encrypting for use data which is not related to user login or
password
You can also ref : https://github.com/codahale/bcrypt-ruby
I've a password stored in a database.
The user should be able to set a new one.
I've also used attr_encrypted gem to store it as encrypted text (symmetric because i need it back to connect to other services and not just to login) but this is another story.
When I show the form, the default behavior of ruby helpers is to not send back the password to the browser for obvious security reasons.
Here is the code:
<%= f.input :app_password, :as => :password %>
this behavior might be ok, nevertheless some issues arise from it.
if the user saves the form with null password, the password will be erased. I should test and avoid null-password savings but in some application null password is acceptable and doing so i would prevent this possibility.
it doesn't provide a visual feedback to the user on the fact that he or she has compiled the password field.
it doesn't play very well with validations
What are my options here in order to obtain the most standard possible behavior (that is, no 'change password' checkboxes)?
Please, in forms include password fields this way:
<%= f.password_field :app_password %>
The standard use and set of password is:
Add to your user model a call to has_secure_password
Add field to users for store an encripted password, migration: add_column :users, :auth_token, :string
Before create generate a token:
begin
self.auth_token = SecureRandom.urlsafe_base64
end while User.exists?(auth_token: self.auth_token)
Authenticate your users with #user.authenticate(params[:password])
Update password at another form with 3 fields, old_password, password, and password_confirmation.
Is there a way I can tell Devise not to use a password? I'm using Devise with LDAP so the encrypted password field is a wasted column (the password is stored in the LDAP directory). If I delete the encrypted_password column and then add some dummy accessors on my models
def encrypted_password
""
end
def encrypted_password=dummy
end
I can at least get rid of the column in the database. However, when I create new users I still have to supply a dummy password
User.create(:first_name => "Dummy", :password => "dummyPass1", :password_confirmation => "dummyPass1")
Is there a setting somewhere that would make this cleaner?
You can take "database_authenticatable" out of the devise config line in your User model, and drop the encrypted_password field entirely.
I'm using the "has_secure_password" way to store a secure password in the database. When creating an user by the admin (in my app users are created, users can't create an account themselves), in the user model the password_digest is filled by a method to create a random password (see code). When the record is then saved, it is saved secure. So the user method is creating a password_digest say "TY5665^%^", then it is saved in the database say "Y^6&$d%$56GFT". Great!
before_validation :create_random_password, :on => :create
def create_random_password
self.password_digest = SecureRandom.hex(5)
end
But when the new user logs in and changes his password in his profile, the new password gets saved OK, but unsecured! Say the user is changing it to "password1", it also gets saved as "password1" in the database. So why is the secure password working on create, but not on update?
Without seeing your update code, make sure your update is to :password, not :password_digest. The magic behind the creation of a password hash to go into :password_digest only starts with :password.
Surprised that you can save your own password directly onto :password_digest and it would work when authenticating. I'd think it would take the password provided by the user, hash it, and then compare the hash to :password_digest (which couldn't be their password).
This is what I do, which may solve the issue:
before_create :set_temporary_password
def set_temporary_password
self.temporary_password = SecureRandom.hex(5)
end
Send the user self.temporary_password, and when they update it, change temporary_password to nil. Then you can know when a user has a temporary password that requires changing.
I've got a User model that is utilizing mongoid. The model has a password, password_confirmation and encrypted_password field. The password and password_confirmation fields are populated at runtime with the value the user would type on the screen when creating a new user. When I persist, I don't want to persist the unencrypted password values, I only want to persist the value contained in encrypted_password. Is this possible? Is there something I can use to denote certain fields as not being persistable?
Thanks in advance
Chris
Here's a way:
Model only needs the password field and use a before_filter:
def User
before_save :hash_password
attr_accessible :password, :password_confirmation
def hash_password
#todo: improve by adding a salt
self.password = Digest::SHA1.hexdigest(self.password)
end
end
Notes:
Passwords should be stored using a one-way hash, and so passwords should not be 'decryptable'
Use a salt (a random value) and add that to the password before passing it to the hexdigest(). Store the salt in the database as well - say a column called password_salt.
password_confirmation is a virtual attribute and does not need to be defined in the model (rails will manage the details internally)