oauth2_provider 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG CHANGED
@@ -1,3 +1,97 @@
1
+ [f15eb88 | Tue Aug 31 23:25:50 UTC 2010] Ketan Padegaonkar <KetanPadegaonkar@gmail.com>
2
+
3
+ * Bumping up version number for a 0.2.0 release!
4
+
5
+ [05c5534 | Wed Aug 25 17:40:04 UTC 2010] Janmejay Singh <singh.janmejay@gmail.com>
6
+
7
+ * plugin when loaded in jruby/rails app(initialized by jruby-rack servlet), in production mode, was failing to find files/load missing constants(even though files are present in path). Fixed the problem by eger loading necessary files.
8
+
9
+ [79c14f0 | Mon Aug 23 18:24:17 UTC 2010] David Rice <david.rice@gmail.com>
10
+
11
+ * add ids and classes to HTML to allow for styling by host application; remove oauth client show view as it was redundant to the list view
12
+
13
+ [0ff4cc7 | Tue Aug 10 21:23:00 UTC 2010] Janmejay Singh <singh.janmejay@gmail.com>
14
+
15
+ * allowed silencing 'using datasource...' message by an environment variable, message is shown unless ENV['LOAD_OAUTH_SILENTLY'] is set
16
+
17
+ [c59ef9f | Tue Aug 10 20:43:53 UTC 2010] Janmejay Singh <singh.janmejay@gmail.com>
18
+
19
+ * added environment variables to make route prefixing possible
20
+
21
+ [e051873 | Fri Aug 06 02:18:36 UTC 2010] Ketan Padegaonkar <KetanPadegaonkar@gmail.com>
22
+
23
+ * user_id_for_oauth_access_token is nil if the token passed using the 'Authorization' header has expired.
24
+
25
+ [740104a | Fri Aug 06 01:19:28 UTC 2010] Janmejay Singh <singh.janmejay@gmail.com>
26
+
27
+ * refactored model_base to pick datasource using a method instead of @@datasource, this makes it easy for plugin users to override what datasource instance is used. jruby-rack initializes @app on first request(insteed of servlet initialization), so it is important to do this lazily
28
+
29
+ [a3728a9 | Fri Aug 06 01:16:27 UTC 2010] Janmejay Singh <singh.janmejay@gmail.com>
30
+
31
+ * user level service approval now has forgery protection enabled + disabled forgery_protection for api request(/oauth/token)
32
+
33
+ [2145cd2 | Tue Aug 03 18:15:15 UTC 2010] Ketan Padegaonkar <KetanPadegaonkar@gmail.com>
34
+
35
+ * Fixed url munging issues because our model objects are not AR based. Duck typing!!
36
+
37
+ [c6d43b3 | Mon Aug 02 17:37:14 UTC 2010] Ketan Padegaonkar <KetanPadegaonkar@gmail.com>
38
+
39
+ * KP/WPC -
40
+
41
+ * Autodiscover the datasource based on whether ActiveRecord is available.
42
+ * Default to using InMemoryDatasource if ActiveRecord is not available, and print a warning.
43
+
44
+ [ddc56ca | Sat Jul 31 00:55:47 UTC 2010] wpc <alex.hal9000@gmail.com>
45
+
46
+ * Specify data type for column for ModelBase. (by default is string type)
47
+
48
+ [9546cd7 | Fri Jul 30 23:22:43 UTC 2010] wpc <alex.hal9000@gmail.com>
49
+
50
+ * KP/WPC use eval instead of constantize for intiailze custom data source, because constantize dose not work on java class
51
+
52
+ [c52a5b6 | Fri Jul 30 23:19:14 UTC 2010] wpc <alex.hal9000@gmail.com>
53
+
54
+ * KP/WPC refactoring for removing all find_all_* methods
55
+
56
+ [136bca5 | Fri Jul 30 22:57:51 UTC 2010] wpc <alex.hal9000@gmail.com>
57
+
58
+ * KP/WPC - removed some find methods.
59
+
60
+ [233b20c | Fri Jul 30 22:37:00 UTC 2010] wpc <alex.hal9000@gmail.com>
61
+
62
+ * KP/WPC - Add some tests for ModelBase. Removed some redundant tests from oauth_client_test which were really ModelBase tests.
63
+
64
+ [5e43b90 | Fri Jul 30 21:05:40 UTC 2010] wpc <alex.hal9000@gmail.com>
65
+
66
+ * KP/WPC change expires_at type to integer, so that DataSource don't need to do Date type converting.
67
+
68
+ [027ded7 | Fri Jul 30 00:41:36 UTC 2010] Ketan Padegaonkar <KetanPadegaonkar@gmail.com>
69
+
70
+ * Renamed a class.
71
+
72
+ [31903c2 | Fri Jul 30 00:05:24 UTC 2010] Ketan Padegaonkar <KetanPadegaonkar@gmail.com>
73
+
74
+ * KP/WPC - Added an example in memory datasource to store oauth DTO objects.
75
+
76
+ [bd4f9db | Thu Jul 29 22:24:06 UTC 2010] Ketan Padegaonkar <KetanPadegaonkar@gmail.com>
77
+
78
+ * KP/WPC - Remove all dependencies on AR.
79
+
80
+ [cf2b818 | Thu Jul 29 20:53:09 UTC 2010] Ketan Padegaonkar <KetanPadegaonkar@gmail.com>
81
+
82
+ * KP/WPC - [cleanup] refactored our classes into their own files.
83
+
84
+ [1f8f120 | Thu Jul 29 20:46:36 UTC 2010] Ketan Padegaonkar <KetanPadegaonkar@gmail.com>
85
+
86
+ * Remove empty file.
87
+
88
+ [4072a40 | Thu Jul 29 19:16:32 UTC 2010] Ketan Padegaonkar <KetanPadegaonkar@gmail.com>
89
+
90
+ * KP/WPC - Remove dependency on AR.
91
+
92
+ Decouple the OauthClient from AR.
93
+ Rolled out our own AR 'clone' that delegates DB operations to a DTO behind the source.
94
+
1
95
  [20b81b6 | Sat Jul 24 00:30:26 UTC 2010] Ketan Padegaonkar <KetanPadegaonkar@gmail.com>
