Files
fizzy/app/models/magic_link/code.rb
T
Stanko K.R. 7ab06d1dbd Use cryptographically secure randomness for Magic Link code generation
#sample uses PRNG under the hood which is pseudo random, which means that given enough magic link codes you can predict which code would come next. To fix that we have to switch to CSPRNG - SecureRandom.random_number - which isn't easy to predict based on previous results.
2025-12-03 20:15:27 +01:00

32 lines
813 B
Ruby

module MagicLink::Code
CODE_ALPHABET = "0123456789ABCDEFGHJKMNPQRSTVWXYZ".chars.freeze
CODE_SUBSTITUTIONS = { "O" => "0", "I" => "1", "L" => "1" }.freeze
class << self
def generate(length)
Array.new(length) { CODE_ALPHABET[SecureRandom.random_number(CODE_ALPHABET.length)] }.join
end
def sanitize(code)
return nil if code.blank?
normalize_code(code)
.then { apply_substitutions(_1) }
.then { remove_invalid_characters(_1) }
end
private
def normalize_code(code)
code.to_s.upcase
end
def apply_substitutions(code)
CODE_SUBSTITUTIONS.reduce(code) { |result, (from, to)| result.gsub(from, to) }
end
def remove_invalid_characters(code)
code.gsub(/[^#{CODE_ALPHABET.join}]/, "")
end
end
end