Skip to content

Commit

Permalink
Beta oauth support added to the runk
Browse files Browse the repository at this point in the history
  • Loading branch information
aitor committed Dec 11, 2008
1 parent 7ca3953 commit 42e166e
Show file tree
Hide file tree
Showing 23 changed files with 564 additions and 3 deletions.
47 changes: 47 additions & 0 deletions app/controllers/oauth_clients_controller.rb
@@ -0,0 +1,47 @@
class OauthClientsController < ApplicationController
before_filter :login_required

def index
@client_applications=current_user.client_applications
@tokens=current_user.tokens.find :all, :conditions=>'oauth_tokens.invalidated_at is null and oauth_tokens.authorized_at is not null'
end

def new
@client_application=ClientApplication.new
end

def create
@client_application=current_user.client_applications.build(params[:client_application])
if @client_application.save
flash[:notice]="Registered the information successfully"
redirect_to :action=>"show",:id=>@client_application.id
else
render :action=>"new"
end
end

def show
@client_application=current_user.client_applications.find(params[:id])
end

def edit
@client_application=current_user.client_applications.find(params[:id])
end

def update
@client_application=current_user.client_applications.find(params[:id])
if @client_application.update_attributes(params[:client_application])
flash[:notice]="Updated the client information successfully"
redirect_to :action=>"show",:id=>@client_application.id
else
render :action=>"edit"
end
end

def destroy
@client_application=current_user.client_applications.find(params[:id])
@client_application.destroy
flash[:notice]="Destroyed the client application registration"
redirect_to :action=>"index"
end
end
62 changes: 62 additions & 0 deletions app/controllers/oauth_controller.rb
@@ -0,0 +1,62 @@
class OauthController < ApplicationController
before_filter :login_required,:except=>[:request_token,:access_token,:test_request]
before_filter :login_or_oauth_required,:only=>[:test_request]
before_filter :verify_oauth_consumer_signature, :only=>[:request_token]
before_filter :verify_oauth_request_token, :only=>[:access_token]
# Uncomment the following if you are using restful_open_id_authentication
# skip_before_filter :verify_authenticity_token

def request_token
@token=current_client_application.create_request_token
if @token
render :text=>@token.to_query
else
render :nothing => true, :status => 401
end
end

def access_token
@token=current_token.exchange!
if @token
render :text=>@token.to_query
else
render :nothing => true, :status => 401
end
end

def test_request
render :text=>params.collect{|k,v|"#{k}=#{v}"}.join("&")
end

def authorize
@token=RequestToken.find_by_token params[:oauth_token]
unless @token.invalidated?
if request.post?
if params[:authorize]=='1'
@token.authorize!(current_user)
redirect_url=params[:oauth_callback]||@token.client_application.callback_url
if redirect_url
redirect_to redirect_url+"?oauth_token=#{@token.token}"
else
render :action=>"authorize_success"
end
elsif params[:authorize]=="0"
@token.invalidate!
render :action=>"authorize_failure"
end
end
else
render :action=>"authorize_failure"
end
end

def revoke
@token=current_user.tokens.find_by_token params[:token]
if @token
@token.invalidate!
flash[:notice]="You've revoked the token for #{@token.client_application.name}"
end
redirect_to oauth_clients_url
end

end
2 changes: 2 additions & 0 deletions app/helpers/oauth_clients_helper.rb
@@ -0,0 +1,2 @@
module OauthClientsHelper
end
2 changes: 2 additions & 0 deletions app/helpers/oauth_helper.rb
@@ -0,0 +1,2 @@
module OauthHelper
end
10 changes: 10 additions & 0 deletions app/models/access_token.rb
@@ -0,0 +1,10 @@
class AccessToken<OauthToken
validates_presence_of :user
before_create :set_authorized_at

protected

def set_authorized_at
self.authorized_at=Time.now
end
end
51 changes: 51 additions & 0 deletions app/models/client_application.rb
@@ -0,0 +1,51 @@
require 'oauth'
class ClientApplication < ActiveRecord::Base
belongs_to :user
has_many :tokens,:class_name=>"OauthToken"
validates_presence_of :name,:url,:key,:secret
validates_uniqueness_of :key
before_validation_on_create :generate_keys

