I am writing a Rails back-end API for a Steam game that is only accessed via REST calls, so no user-specific authentication is required. I am trying to implement the authlogic_api plug-in for the Authlogic gem, which uses an api_key/signature mechanism to restrict access. I have implemented the ApplicationSession and ApplicationAccount models as outlined in the rdocs, but I'm not sure how to modify my ApplicationController to restrict access.
Looking at the source, it appears the authlogic_api plug-in modifies the ActsAsAuthentic and Session modules from Authlogic. But since this is essentially "single access" authentication, requiring the API key and signature to be passed on every request, I don't see how sessions would be a factor.
Has anyone successfully implemented authlogic_api in their apps? If so, would you share your approach for setting up your ApplicationController?
Solved this by following the Authlogic example, and just substituting a ClientAccount model for the User model. So in my Application controller I have:
The ClientAccount model acts_as_authentic, and the ClientSession model handles creating and destroying the sessions for Authlogic (authenticate_with ClientAccount):
This solution has worked well, as we're able to generate different API key/signature combos for different clients, which gives us additional usage data. The only "gotcha" is if you're doing something like a multipart file upload, since the POST hash uses the raw POST data.
Actually, it's much simpler. Using all that code from the Authlogic example is somewhat overkill - it mainly manages storing session details, which you don't need to do for the Application (also known as Client) session. The Client session is re-confirmed at every request.
All you need is:
models\client.rb
models\client_session.rb
controllers\application_controller
You also need to run a migration to create the clients table. Not all of the fields below are necessary, but they won't hurt.
You may not need the overhead of Authlogic.
If you are generating a URL that the client will then send, just add an expiration timestamp, and do an MD5 hash (signature) on the entire URL, adding the result as a final query paramter.
Please a before_filter on the controller action, i.e. a signed_url method that will validate the URL. This method should get the URL from the request object. Verify the expiration has not passed. Remove the signature from the URL to place it in the same form as was used to generate the original URL, do so, and verify a match. Voila.
Expiration is important to be sure that URL's cannot be re-used later.
This is a great method to centralize as an alternate way to authorize requests without requiring a login. As long as you have generated the URL, it will be valid until expiration from any host.