Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • Home
  • SEARCH
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 7740875
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 1, 20262026-06-01T08:53:19+00:00 2026-06-01T08:53:19+00:00

My client wants all user data encrypted, so I’ve created a before_save and after_find

  • 0

My client wants all user data encrypted, so I’ve created a before_save and after_find call back that will encrypt certain properties using Gibberish:

  # user.rb
  before_save UserEncryptor.new 
  after_find UserEncryptor.new

# user_encryptor.rb
class UserEncryptor
  def initialize
    @cipher = Gibberish::AES.new("password")
  end

  def before_save(user)
    user.first_name = encrypt(user.first_name)
    user.last_name = encrypt(user.last_name)
    user.email = encrypt(user.email) unless not user.confirmed? or user.unconfirmed_email
  end

  def after_find(user)
    user.first_name = decrypt(user.first_name)
    user.last_name = decrypt(user.last_name)
    user.email = decrypt(user.email) unless not user.confirmed? or user.unconfirmed_email
  end

  private
    def encrypt(value)
      @cipher.enc(value)
    end

    def decrypt(value)
      @cipher.dec(value)
    end
end

Well, when the user first signs up using Devise, the model looks about like it should. But then once the user confirms, if I inspect the user, the first_name and last_name properties look to have been encrypted multiple times. So I put a breakpoint in the before_save method and click the confirmation link, and I see that it’s getting executed three times in a row. The result is that the encrypted value gets encrypted again, and then again, so next time we retrieve the record, and every time thereafter, we get a twice encrypted value.

Now, why the heck is this happening? It’s not occurring for other non-devise models that are executing the same logic. Does Devise have the current_user cached in a few different places, and it saves the user in each location? How else could a before_save callback be called 3 times before the next before_find is executed?

And, more importantly, how can I successfully encrypt my user data when I’m using Devise? I’ve also had problems with attr_encrypted and devise_aes_encryptable so if I get a lot of those suggestions then I guess I have some more questions to post 🙂

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-01T08:53:20+00:00Added an answer on June 1, 2026 at 8:53 am

    I solved my problem with the help of a coworker.

    For encrypting the first and last name, it was sufficient to add a flag to the model indicating whether or not it’s been encrypted. That way, if multiple saves occur, the model knows it’s already encrypted and can skip that step:

      def before_update(user)
        unless user.encrypted
          user.first_name = encrypt(user.first_name)
          user.last_name = encrypt(user.last_name)
          user.encrypted = true
        end
      end 
    
      def after_find(user) 
        if user.encrypted
          user.first_name = decrypt(user.first_name)
          user.last_name = decrypt(user.last_name)
          user.encrypted = false
        end 
      end
    

    For the email address, this was not sufficient. Devise was doing some really weird stuff with resetting cached values, so the email address was still getting double encrypted. So instead of hooking into the callbacks to encrypt the email address, we overrode some methods on the user model:

      def email_before_type_cast
        super.present? ? AES.decrypt(super, KEY) : ""
      end 
    
      def email
        return "" unless self[:email]
        @email ||= AES.decrypt(self[:email], KEY)
      end
    
      def email=(provided_email)
        self[:email] = encrypted_email(provided_email)
        @email = provided_email
      end
    
      def self.find_for_authentication(conditions={})
        conditions[:email] = encrypted_email(conditions[:email])
        super
      end
    
      def self.find_or_initialize_with_errors(required_attributes, attributes, error=:invalid)
        attributes[:email] = encrypted_email(attributes[:email]) if attributes[:email]
        super
      end
    
      def self.encrypted_email decrypted_email
        AES.encrypt(decrypted_email, KEY, {:iv => IV})
      end
    

    This got us most of the way there. However, my Devise models are reconfirmable, so when I changed a user’s email address and tried to save, the reconfirmable module encountered something funky, the record got saved like a hundred times or so, and then I got a stack overflow and a rollback. We found that we needed to override one more method on the user model to do the trick:

      def email_was
        super.present? ? AES.decrypt(super, KEY) : ""
      end
    

    Now all of our personally identifiable information is encrypted! Yay!

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

A client wants to ensure that I cannot read sensitive data from their site,
A client wants to add functionality to a system that will distribute large files(~700mb)
I am designing an app that will keep track of all user's lat/long. For
My client wants me to make a plugin that intercepts the banner on a
I have a small app that a client uses to manually update some data.
I am working on a PHP project where the client wants multipage form data
I am writing a REST API for a service that will accept user contributed
I have client/server data passing all working correctly. Text, Images, etc. My users create
Let's assume I must store user's sensitive data, which was optionally encrypted on the
I want to make a P2P Chat client, all I want it to do

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.