Creating an API for one project at work, one odbrhw tasks was to implement a token based authentication for some resources, but the client specifically requested not to have to handle cookies.
Also, it was requested for the user to still have to login with it’s own login and password, rather than with a permanent token, like a permanent API key.
The solution I implemented used the excellent authlogic capabilities with the single_access_token, although used slighlty differently from it’s original purpose.

Rather than keeping the single access token generated at user registration untouched, like a standard API key, I enforced it’s regeneration at both login and logout. Returned in the login response, that token then has to be provided by the client for every request that needs authentication, effectively playing the same role as a cookie.

With this solution, the client looses the ability to stay logged in by storing the credentials in the client’s machine, but as the project it’s been created for only required an API, there was no problem with that.
Implementing this solution simply puts a little big more work on the client to store and provide the token in the requests parameters, but I still found it an elegant solution to get around my problem.

The following code implements this solution in the Application and the User_Session controllers, showing the regeneration of the token in both login and logout actions with authlogic’s reset_single_access_token method.

app > controllers > user_sessions_controller

 class UserSessionsController < ApplicationController

  def create
    @user_session = UserSession.new(params[:user_session])
    respond_to do |format|
      if @user_session.save
        current_user.reset_single_access_token!
        format.xml
      else
       format.xml {render :xml=>@user_session.errors, :status=>:unauthorized}
      end
    end
  end

  def destroy
    if(@user_session = UserSession.find)
      current_user.reset_single_access_token!
      @user_session.destroy
      respond_to do |format|
        format.xml {render :xml=>{:status=>'200 ok'},:status=> :ok}
      end
    else
      respond_to do |format|
         format.xml  {render :xml=>@user_session.errors, :status=> :not_found}
      end
    end
  end
end

app > models > user

class User < ActiveRecord::Base
  acts_as_authentic
end

app > views > users_sessions > create.xml.builder

xml.instruct! :xml, :version=>"1.0" 

xml.user{
    xml.user_id(current_user.id)
    xml.user_credentials(current_user.single_access_token)
}

app > controllers > users_controller

class UsersController < ApplicationController
  before_filter :check

  def create
  end

  def index
  end

  def update
  end

  def show
  end

end

db > migrate > create_users

class CreateUsers < ActiveRecord::Migration
  def self.up
    create_table :users do |t|
      t.string  :username
      t.string  :crypted_password
      t.string  :password_salt
      t.string  :persistence_token
      t.string  :single_access_token, :null => false

      t.timestamps
    end
  end

  def self.down
    drop_table :users
  end
end