authie 3.3.1 → 4.0.0.rc2
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 +4 -4
- data/db/migrate/20141012174250_create_authie_sessions.rb +4 -2
- data/db/migrate/20141013115205_add_indexes_to_authie_sessions.rb +4 -2
- data/db/migrate/20150109144120_add_parent_id_to_authie_sessions.rb +2 -0
- data/db/migrate/20150305135400_add_two_factor_auth_fields_to_authie.rb +3 -1
- data/db/migrate/20170417170000_add_token_hashes_to_authie_sessions.rb +2 -0
- data/db/migrate/20170421174100_add_index_to_token_hashes_on_authie_sessions.rb +3 -1
- data/db/migrate/20180215152200_add_host_to_authie_sessions.rb +2 -0
- data/lib/authie/config.rb +19 -35
- data/lib/authie/controller_delegate.rb +67 -40
- data/lib/authie/controller_extension.rb +14 -37
- data/lib/authie/engine.rb +3 -3
- data/lib/authie/error.rb +2 -0
- data/lib/authie/event_manager.rb +12 -8
- data/lib/authie/rack_controller.rb +6 -10
- data/lib/authie/session.rb +244 -277
- data/lib/authie/session_model.rb +141 -0
- data/lib/authie/user.rb +3 -3
- data/lib/authie/version.rb +8 -1
- data/lib/authie.rb +3 -3
- metadata +215 -28
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d5347676808e3554dde1670a91c8402ed166be59767298dfea961a9020659843
|
4
|
+
data.tar.gz: 03ee0e9cc60e7ae24a9e83c7a6ead5d72ebec109ef558898395d476014843a65
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 219676dee96408c5cb85432ab4d919967415b9e575cb9681c4b4a9d210f041213af2a841a63ebdd4c88d9a8d3856f4ab306ddfd5e4947dee6e3d3654de8538b0
|
7
|
+
data.tar.gz: 7dd321dd2d407fd73b89ea6e1894d60362ac7e4fd792d0d74ea9e2cc5178b30eebd8d42ab3bf7baa356bc3d6f161d6809e0c545d9430d6db3267e8dfbda87190
|
@@ -1,9 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
class CreateAuthieSessions < ActiveRecord::Migration[4.2]
|
2
4
|
def change
|
3
5
|
create_table :authie_sessions do |t|
|
4
6
|
t.string :token, :browser_id
|
5
7
|
t.integer :user_id
|
6
|
-
t.boolean :active, :
|
8
|
+
t.boolean :active, default: true
|
7
9
|
t.text :data
|
8
10
|
t.datetime :expires_at
|
9
11
|
t.datetime :login_at
|
@@ -11,7 +13,7 @@ class CreateAuthieSessions < ActiveRecord::Migration[4.2]
|
|
11
13
|
t.datetime :last_activity_at
|
12
14
|
t.string :last_activity_ip, :last_activity_path
|
13
15
|
t.string :user_agent
|
14
|
-
t.timestamps :
|
16
|
+
t.timestamps null: true
|
15
17
|
end
|
16
18
|
end
|
17
19
|
end
|
@@ -1,8 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
class AddIndexesToAuthieSessions < ActiveRecord::Migration[4.2]
|
2
4
|
def change
|
3
5
|
add_column :authie_sessions, :user_type, :string
|
4
|
-
add_index :authie_sessions, :token, :
|
5
|
-
add_index :authie_sessions, :browser_id, :
|
6
|
+
add_index :authie_sessions, :token, length: 10
|
7
|
+
add_index :authie_sessions, :browser_id, length: 10
|
6
8
|
add_index :authie_sessions, :user_id
|
7
9
|
end
|
8
10
|
end
|
@@ -1,8 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
class AddTwoFactorAuthFieldsToAuthie < ActiveRecord::Migration[4.2]
|
2
4
|
def change
|
3
5
|
add_column :authie_sessions, :two_factored_at, :datetime
|
4
6
|
add_column :authie_sessions, :two_factored_ip, :string
|
5
|
-
add_column :authie_sessions, :requests, :integer, :
|
7
|
+
add_column :authie_sessions, :requests, :integer, default: 0
|
6
8
|
add_column :authie_sessions, :password_seen_at, :datetime
|
7
9
|
end
|
8
10
|
end
|
data/lib/authie/config.rb
CHANGED
@@ -1,48 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'authie/event_manager'
|
2
4
|
|
3
5
|
module Authie
|
4
6
|
class Config
|
7
|
+
attr_accessor :session_inactivity_timeout
|
8
|
+
attr_accessor :persistent_session_length
|
9
|
+
attr_accessor :sudo_session_timeout
|
10
|
+
attr_accessor :browser_id_cookie_name
|
11
|
+
attr_accessor :events
|
5
12
|
|
6
13
|
def initialize
|
7
|
-
@
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
@
|
12
|
-
end
|
13
|
-
attr_writer :session_inactivity_timeout
|
14
|
-
|
15
|
-
def persistent_session_length
|
16
|
-
@persistent_session_length || 2.months
|
17
|
-
end
|
18
|
-
attr_writer :persistent_session_length
|
19
|
-
|
20
|
-
def sudo_session_timeout
|
21
|
-
@sudo_session_timeout || 10.minutes
|
22
|
-
end
|
23
|
-
attr_writer :sudo_session_timeout
|
24
|
-
|
25
|
-
def user_relationship_options
|
26
|
-
@user_relationship_options ||= {}
|
14
|
+
@session_inactivity_timeout = 12.hours
|
15
|
+
@persistent_session_length = 2.months
|
16
|
+
@sudo_session_timeout = 10.minutes
|
17
|
+
@browser_id_cookie_name = :browser_id
|
18
|
+
@events = EventManager.new
|
27
19
|
end
|
20
|
+
end
|
28
21
|
|
29
|
-
|
30
|
-
|
22
|
+
class << self
|
23
|
+
def config
|
24
|
+
@config ||= Config.new
|
31
25
|
end
|
32
|
-
attr_writer :browser_id_cookie_name
|
33
26
|
|
34
|
-
def
|
35
|
-
|
27
|
+
def configure(&block)
|
28
|
+
block.call(config)
|
29
|
+
config
|
36
30
|
end
|
37
31
|
end
|
38
|
-
|
39
|
-
def self.config
|
40
|
-
@config ||= Config.new
|
41
|
-
end
|
42
|
-
|
43
|
-
def self.configure(&block)
|
44
|
-
block.call(config)
|
45
|
-
config
|
46
|
-
end
|
47
|
-
|
48
32
|
end
|
@@ -1,86 +1,113 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'securerandom'
|
2
4
|
require 'authie/session'
|
5
|
+
require 'authie/config'
|
6
|
+
require 'authie/session_model'
|
3
7
|
|
4
8
|
module Authie
|
9
|
+
# The controller delegate implements methods that can be used by a controller. These are then
|
10
|
+
# extended into controllers as needed (see ControllerExtension).
|
5
11
|
class ControllerDelegate
|
6
|
-
|
12
|
+
# @param controller [ActionController::Base]
|
13
|
+
# @return [Authie::ControllerDelegate]
|
7
14
|
def initialize(controller)
|
8
15
|
@controller = controller
|
9
16
|
end
|
10
17
|
|
11
|
-
#
|
18
|
+
# Sets a browser ID. This must be performed on any page request where AUthie will be used.
|
19
|
+
# It should be triggered before any other Authie provided methods. This will ensure that
|
20
|
+
# the given browser ID is unique.
|
21
|
+
#
|
22
|
+
# @return [String] the generated browser ID
|
12
23
|
def set_browser_id
|
13
24
|
until cookies[Authie.config.browser_id_cookie_name]
|
14
25
|
proposed_browser_id = SecureRandom.uuid
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
end
|
26
|
+
next if Authie::SessionModel.where(browser_id: proposed_browser_id).exists?
|
27
|
+
|
28
|
+
cookies[Authie.config.browser_id_cookie_name] = {
|
29
|
+
value: proposed_browser_id,
|
30
|
+
expires: 5.years.from_now,
|
31
|
+
httponly: true,
|
32
|
+
secure: @controller.request.ssl?
|
33
|
+
}
|
34
|
+
Authie.config.events.dispatch(:set_browser_id, proposed_browser_id)
|
25
35
|
end
|
36
|
+
proposed_browser_id
|
26
37
|
end
|
27
38
|
|
28
|
-
# Touch the
|
39
|
+
# Touch the session on each request to ensure that it is validated and all last activity
|
40
|
+
# information is updated. This will return the session if one has been touched otherwise
|
41
|
+
# it will reteurn false if there is no session/not logged in. It is safe to run this on
|
42
|
+
# all requests even if there is no session.
|
43
|
+
#
|
44
|
+
# @return [Authie::Session, false]
|
29
45
|
def touch_auth_session
|
30
|
-
if logged_in?
|
31
|
-
|
32
|
-
|
46
|
+
return auth_session.touch if logged_in?
|
47
|
+
|
48
|
+
false
|
33
49
|
end
|
34
50
|
|
35
|
-
# Return the currently logged in user
|
51
|
+
# Return the user for the currently logged in user or nil if no user is logged in
|
52
|
+
#
|
53
|
+
# @return [ActiveRecord::Base, nil]
|
36
54
|
def current_user
|
37
|
-
|
38
|
-
end
|
55
|
+
return nil unless logged_in?
|
39
56
|
|
40
|
-
|
41
|
-
def current_user=(user)
|
42
|
-
create_auth_session(user)
|
43
|
-
user
|
57
|
+
auth_session.session.user
|
44
58
|
end
|
45
59
|
|
46
|
-
# Create a new session for the given user
|
60
|
+
# Create a new session for the given user. If nil is provided as a user, the existing session
|
61
|
+
# will be invalidated.
|
62
|
+
#
|
63
|
+
# @return [Authie::Session, nil]
|
47
64
|
def create_auth_session(user)
|
48
65
|
if user
|
49
|
-
@auth_session = Authie::Session.start(@controller, :
|
50
|
-
|
51
|
-
auth_session.invalidate! if logged_in?
|
52
|
-
@auth_session = :none
|
66
|
+
@auth_session = Authie::Session.start(@controller, user: user)
|
67
|
+
return @auth_session
|
53
68
|
end
|
69
|
+
|
70
|
+
invalidate_auth_session
|
71
|
+
nil
|
54
72
|
end
|
55
73
|
|
56
|
-
# Invalidate
|
74
|
+
# Invalidate the existing auth session if one exists. Return true if a sesion has been invalidated
|
75
|
+
# otherwise return false.
|
76
|
+
#
|
77
|
+
# @return [Boolean]
|
57
78
|
def invalidate_auth_session
|
58
79
|
if logged_in?
|
59
|
-
auth_session.invalidate
|
60
|
-
@auth_session =
|
61
|
-
true
|
62
|
-
else
|
63
|
-
false
|
80
|
+
auth_session.invalidate
|
81
|
+
@auth_session = nil
|
82
|
+
return true
|
64
83
|
end
|
84
|
+
|
85
|
+
false
|
65
86
|
end
|
66
87
|
|
67
|
-
# Is anyone currently logged in?
|
88
|
+
# Is anyone currently logged in? Return true if there is an auth session present.
|
89
|
+
#
|
90
|
+
# Note: this does not check the validatity of the session. You must always ensure that the `validate`
|
91
|
+
# or `touch` method is invoked to ensure that the session that has been found is active.
|
92
|
+
#
|
93
|
+
# @return [Boolean]
|
68
94
|
def logged_in?
|
69
95
|
auth_session.is_a?(Session)
|
70
96
|
end
|
71
97
|
|
72
|
-
# Return
|
98
|
+
# Return an auth session that has been found in the current cookies.
|
99
|
+
#
|
100
|
+
# @return [Authie::Session]
|
73
101
|
def auth_session
|
74
|
-
@auth_session
|
75
|
-
|
102
|
+
return @auth_session if instance_variable_defined?('@auth_session')
|
103
|
+
|
104
|
+
@auth_session = Authie::Session.get_session(@controller)
|
76
105
|
end
|
77
106
|
|
78
107
|
private
|
79
108
|
|
80
|
-
# Return cookies for the controller
|
81
109
|
def cookies
|
82
110
|
@controller.send(:cookies)
|
83
111
|
end
|
84
|
-
|
85
112
|
end
|
86
113
|
end
|
@@ -1,12 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'authie/controller_delegate'
|
2
4
|
|
3
5
|
module Authie
|
4
6
|
module ControllerExtension
|
7
|
+
class << self
|
8
|
+
def included(base)
|
9
|
+
base.helper_method :logged_in?, :current_user, :auth_session
|
10
|
+
base.before_action :set_browser_id, :touch_auth_session
|
5
11
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
12
|
+
base.delegate :set_browser_id, to: :auth_session_delegate
|
13
|
+
base.delegate :touch_auth_session, to: :auth_session_delegate
|
14
|
+
base.delegate :current_user, to: :auth_session_delegate
|
15
|
+
base.delegate :create_auth_session, to: :auth_session_delegate
|
16
|
+
base.delegate :invalidate_auth_session, to: :auth_session_delegate
|
17
|
+
base.delegate :logged_in?, to: :auth_session_delegate
|
18
|
+
base.delegate :auth_session, to: :auth_session_delegate
|
19
|
+
end
|
10
20
|
end
|
11
21
|
|
12
22
|
private
|
@@ -14,38 +24,5 @@ module Authie
|
|
14
24
|
def auth_session_delegate
|
15
25
|
@auth_session_delegate ||= Authie::ControllerDelegate.new(self)
|
16
26
|
end
|
17
|
-
|
18
|
-
def set_browser_id
|
19
|
-
auth_session_delegate.set_browser_id
|
20
|
-
end
|
21
|
-
|
22
|
-
def touch_auth_session
|
23
|
-
auth_session_delegate.touch_auth_session
|
24
|
-
end
|
25
|
-
|
26
|
-
def current_user
|
27
|
-
auth_session_delegate.current_user
|
28
|
-
end
|
29
|
-
|
30
|
-
def current_user=(user)
|
31
|
-
auth_session_delegate.current_user = user
|
32
|
-
end
|
33
|
-
|
34
|
-
def create_auth_session(user)
|
35
|
-
auth_session_delegate.create_auth_session(user)
|
36
|
-
end
|
37
|
-
|
38
|
-
def invalidate_auth_session
|
39
|
-
auth_session_delegate.invalidate_auth_session
|
40
|
-
end
|
41
|
-
|
42
|
-
def logged_in?
|
43
|
-
auth_session_delegate.logged_in?
|
44
|
-
end
|
45
|
-
|
46
|
-
def auth_session
|
47
|
-
auth_session_delegate.auth_session
|
48
|
-
end
|
49
|
-
|
50
27
|
end
|
51
28
|
end
|
data/lib/authie/engine.rb
CHANGED
@@ -1,9 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Authie
|
2
4
|
class Engine < ::Rails::Engine
|
3
|
-
|
4
5
|
engine_name 'authie'
|
5
6
|
|
6
|
-
initializer 'authie.initialize' do |
|
7
|
+
initializer 'authie.initialize' do |_app|
|
7
8
|
ActiveSupport.on_load :active_record do
|
8
9
|
require 'authie/session'
|
9
10
|
end
|
@@ -13,6 +14,5 @@ module Authie
|
|
13
14
|
include Authie::ControllerExtension
|
14
15
|
end
|
15
16
|
end
|
16
|
-
|
17
17
|
end
|
18
18
|
end
|
data/lib/authie/error.rb
CHANGED
data/lib/authie/event_manager.rb
CHANGED
@@ -1,15 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Authie
|
2
4
|
class EventManager
|
5
|
+
attr_reader :callbacks
|
3
6
|
|
4
7
|
def initialize
|
5
8
|
@callbacks = {}
|
6
9
|
end
|
7
10
|
|
8
11
|
def dispatch(event, *args)
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
12
|
+
callbacks = @callbacks[event.to_sym]
|
13
|
+
return if callbacks.nil?
|
14
|
+
|
15
|
+
callbacks.each do |cb|
|
16
|
+
cb.call(*args)
|
13
17
|
end
|
14
18
|
end
|
15
19
|
|
@@ -19,10 +23,10 @@ module Authie
|
|
19
23
|
end
|
20
24
|
|
21
25
|
def remove(event, block)
|
22
|
-
|
23
|
-
|
24
|
-
end
|
25
|
-
end
|
26
|
+
cb = @callbacks[event.to_sym]
|
27
|
+
return if cb.nil?
|
26
28
|
|
29
|
+
cb.delete(block)
|
30
|
+
end
|
27
31
|
end
|
28
32
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# If you're dealing with your authentication in a middleware and you only have
|
2
4
|
# access to your rack environment, this will wrap around rack and make it look
|
3
5
|
# close enough to an ActionController to work with Authie
|
@@ -9,7 +11,6 @@
|
|
9
11
|
|
10
12
|
module Authie
|
11
13
|
class RackController
|
12
|
-
|
13
14
|
attr_reader :request
|
14
15
|
|
15
16
|
def initialize(env)
|
@@ -26,27 +27,22 @@ module Authie
|
|
26
27
|
def set_browser_id
|
27
28
|
until cookies[:browser_id]
|
28
29
|
proposed_browser_id = SecureRandom.uuid
|
29
|
-
unless Session.where(:
|
30
|
-
cookies[:browser_id] = {:
|
30
|
+
unless Session.where(browser_id: proposed_browser_id).exists?
|
31
|
+
cookies[:browser_id] = { value: proposed_browser_id, expires: 20.years.from_now }
|
31
32
|
end
|
32
33
|
end
|
33
34
|
end
|
34
35
|
|
35
36
|
def current_user=(user)
|
36
|
-
Session.start(self, :
|
37
|
+
Session.start(self, user: user)
|
37
38
|
end
|
38
39
|
|
39
40
|
def current_user
|
40
|
-
if auth_session.is_a?(Session)
|
41
|
-
auth_session.user
|
42
|
-
else
|
43
|
-
nil
|
44
|
-
end
|
41
|
+
auth_session.user if auth_session.is_a?(Session)
|
45
42
|
end
|
46
43
|
|
47
44
|
def auth_session
|
48
45
|
@auth_session ||= Session.get_session(self)
|
49
46
|
end
|
50
|
-
|
51
47
|
end
|
52
48
|
end
|