devise_oauth2_providable 1.0.1 → 1.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,10 +1,7 @@
1
- require 'expirable_token'
2
-
3
1
  class Devise::Oauth2Providable::AccessToken < ActiveRecord::Base
4
- include ExpirableToken
5
- self.default_lifetime = 15.minutes
2
+ expires_according_to :access_token_expires_in
6
3
 
7
- before_validation :restrict_expires_at, :if => :refresh_token
4
+ before_validation :restrict_expires_at, :on => :create, :if => :refresh_token
8
5
  belongs_to :refresh_token
9
6
 
10
7
  def token_response
@@ -20,6 +17,6 @@ class Devise::Oauth2Providable::AccessToken < ActiveRecord::Base
20
17
  private
21
18
 
22
19
  def restrict_expires_at
23
- self.expires_at = [self.expires_at, refresh_token.expires_at].min
20
+ self.expires_at = [self.expires_at, refresh_token.expires_at].compact.min
24
21
  end
25
22
  end
@@ -1,7 +1,6 @@
1
- require 'expirable_token'
2
-
3
1
  class Devise::Oauth2Providable::AuthorizationCode < ActiveRecord::Base
4
- include ExpirableToken
2
+ expires_according_to :authorization_code_expires_in
3
+
5
4
  def access_token
6
5
  @access_token ||= expired! && user.access_tokens.create(:client => client)
7
6
  end
@@ -1,7 +1,5 @@
1
- require 'expirable_token'
2
-
3
1
  class Devise::Oauth2Providable::RefreshToken < ActiveRecord::Base
4
- include ExpirableToken
5
- self.default_lifetime = 1.month
2
+ expires_according_to :refresh_token_expires_in
3
+
6
4
  has_many :access_tokens
7
5
  end
@@ -21,6 +21,8 @@ Gem::Specification.new do |s|
21
21
  s.add_development_dependency(%q<sqlite3>, ['1.3.4'])
22
22
  s.add_development_dependency(%q<shoulda-matchers>, ['1.0.0.beta3'])
23
23
  s.add_development_dependency(%q<pry>, ['0.9.6.2'])
24
+ s.add_development_dependency(%q<factory_girl>, ['2.2.0'])
25
+ s.add_development_dependency(%q<factory_girl_rspec>, ['0.0.1'])
24
26
 
25
27
  s.files = `git ls-files`.split("\n")
26
28
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
@@ -1,9 +1,14 @@
1
1
  module Devise
2
2
  module Oauth2Providable
3
3
  class Engine < Rails::Engine
4
+ config.devise_oauth2_providable = ActiveSupport::OrderedOptions.new
5
+ config.devise_oauth2_providable.access_token_expires_in = 15.minutes
6
+ config.devise_oauth2_providable.refresh_token_expires_in = 1.month
7
+ config.devise_oauth2_providable.authorization_code_expires_in = 1.minute
8
+
4
9
  engine_name 'oauth2'
5
10
  isolate_namespace Devise::Oauth2Providable
6
- initializer "devise_oauth2_providable.initialize_application" do |app|
11
+ initializer "devise_oauth2_providable.initialize_application", :before=> :load_config_initializers do |app|
7
12
  app.config.filter_parameters << :client_secret
8
13
  end
9
14
  end
