## Twitter OAuth Strategy

Warden::Strategies.add(:oauth) do
def authenticate!
if params.include?('oauth_token') && credentials.authenticate!(params['oauth_token'])
session.delete(:credential)
success!(credentials)
end

redirect!(credentials.authentication_url)
end

def credentials
@credentials ||= Credential.get(session[:credential] ||= Credential.create.id)
end
end

## Make sure to add this in your init.rb or equivalent

Merb::BootLoader.after_app_loads do
Warden::Manager.serialize_into_session {|cred| cred.to_s }
Warden::Manager.serialize_from_session {|id| Credential.get(id) }
end

## And in your rack.rb or equivalent

use Warden::Manager do |manager|
manager.default_strategies :oauth
end

## credential.rb

require 'oauth' # ~> oauth-0.3.2

class Credential
include DataMapper::Resource
extend Forwardable

CONSUMER_KEY = Merb::Config[:oauth][:consumer_key]
CONSUMER_SECRET = Merb::Config[:oauth][:consumer_secret]

property :id, DM::UUID, :nullable => false, :default => lambda { ::UUID.timestamp_create }, :index => true, :key => true
property :access_token, String, :length => 64
property :access_secret, String, :length => 64
property :request_token, String, :length => 64
property :request_secret, String, :length => 64
property :status, Enum[:authenticated, nil]
property :account_id, Integer

belongs_to :account

def_delegators :id, :to_s
def_delegators :request, :authorize_url

def authenticate!(token)
if token == self.request_token && verified?
update(:status => :authenticated)
end
end

def authentication_url
authorize_url.gsub('authorize', 'authenticate')
end

def authenticated?
self.status == :authenticated unless status.nil?
end

#TODO: you probably want to add more verification yourself
def verified?
!access.nil?
end

private

def consumer
@consumer ||= OAuth::Consumer.new(CONSUMER_KEY, CONSUMER_SECRET, :site => 'http://twitter.com')
end

def request
@request ||= if request_token.nil? || request_secret.nil?
request = consumer.get_request_token
request if self.update(:request_token => request.token, :request_secret => request.secret)
else
OAuth::RequestToken.new(consumer, request_token, request_secret)
end
end

def access
@access ||= if access_token.nil? || access_secret.nil?
access = request.get_access_token
access if update(:access_token => access.token, :access_secret => access.secret)
else
OAuth::AccessToken.new(consumer, access_token, access_secret)
end
end
end