2
96
 
3
97
  * Bump up version number for release.
data/README.textile CHANGED
@@ -15,6 +15,8 @@ OAuth is an open-source specification for building a framework for allowing a th
15
15
 
16
16
  A very good overview of the basic OAuth workflow is "here":http://hueniverse.com/2007/10/beginners-guide-to-oauth-part-ii-protocol-workflow/.
17
17
 
18
+ As some of this is not always easy to grok on first pass, we also put together "some videos":http://www.youtube.com/view_play_list?p=675281900139F609 to give a step-by-step introduction to OAuth.
19
+
18
20
  Common terms:
19
21
 
20
22
  * Provider/Resource Owner - the app that hosts the protected resource. A real world example is Twitter which uses OAuth as the protocol for all its clients.
@@ -48,7 +48,7 @@ module Oauth2
48
48
  return false
49
49
  end
50
50
 
51
- @client = OauthClient.find_by_client_id(params[:client_id])
51
+ @client = OauthClient.find_one(:client_id, params[:client_id])
52
52
 
53
53
  if @client.nil?
54
54
  redirect_to "#{params[:redirect_uri]}?error=invalid-client-id"
@@ -26,7 +26,8 @@ module Oauth2
26
26
 
27
27
  if @oauth_client.save
28
28
  flash[:notice] = 'OauthClient was successfully created.'
29
- redirect_to(@oauth_client)
29
+ redirect_to :action => 'index'
30
+ return
30
31
  else
31
32
  render :action => "new"
32
33
  end
@@ -37,7 +38,8 @@ module Oauth2
37
38
 
38
39
  if @oauth_client.update_attributes(params[:oauth_client])
39
40
  flash[:notice] = 'OauthClient was successfully updated.'
40
- redirect_to(@oauth_client)
41
+ redirect_to :action => 'index'
42
+ return
41
43
  else
42
44
  render :action => "edit"
43
45
  end
@@ -4,43 +4,42 @@
4
4
  module Oauth2
5
5
  module Provider
6
6
  class OauthTokenController < ApplicationController
7
+ skip_before_filter :verify_authenticity_token
7
8
 
8
9
  def get_token
9
10
 
10
- authorization = OauthAuthorization.find_by_code(params[:code])
11
- authorization.delete unless authorization.nil?
11
+ authorization = OauthAuthorization.find_one(:code, params[:code])
12
+ authorization.destroy unless authorization.nil?
12
13
 
13
- original_token = OauthToken.find_by_refresh_token(params[:refresh_token])
14
- original_token.delete unless original_token.nil?
14
+ original_token = OauthToken.find_one(:refresh_token, params[:refresh_token])
15
+ original_token.destroy unless original_token.nil?
15
16
 
16
17
  unless ['authorization-code', 'refresh-token'].include?(params[:grant_type])
17
- render_error('unsupported-grant-type')
18
+ render_error('unsupported-grant-type', "Grant type #{params[:grant_type]} is not supported!")
18
19
  return
19
20
  end
20
21
 
21
- client = OauthClient.find_by_client_id_and_client_secret(
22
- params[:client_id], params[:client_secret]
23
- )
24
-
25
- if client.nil?
26
- render_error('invalid-client-credentials')
22
+ client = OauthClient.find_one(:client_id, params[:client_id])
23
+
24
+ if client.nil? || client.client_secret != params[:client_secret]
25
+ render_error('invalid-client-credentials', 'Invalid client credentials!')
27
26
  return
28
27
  end
29
28
 
30
29
  if client.redirect_uri != params[:redirect_uri]
31
- render_error('invalid-grant')
30
+ render_error('invalid-grant', 'Redirect uri mismatch!')
32
31
  return
33
32
  end
34
33
 
35
34
  if params[:grant_type] == 'authorization-code'
36
- if authorization.nil? || authorization.expired? || authorization.oauth_client != client
37
- render_error('invalid-grant')
35
+ if authorization.nil? || authorization.expired? || authorization.oauth_client.id != client.id
36
+ render_error('invalid-grant', "Authorization expired or invalid!")
38
37
  return
39
38
  end
40
39
  token = authorization.generate_access_token
41
40
  else # refresh-token
42
- if original_token.nil? || original_token.oauth_client != client
43
- render_error('invalid-grant')
41
+ if original_token.nil? || original_token.oauth_client.id != client.id
42
+ render_error('invalid-grant', 'Refresh token is invalid!')
44
43
  return
45
44
  end
46
45
  token = original_token.refresh
@@ -50,8 +49,8 @@ module Oauth2
50
49
  end
51
50
 
52
51
  private
53
- def render_error(error_code)
54
- render :status => :bad_request, :json => {:error => error_code}.to_json
52
+ def render_error(error_code, description)
53
+ render :status => :bad_request, :json => {:error => error_code, :error_description => description}.to_json
55
54
  end
56
55
 
57
56
  end
@@ -6,7 +6,7 @@ module Oauth2
6
6
  class OauthUserTokensController < ApplicationController
7
7
 
8
8
  def index
9
- @tokens = OauthToken.find_all_by_user_id(current_user_id_for_oauth)
9
+ @tokens = OauthToken.find_all_with(:user_id, current_user_id_for_oauth)
10
10
  end
11
11
 
12
12
  def revoke
@@ -15,12 +15,12 @@ module Oauth2
15
15
  render :text => "User not authorized to perform this action!", :status => :bad_request
16
16
  return
17
17
  end
18
- if token.user_id != current_user_id_for_oauth
18
+ if token.user_id.to_s != current_user_id_for_oauth
19
19
  render :text => "User not authorized to perform this action!", :status => :bad_request
20
20
  return
21
21
  end
22
22
 
23
- token.delete
23
+ token.destroy
24
24
  redirect_to :action => :index
25
25
  end
26
26
 
@@ -3,32 +3,34 @@
3
3
 
4
4
  module Oauth2
