mirror of
https://github.com/heartcombo/devise.git
synced 2022-11-09 12:18:31 -05:00
Tidy up token authentication implementation.
This commit is contained in:
parent
4878bdb60b
commit
3781a0f47b
8 changed files with 64 additions and 50 deletions
|
@ -1,3 +1,7 @@
|
|||
* enhancements
|
||||
* Added gemspec to repo
|
||||
* Added token authenticatable (by github.com/grimen)
|
||||
|
||||
== 0.9.1
|
||||
|
||||
* bug fix
|
||||
|
|
|
@ -18,7 +18,7 @@ class SessionsController < ApplicationController
|
|||
set_flash_message :notice, :signed_in
|
||||
sign_in_and_redirect(resource_name, resource, true)
|
||||
else
|
||||
set_now_flash_message :alert, warden.message || :invalid
|
||||
set_now_flash_message :alert, (warden.message || :invalid)
|
||||
build_resource
|
||||
render_with_scope :new
|
||||
end
|
||||
|
|
|
@ -53,6 +53,10 @@ Devise.setup do |config|
|
|||
# Time interval to unlock the account if :time is enabled as unlock_strategy.
|
||||
# config.unlock_in = 1.hour
|
||||
|
||||
# ==> Configuration for :token_authenticatable
|
||||
# Defines name of the authentication token params key
|
||||
# config.token_authentication_key = :auth_token
|
||||
|
||||
# ==> General configuration
|
||||
# Load and configure the ORM. Supports :active_record (default), :mongo_mapper
|
||||
# (requires mongo_ext installed) and :data_mapper (experimental).
|
||||
|
|
|
@ -133,8 +133,8 @@ module Devise
|
|||
@@mailer_sender
|
||||
|
||||
# Authentication token params key name of choice. E.g. /users/sign_in?some_key=...
|
||||
mattr_accessor :authentication_token_param_key
|
||||
@@authentication_token_param_key = :auth_token
|
||||
mattr_accessor :token_authentication_key
|
||||
@@token_authentication_key = :auth_token
|
||||
|
||||
class << self
|
||||
# Default way to setup Devise. Run script/generate devise_install to create
|
||||
|
|
|
@ -10,9 +10,7 @@ module Devise
|
|||
# You can overwrite configuration values by setting in globally in Devise (+Devise.setup+),
|
||||
# using devise method, or overwriting the respective instance method.
|
||||
#
|
||||
# +authentication_token_param_key+ - Defines name of the authentication token params key. E.g. /users/sign_in?some_key=...
|
||||
#
|
||||
# +reset_authentication_token_on+ - Defines which callback hooks that should trigger a authentication token reset.
|
||||
# +token_authentication_key+ - Defines name of the authentication token params key. E.g. /users/sign_in?some_key=...
|
||||
#
|
||||
# == Examples:
|
||||
#
|
||||
|
@ -23,20 +21,29 @@ module Devise
|
|||
def self.included(base)
|
||||
base.class_eval do
|
||||
extend ClassMethods
|
||||
|
||||
before_save :ensure_authentication_token!
|
||||
before_save :ensure_authentication_token
|
||||
end
|
||||
end
|
||||
|
||||
# Generate authentication token unless already exists.
|
||||
def ensure_authentication_token!
|
||||
self.reset_authentication_token!(false) if self.authentication_token.blank?
|
||||
# Generate new authentication token (a.k.a. "single access token").
|
||||
def reset_authentication_token
|
||||
self.authentication_token = self.class.authentication_token
|
||||
end
|
||||
|
||||
# Generate new authentication token (a.k.a. "single access token").
|
||||
def reset_authentication_token!(do_save = true)
|
||||
self.authentication_token = self.class.authentication_token
|
||||
self.save if do_save
|
||||
# Generate new authentication token and save the record.
|
||||
def reset_authentication_token!
|
||||
reset_authentication_token
|
||||
self.save
|
||||
end
|
||||
|
||||
# Generate authentication token unless already exists.
|
||||
def ensure_authentication_token
|
||||
self.reset_authentication_token if self.authentication_token.blank?
|
||||
end
|
||||
|
||||
# Generate authentication token unless already exists and save the record.
|
||||
def ensure_authentication_token!
|
||||
self.reset_authentication_token! if self.authentication_token.blank?
|
||||
end
|
||||
|
||||
# Verifies whether an +incoming_authentication_token+ (i.e. from single access URL)
|
||||
|
@ -46,12 +53,11 @@ module Devise
|
|||
end
|
||||
|
||||
module ClassMethods
|
||||
|
||||
::Devise::Models.config(self, :authentication_token_param_key)
|
||||
::Devise::Models.config(self, :token_authentication_key)
|
||||
|
||||
# Authenticate a user based on authentication token.
|
||||
def authenticate_with_token(attributes = {})
|
||||
token = attributes[::Devise.authentication_token_param_key]
|
||||
def authenticate_with_token(attributes)
|
||||
token = attributes[self.token_authentication_key]
|
||||
resource = self.find_for_token_authentication(token)
|
||||
resource if resource.try(:valid_authentication_token?, token)
|
||||
end
|
||||
|
@ -73,8 +79,8 @@ module Devise
|
|||
# self.find_by_authentication_token(token, :conditions => conditions)
|
||||
# end
|
||||
#
|
||||
def find_for_token_authentication(token, conditions = {})
|
||||
self.find_by_authentication_token(token, :conditions => conditions)
|
||||
def find_for_token_authentication(token)
|
||||
self.find(:first, :conditions => { :authentication_token => token})
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -25,9 +25,9 @@ module Devise
|
|||
# Detect authentication token in params: scoped or not.
|
||||
def authentication_token(scope)
|
||||
if params[scope]
|
||||
params[scope][::Devise.authentication_token_param_key]
|
||||
params[scope][mapping.to.token_authentication_key]
|
||||
else
|
||||
params[::Devise.authentication_token_param_key]
|
||||
params[mapping.to.token_authentication_key]
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -3,8 +3,8 @@ require 'test/test_helper'
|
|||
class TokenAuthenticationTest < ActionController::IntegrationTest
|
||||
|
||||
test 'sign in user should authenticate with valid authentication token and proper authentication token key' do
|
||||
swap Devise, :authentication_token_param_key => :secret_token do
|
||||
sign_in_as_new_user_with_token(:auth_token_key => :secret_token, :auth_token => VALID_AUTHENTICATION_TOKEN)
|
||||
swap Devise, :token_authentication_key => :secret_token do
|
||||
sign_in_as_new_user_with_token(:auth_token_key => :secret_token)
|
||||
|
||||
assert_response :success
|
||||
assert_template 'users/index'
|
||||
|
@ -14,30 +14,22 @@ class TokenAuthenticationTest < ActionController::IntegrationTest
|
|||
end
|
||||
|
||||
test 'user signing in with valid authentication token - but improper authentication token key - return to sign in form with error message' do
|
||||
# FIXME: For some reason I18n value is not respected. Always render defalt one. =S
|
||||
# store_translations :en, :devise => {:sessions => {:unauthenticated => 'Ouch!'}} do
|
||||
# assert 'Ouch!', I18n.t('devise.sessions.unauthenticated') # for paranoia
|
||||
swap Devise, :token_authentication_key => :donald_duck_token do
|
||||
sign_in_as_new_user_with_token(:auth_token_key => :secret_token)
|
||||
assert_redirected_to new_user_session_path(:unauthenticated => true)
|
||||
follow_redirect!
|
||||
|
||||
swap Devise, :authentication_token_param_key => :donald_duck_token do
|
||||
sign_in_as_new_user_with_token(:auth_token_key => :secret_token, :auth_token => VALID_AUTHENTICATION_TOKEN)
|
||||
|
||||
assert_redirected_to new_user_session_path(:unauthenticated => true)
|
||||
follow_redirect!
|
||||
|
||||
# assert_contain 'Ouch!'
|
||||
assert_contain 'Sign in'
|
||||
assert_not warden.authenticated?(:user)
|
||||
end
|
||||
# end
|
||||
assert_contain 'You need to sign in or sign up before continuing'
|
||||
assert_contain 'Sign in'
|
||||
assert_not warden.authenticated?(:user)
|
||||
end
|
||||
end
|
||||
|
||||
test 'user signing in with invalid authentication token should return to sign in form with error message' do
|
||||
store_translations :en, :devise => {:sessions => {:invalid_token => 'LOL, that was not a single character correct.'}} do
|
||||
sign_in_as_new_user_with_token(:auth_token => '*** INVALID TOKEN ***')
|
||||
|
||||
assert_redirected_to new_user_session_path(:invalid_token => true)
|
||||
follow_redirect!
|
||||
assert_equal users_path(Devise.authentication_token_param_key => '*** INVALID TOKEN ***'), session[:"user.return_to"]
|
||||
|
||||
assert_response :success
|
||||
assert_contain 'LOL, that was not a single character correct.'
|
||||
|
@ -49,12 +41,14 @@ class TokenAuthenticationTest < ActionController::IntegrationTest
|
|||
private
|
||||
|
||||
def sign_in_as_new_user_with_token(options = {}, &block)
|
||||
options[:auth_token_key] ||= Devise.authentication_token_param_key
|
||||
options[:auth_token_key] ||= Devise.token_authentication_key
|
||||
options[:auth_token] ||= VALID_AUTHENTICATION_TOKEN
|
||||
|
||||
user = create_user(options)
|
||||
user.authentication_token = VALID_AUTHENTICATION_TOKEN
|
||||
user.save
|
||||
visit users_path(options[:auth_token_key].to_sym => (options[:auth_token] || VALID_AUTHENTICATION_TOKEN))
|
||||
yield if block_given?
|
||||
|
||||
visit users_path(options[:auth_token_key].to_sym => options[:auth_token])
|
||||
user
|
||||
end
|
||||
|
||||
|
|
|
@ -11,14 +11,20 @@ class TokenAuthenticatableTest < ActiveSupport::TestCase
|
|||
|
||||
test 'should reset authentication token' do
|
||||
user = new_user
|
||||
|
||||
user.reset_authentication_token!(false)
|
||||
user.reset_authentication_token
|
||||
previous_token = user.authentication_token
|
||||
|
||||
user.reset_authentication_token!(false)
|
||||
user.reset_authentication_token
|
||||
assert_not_equal previous_token, user.authentication_token
|
||||
end
|
||||
|
||||
test 'should ensure authentication token' do
|
||||
user = new_user
|
||||
user.ensure_authentication_token
|
||||
previous_token = user.authentication_token
|
||||
user.ensure_authentication_token
|
||||
assert_equal previous_token, user.authentication_token
|
||||
end
|
||||
|
||||
test 'should test for a valid authentication token' do
|
||||
User.expects(:authentication_token).returns(VALID_AUTHENTICATION_TOKEN)
|
||||
user = create_user
|
||||
|
@ -29,7 +35,7 @@ class TokenAuthenticatableTest < ActiveSupport::TestCase
|
|||
test 'should authenticate a valid user with authentication token and return it' do
|
||||
User.expects(:authentication_token).returns(VALID_AUTHENTICATION_TOKEN)
|
||||
user = create_user
|
||||
User.any_instance.stubs(:confirmed?).returns(true)
|
||||
user.confirm!
|
||||
authenticated_user = User.authenticate_with_token(:auth_token => user.authentication_token)
|
||||
assert_equal authenticated_user, user
|
||||
end
|
||||
|
@ -37,7 +43,7 @@ class TokenAuthenticatableTest < ActiveSupport::TestCase
|
|||
test 'should return nil when authenticating an invalid user by authentication token' do
|
||||
User.expects(:authentication_token).returns(VALID_AUTHENTICATION_TOKEN)
|
||||
user = create_user
|
||||
User.any_instance.stubs(:confirmed?).returns(true)
|
||||
user.confirm!
|
||||
authenticated_user = User.authenticate_with_token(:auth_token => user.authentication_token.reverse)
|
||||
assert_nil authenticated_user
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue