lib/devise/token_authenticatable/strategy.rb
require 'devise/strategies/base'
module Devise
module Strategies
#
# The +TokenAuthenticatable+ strategy was extracted from Devise 3.1.0. Its purpose is
# to provide the deprecated functionality of the +TokenAuthenticatable+ strategy. The
# following description was adapted accordingly.
#
# See: https://github.com/plataformatec/devise/blob/v3.1/lib/devise/strategies/token_authenticatable.rb
#
#
# Strategy for signing in a user, based on a authenticatable token. This works for both params
# and http. For the former, all you need to do is to pass the params in the URL:
#
# http://myapp.example.com/?user_token=SECRET
#
# For headers, you can use basic authentication passing the token as username and
# blank password. Since some clients may require a password, you can pass "X" as
# password and it will simply be ignored.
#
# You may also pass the token using the Token authentication mechanism provided
# by Rails: http://api.rubyonrails.org/classes/ActionController/HttpAuthentication/Token.html
# The token options are stored in request.env['devise.token_options']
#
class TokenAuthenticatable < Authenticatable
def store?
super && !mapping.to.skip_session_storage.include?(:token_auth)
end
def valid?
super || valid_for_token_auth?
end
def authenticate!
resource = mapping.to.find_for_token_authentication(authentication_hash)
return fail(:invalid_token) unless resource
unless token_expires_in.blank?
if Time.now > (resource.authentication_token_created_at + token_expires_in.to_i)
return fail(:expired_token)
end
end
if validate(resource)
resource.after_token_authentication
success!(resource)
end
end
private
# Token Authenticatable can be authenticated with params in any controller and any verb.
def valid_params_request?
true
end
# Check if the model accepts this strategy as token authenticatable.
def token_authenticatable?
mapping.to.http_authenticatable?(:token)
end
# Check if this is strategy is valid for token authentication by:
#
# * Validating if the model allows http token authentication;
# * If the http auth token exists;
# * If all authentication keys are present;
#
def valid_for_token_auth?
token_authenticatable? && auth_token.present? && with_authentication_hash(:token_auth, token_auth_hash)
end
# Extract the auth token from the request
def auth_token
@auth_token ||= ActionController::HttpAuthentication::Token.token_and_options(request)
end
# Extract a hash with attributes:values from the auth_token
def token_auth_hash
request.env['devise.token_options'] = auth_token.last
{ authentication_keys.first => auth_token.first }
end
# Try both scoped and non scoped keys
def params_auth_hash
if params[scope].kind_of?(Hash) && params[scope].has_key?(authentication_keys.first)
params[scope]
else
params
end
end
# Overwrite authentication keys to use token_authentication_key.
def authentication_keys
@authentication_keys ||= [Devise::TokenAuthenticatable.token_authentication_key]
end
def token_expires_in
@token_expires_in ||= Devise::TokenAuthenticatable.token_expires_in
end
end
end
end
Warden::Strategies.add(:token_authenticatable, Devise::Strategies::TokenAuthenticatable)