5
5
  module Provider
6
- class OauthAuthorization < ::ActiveRecord::Base
6
+ class OauthAuthorization < ModelBase
7
7
 
8
- belongs_to :oauth_client, :class_name => "Oauth2::Provider::OauthClient"
9
-
10
8
  EXPIRY_TIME = 1.hour
11
-
9
+ columns :user_id, :oauth_client_id, :code, :expires_at => :integer
10
+
11
+ def oauth_client
12
+ OauthClient.find_by_id(oauth_client_id)
13
+ end
14
+
12
15
  def generate_access_token
13
16
  token = oauth_client.create_token_for_user_id(user_id)
14
- self.delete
17
+ self.destroy
15
18
  token
16
19
  end
17
-
20
+
18
21
  def expires_in
19
22
  (Time.at(expires_at.to_i) - Clock.now).to_i
20
23
  end
21
-
24
+
22
25
  def expired?
23
26
  expires_in <= 0
24
27
  end
25
-
26
- protected
28
+
27
29
  def before_create
28
- self.expires_at = Clock.now + EXPIRY_TIME
30
+ self.expires_at = (Clock.now + EXPIRY_TIME).to_i
29
31
  self.code = ActiveSupport::SecureRandom.hex(32)
30
32
  end
31
-
33
+
32
34
  end
33
35
  end
34
36
  end
@@ -3,31 +3,41 @@
3
3
 
4
4
  module Oauth2
5
5
  module Provider
6
- class OauthClient < ActiveRecord::Base
7
-
6
+ class OauthClient < ModelBase
7
+
8
8
  validates_presence_of :name, :redirect_uri
9
- before_create :generate_keys
10
- has_many :oauth_tokens, :class_name => "Oauth2::Provider::OauthToken", :dependent => :delete_all
11
- has_many :oauth_authorizations, :class_name => "Oauth2::Provider::OauthAuthorization", :dependent => :delete_all
12
9
  validates_format_of :redirect_uri, :with => Regexp.new("^(https|http)://.+$")
10
+
11
+ columns :name, :client_id, :client_secret, :redirect_uri
13
12
 
14
13
  def create_token_for_user_id(user_id)
15
- oauth_tokens.create!(:user_id => user_id)
14
+ OauthToken.create!(:user_id => user_id, :oauth_client_id => id)
16
15
  end
17
16
 
18
17
  def create_authorization_for_user_id(user_id)
19
- oauth_authorizations.create!(:user_id => user_id)
18
+ OauthAuthorization.create!(:user_id => user_id, :oauth_client_id => id)
20
19
  end
21
-
22
20
  def self.model_name
23
21
  ActiveSupport::ModelName.new('OauthClient')
24
22
  end
23
+
24
+ def oauth_tokens
25
+ OauthToken.find_all_with(:oauth_client_id, id)
26
+ end
27
+
28
+ def oauth_authorizations
29
+ OauthAuthorization.find_all_with(:oauth_client_id, id)
30
+ end
25
31
 
26
- private
27
- def generate_keys
32
+ def before_create
28
33
  self.client_id = ActiveSupport::SecureRandom.hex(32)
29
34
  self.client_secret = ActiveSupport::SecureRandom.hex(32)
30
35
  end
36
+
37
+ def before_destroy
38
+ oauth_tokens.each(&:destroy)
39
+ oauth_authorizations.each(&:destroy)
40
+ end
31
41
 
32
42
  end
33
43
  end
@@ -3,36 +3,39 @@
3
3
 
4
4
  module Oauth2
5
5
  module Provider
6
- class OauthToken < ::ActiveRecord::Base
6
+ class OauthToken < ModelBase
7
+
8
+ columns :user_id, :oauth_client_id, :access_token, :refresh_token, :expires_at => :integer
7
9
 
8
- belongs_to :oauth_client, :class_name => "Oauth2::Provider::OauthClient"
9
-
10
10
  EXPIRY_TIME = 90.days
11
-
11
+
12
+ def oauth_client
13
+ OauthClient.find_by_id(oauth_client_id)
14
+ end
15
+
12
16
  def access_token_attributes
13
17
  {:access_token => access_token, :expires_in => expires_in, :refresh_token => refresh_token}
14
18
  end
15
-
19
+
16
20
  def expires_in
17
21
  (Time.at(expires_at.to_i) - Clock.now).to_i
18
22
  end
19
-
23
+
20
24
  def expired?
21
25
  expires_in <= 0
22
26
  end
23
-
27
+
24
28
  def refresh
25
- self.delete
29
+ self.destroy
26
30
  oauth_client.create_token_for_user_id(user_id)
27
31
  end
28
32
 
29
- protected
30
33
  def before_create
31
34
  self.access_token = ActiveSupport::SecureRandom.hex(32)
32
- self.expires_at = Clock.now + EXPIRY_TIME
35
+ self.expires_at = (Clock.now + EXPIRY_TIME).to_i
33
36
  self.refresh_token = ActiveSupport::SecureRandom.hex(32)
34
37
  end
35
-
38
+
36
39
  end
37
40
  end
38
41
  end
@@ -1,8 +1,8 @@
1
- <form action="<%= url_for(:action => :authorize) %>" method="post" id="oauth_authorize">
1
+ <% form_for(url_for(:action => :authorize), :html => {:id => 'oauth_authorize_form'}) do |f| -%>
2
2
  Do you wish to allow the service named '<%= @client.name %>' to access this application on your behalf? <input type="checkbox" name="authorize" id="authorize" value="1" />
3
3
  <input type="hidden" name="client_id" id="client_id" value="<%= params[:client_id] %>" />
4
4
  <input type="hidden" name="redirect_uri" id="redirect_uri" value="<%= params[:redirect_uri] %>" />
5
5
  <input type="hidden" name="response_type" id="response_type" value="<%= params[:response_type] %>" />
6
6
  <input type="hidden" name="state" id="state" value="<%= params[:state] %>" />
7
7
  <input type="submit" value="Submit" />
8
- </form>
8
+ <% end -%>
@@ -1,20 +1,20 @@
1
1
  <h1>Editing oauth_client</h1>
