24

I need to use token based authentication in a Rails 3.1 API in conjunction with the most recent version of devise. No problem so far.

Now I do not want to append my :auth_token to the POST/PUT parameters on client side but send this token as a request header like HTTP_X_MYAPP_AUTH_TOKEN".

Can I convince devise from using that rather than a token from parameters? Is it possible to implement both, so that my API users can send the token via request header OR POST/PUT parameter?

Regards. Felix

GeorgieF
  • 2,687
  • 5
  • 29
  • 43

4 Answers4

38

I had the same need and came up with this solution:

class YourController < ApplicationController
  prepend_before_filter :get_api_key
  before_filter :authenticate_user!

  private
  def get_api_key
    if api_key = params[:api_key].blank? && request.headers["X-API-KEY"]
      params[:api_key] = api_key
    end
  end
end

Note I have my devise Devise.token_authentication_key set to api_key.

config.token_authentication_key = :api_key
Chris Conley
  • 1,062
  • 10
  • 13
  • Hey Chris, nice Solution, like that. I created my own patch for devise meanwhile, works too. Your Solutions seems to be a nice fit for everyone coming accross the same problem in the future. – GeorgieF Sep 29 '11 at 09:17
  • 2
    Hmm doesn't work for me :-/ ```get_api_key``` is correctly executed before ```authenticate_user!``` but sadly by this time Warden Rack middleware has already parsed params on its own and has own copy of params that won't notice added :api_key item. – Wojtek Kruszewski Jan 09 '13 at 07:03
  • 1
    Nice idea, but I think I'm having the same problem as @WojtekKruszewski – elsurudo Jan 27 '13 at 14:26
  • Same thing here. Was anybody able to have this working with the latest Devise? – Sakin May 03 '13 at 20:50
  • Same problem! The parameter isn't added as it should. – rikas May 27 '13 at 17:25
  • 1
    Same issue here, anyone with a good solution? (Rails 4, devise 3) – Ethan Mick Aug 11 '13 at 21:12
4

I'm using a custom "strategy" for this: https://gist.github.com/4492569

Wojtek Kruszewski
  • 13,940
  • 6
  • 38
  • 38
3

It is possible in Devise to pass a standard authentication token through query string or the header for HTTP Basic Authentication, see here. The Ruby code from the specs to pass token in the HTTP_Authorization header is

header = "Basic #{Base64.encode64("#{VALID_AUTHENTICATION_TOKEN}:X")}"
get users_path(:format => :xml), {}, "HTTP_AUTHORIZATION" => header

Testing from the command line with curl would go like this:

echo  "HUGP59gXsd7773a75Dvc:X" | base64
=> SFVHUDU5Z1hzZDc3NzNhNzVEdmM6WAo=
curl --header "Authorization: Basic SFVHUDU5Z1hzZDc3NzNhNzVEdmM6WAo=" \ 
     http://localhost/users.xml
Community
  • 1
  • 1
0x4a6f4672
  • 27,297
  • 17
  • 103
  • 140
1

Using devise and devise-token_authenticatable, I had to set this in my config/initializers/devise.rb in order to pass the token via http headers:

config.http_authenticatable = true

SharonM
  • 41
  • 3