oauth-plugin 0.3.14 → 0.4.0.pre1
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/CHANGELOG +10 -0
- data/README.rdoc +44 -9
- data/Rakefile +2 -2
- data/VERSION +1 -1
- data/generators/oauth_consumer/templates/migration.rb +1 -1
- data/generators/oauth_provider/oauth_provider_generator.rb +6 -0
- data/generators/oauth_provider/templates/access_token.rb +2 -2
- data/generators/oauth_provider/templates/client_application.rb +8 -6
- data/generators/oauth_provider/templates/client_applications.yml +6 -6
- data/generators/oauth_provider/templates/clients_controller_spec.rb +130 -193
- data/generators/oauth_provider/templates/controller.rb +12 -0
- data/generators/oauth_provider/templates/controller_spec.rb +762 -291
- data/generators/oauth_provider/templates/controller_spec_helper.rb +49 -63
- data/generators/oauth_provider/templates/migration.rb +6 -5
- data/generators/oauth_provider/templates/oauth2_authorize.html.erb +16 -0
- data/generators/oauth_provider/templates/oauth2_authorize.html.haml +17 -0
- data/generators/oauth_provider/templates/oauth2_token.rb +6 -0
- data/generators/oauth_provider/templates/oauth2_token_spec.rb +29 -0
- data/generators/oauth_provider/templates/oauth2_verifier.rb +28 -0
- data/generators/oauth_provider/templates/oauth2_verifier_spec.rb +54 -0
- data/generators/oauth_provider/templates/oauth_nonce_test.rb +1 -1
- data/generators/oauth_provider/templates/oauth_token.rb +3 -4
- data/generators/oauth_provider/templates/request_token.rb +1 -1
- data/lib/generators/active_record/oauth_consumer_generator.rb +33 -0
- data/lib/generators/active_record/oauth_consumer_templates/consumer_token.rb +5 -0
- data/lib/generators/active_record/oauth_consumer_templates/migration.rb +20 -0
- data/lib/generators/active_record/oauth_provider_generator.rb +39 -0
- data/lib/generators/active_record/oauth_provider_templates/access_token.rb +16 -0
- data/lib/generators/active_record/oauth_provider_templates/client_application.rb +57 -0
- data/lib/generators/active_record/oauth_provider_templates/migration.rb +47 -0
- data/lib/generators/active_record/oauth_provider_templates/oauth2_token.rb +5 -0
- data/lib/generators/active_record/oauth_provider_templates/oauth2_verifier.rb +28 -0
- data/lib/generators/active_record/oauth_provider_templates/oauth_nonce.rb +13 -0
- data/lib/generators/active_record/oauth_provider_templates/oauth_token.rb +30 -0
- data/lib/generators/active_record/oauth_provider_templates/request_token.rb +40 -0
- data/lib/generators/erb/oauth_consumer_generator.rb +14 -0
- data/lib/generators/erb/oauth_consumer_templates/index.html.erb +29 -0
- data/lib/generators/erb/oauth_consumer_templates/show.html.erb +7 -0
- data/lib/generators/erb/oauth_provider_generator.rb +21 -0
- data/lib/generators/erb/oauth_provider_templates/_form.html.erb +17 -0
- data/lib/generators/erb/oauth_provider_templates/authorize.html.erb +14 -0
- data/lib/generators/erb/oauth_provider_templates/authorize_failure.html.erb +1 -0
- data/lib/generators/erb/oauth_provider_templates/authorize_success.html.erb +1 -0
- data/lib/generators/erb/oauth_provider_templates/edit.html.erb +7 -0
- data/lib/generators/erb/oauth_provider_templates/index.html.erb +43 -0
- data/lib/generators/erb/oauth_provider_templates/new.html.erb +5 -0
- data/lib/generators/erb/oauth_provider_templates/oauth2_authorize.html.erb +16 -0
- data/lib/generators/erb/oauth_provider_templates/show.html.erb +27 -0
- data/lib/generators/haml/oauth_consumer_generator.rb +21 -0
- data/lib/generators/haml/oauth_consumer_templates/index.html.haml +18 -0
- data/lib/generators/haml/oauth_consumer_templates/show.html.haml +8 -0
- data/lib/generators/haml/oauth_provider_generator.rb +28 -0
- data/lib/generators/haml/oauth_provider_templates/_form.html.haml +21 -0
- data/lib/generators/haml/oauth_provider_templates/authorize.html.haml +16 -0
- data/lib/generators/haml/oauth_provider_templates/authorize_failure.html.haml +1 -0
- data/lib/generators/haml/oauth_provider_templates/authorize_success.html.haml +1 -0
- data/lib/generators/haml/oauth_provider_templates/edit.html.haml +4 -0
- data/lib/generators/haml/oauth_provider_templates/index.html.haml +39 -0
- data/lib/generators/haml/oauth_provider_templates/new.html.haml +5 -0
- data/lib/generators/haml/oauth_provider_templates/oauth2_authorize.html.haml +17 -0
- data/lib/generators/haml/oauth_provider_templates/show.html.haml +30 -0
- data/lib/generators/mongoid/oauth_consumer_generator.rb +15 -0
- data/lib/generators/mongoid/oauth_consumer_templates/consumer_token.rb +14 -0
- data/lib/generators/mongoid/oauth_provider_generator.rb +21 -0
- data/lib/generators/mongoid/oauth_provider_templates/access_token.rb +16 -0
- data/lib/generators/mongoid/oauth_provider_templates/client_application.rb +71 -0
- data/lib/generators/mongoid/oauth_provider_templates/oauth2_token.rb +5 -0
- data/lib/generators/mongoid/oauth_provider_templates/oauth2_verifier.rb +25 -0
- data/lib/generators/mongoid/oauth_provider_templates/oauth_nonce.rb +24 -0
- data/lib/generators/mongoid/oauth_provider_templates/oauth_token.rb +44 -0
- data/lib/generators/mongoid/oauth_provider_templates/request_token.rb +36 -0
- data/lib/generators/oauth_consumer/USAGE +8 -0
- data/lib/generators/oauth_consumer/oauth_consumer_generator.rb +27 -0
- data/lib/generators/oauth_consumer/templates/controller.rb +19 -0
- data/lib/generators/oauth_consumer/templates/oauth_config.rb +46 -0
- data/lib/generators/oauth_inflections.rb +6 -0
- data/lib/generators/oauth_plugin.rb +0 -0
- data/lib/generators/oauth_provider/USAGE +18 -0
- data/lib/generators/oauth_provider/oauth_provider_generator.rb +47 -0
- data/lib/generators/oauth_provider/templates/clients_controller.rb +52 -0
- data/lib/generators/oauth_provider/templates/controller.rb +23 -0
- data/lib/generators/rspec/oauth_provider_generator.rb +39 -0
- data/lib/generators/rspec/templates/client_application_spec.rb +29 -0
- data/lib/generators/rspec/templates/client_applications.yml +23 -0
- data/lib/generators/rspec/templates/clients_controller_spec.rb +176 -0
- data/lib/generators/rspec/templates/controller_spec.rb +838 -0
- data/lib/generators/rspec/templates/controller_spec_helper.rb +66 -0
- data/lib/generators/rspec/templates/oauth2_token_spec.rb +29 -0
- data/lib/generators/rspec/templates/oauth2_verifier_spec.rb +54 -0
- data/lib/generators/rspec/templates/oauth_nonce_spec.rb +24 -0
- data/lib/generators/rspec/templates/oauth_nonces.yml +13 -0
- data/lib/generators/rspec/templates/oauth_token_spec.rb +309 -0
- data/lib/generators/rspec/templates/oauth_tokens.yml +17 -0
- data/lib/generators/test_unit/oauth_provider_generator.rb +37 -0
- data/lib/generators/test_unit/templates/client_application_test.rb +42 -0
- data/lib/generators/test_unit/templates/client_applications.yml +23 -0
- data/lib/generators/test_unit/templates/clients_controller_test.rb +280 -0
- data/lib/generators/test_unit/templates/controller_test.rb +310 -0
- data/lib/generators/test_unit/templates/controller_test_helper.rb +115 -0
- data/lib/generators/test_unit/templates/oauth_nonce_test.rb +26 -0
- data/lib/generators/test_unit/templates/oauth_nonces.yml +13 -0
- data/lib/generators/test_unit/templates/oauth_token_test.rb +57 -0
- data/lib/generators/test_unit/templates/oauth_tokens.yml +17 -0
- data/lib/oauth/controllers/application_controller_methods.rb +169 -66
- data/lib/oauth/controllers/provider_controller.rb +154 -38
- data/lib/oauth/models/consumers/service_loader.rb +2 -0
- data/lib/oauth/models/consumers/token.rb +0 -1
- data/oauth-plugin.gemspec +97 -10
- data/rails/init.rb +6 -2
- metadata +119 -12
|
@@ -1,80 +1,66 @@
|
|
|
1
|
+
require 'oauth/client/action_controller_request'
|
|
1
2
|
module OAuthControllerSpecHelper
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
@user
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
@
|
|
9
|
-
|
|
3
|
+
|
|
4
|
+
def current_user
|
|
5
|
+
@user||=users(:aaron)
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def current_client_application
|
|
9
|
+
@client_application||=client_applications(:one)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def access_token
|
|
13
|
+
@access_token||=AccessToken.create :user=>current_user,:client_application=>current_client_application
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def request_token
|
|
17
|
+
@request_token||=RequestToken.create :client_application=>current_client_application, :callback_url=>"http://application/callback"
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def consumer_request_token
|
|
21
|
+
OAuth::RequestToken.new current_consumer,request_token.token,request_token.secret
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def consumer_access_token
|
|
25
|
+
OAuth::AccessToken.new current_consumer,access_token.token,access_token.secret
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
if defined?(Devise)
|
|
29
|
+
include Devise::TestHelpers
|
|
30
|
+
def login
|
|
31
|
+
sign_in :user, current_user
|
|
32
|
+
end
|
|
33
|
+
else
|
|
34
|
+
def login
|
|
35
|
+
controller.stub!(:current_user).and_return(current_user)
|
|
36
|
+
end
|
|
10
37
|
end
|
|
11
38
|
|
|
12
39
|
def login_as_application_owner
|
|
40
|
+
@user = users(:quentin)
|
|
13
41
|
login
|
|
14
|
-
@client_application = mock_model(ClientApplication)
|
|
15
|
-
@client_applications = [@client_application]
|
|
16
|
-
|
|
17
|
-
@user.stub!(:client_applications).and_return(@client_applications)
|
|
18
|
-
@client_applications.stub!(:find).and_return(@client_application)
|
|
19
42
|
end
|
|
20
|
-
|
|
21
|
-
def
|
|
22
|
-
|
|
23
|
-
@user||=mock_model(User)
|
|
24
|
-
|
|
25
|
-
User.stub!(:find_by_id).and_return(@user)
|
|
26
|
-
|
|
27
|
-
@server = OAuth::Server.new "http://test.host"
|
|
28
|
-
@consumer = OAuth::Consumer.new('key', 'secret',{:site => "http://test.host"})
|
|
29
|
-
|
|
30
|
-
@client_application = mock_model(ClientApplication)
|
|
31
|
-
controller.stub!(:current_client_application).and_return(@client_application)
|
|
32
|
-
ClientApplication.stub!(:find_by_key).and_return(@client_application)
|
|
33
|
-
@client_application.stub!(:key).and_return(@consumer.key)
|
|
34
|
-
@client_application.stub!(:secret).and_return(@consumer.secret)
|
|
35
|
-
@client_application.stub!(:name).and_return("Client Application name")
|
|
36
|
-
@client_application.stub!(:callback_url).and_return("http://application/callback")
|
|
37
|
-
@request_token = mock_model(RequestToken, :token => 'request_token', :client_application => @client_application, :secret => "request_secret", :user => @user)
|
|
38
|
-
@request_token.stub!(:invalidated?).and_return(false)
|
|
39
|
-
ClientApplication.stub!(:find_token).and_return(@request_token)
|
|
40
|
-
|
|
41
|
-
@request_token_string="oauth_token=request_token&oauth_token_secret=request_secret"
|
|
42
|
-
@request_token.stub!(:to_query).and_return(@request_token_string)
|
|
43
|
-
@request_token.stub!(:expired?).and_return(false)
|
|
44
|
-
@request_token.stub!(:callback_url).and_return(nil)
|
|
45
|
-
@request_token.stub!(:verifier).and_return("verifyme")
|
|
46
|
-
@request_token.stub!(:oauth10?).and_return(false)
|
|
47
|
-
@request_token.stub!(:oob?).and_return(true)
|
|
48
|
-
|
|
49
|
-
@access_token = mock_model(AccessToken, :token => 'access_token', :client_application => @client_application, :secret => "access_secret", :user => @user)
|
|
50
|
-
@access_token.stub!(:invalidated?).and_return(false)
|
|
51
|
-
@access_token.stub!(:authorized?).and_return(true)
|
|
52
|
-
@access_token.stub!(:expired?).and_return(false)
|
|
53
|
-
@access_token_string="oauth_token=access_token&oauth_token_secret=access_secret"
|
|
54
|
-
@access_token.stub!(:to_query).and_return(@access_token_string)
|
|
55
|
-
|
|
56
|
-
@client_application.stub!(:authorize_request?).and_return(true)
|
|
57
|
-
# @client_application.stub!(:sign_request_with_oauth_token).and_return(@request_token)
|
|
58
|
-
@client_application.stub!(:exchange_for_access_token).and_return(@access_token)
|
|
43
|
+
|
|
44
|
+
def current_consumer
|
|
45
|
+
@consumer ||= OAuth::Consumer.new(current_client_application.key,current_client_application.secret,{:site => "http://test.host"})
|
|
59
46
|
end
|
|
60
47
|
|
|
61
48
|
def setup_oauth_for_user
|
|
62
49
|
login
|
|
63
|
-
setup_oauth
|
|
64
|
-
@tokens = [@request_token]
|
|
65
|
-
@tokens.stub!(:find).and_return(@tokens)
|
|
66
|
-
@tokens.stub!(:find_by_token).and_return(@request_token)
|
|
67
|
-
@user.stub!(:tokens).and_return(@tokens)
|
|
68
50
|
end
|
|
69
51
|
|
|
70
52
|
def sign_request_with_oauth(token=nil,options={})
|
|
71
53
|
ActionController::TestRequest.use_oauth=true
|
|
72
|
-
@request.configure_oauth(
|
|
54
|
+
@request.configure_oauth(current_consumer,token,options)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def two_legged_sign_request_with_oauth(consumer=nil,options={})
|
|
58
|
+
ActionController::TestRequest.use_oauth=true
|
|
59
|
+
@request.configure_oauth(consumer,nil,options)
|
|
73
60
|
end
|
|
74
61
|
|
|
75
|
-
def
|
|
76
|
-
|
|
77
|
-
OauthToken.stub!(:find_by_token).with( @access_token.token).and_return(@access_token)
|
|
78
|
-
@access_token.stub!(:is_a?).and_return(true)
|
|
62
|
+
def add_oauth2_token_header(token,options={})
|
|
63
|
+
request.env['HTTP_AUTHORIZATION'] = "OAuth #{token.token}"
|
|
79
64
|
end
|
|
80
|
-
|
|
65
|
+
|
|
66
|
+
end
|
|
@@ -5,27 +5,28 @@ class CreateOauthTables < ActiveRecord::Migration
|
|
|
5
5
|
t.string :url
|
|
6
6
|
t.string :support_url
|
|
7
7
|
t.string :callback_url
|
|
8
|
-
t.string :key, :limit =>
|
|
8
|
+
t.string :key, :limit => 40
|
|
9
9
|
t.string :secret, :limit => 40
|
|
10
10
|
t.integer :user_id
|
|
11
11
|
|
|
12
12
|
t.timestamps
|
|
13
13
|
end
|
|
14
|
-
add_index :client_applications, :key, :unique
|
|
14
|
+
add_index :client_applications, :key, :unique => true
|
|
15
15
|
|
|
16
16
|
create_table :oauth_tokens do |t|
|
|
17
17
|
t.integer :user_id
|
|
18
18
|
t.string :type, :limit => 20
|
|
19
19
|
t.integer :client_application_id
|
|
20
|
-
t.string :token, :limit =>
|
|
20
|
+
t.string :token, :limit => 40
|
|
21
21
|
t.string :secret, :limit => 40
|
|
22
22
|
t.string :callback_url
|
|
23
23
|
t.string :verifier, :limit => 20
|
|
24
|
-
t.
|
|
24
|
+
t.string :scope
|
|
25
|
+
t.timestamp :authorized_at, :invalidated_at, :valid_to
|
|
25
26
|
t.timestamps
|
|
26
27
|
end
|
|
27
28
|
|
|
28
|
-
add_index :oauth_tokens, :token, :unique
|
|
29
|
+
add_index :oauth_tokens, :token, :unique => true
|
|
29
30
|
|
|
30
31
|
create_table :oauth_nonces do |t|
|
|
31
32
|
t.string :nonce
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
<h1>Authorize access to your account</h1>
|
|
2
|
+
<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>
|
|
3
|
+
<%% form_tag authorize_url do %>
|
|
4
|
+
<%%= hidden_field_tag "response_type", params[:response_type]%>
|
|
5
|
+
<%%= hidden_field_tag "client_id", params[:client_id]%>
|
|
6
|
+
<%%= hidden_field_tag "redirect_url", params[:redirect_url]%>
|
|
7
|
+
<%%= hidden_field_tag "state", params[:state]%>
|
|
8
|
+
<%%= hidden_field_tag "scope", params[:scope]%>
|
|
9
|
+
|
|
10
|
+
<p>
|
|
11
|
+
<%%= check_box_tag 'authorize' %> authorize access
|
|
12
|
+
</p>
|
|
13
|
+
<p>
|
|
14
|
+
<%%= submit_tag %>
|
|
15
|
+
</p>
|
|
16
|
+
<%% end %>
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
%h1 Authorize access to your account
|
|
2
|
+
%p
|
|
3
|
+
Would you like to authorize
|
|
4
|
+
= link_to @client_application.name,@client_application.url
|
|
5
|
+
(
|
|
6
|
+
= link_to @client_application.url,@client_application.url
|
|
7
|
+
) to access your account?
|
|
8
|
+
- form_tag authorize_url do
|
|
9
|
+
= hidden_field_tag "response_type", params[:response_type]
|
|
10
|
+
= hidden_field_tag "client_id", params[:client_id]
|
|
11
|
+
= hidden_field_tag "redirect_url", params[:redirect_url]
|
|
12
|
+
= hidden_field_tag "state", params[:state]
|
|
13
|
+
= hidden_field_tag "scope", params[:scope]
|
|
14
|
+
= check_box_tag 'authorize'
|
|
15
|
+
authorize access
|
|
16
|
+
%p
|
|
17
|
+
= submit_tag
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Oauth2Token do
|
|
4
|
+
fixtures :client_applications, :users, :oauth_tokens
|
|
5
|
+
before(:each) do
|
|
6
|
+
@token = Oauth2Token.create :client_application => client_applications(:one), :user=>users(:aaron)
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
it "should be valid" do
|
|
10
|
+
@token.should be_valid
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
it "should have a token" do
|
|
14
|
+
@token.token.should_not be_nil
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it "should have a secret" do
|
|
18
|
+
@token.secret.should_not be_nil
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
it "should be authorized" do
|
|
22
|
+
@token.should be_authorized
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
it "should not be invalidated" do
|
|
26
|
+
@token.should_not be_invalidated
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
class Oauth2Verifier < OauthToken
|
|
2
|
+
validates_presence_of :user
|
|
3
|
+
|
|
4
|
+
def exchange!(params={})
|
|
5
|
+
OauthToken.transaction do
|
|
6
|
+
token = Oauth2Token.create! :user=>user,:client_application=>client_application
|
|
7
|
+
invalidate!
|
|
8
|
+
token
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def code
|
|
13
|
+
token
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def redirect_url
|
|
17
|
+
callback_url
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
protected
|
|
21
|
+
|
|
22
|
+
def generate_keys
|
|
23
|
+
self.token = OAuth::Helper.generate_key(20)[0,20]
|
|
24
|
+
self.valid_to = 10.minutes.from_now
|
|
25
|
+
self.authorized_at = Time.now
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
end
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Oauth2Verifier do
|
|
4
|
+
fixtures :client_applications, :users, :oauth_tokens
|
|
5
|
+
before(:each) do
|
|
6
|
+
@verifier = Oauth2Verifier.create :client_application => client_applications(:one), :user=>users(:aaron)
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
it "should be valid" do
|
|
10
|
+
@verifier.should be_valid
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
it "should have a code" do
|
|
14
|
+
@verifier.code.should_not be_nil
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it "should not have a secret" do
|
|
18
|
+
@verifier.secret.should be_nil
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
it "should be authorized" do
|
|
22
|
+
@verifier.should be_authorized
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
it "should not be invalidated" do
|
|
26
|
+
@verifier.should_not be_invalidated
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
describe "exchange for oauth2 token" do
|
|
30
|
+
before(:each) do
|
|
31
|
+
@token = @verifier.exchange!
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
it "should invalidate verifier" do
|
|
35
|
+
@verifier.should be_invalidated
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
it "should set user on token" do
|
|
39
|
+
@token.user.should==@verifier.user
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
it "should set client application on token" do
|
|
43
|
+
@token.client_application.should == @verifier.client_application
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
it "should be authorized" do
|
|
47
|
+
@token.should be_authorized
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
it "should not be invalidated" do
|
|
51
|
+
@token.should_not be_invalidated
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
@@ -2,7 +2,7 @@ class OauthToken < ActiveRecord::Base
|
|
|
2
2
|
belongs_to :client_application
|
|
3
3
|
belongs_to :user
|
|
4
4
|
validates_uniqueness_of :token
|
|
5
|
-
validates_presence_of :client_application, :token
|
|
5
|
+
validates_presence_of :client_application, :token
|
|
6
6
|
before_validation_on_create :generate_keys
|
|
7
7
|
|
|
8
8
|
def invalidated?
|
|
@@ -24,8 +24,7 @@ class OauthToken < ActiveRecord::Base
|
|
|
24
24
|
protected
|
|
25
25
|
|
|
26
26
|
def generate_keys
|
|
27
|
-
|
|
28
|
-
self.
|
|
29
|
-
self.secret = oauth_token[1][0,40]
|
|
27
|
+
self.token = OAuth::Helper.generate_key(40)[0,40]
|
|
28
|
+
self.secret = OAuth::Helper.generate_key(40)[0,40]
|
|
30
29
|
end
|
|
31
30
|
end
|
|
@@ -6,7 +6,7 @@ class RequestToken < OauthToken
|
|
|
6
6
|
return false if authorized?
|
|
7
7
|
self.user = user
|
|
8
8
|
self.authorized_at = Time.now
|
|
9
|
-
self.verifier=OAuth::Helper.generate_key(
|
|
9
|
+
self.verifier=OAuth::Helper.generate_key(20)[0,20] unless oauth10?
|
|
10
10
|
self.save
|
|
11
11
|
end
|
|
12
12
|
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
require 'rails/generators/active_record'
|
|
2
|
+
|
|
3
|
+
module ActiveRecord
|
|
4
|
+
module Generators
|
|
5
|
+
class OauthProviderGenerator < Rails::Generators::Base
|
|
6
|
+
include Rails::Generators::Migration
|
|
7
|
+
|
|
8
|
+
source_root File.expand_path('../oauth_consumer_templates', __FILE__)
|
|
9
|
+
|
|
10
|
+
# Implement the required interface for Rails::Generators::Migration.
|
|
11
|
+
def self.next_migration_number(dirname) #:nodoc:
|
|
12
|
+
next_migration_number = current_migration_number(dirname) + 1
|
|
13
|
+
if ActiveRecord::Base.timestamped_migrations
|
|
14
|
+
[Time.now.utc.strftime("%Y%m%d%H%M%S"), "%.14d" % next_migration_number].max
|
|
15
|
+
else
|
|
16
|
+
"%.3d" % next_migration_number
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def check_class_collisions
|
|
21
|
+
class_collisions '', %w(ConsumerToken)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def copy_models
|
|
25
|
+
template 'consumer_token.rb', File.join('app/models', 'consumer_token.rb')
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def copy_migration
|
|
29
|
+
migration_template 'migration.rb', 'db/migrate/create_oauth_consumer_tokens'
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
class CreateOauthConsumerTokens < ActiveRecord::Migration
|
|
2
|
+
def self.up
|
|
3
|
+
|
|
4
|
+
create_table :consumer_tokens do |t|
|
|
5
|
+
t.integer :user_id
|
|
6
|
+
t.string :type, :limit => 30
|
|
7
|
+
t.string :token, :limit => 1024 # This has to be huge because of Yahoo's excessively large tokens
|
|
8
|
+
t.string :secret
|
|
9
|
+
t.timestamps
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
add_index :consumer_tokens, :token, :unique => true
|
|
13
|
+
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def self.down
|
|
17
|
+
drop_table :consumer_tokens
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
end
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
require 'rails/generators/active_record'
|
|
2
|
+
|
|
3
|
+
module ActiveRecord
|
|
4
|
+
module Generators
|
|
5
|
+
class OauthProviderGenerator < Rails::Generators::Base
|
|
6
|
+
include Rails::Generators::Migration
|
|
7
|
+
|
|
8
|
+
source_root File.expand_path('../oauth_provider_templates', __FILE__)
|
|
9
|
+
|
|
10
|
+
# Implement the required interface for Rails::Generators::Migration.
|
|
11
|
+
def self.next_migration_number(dirname) #:nodoc:
|
|
12
|
+
next_migration_number = current_migration_number(dirname) + 1
|
|
13
|
+
if ActiveRecord::Base.timestamped_migrations
|
|
14
|
+
[Time.now.utc.strftime("%Y%m%d%H%M%S"), "%.14d" % next_migration_number].max
|
|
15
|
+
else
|
|
16
|
+
"%.3d" % next_migration_number
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def check_class_collisions
|
|
21
|
+
class_collisions '', %w(ClientApplication OauthNonce RequestToken AccessToken OauthToken)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def copy_models
|
|
25
|
+
template 'client_application.rb', File.join('app/models', 'client_application.rb')
|
|
26
|
+
template 'oauth_token.rb', File.join('app/models', 'oauth_token.rb')
|
|
27
|
+
template 'request_token.rb', File.join('app/models', 'request_token.rb')
|
|
28
|
+
template 'access_token.rb', File.join('app/models', 'access_token.rb')
|
|
29
|
+
template 'oauth2_token.rb', File.join('app/models', 'oauth2_token.rb')
|
|
30
|
+
template 'oauth2_verifier.rb', File.join('app/models', 'oauth2_verifier.rb')
|
|
31
|
+
template 'oauth_nonce.rb', File.join('app/models', 'oauth_nonce.rb')
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def copy_migration
|
|
35
|
+
migration_template 'migration.rb', 'db/migrate/create_oauth_tables'
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
class AccessToken < OauthToken
|
|
2
|
+
validates_presence_of :user, :secret
|
|
3
|
+
before_create :set_authorized_at
|
|
4
|
+
|
|
5
|
+
# Implement this to return a hash or array of the capabilities the access token has
|
|
6
|
+
# This is particularly useful if you have implemented user defined permissions.
|
|
7
|
+
# def capabilities
|
|
8
|
+
# {:invalidate=>"/oauth/invalidate",:capabilities=>"/oauth/capabilities"}
|
|
9
|
+
# end
|
|
10
|
+
|
|
11
|
+
protected
|
|
12
|
+
|
|
13
|
+
def set_authorized_at
|
|
14
|
+
self.authorized_at = Time.now
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
require 'oauth'
|
|
2
|
+
class ClientApplication < ActiveRecord::Base
|
|
3
|
+
belongs_to :user
|
|
4
|
+
has_many :tokens, :class_name => "OauthToken"
|
|
5
|
+
has_many :access_tokens
|
|
6
|
+
has_many :oauth2_verifiers
|
|
7
|
+
has_many :oauth_tokens
|
|
8
|
+
validates_presence_of :name, :url, :key, :secret
|
|
9
|
+
validates_uniqueness_of :key
|
|
10
|
+
before_validation :generate_keys, :on => :create
|
|
11
|
+
|
|
12
|
+
validates_format_of :url, :with => /\Ahttp(s?):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?/i
|
|
13
|
+
validates_format_of :support_url, :with => /\Ahttp(s?):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?/i, :allow_blank=>true
|
|
14
|
+
validates_format_of :callback_url, :with => /\Ahttp(s?):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?/i, :allow_blank=>true
|
|
15
|
+
|
|
16
|
+
attr_accessor :token_callback_url
|
|
17
|
+
|
|
18
|
+
def self.find_token(token_key)
|
|
19
|
+
token = OauthToken.find_by_token(token_key, :include => :client_application)
|
|
20
|
+
if token && token.authorized?
|
|
21
|
+
token
|
|
22
|
+
else
|
|
23
|
+
nil
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def self.verify_request(request, options = {}, &block)
|
|
28
|
+
begin
|
|
29
|
+
signature = OAuth::Signature.build(request, options, &block)
|
|
30
|
+
return false unless OauthNonce.remember(signature.request.nonce, signature.request.timestamp)
|
|
31
|
+
value = signature.verify
|
|
32
|
+
value
|
|
33
|
+
rescue OAuth::Signature::UnknownSignatureMethod => e
|
|
34
|
+
false
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def oauth_server
|
|
39
|
+
@oauth_server ||= OAuth::Server.new("http://your.site")
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def credentials
|
|
43
|
+
@oauth_client ||= OAuth::Consumer.new(key, secret)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# If your application requires passing in extra parameters handle it here
|
|
47
|
+
def create_request_token(params={})
|
|
48
|
+
RequestToken.create :client_application => self, :callback_url=>self.token_callback_url
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
protected
|
|
52
|
+
|
|
53
|
+
def generate_keys
|
|
54
|
+
self.key = OAuth::Helper.generate_key(40)[0,40]
|
|
55
|
+
self.secret = OAuth::Helper.generate_key(40)[0,40]
|
|
56
|
+
end
|
|
57
|
+
end
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
class CreateOauthTables < ActiveRecord::Migration
|
|
2
|
+
def self.up
|
|
3
|
+
create_table :client_applications do |t|
|
|
4
|
+
t.string :name
|
|
5
|
+
t.string :url
|
|
6
|
+
t.string :support_url
|
|
7
|
+
t.string :callback_url
|
|
8
|
+
t.string :key, :limit => 40
|
|
9
|
+
t.string :secret, :limit => 40
|
|
10
|
+
t.integer :user_id
|
|
11
|
+
|
|
12
|
+
t.timestamps
|
|
13
|
+
end
|
|
14
|
+
add_index :client_applications, :key, :unique => true
|
|
15
|
+
|
|
16
|
+
create_table :oauth_tokens do |t|
|
|
17
|
+
t.integer :user_id
|
|
18
|
+
t.string :type, :limit => 20
|
|
19
|
+
t.integer :client_application_id
|
|
20
|
+
t.string :token, :limit => 40
|
|
21
|
+
t.string :secret, :limit => 40
|
|
22
|
+
t.string :callback_url
|
|
23
|
+
t.string :verifier, :limit => 20
|
|
24
|
+
t.string :scope
|
|
25
|
+
t.timestamp :authorized_at, :invalidated_at, :valid_to
|
|
26
|
+
t.timestamps
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
add_index :oauth_tokens, :token, :unique => true
|
|
30
|
+
|
|
31
|
+
create_table :oauth_nonces do |t|
|
|
32
|
+
t.string :nonce
|
|
33
|
+
t.integer :timestamp
|
|
34
|
+
|
|
35
|
+
t.timestamps
|
|
36
|
+
end
|
|
37
|
+
add_index :oauth_nonces,[:nonce, :timestamp], :unique => true
|
|
38
|
+
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def self.down
|
|
42
|
+
drop_table :client_applications
|
|
43
|
+
drop_table :oauth_tokens
|
|
44
|
+
drop_table :oauth_nonces
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
class Oauth2Verifier < OauthToken
|
|
2
|
+
validates_presence_of :user
|
|
3
|
+
|
|
4
|
+
def exchange!(params={})
|
|
5
|
+
OauthToken.transaction do
|
|
6
|
+
token = Oauth2Token.create! :user=>user,:client_application=>client_application
|
|
7
|
+
invalidate!
|
|
8
|
+
token
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def code
|
|
13
|
+
token
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def redirect_url
|
|
17
|
+
callback_url
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
protected
|
|
21
|
+
|
|
22
|
+
def generate_keys
|
|
23
|
+
self.token = OAuth::Helper.generate_key(20)[0,20]
|
|
24
|
+
self.valid_to = 10.minutes.from_now
|
|
25
|
+
self.authorized_at = Time.now
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Simple store of nonces. The OAuth Spec requires that any given pair of nonce and timestamps are unique.
|
|
2
|
+
# Thus you can use the same nonce with a different timestamp and viceversa.
|
|
3
|
+
class OauthNonce < ActiveRecord::Base
|
|
4
|
+
validates_presence_of :nonce, :timestamp
|
|
5
|
+
validates_uniqueness_of :nonce, :scope => :timestamp
|
|
6
|
+
|
|
7
|
+
# Remembers a nonce and it's associated timestamp. It returns false if it has already been used
|
|
8
|
+
def self.remember(nonce, timestamp)
|
|
9
|
+
oauth_nonce = OauthNonce.create(:nonce => nonce, :timestamp => timestamp)
|
|
10
|
+
return false if oauth_nonce.new_record?
|
|
11
|
+
oauth_nonce
|
|
12
|
+
end
|
|
13
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
class OauthToken < ActiveRecord::Base
|
|
2
|
+
belongs_to :client_application
|
|
3
|
+
belongs_to :user
|
|
4
|
+
validates_uniqueness_of :token
|
|
5
|
+
validates_presence_of :client_application, :token
|
|
6
|
+
before_validation :generate_keys, :on => :create
|
|
7
|
+
|
|
8
|
+
def invalidated?
|
|
9
|
+
invalidated_at != nil
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def invalidate!
|
|
13
|
+
update_attribute(:invalidated_at, Time.now)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def authorized?
|
|
17
|
+
authorized_at != nil && !invalidated?
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def to_query
|
|
21
|
+
"oauth_token=#{token}&oauth_token_secret=#{secret}"
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
protected
|
|
25
|
+
|
|
26
|
+
def generate_keys
|
|
27
|
+
self.token = OAuth::Helper.generate_key(40)[0,40]
|
|
28
|
+
self.secret = OAuth::Helper.generate_key(40)[0,40]
|
|
29
|
+
end
|
|
30
|
+
end
|