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.

Was it helpful?

Solution

  1. 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...
  2. 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)
  3. 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.

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top