authie 4.0.0.rc10 → 4.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c2ba869656ec43ca7b92803584ad2361ad2a7c443b2b69bc7f7bac2c0e991218
4
- data.tar.gz: 67340e7ab60e5fafb35a17a8760611d5f1c25a3ae67abf75363f7210ec3cb181
3
+ metadata.gz: 1b35fefc8e1d77c5dc713e70d46d29a2e6de782e3d3c6cb35a89f8a31f416406
4
+ data.tar.gz: f4bfa5628f66ef549e2cb0e74b87c2a503a0d49916d1a93aba7af299bc0e7d29
5
5
  SHA512:
6
- metadata.gz: b6f3604a227d448f0d2724eb6566f83c4b665121fd3d9075691bdccd4e72370a230b4916ae1a8fd8b68fff893e81b5bd39170be2c5ebe244817fa33c5365daf7
7
- data.tar.gz: fcde4d28afbc7bab2727150c69be0baa527a89e65bb1047159499247771b2284bec104f54bbd7adf7db52f18dacac58ab0817085d8b42ff8f07e226b201bffe6
6
+ metadata.gz: 47793da24b501a3e3a5f26652cde36431c90f6f43b8d0e1fa8477e366b2ba6f6ee524e989dd5d2520f15b61c567320f701c29caa5c62bf1acfafc1ad1d096415
7
+ data.tar.gz: 98e9993d49250765b479e7bd37703652f381d3dc6fb2cf1d1792498b5c95f81c200bb0ea68ff09be6fe072e7141ed49876b43a0953a94fed012370bbbce5c36f
@@ -1,10 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class CreateAuthieSessions < ActiveRecord::Migration[4.2]
3
+ class CreateAuthieSessions < ActiveRecord::Migration[6.1]
4
4
  def change
5
5
  create_table :authie_sessions do |t|
6
6
  t.string :token, :browser_id
7
- t.integer :user_id
7
+ t.bigint :user_id
8
8
  t.boolean :active, default: true
9
9
  t.text :data
10
10
  t.datetime :expires_at
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class AddIndexesToAuthieSessions < ActiveRecord::Migration[4.2]
3
+ class AddIndexesToAuthieSessions < ActiveRecord::Migration[6.1]
4
4
  def change
5
5
  add_column :authie_sessions, :user_type, :string
6
6
  add_index :authie_sessions, :token, length: 10
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class AddParentIdToAuthieSessions < ActiveRecord::Migration[4.2]
3
+ class AddParentIdToAuthieSessions < ActiveRecord::Migration[6.1]
4
4
  def change
5
- add_column :authie_sessions, :parent_id, :integer
5
+ add_column :authie_sessions, :parent_id, :bigint
6
6
  end
7
7
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class AddTwoFactorAuthFieldsToAuthie < ActiveRecord::Migration[4.2]
3
+ class AddTwoFactorAuthFieldsToAuthie < ActiveRecord::Migration[6.1]
4
4
  def change
5
5
  add_column :authie_sessions, :two_factored_at, :datetime
6
6
  add_column :authie_sessions, :two_factored_ip, :string
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class AddTokenHashesToAuthieSessions < ActiveRecord::Migration[4.2]
3
+ class AddTokenHashesToAuthieSessions < ActiveRecord::Migration[6.1]
4
4
  def change
5
5
  add_column :authie_sessions, :token_hash, :string
6
6
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class AddIndexToTokenHashesOnAuthieSessions < ActiveRecord::Migration[4.2]
3
+ class AddIndexToTokenHashesOnAuthieSessions < ActiveRecord::Migration[6.1]
4
4
  def change
5
5
  add_index :authie_sessions, :token_hash, length: 10
6
6
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class AddHostToAuthieSessions < ActiveRecord::Migration[4.2]
3
+ class AddHostToAuthieSessions < ActiveRecord::Migration[6.1]
4
4
  def change
5
5
  add_column :authie_sessions, :host, :string
6
6
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class AddTwoFactorRequiredToSessions < ActiveRecord::Migration[4.2]
3
+ class AddTwoFactorRequiredToSessions < ActiveRecord::Migration[6.1]
4
4
  def change
5
5
  add_column :authie_sessions, :skip_two_factor, :boolean, default: false
6
6
  end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ class AddCountriesToAuthieSessions < ActiveRecord::Migration[6.1]
