rodauth 2.6.0 → 2.7.0
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 +12 -0
- data/doc/jwt_refresh.rdoc +2 -0
- data/doc/recovery_codes.rdoc +2 -1
- data/doc/release_notes/2.7.0.txt +33 -0
- data/doc/remember.rdoc +1 -1
- data/lib/rodauth.rb +5 -1
- data/lib/rodauth/features/base.rb +1 -1
- data/lib/rodauth/features/jwt.rb +6 -2
- data/lib/rodauth/features/jwt_refresh.rb +19 -0
- data/lib/rodauth/features/otp.rb +0 -2
- data/lib/rodauth/features/recovery_codes.rb +22 -1
- data/lib/rodauth/features/remember.rb +4 -1
- data/lib/rodauth/features/verify_account.rb +0 -1
- data/lib/rodauth/version.rb +1 -1
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ce2af7161a7aaba17ebb25beda65f8598306b2d040986db0be215b89fb683149
|
4
|
+
data.tar.gz: cf69c788c9401485610599f0b6996f340ab315fcbceb359bccf01a78dceaadc8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8b2d72d0f9338a359653e90829618f2579afc30095bb0dd1bd0c627730c91117158ef5ebbca9a4a32bb78bd312ebbac308a68efb761cf93c4dfc707d7bdcea24
|
7
|
+
data.tar.gz: d5eb1fc01df26b8305edec707642d3192e7a5dc3507416d0e60aaf6ffd1b079ac4ddced72a85d61c4623c70df2d784307cfba60b8759741b2991f591c623b0b0
|
data/CHANGELOG
CHANGED
@@ -1,3 +1,15 @@
|
|
1
|
+
=== 2.7.0 (2020-12-22)
|
2
|
+
|
3
|
+
* Avoid method redefinition warnings in verbose warning mode (jeremyevans)
|
4
|
+
|
5
|
+
* Return expired access token error message in the JWT refresh feature when using an expired token when it isn't allowed (AlexyMatskevich) (#133)
|
6
|
+
|
7
|
+
* Allow Rodauth features to be preloaded, instead of always trying to require them (janko) (#136)
|
8
|
+
|
9
|
+
* Use a default remember cookie path of '/', though this may cause problem with multiple Rodauth configurations on the same domain (janko) (#134)
|
10
|
+
|
11
|
+
* Add auto_remove_recovery_codes? to the recovery_codes feature, for automatically removing the codes when disabling multifactor authentication (SilasSpet, jeremyevans) (#135)
|
12
|
+
|
1
13
|
=== 2.6.0 (2020-11-20)
|
2
14
|
|
3
15
|
* Avoid loading features multiple times (janko) (#131)
|
data/doc/jwt_refresh.rdoc
CHANGED
@@ -30,6 +30,8 @@ This feature depends on the jwt feature.
|
|
30
30
|
== Auth Value Methods
|
31
31
|
|
32
32
|
allow_refresh_with_expired_jwt_access_token? :: Whether refreshing should be allowed with an expired access token. Default is +false+. You must set an +hmac_secret+ if setting this value to +true+.
|
33
|
+
expired_jwt_access_token_status :: The HTTP status code to use when a access token (JWT) is expired is submitted in the Authorization header. Default is 400 for backwards compatibility, and it is recommended to set it to 401.
|
34
|
+
expired_jwt_access_token_message :: The error message to use when a access token (JWT) is expired is submitted in the Authorization header.
|
33
35
|
jwt_access_token_key :: Name of the key in the response json holding the access token. Default is +access_token+.
|
34
36
|
jwt_access_token_not_before_period :: How many seconds before the current time will the jwt be considered valid (to account for inaccurate clocks). Default is 5.
|
35
37
|
jwt_access_token_period :: Validity of an access token in seconds, default is 1800 (30 minutes).
|
data/doc/recovery_codes.rdoc
CHANGED
@@ -17,7 +17,8 @@ add_recovery_codes_error_flash :: The flash error to show when adding recovery c
|
|
17
17
|
add_recovery_codes_heading :: Text to use for heading above the form to add recovery codes.
|
18
18
|
add_recovery_codes_page_title :: The page title to use on the add recovery codes form.
|
19
19
|
add_recovery_codes_param :: The parameter name to use for adding recovery codes.
|
20
|
-
auto_add_recovery_codes? :: Whether to automatically add recovery codes (or any missing recovery codes) when
|
20
|
+
auto_add_recovery_codes? :: Whether to automatically add recovery codes (or any missing recovery codes) when enabling otp, webauthn, or sms authentication (false by default).
|
21
|
+
auto_remove_recovery_codes? :: Whether to automatically remove recovery codes when disabling otp, webauthn, or sms authentication and not having one of the other two authentication methods enabled (false by default).
|
21
22
|
invalid_recovery_code_error_flash :: The flash error to show when an invalid recovery code is used.
|
22
23
|
invalid_recovery_code_message :: The error message to show when an invalid recovery code is used.
|
23
24
|
recovery_auth_additional_form_tags :: HTML fragment containing additional form tags when authenticating via a recovery code.
|
@@ -0,0 +1,33 @@
|
|
1
|
+
= New Features
|
2
|
+
|
3
|
+
* An auto_remove_recovery_codes? configuration method has been added
|
4
|
+
to the recovery_codes feature. This will automatically remove
|
5
|
+
recovery codes when the last multifactor authentication type other
|
6
|
+
than the recovery codes has been removed.
|
7
|
+
|
8
|
+
* The jwt_access_expired_status and expired_jwt_access_token_message
|
9
|
+
configuration methods have been added to the jwt_refresh feature,
|
10
|
+
for supporting custom statuses and messages for expired tokens.
|
11
|
+
|
12
|
+
= Other Improvements
|
13
|
+
|
14
|
+
* Rodauth will no longer attempt to require a feature that has
|
15
|
+
already been required. Related to this is you can now use a
|
16
|
+
a custom Rodauth feature without a rodauth/features/*.rb file
|
17
|
+
in the Ruby library path, as long as you load the feature
|
18
|
+
manually.
|
19
|
+
|
20
|
+
* Rodauth now avoids method redefinition warnings in verbose
|
21
|
+
warning mode. As Ruby 3 is dropping uninitialized instance
|
22
|
+
variable warnings, Rodauth will be verbose warning free in
|
23
|
+
Ruby 3.
|
24
|
+
|
25
|
+
= Backwards Compatibility
|
26
|
+
|
27
|
+
* The default remember cookie path is now set to '/'. This fixes
|
28
|
+
usage in the case where rodauth is loaded under a subpath of the
|
29
|
+
application (which is not the default behavior). Unfortunately,
|
30
|
+
this change can negatively affect cases where multiple rodauth
|
31
|
+
configurations are used in separate paths on the same domain.
|
32
|
+
In these cases, you should now use remember_cookie_options and
|
33
|
+
include a :path option.
|
data/doc/remember.rdoc
CHANGED
@@ -35,7 +35,7 @@ raw_remember_token_deadline :: A deadline before which to allow a raw remember t
|
|
35
35
|
remember_additional_form_tags :: HTML fragment containing additional form tags to use on the change remember setting form.
|
36
36
|
remember_button :: The text to use for the change remember settings button.
|
37
37
|
remember_cookie_key :: The cookie name to use for the remember token.
|
38
|
-
remember_cookie_options :: Any options to set for the remember cookie.
|
38
|
+
remember_cookie_options :: Any options to set for the remember cookie. By default, the `:path` cookie option is set to `/`.
|
39
39
|
remember_deadline_column :: The column name in the +remember_table+ storing the deadline after which the token will be ignored.
|
40
40
|
remember_deadline_interval :: The amount of time for which to remember accounts, 14 days by default. Only used if +set_deadline_values?+ is true.
|
41
41
|
remember_disable_label :: The label for disabling remembering.
|
data/lib/rodauth.rb
CHANGED
@@ -66,6 +66,7 @@ module Rodauth
|
|
66
66
|
define_method(meth) do |&block|
|
67
67
|
@auth.send(:define_method, meth, &block)
|
68
68
|
@auth.send(:private, meth) if priv
|
69
|
+
@auth.send(:alias_method, meth, meth)
|
69
70
|
end
|
70
71
|
end
|
71
72
|
|
@@ -74,6 +75,7 @@ module Rodauth
|
|
74
75
|
define_method(meth) do |&block|
|
75
76
|
@auth.send(:define_method, umeth, &block)
|
76
77
|
@auth.send(:private, umeth)
|
78
|
+
@auth.send(:alias_method, umeth, umeth)
|
77
79
|
end
|
78
80
|
end
|
79
81
|
|
@@ -82,6 +84,7 @@ module Rodauth
|
|
82
84
|
block ||= proc{v}
|
83
85
|
@auth.send(:define_method, meth, &block)
|
84
86
|
@auth.send(:private, meth) if priv
|
87
|
+
@auth.send(:alias_method, meth, meth)
|
85
88
|
end
|
86
89
|
end
|
87
90
|
end
|
@@ -240,6 +243,7 @@ module Rodauth
|
|
240
243
|
instance_variable_set(iv, send(umeth))
|
241
244
|
end
|
242
245
|
end
|
246
|
+
alias_method(meth, meth)
|
243
247
|
auth_private_methods(meth)
|
244
248
|
end
|
245
249
|
|
@@ -300,7 +304,7 @@ module Rodauth
|
|
300
304
|
private
|
301
305
|
|
302
306
|
def load_feature(feature_name)
|
303
|
-
require "rodauth/features/#{feature_name}"
|
307
|
+
require "rodauth/features/#{feature_name}" unless FEATURES[feature_name]
|
304
308
|
feature = FEATURES[feature_name]
|
305
309
|
enable(*feature.dependencies)
|
306
310
|
extend feature.configuration
|
@@ -102,7 +102,6 @@ module Rodauth
|
|
102
102
|
:set_redirect_error_flash,
|
103
103
|
:set_title,
|
104
104
|
:translate,
|
105
|
-
:unverified_account_message,
|
106
105
|
:update_session
|
107
106
|
)
|
108
107
|
|
@@ -261,6 +260,7 @@ module Rodauth
|
|
261
260
|
@password_field_autocomplete_value || 'current-password'
|
262
261
|
end
|
263
262
|
|
263
|
+
alias account_password_hash_column account_password_hash_column
|
264
264
|
# If the account_password_hash_column is set, the password hash is verified in
|
265
265
|
# ruby, it will not use a database function to do so, it will check the password
|
266
266
|
# hash using bcrypt.
|
data/lib/rodauth/features/jwt.rb
CHANGED
@@ -47,7 +47,7 @@ module Rodauth
|
|
47
47
|
s = {}
|
48
48
|
if jwt_token
|
49
49
|
unless session_data = jwt_payload
|
50
|
-
json_response[json_response_error_key]
|
50
|
+
json_response[json_response_error_key] ||= invalid_jwt_format_error_message
|
51
51
|
response.status ||= json_response_error_status
|
52
52
|
response['Content-Type'] ||= json_response_content_type
|
53
53
|
response.write(_json_response_body(json_response))
|
@@ -236,7 +236,11 @@ module Rodauth
|
|
236
236
|
def jwt_payload
|
237
237
|
return @jwt_payload if defined?(@jwt_payload)
|
238
238
|
@jwt_payload = JWT.decode(jwt_token, jwt_secret, true, _jwt_decode_opts.merge(:algorithm=>jwt_algorithm))[0]
|
239
|
-
rescue JWT::DecodeError
|
239
|
+
rescue JWT::DecodeError => e
|
240
|
+
rescue_jwt_payload(e)
|
241
|
+
end
|
242
|
+
|
243
|
+
def rescue_jwt_payload(_)
|
240
244
|
@jwt_payload = false
|
241
245
|
end
|
242
246
|
|
@@ -24,6 +24,8 @@ module Rodauth
|
|
24
24
|
auth_value_method :jwt_refresh_token_table, :account_jwt_refresh_keys
|
25
25
|
translatable_method :jwt_refresh_without_access_token_message, 'no JWT access token provided during refresh'
|
26
26
|
auth_value_method :jwt_refresh_without_access_token_status, 401
|
27
|
+
translatable_method :expired_jwt_access_token_message, "expired JWT access token"
|
28
|
+
auth_value_method :expired_jwt_access_token_status, 400
|
27
29
|
|
28
30
|
auth_private_methods(
|
29
31
|
:account_from_refresh_token
|
@@ -92,6 +94,23 @@ module Rodauth
|
|
92
94
|
|
93
95
|
private
|
94
96
|
|
97
|
+
def rescue_jwt_payload(e)
|
98
|
+
if e.instance_of?(JWT::ExpiredSignature)
|
99
|
+
begin
|
100
|
+
# Some versions of jwt will raise JWT::ExpiredSignature even when the
|
101
|
+
# JWT is invalid for other reasons. Make sure the expiration is the
|
102
|
+
# only reason the JWT isn't valid before treating this as an expired token.
|
103
|
+
JWT.decode(jwt_token, jwt_secret, true, Hash[jwt_decode_opts].merge!(:verify_expiration=>false, :algorithm=>jwt_algorithm))[0]
|
104
|
+
rescue => e
|
105
|
+
else
|
106
|
+
json_response[json_response_error_key] = expired_jwt_access_token_message
|
107
|
+
response.status ||= expired_jwt_access_token_status
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
super
|
112
|
+
end
|
113
|
+
|
95
114
|
def _account_from_refresh_token(token)
|
96
115
|
id, token_id, key = _account_refresh_token_split(token)
|
97
116
|
|
data/lib/rodauth/features/otp.rb
CHANGED
@@ -34,6 +34,7 @@ module Rodauth
|
|
34
34
|
auth_value_method :add_recovery_codes_param, 'add'
|
35
35
|
translatable_method :add_recovery_codes_heading, '<h2>Add Additional Recovery Codes</h2>'
|
36
36
|
auth_value_method :auto_add_recovery_codes?, false
|
37
|
+
auth_value_method :auto_remove_recovery_codes?, false
|
37
38
|
translatable_method :invalid_recovery_code_message, "Invalid recovery code"
|
38
39
|
auth_value_method :recovery_codes_limit, 16
|
39
40
|
auth_value_method :recovery_codes_column, :code
|
@@ -56,7 +57,6 @@ module Rodauth
|
|
56
57
|
:can_add_recovery_codes?,
|
57
58
|
:new_recovery_code,
|
58
59
|
:recovery_code_match?,
|
59
|
-
:recovery_codes
|
60
60
|
)
|
61
61
|
|
62
62
|
route(:recovery_auth) do |r|
|
@@ -213,6 +213,21 @@ module Rodauth
|
|
213
213
|
super
|
214
214
|
end
|
215
215
|
|
216
|
+
def after_otp_disable
|
217
|
+
super if defined?(super)
|
218
|
+
auto_remove_recovery_codes
|
219
|
+
end
|
220
|
+
|
221
|
+
def after_sms_disable
|
222
|
+
super if defined?(super)
|
223
|
+
auto_remove_recovery_codes
|
224
|
+
end
|
225
|
+
|
226
|
+
def after_webauthn_remove
|
227
|
+
super if defined?(super)
|
228
|
+
auto_remove_recovery_codes
|
229
|
+
end
|
230
|
+
|
216
231
|
def new_recovery_code
|
217
232
|
random_key
|
218
233
|
end
|
@@ -227,6 +242,12 @@ module Rodauth
|
|
227
242
|
end
|
228
243
|
end
|
229
244
|
|
245
|
+
def auto_remove_recovery_codes
|
246
|
+
if auto_remove_recovery_codes? && (%w'totp webauthn sms_code' & possible_authentication_methods).empty?
|
247
|
+
recovery_codes_remove
|
248
|
+
end
|
249
|
+
end
|
250
|
+
|
230
251
|
def _recovery_codes
|
231
252
|
recovery_codes_ds.select_map(recovery_codes_column)
|
232
253
|
end
|
@@ -132,11 +132,14 @@ module Rodauth
|
|
132
132
|
opts = Hash[remember_cookie_options]
|
133
133
|
opts[:value] = "#{account_id}_#{convert_token_key(remember_key_value)}"
|
134
134
|
opts[:expires] = convert_timestamp(active_remember_key_ds.get(remember_deadline_column))
|
135
|
+
opts[:path] = "/" unless opts.key?(:path)
|
135
136
|
::Rack::Utils.set_cookie_header!(response.headers, remember_cookie_key, opts)
|
136
137
|
end
|
137
138
|
|
138
139
|
def forget_login
|
139
|
-
|
140
|
+
opts = Hash[remember_cookie_options]
|
141
|
+
opts[:path] = "/" unless opts.key?(:path)
|
142
|
+
::Rack::Utils.delete_cookie_header!(response.headers, remember_cookie_key, opts)
|
140
143
|
end
|
141
144
|
|
142
145
|
def get_remember_key
|
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.7.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-12-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: sequel
|
@@ -309,6 +309,7 @@ extra_rdoc_files:
|
|
309
309
|
- doc/release_notes/2.4.0.txt
|
310
310
|
- doc/release_notes/2.5.0.txt
|
311
311
|
- doc/release_notes/2.6.0.txt
|
312
|
+
- doc/release_notes/2.7.0.txt
|
312
313
|
files:
|
313
314
|
- CHANGELOG
|
314
315
|
- MIT-LICENSE
|
@@ -394,6 +395,7 @@ files:
|
|
394
395
|
- doc/release_notes/2.4.0.txt
|
395
396
|
- doc/release_notes/2.5.0.txt
|
396
397
|
- doc/release_notes/2.6.0.txt
|
398
|
+
- doc/release_notes/2.7.0.txt
|
397
399
|
- doc/remember.rdoc
|
398
400
|
- doc/reset_password.rdoc
|
399
401
|
- doc/session_expiration.rdoc
|