2
2
 
3
- <% form_for(@oauth_client) do |f| %>
3
+ <% form_for(@oauth_client, :html => {:id => 'oauth_client_edit_form', :class => nil}) do |f| %>
4
4
  <%= f.error_messages %>
5
5
 
6
- <p>
7
- <%= f.label :name %><br />
6
+ <div>
7
+ <%= f.label :name %>
8
8
  <%= f.text_field :name %>
9
- </p>
10
- <p>
11
- <%= f.label :redirect_uri %><br />
9
+ </div>
10
+ <div>
11
+ <%= f.label :redirect_uri %>
12
12
  <%= f.text_field :redirect_uri %>
13
- </p>
14
- <p>
13
+ </div>
14
+ <div>
15
15
  <%= f.submit 'Update' %>
16
- </p>
16
+ </div>
17
17
  <% end %>
18
18
 
19
- <%= link_to 'Show', @oauth_client %> |
20
- <%= link_to 'Back', oauth_clients_path %>
19
+ <%= link_to 'Show', @oauth_client, :class => 'show_link' %> |
20
+ <%= link_to 'Back', oauth_clients_path, :class => 'back_link' %>
@@ -1,11 +1,12 @@
1
1
  <h1>Listing oauth_clients</h1>
2
2
 
3
- <table>
3
+ <table id="oauth_clients_table" class="list_table">
4
4
  <tr>
5
5
  <th>Name</th>
6
6
  <th>Client id</th>
7
7
  <th>Client secret</th>
8
8
  <th>Redirect URI</th>
9
+ <th>Actions</th>
9
10
  </tr>
10
11
 
11
12
  <% @oauth_clients.each do |oauth_client| %>
@@ -14,13 +15,14 @@
14
15
  <td><%=h oauth_client.client_id %></td>
15
16
  <td><%=h oauth_client.client_secret %></td>
16
17
  <td><%=h oauth_client.redirect_uri %></td>
17
- <td><%= link_to 'Show', oauth_client %></td>
18
- <td><%= link_to 'Edit', edit_oauth_client_path(oauth_client) %></td>
19
- <td><%= link_to 'Destroy', oauth_client, :confirm => 'Are you sure?', :method => :delete %></td>
18
+ <td>
19
+ <%= link_to 'Edit', edit_oauth_client_path(oauth_client), :class => 'edit_link' %>
20
+ <%= link_to 'Destroy', oauth_client, :confirm => 'Are you sure?', :method => :delete, :class => 'delete_link' %>
21
+ </td>
20
22
  </tr>
21
23
  <% end %>
22
24
  </table>
23
25
 
24
26
  <br />
25
27
 
26
- <%= link_to 'New oauth_client', new_oauth_client_path %>
28
+ <%= link_to 'New oauth_client', new_oauth_client_path, :class => 'link_as_button', :id => 'new_oauth_client_button' %>
@@ -1,19 +1,21 @@
1
1
  <h1>New oauth_client</h1>
2
2
 
3
- <% form_for(@oauth_client) do |f| %>
3
+ <!-- add in an ID for the form -->
4
+
5
+ <% form_for(@oauth_client, :html => {:id => 'oauth_client_create_form', :class => nil}) do |f| %>
4
6
  <%= f.error_messages %>
5
7
 
6
- <p>
7
- <%= f.label :name %><br />
8
+ <div>
9
+ <%= f.label :name %>
8
10
  <%= f.text_field :name %>
9
- </p>
10
- <p>
11
- <%= f.label :redirect_uri %><br />
11
+ </div>
12
+ <div>
13
+ <%= f.label :redirect_uri %>
12
14
  <%= f.text_field :redirect_uri %>
13
- </p>
14
- <p>
15
+ </div>
16
+ <div>
15
17
  <%= f.submit 'Create' %>
16
- </p>
18
+ </div>
17
19
  <% end %>
18
20
 
19
- <%= link_to 'Back', oauth_clients_path %>
21
+ <%= link_to 'Back', oauth_clients_path, :class => 'back_link' %>
@@ -1,4 +1,4 @@
1
- <table>
1
+ <table id="oauth_user_token_table" class="list_table">
2
2
  <tr>
3
3
  <th>Client</th>
4
4
  <th>Token</th>
@@ -8,7 +8,7 @@
8
8
  <tr>
9
9
  <td><%= token.oauth_client.name %></td>
10
10
  <td><%= token.access_token %></td>
11
- <td><%= link_to('Destroy', {:action => :revoke, :token_id => token.id, :controller => 'Oauth2::Provider::OauthUserTokens'}, {:confirm => 'Are you sure?', :method => :delete})%></td>
11
+ <td><%= link_to('Destroy', {:action => :revoke, :token_id => token.id, :controller => 'Oauth2::Provider::OauthUserTokens'}, {:confirm => 'Are you sure?', :method => :delete, :class => 'delete_link'})%></td>
12
12
  </tr>
13
13
  <% end -%>
14
14
  </table>
data/config/routes.rb CHANGED
@@ -2,13 +2,18 @@
2
2
  # Licenced under the MIT License (http://www.opensource.org/licenses/mit-license.php)
3
3
 
4
4
  ActionController::Routing::Routes.draw do |map|
