Prevent Authlogic from establishing a session/cookie for non-HTML requests
I'm using Authlogic and Rails 3. On top of the regular browser-based user experience (logging in via form and whatnot), I'd like to implement an API.
Authlogic seems to support single access tokens that don't persist by default. I supply them by adding a GET argument as in:
/users.xml?user_credentails=my_single_access_token
Question: Is there any way I can have Authlogic accept the API key via HTTP Basic Auth? Highrise does something just like this, allowing for:
curl -u 605b32dd:X http://sample.highrisehq.com/people/1.xml
The same with Freshbooks:
curl -u insert_token_here:X https://sample.freshbooks.com/api/2.1/xml-in -d '[xml body here]'
How I would go about imitating this functionality? I can't even figure out where the input data (postdata from forms, HTTP basic, API token) are taken in. I've boiled it down to a call to UserSessions.find
with no arguments, but I lose track of it after there.
Any help would be much appreciated!
Related question: I'd also like to disable session persistence (make it so that no cookie is stored) if HTTP basic is used. Any help on this too would开发者_StackOverflow中文版 be appreciated!
If you're implementing an API, you could consider building a separate Rack application that is then mounted at '/api/1.0/...' and shares your models.
That way you are not tying yourself into having your API directly related to your public routes, which could be difficult to construct for the API user.
A good approach would be to create a simple Sinatra application that exposes just the methods that you want, and to then create a separate authentication strategy:
require 'sinatra'
require 'active_support' # all the Rails stuff
require 'lib/user' # your User class
require 'sinatra/respond_to' # gem install sinatra-respond_to
Sinatra::Application.register Sinatra::RespondTo
use Rack::Auth::Basic, "API", do |username, password|
User.find_by_login(username).valid_password?(password)
end
get '/api/1.0/posts' do
@posts = Post.recent # assuming you have a Post model...
respond_to do |wants|
wants.xml { @posts.to_xml }
wants.to_json { @posts.to_json }
end
end
get '/api/1.0/users/:id' do
@user = User.find_by_login(params[:id])
# Careful here - don't release personal details!
respond_to do |wants|
wants.xml { @user.to_xml }
wants.to_json { @user.to_json }
end
end
Versioning your API with a '1.0' (or similar) in the path means that if you change your models you can create a new version of your API without breaking your users' existing code.
Using this you should be able to allow users to authenticate with HTTP Basic in the form:
curl -u steven:password http://example.com/api/1.0/users/steven.xml
curl -u steven:password http://example.com/api/1.0/users/steven.json
curl -u steven:password http://example.com/api/1.0/posts.xml
To get this running, save it as 'api.rb', and either run it as a Rack Middleware, or create a 'config.ru' file like so:
require 'api'
run Sinatra::Application
And then from that directory:
rackup
Disclaimer: I'm not a 100% this is possible in the way your describing without hacking up Authlogic's core functionality.
The first issue your going to have is that authlogic prevents the use of SSO tokens for authentication unless the request is ATOM or RSS to override this you need to pass a config paramater see here: http://rdoc.info/github/binarylogic/authlogic/master/Authlogic/Session/Params/Config
To the core issue: I don't see any 'easy' way to handle this functionality, however what you could do for something like curl is pass the user token as a paramater (using the -G
option) just like you would when visiting the url.
cURL Documentation: http://curl.haxx.se/docs/manpage.html
Forgive me if I misunderstand your question, but I think the answer is a simple "no." You're mixing two metaphors here. If you want a secure API key, use the single access token; if you want to use http basic access authentication, you need a different base64 glyph -- and http basic auth isn't particularly secure (unless used over https, which isn't generally practical).
In more detail:
Per the wikipedia, http basic authentication is intended to provide a username and password in a simple, standard, but fairly insecure base64 encoded glyph.
To use basic auth, then I believe you want to generate the glyph via a simple
Base64.encode64("#{user.name}:#{password}")
...and I'd probably do this by having the user type their password, since you can't derive the password from the crypted_password that authlogic stores in your database.
But the upshot is that this is a very different beast from the single_access_token, and the two can't be mixed.
精彩评论