def self.find_token(token_key)
token=OauthToken.find_by_token(token_key, :include => :client_application)
logger.info "Loaded #{token.token} which was authorized by (user_id=#{token.user_id}) on the #{token.authorized_at}"
return token if token.authorized?
nil
end

def self.verify_request(request, options = {}, &block)
begin
signature=OAuth::Signature.build(request,options,&block)
logger.info "Signature Base String: #{signature.signature_base_string}"
logger.info "Consumer: #{signature.send :consumer_key}"
logger.info "Token: #{signature.send :token}"
return false unless OauthNonce.remember(signature.request.nonce,signature.request.timestamp)
value=signature.verify
logger.info "Signature verification returned: #{value.to_s}"
value
rescue OAuth::Signature::UnknownSignatureMethod=>e
logger.info "ERROR"+e.to_s
false
end
end

def oauth_server
@oauth_server||=OAuth::Server.new "http://your.site"
end

def credentials
@oauth_client||=OAuth::Consumer.new key,secret
end

def create_request_token
RequestToken.create :client_application=>self
end

protected

def generate_keys
@oauth_client=oauth_server.generate_consumer_credentials
self.key=@oauth_client.key
self.secret=@oauth_client.secret
end
end
13 changes: 13 additions & 0 deletions app/models/oauth_nonce.rb
@@ -0,0 +1,13 @@
# Simple store of nonces. The OAuth Spec requires that any given pair of nonce and timestamps are unique.
# Thus you can use the same nonce with a different timestamp and viceversa.
class OauthNonce < ActiveRecord::Base
validates_presence_of :nonce,:timestamp
validates_uniqueness_of :nonce,:scope=>:timestamp

# Remembers a nonce and it's associated timestamp. It returns false if it has already been used
def self.remember(nonce,timestamp)
oauth_nonce=OauthNonce.create(:nonce=>nonce,:timestamp=>timestamp)
return false if oauth_nonce.new_record?
oauth_nonce
end
end
32 changes: 32 additions & 0 deletions app/models/oauth_token.rb
@@ -0,0 +1,32 @@
class OauthToken < ActiveRecord::Base
belongs_to :client_application
belongs_to :user
validates_uniqueness_of :token
validates_presence_of :client_application,:token,:secret
before_validation_on_create :generate_keys

def invalidated?
invalidated_at!=nil
end

def invalidate!
update_attribute(:invalidated_at,Time.now)
end

def authorized?
authorized_at!=nil && !invalidated?
end

def to_query
"oauth_token=#{token}&oauth_token_secret=#{secret}"
end

protected

def generate_keys
@oauth_token=client_application.oauth_server.generate_credentials
self.token=@oauth_token[0]
self.secret=@oauth_token[1]
end

end
18 changes: 18 additions & 0 deletions app/models/request_token.rb
@@ -0,0 +1,18 @@
class RequestToken<OauthToken

def authorize!(user)
return false if authorized?
self.user=user
self.authorized_at=Time.now
self.save
end

def exchange!
return false unless authorized?
RequestToken.transaction do
access_token=AccessToken.create(:user=>user,:client_application=>client_application)
invalidate!
access_token
end
end
end
40 changes: 40 additions & 0 deletions app/models/tog/oauth.rb
@@ -0,0 +1,40 @@
# Tog::Oauth provides a simple way to create a consumer for an oauth provider.

module Oauth

# This method uses Tog::Plugins settings to autoconfigure an oauth consumer for a given service.
# So if you want to request info from fireeagle you will have to set at least the following info:
#
# Tog::Plugins.settings :tog_social, "oauth.fireeagle.key" => "OAUTH_KEY_HERE",
# "oauth.fireeagle.secret" => "OAUTH_SECRET_HERE",
# "oauth.fireeagle.site" => "https://fireeagle.yahooapis.com",
# ==== Attributes
#
# * <tt>:service</tt> - The service you want to use this consumer for.
#
def self.consumer(service)

key = setting_for_service(service, "key")
secret = setting_for_service(service, "secret")
site = setting_for_service(service, "site")

OAuth::Consumer.new(key, secret, {:site=>site})
end

protected