5
-
6
- map.resources :oauth_clients, :controller => 'Oauth2::Provider::OauthClients', :as => 'oauth/clients'
7
-
8
- map.connect '/oauth/authorize', :controller => 'Oauth2::Provider::OauthAuthorize', :action => :authorize, :conditions => {:method => :post}
9
- map.connect '/oauth/authorize', :controller => 'Oauth2::Provider::OauthAuthorize', :action => :index, :conditions => {:method => :get}
10
- map.connect '/oauth/token', :controller => 'Oauth2::Provider::OauthToken', :action => :get_token, :conditions => {:method => :post}
11
-
12
- map.connect '/oauth/user_tokens/revoke/:token_id', :controller => 'Oauth2::Provider::OauthUserTokens', :action => :revoke, :conditions => {:method => :delete}
13
- map.connect '/oauth/user_tokens', :controller => 'Oauth2::Provider::OauthUserTokens', :action => :index, :conditions => {:method => :get}
5
+
6
+ admin_prefix=ENV['ADMIN_OAUTH_URL_PREFIX']
7
+
8
+ map.resources :oauth_clients, :controller => 'Oauth2::Provider::OauthClients', :as => "#{admin_prefix}oauth/clients"
9
+
10
+ user_prefix=ENV['USER_OAUTH_URL_PREFIX']
11
+
12
+ map.connect "#{user_prefix}/oauth/authorize", :controller => 'Oauth2::Provider::OauthAuthorize', :action => :authorize, :conditions => {:method => :post}
13
+ map.connect "#{user_prefix}/oauth/authorize", :controller => 'Oauth2::Provider::OauthAuthorize', :action => :index, :conditions => {:method => :get}
14
+ map.connect "#{user_prefix}/oauth/token", :controller => 'Oauth2::Provider::OauthToken', :action => :get_token, :conditions => {:method => :post}
15
+
16
+ map.connect "#{user_prefix}/oauth/user_tokens/revoke/:token_id", :controller => 'Oauth2::Provider::OauthUserTokens', :action => :revoke, :conditions => {:method => :delete}
17
+ map.connect "#{user_prefix}/oauth/user_tokens", :controller => 'Oauth2::Provider::OauthUserTokens', :action => :index, :conditions => {:method => :get}
18
+
14
19
  end
@@ -7,7 +7,7 @@ class CreateOauthAuthorizations < ActiveRecord::Migration
7
7
  t.string :user_id
8
8
  t.integer :oauth_client_id
9
9
  t.string :code
10
- t.timestamp :expires_at
10
+ t.integer :expires_at
11
11
 
12
12
  t.timestamps
13
13
  end
@@ -8,7 +8,7 @@ class CreateOauthTokens < ActiveRecord::Migration
8
8
  t.integer :oauth_client_id
9
9
  t.string :access_token
10
10
  t.string :refresh_token
11
- t.timestamp :expires_at
11
+ t.integer :expires_at
12
12
 
13
13
  t.timestamps
14
14
  end
data/init.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # Copyright (c) 2010 ThoughtWorks Inc. (http://thoughtworks.com)
2
2
  # Licenced under the MIT License (http://www.opensource.org/licenses/mit-license.php)
3
3
 
4
- # DO NOT REMOVE
5
- # this file is required when this plugin is used as a plugin!
4
+ # !!perform any initialization in oauth2_provider!!
5
+ require 'oauth2_provider'
@@ -0,0 +1,108 @@
1
+ # Copyright (c) 2010 ThoughtWorks Inc. (http://thoughtworks.com)
2
+ # Licenced under the MIT License (http://www.opensource.org/licenses/mit-license.php)
3
+
4
+ if defined?(ActiveRecord)
5
+ module Oauth2
6
+ module Provider
7
+ class ARDatasource
8
+
9
+ class OauthClientDto < ActiveRecord::Base
10
+ set_table_name :oauth_clients
11
+ end
12
+
13
+ class OauthAuthorizationDto < ActiveRecord::Base
14
+ set_table_name :oauth_authorizations
15
+ end
16
+
17
+ class OauthTokenDto < ActiveRecord::Base
18
+ set_table_name :oauth_tokens
19
+ end
20
+
21
+ # used in tests, use it to clear datasource
22
+ def reset
23
+
24
+ end
25
+
26
+ def find_oauth_client_by_id(id)
27
+ OauthClientDto.find_by_id(id)
28
+ end
29
+
30
+ def find_oauth_client_by_client_id(client_id)
31
+ OauthClientDto.find_by_client_id(client_id)
32
+ end
33
+
34
+ def find_all_oauth_client
35
+ OauthClientDto.all
36
+ end
37
+
38
+ def save_oauth_client(attrs)
39
+ save(OauthClientDto, attrs)
40
+ end
41
+
42
+ def delete_oauth_client(id)
43
+ OauthClientDto.delete(id)
44
+ end
45
+
46
+ def find_all_oauth_authorization_by_oauth_client_id(client_id)
47
+ OauthAuthorizationDto.find_all_by_oauth_client_id(client_id)
48
+ end
49
+
50
+ def find_oauth_authorization_by_id(id)
51
+ OauthAuthorizationDto.find_by_id(id)
52
+ end
53
+
54
+ def find_oauth_authorization_by_code(code)
55
+ OauthAuthorizationDto.find_by_code(code)
56
+ end
57
+
58
+ def save_oauth_authorization(attrs)
59
+ save(OauthAuthorizationDto, attrs)
60
+ end
61
+
62
+ def delete_oauth_authorization(id)
63
+ OauthAuthorizationDto.delete(id)
64
+ end
65
+
66
+ def find_oauth_token_by_id(id)
67
+ OauthTokenDto.find_by_id(id)
68
+ end
69
+
70
+ def find_all_oauth_token_by_oauth_client_id(client_id)
71
+ OauthTokenDto.find_all_by_oauth_client_id(client_id)
72
+ end
73
+
74
+ def find_all_oauth_token_by_user_id(user_id)
75
+ OauthTokenDto.find_all_by_user_id(user_id)
76
+ end
77
+
78
+ def find_oauth_token_by_access_token(access_token)
79
+ OauthTokenDto.find_by_access_token(access_token)
80
+ end
81
+
82
+ def find_oauth_token_by_refresh_token(refresh_token)
83
+ OauthTokenDto.find_by_refresh_token(refresh_token)
84
+ end
85
+
86
+ def save_oauth_token(attrs)
87
+ save(OauthTokenDto, attrs)
88
+ end
89
+
90
+ def delete_oauth_token(id)
91
+ OauthTokenDto.delete(id)
92
+ end
93
+
94
+ private
95
+
96
+ def save(dto_klass, attrs)
97
+ dto = dto_klass.find_by_id(attrs[:id])
98
+ if dto
99
+ dto.update_attributes(attrs)
100
+ else
101
+ dto = dto_klass.create(attrs)
102
+ end
103
+ dto
104
+ end
105
+ end
106
+ end
107
+ end
108
+ end
@@ -29,8 +29,8 @@ module Oauth2
29
29
  header_field = request.headers["Authorization"]
