Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create user failure with Rails 7.0 and encryption email #5436

Closed
devon opened this issue Dec 16, 2021 · 4 comments
Closed

Create user failure with Rails 7.0 and encryption email #5436

devon opened this issue Dec 16, 2021 · 4 comments

Comments

@devon
Copy link

devon commented Dec 16, 2021

Pre-check

class User < ApplicationRecord
  encrypts :email, deterministic: true, downcase: true

  devise :database_authenticatable, :registerable, :recoverable, :rememberable, :validatable
end

Environment

  • ruby 3.0.2p107
  • Rails 7.0.0
  • Devise master branch (commit 025b1c8)

Current behavior

Error when creating user

User.create(email: 'jack@example.com',  password: 'password', password_confirmation: 'password')
gems/ruby-3.0.2/gems/activerecord-7.0.0/lib/active_record/encryption/encryptor.rb:58:in `rescue in decrypt': ActiveRecord::Encryption::Errors::Decryption (ActiveRecord::Encryption::Errors::Decryption)
gems/ruby-3.0.2/gems/activerecord-7.0.0/lib/active_record/encryption/message_serializer.rb:26:in `rescue in load': ActiveRecord::Encryption::Errors::Encoding (ActiveRecord::Encryption::Errors::Encoding)
rubies/ruby-3.0.2/lib/ruby/3.0.0/json/common.rb:216:in `parse': 809: unexpected token at '' (JSON::ParserError)

Create user successfully if we remove devise from User model.

User.create!(email: 'jack@example.com')

Expected behavior

Create user successfully when encrypts email.

@robicode
Copy link

robicode commented Jan 6, 2022

I was having this issue as well, under Ruby 2.7.5 and 3.0.3, so I started a new application and set up authentication with the vanilla has_secure_password built into Rails. I basically used the same User model and migration provided by Devise but without the devise declarations. I then migrated the database and started a rails console. Surprise! Exact same error without Devise!

After a bit I found out that it was the null: false, default: "" options used on the email column that was the culprit. I removed those options, and now Devise seems to be working perfectly fine :)

@devon
Copy link
Author

devon commented Jan 17, 2022

I was having this issue as well, under Ruby 2.7.5 and 3.0.3, so I started a new application and set up authentication with the vanilla has_secure_password built into Rails. I basically used the same User model and migration provided by Devise but without the devise declarations. I then migrated the database and started a rails console. Surprise! Exact same error without Devise!

After a bit I found out that it was the null: false, default: "" options used on the email column that was the culprit. I removed those options, and now Devise seems to be working perfectly fine :)

Yes, you're right, it works when the email could be nil.

In active record 7.0.1, encrypted_attribute_type.rb, the code detect nil? value, not blank? value:

def decrypt(value)
  with_context do
    encryptor.decrypt(value, **decryption_options) unless value.nil?
  end
  ...
end

Another approach is setup support_unencrypted_data to true:

config.active_record.encryption.support_unencrypted_data = true

@giedriusr
Copy link
Contributor

Why devise has these options in the first place? Why it has null sounds obvious, but why it has default: ""?

@bpurinton
Copy link

Why devise has these options in the first place? Why it has null sounds obvious, but why it has default: ""?

@giedriusr I was wondering the same thing, here's how my colleague explained it, and now it makes sense to me:

Database constraints are more reliable than model validations in terms of keeping data integrity. I believe the idea is not that we expect, or even want, a blank email address, but rather we definitely don't want a nil email address. Yes, we can (and should) have validations to make sure that the email is present, but sometimes those can be skipped or maybe someone adds a callback to set the default email but the logic has a bug that sometimes allows nil values in. Constraints can notify people about those situations and uphold data integrity.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

4 participants