Skip to content

Instantly share code, notes, and snippets.

@robhurring
Last active January 30, 2020 19:00
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save robhurring/4746675 to your computer and use it in GitHub Desktop.
Save robhurring/4746675 to your computer and use it in GitHub Desktop.
Override devise's TokenAuthenticatable strategy to use Authorization headers

This will allow you to use devise's TokenAuthenticatable strategy while passing your :auth_token in using HTTP Authorization headers instead of params.

You can check it out using

curl -H "Authorization: Token token=XXXXXX, option=1" -vv http://railsapp.dev/api/v1/endpoint.json

It should properly authenticate using the token as well as set request.env['token.options'] to {"options" => "1"}.

# File: lib/devise/strategies/api_authenticatable.rb
require 'devise/strategies/token_authenticatable'
module Devise
module Strategies
class ApiAuthenticatable < TokenAuthenticatable
private
# Try to rip out authorization and override our authentication_key
def params_auth_hash
return_params = super
token_key = mapping.to.token_authentication_key
token = ActionController::HttpAuthentication::Token
.token_and_options(request)
if token
return_params.merge! token_key => token.first
request.env['token.options'] = token.last || {}
end
return_params
end
end
end
end
Warden::Strategies.add(
:api_authenticatable,
Devise::Strategies::ApiAuthenticatable
)
# File: config/initializers/devise.rb
require 'devise/strategies/api_authenticatable'
Devise.setup do |config|
# ...
config.warden do |manager|
manager.default_strategies(:scope => :user).unshift :api_authenticatable
end
# ...
end
describe 'authenticating with Authorization header' do
let(:token_key){ Devise.token_authentication_key }
let!(:user){ create :user }
let(:token){ user.authentication_token }
controller(described_class) do
def index
head :ok
end
end
before do
request.env['HTTP_AUTHORIZATION'] =
ActionController::HttpAuthentication::Token.encode_credentials(
token, {hello: 'world'})
end
it 'sets env[token.options]' do
json_get :index
request.env['token.options'] == {'hello' => 'world'}
end
context 'when auth_token param is missing' do
it 'sets the auth token from Authorization header' do
json_get :index
controller.params[token_key].should eq token
response.should be_success
end
end
context 'when auth_token param is present' do
it 'it overrides the param' do
json_get :index, auth_token: 'bad token'
controller.params[token_key].should eq token
response.should be_success
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment