-
Notifications
You must be signed in to change notification settings - Fork 21.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add ActiveSupport::MessageVerifier#expired?
#48820
Conversation
f41df29
to
077ff0a
Compare
077ff0a
to
5deb67c
Compare
5deb67c
to
8de3db4
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
With the current implementation in this PR, writing something like
if verifier.expired?(message)
# ...
else
data = verifier.verify(message)
end
will decode and verify the message twice (i.e. double the work).
I think avoiding that would require a deeper implementation of expired?
.
Furthermore, MessageVerifier#expired?
suggests we should also have MessageEncryptor#expired?
, and there is no way MessageEncryptor#expired?
could avoid (double) decrypting the message.
Reading rails/globalid#141, it seems like the user doesn't actually require expired?
; they just need a way to determine whether a nil
result is due to expiration vs a missing record. There are a few ways I think we could accommodate that in the MessageVerifier
(and MessageEncryptor
) API.
One way would be to make verified
(and decrypt_and_verify
) accept a block:
verifier.verified(valid_message) do |data|
"is valid"
end
# => "is valid"
verifier.verified(invalid_message) do |data|
raise "never reached"
end
# => nil
Though even that may not be necessary... Unlike arbitrary data, the signed value of an SGID should never be
|
If |
Why would you want to? An expired message can be from a malicious actor reusing old messages just as much as a message with a mismatched purpose. |
Here's an example of why: rails/globalid#141 (comment)
|
That will not be possible with |
Seems like the proper way would be a more finely grained API that start an object representing the message that you can then query:
etc. |
I agree that is the way to go if we want to expose message = verifier.generate("data", expires_at: 1.day.from_now)
data = verifier.verified(message)
if data.nil?
# Show generic error
end You would write: message = verifier.generate(["data", 1.day.from_now])
data, expiration = verifier.verified(message)
if expiration&.past?
# Show expiration
end (Though you may need to write |
Yeah, I guess your suggestion is simpler. |
Motivation / Background
I'd like to add support for rails/globalid#141. As noted in that issue, the
expired?
method needs to be added to Active Support first. This PR adds it.Detail