diff --git a/CHANGELOG.rdoc b/CHANGELOG.rdoc index 4d2bf445..79d12f59 100644 --- a/CHANGELOG.rdoc +++ b/CHANGELOG.rdoc @@ -12,6 +12,7 @@ * Extracted encryptors into :encryptable for better bcrypt support * :rememberable is now able to use salt as token if no remember_token is provided * Store the salt in session and expire the session if the user changes his password + * Allow :stateless_token to be set to true avoiding users to be stored in session through token authentication * bugfix * after_sign_in_path_for always receives a resource diff --git a/lib/devise.rb b/lib/devise.rb index 6402b7c2..2cde4402 100644 --- a/lib/devise.rb +++ b/lib/devise.rb @@ -164,6 +164,10 @@ module Devise mattr_accessor :token_authentication_key @@token_authentication_key = :auth_token + # If true, authentication through token does not store user in session + mattr_accessor :stateless_token + @@stateless_token = false + # Which formats should be treated as navigational. mattr_accessor :navigational_formats @@navigational_formats = [:html] diff --git a/lib/devise/models/token_authenticatable.rb b/lib/devise/models/token_authenticatable.rb index 075f95ed..42150b14 100644 --- a/lib/devise/models/token_authenticatable.rb +++ b/lib/devise/models/token_authenticatable.rb @@ -5,8 +5,18 @@ module Devise # The TokenAuthenticatable module is responsible for generating an authentication token and # validating the authenticity of the same while signing in. # - # This module only provides a few helpers to help you manage the token. Creating and resetting - # the token is your responsibility. + # This module only provides a few helpers to help you manage the token, but it is up to you + # to choose how to use it. For example, if you want to have a new token every time the user + # saves his account, you can do the following: + # + # before_save :reset_authentication_token + # + # On the other hand, if you want to generate token unless one exists, you should use instead: + # + # before_save :ensure_authentication_token + # + # If you want to delete the token after it is used, you can do so in the + # after_token_authentication callback. # # == Options # @@ -14,6 +24,9 @@ module Devise # # * +token_authentication_key+: Defines name of the authentication token params key. E.g. /users/sign_in?some_key=... # + # * +stateless_token+: By default, when you sign up with a token, Devise will store the user in session + # as any other authentication strategy. You can set stateless_token to true to avoid this. + # module TokenAuthenticatable extend ActiveSupport::Concern @@ -52,7 +65,7 @@ module Devise generate_token(:authentication_token) end - ::Devise::Models.config(self, :token_authentication_key) + ::Devise::Models.config(self, :token_authentication_key, :stateless_token) end end end diff --git a/lib/devise/strategies/token_authenticatable.rb b/lib/devise/strategies/token_authenticatable.rb index 631c39d4..122efb39 100644 --- a/lib/devise/strategies/token_authenticatable.rb +++ b/lib/devise/strategies/token_authenticatable.rb @@ -10,6 +10,10 @@ module Devise # For HTTP, you can pass 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. class TokenAuthenticatable < Authenticatable + def store? + !mapping.to.stateless_token + end + def authenticate! resource = mapping.to.find_for_token_authentication(authentication_hash) diff --git a/lib/generators/templates/devise.rb b/lib/generators/templates/devise.rb index fed313c0..710558a4 100644 --- a/lib/generators/templates/devise.rb +++ b/lib/generators/templates/devise.rb @@ -118,6 +118,10 @@ Devise.setup do |config| # Defines name of the authentication token params key # config.token_authentication_key = :auth_token + # If true, authentication through token does not store user in session and needs + # to be supplied on each request. Useful if you are using the token as API token. + # config.stateless_token = false + # ==> Scopes configuration # Turn scoped views on. Before rendering "sessions/new", it will first check for # "users/sessions/new". It's turned off by default because it's slower if you diff --git a/test/integration/token_authenticatable_test.rb b/test/integration/token_authenticatable_test.rb index 16a2a707..fd369531 100644 --- a/test/integration/token_authenticatable_test.rb +++ b/test/integration/token_authenticatable_test.rb @@ -7,12 +7,23 @@ class TokenAuthenticationTest < ActionController::IntegrationTest sign_in_as_new_user_with_token assert_response :success - assert_template 'users/index' + assert_current_url "/users?secret_token=#{VALID_AUTHENTICATION_TOKEN}" assert_contain 'Welcome' assert warden.authenticated?(:user) end end + test 'authenticate with valid authentication token key but does not store if stateless' do + swap Devise, :token_authentication_key => :secret_token, :stateless_token => true do + sign_in_as_new_user_with_token + assert warden.authenticated?(:user) + + get users_path + assert_redirected_to new_user_session_path + assert_not warden.authenticated?(:user) + end + end + test 'authenticate with valid authentication token key and value through http' do swap Devise, :token_authentication_key => :secret_token do sign_in_as_new_user_with_token(:http_auth => true)