There are many ways of generating a signed link for
implementing things like invitation email, unsubscribe link
or password reset feature. You could add a token
field on the
model, use JWT tokens. But in the upcoming Rails versions, the
functionality to
generate tamper-proof and verifiable ids
will be built into rails.
# user = User.find(1)
# signed_user_id = user.signed_id
# User.find_signed signed_user_id
=> [user record]
# User.find_signed invalid_data
=> ActiveSupport::MessageVerifier::InvalidSignature
The secret to encode and decode messages is auto generated using
ActiveSupport::KeyGenerator
. You can also provide your own secret key
by setting signed_id_verifier_secret
on ActiveRecord::Base
inside of
an initializer.
The signed ids could also be configured to expire. There is also support for generating ids with specific purpose like password reset.
# user = User.find(1)
# signed_user_id = expires_in: 15.minutes, purpose: :password_reset
The signed ids are generated and verified using ActiveSupport::MessageVerifier which creates HMAC signarutes as Base64-encoded string.
The feature will be available when Rails 6.1 is released.
If you want to start using it right away, then
it can be implemented as a model concern using
ActiveSupport::MessageVerifier
module SignedIds
extend ActiveSupport::Concern
def signed_id
self.class.signed_id_verifier.generate id
end
private
class_methods do
def find_signed(signed_id)
if id = signed_id_verifier.verified(signed_id)
find(id)
end
end
def signed_id_verifier
ActiveSupport::MessageVerifier.new signed_id_verifier_secret digest: 'SHA256'
end
def signed_id_verifier_secret
@_signed_id_verifier_secret ||= Rails.application.config.signed_id_verifier_secret
end
end
end