30
30
 
31
31
  if header_field =~ /Token token="(.*)"/
32
- token = OauthToken.find_by_access_token($1)
33
- token.user_id if token
32
+ token = OauthToken.find_one(:access_token, $1)
33
+ token.user_id if (token && !token.expired?)
34
34
  end
35
35
  end
36
36
 
@@ -0,0 +1,121 @@
1
+ # Copyright (c) 2010 ThoughtWorks Inc. (http://thoughtworks.com)
2
+ # Licenced under the MIT License (http://www.opensource.org/licenses/mit-license.php)
3
+
4
+ require 'ostruct'
5
+ module Oauth2
6
+ module Provider
7
+ class InMemoryDatasource
8
+
9
+ class MyStruct < OpenStruct
10
+
11
+ attr_accessor :id
12
+
13
+ def initialize(id, attrs)
14
+ self.id = id
15
+ super(attrs)
16
+ end
17
+ end
18
+
19
+ @@id = 0
20
+
21
+ @@oauth_clients = []
22
+ @@oauth_tokens = []
23
+ @@oauth_authorizations = []
24
+
25
+ def reset
26
+ @@id = 0
27
+ @@oauth_clients = []
28
+ @@oauth_tokens = []
29
+ @@oauth_authorizations = []
30
+ end
31
+
32
+ def find_oauth_client_by_id(id)
33
+ @@oauth_clients.find{|i| i.id.to_s == id.to_s}
34
+ end
35
+
36
+ def find_oauth_client_by_client_id(client_id)
37
+ @@oauth_clients.find{|i| i.client_id.to_s == client_id.to_s}
38
+ end
39
+
40
+ def find_all_oauth_client
41
+ @@oauth_clients
42
+ end
43
+
44
+ def save_oauth_client(attrs)
45
+ save(@@oauth_clients, attrs)
46
+ end
47
+
48
+ def delete_oauth_client(id)
49
+ @@oauth_clients.delete_if {|i| i.id.to_s == id.to_s}
50
+ end
51
+
52
+ def find_all_oauth_authorization_by_oauth_client_id(client_id)
53
+ @@oauth_authorizations.select {|i| i.oauth_client_id.to_s == client_id.to_s}
54
+ end
55
+
56
+ def find_oauth_authorization_by_id(id)
57
+ @@oauth_authorizations.find{|i| i.id.to_s == id.to_s}
58
+ end
59
+
60
+ def find_oauth_authorization_by_code(code)
61
+ @@oauth_authorizations.find{|i| i.code.to_s == code.to_s}
62
+ end
63
+
64
+ def save_oauth_authorization(attrs)
65
+ save(@@oauth_authorizations, attrs)
66
+ end
67
+
68
+ def delete_oauth_authorization(id)
69
+ @@oauth_authorizations.delete_if {|i| i.id.to_s == id.to_s}
70
+ end
71
+
72
+ def find_oauth_token_by_id(id)
73
+ @@oauth_tokens.find{|i| i.id.to_s == id.to_s}
74
+ end
75
+
76
+ def find_all_oauth_token_by_oauth_client_id(client_id)
77
+ @@oauth_tokens.select {|i| i.oauth_client_id.to_s == client_id.to_s}
78
+ end
79
+
80
+ def find_all_oauth_token_by_user_id(user_id)
81
+ @@oauth_tokens.select {|i| i.user_id.to_s == user_id.to_s}
82
+ end
83
+
84
+ def find_oauth_token_by_access_token(access_token)
85
+ @@oauth_tokens.find {|i| i.access_token.to_s == access_token.to_s}
86
+ end
87
+
88
+ def find_oauth_token_by_refresh_token(refresh_token)
89
+ @@oauth_tokens.find {|i| i.refresh_token.to_s == refresh_token.to_s}
90
+ end
91
+
92
+ def save_oauth_token(attrs)
93
+ save(@@oauth_tokens, attrs)
94
+ end
95
+
96
+ def delete_oauth_token(id)
97
+ @@oauth_tokens.delete_if { |i| i.id.to_s == id .to_s}
98
+ end
99
+
100
+ private
101
+ def save(collection, attrs)
102
+ dto = collection.find {|i| i.id.to_s == attrs[:id].to_s}
103
+
104
+ if dto
105
+ attrs.each do |k, v|
106
+ dto.send("#{k}=", v)
107
+ end
108
+ else
109
+ dto = MyStruct.new(next_id, attrs)
110
+ collection << dto
111
+ end
112
+ dto
113
+ end
114
+
115
+ def next_id
116
+ @@id += 1
117
+ @@id.to_s
118
+ end
119
+ end
120
+ end
121
+ end
@@ -0,0 +1,204 @@
1
+ # Copyright (c) 2010 ThoughtWorks Inc. (http://thoughtworks.com)
2
+ # Licenced under the MIT License (http://www.opensource.org/licenses/mit-license.php)
3
+
4
+ module Oauth2
5
+ module Provider
6
+ class NotFoundException < StandardError
7
+ end
8
+
9
+ class RecordNotSaved < StandardError
10
+ end
11
+
12
+ class ModelBase
13
+ include Validatable
14
+ CONVERTORS = {
15
+ :integer => Proc.new { |v| v.to_i },
16
+ :string => Proc.new { |v| v.to_s }
17
+ }.with_indifferent_access
18
+
19
+ class_inheritable_hash :db_columns
20
+ self.db_columns = {}
21
+
22
+ def self.columns(*names)
23
+ names.each do |name|
24
+ column_name, convertor = (Hash === name) ?
25
+ [name.keys.first, CONVERTORS[name.values.first]] :
26
+ [name, CONVERTORS[:string]]
27
+ attr_accessor column_name
28
+ self.db_columns[column_name.to_s] = convertor
29
+ end
30
+ end
31
+
32
+ columns :id
33
+
34
+ def initialize(attributes={})
35
+ assign_attributes(attributes)
36
+ end
37
+
38
+ cattr_accessor :datasource
39
+
40
+ def self.datasource=(ds)
41
+ @@datasource = case ds
42
+ when NilClass
43
+ default_datasource
44
+ when String
45
+ eval(ds).new
46
+ when Class
47
+ ds.new
48
+ else
49
+ ds
50
+ end
51
+ end
52
+
53
+ def self.datasource
54
+ @@datasource ||= default_datasource
55
+ end
56
+
57
+ def datasource
58
+ self.class.datasource
59
+ end
60
+
61
+ def self.default_datasource
62
+ if defined?(ActiveRecord)
63
+ ARDatasource.new
64
+ else
65
+ unless ENV['LOAD_OAUTH_SILENTLY']
66
+ puts "*"*80
67
+ puts "*** Activerecord is not defined! Using InMemoryDatasource, which will not persist across application restarts!! ***"
68
+ puts "*"*80
69
+ end
70
+ InMemoryDatasource.new
71
+ end
72
+ end
73
+
74
+ def self.find(id)
75
+ find_by_id(id) || raise(NotFoundException.new("Record not found!"))
76
+ end
77
+
78
+ def self.find_by_id(id)
79
+ find_one(:id, id)
80
+ end
81
+
82
+ def self.find_all_with(column_name, column_value)
83
+ datasource.send("find_all_#{compact_name}_by_#{column_name}", convert(column_name, column_value)).collect do |dto|
84
+ new.update_from_dto(dto)
85
+ end
86
+ end
87
+
88
+ def self.find_one(column_name, column_value)
89
+ if dto = datasource.send("find_#{compact_name}_by_#{column_name}", convert(column_name, column_value))
90
+ self.new.update_from_dto(dto)
91
+ end
92
+ end
93
+
94
+ def self.all
95
+ datasource.send("find_all_#{compact_name}").collect do |dto|
96
+ new.update_from_dto(dto)
97
+ end
98
+ end
99
+
100
+ def self.count
101
+ all.size
102
+ end
103
+
104
+ def self.size
105
+ all.size
106
+ end
107
+
108
+ def self.compact_name
109
+ self.name.split('::').last.underscore
110
+ end
111
+
112
+ def self.create(attributes={})
113
+ client = self.new(attributes)
114
+ client.save
115
+ client
116
+ end
117
+
118
+ def self.create!(attributes={})
119
+ client = self.new(attributes)
120
+ client.save!
121
+ client
122
+ end
123
+
124
+ def update_attributes(attributes={})
125
+ assign_attributes(attributes)
126
+ save
127
+ end
128
+
129
+ def save!
130
+ save || raise(RecordNotSaved.new("Could not save model!"))
131
+ end
132
+
133
+ def save
134
+ before_create if new_record?
135
+ attrs = db_columns.keys.inject({}) do |result, column_name|
136
+ result[column_name] = read_attribute(column_name)
137
+ result
138
+ end
139
+
140
+ if self.valid?
141
+ dto = datasource.send("save_#{self.class.compact_name}", attrs.with_indifferent_access)
142
+ update_from_dto(dto)
143
+ return true
144
+ end
145
+ false
146
+ end
147
+
148
+ def reload
149
+ update_from_dto(self.class.find(id))
150
+ end
151
+
152
+ def destroy
153
+ before_destroy
154
+ datasource.send("delete_#{self.class.compact_name}", convert(:id, id) )
155
+ end
156
+
157
+ def before_create
158
+ # for subclasses to override to support hooks.
159
+ end
160
+
161
+ def before_destroy
162
+ # for subclasses to override to support hooks.
163
+ end
164
+
165
+ def update_from_dto(dto)
166
+ db_columns.keys.each do |column_name|
167
+ write_attribute(column_name, dto.send(column_name))
168
+ end
169
+ self
170
+ end
171
+
172
+ def new_record?
173
+ id.nil?
174
+ end
175
+
176
+ def to_param
177
+ id.nil? ? nil: id.to_s
178
+ end
179
+
180
+ def assign_attributes(attrs={})
181
+ attrs.each { |k, v| write_attribute(k, v) }
182
+ end
183
+
184
+ private
185
+
186
+ def self.convert(column_name, value)
187
+ db_columns[column_name.to_s].call(value)
188
+ end
189
+
190
+ def convert(column_name, value)
191
+ self.class.convert(column_name, value)
192
+ end
193
+
194
+ def read_attribute(column_name)
195
+ convert(column_name, self.send(column_name))
196
+ end
197
+
198
+ def write_attribute(column_name, value)
199
+ self.send("#{column_name}=", convert(column_name, value))
200
+ end
201
+
202
+ end
203
+ end
204
+ end
@@ -1,5 +1,20 @@
1
1
  # Copyright (c) 2010 ThoughtWorks Inc. (http://thoughtworks.com)
