- Limiting your Ruby code from fetching some data from the DB hardly enhances security - chances are a hacker will get to your DB not through your ruby code, but by hacking straight to you database...
- If all that is saved in the database is an encrypted password and the salt (both of which you need to authenticate the user) - you should be fine, having both is not enough to know the user's password (at least not easily, assuming the encryption is strong enough)
- If you want to be extra careful, you can save the salt in a separate repository than the encrypted password repository. This way a hacker will have to break into both repositories to even start brute forcing your users' passwords.
Prevent fetching password attribute value for an instance of User object
-
20-07-2023 - |
Question
I have this in my :show
action of users_controller
.
def show
@user = User.find(params[:id])
end
But there are some columns in the users table that I wouldn't want accessed from the @user
instance variable.
There is the encrypted_password
column and the salt
column. What can i do on the model or the controller to ensure that @user
has no password
or salt
values.
I want when I do @user.password
or @user.salt
, it returns nil
or something that can't compromise a user's security.
Solution
OTHER TIPS
Don't store the password in the database in unencrypted format. Ever.
Hiding an attribute in an ActiveRecord model provides some basic information on how you could hide various attributes in the model class.
The best approach would be to serve a facade to your controller from some intermediate object, and the facace would basically only expose those fields that the controler needed to manipulate.
You can add an after_find callback in the model...
class User << ActiveRecord::Base
after_find :nil_secure_fields
def nil_secure_fields
password = nil
salt = nil
end
end
If the record is updated you'd want to ensure the password and salt attributes aren't included in the attributes to update.
For User
model add
class << self
def find_secure(id)
user = self.find(id)
user.secure_attributes!
user
end
end
def secure_attributes!
@attributes_secure = true
end
def secure_attributes?
!!@attributes_secure
end
def encrypted_password
secure_attributes? ? nil : super
end
def salt
secure_attributes? ? nil : super
end
Now you can use find_secure
method instead of find
which will restrict access to secure attributes.
PS This is not obviate the need to store passwords encrypted.