4
+ def change
5
+ add_column :authie_sessions, :login_ip_country, :string
6
+ add_column :authie_sessions, :two_factored_ip_country, :string
7
+ add_column :authie_sessions, :last_activity_ip_country, :string
8
+ end
9
+ end
data/lib/authie/config.rb CHANGED
@@ -8,6 +8,7 @@ module Authie
8
8
  attr_accessor :browser_id_cookie_name
9
9
  attr_accessor :session_token_length
10
10
  attr_accessor :extend_session_expiry_on_touch
11
+ attr_accessor :ip_lookup
11
12
 
12
13
  def initialize
13
14
  @session_inactivity_timeout = 12.hours
@@ -16,6 +17,13 @@ module Authie
16
17
  @browser_id_cookie_name = :browser_id
17
18
  @session_token_length = 64
18
19
  @extend_session_expiry_on_touch = false
20
+ @lookup_ip_country_backend = nil
21
+ end
22
+
23
+ def lookup_ip_country(ip)
24
+ return nil if @lookup_ip_country_backend.nil?
25
+
26
+ @lookup_ip_country_backend.call(ip)
19
27
  end
20
28
  end
21
29
 
@@ -46,9 +46,9 @@ module Authie
46
46
  #
47
47
  # @return [Authie::Session, false]
48
48
  def validate_auth_session
49
- return auth_session.validate if logged_in?
49
+ return false unless logged_in?
50
50
 
51
- false
51
+ auth_session.validate
52
52
  end
53
53
 
54
54
  # Touch the session to update details on the latest activity.
@@ -74,13 +74,12 @@ module Authie
74
74
  #
75
75
  # @return [Authie::Session, nil]
76
76
  def create_auth_session(user, **kwargs)
77
- if user
78
- @auth_session = Authie::Session.start(@controller, user: user, **kwargs)
79
- return @auth_session
77
+ if user.nil?
78
+ invalidate_auth_session
79
+ return nil
80
80
  end
81
81
 
82
- invalidate_auth_session
83
- nil
82
+ @auth_session = Authie::Session.start(@controller, user: user, **kwargs)
84
83
  end
85
84
 
86
85
  # Invalidate the existing auth session if one exists. Return true if a sesion has been invalidated
@@ -88,13 +87,11 @@ module Authie
88
87
  #
89
88
  # @return [Boolean]
90
89
  def invalidate_auth_session
91
- if logged_in?
92
- auth_session.invalidate
93
- @auth_session = nil
94
- return true
95
- end
90
+ return false unless logged_in?
96
91
 
97
- false
92
+ auth_session.invalidate
93
+ @auth_session = nil
94
+ true
98
95
  end
99
96
 
100
97
  # Is anyone currently logged in? Return true if there is an auth session present.
@@ -6,7 +6,8 @@ module Authie
6
6
  module ControllerExtension
7
7
  class << self
8
8
  def included(base)
9
- base.helper_method :logged_in?, :current_user, :auth_session
9
+ base.helper_method :logged_in?, :current_user, :auth_session if base.respond_to?(:helper_method)
10
+
10
11
  base.before_action :set_browser_id, :validate_auth_session
11
12
  base.around_action :touch_auth_session
12
13
 
@@ -13,7 +13,14 @@ module Authie
13
13
  attr_reader :session
14
14
 
15
15
  # A parent class that encapsulates all session validity errors.
16
- class ValidityError < Error; end
16
+ class ValidityError < Error
17
+ attr_reader :session
18
+
19
+ def initialize(message, session = nil)
20
+ super(message)
21
+ @session = session
22
+ end
23
+ end
17
24
 
18
25
  # Raised when a session is used but it is no longer active
19
26
  class InactiveSession < ValidityError; end
@@ -89,7 +96,11 @@ module Authie
89
96
  # @return [Authie::Session]
90
97
  def touch
91
98
  @session.last_activity_at = Time.now
99
+ if @controller.request.ip != @session.last_activity_ip
100
+ @session.last_activity_ip_country = Authie.config.lookup_ip_country(@controller.request.ip)
101
+ end
92
102
  @session.last_activity_ip = @controller.request.ip
103
+
93
104
  @session.last_activity_path = @controller.request.path
94
105
  @session.requests += 1
95
106
  extend_session_expiry_if_appropriate
@@ -117,6 +128,7 @@ module Authie
117
128
  def mark_as_two_factored(skip: nil)
118
129
  @session.two_factored_at = Time.now