@@ -0,0 +1,57 @@
1
+ require 'active_support/concern'
2
+ require 'active_record'
3
+
4
+ module Devise
5
+ module Oauth2Providable
6
+ module ExpirableToken
7
+ extend ActiveSupport::Concern
8
+
9
+ module ClassMethods
10
+ def expires_according_to(config_name)
11
+ cattr_accessor :default_lifetime
12
+ self.default_lifetime = Rails.application.config.devise_oauth2_providable[config_name]
13
+
14
+ belongs_to :user
15
+ belongs_to :client
16
+
17
+ after_initialize :init_token, :on => :create, :unless => :token?
18
+ after_initialize :init_expires_at, :on => :create, :unless => :expires_at?
19
+ validates :expires_at, :presence => true
20
+ validates :client, :presence => true
21
+ validates :token, :presence => true, :uniqueness => true
22
+
23
+ scope :not_expired, lambda {
24
+ where(self.arel_table[:expires_at].gteq(Time.now.utc))
25
+ }
26
+ default_scope not_expired
27
+
28
+ include LocalInstanceMethods
29
+ end
30
+ end
31
+
32
+ module LocalInstanceMethods
33
+ # number of seconds until the token expires
34
+ def expires_in
35
+ (expires_at - Time.now.utc).to_i
36
+ end
37
+
38
+ # forcefully expire the token
39
+ def expired!
40
+ self.expires_at = Time.now.utc
41
+ self.save!
42
+ end
43
+
44
+ private
45
+
46
+ def init_token
47
+ self.token = Devise::Oauth2Providable.random_id
48
+ end
49
+ def init_expires_at
50
+ self.expires_at = self.default_lifetime.from_now
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
56
+
57
+ ActiveRecord::Base.send :include, Devise::Oauth2Providable::ExpirableToken
@@ -8,7 +8,7 @@ module Devise
8
8
  end
9
9
 
10
10
  def authenticate!
11
- if client && code = client.authorization_codes.valid.find_by_token(params[:code])
11
+ if client && code = client.authorization_codes.find_by_token(params[:code])
12
12
  success! code.user
13
13
  elsif !halted?
14
14
  oauth_error! :invalid_grant, 'invalid authorization code request'
@@ -9,7 +9,7 @@ module Devise
9
9
  end
10
10
  def authenticate!
11
11
  @req.setup!
12
- token = Devise::Oauth2Providable::AccessToken.valid.find_by_token @req.access_token
12
+ token = Devise::Oauth2Providable::AccessToken.find_by_token @req.access_token
13
13
  env[Devise::Oauth2Providable::CLIENT_ENV_REF] = token.client if token
14
14
  resource = token ? token.user : nil
15
15
  if validate(resource)
@@ -8,7 +8,7 @@ module Devise
8
8
  end
9
9
 
10
10
  def authenticate!
11
- if client && refresh_token = client.refresh_tokens.valid.find_by_token(params[:refresh_token])
11
+ if client && refresh_token = client.refresh_tokens.find_by_token(params[:refresh_token])
12
12
  env[Devise::Oauth2Providable::REFRESH_TOKEN_ENV_REF] = refresh_token
13
13
  success! refresh_token.user
14
14
  elsif !halted?
@@ -1,5 +1,5 @@
1
1
  module Devise
2
2
  module Oauth2Providable
3
- VERSION = "1.0.1"
3
+ VERSION = "1.0.2"
4
4
  end
5
5
  end
@@ -1,6 +1,7 @@
1
1
  require 'devise'
2
2
  require 'rack/oauth2'
3
3
  require 'devise/oauth2_providable/engine'
4
+ require 'devise/oauth2_providable/expirable_token'
4
5
  require 'devise/oauth2_providable/strategies/oauth2_providable_strategy'
5
6
  require 'devise/oauth2_providable/strategies/oauth2_password_grant_type_strategy'
6
7
  require 'devise/oauth2_providable/strategies/oauth2_refresh_token_grant_type_strategy'
@@ -3,8 +3,8 @@ require 'spec_helper'
3
3
  describe ProtectedController do
4
4
 
5
5
  describe 'get :index' do
6
+ with :client
6
7
  before do
7
- client = Devise::Oauth2Providable::Client.create! :name => 'test', :redirect_uri => 'http://localhost:3000', :website => 'http://localhost'
8
8
  @user = User.create! :email => 'foo@example.com'
9
9
  @token = Devise::Oauth2Providable::AccessToken.create! :client => client, :user => @user
10
10
  end
@@ -40,6 +40,12 @@ module Dummy
40
40
 
41
41
  # Version of your assets, change this if you want to expire all your assets
42
42
  config.assets.version = '1.0'
