uber_login 0.2.0 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/lib/uber_login/configuration.rb +23 -0
- data/lib/uber_login/cookie_manager.rb +39 -61
- data/lib/uber_login/session_manager.rb +38 -0
- data/lib/uber_login/storage.rb +31 -0
- data/lib/uber_login/token_encoder.rb +36 -0
- data/lib/uber_login/token_validator.rb +28 -0
- data/lib/uber_login/version.rb +1 -1
- data/lib/uber_login.rb +58 -36
- data/spec/cookie_manager_spec.rb +48 -76
- data/spec/session_manager_spec.rb +80 -0
- data/spec/spec_helper.rb +5 -1
- data/spec/storage_spec.rb +0 -0
- data/spec/token_encoder_spec.rb +58 -0
- data/spec/token_validator_spec.rb +66 -0
- data/spec/uber_login_spec.rb +101 -72
- metadata +13 -1
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
NjcyNWVjZmViMmQ3ZTY4MDljODFjYjAxZDc2YmY5YmE4ZDEyNjhiZA==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
ZDg0ZTA4MzZkODQ4ZThjN2FkOTYyNjllMTk5MDY1ZmUxZDdlN2NmYg==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
NWFjODkyYjYwN2FlNDFkY2I0NTUwZDZlMmIyMGJhMzRiNTg5MGM1YmY0YzVj
|
10
|
+
M2Y0YTBhY2U0NjNkNThiMDg4MDJlYjM4NjAwNWUxNzcxYTc0N2E1MjdmZDZh
|
11
|
+
NmQzYWNkN2Q0YzhhODNlYmQ2ZmNmYTNmMzZjZGRlMzdhNmNkMTE=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
MTJmMWI1MDhjODQzMWZlNWEzYjk2YzQxMTYxYzc3MGEzNWMyNDM5ZWU2MTc1
|
14
|
+
NDM0ZjQ2OGVhMjgxMzlkN2QyZGJlNThhODNiMDNmOWFjYTI1ZWU5MjVmMWVk
|
15
|
+
ZjlmOWI5N2JjMGJmYmY0MjdmNGNiODkzZjc0YWZkMzg2OGZiZTU=
|
@@ -2,14 +2,37 @@
|
|
2
2
|
# Use this class in app/config/initializers to change configuration parameters.
|
3
3
|
module UberLogin
|
4
4
|
class Configuration
|
5
|
+
# Allow the same user to login on many different devices.
|
6
|
+
# This is only effective if strong_sessions is +true+. Otherwise it only affects persistent logins.
|
7
|
+
# Defaults to +true+
|
5
8
|
attr_accessor :allow_multiple_login
|
9
|
+
|
10
|
+
# The validity of a login token (be it a cookie or session token). Tokens whose age is larger than that are
|
11
|
+
# considered expired and not valid.
|
12
|
+
# Defaults to +nil+ (no expiration)
|
6
13
|
attr_accessor :token_expiration
|
14
|
+
|
15
|
+
# A token is considered valid only if brought by the same IP address to which it was assigned.
|
16
|
+
# This would provide a very effective solution against Cookie sniffing, unless it would affect legitimate users a
|
17
|
+
# lot. 99% of ISPs will change user IP on each connecition. Also mobile devices might change IP many times in a
|
18
|
+
# hour. Setting this to true may disconnect many mobile users each minute.
|
19
|
+
# Only decently usable in a private network where all IPs are static (or if you're really paranoid).
|
20
|
+
# Defaults to +false+
|
7
21
|
attr_accessor :tie_tokens_to_ip
|
8
22
|
|
23
|
+
# Non persistent sessions are saved to the database too. On each request the session token is checked against the
|
24
|
+
# database just like the cookies one. It won't refresh it, however.
|
25
|
+
# This allows you to do nice things, like logging out users, just by removing the token from the database. Or having
|
26
|
+
# a full list of open sessions of any kind on any device.
|
27
|
+
# Even though this is strongly suggested to be +true+, it might impact performance, issuing a query on almost
|
28
|
+
# each page load. Be sure to index :uid and :sequence together on the +login_tokens+ table.
|
29
|
+
attr_accessor :strong_sessions
|
30
|
+
|
9
31
|
def initialize
|
10
32
|
self.allow_multiple_login = true
|
11
33
|
self.token_expiration = nil
|
12
34
|
self.tie_tokens_to_ip = false
|
35
|
+
self.strong_sessions = true
|
13
36
|
end
|
14
37
|
end
|
15
38
|
|
@@ -1,66 +1,44 @@
|
|
1
|
+
require 'uber_login/storage'
|
2
|
+
require 'uber_login/token_encoder'
|
3
|
+
require 'uber_login/token_validator'
|
4
|
+
|
1
5
|
##
|
2
6
|
# This class handles the +:uid+ and +:ulogin+ cookies
|
3
7
|
# It builds and sets the cookies, clears them, checks for their validity.
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
end
|
40
|
-
|
41
|
-
def sequence_and_token
|
42
|
-
@cookies[:ulogin].split(':')
|
43
|
-
end
|
44
|
-
|
45
|
-
def sequence
|
46
|
-
sequence_and_token[0]
|
47
|
-
end
|
48
|
-
|
49
|
-
def token
|
50
|
-
sequence_and_token[1]
|
51
|
-
end
|
52
|
-
|
53
|
-
# Validity checks
|
54
|
-
|
55
|
-
def token_match(row)
|
56
|
-
BCrypt::Password.new(row.token) == token
|
57
|
-
end
|
58
|
-
|
59
|
-
def ip_equality(row)
|
60
|
-
row.ip_address == @request.remote_ip
|
61
|
-
end
|
62
|
-
|
63
|
-
def expiration(row)
|
64
|
-
row.updated_at >= Time.now - UberLogin.configuration.token_expiration
|
8
|
+
module UberLogin
|
9
|
+
class CookieManager
|
10
|
+
def initialize(cookies, request)
|
11
|
+
@cookies = cookies
|
12
|
+
@request = request
|
13
|
+
end
|
14
|
+
|
15
|
+
##
|
16
|
+
# Sets the +:uid+ and +:ulogin+ cookies for next login
|
17
|
+
def persistent_login(uid, composite)
|
18
|
+
@cookies.permanent[:uid] = uid
|
19
|
+
@cookies.permanent[:ulogin] = TokenEncoder.encode_array composite
|
20
|
+
end
|
21
|
+
|
22
|
+
##
|
23
|
+
# Clears +:uid+ and +:ulogin+ cookies
|
24
|
+
def clear
|
25
|
+
@cookies.delete :uid
|
26
|
+
@cookies.delete :ulogin
|
27
|
+
end
|
28
|
+
|
29
|
+
##
|
30
|
+
# Returns true if cookies are considered valid from TokenEncoder validation rules
|
31
|
+
def valid?
|
32
|
+
token_row = Storage.find_composite(@cookies[:uid], @cookies[:ulogin])
|
33
|
+
TokenValidator.new(TokenEncoder.token(@cookies[:ulogin]), @request).valid?(token_row)
|
34
|
+
rescue
|
35
|
+
false
|
36
|
+
end
|
37
|
+
|
38
|
+
##
|
39
|
+
# Returns true if the +:uid+ and +:ulogin+ cookies are set
|
40
|
+
def login_cookies?
|
41
|
+
@cookies[:uid] and @cookies[:ulogin]
|
42
|
+
end
|
65
43
|
end
|
66
44
|
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'uber_login/storage'
|
2
|
+
require 'uber_login/token_encoder'
|
3
|
+
require 'uber_login/token_validator'
|
4
|
+
|
5
|
+
##
|
6
|
+
# This class handles the +:uid+ and +:ulogin+ session variables
|
7
|
+
# It builds and sets the session variables, clears them, checks for their validity.
|
8
|
+
module UberLogin
|
9
|
+
class SessionManager
|
10
|
+
def initialize(session, request)
|
11
|
+
@session = session
|
12
|
+
@request = request
|
13
|
+
end
|
14
|
+
|
15
|
+
##
|
16
|
+
# Sets the +:uid+ and +:ulogin+ session variables
|
17
|
+
def login(uid, composite)
|
18
|
+
@session[:uid] = uid
|
19
|
+
@session[:ulogin] = TokenEncoder.encode_array(composite) if UberLogin.configuration.strong_sessions
|
20
|
+
end
|
21
|
+
|
22
|
+
##
|
23
|
+
# Clears +:uid+ and +:ulogin+ session variables
|
24
|
+
def clear
|
25
|
+
@session.delete :uid
|
26
|
+
@session.delete :ulogin
|
27
|
+
end
|
28
|
+
|
29
|
+
##
|
30
|
+
# Returns true if the session is considered valid from TokenEncoder validation rules
|
31
|
+
def valid?
|
32
|
+
token_row = Storage.find_composite(@session[:uid], @session[:ulogin])
|
33
|
+
TokenValidator.new(TokenEncoder.token(@session[:ulogin]), @request).valid?(token_row)
|
34
|
+
rescue
|
35
|
+
false
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module UberLogin
|
2
|
+
class Storage
|
3
|
+
class << self
|
4
|
+
def find(uid, sequence)
|
5
|
+
LoginToken.find_by(uid: uid, sequence: sequence)
|
6
|
+
end
|
7
|
+
|
8
|
+
def find_composite(uid, composite)
|
9
|
+
find(uid, TokenEncoder.sequence(composite))
|
10
|
+
rescue # composite might invalid if cookies are tampered
|
11
|
+
nil
|
12
|
+
end
|
13
|
+
|
14
|
+
def build(uid, composite)
|
15
|
+
LoginToken.new(
|
16
|
+
uid: uid,
|
17
|
+
sequence: TokenEncoder.sequence(composite),
|
18
|
+
token: TokenEncoder.token_hash(composite)
|
19
|
+
)
|
20
|
+
end
|
21
|
+
|
22
|
+
def delete_all(uid)
|
23
|
+
LoginToken.destroy_all(uid: uid)
|
24
|
+
end
|
25
|
+
|
26
|
+
def delete_all_but(uid, composite)
|
27
|
+
# TODO: How to make this ORM agnostic?
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'bcrypt'
|
2
|
+
|
3
|
+
module UberLogin
|
4
|
+
class TokenEncoder
|
5
|
+
class << self
|
6
|
+
def generate
|
7
|
+
# 9 and 21 are both multiple of 3, so we do not get base64 padding (==)
|
8
|
+
[ SecureRandom.urlsafe_base64(9), SecureRandom.base64(21) ]
|
9
|
+
end
|
10
|
+
|
11
|
+
def encode(sequence, token)
|
12
|
+
encode_array [ sequence, token ]
|
13
|
+
end
|
14
|
+
|
15
|
+
def encode_array(composite_array)
|
16
|
+
composite_array.join(':')
|
17
|
+
end
|
18
|
+
|
19
|
+
def decode(composite)
|
20
|
+
composite.split(':')
|
21
|
+
end
|
22
|
+
|
23
|
+
def sequence(composite)
|
24
|
+
decode(composite)[0]
|
25
|
+
end
|
26
|
+
|
27
|
+
def token(composite)
|
28
|
+
decode(composite)[1]
|
29
|
+
end
|
30
|
+
|
31
|
+
def token_hash(composite)
|
32
|
+
BCrypt::Password.create(token(composite)).to_s
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module UberLogin
|
2
|
+
class TokenValidator
|
3
|
+
def initialize(token, request)
|
4
|
+
@token = token
|
5
|
+
@request = request
|
6
|
+
@validity_checks = [ :token_match ]
|
7
|
+
@validity_checks << :ip_equality if UberLogin.configuration.tie_tokens_to_ip
|
8
|
+
@validity_checks << :expiration if UberLogin.configuration.token_expiration
|
9
|
+
end
|
10
|
+
|
11
|
+
def valid?(row)
|
12
|
+
@validity_checks.all? { |check| send(check, row) }
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
def token_match(row)
|
17
|
+
BCrypt::Password.new(row.token) == @token
|
18
|
+
end
|
19
|
+
|
20
|
+
def ip_equality(row)
|
21
|
+
row.ip_address == @request.remote_ip
|
22
|
+
end
|
23
|
+
|
24
|
+
def expiration(row)
|
25
|
+
row.updated_at >= Time.now - UberLogin.configuration.token_expiration
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
data/lib/uber_login/version.rb
CHANGED
data/lib/uber_login.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'uber_login/version'
|
2
2
|
require 'uber_login/cookie_manager'
|
3
3
|
require 'uber_login/configuration'
|
4
|
+
require 'uber_login/session_manager'
|
4
5
|
require 'securerandom'
|
5
6
|
require 'bcrypt'
|
6
7
|
require 'user_agent'
|
@@ -8,7 +9,10 @@ require 'user_agent'
|
|
8
9
|
module UberLogin
|
9
10
|
##
|
10
11
|
# Returns the logged in user.
|
11
|
-
# If session[+:uid+] is set
|
12
|
+
# If session[+:uid+] is set:
|
13
|
+
# * if strong sessions are enabled, it checks for session[+:ulogin+] and tests its value against the database
|
14
|
+
# * if strong sessions are not enabled, it only returns the corresponding +User+
|
15
|
+
#
|
12
16
|
# If session[+:uid+] is NOT set but cookies[+:uid+] and cookies[+:ulogin+] ARE:
|
13
17
|
# * It dissects +:ulogin+ into Sequence and Token
|
14
18
|
# * Looks for a LoginToken from UID and Sequence
|
@@ -26,24 +30,31 @@ module UberLogin
|
|
26
30
|
# Logs in the given +user+
|
27
31
|
# If +remember+ is true all the needed cookies are set.
|
28
32
|
# session[+:uid+] is set to user.id
|
33
|
+
# If strong sessions are enabled session[+:ulogin+] is set to the same value that cookies[+:ulogin+] would have
|
29
34
|
def login(user, remember = false)
|
30
35
|
logout_all unless UberLogin.configuration.allow_multiple_login
|
31
36
|
|
32
|
-
|
33
|
-
|
37
|
+
if strong_sessions or remember
|
38
|
+
composite = generate_and_save_token(user.id)
|
39
|
+
cookie_manager.persistent_login(user.id, composite) if remember
|
40
|
+
else
|
41
|
+
composite = nil
|
42
|
+
end
|
43
|
+
|
44
|
+
session_manager.login(user.id, composite)
|
34
45
|
end
|
35
46
|
|
36
47
|
##
|
37
|
-
#
|
38
|
-
#
|
39
|
-
#
|
48
|
+
# If sequence is nil it clears the current session and if remember cookies are in place they're cleared
|
49
|
+
# and corresponding token removed from the database.
|
50
|
+
# If sequence is not nil it only removes the sequence and token from the database.
|
40
51
|
def logout(sequence = nil)
|
41
|
-
if sequence
|
42
|
-
delete_from_database
|
43
|
-
|
44
|
-
session.delete(:uid)
|
45
|
-
delete_from_database if cookies[:uid]
|
52
|
+
if sequence.nil? or sequence == current_sequence
|
53
|
+
delete_from_database if cookies[:uid] or strong_sessions
|
54
|
+
session_manager.clear
|
46
55
|
cookie_manager.clear
|
56
|
+
else
|
57
|
+
delete_from_database(sequence)
|
47
58
|
end
|
48
59
|
end
|
49
60
|
|
@@ -51,8 +62,8 @@ module UberLogin
|
|
51
62
|
# Deletes all "remember me" session for this user from whatever device
|
52
63
|
# he/she has ever used to login.
|
53
64
|
def logout_all
|
54
|
-
|
55
|
-
|
65
|
+
Storage.delete_all session[:uid]
|
66
|
+
session_manager.clear
|
56
67
|
cookie_manager.clear
|
57
68
|
end
|
58
69
|
|
@@ -61,11 +72,19 @@ module UberLogin
|
|
61
72
|
@cookie_manager ||= CookieManager.new(cookies, request)
|
62
73
|
end
|
63
74
|
|
75
|
+
def session_manager
|
76
|
+
@session_manager ||= SessionManager.new(session, request)
|
77
|
+
end
|
78
|
+
|
64
79
|
# See +current_user+
|
65
80
|
def current_user_uncached
|
66
|
-
|
67
|
-
|
68
|
-
|
81
|
+
if session[:uid]
|
82
|
+
logout if strong_sessions and !session_manager.valid?
|
83
|
+
else
|
84
|
+
login_from_cookies if cookie_manager.login_cookies?
|
85
|
+
end
|
86
|
+
|
87
|
+
User.find(session[:uid]) rescue nil
|
69
88
|
end
|
70
89
|
|
71
90
|
##
|
@@ -74,6 +93,7 @@ module UberLogin
|
|
74
93
|
if cookie_manager.valid?
|
75
94
|
session[:uid] = cookies[:uid]
|
76
95
|
generate_new_token
|
96
|
+
session[:ulogin] = cookies[:ulogin]
|
77
97
|
session[:uid]
|
78
98
|
else
|
79
99
|
cookie_manager.clear
|
@@ -86,7 +106,8 @@ module UberLogin
|
|
86
106
|
# Sets the user cookies to match the new values
|
87
107
|
def generate_new_token
|
88
108
|
delete_from_database
|
89
|
-
|
109
|
+
composite = generate_and_save_token(cookies[:uid])
|
110
|
+
cookie_manager.persistent_login(cookies[:uid], composite)
|
90
111
|
end
|
91
112
|
|
92
113
|
##
|
@@ -96,21 +117,16 @@ module UberLogin
|
|
96
117
|
#
|
97
118
|
# +:sequence+ is used to choose between all possible user login tokens
|
98
119
|
# +:token+ is stored +bcrypt+ed in the database and then compared on login
|
99
|
-
def
|
100
|
-
sequence, token =
|
101
|
-
|
102
|
-
|
120
|
+
def generate_and_save_token(uid)
|
121
|
+
sequence, token = TokenEncoder.generate
|
122
|
+
save_to_database(uid, sequence, token)
|
123
|
+
[ sequence, token ]
|
103
124
|
end
|
104
125
|
|
105
126
|
##
|
106
127
|
# Creates a LoginToken based on the +uid+, +sequence+ and hashed +token+
|
107
|
-
def save_to_database
|
108
|
-
token_row =
|
109
|
-
uid: cookies[:uid],
|
110
|
-
sequence: cookie_manager.sequence,
|
111
|
-
token: cookie_manager.hashed_token
|
112
|
-
)
|
113
|
-
|
128
|
+
def save_to_database(uid, sequence, token)
|
129
|
+
token_row = Storage.build(uid, TokenEncoder.encode(sequence, token))
|
114
130
|
set_user_data token_row
|
115
131
|
|
116
132
|
token_row.save!
|
@@ -119,15 +135,13 @@ module UberLogin
|
|
119
135
|
##
|
120
136
|
# Removes a LoginToken with current +uid+ and given +sequence+
|
121
137
|
# If +sequence+ is nil it is taken from the cookies.
|
138
|
+
#
|
139
|
+
# A token might have already been destroyed from another client with the intent of disconnecting
|
140
|
+
# the current session.
|
122
141
|
def delete_from_database(sequence = nil)
|
123
|
-
sequence = sequence ||
|
124
|
-
token =
|
125
|
-
token.destroy
|
126
|
-
end
|
127
|
-
|
128
|
-
def generate_sequence_and_token
|
129
|
-
# 9 and 21 are both multiple of 3, so we do not get base64 padding (==)
|
130
|
-
[ SecureRandom.base64(9), SecureRandom.base64(21) ]
|
142
|
+
sequence = sequence || current_sequence
|
143
|
+
token = Storage.find(cookies[:uid] || session[:uid], sequence)
|
144
|
+
token.destroy if token
|
131
145
|
end
|
132
146
|
|
133
147
|
def set_user_data(row)
|
@@ -137,4 +151,12 @@ module UberLogin
|
|
137
151
|
row.os = user_agent.os if row.respond_to? :os=
|
138
152
|
row.browser = user_agent.browser + ' ' + user_agent.version if row.respond_to? :browser=
|
139
153
|
end
|
154
|
+
|
155
|
+
def strong_sessions
|
156
|
+
UberLogin.configuration.strong_sessions
|
157
|
+
end
|
158
|
+
|
159
|
+
def current_sequence
|
160
|
+
TokenEncoder.sequence(cookies[:ulogin] || session[:ulogin])
|
161
|
+
end
|
140
162
|
end
|
data/spec/cookie_manager_spec.rb
CHANGED
@@ -1,60 +1,54 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
describe CookieManager do
|
4
|
-
let(:
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
before { LoginToken.stub(:find_by).and_return fake_token }
|
16
|
-
|
17
|
-
it 'always executes token_match' do
|
18
|
-
expect(cookie_manager).to receive(:token_match)
|
19
|
-
cookie_manager.valid?
|
20
|
-
end
|
3
|
+
describe UberLogin::CookieManager do
|
4
|
+
let(:user) { double(id: 100) }
|
5
|
+
let(:controller) { ApplicationController.new }
|
6
|
+
let(:session) { controller.session }
|
7
|
+
let(:cookies) { controller.cookies }
|
8
|
+
let(:cookie_manager) { UberLogin::CookieManager.new(cookies, FakeRequest.new) }
|
9
|
+
|
10
|
+
describe '#persistent_login' do
|
11
|
+
it 'sets the :uid cookie' do
|
12
|
+
cookie_manager.persistent_login(100, [ 'dead', 'beef' ])
|
13
|
+
expect(cookies[:uid]).to eq 100
|
14
|
+
end
|
21
15
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
16
|
+
it 'sets the :ulogin cookie' do
|
17
|
+
cookie_manager.persistent_login(100, [ 'dead', 'beef' ])
|
18
|
+
expect(cookies[:ulogin]).to eq 'dead:beef'
|
19
|
+
end
|
20
|
+
end
|
26
21
|
|
27
|
-
|
28
|
-
|
22
|
+
describe '#clear' do
|
23
|
+
before { controller.login(user, true) }
|
29
24
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
end
|
25
|
+
it 'deletes the :uid cookie' do
|
26
|
+
cookie_manager.clear
|
27
|
+
expect(cookies[:uid]).to be_nil
|
28
|
+
end
|
35
29
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
30
|
+
it 'deletes the :ulogin cookie' do
|
31
|
+
cookie_manager.clear
|
32
|
+
expect(cookies[:ulogin]).to be_nil
|
33
|
+
end
|
34
|
+
end
|
40
35
|
|
41
|
-
|
42
|
-
|
36
|
+
describe '#valid?' do
|
37
|
+
before { controller.login(user, true) }
|
43
38
|
|
44
|
-
|
45
|
-
|
46
|
-
cookie_manager.valid?
|
47
|
-
end
|
48
|
-
end
|
39
|
+
context 'User id and sequence combination is found' do
|
40
|
+
before { UberLogin::Storage.stub(:find_composite).and_return user }
|
49
41
|
|
50
42
|
context 'all checks return true' do
|
43
|
+
before { UberLogin::TokenValidator.any_instance.stub(:valid?).and_return true }
|
44
|
+
|
51
45
|
it 'returns true' do
|
52
46
|
expect(cookie_manager.valid?).to be_true
|
53
47
|
end
|
54
48
|
end
|
55
49
|
|
56
50
|
context 'any check fails' do
|
57
|
-
before {
|
51
|
+
before { UberLogin::TokenValidator.any_instance.stub(:valid?).and_return false }
|
58
52
|
|
59
53
|
it 'returns false' do
|
60
54
|
expect(cookie_manager.valid?).to be_false
|
@@ -63,7 +57,7 @@ describe CookieManager do
|
|
63
57
|
end
|
64
58
|
|
65
59
|
context 'User id and sequence combination is not found' do
|
66
|
-
before {
|
60
|
+
before { UberLogin::Storage.stub(:find).and_return nil }
|
67
61
|
|
68
62
|
it 'returns false' do
|
69
63
|
expect(cookie_manager.valid?).to be_false
|
@@ -71,45 +65,23 @@ describe CookieManager do
|
|
71
65
|
end
|
72
66
|
end
|
73
67
|
|
74
|
-
describe '#
|
75
|
-
before {
|
68
|
+
describe '#login_cookies?' do
|
69
|
+
before { controller.login(user, true) }
|
76
70
|
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
it 'returns false if tokens are not matched' do
|
83
|
-
row = double(token: BCrypt::Password.create('s3cr3t', cost: 1))
|
84
|
-
expect(cookie_manager.token_match(row)).to be_false
|
85
|
-
end
|
86
|
-
end
|
87
|
-
|
88
|
-
describe '#ip_equality' do
|
89
|
-
before { FakeRequest.any_instance.stub(:remote_ip).and_return '10.10.10.10' }
|
90
|
-
|
91
|
-
it 'returns true if IPs are equal' do
|
92
|
-
row = double(ip_address: '10.10.10.10')
|
93
|
-
expect(cookie_manager.ip_equality(row)).to be_true
|
94
|
-
end
|
95
|
-
|
96
|
-
it 'returns false if IPs are different' do
|
97
|
-
row = double(ip_address: '192.168.1.1')
|
98
|
-
expect(cookie_manager.ip_equality(row)).to be_false
|
71
|
+
context 'both cookies are set' do
|
72
|
+
it 'returns true' do
|
73
|
+
expect(cookie_manager.login_cookies?).to be_true
|
74
|
+
end
|
99
75
|
end
|
100
|
-
end
|
101
|
-
|
102
|
-
describe '#expiration' do
|
103
|
-
before { UberLogin.configuration.token_expiration = 86400 }
|
104
76
|
|
105
|
-
it 'returns
|
106
|
-
|
107
|
-
expect(cookie_manager.
|
77
|
+
it 'returns false if uid is missing' do
|
78
|
+
cookies.delete :uid
|
79
|
+
expect(cookie_manager.login_cookies?).to be_false
|
108
80
|
end
|
109
81
|
|
110
|
-
it 'returns false if
|
111
|
-
|
112
|
-
expect(cookie_manager.
|
82
|
+
it 'returns false if ulogin is missing' do
|
83
|
+
cookies.delete :ulogin
|
84
|
+
expect(cookie_manager.login_cookies?).to be_false
|
113
85
|
end
|
114
86
|
end
|
115
87
|
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe UberLogin::SessionManager do
|
4
|
+
let(:user) { double(id: 100) }
|
5
|
+
let(:controller) { ApplicationController.new }
|
6
|
+
let(:session) { controller.session }
|
7
|
+
let(:cookies) { controller.cookies }
|
8
|
+
let(:session_manager) { UberLogin::SessionManager.new(session, FakeRequest.new) }
|
9
|
+
|
10
|
+
describe '#login' do
|
11
|
+
it 'sets the :uid variable' do
|
12
|
+
session_manager.login(100, [ 'dead', 'beef' ])
|
13
|
+
expect(session[:uid]).to eq 100
|
14
|
+
end
|
15
|
+
|
16
|
+
context 'strong_sessions are not enabled' do
|
17
|
+
before { UberLogin.configuration.strong_sessions = false }
|
18
|
+
|
19
|
+
it 'does not set the :ulogin cookie' do
|
20
|
+
session_manager.login(100, [ 'dead', 'beef' ])
|
21
|
+
expect(session[:ulogin]).to be_nil
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
context 'strong_sessions are enabled' do
|
26
|
+
before { UberLogin.configuration.strong_sessions = true }
|
27
|
+
|
28
|
+
it 'sets the :ulogin cookie' do
|
29
|
+
session_manager.login(100, [ 'dead', 'beef' ])
|
30
|
+
expect(session[:ulogin]).to_not be_nil
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe '#clear' do
|
36
|
+
before { controller.login(user, true) }
|
37
|
+
|
38
|
+
it 'deletes the :uid variable' do
|
39
|
+
session_manager.clear
|
40
|
+
expect(session[:uid]).to be_nil
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'deletes the :ulogin variable' do
|
44
|
+
session_manager.clear
|
45
|
+
expect(session[:ulogin]).to be_nil
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
describe '#valid?' do
|
50
|
+
before { controller.login(user, true) }
|
51
|
+
|
52
|
+
context 'User id and sequence combination is found' do
|
53
|
+
before { UberLogin::Storage.stub(:find_composite).and_return user }
|
54
|
+
|
55
|
+
context 'all checks return true' do
|
56
|
+
before { UberLogin::TokenValidator.any_instance.stub(:valid?).and_return true }
|
57
|
+
|
58
|
+
it 'returns true' do
|
59
|
+
expect(session_manager.valid?).to be_true
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
context 'any check fails' do
|
64
|
+
before { UberLogin::TokenValidator.any_instance.stub(:valid?).and_return false }
|
65
|
+
|
66
|
+
it 'returns false' do
|
67
|
+
expect(session_manager.valid?).to be_false
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
context 'User id and sequence combination is not found' do
|
73
|
+
before { UberLogin::Storage.stub(:find).and_return nil }
|
74
|
+
|
75
|
+
it 'returns false' do
|
76
|
+
expect(session_manager.valid?).to be_false
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -63,6 +63,10 @@ class LoginToken
|
|
63
63
|
new
|
64
64
|
end
|
65
65
|
|
66
|
+
def self.destroy_all(hash)
|
67
|
+
|
68
|
+
end
|
69
|
+
|
66
70
|
def updated_at
|
67
71
|
Time.now - 100
|
68
72
|
end
|
@@ -78,6 +82,6 @@ class User
|
|
78
82
|
end
|
79
83
|
|
80
84
|
def self.find(id)
|
81
|
-
User.new(id: id)
|
85
|
+
id ? User.new(id: id) : nil
|
82
86
|
end
|
83
87
|
end
|
File without changes
|
@@ -0,0 +1,58 @@
|
|
1
|
+
describe UberLogin::TokenEncoder do
|
2
|
+
describe '#generate' do
|
3
|
+
it 'returns an array of size 2' do
|
4
|
+
expect(UberLogin::TokenEncoder.generate.size).to eq 2
|
5
|
+
end
|
6
|
+
end
|
7
|
+
|
8
|
+
describe '#encode' do
|
9
|
+
it 'retuns a string' do
|
10
|
+
expect(UberLogin::TokenEncoder.encode('what', 'ever').class).to eq String
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'returns the two arguments separated by colons' do
|
14
|
+
expect(UberLogin::TokenEncoder.encode('what', 'ever')).to eq 'what:ever'
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe '#encode_array' do
|
19
|
+
it 'retuns a string' do
|
20
|
+
expect(UberLogin::TokenEncoder.encode_array([ 'what', 'ever' ]).class).to eq String
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'returns the two arguments separated by colons' do
|
24
|
+
expect(UberLogin::TokenEncoder.encode_array([ 'what', 'ever' ])).to eq 'what:ever'
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe '#decode' do
|
29
|
+
it 'returns an array of size 2' do
|
30
|
+
expect(UberLogin::TokenEncoder.decode('dead:beef').size).to eq 2
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'returns the two elements of the token' do
|
34
|
+
expect(UberLogin::TokenEncoder.decode('what:ever')).to eq [ 'what', 'ever' ]
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe '#sequence' do
|
39
|
+
it 'returns the first part of the token' do
|
40
|
+
expect(UberLogin::TokenEncoder.sequence('what:ever')).to eq 'what'
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
describe '#token' do
|
45
|
+
it 'returns the second part of the token' do
|
46
|
+
expect(UberLogin::TokenEncoder.token('what:ever')).to eq 'ever'
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
describe '#token_hash' do
|
51
|
+
it 'returns the second part of the token as a hash' do
|
52
|
+
token = UberLogin::TokenEncoder.token('what:ever')
|
53
|
+
hash = UberLogin::TokenEncoder.token_hash('what:ever')
|
54
|
+
|
55
|
+
expect(BCrypt::Password.new(hash)).to eq token
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe UberLogin::TokenValidator do
|
4
|
+
let(:token_validator) { UberLogin::TokenValidator.new('secret', FakeRequest.new) }
|
5
|
+
let(:fake_token) {
|
6
|
+
LoginToken.new(
|
7
|
+
token: BCrypt::Password.create("beef"),
|
8
|
+
ip_address: '192.168.1.1'
|
9
|
+
)
|
10
|
+
}
|
11
|
+
|
12
|
+
describe '#valid?' do
|
13
|
+
it 'always executes token_match' do
|
14
|
+
expect(token_validator).to receive(:token_match)
|
15
|
+
token_validator.valid?(fake_token)
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'does not run ip_equality by default' do
|
19
|
+
expect(token_validator).to_not receive(:ip_equality)
|
20
|
+
token_validator.valid?(fake_token)
|
21
|
+
end
|
22
|
+
|
23
|
+
context 'if IP are tied to tokens' do
|
24
|
+
before { UberLogin.configuration.tie_tokens_to_ip = true }
|
25
|
+
let(:token_validator) { UberLogin::TokenValidator.new('secret', FakeRequest.new) }
|
26
|
+
|
27
|
+
it 'executes ip_equality' do
|
28
|
+
token_validator.stub(:token_match).and_return true
|
29
|
+
expect(token_validator).to receive(:ip_equality)
|
30
|
+
token_validator.valid?(fake_token)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'does not run expiration by default' do
|
35
|
+
expect(token_validator).to_not receive(:expiration)
|
36
|
+
token_validator.valid?(fake_token)
|
37
|
+
end
|
38
|
+
|
39
|
+
context 'if tokens do expire' do
|
40
|
+
before { UberLogin.configuration.token_expiration = 86400 }
|
41
|
+
let(:token_validator) { UberLogin::TokenValidator.new('secret', FakeRequest.new) }
|
42
|
+
|
43
|
+
it 'executes expiration' do
|
44
|
+
token_validator.stub(:token_match).and_return true
|
45
|
+
expect(token_validator).to receive(:expiration)
|
46
|
+
token_validator.valid?(fake_token)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
context 'all checks return true' do
|
51
|
+
before { Array.any_instance.stub(:all?).and_return true }
|
52
|
+
|
53
|
+
it 'returns true' do
|
54
|
+
expect(token_validator.valid?(fake_token)).to be_true
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
context 'any check fails' do
|
59
|
+
before { Array.any_instance.stub(:all?).and_return false }
|
60
|
+
|
61
|
+
it 'returns false' do
|
62
|
+
expect(token_validator.valid?(fake_token)).to be_false
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
data/spec/uber_login_spec.rb
CHANGED
@@ -12,6 +12,34 @@ describe UberLogin do
|
|
12
12
|
controller.login(user)
|
13
13
|
expect(session[:uid]).to eq 100
|
14
14
|
end
|
15
|
+
|
16
|
+
context 'sessions have stored tokens' do
|
17
|
+
before { UberLogin.configuration.strong_sessions = true }
|
18
|
+
|
19
|
+
it 'saves a token to database' do
|
20
|
+
expect_any_instance_of(LoginToken).to receive :save!
|
21
|
+
controller.login(user)
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'sets session[:ulogin]' do
|
25
|
+
controller.login(user)
|
26
|
+
expect(session[:ulogin]).to_not be_nil
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
context 'sessions do not have stored tokens' do
|
31
|
+
before { UberLogin.configuration.strong_sessions = false }
|
32
|
+
|
33
|
+
it 'does not save a token to database' do
|
34
|
+
expect_any_instance_of(LoginToken).to_not receive :save!
|
35
|
+
controller.login(user)
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'does not set session[:ulogin]' do
|
39
|
+
controller.login(user)
|
40
|
+
expect(session[:ulogin]).to be_nil
|
41
|
+
end
|
42
|
+
end
|
15
43
|
end
|
16
44
|
|
17
45
|
context 'remember is true' do
|
@@ -27,7 +55,7 @@ describe UberLogin do
|
|
27
55
|
|
28
56
|
it 'sets the ulogin cookie' do
|
29
57
|
controller.login(user, true)
|
30
|
-
expect(cookies[:ulogin]).to match(/[a-z0-
|
58
|
+
expect(cookies[:ulogin]).to match(/[a-z0-9_\-]+:[a-z0-9+\/]+/i)
|
31
59
|
end
|
32
60
|
|
33
61
|
it 'sets both cookies as persistent' do
|
@@ -37,37 +65,40 @@ describe UberLogin do
|
|
37
65
|
end
|
38
66
|
|
39
67
|
context 'only one session is allowed per user' do
|
40
|
-
before { UberLogin
|
68
|
+
before { UberLogin.configuration.allow_multiple_login = false }
|
41
69
|
|
42
70
|
it 'clears all the other tokens' do
|
43
|
-
|
71
|
+
expect(LoginToken).to receive :destroy_all
|
44
72
|
controller.login(user)
|
45
73
|
end
|
46
74
|
end
|
47
75
|
end
|
48
76
|
|
49
77
|
describe '#logout' do
|
78
|
+
before { controller.login(user, true) }
|
79
|
+
|
50
80
|
context 'sequence is nil' do
|
51
81
|
it 'deletes session[:uid]' do
|
52
|
-
controller.login(user)
|
53
82
|
controller.logout
|
54
83
|
expect(session[:uid]).to be_nil
|
55
84
|
end
|
56
85
|
|
57
|
-
|
58
|
-
|
86
|
+
it 'deletes session[:ulogin]' do
|
87
|
+
controller.logout
|
88
|
+
expect(session[:ulogin]).to be_nil
|
89
|
+
end
|
59
90
|
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
91
|
+
it 'deletes cookies[:uid]' do
|
92
|
+
controller.logout
|
93
|
+
expect(cookies[:uid]).to be_nil
|
94
|
+
end
|
64
95
|
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
end
|
96
|
+
it 'deletes cookies[:ulogin]' do
|
97
|
+
controller.logout
|
98
|
+
expect(cookies[:ulogin]).to be_nil
|
99
|
+
end
|
70
100
|
|
101
|
+
context 'persistent login was made' do
|
71
102
|
it 'deletes a LoginToken row' do
|
72
103
|
expect {
|
73
104
|
controller.logout
|
@@ -76,9 +107,37 @@ describe UberLogin do
|
|
76
107
|
end
|
77
108
|
end
|
78
109
|
|
79
|
-
context 'sequence is
|
80
|
-
|
110
|
+
context 'sequence is equal to current user sequence' do
|
111
|
+
it 'deletes session[:uid]' do
|
112
|
+
controller.logout(UberLogin::TokenEncoder.sequence(cookies[:ulogin]))
|
113
|
+
expect(session[:uid]).to be_nil
|
114
|
+
end
|
115
|
+
|
116
|
+
it 'deletes session[:ulogin]' do
|
117
|
+
controller.logout(UberLogin::TokenEncoder.sequence(cookies[:ulogin]))
|
118
|
+
expect(session[:ulogin]).to be_nil
|
119
|
+
end
|
120
|
+
|
121
|
+
it 'deletes cookies[:uid]' do
|
122
|
+
controller.logout(UberLogin::TokenEncoder.sequence(cookies[:ulogin]))
|
123
|
+
expect(cookies[:uid]).to be_nil
|
124
|
+
end
|
81
125
|
|
126
|
+
it 'deletes cookies[:ulogin]' do
|
127
|
+
controller.logout(UberLogin::TokenEncoder.sequence(cookies[:ulogin]))
|
128
|
+
expect(cookies[:ulogin]).to be_nil
|
129
|
+
end
|
130
|
+
|
131
|
+
context 'persistent login was made' do
|
132
|
+
it 'deletes a LoginToken row' do
|
133
|
+
expect {
|
134
|
+
controller.logout(UberLogin::TokenEncoder.sequence(cookies[:ulogin]))
|
135
|
+
}.to change{ LoginToken.count }.by -1
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
context 'sequence is not nil' do
|
82
141
|
it 'does not clear session[:uid]' do
|
83
142
|
controller.logout('sequence')
|
84
143
|
expect(session[:uid]).to_not be_nil
|
@@ -103,72 +162,42 @@ describe UberLogin do
|
|
103
162
|
end
|
104
163
|
|
105
164
|
describe '#logout_all' do
|
165
|
+
before { controller.login(user, true) }
|
166
|
+
|
106
167
|
it 'deletes session[:uid]' do
|
107
|
-
controller.login(user)
|
108
168
|
controller.logout_all
|
109
169
|
expect(session[:uid]).to be_nil
|
110
170
|
end
|
111
171
|
|
112
|
-
it 'deletes session[:
|
172
|
+
it 'deletes session[:ulogin]' do
|
113
173
|
controller.logout_all
|
114
|
-
expect(session[:
|
174
|
+
expect(session[:ulogin]).to be_nil
|
115
175
|
end
|
116
176
|
|
117
|
-
it 'deletes
|
177
|
+
it 'deletes cookies[:uid]' do
|
118
178
|
controller.logout_all
|
119
179
|
expect(cookies[:uid]).to be_nil
|
120
|
-
expect(cookies[:ulogin]).to be_nil
|
121
180
|
end
|
122
181
|
|
123
|
-
it 'deletes
|
124
|
-
expect_any_instance_of(LoginToken).to receive :destroy
|
182
|
+
it 'deletes cookies[:ulogin]' do
|
125
183
|
controller.logout_all
|
184
|
+
expect(cookies[:ulogin]).to be_nil
|
126
185
|
end
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
before {
|
131
|
-
cookies[:uid] = "100"
|
132
|
-
cookies[:ulogin] = "dead:beef"
|
133
|
-
}
|
134
|
-
|
135
|
-
it 'saves the triplet to the database' do
|
136
|
-
expect_any_instance_of(LoginToken).to receive(:save!)
|
137
|
-
controller.send('save_to_database')
|
138
|
-
end
|
139
|
-
end
|
140
|
-
|
141
|
-
describe '#set_user_data' do
|
142
|
-
let(:row) { LoginToken.new }
|
143
|
-
|
144
|
-
context 'the token table has an "ip_address" field' do
|
145
|
-
it 'sets the field to the client IP' do
|
146
|
-
expect(row).to receive(:ip_address=).with('192.168.1.1')
|
147
|
-
controller.send('set_user_data', row)
|
148
|
-
end
|
149
|
-
end
|
150
|
-
|
151
|
-
context 'the token table has an "os" field' do
|
152
|
-
it 'sets the field to the client Operating System' do
|
153
|
-
expect(row).to receive(:os=).with('Linux x86_64')
|
154
|
-
controller.send('set_user_data', row)
|
155
|
-
end
|
156
|
-
end
|
157
|
-
|
158
|
-
context 'the token table has a "browser" field' do
|
159
|
-
it 'sets the field to the client Browser and version' do
|
160
|
-
expect(row).to receive(:browser=).with('Chrome 32.0.1667.0')
|
161
|
-
controller.send('set_user_data', row)
|
162
|
-
end
|
186
|
+
it 'deletes any token associated with the user' do
|
187
|
+
expect(LoginToken).to receive :destroy_all
|
188
|
+
controller.logout_all
|
163
189
|
end
|
164
190
|
end
|
165
191
|
|
166
|
-
describe '#
|
192
|
+
describe '#current_user' do
|
167
193
|
context 'session[:uid] is set' do
|
168
|
-
before {
|
194
|
+
before {
|
195
|
+
session[:uid] = 100
|
196
|
+
session[:ulogin] = 'dead:beef'
|
197
|
+
}
|
169
198
|
|
170
199
|
it 'returns an user object with that uid' do
|
171
|
-
expect(controller.
|
200
|
+
expect(controller.current_user.id).to eq 100
|
172
201
|
end
|
173
202
|
end
|
174
203
|
|
@@ -182,38 +211,38 @@ describe UberLogin do
|
|
182
211
|
}
|
183
212
|
|
184
213
|
context 'the cookies are valid' do
|
185
|
-
before { CookieManager.any_instance.stub(:valid?).and_return true }
|
214
|
+
before { UberLogin::CookieManager.any_instance.stub(:valid?).and_return true }
|
186
215
|
|
187
216
|
it 'returns an user object with that uid' do
|
188
|
-
expect(controller.
|
217
|
+
expect(controller.current_user.id).to eq "100"
|
189
218
|
end
|
190
219
|
|
191
220
|
it 'deletes the token from the database' do
|
192
221
|
expect_any_instance_of(LoginToken).to receive(:destroy)
|
193
|
-
controller.
|
222
|
+
controller.current_user
|
194
223
|
end
|
195
224
|
|
196
225
|
it 'creates a new token for the next login' do
|
197
226
|
expect_any_instance_of(LoginToken).to receive(:save!)
|
198
|
-
controller.
|
227
|
+
controller.current_user
|
199
228
|
end
|
200
229
|
|
201
230
|
it 'refreshes the cookie' do
|
202
|
-
controller.
|
231
|
+
controller.current_user
|
203
232
|
expect(cookies[:uid]).to eq "100"
|
204
233
|
expect(cookies[:ulogin]).to_not eq "whatever:beef"
|
205
234
|
end
|
206
235
|
end
|
207
236
|
|
208
237
|
context 'the cookies are not valid' do
|
209
|
-
before { CookieManager.any_instance.stub(:valid?).and_return false }
|
238
|
+
before { UberLogin::CookieManager.any_instance.stub(:valid?).and_return false }
|
210
239
|
|
211
240
|
it 'returns nil' do
|
212
|
-
expect(controller.
|
241
|
+
expect(controller.current_user).to be_nil
|
213
242
|
end
|
214
243
|
|
215
244
|
it 'clears the cookies for this user' do
|
216
|
-
controller.
|
245
|
+
controller.current_user
|
217
246
|
expect(cookies[:uid]).to be_nil
|
218
247
|
expect(cookies[:ulogin]).to be_nil
|
219
248
|
end
|
@@ -222,7 +251,7 @@ describe UberLogin do
|
|
222
251
|
|
223
252
|
context 'cookies are not set' do
|
224
253
|
it 'returns nil' do
|
225
|
-
expect(controller.
|
254
|
+
expect(controller.current_user).to be_nil
|
226
255
|
end
|
227
256
|
end
|
228
257
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: uber_login
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Francesco Boffa
|
@@ -32,11 +32,19 @@ extra_rdoc_files: []
|
|
32
32
|
files:
|
33
33
|
- lib/uber_login.rb
|
34
34
|
- lib/uber_login/cookie_manager.rb
|
35
|
+
- lib/uber_login/token_validator.rb
|
36
|
+
- lib/uber_login/token_encoder.rb
|
37
|
+
- lib/uber_login/storage.rb
|
35
38
|
- lib/uber_login/version.rb
|
39
|
+
- lib/uber_login/session_manager.rb
|
36
40
|
- lib/uber_login/configuration.rb
|
41
|
+
- spec/token_encoder_spec.rb
|
42
|
+
- spec/storage_spec.rb
|
37
43
|
- spec/spec_helper.rb
|
38
44
|
- spec/cookie_manager_spec.rb
|
39
45
|
- spec/uber_login_spec.rb
|
46
|
+
- spec/session_manager_spec.rb
|
47
|
+
- spec/token_validator_spec.rb
|
40
48
|
homepage: https://github.com/AlfaOmega08/uber_login
|
41
49
|
licenses:
|
42
50
|
- MIT
|
@@ -65,7 +73,11 @@ summary: Tired of rewriting the login, logout and current_user methods for the m
|
|
65
73
|
This gem will solve all of this problems and still leave you the control over your
|
66
74
|
application.
|
67
75
|
test_files:
|
76
|
+
- spec/token_encoder_spec.rb
|
77
|
+
- spec/storage_spec.rb
|
68
78
|
- spec/spec_helper.rb
|
69
79
|
- spec/cookie_manager_spec.rb
|
70
80
|
- spec/uber_login_spec.rb
|
81
|
+
- spec/session_manager_spec.rb
|
82
|
+
- spec/token_validator_spec.rb
|
71
83
|
has_rdoc:
|