class

ActiveSupport::MessageVerifier

v3.2.13 - Show latest stable - Superclass: Object

MessageVerifier makes it easy to generate and verify messages which are signed to prevent tampering.

This is useful for cases like remember-me tokens and auto-unsubscribe links where the session store isn’t suitable or available.

Remember Me:

cookies[:remember_me] = @verifier.generate([@user.id, 2.weeks.from_now])

In the authentication filter:

id, time = @verifier.verify(cookies[:remember_me])
if time < Time.now
  self.current_user = User.find(id)
end

By default it uses Marshal to serialize the message. If you want to use another serialization method, you can set the serializer attribute to something that responds to dump and load, e.g.:

@verifier.serializer = YAML

Files

  • activesupport/lib/active_support/message_verifier.rb

Nested classes and modules

3Notes

Wrong example

szeryf · Mar 29, 2010

In the authentication filter example above, the time condition should be reversed: we only want to find the user if +time+ is still in the future (because it's the valid-until time).

So the example should look like this:

id, time = @verifier.verify(cookies[:remember_me])
if time > Time.now
self.current_user = User.find(id)
end

Security issue

aamer · Aug 14, 2011

One thing to note about the code above is that it could have a security issue. If the user changes his/her password, the authentication token should expire. Hence, in a production scenario you should put in the password salt or something to allow the token to become invalidated.

Security

ksylvest · May 4, 2014

In regards to @aamer's comment on including the password salt this is a bad idea. ActiveSupport::MessageVerifier is NOT encrypted so:

verifier = ActiveSupport::MessageVerifier.new('secret')
id = 'id'
salt = 'salt'
verifier.generate("#{id}-#{salt}") # "BAhJIgxpZC1zYWx0BjoGRVQ=--c880254708d18ce4a686bcd96a25cf0d2117e1e0"

Base64.decode64(token.split("--").first) # "...id-salt..."

Note how the salt and id are both exposed! Instead a different token (reset_passowrd_token) should be used.