43
+
44
+
45
+ # (optional) configure token expiration
46
+ # config.devise_oauth2_providable.access_token_expires_in = 1.second # 15.minute default
47
+ # config.devise_oauth2_providable.refresh_token_expires_in = 1.minute # 1.month default
48
+ # config.devise_oauth2_providable.authorization_token_expires_in = 5.seconds # 1.minute default
43
49
  end
44
50
  end
45
51
 
@@ -0,0 +1,5 @@
1
+ Factory.define :client, :class => 'Devise::Oauth2Providable::Client' do |f|
2
+ f.name 'test'
3
+ f.website 'http://localhost'
4
+ f.redirect_uri 'http://localhost:3000'
5
+ end
@@ -3,15 +3,15 @@ require 'spec_helper'
3
3
  describe Devise::Strategies::Oauth2AuthorizationCodeGrantTypeStrategy do
4
4
  describe 'POST /oauth2/token' do
5
5
  describe 'with grant_type=authorization_code' do
6
+ with :client
6
7
  context 'with valid params' do
7
8
  before do
8
9
  @user = User.create! :email => 'ryan@socialcast.com', :password => 'test'
9
- @client = Devise::Oauth2Providable::Client.create! :name => 'example', :redirect_uri => 'http://localhost', :website => 'http://localhost'
10
- @authorization_code = @user.authorization_codes.create(:client_id => @client, :redirect_uri => @client.redirect_uri)
10
+ @authorization_code = @user.authorization_codes.create(:client_id => client, :redirect_uri => client.redirect_uri)
11
11
  params = {
12
12
  :grant_type => 'authorization_code',
13
- :client_id => @client.identifier,
14
- :client_secret => @client.secret,
13
+ :client_id => client.identifier,
14
+ :client_secret => client.secret,
15
15
  :code => @authorization_code.token
16
16
  }
17
17
 
@@ -32,14 +32,14 @@ describe Devise::Strategies::Oauth2AuthorizationCodeGrantTypeStrategy do
32
32
  end
33
33
  end
34
34
  context 'with invalid authorization_code' do
35
+ with :client
35
36
  before do
36
37
  @user = User.create! :email => 'ryan@socialcast.com', :password => 'test'
37
- @client = Devise::Oauth2Providable::Client.create! :name => 'example', :redirect_uri => 'http://localhost', :website => 'http://localhost'
38
- @authorization_code = @user.authorization_codes.create(:client_id => @client, :redirect_uri => @client.redirect_uri)
38
+ @authorization_code = @user.authorization_codes.create(:client_id => client, :redirect_uri => client.redirect_uri)
39
39
  params = {
40
40
  :grant_type => 'authorization_code',
41
- :client_id => @client.identifier,
42
- :client_secret => @client.secret,
41
+ :client_id => client.identifier,
42
+ :client_secret => client.secret,
43
43
  :refresh_token => 'invalid'
44
44
  }
45
45
 
@@ -4,14 +4,14 @@ describe Devise::Strategies::Oauth2PasswordGrantTypeStrategy do
4
4
  describe 'POST /oauth2/token' do
5
5
  describe 'with grant_type=password' do
6
6
  context 'with valid params' do
7
+ with :client
7
8
  before do
8
9
  @user = User.create! :email => 'ryan@socialcast.com', :password => 'test'
9
- @client = Devise::Oauth2Providable::Client.create! :name => 'example', :redirect_uri => 'http://localhost', :website => 'http://localhost'
10
10
 
11
11
  params = {
12
12
  :grant_type => 'password',
13
- :client_id => @client.identifier,
14
- :client_secret => @client.secret,
13
+ :client_id => client.identifier,
14
+ :client_secret => client.secret,
15
15
  :username => @user.email,
16
16
  :password => 'test'
17
17
  }
@@ -27,14 +27,14 @@ describe Devise::Strategies::Oauth2PasswordGrantTypeStrategy do
27
27
  end
28
28
  end
29
29
  context 'with invalid params' do
30
+ with :client
30
31
  before do
31
32
  @user = User.create! :email => 'ryan@socialcast.com', :password => 'test'
32
- @client = Devise::Oauth2Providable::Client.create! :name => 'example', :redirect_uri => 'http://localhost', :website => 'http://localhost'
33
33
 
34
34
  params = {
35
35
  :grant_type => 'password',
36
- :client_id => @client.identifier,
37
- :client_secret => @client.secret,
36
+ :client_id => client.identifier,
37
+ :client_secret => client.secret,
38
38
  :username => @user.email,
39
39
  :password => 'bar'
40
40
  }
@@ -4,14 +4,14 @@ describe Devise::Strategies::Oauth2RefreshTokenGrantTypeStrategy do
4
4
  describe 'POST /oauth2/token' do
5
5
  describe 'with grant_type=refresh_token' do
6
6
  context 'with valid params' do
7
+ with :client
7
8
  before do
8
9
  @user = User.create! :email => 'ryan@socialcast.com', :password => 'test'
9
- @client = Devise::Oauth2Providable::Client.create! :name => 'example', :redirect_uri => 'http://localhost', :website => 'http://localhost'
10
- @refresh_token = @client.refresh_tokens.create! :user => @user
10
+ @refresh_token = client.refresh_tokens.create! :user => @user
11
11
  params = {
12
12
  :grant_type => 'refresh_token',
13
- :client_id => @client.identifier,
14
- :client_secret => @client.secret,
13
+ :client_id => client.identifier,
14
+ :client_secret => client.secret,
15
15
  :refresh_token => @refresh_token.token
16
16
  }
17
17
 
@@ -34,12 +34,12 @@ describe Devise::Strategies::Oauth2RefreshTokenGrantTypeStrategy do
34
34
  context 'with invalid refresh_token' do
35
35
  before do
36
36
  @user = User.create! :email => 'ryan@socialcast.com', :password => 'test'
37
- @client = Devise::Oauth2Providable::Client.create! :name => 'example', :redirect_uri => 'http://localhost', :website => 'http://localhost'
38
- @refresh_token = @client.refresh_tokens.create! :user => @user
37
+ client = Devise::Oauth2Providable::Client.create! :name => 'example', :redirect_uri => 'http://localhost', :website => 'http://localhost'
38
+ @refresh_token = client.refresh_tokens.create! :user => @user
39
39
  params = {
40
40
  :grant_type => 'refresh_token',
41
- :client_id => @client.identifier,
42
- :client_secret => @client.secret,
41
+ :client_id => client.identifier,
42
+ :client_secret => client.secret,
43
43
  :refresh_token => 'invalid'
44
44
  }
45
45
 
@@ -4,8 +4,8 @@ describe Devise::Oauth2Providable::AccessToken do
4
4
  it { Devise::Oauth2Providable::AccessToken.table_name.should == 'oauth2_access_tokens' }
5
5
 
6
6
  describe 'basic access token instance' do
7
+ with :client
7
8
  subject do
8
- client = Devise::Oauth2Providable::Client.create! :name => 'test', :redirect_uri => 'http://localhost:3000', :website => 'http://localhost'
9
9
  Devise::Oauth2Providable::AccessToken.create! :client => client
10
10
  end
11
11
  it { should validate_presence_of :token }
@@ -22,17 +22,30 @@ describe Devise::Oauth2Providable::AccessToken do
22
22
  it { should have_db_index :expires_at }
23
23
  end
24
24
 
25
- describe 'refresh token expires before access token expires_at' do
26
- before do
27
- @soon = 1.minute.from_now
28
- client = Devise::Oauth2Providable::Client.create! :name => 'test', :redirect_uri => 'http://localhost:3000', :website => 'http://localhost'
29
- @refresh_token = client.refresh_tokens.create!
30
- @refresh_token.expires_at = @soon
31
- @access_token = Devise::Oauth2Providable::AccessToken.create! :client => client, :refresh_token => @refresh_token
25
+ describe '#expires_at' do
26
+ context 'when refresh token does not expire before access token' do
27
+ with :client
28
+ before do
29
+ @later = 1.year.from_now
30
+ @refresh_token = client.refresh_tokens.create!
31
+ @refresh_token.expires_at = @soon
32
+ @access_token = Devise::Oauth2Providable::AccessToken.create! :client => client, :refresh_token => @refresh_token
33
+ end
34
+ focus 'should not set the access token expires_at to equal refresh token' do
35
+ @access_token.expires_at.should_not == @later
36
+ end
32
37
  end
33
- it 'should set the access token expires_at to equal refresh token' do
34
- @access_token.expires_at.should eq @soon
38
+ context 'when refresh token expires before access token' do
39
+ with :client
40
+ before do
41
+ @soon = 1.minute.from_now
42
+ @refresh_token = client.refresh_tokens.create!
43
+ @refresh_token.expires_at = @soon
44
+ @access_token = Devise::Oauth2Providable::AccessToken.create! :client => client, :refresh_token => @refresh_token
45
+ end
46
+ it 'should set the access token expires_at to equal refresh token' do
47
+ @access_token.expires_at.should == @soon
48
+ end
35
49
  end
36
50
  end
37
51
  end
38
-
@@ -2,8 +2,8 @@ require 'spec_helper'
2
2
 
3
3
  describe Devise::Oauth2Providable::AuthorizationCode do
4
4
  describe 'basic authorization code instance' do
5
+ with :client
5
6
  subject do
6
- client = Devise::Oauth2Providable::Client.create! :name => 'test', :redirect_uri => 'http://localhost:3000', :website => 'http://localhost'
7
7
  Devise::Oauth2Providable::AuthorizationCode.create! :client => client
8
8
  end
9
9
  it { should validate_presence_of :token }
@@ -4,8 +4,8 @@ describe Devise::Oauth2Providable::RefreshToken do
4
4
  it { Devise::Oauth2Providable::RefreshToken.table_name.should == 'oauth2_refresh_tokens' }
5
5
 
6
6
  describe 'basic refresh token instance' do
7
+ with :client
7
8
  subject do
8
- client = Devise::Oauth2Providable::Client.create! :name => 'test', :redirect_uri => 'http://localhost:3000', :website => 'http://localhost'
9
9
  Devise::Oauth2Providable::RefreshToken.create! :client => client
10
10
  end
11
11
  it { should validate_presence_of :token }
data/spec/spec_helper.rb CHANGED
@@ -2,9 +2,15 @@
2
2
  ENV["RAILS_ENV"] = "test"
3
3
  require File.expand_path("../dummy/config/environment.rb", __FILE__)
4
4
 
5
+ require 'pry'
5
6
  require 'rspec/rails'
6
7
  require 'shoulda-matchers'
7
- require 'pry'
8
+
9
+ require 'factory_girl_rspec'
10
+ FactoryGirl.definition_file_paths = [
11
+ File.join(File.dirname(__FILE__), 'factories')
12
+ ]
13
+ FactoryGirl.find_definitions
8
14
 
9
15
  ENGINE_RAILS_ROOT=File.join(File.dirname(__FILE__), '../')
10
16
 
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: devise_oauth2_providable
3
3
  version: !ruby/object:Gem::Version
4
- hash: 21
4
+ hash: 19
5
5
  prerelease:
6
6
  segments:
7
7
  - 1
8
8
  - 0
9
- - 1
10
- version: 1.0.1
9
+ - 2
10
+ version: 1.0.2
11
11
  platform: ruby
12
12
  authors:
13
13
  - Ryan Sonnek
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-10-27 00:00:00 Z
18
+ date: 2011-10-28 00:00:00 Z
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
21
  name: rails
@@ -132,6 +132,38 @@ dependencies:
132
132
  version: 0.9.6.2
133
133
  version_requirements: *id007
134
134
  type: :development
135
+ - !ruby/object:Gem::Dependency
136
+ name: factory_girl
137
+ prerelease: false
138
+ requirement: &id008 !ruby/object:Gem::Requirement
139
+ none: false
140
+ requirements:
141
+ - - "="
142
+ - !ruby/object:Gem::Version
143
+ hash: 7
144
+ segments:
145
+ - 2
146
+ - 2
147
+ - 0
148
+ version: 2.2.0
149
+ version_requirements: *id008
150
+ type: :development
151
+ - !ruby/object:Gem::Dependency
152
+ name: factory_girl_rspec
153
+ prerelease: false
154
+ requirement: &id009 !ruby/object:Gem::Requirement
155
+ none: false
156
+ requirements:
157
+ - - "="
158
+ - !ruby/object:Gem::Version
159
+ hash: 29
160
+ segments:
161
+ - 0
162
+ - 0
163
+ - 1
164
+ version: 0.0.1
165
+ version_requirements: *id009
166
+ type: :development
135
167
  description: Rails3 engine that adds OAuth2 Provider support to any application built with Devise authentication
136
168
  email:
137
169
  - ryan@socialcast.com
@@ -163,6 +195,7 @@ files:
163
195
  - db/migrate/20111014160714_create_devise_oauth2_providable_schema.rb
164
196
  - devise_oauth2_providable.gemspec
165
197
  - lib/devise/oauth2_providable/engine.rb
198
+ - lib/devise/oauth2_providable/expirable_token.rb
166
199
  - lib/devise/oauth2_providable/models/oauth2_authorization_code_grantable.rb
167
200
  - lib/devise/oauth2_providable/models/oauth2_password_grantable.rb
168
201
  - lib/devise/oauth2_providable/models/oauth2_providable.rb
@@ -174,7 +207,6 @@ files:
174
207
  - lib/devise/oauth2_providable/strategies/oauth2_refresh_token_grant_type_strategy.rb
175
208
  - lib/devise/oauth2_providable/version.rb
176
209
  - lib/devise_oauth2_providable.rb
177
- - lib/expirable_token.rb
178
210
  - script/rails
179
211
  - spec/controllers/protected_controller_spec.rb
180
212
  - spec/dummy/Rakefile
@@ -215,6 +247,7 @@ files:
215
247
  - spec/dummy/public/500.html
216
248
  - spec/dummy/public/favicon.ico
217
249
  - spec/dummy/script/rails
250
+ - spec/factories/client_factory.rb
218
251
  - spec/integration/oauth2_authorization_token_grant_type_strategy_spec.rb
219
252
  - spec/integration/oauth2_password_grant_type_strategy_spec.rb
220
253
  - spec/integration/oauth2_refresh_token_grant_type_strategy_spec.rb
@@ -302,6 +335,7 @@ test_files:
302
335
  - spec/dummy/public/500.html
303
336
  - spec/dummy/public/favicon.ico
304
337
  - spec/dummy/script/rails
338
+ - spec/factories/client_factory.rb
305
339
  - spec/integration/oauth2_authorization_token_grant_type_strategy_spec.rb
306
340
  - spec/integration/oauth2_password_grant_type_strategy_spec.rb
307
341
  - spec/integration/oauth2_refresh_token_grant_type_strategy_spec.rb
@@ -1,41 +0,0 @@
1
- module ExpirableToken
2
- def self.included(klass)
3
- klass.class_eval do
4
- cattr_accessor :default_lifetime
5
- self.default_lifetime = 1.minute
6
-
7
- belongs_to :user
8
- belongs_to :client
9
-
10
- before_validation :init_token, :on => :create, :unless => :token?
11
- before_validation :init_expires_at, :on => :create, :unless => :expires_at?
12
- validates :expires_at, :presence => true
13
- validates :client, :presence => true
14
- validates :token, :presence => true, :uniqueness => true
15
-
16
- # TODO: this should be a default scope once rails default_scope supports lambda's
17
- scope :valid, lambda {
18
- where(self.arel_table[:expires_at].gteq(Time.now.utc))
19
- }
20
- end
21
- end
22
-
23
- def expires_in
24
- (expires_at - Time.now.utc).to_i
25
- end
26
-
27
- def expired!
28
- self.expires_at = Time.now.utc
29
- self.save!
30
- end
31
-
32
- private
33
-
34
- def init_token
35
- self.token = Devise::Oauth2Providable.random_id
36
- end
37
- def init_expires_at
38
- self.expires_at = self.default_lifetime.from_now
39
- end
40
- end
41
-