module ActiveRecord::TokenFor::ClassMethods

def find_by_token_for(purpose, token)

+nil+ if the token is invalid or the record was not found.
Finds a record using a given +token+ for a predefined +purpose+. Returns
def find_by_token_for(purpose, token)
  raise UnknownPrimaryKey.new(self) unless primary_key
  token_definitions.fetch(purpose).resolve_token(token) { |id| find_by(primary_key => id) }
end

def find_by_token_for!(purpose, token)

the token is valid but the record was not found.
(e.g. expired, bad format, etc). Raises ActiveRecord::RecordNotFound if
ActiveSupport::MessageVerifier::InvalidSignature if the token is invalid
Finds a record using a given +token+ for a predefined +purpose+. Raises
def find_by_token_for!(purpose, token)
  token_definitions.fetch(purpose).resolve_token(token) { |id| find(id) } ||
    (raise ActiveSupport::MessageVerifier::InvalidSignature)
end

def generates_token_for(purpose, expires_in: nil, &block)

User.find_by_token_for(:password_reset, token) # => nil
user.update!(password: "new password")
User.find_by_token_for(:password_reset, token) # => user
token = user.generate_token_for(:password_reset)

User.find_by_token_for(:password_reset, token) # => nil
# 16 minutes later...
User.find_by_token_for(:password_reset, token) # => user
token = user.generate_token_for(:password_reset)

user = User.first

end
end
password_salt&.last(10)
# Last 10 characters of password salt, which changes when password is updated:
generates_token_for :password_reset, expires_in: 15.minutes do

has_secure_password
class User < ActiveRecord::Base

==== Examples

human-readable plaintext JSON.
information because it will be embedded in the token as
that the value returned by the block should not contain sensitive
JSON values do not match, the token will be treated as invalid. Note
will be evaluated again in the context of the fetched record. If the two
JSON. Later, when fetching the record with #find_by_token_for, the block
of the record, and its return value will be embedded in the token as
TokenFor#generate_token_for, the block will be evaluated in the context
A block may also be specified. When generating a token with

will automatically invalidate previously generated tokens.
part of the token's signature, so changing the value of +expires_in+
specifying a duration via the +expires_in+ option. The duration becomes
By default, tokens do not expire. They can be configured to expire by

exposed to outside world as, for example, password reset tokens.
Tokens are signed so that they are tamper-proof. Thus they can be

(or #find_by_token_for!) with the same purpose and token.
record. Later, that record can be fetched by calling #find_by_token_for
A token can be generated by calling TokenFor#generate_token_for on a
Defines the behavior of tokens generated for a specific +purpose+.
def generates_token_for(purpose, expires_in: nil, &block)
  self.token_definitions = token_definitions.merge(purpose => TokenDefinition.new(self, purpose, expires_in, block))
end