Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allowing http token auth to set the token_authentication_key if missing from params #2271

Merged
merged 6 commits into from Apr 14, 2013
4 changes: 4 additions & 0 deletions lib/devise.rb
Expand Up @@ -177,6 +177,10 @@ module Strategies
mattr_accessor :token_authentication_key
@@token_authentication_key = :auth_token

# Allow HTTP token authorization to set token_authentication_key
mattr_accessor :allow_authorization_to_set_auth_token
@@allow_authorization_to_set_auth_token = true

# Skip session storage for the following strategies
mattr_accessor :skip_session_storage
@@skip_session_storage = []
Expand Down
2 changes: 1 addition & 1 deletion lib/devise/models/token_authenticatable.rb
Expand Up @@ -82,7 +82,7 @@ def authentication_token
generate_token(:authentication_token)
end

Devise::Models.config(self, :token_authentication_key, :expire_auth_token_on_timeout)
Devise::Models.config(self, :token_authentication_key, :allow_authorization_to_set_auth_token, :expire_auth_token_on_timeout)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we call this configuration option something like allow_token_authenticatable_via_headers or something like it?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like that much better -- fixed!

end
end
end
Expand Down
21 changes: 17 additions & 4 deletions lib/devise/strategies/token_authenticatable.rb
Expand Up @@ -38,11 +38,24 @@ def remember_me?

# 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
auth_key = authentication_keys.first

return_params = \
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't need the \. :)

if params[scope].kind_of?(Hash) && params[scope].has_key?(auth_key)
params[scope]
else
params
end

if mapping.to.allow_authorization_to_set_auth_token
token = ActionController::HttpAuthentication::Token.token_and_options(request)

if token
return_params.merge! auth_key => token.first
end
end

return_params
end

# Overwrite authentication keys to use token_authentication_key.
Expand Down
29 changes: 29 additions & 0 deletions test/integration/token_authenticatable_test.rb
Expand Up @@ -129,6 +129,32 @@ class TokenAuthenticationTest < ActionDispatch::IntegrationTest
end
end

test 'authenticate with valid authentication token key and value through http header' do
swap Devise, :token_authentication_key => :secret_token do
sign_in_as_new_user_with_token(:token_auth => true)

assert_response :success
assert_match '<email>user@test.com</email>', response.body
assert warden.authenticated?(:user)
end
end

test 'authenticate with valid authentication token key and value through http header without allowing token authorization setting is denied' do
swap Devise, :token_authentication_key => :secret_token, :allow_authorization_to_set_auth_token => false do
sign_in_as_new_user_with_token(:token_auth => true)

assert_response :unauthorized
assert_nil warden.user(:user)
end
end

test 'does not authenticate with improper authentication token value in header' do
sign_in_as_new_user_with_token(:token_auth => true, :auth_token => '*** INVALID TOKEN ***')

assert_response :unauthorized
assert_nil warden.user(:user)
end

private

def sign_in_as_new_user_with_token(options = {})
Expand All @@ -140,6 +166,9 @@ def sign_in_as_new_user_with_token(options = {})
if options[:http_auth]
header = "Basic #{Base64.encode64("#{VALID_AUTHENTICATION_TOKEN}:X")}"
get users_path(:format => :xml), {}, "HTTP_AUTHORIZATION" => header
elsif options[:token_auth]
header = %{Token token="#{options[:auth_token]}"}
get users_path(:format => :xml), {}, "HTTP_AUTHORIZATION" => header
else
visit users_path(options[:auth_token_key].to_sym => options[:auth_token])
end
Expand Down