oauth-plugin 0.3.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +5 -0
- data/CHANGELOG +76 -0
- data/MIT-LICENSE +20 -0
- data/README.rdoc +375 -0
- data/Rakefile +38 -0
- data/VERSION +1 -0
- data/generators/oauth_consumer/USAGE +10 -0
- data/generators/oauth_consumer/oauth_consumer_generator.rb +49 -0
- data/generators/oauth_consumer/templates/consumer_token.rb +5 -0
- data/generators/oauth_consumer/templates/controller.rb +14 -0
- data/generators/oauth_consumer/templates/migration.rb +20 -0
- data/generators/oauth_consumer/templates/oauth_config.rb +37 -0
- data/generators/oauth_consumer/templates/show.html.erb +7 -0
- data/generators/oauth_consumer/templates/show.html.haml +8 -0
- data/generators/oauth_provider/USAGE +20 -0
- data/generators/oauth_provider/lib/insert_routes.rb +67 -0
- data/generators/oauth_provider/oauth_provider_generator.rb +124 -0
- data/generators/oauth_provider/templates/_form.html.erb +17 -0
- data/generators/oauth_provider/templates/_form.html.haml +21 -0
- data/generators/oauth_provider/templates/access_token.rb +10 -0
- data/generators/oauth_provider/templates/authorize.html.erb +14 -0
- data/generators/oauth_provider/templates/authorize.html.haml +16 -0
- data/generators/oauth_provider/templates/authorize_failure.html.erb +1 -0
- data/generators/oauth_provider/templates/authorize_failure.html.haml +1 -0
- data/generators/oauth_provider/templates/authorize_success.html.erb +1 -0
- data/generators/oauth_provider/templates/authorize_success.html.haml +1 -0
- data/generators/oauth_provider/templates/client_application.rb +55 -0
- data/generators/oauth_provider/templates/client_application_spec.rb +29 -0
- data/generators/oauth_provider/templates/client_application_test.rb +42 -0
- data/generators/oauth_provider/templates/client_applications.yml +23 -0
- data/generators/oauth_provider/templates/clients_controller.rb +52 -0
- data/generators/oauth_provider/templates/clients_controller_spec.rb +239 -0
- data/generators/oauth_provider/templates/clients_controller_test.rb +280 -0
- data/generators/oauth_provider/templates/controller.rb +5 -0
- data/generators/oauth_provider/templates/controller_spec.rb +367 -0
- data/generators/oauth_provider/templates/controller_spec_helper.rb +80 -0
- data/generators/oauth_provider/templates/controller_test.rb +310 -0
- data/generators/oauth_provider/templates/controller_test_helper.rb +115 -0
- data/generators/oauth_provider/templates/edit.html.erb +7 -0
- data/generators/oauth_provider/templates/edit.html.haml +4 -0
- data/generators/oauth_provider/templates/index.html.erb +43 -0
- data/generators/oauth_provider/templates/index.html.haml +39 -0
- data/generators/oauth_provider/templates/migration.rb +46 -0
- data/generators/oauth_provider/templates/new.html.erb +5 -0
- data/generators/oauth_provider/templates/new.html.haml +5 -0
- data/generators/oauth_provider/templates/oauth_nonce.rb +13 -0
- data/generators/oauth_provider/templates/oauth_nonce_spec.rb +24 -0
- data/generators/oauth_provider/templates/oauth_nonce_test.rb +26 -0
- data/generators/oauth_provider/templates/oauth_nonces.yml +13 -0
- data/generators/oauth_provider/templates/oauth_token.rb +31 -0
- data/generators/oauth_provider/templates/oauth_token_spec.rb +309 -0
- data/generators/oauth_provider/templates/oauth_token_test.rb +57 -0
- data/generators/oauth_provider/templates/oauth_tokens.yml +17 -0
- data/generators/oauth_provider/templates/request_token.rb +40 -0
- data/generators/oauth_provider/templates/show.html.erb +27 -0
- data/generators/oauth_provider/templates/show.html.haml +30 -0
- data/init.rb +7 -0
- data/install.rb +2 -0
- data/lib/oauth/controllers/application_controller_methods.rb +110 -0
- data/lib/oauth/controllers/consumer_controller.rb +69 -0
- data/lib/oauth/controllers/provider_controller.rb +78 -0
- data/lib/oauth/models/consumers/service_loader.rb +18 -0
- data/lib/oauth/models/consumers/services/agree2_token.rb +14 -0
- data/lib/oauth/models/consumers/services/twitter_token.rb +19 -0
- data/lib/oauth/models/consumers/token.rb +60 -0
- data/oauth-plugin.gemspec +104 -0
- data/tasks/oauth_tasks.rake +4 -0
- data/uninstall.rb +1 -0
- metadata +131 -0
@@ -0,0 +1,57 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../test_helper'
|
2
|
+
|
3
|
+
class RequestTokenTest < ActiveSupport::TestCase
|
4
|
+
|
5
|
+
fixtures :client_applications, :users, :oauth_tokens
|
6
|
+
|
7
|
+
def setup
|
8
|
+
@token = RequestToken.create :client_application=>client_applications(:one)
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_should_be_valid
|
12
|
+
assert @token.valid?
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_should_not_have_errors
|
16
|
+
assert @token.errors.empty?
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_should_have_a_token
|
20
|
+
assert_not_nil @token.token
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_should_have_a_secret
|
24
|
+
assert_not_nil @token.secret
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_should_not_be_authorized
|
28
|
+
assert !@token.authorized?
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_should_not_be_invalidated
|
32
|
+
assert !@token.invalidated?
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_should_authorize_request
|
36
|
+
@token.authorize!(users(:quentin))
|
37
|
+
assert @token.authorized?
|
38
|
+
assert_not_nil @token.authorized_at
|
39
|
+
assert_equal users(:quentin), @token.user
|
40
|
+
end
|
41
|
+
|
42
|
+
def test_should_not_exchange_without_approval
|
43
|
+
assert_equal false, @token.exchange!
|
44
|
+
assert_equal false, @token.invalidated?
|
45
|
+
end
|
46
|
+
|
47
|
+
def test_should_not_exchange_without_approval
|
48
|
+
@token.authorize!(users(:quentin))
|
49
|
+
@access = @token.exchange!
|
50
|
+
assert_not_equal false, @access
|
51
|
+
assert @token.invalidated?
|
52
|
+
|
53
|
+
assert_equal users(:quentin), @access.user
|
54
|
+
assert @access.authorized?
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html
|
2
|
+
one:
|
3
|
+
id: 1
|
4
|
+
user_id: 1
|
5
|
+
client_application_id: 1
|
6
|
+
token: one
|
7
|
+
secret: MyString
|
8
|
+
created_at: 2007-11-19 07:31:46
|
9
|
+
updated_at: 2007-11-19 07:31:46
|
10
|
+
two:
|
11
|
+
id: 2
|
12
|
+
user_id: 1
|
13
|
+
client_application_id: 1
|
14
|
+
token: two
|
15
|
+
secret: MyString
|
16
|
+
created_at: 2007-11-19 07:31:46
|
17
|
+
updated_at: 2007-11-19 07:31:46
|
@@ -0,0 +1,40 @@
|
|
1
|
+
class RequestToken < OauthToken
|
2
|
+
|
3
|
+
attr_accessor :provided_oauth_verifier
|
4
|
+
|
5
|
+
def authorize!(user)
|
6
|
+
return false if authorized?
|
7
|
+
self.user = user
|
8
|
+
self.authorized_at = Time.now
|
9
|
+
self.verifier=OAuth::Helper.generate_key(16)[0,20] unless oauth10?
|
10
|
+
self.save
|
11
|
+
end
|
12
|
+
|
13
|
+
def exchange!
|
14
|
+
return false unless authorized?
|
15
|
+
return false unless oauth10? || verifier==provided_oauth_verifier
|
16
|
+
|
17
|
+
RequestToken.transaction do
|
18
|
+
access_token = AccessToken.create(:user => user, :client_application => client_application)
|
19
|
+
invalidate!
|
20
|
+
access_token
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def to_query
|
25
|
+
if oauth10?
|
26
|
+
super
|
27
|
+
else
|
28
|
+
"#{super}&oauth_callback_confirmed=true"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def oob?
|
33
|
+
self.callback_url=='oob'
|
34
|
+
end
|
35
|
+
|
36
|
+
def oauth10?
|
37
|
+
(defined? OAUTH_10_SUPPORT) && OAUTH_10_SUPPORT && self.callback_url.blank?
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
<h1>OAuth details for <%%=@client_application.name %></h1>
|
2
|
+
<p>
|
3
|
+
<strong>Consumer Key:</strong>
|
4
|
+
<code><%%=@client_application.key %></code>
|
5
|
+
</p>
|
6
|
+
<p>
|
7
|
+
<strong>Consumer Secret:</strong>
|
8
|
+
<code><%%=@client_application.secret %></code>
|
9
|
+
</p>
|
10
|
+
<p>
|
11
|
+
<strong>Request Token URL</strong>
|
12
|
+
<code>http<%%='s' if request.ssl? %>://<%%= request.host_with_port %><%%=@client_application.oauth_server.request_token_path %></code>
|
13
|
+
</p>
|
14
|
+
<p>
|
15
|
+
<strong>Access Token URL</strong>
|
16
|
+
<code>http<%%='s' if request.ssl? %>://<%%= request.host_with_port %><%%=@client_application.oauth_server.access_token_path %></code>
|
17
|
+
</p>
|
18
|
+
<p>
|
19
|
+
<strong>Authorize URL</strong>
|
20
|
+
<code>http<%%='s' if request.ssl? %>://<%%= request.host_with_port %><%%=@client_application.oauth_server.authorize_path %></code>
|
21
|
+
</p>
|
22
|
+
|
23
|
+
<p>
|
24
|
+
We support hmac-sha1 (recommended) as well as plain text in ssl mode.
|
25
|
+
</p>
|
26
|
+
<%%= link_to 'Edit', edit_oauth_client_path(@client_application) %> |
|
27
|
+
<%%= link_to 'Back', oauth_clients_path %>
|
@@ -0,0 +1,30 @@
|
|
1
|
+
%h1
|
2
|
+
OAuth details for
|
3
|
+
=@client_application.name
|
4
|
+
%p
|
5
|
+
%strong Consumer Key:
|
6
|
+
%code=@client_application.key
|
7
|
+
%p
|
8
|
+
%strong Consumer Secret:
|
9
|
+
%code=@client_application.secret
|
10
|
+
|
11
|
+
%p
|
12
|
+
%strong Request Token URL
|
13
|
+
%code
|
14
|
+
="http#{'s' if request.ssl?}://#{request.host_with_port}#{@client_application.oauth_server.request_token_path}"
|
15
|
+
|
16
|
+
%p
|
17
|
+
%strong Access Token URL
|
18
|
+
%code
|
19
|
+
="http#{'s' if request.ssl?}://#{request.host_with_port}#{@client_application.oauth_server.access_token_path}"
|
20
|
+
|
21
|
+
%p
|
22
|
+
%strong Authorize URL
|
23
|
+
%code
|
24
|
+
="http#{'s' if request.ssl?}://#{request.host_with_port}#{@client_application.oauth_server.authorize_path}"
|
25
|
+
|
26
|
+
%p
|
27
|
+
We support hmac-sha1 (recommended) as well as plain text in ssl mode.
|
28
|
+
|
29
|
+
= link_to 'Edit', edit_oauth_client_path(@client_application)
|
30
|
+
= link_to 'Back', oauth_clients_path
|
data/init.rb
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
gem 'oauth', '>=0.3.5'
|
2
|
+
require 'oauth/signature/hmac/sha1'
|
3
|
+
require 'oauth/request_proxy/action_controller_request'
|
4
|
+
require 'oauth/server'
|
5
|
+
require 'oauth/controllers/application_controller_methods'
|
6
|
+
|
7
|
+
ActionController::Base.send :include, OAuth::Controllers::ApplicationControllerMethods
|
data/install.rb
ADDED
@@ -0,0 +1,110 @@
|
|
1
|
+
require 'oauth/signature'
|
2
|
+
module OAuth
|
3
|
+
module Controllers
|
4
|
+
|
5
|
+
module ApplicationControllerMethods
|
6
|
+
protected
|
7
|
+
|
8
|
+
def current_token
|
9
|
+
@current_token
|
10
|
+
end
|
11
|
+
|
12
|
+
def current_client_application
|
13
|
+
@current_client_application
|
14
|
+
end
|
15
|
+
|
16
|
+
def oauthenticate
|
17
|
+
verified=verify_oauth_signature
|
18
|
+
return verified && current_token.is_a?(::AccessToken)
|
19
|
+
end
|
20
|
+
|
21
|
+
def oauth?
|
22
|
+
current_token!=nil
|
23
|
+
end
|
24
|
+
|
25
|
+
# use in a before_filter
|
26
|
+
def oauth_required
|
27
|
+
if oauthenticate
|
28
|
+
if authorized?
|
29
|
+
return true
|
30
|
+
else
|
31
|
+
invalid_oauth_response
|
32
|
+
end
|
33
|
+
else
|
34
|
+
invalid_oauth_response
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# This requies that you have an acts_as_authenticated compatible authentication plugin installed
|
39
|
+
def login_or_oauth_required
|
40
|
+
if oauthenticate
|
41
|
+
if authorized?
|
42
|
+
return true
|
43
|
+
else
|
44
|
+
invalid_oauth_response
|
45
|
+
end
|
46
|
+
else
|
47
|
+
login_required
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
|
52
|
+
# verifies a request token request
|
53
|
+
def verify_oauth_consumer_signature
|
54
|
+
begin
|
55
|
+
valid = ClientApplication.verify_request(request) do |request_proxy|
|
56
|
+
@current_client_application = ClientApplication.find_by_key(request_proxy.consumer_key)
|
57
|
+
|
58
|
+
# Store this temporarily in client_application object for use in request token generation
|
59
|
+
@current_client_application.token_callback_url=request_proxy.oauth_callback if request_proxy.oauth_callback
|
60
|
+
|
61
|
+
# return the token secret and the consumer secret
|
62
|
+
[nil, @current_client_application.secret]
|
63
|
+
end
|
64
|
+
rescue
|
65
|
+
valid=false
|
66
|
+
end
|
67
|
+
|
68
|
+
invalid_oauth_response unless valid
|
69
|
+
end
|
70
|
+
|
71
|
+
def verify_oauth_request_token
|
72
|
+
verify_oauth_signature && current_token.is_a?(RequestToken)
|
73
|
+
end
|
74
|
+
|
75
|
+
def invalid_oauth_response(code=401,message="Invalid OAuth Request")
|
76
|
+
render :text => message, :status => code
|
77
|
+
end
|
78
|
+
|
79
|
+
private
|
80
|
+
|
81
|
+
def current_token=(token)
|
82
|
+
@current_token=token
|
83
|
+
if @current_token
|
84
|
+
@current_user=@current_token.user
|
85
|
+
@current_client_application=@current_token.client_application
|
86
|
+
end
|
87
|
+
@current_token
|
88
|
+
end
|
89
|
+
|
90
|
+
# Implement this for your own application using app-specific models
|
91
|
+
def verify_oauth_signature
|
92
|
+
begin
|
93
|
+
valid = ClientApplication.verify_request(request) do |request_proxy|
|
94
|
+
self.current_token = ClientApplication.find_token(request_proxy.token)
|
95
|
+
if self.current_token.respond_to?(:provided_oauth_verifier=)
|
96
|
+
self.current_token.provided_oauth_verifier=request_proxy.oauth_verifier
|
97
|
+
end
|
98
|
+
# return the token secret and the consumer secret
|
99
|
+
[(current_token.nil? ? nil : current_token.secret), (current_client_application.nil? ? nil : current_client_application.secret)]
|
100
|
+
end
|
101
|
+
# reset @current_user to clear state for restful_...._authentication
|
102
|
+
@current_user = nil if (!valid)
|
103
|
+
valid
|
104
|
+
rescue
|
105
|
+
false
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
module Oauth
|
2
|
+
module Controllers
|
3
|
+
module ConsumerController
|
4
|
+
def self.included(controller)
|
5
|
+
controller.class_eval do
|
6
|
+
before_filter :login_required
|
7
|
+
before_filter :load_consumer
|
8
|
+
skip_before_filter :verify_authenticity_token
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
# creates request token and redirects on to oauth provider's auth page
|
13
|
+
# If user is already connected it displays a page with an option to disconnect and redo
|
14
|
+
def show
|
15
|
+
unless @token
|
16
|
+
@request_token=@consumer.get_request_token(callback_oauth_consumer_url(params[:id]))
|
17
|
+
session[@request_token.token]=@request_token.secret
|
18
|
+
if @request_token.callback_confirmed?
|
19
|
+
redirect_to @request_token.authorize_url
|
20
|
+
else
|
21
|
+
redirect_to(@request_token.authorize_url + "&oauth_callback=#{callback_oauth_consumer_url(params[:id])}")
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def callback
|
27
|
+
@request_token_secret=session[params[:oauth_token]]
|
28
|
+
if @request_token_secret
|
29
|
+
@token=@consumer.create_from_request_token(current_user,params[:oauth_token],@request_token_secret,params[:oauth_verifier])
|
30
|
+
if @token
|
31
|
+
flash[:notice] = "#{params[:id].humanize} was successfully connected to your account"
|
32
|
+
go_back
|
33
|
+
else
|
34
|
+
flash[:error] = "An error happened, please try connecting again"
|
35
|
+
redirect_to oauth_consumer_url(params[:id])
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
|
41
|
+
def destroy
|
42
|
+
throw RecordNotFound unless @token
|
43
|
+
@token.destroy
|
44
|
+
if params[:Reconnect]
|
45
|
+
redirect_to oauth_consumer_url(params[:id])
|
46
|
+
else
|
47
|
+
flash[:notice] = "#{params[:id].humanize} was successfully disconnected from your account"
|
48
|
+
|
49
|
+
go_back
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
protected
|
54
|
+
|
55
|
+
# Override this in your controller to decide where you want to redirect user to after callback is finished.
|
56
|
+
def go_back
|
57
|
+
redirect_to root_url
|
58
|
+
end
|
59
|
+
|
60
|
+
def load_consumer
|
61
|
+
consumer_key=params[:id].to_sym
|
62
|
+
throw RecordNotFound unless OAUTH_CREDENTIALS.include?(consumer_key)
|
63
|
+
@consumer="#{consumer_key.to_s.camelcase}Token".constantize
|
64
|
+
@token=@consumer.find_by_user_id current_user.id
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
module OAuth
|
2
|
+
module Controllers
|
3
|
+
|
4
|
+
module ProviderController
|
5
|
+
def self.included(controller)
|
6
|
+
controller.class_eval do
|
7
|
+
before_filter :login_required, :except => [:request_token, :access_token, :test_request]
|
8
|
+
before_filter :login_or_oauth_required, :only => [:test_request]
|
9
|
+
before_filter :verify_oauth_consumer_signature, :only => [:request_token]
|
10
|
+
before_filter :verify_oauth_request_token, :only => [:access_token]
|
11
|
+
skip_before_filter :verify_authenticity_token
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def request_token
|
16
|
+
@token = current_client_application.create_request_token
|
17
|
+
if @token
|
18
|
+
render :text => @token.to_query
|
19
|
+
else
|
20
|
+
render :nothing => true, :status => 401
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def access_token
|
25
|
+
@token = current_token && current_token.exchange!
|
26
|
+
if @token
|
27
|
+
render :text => @token.to_query
|
28
|
+
else
|
29
|
+
render :nothing => true, :status => 401
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_request
|
34
|
+
render :text => params.collect{|k,v|"#{k}=#{v}"}.join("&")
|
35
|
+
end
|
36
|
+
|
37
|
+
def authorize
|
38
|
+
@token = ::RequestToken.find_by_token params[:oauth_token]
|
39
|
+
unless @token.invalidated?
|
40
|
+
if request.post?
|
41
|
+
if params[:authorize] == '1'
|
42
|
+
@token.authorize!(current_user)
|
43
|
+
if @token.oauth10?
|
44
|
+
@redirect_url = params[:oauth_callback] || @token.client_application.callback_url
|
45
|
+
else
|
46
|
+
@redirect_url = @token.oob? ? @token.client_application.callback_url : @token.callback_url
|
47
|
+
end
|
48
|
+
|
49
|
+
if @redirect_url
|
50
|
+
if @token.oauth10?
|
51
|
+
redirect_to "#{@redirect_url}?oauth_token=#{@token.token}"
|
52
|
+
else
|
53
|
+
redirect_to "#{@redirect_url}?oauth_token=#{@token.token}&oauth_verifier=#{@token.verifier}"
|
54
|
+
end
|
55
|
+
else
|
56
|
+
render :action => "authorize_success"
|
57
|
+
end
|
58
|
+
elsif params[:authorize] == "0"
|
59
|
+
@token.invalidate!
|
60
|
+
render :action => "authorize_failure"
|
61
|
+
end
|
62
|
+
end
|
63
|
+
else
|
64
|
+
render :action => "authorize_failure"
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def revoke
|
69
|
+
@token = current_user.tokens.find_by_token params[:token]
|
70
|
+
if @token
|
71
|
+
@token.invalidate!
|
72
|
+
flash[:notice] = "You've revoked the token for #{@token.client_application.name}"
|
73
|
+
end
|
74
|
+
redirect_to oauth_clients_url
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|