DEV: Hash tokens stored from email_tokens (#14493)

This commit adds token_hash and scopes columns to email_tokens table.
token_hash is a replacement for the token column to avoid storing email
tokens in plaintext as it can pose a security risk. The new scope column
ensures that email tokens cannot be used to perform a different action
than the one intended.

To sum up, this commit:

* Adds token_hash and scope to email_tokens

* Reuses code that schedules critical_user_email

* Refactors EmailToken.confirm and EmailToken.atomic_confirm methods

* Periodically cleans old, unconfirmed or expired email tokens
This commit is contained in:
Dan Ungureanu
2021-11-25 09:34:39 +02:00
committed by GitHub
parent 4c46c7e334
commit fa8cd629f1
34 changed files with 482 additions and 599 deletions
@@ -0,0 +1,29 @@
# frozen_string_literal: true
class AddTokenHashToEmailToken < ActiveRecord::Migration[6.1]
def up
add_column :email_tokens, :token_hash, :string
loop do
rows = DB
.query("SELECT id, token FROM email_tokens WHERE token_hash IS NULL LIMIT 500")
.map { |row| { id: row.id, token_hash: Digest::SHA256.hexdigest(row.token) } }
break if rows.size == 0
data_string = rows.map { |r| "(#{r[:id]}, '#{r[:token_hash]}')" }.join(",")
execute <<~SQL
UPDATE email_tokens
SET token_hash = data.token_hash
FROM (VALUES #{data_string}) AS data(id, token_hash)
WHERE email_tokens.id = data.id
SQL
end
change_column_null :email_tokens, :token_hash, false
end
def down
drop_column :email_tokens, :token_hash, :string
end
end
@@ -0,0 +1,11 @@
# frozen_string_literal: true
class AddScopeToEmailToken < ActiveRecord::Migration[6.1]
def up
add_column :email_tokens, :scope, :integer
end
def down
drop_column :email_tokens, :scope, :integer
end
end