Skip to content

Commit 3bf3653

Browse files
committed
add metadata support to message verifier
1 parent 5c16dd3 commit 3bf3653

File tree

2 files changed

+48
-6
lines changed

2 files changed

+48
-6
lines changed

activesupport/lib/active_support/message_verifier.rb

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
require "base64"
44
require_relative "core_ext/object/blank"
55
require_relative "security_utils"
6+
require_relative "messages/metadata"
67

78
module ActiveSupport
89
# +MessageVerifier+ makes it easy to generate and verify messages which are
@@ -79,11 +80,11 @@ def valid_message?(signed_message)
7980
#
8081
# incompatible_message = "test--dad7b06c94abba8d46a15fafaef56c327665d5ff"
8182
# verifier.verified(incompatible_message) # => TypeError: incompatible marshal file format
82-
def verified(signed_message)
83+
def verified(signed_message, purpose: nil)
8384
if valid_message?(signed_message)
8485
begin
8586
data = signed_message.split("--".freeze)[0]
86-
@serializer.load(decode(data))
87+
Messages::Metadata.verify(@serializer.load(decode(data)), purpose)
8788
rescue ArgumentError => argument_error
8889
return if argument_error.message.include?("invalid base64")
8990
raise
@@ -103,8 +104,8 @@ def verified(signed_message)
103104
#
104105
# other_verifier = ActiveSupport::MessageVerifier.new 'd1ff3r3nt-s3Krit'
105106
# other_verifier.verify(signed_message) # => ActiveSupport::MessageVerifier::InvalidSignature
106-
def verify(signed_message)
107-
verified(signed_message) || raise(InvalidSignature)
107+
def verify(signed_message, purpose: nil)
108+
verified(signed_message, purpose: purpose) || raise(InvalidSignature)
108109
end
109110

110111
# Generates a signed message for the provided value.
@@ -114,8 +115,8 @@ def verify(signed_message)
114115
#
115116
# verifier = ActiveSupport::MessageVerifier.new 's3Krit'
116117
# verifier.generate 'a private message' # => "BAhJIhRwcml2YXRlLW1lc3NhZ2UGOgZFVA==--e2d724331ebdee96a10fb99b089508d1c72bd772"
117-
def generate(value)
118-
data = encode(@serializer.dump(value))
118+
def generate(value, expires_at: nil, expires_in: nil, purpose: nil)
119+
data = encode(@serializer.dump(Messages::Metadata.wrap(value, expires_at: expires_at, expires_in: expires_in, purpose: purpose)))
119120
"#{data}--#{generate_digest(data)}"
120121
end
121122

activesupport/test/message_verifier_test.rb

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
require "openssl"
55
require "active_support/time"
66
require "active_support/json"
7+
require_relative "metadata/shared_metadata_tests"
78

89
class MessageVerifierTest < ActiveSupport::TestCase
910
class JSONSerializer
@@ -84,4 +85,44 @@ def test_raise_error_when_secret_is_nil
8485
end
8586
assert_equal "Secret should not be nil.", exception.message
8687
end
88+
89+
def test_backward_compatibility_messages_signed_without_metadata
90+
signed_message = "BAh7BzoJc29tZUkiCWRhdGEGOgZFVDoIbm93SXU6CVRpbWUNIIAbgAAAAAAHOgtvZmZzZXRpADoJem9uZUkiCFVUQwY7BkY=--d03c52c91dfe4ccc5159417c660461bcce005e96"
91+
assert_equal @data, @verifier.verify(signed_message)
92+
end
93+
end
94+
95+
class MessageVerifierMetadataTest < ActiveSupport::TestCase
96+
include SharedMessageMetadataTests
97+
98+
setup do
99+
@verifier = ActiveSupport::MessageVerifier.new("Hey, I'm a secret!", verifier_options)
100+
end
101+
102+
private
103+
def generate(message, **options)
104+
@verifier.generate(message, options)
105+
end
106+
107+
def parse(message, **options)
108+
@verifier.verified(message, options)
109+
end
110+
111+
def verifier_options
112+
Hash.new
113+
end
114+
end
115+
116+
class MessageVerifierMetadataMarshalTest < MessageVerifierMetadataTest
117+
private
118+
def verifier_options
119+
{ serializer: Marshal }
120+
end
121+
end
122+
123+
class MessageVerifierMetadataJSONTest < MessageVerifierMetadataTest
124+
private
125+
def verifier_options
126+
{ serializer: MessageVerifierTest::JSONSerializer.new }
127+
end
87128
end

0 commit comments

Comments
 (0)