diff options
Diffstat (limited to 'activesupport/test/message_verifier_test.rb')
-rw-r--r-- | activesupport/test/message_verifier_test.rb | 121 |
1 files changed, 120 insertions, 1 deletions
diff --git a/activesupport/test/message_verifier_test.rb b/activesupport/test/message_verifier_test.rb index d6109c761d..05d5c1cbc3 100644 --- a/activesupport/test/message_verifier_test.rb +++ b/activesupport/test/message_verifier_test.rb @@ -1,7 +1,10 @@ +# frozen_string_literal: true + require "abstract_unit" require "openssl" require "active_support/time" require "active_support/json" +require_relative "metadata/shared_metadata_tests" class MessageVerifierTest < ActiveSupport::TestCase class JSONSerializer @@ -16,7 +19,8 @@ class MessageVerifierTest < ActiveSupport::TestCase def setup @verifier = ActiveSupport::MessageVerifier.new("Hey, I'm a secret!") - @data = { some: "data", now: Time.local(2010) } + @data = { some: "data", now: Time.utc(2010) } + @secret = SecureRandom.random_bytes(32) end def test_valid_message @@ -82,4 +86,119 @@ class MessageVerifierTest < ActiveSupport::TestCase end assert_equal "Secret should not be nil.", exception.message end + + def test_backward_compatibility_messages_signed_without_metadata + signed_message = "BAh7BzoJc29tZUkiCWRhdGEGOgZFVDoIbm93SXU6CVRpbWUNIIAbgAAAAAAHOgtvZmZzZXRpADoJem9uZUkiCFVUQwY7BkY=--d03c52c91dfe4ccc5159417c660461bcce005e96" + assert_equal @data, @verifier.verify(signed_message) + end + + def test_rotating_secret + old_message = ActiveSupport::MessageVerifier.new("old", digest: "SHA1").generate("old") + + verifier = ActiveSupport::MessageVerifier.new(@secret, digest: "SHA1") + verifier.rotate "old" + + assert_equal "old", verifier.verified(old_message) + end + + def test_multiple_rotations + old_message = ActiveSupport::MessageVerifier.new("old", digest: "SHA256").generate("old") + older_message = ActiveSupport::MessageVerifier.new("older", digest: "SHA1").generate("older") + + verifier = ActiveSupport::MessageVerifier.new(@secret, digest: "SHA512") + verifier.rotate "old", digest: "SHA256" + verifier.rotate "older", digest: "SHA1" + + assert_equal "new", verifier.verified(verifier.generate("new")) + assert_equal "old", verifier.verified(old_message) + assert_equal "older", verifier.verified(older_message) + end + + def test_on_rotation_is_called_and_verified_returns_message + older_message = ActiveSupport::MessageVerifier.new("older", digest: "SHA1").generate(encoded: "message") + + verifier = ActiveSupport::MessageVerifier.new(@secret, digest: "SHA512") + verifier.rotate "old", digest: "SHA256" + verifier.rotate "older", digest: "SHA1" + + rotated = false + message = verifier.verified(older_message, on_rotation: proc { rotated = true }) + + assert_equal({ encoded: "message" }, message) + assert rotated + end + + def test_rotations_with_metadata + old_message = ActiveSupport::MessageVerifier.new("old").generate("old", purpose: :rotation) + + verifier = ActiveSupport::MessageVerifier.new(@secret) + verifier.rotate "old" + + assert_equal "old", verifier.verified(old_message, purpose: :rotation) + end +end + +class MessageVerifierMetadataTest < ActiveSupport::TestCase + include SharedMessageMetadataTests + + setup do + @verifier = ActiveSupport::MessageVerifier.new("Hey, I'm a secret!", verifier_options) + end + + def test_verify_raises_when_purpose_differs + assert_raise(ActiveSupport::MessageVerifier::InvalidSignature) do + @verifier.verify(generate(data, purpose: "payment"), purpose: "shipping") + end + end + + def test_verify_raises_when_expired + signed_message = generate(data, expires_in: 1.month) + + travel 2.months + assert_raise(ActiveSupport::MessageVerifier::InvalidSignature) do + @verifier.verify(signed_message) + end + end + + private + def generate(message, **options) + @verifier.generate(message, options) + end + + def parse(message, **options) + @verifier.verified(message, options) + end + + def verifier_options + Hash.new + end +end + +class MessageVerifierMetadataMarshalTest < MessageVerifierMetadataTest + private + def verifier_options + { serializer: Marshal } + end +end + +class MessageVerifierMetadataJSONTest < MessageVerifierMetadataTest + private + def verifier_options + { serializer: MessageVerifierTest::JSONSerializer.new } + end +end + +class MessageEncryptorMetadataNullSerializerTest < MessageVerifierMetadataTest + private + def data + "string message" + end + + def null_serializing? + true + end + + def verifier_options + { serializer: ActiveSupport::MessageEncryptor::NullSerializer } + end end |