quo_vadis 2.1.4 → 2.1.7

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: c0b470ad4482010d9774287306051d802625c95fa5e20675a12bf4537e71d939
4
- data.tar.gz: 67574e42473e4c87dc112f7e7ced2104c8df54a8a02e7befcedad6e806d136a4
3
+ metadata.gz: f2f5586e06a0e01dd89d66bf9cae01317b0d302ba51e5a82cfcb4bc00dc0ea85
4
+ data.tar.gz: f37f34fbae6ab23081643aff844525b4ca8795c9e5057cbce737e7348d6a254f
5
5
  SHA512:
6
- metadata.gz: debe3294db5262b56514b9ece8181464783521f475c4472a43dd4555739cd97fd81bea5fde66e700be8a75ada62ee554d4374aa196bfcb063bc9ecfcd989d1cf
7
- data.tar.gz: 00f90c64fd56cec727ba364d784de3928e68e5d34eb5fca1fd56382c77289c0d6c5a4be7396687e1e175d5dc66c4473e00ae77b8b6f52c56def2496e0abeab40
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
- gem 'quo_vadis', '~> 2.0'
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
@@ -9,6 +9,7 @@ module QuoVadis
9
9
 
10
10
  belongs_to :account
11
11
  validates :ip, presence: true
12
+ scope :new_to_old, -> { order created_at: :desc }
12
13
 
13
14
  attribute :last_seen_at, :datetime, default: -> { Time.now.utc }
14
15
 
@@ -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>
@@ -8,7 +8,7 @@ module QuoVadis
8
8
  return '' if value == ''
9
9
 
10
10
  salt = SecureRandom.hex KEY_LENGTH
11
- crypt = encryptor key(salt)
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 key(salt)
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(key)
31
- ActiveSupport::MessageEncryptor.new(key)
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.new(secret).generate_key(salt, KEY_LENGTH)
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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module QuoVadis
4
- VERSION = '2.1.4'
4
+ VERSION = '2.1.7'
5
5
  end
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 input[type=submit][value="Log out"]', 1
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)
@@ -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
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: 2021-10-02 00:00:00.000000000 Z
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.1.2
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: []