quo_vadis 2.1.4 → 2.1.7
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/CHANGELOG.md +23 -0
- data/README.md +1 -3
- data/app/controllers/quo_vadis/sessions_controller.rb +3 -3
- data/app/controllers/quo_vadis/twofas_controller.rb +1 -1
- data/app/models/quo_vadis/session.rb +1 -0
- data/app/views/quo_vadis/logs/index.html.erb +1 -1
- data/app/views/quo_vadis/sessions/index.html.erb +6 -0
- data/lib/quo_vadis/crypt.rb +12 -6
- data/lib/quo_vadis/version.rb +1 -1
- data/quo_vadis.gemspec +1 -1
- data/test/integration/sessions_test.rb +1 -1
- data/test/models/crypt_test.rb +19 -0
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f2f5586e06a0e01dd89d66bf9cae01317b0d302ba51e5a82cfcb4bc00dc0ea85
|
4
|
+
data.tar.gz: f37f34fbae6ab23081643aff844525b4ca8795c9e5057cbce737e7348d6a254f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: de242f63f325f1520fb9fb209535a4dfcff1c6f3f2e80d6620bce3e940c1000d5452145e83b6917e9106deb844aa4f467be922880c92bbb357da2dcb6bbf563b
|
7
|
+
data.tar.gz: d706a441437cab9af6ee75f3581cc18df8edfd17414317555eecd58a1c984f7cc62a085297158fb5a42f9d244bcfdbde98bd6792220434a6118e32f801c0241e
|
data/CHANGELOG.md
CHANGED
@@ -4,6 +4,29 @@
|
|
4
4
|
## HEAD
|
5
5
|
|
6
6
|
|
7
|
+
## 2.1.7 (30 May 2022)
|
8
|
+
|
9
|
+
* Use SHA256 digest for encryption.
|
10
|
+
* Use <time> element in logs view.
|
11
|
+
|
12
|
+
|
13
|
+
## 2.1.6 (30 May 2022)
|
14
|
+
|
15
|
+
* Fix typo in session scope.
|
16
|
+
|
17
|
+
|
18
|
+
## 2.1.5 (27 May 2022)
|
19
|
+
|
20
|
+
* Order sessions list and display more information.
|
21
|
+
* Set status 303 See Other on destroy redirects.
|
22
|
+
* Streamline bundler instructions.
|
23
|
+
|
24
|
+
|
25
|
+
## 2.1.4 (2 October 2021)
|
26
|
+
|
27
|
+
* Allow metadata for login log.
|
28
|
+
|
29
|
+
|
7
30
|
## 2.1.3 (30 September 2021)
|
8
31
|
|
9
32
|
* Pass IP and timestamp as paramenters to mailer.
|
data/README.md
CHANGED
@@ -37,11 +37,9 @@ Simple to integrate into your application. The main task is customising the exa
|
|
37
37
|
Add the gem to your Gemfile:
|
38
38
|
|
39
39
|
```ruby
|
40
|
-
|
40
|
+
bundle add 'quo_vadis'
|
41
41
|
```
|
42
42
|
|
43
|
-
Then run `bundle install`.
|
44
|
-
|
45
43
|
Next, add the database tables:
|
46
44
|
|
47
45
|
```
|
@@ -9,7 +9,7 @@ module QuoVadis
|
|
9
9
|
|
10
10
|
def index
|
11
11
|
@qv_session = qv.session
|
12
|
-
@qv_sessions = @qv_session.account.sessions
|
12
|
+
@qv_sessions = @qv_session.account.sessions.new_to_old
|
13
13
|
end
|
14
14
|
|
15
15
|
|
@@ -58,12 +58,12 @@ module QuoVadis
|
|
58
58
|
current_qv_session.account.sessions.destroy params[:id]
|
59
59
|
qv.log current_qv_session.account, Log::LOGOUT_OTHER
|
60
60
|
flash[:notice] = QuoVadis.translate 'flash.logout.other'
|
61
|
-
redirect_to action: :index
|
61
|
+
redirect_to action: :index, status: :see_other
|
62
62
|
else # this session
|
63
63
|
qv.log authenticated_model.qv_account, Log::LOGOUT
|
64
64
|
qv.logout
|
65
65
|
flash[:notice] = QuoVadis.translate 'flash.logout.self'
|
66
|
-
redirect_to main_app.root_path
|
66
|
+
redirect_to main_app.root_path, status: :see_other
|
67
67
|
end
|
68
68
|
end
|
69
69
|
|
@@ -14,7 +14,7 @@ module QuoVadis
|
|
14
14
|
account.sessions.each &:reset_authenticated_with_second_factor # OWASP ASV v4.0, 2.8.6
|
15
15
|
qv.log account, Log::TWOFA_DEACTIVATED
|
16
16
|
QuoVadis.notify :twofa_deactivated_notification, email: authenticated_model.email
|
17
|
-
redirect_to twofa_path, notice: QuoVadis.translate('flash.2fa.invalidated')
|
17
|
+
redirect_to twofa_path, notice: QuoVadis.translate('flash.2fa.invalidated'), status: :see_other
|
18
18
|
end
|
19
19
|
|
20
20
|
private
|
@@ -12,7 +12,7 @@
|
|
12
12
|
<tbody>
|
13
13
|
<% @logs.each do |log| %>
|
14
14
|
<tr>
|
15
|
-
<td><%= log.created_at %></td>
|
15
|
+
<td><time datetime="<%= log.created_at.to_formatted_s(:iso8601) %>"><%= log.created_at.to_formatted_s('%-d %B %Y') %></time></td>
|
16
16
|
<td><%= QuoVadis.translate "log.action.#{log.action}" %></td>
|
17
17
|
<td><%= log.ip %></td>
|
18
18
|
<td><%= log.metadata.empty? ? '' : log.metadata.map {|k,v| "#{k}: #{v}"}.join(', ') %></td>
|
@@ -3,6 +3,9 @@
|
|
3
3
|
<table>
|
4
4
|
<thead>
|
5
5
|
<tr>
|
6
|
+
<th>Signed in</th>
|
7
|
+
<th>Last seen</th>
|
8
|
+
<th>2FA used</th>
|
6
9
|
<th>IP</th>
|
7
10
|
<th>User agent</th>
|
8
11
|
<th></th>
|
@@ -11,6 +14,9 @@
|
|
11
14
|
<tbody>
|
12
15
|
<% @qv_sessions.each do |sess| %>
|
13
16
|
<tr>
|
17
|
+
<td><time datetime="<%= sess.created_at.to_formatted_s(:iso_8601) %>"><%= sess.created_at.to_formatted_s('%-d %B %Y') %></time></td>
|
18
|
+
<td><time datetime="<%= sess.last_seen_at.to_formatted_s(:iso_8601) %>"><%= sess.last_seen_at.to_formatted_s('%-d %B %Y') %></time></td>
|
19
|
+
<td><%= sess.second_factor_authenticated? ? 'Yes' : 'No' %></td>
|
14
20
|
<td><%= sess.ip %></td>
|
15
21
|
<td><%= sess.user_agent %></td>
|
16
22
|
<td>
|
data/lib/quo_vadis/crypt.rb
CHANGED
@@ -8,7 +8,7 @@ module QuoVadis
|
|
8
8
|
return '' if value == ''
|
9
9
|
|
10
10
|
salt = SecureRandom.hex KEY_LENGTH
|
11
|
-
crypt = encryptor
|
11
|
+
crypt = encryptor salt
|
12
12
|
ciphertext = crypt.encrypt_and_sign value
|
13
13
|
[salt, ciphertext].join SEPARATOR
|
14
14
|
end
|
@@ -18,7 +18,7 @@ module QuoVadis
|
|
18
18
|
return '' if value == ''
|
19
19
|
|
20
20
|
salt, data = value.split SEPARATOR
|
21
|
-
crypt = encryptor
|
21
|
+
crypt = encryptor salt
|
22
22
|
crypt.decrypt_and_verify(data)
|
23
23
|
end
|
24
24
|
|
@@ -27,12 +27,18 @@ module QuoVadis
|
|
27
27
|
KEY_LENGTH = ActiveSupport::MessageEncryptor.key_len
|
28
28
|
SEPARATOR = '$$'
|
29
29
|
|
30
|
-
def self.encryptor(
|
31
|
-
|
30
|
+
def self.encryptor(salt)
|
31
|
+
key_sha256 = key salt, OpenSSL::Digest::SHA256
|
32
|
+
key_sha1 = key salt, OpenSSL::Digest::SHA1
|
33
|
+
ActiveSupport::MessageEncryptor.new(key_sha256).tap { |crypt|
|
34
|
+
crypt.rotate key_sha1
|
35
|
+
}
|
32
36
|
end
|
33
37
|
|
34
|
-
def self.key(salt)
|
35
|
-
ActiveSupport::KeyGenerator
|
38
|
+
def self.key(salt, hash_digest_class)
|
39
|
+
ActiveSupport::KeyGenerator
|
40
|
+
.new(secret, hash_digest_class: hash_digest_class)
|
41
|
+
.generate_key(salt, KEY_LENGTH)
|
36
42
|
end
|
37
43
|
|
38
44
|
def self.secret
|
data/lib/quo_vadis/version.rb
CHANGED
data/quo_vadis.gemspec
CHANGED
@@ -8,7 +8,7 @@ Gem::Specification.new do |spec|
|
|
8
8
|
spec.authors = ['Andy Stewart']
|
9
9
|
spec.email = ['boss@airbladesoftware.com']
|
10
10
|
|
11
|
-
spec.summary = 'Multifactor authentication for Rails 6.'
|
11
|
+
spec.summary = 'Multifactor authentication for Rails 6 and 7.'
|
12
12
|
spec.homepage = 'https://github.com/airblade/quo_vadis'
|
13
13
|
spec.license = 'MIT'
|
14
14
|
|
@@ -54,7 +54,7 @@ class SessionsTest < IntegrationTest
|
|
54
54
|
phone.get quo_vadis.sessions_path
|
55
55
|
phone.assert_response :success
|
56
56
|
phone.assert_select 'td', 'This session'
|
57
|
-
phone.assert_select 'td
|
57
|
+
phone.assert_select 'td button[type=submit]', text: 'Log out', count: 1
|
58
58
|
|
59
59
|
# on phone, log out the desktop session
|
60
60
|
phone.delete quo_vadis.session_path(QuoVadis::Session.first.id)
|
data/test/models/crypt_test.rb
CHANGED
@@ -4,6 +4,13 @@ class CryptTest < ActiveSupport::TestCase
|
|
4
4
|
|
5
5
|
setup do
|
6
6
|
@crypt = QuoVadis::Crypt
|
7
|
+
|
8
|
+
@crypt_sha1 = Class.new(QuoVadis::Crypt) do
|
9
|
+
def self.encryptor(salt)
|
10
|
+
key_sha1 = key salt, OpenSSL::Digest::SHA1
|
11
|
+
ActiveSupport::MessageEncryptor.new key_sha1
|
12
|
+
end
|
13
|
+
end
|
7
14
|
end
|
8
15
|
|
9
16
|
test 'round trip' do
|
@@ -19,4 +26,16 @@ class CryptTest < ActiveSupport::TestCase
|
|
19
26
|
refute_equal ciphertext, @crypt.encrypt(plaintext)
|
20
27
|
end
|
21
28
|
|
29
|
+
test 'rotation' do
|
30
|
+
# This test only works if our test Rails contains this commit:
|
31
|
+
# https://github.com/rails/rails/commit/447e28347eb46e2ad5dc625de616152bd1b69a32
|
32
|
+
return unless ActiveSupport::KeyGenerator.respond_to? :hash_digest_class
|
33
|
+
|
34
|
+
plaintext = 'the quick brown fox'
|
35
|
+
# Encrypt with SHA1 digest
|
36
|
+
ciphertext_sha1 = @crypt_sha1.encrypt plaintext
|
37
|
+
# Ensure code can decrypt it.
|
38
|
+
assert_equal plaintext, @crypt.decrypt(ciphertext_sha1)
|
39
|
+
end
|
40
|
+
|
22
41
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: quo_vadis
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.1.
|
4
|
+
version: 2.1.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andy Stewart
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-05-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -224,8 +224,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
224
224
|
- !ruby/object:Gem::Version
|
225
225
|
version: '0'
|
226
226
|
requirements: []
|
227
|
-
rubygems_version: 3.
|
227
|
+
rubygems_version: 3.2.22
|
228
228
|
signing_key:
|
229
229
|
specification_version: 4
|
230
|
-
summary: Multifactor authentication for Rails 6.
|
230
|
+
summary: Multifactor authentication for Rails 6 and 7.
|
231
231
|
test_files: []
|