rodauth 2.3.0 → 2.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG +6 -0
- data/README.rdoc +14 -0
- data/doc/base.rdoc +1 -0
- data/doc/password_pepper.rdoc +44 -0
- data/doc/release_notes/2.4.0.txt +22 -0
- data/lib/rodauth/features/base.rb +12 -2
- data/lib/rodauth/features/disallow_password_reuse.rb +4 -2
- data/lib/rodauth/features/password_pepper.rb +45 -0
- data/lib/rodauth/features/remember.rb +2 -0
- data/lib/rodauth/version.rb +1 -1
- metadata +7 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: db02abed46d2dd511d07e2c8bf8640ca01f14fff595953a3c05b9a2cbe314511
|
4
|
+
data.tar.gz: 81f74322d49942d099789350c031c59227ec92b8eb6304dce9b4e15a91f2e60f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bda7da30406c315d6f467ac88701668c5288c93f8415bb1cffa280136cf7838a4fec81e865b8d0e607fef646df5d33a37e96f6e5e00dba2d6956757efc25ffc8
|
7
|
+
data.tar.gz: f19903ffb51eb7a87107fe0a24a33214fde275e732a6ac2a41e9bf3409f7b348c2ca8f9f87fe690d8b239fc5ae796f02a36ac32c7f615c8fca25f628d4173a80
|
data/CHANGELOG
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
+
=== 2.4.0 (2020-09-21)
|
2
|
+
|
3
|
+
* Add session_key_prefix for more easily using separate session keys when using multiple configurations (janko) (#121)
|
4
|
+
|
5
|
+
* Add password_pepper feature for appending a secret key to passwords before they are hashed, supporting secret rotation (janko) (#119)
|
6
|
+
|
1
7
|
=== 2.3.0 (2020-08-21)
|
2
8
|
|
3
9
|
* Return an error status instead of an invalid access token when trying to refresh JWT without an access token in the jwt_refresh feature (jeremyevans)
|
data/README.rdoc
CHANGED
@@ -44,6 +44,7 @@ HTML and JSON API for all supported features.
|
|
44
44
|
* Verify Account Grace Period (Don't require verification before login)
|
45
45
|
* Password Grace Period (Don't require password entry if recently entered)
|
46
46
|
* Password Complexity (More sophisticated checks)
|
47
|
+
* Password Pepper
|
47
48
|
* Disallow Password Reuse
|
48
49
|
* Disallow Common Passwords
|
49
50
|
* Password Expiration
|
@@ -881,6 +882,7 @@ view the appropriate file in the doc directory.
|
|
881
882
|
* {Password Complexity}[rdoc-ref:doc/password_complexity.rdoc]
|
882
883
|
* {Password Expiration}[rdoc-ref:doc/password_expiration.rdoc]
|
883
884
|
* {Password Grace Period}[rdoc-ref:doc/password_grace_period.rdoc]
|
885
|
+
* {Password Pepper}[rdoc-ref:doc/password_pepper.rdoc]
|
884
886
|
* {Recovery Codes}[rdoc-ref:doc/recovery_codes.rdoc]
|
885
887
|
* {Remember}[rdoc-ref:doc/remember.rdoc]
|
886
888
|
* {Reset Password}[rdoc-ref:doc/reset_password.rdoc]
|
@@ -1062,6 +1064,18 @@ the name as an argument to use that configuration:
|
|
1062
1064
|
r.rodauth
|
1063
1065
|
end
|
1064
1066
|
|
1067
|
+
By default, alternate configurations will use the same session keys as the
|
1068
|
+
primary configuration, which may be undesirable. To ensure session state is
|
1069
|
+
separated between configurations, you can set a session key prefix for
|
1070
|
+
alternate configurations. If you are using the remember feature in both
|
1071
|
+
configurations, you may also want to set a different remember key in the
|
1072
|
+
alternate configuration:
|
1073
|
+
|
1074
|
+
plugin :rodauth, :name=>:secondary do
|
1075
|
+
session_key_prefix "secondary_"
|
1076
|
+
remember_cookie_key "_secondary_remember"
|
1077
|
+
end
|
1078
|
+
|
1065
1079
|
=== With Password Hashes Inside the Accounts Table
|
1066
1080
|
|
1067
1081
|
You can use Rodauth if you are storing password hashes in the same
|
data/doc/base.rdoc
CHANGED
@@ -17,6 +17,7 @@ mark_input_fields_as_required? :: Whether input fields should be marked as requi
|
|
17
17
|
prefix :: The routing prefix used for Rodauth routes. If you are calling in a routing subtree, this should be set to the root path of the subtree. This should include a leading slash if set, but not a trailing slash.
|
18
18
|
require_bcrypt? :: Set to false to not require bcrypt, useful if using custom authentication.
|
19
19
|
session_key :: The key in the session hash storing the primary key of the logged in account.
|
20
|
+
session_key_prefix :: The string that will be prepended to the default value for all session keys.
|
20
21
|
skip_status_checks? :: Whether status checks should be skipped for accounts. Defaults to true unless enabling the verify_account or close_account features.
|
21
22
|
title_instance_variable :: The instance variable to set in the Roda scope with the page title. The layout should use this instance variable if available to set the title of the page. You can use +set_title+ if setting the page title is not done through an instance variable.
|
22
23
|
|
@@ -0,0 +1,44 @@
|
|
1
|
+
= Documentation for Password Pepper Feature
|
2
|
+
|
3
|
+
The password pepper feature appends a specified secret string to passwords
|
4
|
+
before they are hashed. This way, if the password hashes get compromised, an
|
5
|
+
attacker cannot use them to crack the passwords without also knowing the
|
6
|
+
pepper.
|
7
|
+
|
8
|
+
In the configuration block set the +password_pepper+ with your secret string.
|
9
|
+
It's recommended for the password pepper to be at last 32 characters long and
|
10
|
+
randomly generated.
|
11
|
+
|
12
|
+
password_pepper "<long secret key>"
|
13
|
+
|
14
|
+
If your database already contains password hashes that were created without a
|
15
|
+
password pepper, these will get automatically updated with a password pepper
|
16
|
+
next time the user successfully enters their password.
|
17
|
+
|
18
|
+
You can rotate the password pepper as well, just make sure to add the previous
|
19
|
+
pepper to the +previous_password_peppers+ array. Password hashes using the old
|
20
|
+
pepper will get automatically updated on the next successful password match.
|
21
|
+
|
22
|
+
password_pepper "new pepper"
|
23
|
+
previous_password_peppers ["old pepper", ""]
|
24
|
+
|
25
|
+
The empty string above ensures password hashes without pepper are handled as
|
26
|
+
well.
|
27
|
+
|
28
|
+
Note that each entry in +previous_password_peppers+ will multiply the amount of
|
29
|
+
possible password checks during login, at least for incorrect passwords.
|
30
|
+
|
31
|
+
Additionally, when using this feature with the disallow_password_reuse feature,
|
32
|
+
the number of passwords checked when changing or resetting a password will be
|
33
|
+
|
34
|
+
(previous_password_peppers.length + 1) * previous_passwords_to_check
|
35
|
+
|
36
|
+
So if you have 2 entries in +previous_password_peppers+, using the default
|
37
|
+
value of 6 for +previous_passwords_to_check+, every time a password
|
38
|
+
is changed, there will be 18 password checks done, which will be quite slow.
|
39
|
+
|
40
|
+
== Auth Value Methods
|
41
|
+
|
42
|
+
password_pepper :: The secret string appended to passwords before they are hashed.
|
43
|
+
previous_password_peppers :: An array of password peppers that will be tried on an unsuccessful password match. Defaults to <tt>[""]</tt>, which allows introducing this feature with existing passwords.
|
44
|
+
password_pepper_update? :: Whether to update password hashes that use a pepper from +previous_password_peppers+ with a new pepper. Defaults to +true+.
|
@@ -0,0 +1,22 @@
|
|
1
|
+
= New Features
|
2
|
+
|
3
|
+
* A password_pepper feature has been added. This allows you to use a
|
4
|
+
secret key (called a pepper) to append to passwords before hashing
|
5
|
+
and hash checking. Using this approach, if an attacker obtains the
|
6
|
+
password hash, it is unusable for cracking unless they can also
|
7
|
+
get access to the pepper.
|
8
|
+
|
9
|
+
The password_pepper feature also supports a list of previous peppers
|
10
|
+
that can be used to implement secret rotation and to support
|
11
|
+
compatibility with unpeppered passwords.
|
12
|
+
|
13
|
+
Rodauth by default uses database functions for password hash
|
14
|
+
checking on PostgreSQL, MySQL, and Microsoft SQL Server, which in
|
15
|
+
general provides more security than a password pepper, but both
|
16
|
+
approaches can be used simultaneously.
|
17
|
+
|
18
|
+
* A session_key_prefix configuration method has been added for
|
19
|
+
prefixing the values of all default session keys. This can be
|
20
|
+
useful if you are using multiple Rodauth configurations in the same
|
21
|
+
application and want to make sure the session keys for the separate
|
22
|
+
configurations do not overlap.
|
@@ -47,6 +47,7 @@ module Rodauth
|
|
47
47
|
session_key :authenticated_by_session_key, :authenticated_by
|
48
48
|
session_key :autologin_type_session_key, :autologin_type
|
49
49
|
auth_value_method :prefix, ''
|
50
|
+
auth_value_method :session_key_prefix, nil
|
50
51
|
auth_value_method :require_bcrypt?, true
|
51
52
|
auth_value_method :mark_input_fields_as_required?, true
|
52
53
|
auth_value_method :mark_input_fields_with_autocomplete?, true
|
@@ -393,9 +394,9 @@ module Rodauth
|
|
393
394
|
def password_match?(password)
|
394
395
|
if hash = get_password_hash
|
395
396
|
if account_password_hash_column || !use_database_authentication_functions?
|
396
|
-
|
397
|
+
password_hash_match?(hash, password)
|
397
398
|
else
|
398
|
-
|
399
|
+
database_function_password_match?(:rodauth_valid_password_hash, account_id, password, hash)
|
399
400
|
end
|
400
401
|
end
|
401
402
|
end
|
@@ -458,6 +459,14 @@ module Rodauth
|
|
458
459
|
|
459
460
|
private
|
460
461
|
|
462
|
+
def database_function_password_match?(name, hash_id, password, salt)
|
463
|
+
db.get(Sequel.function(function_name(name), hash_id, BCrypt::Engine.hash_secret(password, salt)))
|
464
|
+
end
|
465
|
+
|
466
|
+
def password_hash_match?(hash, password)
|
467
|
+
BCrypt::Password.new(hash) == password
|
468
|
+
end
|
469
|
+
|
461
470
|
def convert_token_key(key)
|
462
471
|
if key && hmac_secret
|
463
472
|
compute_hmac(key)
|
@@ -493,6 +502,7 @@ module Rodauth
|
|
493
502
|
end
|
494
503
|
|
495
504
|
def convert_session_key(key)
|
505
|
+
key = "#{session_key_prefix}#{key}".to_sym if session_key_prefix
|
496
506
|
scope.opts[:sessions_convert_symbols] ? key.to_s : key
|
497
507
|
end
|
498
508
|
|
@@ -51,11 +51,13 @@ module Rodauth
|
|
51
51
|
return true if salts.empty?
|
52
52
|
|
53
53
|
salts.any? do |hash_id, salt|
|
54
|
-
|
54
|
+
database_function_password_match?(:rodauth_previous_password_hash_match, hash_id, password, salt)
|
55
55
|
end
|
56
56
|
else
|
57
57
|
# :nocov:
|
58
|
-
previous_password_ds.select_map(previous_password_hash_column).any?
|
58
|
+
previous_password_ds.select_map(previous_password_hash_column).any? do |hash|
|
59
|
+
password_hash_match?(hash, password)
|
60
|
+
end
|
59
61
|
# :nocov:
|
60
62
|
end
|
61
63
|
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen-string-literal: true
|
2
|
+
|
3
|
+
module Rodauth
|
4
|
+
Feature.define(:password_pepper, :PasswordPepper) do
|
5
|
+
depends :login_password_requirements_base
|
6
|
+
|
7
|
+
auth_value_method :password_pepper, nil
|
8
|
+
auth_value_method :previous_password_peppers, [""]
|
9
|
+
auth_value_method :password_pepper_update?, true
|
10
|
+
|
11
|
+
def password_match?(password)
|
12
|
+
if (result = super) && @previous_pepper_matched && password_pepper_update?
|
13
|
+
set_password(password)
|
14
|
+
end
|
15
|
+
|
16
|
+
result
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def password_hash(password)
|
22
|
+
super(password + password_pepper.to_s)
|
23
|
+
end
|
24
|
+
|
25
|
+
def password_hash_match?(hash, password)
|
26
|
+
return super if password_pepper.nil?
|
27
|
+
|
28
|
+
return true if super(hash, password + password_pepper)
|
29
|
+
|
30
|
+
@previous_pepper_matched = previous_password_peppers.any? do |pepper|
|
31
|
+
super(hash, password + pepper)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def database_function_password_match?(name, hash_id, password, salt)
|
36
|
+
return super if password_pepper.nil?
|
37
|
+
|
38
|
+
return true if super(name, hash_id, password + password_pepper, salt)
|
39
|
+
|
40
|
+
@previous_pepper_matched = previous_password_peppers.any? do |pepper|
|
41
|
+
super(name, hash_id, password + pepper, salt)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -58,7 +58,9 @@ module Rodauth
|
|
58
58
|
if [remember_remember_param_value, remember_forget_param_value, remember_disable_param_value].include?(remember)
|
59
59
|
transaction do
|
60
60
|
before_remember
|
61
|
+
# :nocov:
|
61
62
|
case remember
|
63
|
+
# :nocov:
|
62
64
|
when remember_remember_param_value
|
63
65
|
remember_login
|
64
66
|
when remember_forget_param_value
|
data/lib/rodauth/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rodauth
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jeremy Evans
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-09-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: sequel
|
@@ -277,6 +277,7 @@ extra_rdoc_files:
|
|
277
277
|
- doc/webauthn_verify_account.rdoc
|
278
278
|
- doc/active_sessions.rdoc
|
279
279
|
- doc/audit_logging.rdoc
|
280
|
+
- doc/password_pepper.rdoc
|
280
281
|
- doc/release_notes/1.17.0.txt
|
281
282
|
- doc/release_notes/1.0.0.txt
|
282
283
|
- doc/release_notes/1.1.0.txt
|
@@ -305,6 +306,7 @@ extra_rdoc_files:
|
|
305
306
|
- doc/release_notes/2.1.0.txt
|
306
307
|
- doc/release_notes/2.2.0.txt
|
307
308
|
- doc/release_notes/2.3.0.txt
|
309
|
+
- doc/release_notes/2.4.0.txt
|
308
310
|
files:
|
309
311
|
- CHANGELOG
|
310
312
|
- MIT-LICENSE
|
@@ -357,6 +359,7 @@ files:
|
|
357
359
|
- doc/password_complexity.rdoc
|
358
360
|
- doc/password_expiration.rdoc
|
359
361
|
- doc/password_grace_period.rdoc
|
362
|
+
- doc/password_pepper.rdoc
|
360
363
|
- doc/recovery_codes.rdoc
|
361
364
|
- doc/release_notes/1.0.0.txt
|
362
365
|
- doc/release_notes/1.1.0.txt
|
@@ -386,6 +389,7 @@ files:
|
|
386
389
|
- doc/release_notes/2.1.0.txt
|
387
390
|
- doc/release_notes/2.2.0.txt
|
388
391
|
- doc/release_notes/2.3.0.txt
|
392
|
+
- doc/release_notes/2.4.0.txt
|
389
393
|
- doc/remember.rdoc
|
390
394
|
- doc/reset_password.rdoc
|
391
395
|
- doc/session_expiration.rdoc
|
@@ -429,6 +433,7 @@ files:
|
|
429
433
|
- lib/rodauth/features/password_complexity.rb
|
430
434
|
- lib/rodauth/features/password_expiration.rb
|
431
435
|
- lib/rodauth/features/password_grace_period.rb
|
436
|
+
- lib/rodauth/features/password_pepper.rb
|
432
437
|
- lib/rodauth/features/recovery_codes.rb
|
433
438
|
- lib/rodauth/features/remember.rb
|
434
439
|
- lib/rodauth/features/reset_password.rb
|