119
130
  @session.two_factored_ip = @controller.request.ip
131
+ @session.two_factored_ip_country = Authie.config.lookup_ip_country(@controller.request.ip)
120
132
  @session.skip_two_factor = skip unless skip.nil?
121
133
  @session.save!
122
134
  Authie.notify(:mark_as_two_factor, session: self)
@@ -145,7 +157,6 @@ module Authie
145
157
 
146
158
  private
147
159
 
148
- # rubocop:disable Naming/AccessorMethodName
149
160
  def set_cookie(value = @session.temporary_token)
150
161
  cookies[:user_session] = {
151
162
  value: value,
@@ -156,7 +167,6 @@ module Authie
156
167
  Authie.notify(:cookie_updated, session: session)
157
168
  true
158
169
  end
159
- # rubocop:enable Naming/AccessorMethodName
160
170
 
161
171
  def cookies
162
172
  @controller.send(:cookies)
@@ -164,9 +174,9 @@ module Authie
164
174
 
165
175
  def validate_browser_id
166
176
  if cookies[:browser_id] != @session.browser_id
167
- invalidate
168
177
  Authie.notify(:browser_id_mismatch_error, session: self)
169
- raise BrowserMismatch, 'Browser ID mismatch'
178
+ invalidate
179
+ raise BrowserMismatch.new('Browser ID mismatch', self)
170
180
  end
171
181
 
172
182
  self
@@ -176,7 +186,7 @@ module Authie
176
186
  unless @session.active?
177
187
  invalidate
178
188
  Authie.notify(:invalid_session_error, session: self)
179
- raise InactiveSession, 'Session is no longer active'
189
+ raise InactiveSession.new('Session is no longer active', self)
180
190
  end
181
191
 
182
192
  self
@@ -186,7 +196,7 @@ module Authie
186
196
  if @session.expired?
187
197
  invalidate
188
198
  Authie.notify(:expired_session_error, session: self)
189
- raise ExpiredSession, 'Persistent session has expired'
199
+ raise ExpiredSession.new('Persistent session has expired', self)
190
200
  end
191
201
 
192
202
  self
@@ -195,8 +205,8 @@ module Authie
195
205
  def validate_inactivity
196
206
  if @session.inactive?
197
207
  invalidate
198
- Authie.notify(:inactive_session_error, session: self)
199
- raise InactiveSession, 'Non-persistent session has expired'
208
+ Authie.notify(:inactive_session_error, session: self)
209
+ raise InactiveSession.new('Non-persistent session has expired', self)
200
210
  end
201
211
 
202
212
  self
@@ -206,7 +216,8 @@ module Authie
206
216
  if @session.host && @session.host != @controller.request.host
207
217
  invalidate
208
218
  Authie.notify(:host_mismatch_error, session: self)
209
- raise HostMismatch, "Session was created on #{@session.host} but accessed using #{@controller.request.host}"
219
+ raise HostMismatch.new("Session was created on #{@session.host} but accessed using #{@controller.request.host}",
220
+ self)
210
221
  end
211
222
 
212
223
  self
@@ -238,6 +249,7 @@ module Authie
238
249
  session.browser_id = cookies[:browser_id]
239
250
  session.login_at = Time.now
240
251
  session.login_ip = controller.request.ip
252
+ session.login_ip_country = Authie.config.lookup_ip_country(session.login_ip)
241
253
  session.host = controller.request.host
242
254
  session.user_agent = controller.request.user_agent
243
255
  session.expires_at = Time.now + Authie.config.persistent_session_length if persistent
@@ -292,9 +304,11 @@ module Authie
292
304
  delegate :invalidate_others!, to: :session
293
305
  delegate :last_activity_at, to: :session
294
306
  delegate :last_activity_ip, to: :session
307
+ delegate :last_activity_ip_country, to: :session
295
308
  delegate :last_activity_path, to: :session
296
309
  delegate :login_at, to: :session
297
310
  delegate :login_ip, to: :session
311
+ delegate :login_ip_country, to: :session
298
312
  delegate :password_seen_at, to: :session
299
313
  delegate :persisted?, to: :session
300
314
  delegate :persistent?, to: :session
@@ -305,6 +319,7 @@ module Authie
305
319
  delegate :token_hash, to: :session
306
320
  delegate :two_factored_at, to: :session
307
321
  delegate :two_factored_ip, to: :session
322
+ delegate :two_factored_ip_country, to: :session
308
323
  delegate :two_factored?, to: :session
309
324
  delegate :skip_two_factor?, to: :session
310
325
  delegate :update, to: :session
@@ -63,8 +63,10 @@ module Authie
63
63
  end
64
64
 
65
65
  def invalidate!
66
+ active_now = active?
66
67
  self.active = false
67
68
  save!
69
+ Authie.notify(:session_invalidate, session: self) if active_now
68
70
  true
69
71
  end
70
72
 
@@ -79,7 +81,7 @@ module Authie
79
81
  end
80
82
 
81
83
  def invalidate_others!
82
- self.class.where('id != ?', id).for_user(user).each(&:invalidate!).inspect
84
+ self.class.where('id != ?', id).active.for_user(user).each(&:invalidate!)
83
85
  end
84
86
 
85
87
  # Have we seen the user's password recently in this sesion?
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: authie
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.0.0.rc10
4
+ version: 4.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Adam Cooke
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-05-20 00:00:00.000000000 Z
11
+ date: 2023-06-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -30,194 +30,6 @@ dependencies:
30
30
  - - "<"
31
31
  - !ruby/object:Gem::Version
32
32
  version: '8.0'
33
- - !ruby/object:Gem::Dependency
34
- name: appraisal
35
- requirement: !ruby/object:Gem::Requirement
36
- requirements:
37
- - - '='
38
- - !ruby/object:Gem::Version
39
- version: 2.4.1
40
- type: :development
41
- prerelease: false
42
- version_requirements: !ruby/object:Gem::Requirement
43
- requirements:
44
- - - '='
45
- - !ruby/object:Gem::Version
46
- version: 2.4.1
47
- - !ruby/object:Gem::Dependency
48
- name: rails
49
- requirement: !ruby/object:Gem::Requirement
50
- requirements:
51
- - - ">="
52
- - !ruby/object:Gem::Version
53
- version: '5.0'
54
- - - "<"
55
- - !ruby/object:Gem::Version
56
- version: '8.0'
57
- type: :development
58
- prerelease: false
59
- version_requirements: !ruby/object:Gem::Requirement
60
- requirements:
61
- - - ">="
62
- - !ruby/object:Gem::Version
63
- version: '5.0'
64
- - - "<"
65
- - !ruby/object:Gem::Version
66
- version: '8.0'
67
- - !ruby/object:Gem::Dependency
68
- name: rspec
69
- requirement: !ruby/object:Gem::Requirement
70
- requirements:
71
- - - ">="
72
- - !ruby/object:Gem::Version
73
- version: '0'
74
- type: :development
75
- prerelease: false
76
- version_requirements: !ruby/object:Gem::Requirement
77
- requirements:
78
- - - ">="
79
- - !ruby/object:Gem::Version
80
- version: '0'
81
- - !ruby/object:Gem::Dependency
82
- name: rspec-core
83
- requirement: !ruby/object:Gem::Requirement
84
- requirements:
85
- - - ">="
86
- - !ruby/object:Gem::Version
87
- version: '0'
88
- type: :development
89
- prerelease: false
90
- version_requirements: !ruby/object:Gem::Requirement
91
- requirements:
92
- - - ">="
93
- - !ruby/object:Gem::Version
94
- version: '0'
95
- - !ruby/object:Gem::Dependency
96
- name: rspec-expectations
97
- requirement: !ruby/object:Gem::Requirement
98
- requirements:
99
- - - ">="
100
- - !ruby/object:Gem::Version
101
- version: '0'
102
- type: :development
103
- prerelease: false
104
- version_requirements: !ruby/object:Gem::Requirement
105
- requirements:
106
- - - ">="
107
- - !ruby/object:Gem::Version
108
- version: '0'
109
- - !ruby/object:Gem::Dependency
110
- name: rspec-mocks
111
- requirement: !ruby/object:Gem::Requirement
112
- requirements:
113
- - - ">="
114
- - !ruby/object:Gem::Version
115
- version: '0'
116
- type: :development
117
- prerelease: false
118
- version_requirements: !ruby/object:Gem::Requirement
119
- requirements:
120
- - - ">="
121
- - !ruby/object:Gem::Version
122
- version: '0'
123
- - !ruby/object:Gem::Dependency
124
- name: rspec-rails
125
- requirement: !ruby/object:Gem::Requirement
126
- requirements:
127
- - - ">="
128
- - !ruby/object:Gem::Version
129
- version: '0'
130
- type: :development
131
- prerelease: false
132
- version_requirements: !ruby/object:Gem::Requirement
133
- requirements:
134
- - - ">="
135
- - !ruby/object:Gem::Version
136
- version: '0'
137
- - !ruby/object:Gem::Dependency
138
- name: rubocop
139
- requirement: !ruby/object:Gem::Requirement
140
- requirements:
141
- - - '='
142
- - !ruby/object:Gem::Version
143
- version: 1.17.0
144
- type: :development
145
- prerelease: false
146
- version_requirements: !ruby/object:Gem::Requirement
147
- requirements:
148
- - - '='
149
- - !ruby/object:Gem::Version
150
- version: 1.17.0
151
- - !ruby/object:Gem::Dependency
152
- name: simplecov
153
- requirement: !ruby/object:Gem::Requirement
154
- requirements:
155
- - - ">="
156
- - !ruby/object:Gem::Version
157
- version: '0'
158
- type: :development
159
- prerelease: false
160
- version_requirements: !ruby/object:Gem::Requirement
161
- requirements:
162
- - - ">="
163
- - !ruby/object:Gem::Version
164
- version: '0'
165
- - !ruby/object:Gem::Dependency
166
- name: simplecov-console
167
- requirement: !ruby/object:Gem::Requirement
168
- requirements:
169
- - - ">="
170
- - !ruby/object:Gem::Version
171
- version: '0'
172
- type: :development
173
- prerelease: false
174
- version_requirements: !ruby/object:Gem::Requirement
175
- requirements:
176
- - - ">="
177
- - !ruby/object:Gem::Version
178
- version: '0'
179
- - !ruby/object:Gem::Dependency
180
- name: solargraph
181
- requirement: !ruby/object:Gem::Requirement
182
- requirements:
183
- - - ">="
184
- - !ruby/object:Gem::Version
185
- version: '0'
186
- type: :development
187
- prerelease: false
188
- version_requirements: !ruby/object:Gem::Requirement
189
- requirements:
190
- - - ">="
191
- - !ruby/object:Gem::Version
192
- version: '0'
193
- - !ruby/object:Gem::Dependency
194
- name: sqlite3
195
- requirement: !ruby/object:Gem::Requirement
196
- requirements:
197
- - - '='
198
- - !ruby/object:Gem::Version
199
- version: 1.4.2
200
- type: :development
201
- prerelease: false
202
- version_requirements: !ruby/object:Gem::Requirement
203
- requirements:
204
- - - '='
205
- - !ruby/object:Gem::Version
206
- version: 1.4.2
207
- - !ruby/object:Gem::Dependency
208
- name: timecop
209
- requirement: !ruby/object:Gem::Requirement
210
- requirements:
211
- - - ">="
212
- - !ruby/object:Gem::Version
213
- version: '0'
214
- type: :development
215
- prerelease: false
216
- version_requirements: !ruby/object:Gem::Requirement
217
- requirements:
218
- - - ">="
219
- - !ruby/object:Gem::Version
220
- version: '0'
221
33
  description: A Rails library for storing user sessions in a backend database
222
34
  email:
223
35
  - me@adamcooke.io
@@ -233,6 +45,7 @@ files:
233
45
  - db/migrate/20170421174100_add_index_to_token_hashes_on_authie_sessions.rb
234
46
  - db/migrate/20180215152200_add_host_to_authie_sessions.rb
235
47
  - db/migrate/20220502180100_add_two_factor_required_to_sessions.rb
48
+ - db/migrate/20230627165500_add_countries_to_authie_sessions.rb
236
49
  - lib/authie.rb
237
50
  - lib/authie/config.rb
238
51
  - lib/authie/controller_delegate.rb
@@ -259,11 +72,11 @@ required_ruby_version: !ruby/object:Gem::Requirement
259
72
  version: '0'
260
73
  required_rubygems_version: !ruby/object:Gem::Requirement
261
74
  requirements:
262
- - - ">"
75
+ - - ">="
263
76
  - !ruby/object:Gem::Version
264
- version: 1.3.1
77
+ version: '0'
265
78
  requirements: []
266
- rubygems_version: 3.3.7
79
+ rubygems_version: 3.3.26
267
80
  signing_key:
268
81
  specification_version: 4
269
82
  summary: A Rails library for storing user sessions in a backend database