def self.setting_for_service(service, setting)
setting_key = "oauth.#{service}.#{setting}"
value = Tog::Plugins.settings(:tog_social, setting_key)
RAILS_DEFAULT_LOGGER.warn <<-WARNING
**************************************************************************************************************************************************
OAUTH WARNING: #{setting_key} setting is nil and this could potentially create problem in the oauth process.
**************************************************************************************************************************************************
WARNING
) unless value
value
end

end
5 changes: 5 additions & 0 deletions app/models/user.rb
Expand Up @@ -15,6 +15,11 @@ class User < ActiveRecord::Base
has_many :moderated_groups, :through => :moderator_memberships,
:conditions => "memberships.state='active' and groups.state='active'", :source => :group

# => oauth support
has_many :client_applications
has_many :tokens, :class_name=>"OauthToken", :order=>"authorized_at desc", :include=>[:client_application]
# => oauth support

protected

def create_profile
Expand Down
14 changes: 14 additions & 0 deletions app/views/oauth/authorize.html.erb
@@ -0,0 +1,14 @@
<h1>Authorize access to your account</h1>
<p>Would you like to authorize <%=link_to @token.client_application.name,@token.client_application.url%> (<%=link_to @token.client_application.url,@token.client_application.url%>) to access your account?</p>
<%form_tag authorize_url do %>
<%=hidden_field_tag "oauth_token",@token.token%>
<%-if params[:oauth_callback]-%>
<%=hidden_field_tag "oauth_callback", params[:oauth_callback]%>
<%-end-%>
<p>
<%=check_box_tag 'authorize'%> authorize access
</p>
<p>
<%=submit_tag%>
</p>
<%end%>
1 change: 1 addition & 0 deletions app/views/oauth/authorize_failure.html.erb
@@ -0,0 +1 @@
<h1>You have disallowed this request</h1>
1 change: 1 addition & 0 deletions app/views/oauth/authorize_success.html.erb
@@ -0,0 +1 @@
<h1>You have allowed this request</h1>
16 changes: 16 additions & 0 deletions app/views/oauth_clients/_form.html.erb
@@ -0,0 +1,16 @@
<div class="field">
<label for="client_application_name">Name*</label><br/>
<%=f.text_field :name%>
</div>
<div class="field">
<label for="client_application_url">Main Application URL*</label><br/>
<%=f.text_field :url%>
</div>
<div class="field">
<label for="client_application_callback_url">Callback URL*</label><br/>
<%=f.text_field :callback_url%>
</div>
<div class="field">
<label for="client_application_support_url">Support URL</label><br/>
<%=f.text_field :support_url%>
</div>
40 changes: 40 additions & 0 deletions app/views/oauth_clients/index.html.erb
@@ -0,0 +1,40 @@
<div class="flash"><%=flash[:notice]%></div>
<h1>OAuth Client Applications</h1>
<%unless @tokens.empty?%>
<p>The following tokens have been issued to applications in your name</p>
<table>
<tr><th>Application</th><th>Issued</th><th>&nbsp;</th></tr>
<%@tokens.each do |token|%>
<%content_tag_for :tr,token do%>
<td><%=link_to token.client_application.name,token.client_application.url%></td>
<td><%=token.authorized_at%></td>
<td>
<%form_tag :controller=>'oauth',:action=>'revoke' do%>
<%=hidden_field_tag 'token',token.token%>
<%=submit_tag "Revoke!"%>
<%end%>
</td>
<%end%>
<%end%>
</table>
<%end%>
<h3>Application Developers</h3>
<%if @client_applications.empty?%>
<p>
Do you have an application you would like to register for use with us using the <a href="http://oauth.net">OAuth</a> standard?
</p>
<p>
You must register your web application before it can make OAuth requests to this service
</p>
<%else%>
<p>
You have the following client applications registered:
</p>
<%@client_applications.each do |client|%>
<%div_for client do%>
<%=link_to client.name,:action=>:show,:id=>client.id%>
<%end%>
<%end%>
<%end%>
<h3><%=link_to "Register your application",:action=>:new%></h3>
5 changes: 5 additions & 0 deletions app/views/oauth_clients/new.html.erb
@@ -0,0 +1,5 @@
<h1>Register a new application</h1>
<% form_for :client_application, :url => { :action => :create } do |f| %>
<%= render :partial => "form", :locals => { :f => f } %>
<%= submit_tag "Register" %>
<% end %>

0 comments on commit 42e166e

Please sign in to comment.