I’m facing a problem: how to do authentication for my app’s REST API.
I’m trying not to repeat myself so I was thinking on using large tokens
and modify restful_authentication to recognize this token and require
all calls to the api to specify it. If I’m not wrong, this might cause
problems because restful_auth depends on sessions which depend on
cookies which a client that accesses the API might not support.
I want to know if someone has dealt with this problem before. Any tips
or ideas are greatly appreciated.
I’m facing a problem: how to do authentication for my app’s REST API.
I’m trying not to repeat myself so I was thinking on using large tokens
and modify restful_authentication to recognize this token and require
all calls to the api to specify it. If I’m not wrong, this might cause
problems because restful_auth depends on sessions which depend on
cookies which a client that accesses the API might not support.
I want to know if someone has dealt with this problem before. Any tips
or ideas are greatly appreciated.
Thanks!
Hey Eduardo-
I haven’t liked any of the username/password authentication things that
are out there. (e.g. Basecamp API)
I’ve implemented a token-based thing like you suggest. The user has the
application create an API token (if API stuff is to be enabled). This
token is stored with the account.
I use the map.resources bit to map out the API resources with a prefix
like /api/:api_token –
map.with_options :path_prefix => “/api/:api_token” do |api|
api.resources :item
end
Then maps to the “item” resource in the RESTful manner. Since URLs are
encrypted for HTTPS, this seems pretty secure to me. (i.e. the
api_token is never in the wild)
My “require_login” filters automatically check for the api_token and can
authenticate that way. If no api_token is present, authentication must
be done with the session.
If the user wants to change the api_token, they’re free to do so at any
time. Personally, I don’t like the idea of keeping a username and
password somewhere in an application that is using an API. I’d much
rather just set the token.
I’ve implemented a token-based thing like you suggest. The user has the
application create an API token (if API stuff is to be enabled). This
token is stored with the account.
Hi Jake,
i have the similar needs for my application. Do you mind to post some
code or a link to repository to take a look on? Thanks in advance.
I’m facing a problem: how to do authentication for my app’s REST API.
I’m trying not to repeat myself so I was thinking on using large
tokens
and modify restful_authentication to recognize this token and require
all calls to the api to specify it. If I’m not wrong, this might cause
problems because restful_auth depends on sessions which depend on
cookies which a client that accesses the API might not support.
restful_authentication uses forms and cookies for standard web
requests but offers http authentication for api calls. eg, the
default access_denied method is:
def access_denied
respond_to do |accepts|
accepts.html do
store_location
redirect_to :controller => 'sessions', :action => 'new'
end
accepts.xml do
headers["Status"] = "Unauthorized"
headers["WWW-Authenticate"] = %(Basic realm="Web Password")
render :text => "Could't authenticate you", :status =>
‘401 Unauthorized’
end
end
false
end
So you shouldn’t need to define a key etc, restful authentication and
http have it covered.
I’ve implemented a token-based thing like you suggest. The user has the
application create an API token (if API stuff is to be enabled). This
token is stored with the account.
Hi Jake,
i have the similar needs for my application. Do you mind to post some
code or a link to repository to take a look on? Thanks in advance.
Hi Stoyan-
Unfortunately, I don’t have things very neatly organized. Fortunately,
there isn’t much to it, really. I stole the “create_token” code from
the salted-hash login generator:
def create_token
# Create an integer from an SHA1 hash of the time.
# Add a random number to the time in case we're generating these
quickly.
val = Integer(‘0x’ +
Digest::SHA1.hexdigest(“#{TOKEN_SALT}#{Time.now.to_f}#{rand}”))
# Convert the integer to URL-safe characters.
# 64 characters per 6 bits of the integer.
ch64 = ('a'..'z').to_a + ('A'..'Z').to_a + ('0'..'9').to_a +
[‘-’,‘_’]
token = ‘’
26.times do
token += ch64[(val & 0x3f)]
val = val >> 6
end
token
end
From there, you can use the other login systems fairly easily. During
the authentication step (require_login or wherever), just check for the
API token as a parameter:
# Check for an API token
if params[:api_token] && params[:api_token]
activeaccount = Account.find_by_api_token(params[:api_token])
return true if activeaccount
end
Unfortunately, I don’t have things very neatly organized. Fortunately,
there isn’t much to it, really. I stole the “create_token” code from
the salted-hash login generator: