tiddle 1.0.2 → 1.1.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 1fa66626fb86bdb8e5e02ff35478ba8429a8f416
4
- data.tar.gz: 6cc2d9b7fb7f389a2345eb7c3eef23cb9d580b2f
2
+ SHA256:
3
+ metadata.gz: 636a498dc602f9309c1baf81f3f34276aad7e710fd14d170c02ba5af381b40f1
4
+ data.tar.gz: 670f3801abc579331c721d66ee5cf68e46817a89bdadfc6356d0f02ce0276176
5
5
  SHA512:
6
- metadata.gz: bc942083526221652b791dd9fd8f69cded955daa2f542dc7089def991997f503f08331690ec11b35d232a782d7e16bd3dfc3c964a13886044799d77e73f7d9b9
7
- data.tar.gz: e5b5d147c14bc589affe4bae4623352e0f77d7be8210312f563e1d672f1eb5d3b2fa347f545ea809ac43722a5f9a141075e34e3c24d9643812c0b5ff81c063c6
6
+ metadata.gz: d5305d3d877befdee9203d7001f05e07ef38a3ad77abcc74563140f2217f69319d39d723be4453410b1935ed01a839995e8c296c767349b2355657b36ba7532b
7
+ data.tar.gz: c114628903a18817a6a99ab3e233639d4e2c428e7216c06e46eed4407aac243f89533db8cae5edf05335d351c4903ea3559da60e1b42821b3c98ffdbf984eb0b
@@ -26,3 +26,5 @@ Naming/FileName:
26
26
  Metrics/BlockLength:
27
27
  Exclude:
28
28
  - 'spec/**/*'
29
+ Metrics/MethodLength:
30
+ Max: 15
@@ -1,8 +1,10 @@
1
1
  language: ruby
2
+ before_install: gem update --system
2
3
  rvm:
3
4
  - "2.2.8"
4
5
  - "2.3.5"
5
6
  - "2.4.2"
7
+ - "2.5.0"
6
8
  gemfile:
7
9
  - "gemfiles/rails4.2.gemfile"
8
10
  - "gemfiles/rails5.0.gemfile"
@@ -1,3 +1,10 @@
1
+ ### 1.1.0
2
+
3
+ New feature: optional token expiration after period of inactivity - #37
4
+
5
+ You have to add `expires_in` field to the database table holding the tokens
6
+ to benefit from this feature.
7
+
1
8
  ### 1.0.0
2
9
 
3
10
  No major changes - just a stable version release.
data/README.md CHANGED
@@ -40,7 +40,7 @@ end
40
40
  2) Generate the model which stores authentication tokens. The model name is not important, but the Devise-enabled model should have association called ```authentication_tokens```.
41
41
 
42
42
  ```
43
- rails g model AuthenticationToken body:string user:references last_used_at:datetime ip_address:string user_agent:string
43
+ rails g model AuthenticationToken body:string:index user:references last_used_at:datetime expires_in:integer ip_address:string user_agent:string
44
44
  ```
45
45
 
46
46
  ```ruby
@@ -111,3 +111,9 @@ Change ```config.authentication_keys``` in Devise intitializer and Tiddle will u
111
111
  Usually it makes sense to remove user's tokens after a password change. Depending on the project and on your taste, this can be done using various methods like running `user.authentication_tokens.destroy_all` after the password change or with an `after_save` callback in your model which runs `authentication_tokens.destroy_all if encrypted_password_changed?`.
112
112
 
113
113
  In case of a security breach, remove all existing tokens.
114
+
115
+ Tokens are expiring after certain period of inactivity. This behavior is optional. If you want your token to expire, create it passing `expires_in` option:
116
+
117
+ ```ruby
118
+ token = Tiddle.create_and_return_token(user, request, expires_in: 1.month)
119
+ ```
@@ -5,8 +5,8 @@ require "tiddle/rails"
5
5
  require "tiddle/token_issuer"
6
6
 
7
7
  module Tiddle
8
- def self.create_and_return_token(resource, request)
9
- TokenIssuer.build.create_and_return_token(resource, request)
8
+ def self.create_and_return_token(resource, request, options = {})
9
+ TokenIssuer.build.create_and_return_token(resource, request, options)
10
10
  end
11
11
 
12
12
  def self.expire_token(resource, request)
@@ -12,7 +12,7 @@ module Devise
12
12
  return fail(:invalid_token) unless resource
13
13
 
14
14
  token = Tiddle::TokenIssuer.build.find_token(resource, token_from_headers)
15
- if token
15
+ if token && unexpired?(token)
16
16
  touch_token(token)
17
17
  return success!(resource)
18
18
  end
@@ -51,6 +51,13 @@ module Devise
51
51
  def touch_token(token)
52
52
  token.update_attribute(:last_used_at, Time.current) if token.last_used_at < 1.hour.ago
53
53
  end
54
+
55
+ def unexpired?(token)
56
+ return true unless token.respond_to?(:expires_in)
57
+ return true if token.expires_in.blank? || token.expires_in.zero?
58
+
59
+ Time.current <= token.last_used_at + token.expires_in
60
+ end
54
61
  end
55
62
  end
56
63
  end
@@ -12,15 +12,13 @@ module Tiddle
12
12
  self.maximum_tokens_per_user = maximum_tokens_per_user
13
13
  end
14
14
 
15
- def create_and_return_token(resource, request)
15
+ def create_and_return_token(resource, request, expires_in: nil)
16
16
  token_class = authentication_token_class(resource)
17
17
  token, token_body = Devise.token_generator.generate(token_class, :body)
18
18
 
19
- resource.authentication_tokens
20
- .create! body: token_body,
21
- last_used_at: Time.current,
22
- ip_address: request.remote_ip,
23
- user_agent: request.user_agent
19
+ resource.authentication_tokens.create!(
20
+ token_attributes(token_body, request, expires_in)
21
+ )
24
22
 
25
23
  token
26
24
  end
@@ -33,9 +31,7 @@ module Tiddle
33
31
  def find_token(resource, token_from_headers)
34
32
  token_class = authentication_token_class(resource)
35
33
  token_body = Devise.token_generator.digest(token_class, :body, token_from_headers)
36
- resource.authentication_tokens.detect do |token|
37
- Devise.secure_compare(token.body, token_body)
38
- end
34
+ resource.authentication_tokens.find_by(body: token_body)
39
35
  end
40
36
 
41
37
  def purge_old_tokens(resource)
@@ -52,5 +48,20 @@ module Tiddle
52
48
  def authentication_token_class(resource)
53
49
  resource.association(:authentication_tokens).klass
54
50
  end
51
+
52
+ def token_attributes(token_body, request, expires_in)
53
+ attributes = {
54
+ body: token_body,
55
+ last_used_at: Time.current,
56
+ ip_address: request.remote_ip,
57
+ user_agent: request.user_agent
58
+ }
59
+
60
+ if expires_in
61
+ attributes.merge(expires_in: expires_in)
62
+ else
63
+ attributes
64
+ end
65
+ end
55
66
  end
56
67
  end
@@ -1,3 +1,3 @@
1
1
  module Tiddle
2
- VERSION = "1.0.2".freeze
2
+ VERSION = "1.1.0".freeze
3
3
  end
@@ -1,10 +1,8 @@
1
1
  require File.expand_path('../boot', __FILE__)
2
2
 
3
3
  require "active_model/railtie"
4
- require "active_job/railtie"
5
4
  require "active_record/railtie"
6
5
  require "action_controller/railtie"
7
- require "action_mailer/railtie"
8
6
  require "action_view/railtie"
9
7
 
10
8
  module RailsApp
@@ -56,6 +56,7 @@ class CreateTables < migration_class
56
56
  t.string :body, null: false
57
57
  t.references :authenticatable, null: false, polymorphic: true
58
58
  t.datetime :last_used_at, null: false
59
+ t.integer :expires_in, null: false, default: 0
59
60
  t.string :ip_address
60
61
  t.string :user_agent
61
62
 
@@ -159,4 +159,42 @@ describe "Authentication using Tiddle strategy", type: :request do
159
159
  expect(response.status).to eq 200
160
160
  end
161
161
  end
162
+
163
+ context "when token has expires_in set up" do
164
+ before do
165
+ @user = User.create!(email: "test@example.com", password: "12345678")
166
+ @token = Tiddle.create_and_return_token(@user, FakeRequest.new, expires_in: 1.week)
167
+ end
168
+
169
+ describe "token is not expired" do
170
+ it "does allow to access endpoints which require authentication" do
171
+ warningless_get(
172
+ secrets_path,
173
+ headers: {
174
+ "X-USER-EMAIL" => "test@example.com",
175
+ "X-USER-TOKEN" => @token
176
+ }
177
+ )
178
+ expect(response.status).to eq 200
179
+ end
180
+ end
181
+
182
+ describe "token is expired" do
183
+ before do
184
+ token = @user.authentication_tokens.order(:id).last
185
+ token.update_attribute(:last_used_at, 1.month.ago)
186
+ end
187
+
188
+ it "does not allow to access endpoints which require authentication" do
189
+ warningless_get(
190
+ secrets_path,
191
+ headers: {
192
+ "X-USER-EMAIL" => "test@example.com",
193
+ "X-USER-TOKEN" => @token
194
+ }
195
+ )
196
+ expect(response.status).to eq 401
197
+ end
198
+ end
199
+ end
162
200
  end
@@ -18,7 +18,7 @@ Gem::Specification.new do |spec|
18
18
 
19
19
  spec.required_ruby_version = '>= 2.2.0'
20
20
 
21
- spec.add_dependency "devise", ">= 4.0.0.rc1", "< 4.4"
21
+ spec.add_dependency "devise", ">= 4.0.0.rc1", "< 4.5"
22
22
  spec.add_dependency "activerecord", ">= 4.2.0"
23
23
  spec.add_development_dependency "bundler", "~> 1.7"
24
24
  spec.add_development_dependency "rake", "~> 12.0"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tiddle
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.2
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Adam Niedzielski
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-12-14 00:00:00.000000000 Z
11
+ date: 2018-03-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: devise
@@ -19,7 +19,7 @@ dependencies:
19
19
  version: 4.0.0.rc1
20
20
  - - "<"
21
21
  - !ruby/object:Gem::Version
22
- version: '4.4'
22
+ version: '4.5'
23
23
  type: :runtime
24
24
  prerelease: false
25
25
  version_requirements: !ruby/object:Gem::Requirement
@@ -29,7 +29,7 @@ dependencies:
29
29
  version: 4.0.0.rc1
30
30
  - - "<"
31
31
  - !ruby/object:Gem::Version
32
- version: '4.4'
32
+ version: '4.5'
33
33
  - !ruby/object:Gem::Dependency
34
34
  name: activerecord
35
35
  requirement: !ruby/object:Gem::Requirement
@@ -224,7 +224,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
224
224
  version: '0'
225
225
  requirements: []
226
226
  rubyforge_project:
227
- rubygems_version: 2.6.13
227
+ rubygems_version: 2.7.3
228
228
  signing_key:
229
229
  specification_version: 4
230
230
  summary: Token authentication for Devise which supports multiple tokens per model