Skip to content

Commit 241e125

Browse files
authored
Merge pull request rails#54310 from byroot/message-verifier-fallback
AS::MessageVerifier#verify always accept both safe and unsafe encoding
2 parents fb3dff3 + f643919 commit 241e125

File tree

2 files changed

+29
-0
lines changed

2 files changed

+29
-0
lines changed

activesupport/lib/active_support/message_verifier.rb

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,8 @@ class InvalidSignature < StandardError; end
154154
# not URL-safe. In other words, they can contain "+" and "/". If you want to
155155
# generate URL-safe strings (in compliance with "Base 64 Encoding with URL
156156
# and Filename Safe Alphabet" in RFC 4648), you can pass +true+.
157+
# Note that MessageVerifier will always accept both URL-safe and URL-unsafe
158+
# encoded messages, to allow a smooth transition between the two settings.
157159
#
158160
# [+:force_legacy_metadata_serializer+]
159161
# Whether to use the legacy metadata serializer, which serializes the
@@ -318,6 +320,13 @@ def inspect # :nodoc:
318320
end
319321

320322
private
323+
def decode(encoded, url_safe: @url_safe)
324+
catch :invalid_message_format do
325+
return super
326+
end
327+
super(encoded, url_safe: !url_safe)
328+
end
329+
321330
def sign_encoded(encoded)
322331
digest = generate_digest(encoded)
323332
encoded << SEPARATOR << digest

activesupport/test/message_verifier_test.rb

Lines changed: 20 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 "active_support/core_ext/securerandom"
78
require_relative "messages/message_codec_tests"
89

910
class MessageVerifierTest < ActiveSupport::TestCase
@@ -81,6 +82,25 @@ def test_verify_exception_on_invalid_message
8182
"Unable to assert that the message payload is unpadded, because it does not require padding"
8283
end
8384

85+
test "URL-safe and URL-unsafe can decode each other messages" do
86+
safe_verifier = ActiveSupport::MessageVerifier.new(@secret, url_safe: true, serializer: JSON)
87+
unsafe_verifier = ActiveSupport::MessageVerifier.new(@secret, url_safe: false, serializer: JSON)
88+
89+
data = "??"
90+
91+
assert_equal safe_verifier.generate(data), safe_verifier.generate(data)
92+
assert_not_equal safe_verifier.generate(data), unsafe_verifier.generate(data)
93+
94+
assert_equal data, unsafe_verifier.verify(safe_verifier.generate(data))
95+
assert_equal data, safe_verifier.verify(unsafe_verifier.generate(data))
96+
97+
50.times do
98+
data = SecureRandom.base58(Random.rand(10..50))
99+
assert_equal data, unsafe_verifier.verify(safe_verifier.generate(data))
100+
assert_equal data, safe_verifier.verify(unsafe_verifier.generate(data))
101+
end
102+
end
103+
84104
def test_alternative_serialization_method
85105
prev = ActiveSupport.use_standard_json_time_format
86106
ActiveSupport.use_standard_json_time_format = true

0 commit comments

Comments
 (0)