require 'test_helper' class TokenAuthenticationTest < ActionDispatch::IntegrationTest test 'authenticate with valid authentication token key and value through params' do swap Devise, :token_authentication_key => :secret_token do sign_in_as_new_user_with_token assert_response :success 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 and value through params, when params with the same key as scope exist' do swap Devise, :token_authentication_key => :secret_token do user = create_user_with_authentication_token post exhibit_user_path(user), Devise.token_authentication_key => user.authentication_token, :user => { :some => "data" } assert_response :success assert_contain 'User is authenticated' 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, :skip_session_storage => [:token_auth] 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) assert_response :success assert_match 'user@test.com', response.body assert warden.authenticated?(:user) end end test 'does authenticate with valid authentication token key and value through params if not configured' do swap Devise, :token_authentication_key => :secret_token, :params_authenticatable => [:database] do sign_in_as_new_user_with_token assert_contain 'You need to sign in or sign up before continuing' assert_contain 'Sign in' assert_not warden.authenticated?(:user) end end test 'does authenticate with valid authentication token key and value through http if not configured' do swap Devise, :token_authentication_key => :secret_token, :http_authenticatable => [:database] do sign_in_as_new_user_with_token(:http_auth => true) assert_response 401 assert_contain 'Invalid email or password.' assert_not warden.authenticated?(:user) end end test 'does not authenticate with improper authentication token key' do swap Devise, :token_authentication_key => :donald_duck_token do sign_in_as_new_user_with_token(:auth_token_key => :secret_token) assert_equal new_user_session_path, @request.path assert_contain 'You need to sign in or sign up before continuing' assert_contain 'Sign in' assert_not warden.authenticated?(:user) end end test 'does not authenticate with improper authentication token value' do store_translations :en, :devise => {:failure => {:invalid_token => 'LOL, that was not a single character correct.'}} do sign_in_as_new_user_with_token(:auth_token => '*** INVALID TOKEN ***') assert_equal new_user_session_path, @request.path assert_contain 'LOL, that was not a single character correct.' assert_contain 'Sign in' assert_not warden.authenticated?(:user) end end test 'authenticate with valid authentication token key and do not store if stateless and timeoutable are enabled' do swap Devise, :token_authentication_key => :secret_token, :skip_session_storage => [:token_auth], :timeout_in => (0.1).second do user = sign_in_as_new_user_with_token assert warden.authenticated?(:user) # Expiring does not work because we are setting the session value when accessing it sleep 0.3 get_users_path_as_existing_user(user) assert warden.authenticated?(:user) end end test 'should reset token and not authenticate when expire_auth_token_on_timeout is set to true, timeoutable is enabled and we have a timed out session' do swap Devise, :token_authentication_key => :secret_token, :expire_auth_token_on_timeout => true, :timeout_in => (-1).minute do user = sign_in_as_new_user_with_token assert warden.authenticated?(:user) token = user.authentication_token get_users_path_as_existing_user(user) assert_not warden.authenticated?(:user) user.reload assert_not_equal token, user.authentication_token end end test 'should not be subject to injection' do swap Devise, :token_authentication_key => :secret_token do user1 = create_user_with_authentication_token() # Clean up user cache @user = nil user2 = create_user_with_authentication_token(:email => "another@test.com") user2.update_attribute(:authentication_token, "ANOTHERTOKEN") assert_not_equal user1, user2 visit users_path(Devise.token_authentication_key.to_s + '[$ne]' => user1.authentication_token) assert_nil warden.user(:user) end end private def sign_in_as_new_user_with_token(options = {}) user = options.delete(:user) || create_user_with_authentication_token(options) options[:auth_token_key] ||= Devise.token_authentication_key options[:auth_token] ||= user.authentication_token if options[:http_auth] header = "Basic #{Base64.encode64("#{VALID_AUTHENTICATION_TOKEN}:X")}" get users_path(:format => :xml), {}, "HTTP_AUTHORIZATION" => header else visit users_path(options[:auth_token_key].to_sym => options[:auth_token]) end user end def create_user_with_authentication_token(options={}) user = create_user(options) user.authentication_token = VALID_AUTHENTICATION_TOKEN user.save user end def get_users_path_as_existing_user(user) sign_in_as_new_user_with_token(:user => user) end end