2
2
  # Licenced under the MIT License (http://www.opensource.org/licenses/mit-license.php)
3
3
 
4
- # DO NOT REMOVE
5
- # this file is required when this plugin is used as a gem!
4
+ require 'oauth2/provider/a_r_datasource'
5
+ require 'oauth2/provider/in_memory_datasource'
6
+ require 'oauth2/provider/model_base'
7
+ require 'oauth2/provider/clock'
8
+
9
+ Oauth2::Provider::ModelBase.datasource = ENV["OAUTH2_PROVIDER_DATASOURCE"]
10
+
11
+ unless ENV['LOAD_OAUTH_SILENTLY']
12
+ puts "*"*80
13
+ puts "*** Using data source: #{Oauth2::Provider::ModelBase.datasource.class}"
14
+ puts "*"*80
15
+ end
16
+
17
+ Dir[File.join(File.dirname(__FILE__), "..", "app", "**", '*.rb')].each do |rb_file|
18
+ require File.expand_path(rb_file)
19
+ end
20
+
@@ -2,15 +2,15 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = %q{oauth2_provider}
5
- s.version = "0.1.0"
5
+ s.version = "0.2.0"
6
6
 
7
7
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
8
  s.authors = ["ThoughtWorks, Inc."]
9
- s.date = %q{2010-07-23}
9
+ s.date = %q{2010-08-31}
10
10
  s.description = %q{A Rails plugin to OAuth v2.0 enable your rails application. This plugin implements v09 of the OAuth2 draft spec http://tools.ietf.org/html/draft-ietf-oauth-v2-09.}
11
11
  s.email = %q{ketan@thoughtworks.com}
12
12
  s.extra_rdoc_files = ["README.textile", "MIT-LICENSE.txt"]
13
- s.files = ["app/controllers/oauth2/provider/oauth_authorize_controller.rb", "app/controllers/oauth2/provider/oauth_clients_controller.rb", "app/controllers/oauth2/provider/oauth_token_controller.rb", "app/controllers/oauth2/provider/oauth_user_tokens_controller.rb", "app/models/oauth2/provider/oauth_authorization.rb", "app/models/oauth2/provider/oauth_client.rb", "app/models/oauth2/provider/oauth_token.rb", "app/views/oauth2/provider/layouts/oauth_clients.html.erb", "app/views/oauth2/provider/oauth_authorize/index.html.erb", "app/views/oauth2/provider/oauth_clients/edit.html.erb", "app/views/oauth2/provider/oauth_clients/index.html.erb", "app/views/oauth2/provider/oauth_clients/new.html.erb", "app/views/oauth2/provider/oauth_clients/show.html.erb", "app/views/oauth2/provider/oauth_user_tokens/index.html.erb", "config/routes.rb", "generators/oauth2_provider/oauth2_provider_generator.rb", "generators/oauth2_provider/templates/config/initializers/oauth2_provider.rb", "generators/oauth2_provider/templates/db/migrate/create_oauth_authorizations.rb", "generators/oauth2_provider/templates/db/migrate/create_oauth_clients.rb", "generators/oauth2_provider/templates/db/migrate/create_oauth_tokens.rb", "init.rb", "lib/oauth2/provider/application_controller_methods.rb", "lib/oauth2/provider/clock.rb", "lib/oauth2_provider.rb", "MIT-LICENSE.txt", "oauth2_provider.gemspec", "README.textile", "tasks/gem.rake", "CHANGELOG"]
13
+ s.files = ["app/controllers/oauth2/provider/oauth_authorize_controller.rb", "app/controllers/oauth2/provider/oauth_clients_controller.rb", "app/controllers/oauth2/provider/oauth_token_controller.rb", "app/controllers/oauth2/provider/oauth_user_tokens_controller.rb", "app/models/oauth2/provider/oauth_authorization.rb", "app/models/oauth2/provider/oauth_client.rb", "app/models/oauth2/provider/oauth_token.rb", "app/views/oauth2/provider/layouts/oauth_clients.html.erb", "app/views/oauth2/provider/oauth_authorize/index.html.erb", "app/views/oauth2/provider/oauth_clients/edit.html.erb", "app/views/oauth2/provider/oauth_clients/index.html.erb", "app/views/oauth2/provider/oauth_clients/new.html.erb", "app/views/oauth2/provider/oauth_clients/show.html.erb", "app/views/oauth2/provider/oauth_user_tokens/index.html.erb", "config/routes.rb", "generators/oauth2_provider/oauth2_provider_generator.rb", "generators/oauth2_provider/templates/config/initializers/oauth2_provider.rb", "generators/oauth2_provider/templates/db/migrate/create_oauth_authorizations.rb", "generators/oauth2_provider/templates/db/migrate/create_oauth_clients.rb", "generators/oauth2_provider/templates/db/migrate/create_oauth_tokens.rb", "init.rb", "lib/oauth2/provider/a_r_datasource.rb", "lib/oauth2/provider/application_controller_methods.rb", "lib/oauth2/provider/clock.rb", "lib/oauth2/provider/in_memory_datasource.rb", "lib/oauth2/provider/model_base.rb", "lib/oauth2_provider.rb", "MIT-LICENSE.txt", "oauth2_provider.gemspec", "README.textile", "tasks/gem.rake", "CHANGELOG"]
14
14
  s.homepage = %q{http://github.com/ThoughtWorksStudios/oauth2_provider}
15
15
  s.require_paths = ["lib"]
16
16
  s.rubygems_version = %q{1.3.7}
data/tasks/gem.rake CHANGED
@@ -35,7 +35,7 @@ namespace :release do
35
35
 
36
36
  spec = Gem::Specification.new do |s|
37
37
  s.name = "oauth2_provider"
38
- s.version = "0.1.0"
38
+ s.version = "0.2.0"
39
39
  s.author = "ThoughtWorks, Inc."
40
40
  s.email = "ketan@thoughtworks.com"
41
41
  s.homepage = "http://github.com/ThoughtWorksStudios/oauth2_provider"
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: oauth2_provider
3
3
  version: !ruby/object:Gem::Version
4
- hash: 27
4
+ hash: 23
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
- - 1
8
+ - 2
9
9
  - 0
10
- version: 0.1.0
10
+ version: 0.2.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - ThoughtWorks, Inc.
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2010-07-23 00:00:00 -07:00
18
+ date: 2010-08-31 00:00:00 -07:00
19
19
  default_executable:
20
20
  dependencies: []
21
21
 
@@ -50,8 +50,11 @@ files:
50
50
  - generators/oauth2_provider/templates/db/migrate/create_oauth_clients.rb
51
51
  - generators/oauth2_provider/templates/db/migrate/create_oauth_tokens.rb
52
52
  - init.rb
53
+ - lib/oauth2/provider/a_r_datasource.rb
53
54
  - lib/oauth2/provider/application_controller_methods.rb
54
55
  - lib/oauth2/provider/clock.rb
56
+ - lib/oauth2/provider/in_memory_datasource.rb
57
+ - lib/oauth2/provider/model_base.rb
55
58
  - lib/oauth2_provider.rb
56
59
  - MIT-LICENSE.txt
57
60
  - oauth2_provider.gemspec