rodauth 2.4.0 → 2.9.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 +42 -0
- data/MIT-LICENSE +1 -1
- data/README.rdoc +10 -2
- data/doc/base.rdoc +2 -1
- data/doc/json.rdoc +47 -0
- data/doc/jwt.rdoc +1 -28
- data/doc/jwt_refresh.rdoc +8 -0
- data/doc/login.rdoc +1 -0
- data/doc/recovery_codes.rdoc +2 -1
- data/doc/release_notes/2.5.0.txt +20 -0
- data/doc/release_notes/2.6.0.txt +37 -0
- data/doc/release_notes/2.7.0.txt +33 -0
- data/doc/release_notes/2.8.0.txt +20 -0
- data/doc/release_notes/2.9.0.txt +21 -0
- data/doc/remember.rdoc +1 -1
- data/doc/verify_login_change.rdoc +1 -0
- data/javascript/webauthn_auth.js +9 -9
- data/javascript/webauthn_setup.js +9 -6
- data/lib/rodauth.rb +14 -6
- data/lib/rodauth/features/base.rb +7 -2
- data/lib/rodauth/features/change_password.rb +1 -1
- data/lib/rodauth/features/confirm_password.rb +2 -2
- data/lib/rodauth/features/json.rb +189 -0
- data/lib/rodauth/features/jwt.rb +22 -170
- data/lib/rodauth/features/jwt_refresh.rb +63 -13
- data/lib/rodauth/features/login.rb +8 -2
- data/lib/rodauth/features/otp.rb +0 -2
- data/lib/rodauth/features/recovery_codes.rb +22 -1
- data/lib/rodauth/features/remember.rb +6 -1
- data/lib/rodauth/features/verify_account.rb +6 -7
- data/lib/rodauth/features/verify_login_change.rb +2 -1
- data/lib/rodauth/features/webauthn_verify_account.rb +1 -1
- data/lib/rodauth/version.rb +1 -1
- metadata +35 -22
@@ -7,6 +7,9 @@ module Rodauth
|
|
7
7
|
after 'refresh_token'
|
8
8
|
before 'refresh_token'
|
9
9
|
|
10
|
+
auth_value_method :allow_refresh_with_expired_jwt_access_token?, false
|
11
|
+
session_key :jwt_refresh_token_data_session_key, :jwt_refresh_token_data
|
12
|
+
session_key :jwt_refresh_token_hmac_session_key, :jwt_refresh_token_hash
|
10
13
|
auth_value_method :jwt_access_token_key, 'access_token'
|
11
14
|
auth_value_method :jwt_access_token_not_before_period, 5
|
12
15
|
auth_value_method :jwt_access_token_period, 1800
|
@@ -21,12 +24,15 @@ module Rodauth
|
|
21
24
|
auth_value_method :jwt_refresh_token_table, :account_jwt_refresh_keys
|
22
25
|
translatable_method :jwt_refresh_without_access_token_message, 'no JWT access token provided during refresh'
|
23
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
|
24
29
|
|
25
30
|
auth_private_methods(
|
26
31
|
:account_from_refresh_token
|
27
32
|
)
|
28
33
|
|
29
34
|
route do |r|
|
35
|
+
@jwt_refresh_route = true
|
30
36
|
before_jwt_refresh_route
|
31
37
|
|
32
38
|
r.post do
|
@@ -38,17 +44,15 @@ module Rodauth
|
|
38
44
|
before_refresh_token
|
39
45
|
formatted_token = generate_refresh_token
|
40
46
|
remove_jwt_refresh_token_key(refresh_token)
|
47
|
+
set_jwt_refresh_token_hmac_session_key(formatted_token)
|
41
48
|
json_response[jwt_refresh_token_key] = formatted_token
|
42
49
|
json_response[jwt_access_token_key] = session_jwt
|
43
50
|
after_refresh_token
|
44
51
|
end
|
45
52
|
else
|
46
53
|
json_response[json_response_error_key] = jwt_refresh_invalid_token_message
|
47
|
-
response.status ||= json_response_error_status
|
48
54
|
end
|
49
|
-
|
50
|
-
response.write(_json_response_body(json_response))
|
51
|
-
request.halt
|
55
|
+
_return_json_response
|
52
56
|
end
|
53
57
|
end
|
54
58
|
|
@@ -58,7 +62,9 @@ module Rodauth
|
|
58
62
|
# JWT login puts the access token in the header.
|
59
63
|
# We put the refresh token in the body.
|
60
64
|
# Note, do not put the access_token in the body here, as the access token content is not yet finalised.
|
61
|
-
json_response[
|
65
|
+
token = json_response[jwt_refresh_token_key] = generate_refresh_token
|
66
|
+
|
67
|
+
set_jwt_refresh_token_hmac_session_key(token)
|
62
68
|
end
|
63
69
|
|
64
70
|
def set_jwt_token(token)
|
@@ -85,12 +91,33 @@ module Rodauth
|
|
85
91
|
|
86
92
|
private
|
87
93
|
|
94
|
+
def rescue_jwt_payload(e)
|
95
|
+
if e.instance_of?(JWT::ExpiredSignature)
|
96
|
+
begin
|
97
|
+
# Some versions of jwt will raise JWT::ExpiredSignature even when the
|
98
|
+
# JWT is invalid for other reasons. Make sure the expiration is the
|
99
|
+
# only reason the JWT isn't valid before treating this as an expired token.
|
100
|
+
JWT.decode(jwt_token, jwt_secret, true, Hash[jwt_decode_opts].merge!(:verify_expiration=>false, :algorithm=>jwt_algorithm))[0]
|
101
|
+
rescue => e
|
102
|
+
else
|
103
|
+
json_response[json_response_error_key] = expired_jwt_access_token_message
|
104
|
+
response.status ||= expired_jwt_access_token_status
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
super
|
109
|
+
end
|
110
|
+
|
88
111
|
def _account_from_refresh_token(token)
|
89
112
|
id, token_id, key = _account_refresh_token_split(token)
|
90
113
|
|
91
|
-
|
92
|
-
|
93
|
-
|
114
|
+
unless key &&
|
115
|
+
(id == session_value.to_s) &&
|
116
|
+
(actual = get_active_refresh_token(id, token_id)) &&
|
117
|
+
timing_safe_eql?(key, convert_token_key(actual)) &&
|
118
|
+
jwt_refresh_token_match?(key)
|
119
|
+
return
|
120
|
+
end
|
94
121
|
|
95
122
|
ds = account_ds(id)
|
96
123
|
ds = ds.where(account_status_column=>account_open_status_value) unless skip_status_checks?
|
@@ -107,6 +134,23 @@ module Rodauth
|
|
107
134
|
[id, token_id, key]
|
108
135
|
end
|
109
136
|
|
137
|
+
def _jwt_decode_opts
|
138
|
+
if allow_refresh_with_expired_jwt_access_token? && @jwt_refresh_route
|
139
|
+
Hash[super].merge!(:verify_expiration=>false)
|
140
|
+
else
|
141
|
+
super
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
def jwt_refresh_token_match?(key)
|
146
|
+
# We don't need to match tokens if we are requiring a valid current access token
|
147
|
+
return true unless allow_refresh_with_expired_jwt_access_token?
|
148
|
+
|
149
|
+
# If allowing with expired jwt access token, check the expired session contains
|
150
|
+
# hmac matching submitted and active refresh token.
|
151
|
+
timing_safe_eql?(compute_hmac(session[jwt_refresh_token_data_session_key].to_s + key), session[jwt_refresh_token_hmac_session_key].to_s)
|
152
|
+
end
|
153
|
+
|
110
154
|
def get_active_refresh_token(account_id, token_id)
|
111
155
|
jwt_refresh_token_account_ds(account_id).
|
112
156
|
where(Sequel::CURRENT_TIMESTAMP > jwt_refresh_token_deadline_column).
|
@@ -130,8 +174,7 @@ module Rodauth
|
|
130
174
|
end
|
131
175
|
|
132
176
|
def remove_jwt_refresh_token_key(token)
|
133
|
-
account_id,
|
134
|
-
token_id, _ = split_token(token)
|
177
|
+
account_id, token_id, _ = _account_refresh_token_split(token)
|
135
178
|
jwt_refresh_token_account_token_ds(account_id, token_id).delete
|
136
179
|
end
|
137
180
|
|
@@ -146,6 +189,15 @@ module Rodauth
|
|
146
189
|
hash
|
147
190
|
end
|
148
191
|
|
192
|
+
def set_jwt_refresh_token_hmac_session_key(token)
|
193
|
+
if allow_refresh_with_expired_jwt_access_token?
|
194
|
+
key = _account_refresh_token_split(token).last
|
195
|
+
data = random_key
|
196
|
+
set_session_value(jwt_refresh_token_data_session_key, data)
|
197
|
+
set_session_value(jwt_refresh_token_hmac_session_key, compute_hmac(data + key))
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
149
201
|
def before_logout
|
150
202
|
if token = param_or_nil(jwt_refresh_token_key_param)
|
151
203
|
if token == 'all'
|
@@ -154,9 +206,7 @@ module Rodauth
|
|
154
206
|
id, token_id, key = _account_refresh_token_split(token)
|
155
207
|
|
156
208
|
if id && token_id && key && (actual = get_active_refresh_token(session_value, token_id)) && timing_safe_eql?(key, convert_token_key(actual))
|
157
|
-
|
158
|
-
where(jwt_refresh_token_id_column=>token_id).
|
159
|
-
delete
|
209
|
+
jwt_refresh_token_account_token_ds(id, token_id).delete
|
160
210
|
end
|
161
211
|
end
|
162
212
|
end
|
@@ -23,6 +23,8 @@ module Rodauth
|
|
23
23
|
auth_cached_method :login_form_footer_links
|
24
24
|
auth_cached_method :login_form_footer
|
25
25
|
|
26
|
+
auth_value_methods :login_return_to_requested_location_path
|
27
|
+
|
26
28
|
route do |r|
|
27
29
|
check_already_logged_in
|
28
30
|
before_login_route
|
@@ -85,12 +87,16 @@ module Rodauth
|
|
85
87
|
end
|
86
88
|
|
87
89
|
def login_required
|
88
|
-
if login_return_to_requested_location?
|
89
|
-
set_session_value(login_redirect_session_key,
|
90
|
+
if login_return_to_requested_location? && (path = login_return_to_requested_location_path)
|
91
|
+
set_session_value(login_redirect_session_key, path)
|
90
92
|
end
|
91
93
|
super
|
92
94
|
end
|
93
95
|
|
96
|
+
def login_return_to_requested_location_path
|
97
|
+
request.fullpath if request.get?
|
98
|
+
end
|
99
|
+
|
94
100
|
def after_login_entered_during_multi_phase_login
|
95
101
|
set_notice_now_flash need_password_notice_flash
|
96
102
|
if multi_phase_login_forms.length == 1 && (meth = multi_phase_login_forms[0][2])
|
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,16 @@ 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)
|
136
|
+
opts[:httponly] = true unless opts.key?(:httponly)
|
137
|
+
opts[:secure] = true unless opts.key?(:secure) || !request.ssl?
|
135
138
|
::Rack::Utils.set_cookie_header!(response.headers, remember_cookie_key, opts)
|
136
139
|
end
|
137
140
|
|
138
141
|
def forget_login
|
139
|
-
|
142
|
+
opts = Hash[remember_cookie_options]
|
143
|
+
opts[:path] = "/" unless opts.key?(:path)
|
144
|
+
::Rack::Utils.delete_cookie_header!(response.headers, remember_cookie_key, opts)
|
140
145
|
end
|
141
146
|
|
142
147
|
def get_remember_key
|
@@ -47,7 +47,6 @@ module Rodauth
|
|
47
47
|
:get_verify_account_key,
|
48
48
|
:get_verify_account_email_last_sent,
|
49
49
|
:remove_verify_account_key,
|
50
|
-
:resend_verify_account_view,
|
51
50
|
:send_verify_account_email,
|
52
51
|
:set_verify_account_email_last_sent,
|
53
52
|
:verify_account,
|
@@ -245,6 +244,12 @@ module Rodauth
|
|
245
244
|
end
|
246
245
|
end
|
247
246
|
|
247
|
+
def setup_account_verification
|
248
|
+
generate_verify_account_key_value
|
249
|
+
create_verify_account_key
|
250
|
+
send_verify_account_email
|
251
|
+
end
|
252
|
+
|
248
253
|
private
|
249
254
|
|
250
255
|
def _login_form_footer_links
|
@@ -276,12 +281,6 @@ module Rodauth
|
|
276
281
|
super
|
277
282
|
end
|
278
283
|
|
279
|
-
def setup_account_verification
|
280
|
-
generate_verify_account_key_value
|
281
|
-
create_verify_account_key
|
282
|
-
send_verify_account_email
|
283
|
-
end
|
284
|
-
|
285
284
|
def verify_account_check_already_logged_in
|
286
285
|
check_already_logged_in
|
287
286
|
end
|
@@ -8,6 +8,7 @@ module Rodauth
|
|
8
8
|
error_flash "Unable to change login as there is already an account with the new login", 'verify_login_change_duplicate_account'
|
9
9
|
error_flash "There was an error verifying your login change: invalid verify login change key", 'no_matching_verify_login_change_key'
|
10
10
|
notice_flash "Your login change has been verified"
|
11
|
+
notice_flash "An email has been sent to you with a link to verify your login change", 'change_login_needs_verification'
|
11
12
|
loaded_templates %w'verify-login-change verify-login-change-email'
|
12
13
|
view 'verify-login-change', 'Verify Login Change'
|
13
14
|
additional_form_tags
|
@@ -131,7 +132,7 @@ module Rodauth
|
|
131
132
|
end
|
132
133
|
|
133
134
|
def change_login_notice_flash
|
134
|
-
|
135
|
+
change_login_needs_verification_notice_flash
|
135
136
|
end
|
136
137
|
|
137
138
|
def verify_login_change_old_login
|
@@ -29,7 +29,7 @@ module Rodauth
|
|
29
29
|
|
30
30
|
def before_verify_account
|
31
31
|
super
|
32
|
-
if features.include?(:
|
32
|
+
if features.include?(:json) && use_json? && !param_or_nil(webauthn_setup_param)
|
33
33
|
cred = new_webauthn_credential
|
34
34
|
json_response[webauthn_setup_param] = cred.as_json
|
35
35
|
json_response[webauthn_setup_challenge_param] = cred.challenge
|
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.9.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:
|
11
|
+
date: 2021-01-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: sequel
|
@@ -237,28 +237,34 @@ extra_rdoc_files:
|
|
237
237
|
- README.rdoc
|
238
238
|
- CHANGELOG
|
239
239
|
- MIT-LICENSE
|
240
|
-
- doc/change_password_notify.rdoc
|
241
240
|
- doc/account_expiration.rdoc
|
241
|
+
- doc/active_sessions.rdoc
|
242
|
+
- doc/audit_logging.rdoc
|
242
243
|
- doc/base.rdoc
|
243
244
|
- doc/change_login.rdoc
|
244
245
|
- doc/change_password.rdoc
|
245
|
-
- doc/
|
246
|
+
- doc/change_password_notify.rdoc
|
246
247
|
- doc/close_account.rdoc
|
247
|
-
- doc/
|
248
|
+
- doc/confirm_password.rdoc
|
248
249
|
- doc/create_account.rdoc
|
249
|
-
- doc/email_base.rdoc
|
250
250
|
- doc/disallow_common_passwords.rdoc
|
251
251
|
- doc/disallow_password_reuse.rdoc
|
252
|
-
- doc/
|
252
|
+
- doc/email_auth.rdoc
|
253
|
+
- doc/email_base.rdoc
|
254
|
+
- doc/http_basic_auth.rdoc
|
255
|
+
- doc/json.rdoc
|
253
256
|
- doc/jwt.rdoc
|
257
|
+
- doc/jwt_cors.rdoc
|
258
|
+
- doc/jwt_refresh.rdoc
|
254
259
|
- doc/lockout.rdoc
|
255
260
|
- doc/login.rdoc
|
261
|
+
- doc/login_password_requirements_base.rdoc
|
256
262
|
- doc/logout.rdoc
|
257
263
|
- doc/otp.rdoc
|
258
|
-
- doc/
|
259
|
-
- doc/jwt_cors.rdoc
|
264
|
+
- doc/password_complexity.rdoc
|
260
265
|
- doc/password_expiration.rdoc
|
261
266
|
- doc/password_grace_period.rdoc
|
267
|
+
- doc/password_pepper.rdoc
|
262
268
|
- doc/recovery_codes.rdoc
|
263
269
|
- doc/remember.rdoc
|
264
270
|
- doc/reset_password.rdoc
|
@@ -268,17 +274,11 @@ extra_rdoc_files:
|
|
268
274
|
- doc/two_factor_base.rdoc
|
269
275
|
- doc/update_password_hash.rdoc
|
270
276
|
- doc/verify_account.rdoc
|
271
|
-
- doc/email_auth.rdoc
|
272
|
-
- doc/jwt_refresh.rdoc
|
273
277
|
- doc/verify_account_grace_period.rdoc
|
274
278
|
- doc/verify_login_change.rdoc
|
275
279
|
- doc/webauthn.rdoc
|
276
280
|
- doc/webauthn_login.rdoc
|
277
281
|
- doc/webauthn_verify_account.rdoc
|
278
|
-
- doc/active_sessions.rdoc
|
279
|
-
- doc/audit_logging.rdoc
|
280
|
-
- doc/password_pepper.rdoc
|
281
|
-
- doc/release_notes/1.17.0.txt
|
282
282
|
- doc/release_notes/1.0.0.txt
|
283
283
|
- doc/release_notes/1.1.0.txt
|
284
284
|
- doc/release_notes/1.10.0.txt
|
@@ -288,7 +288,14 @@ extra_rdoc_files:
|
|
288
288
|
- doc/release_notes/1.14.0.txt
|
289
289
|
- doc/release_notes/1.15.0.txt
|
290
290
|
- doc/release_notes/1.16.0.txt
|
291
|
+
- doc/release_notes/1.17.0.txt
|
292
|
+
- doc/release_notes/1.18.0.txt
|
293
|
+
- doc/release_notes/1.19.0.txt
|
291
294
|
- doc/release_notes/1.2.0.txt
|
295
|
+
- doc/release_notes/1.20.0.txt
|
296
|
+
- doc/release_notes/1.21.0.txt
|
297
|
+
- doc/release_notes/1.22.0.txt
|
298
|
+
- doc/release_notes/1.23.0.txt
|
292
299
|
- doc/release_notes/1.3.0.txt
|
293
300
|
- doc/release_notes/1.4.0.txt
|
294
301
|
- doc/release_notes/1.5.0.txt
|
@@ -296,17 +303,16 @@ extra_rdoc_files:
|
|
296
303
|
- doc/release_notes/1.7.0.txt
|
297
304
|
- doc/release_notes/1.8.0.txt
|
298
305
|
- doc/release_notes/1.9.0.txt
|
299
|
-
- doc/release_notes/1.18.0.txt
|
300
|
-
- doc/release_notes/1.19.0.txt
|
301
|
-
- doc/release_notes/1.20.0.txt
|
302
|
-
- doc/release_notes/1.21.0.txt
|
303
|
-
- doc/release_notes/1.22.0.txt
|
304
|
-
- doc/release_notes/1.23.0.txt
|
305
306
|
- doc/release_notes/2.0.0.txt
|
306
307
|
- doc/release_notes/2.1.0.txt
|
307
308
|
- doc/release_notes/2.2.0.txt
|
308
309
|
- doc/release_notes/2.3.0.txt
|
309
310
|
- doc/release_notes/2.4.0.txt
|
311
|
+
- doc/release_notes/2.5.0.txt
|
312
|
+
- doc/release_notes/2.6.0.txt
|
313
|
+
- doc/release_notes/2.7.0.txt
|
314
|
+
- doc/release_notes/2.8.0.txt
|
315
|
+
- doc/release_notes/2.9.0.txt
|
310
316
|
files:
|
311
317
|
- CHANGELOG
|
312
318
|
- MIT-LICENSE
|
@@ -348,6 +354,7 @@ files:
|
|
348
354
|
- doc/guides/status_column.rdoc
|
349
355
|
- doc/guides/totp_or_recovery.rdoc
|
350
356
|
- doc/http_basic_auth.rdoc
|
357
|
+
- doc/json.rdoc
|
351
358
|
- doc/jwt.rdoc
|
352
359
|
- doc/jwt_cors.rdoc
|
353
360
|
- doc/jwt_refresh.rdoc
|
@@ -390,6 +397,11 @@ files:
|
|
390
397
|
- doc/release_notes/2.2.0.txt
|
391
398
|
- doc/release_notes/2.3.0.txt
|
392
399
|
- doc/release_notes/2.4.0.txt
|
400
|
+
- doc/release_notes/2.5.0.txt
|
401
|
+
- doc/release_notes/2.6.0.txt
|
402
|
+
- doc/release_notes/2.7.0.txt
|
403
|
+
- doc/release_notes/2.8.0.txt
|
404
|
+
- doc/release_notes/2.9.0.txt
|
393
405
|
- doc/remember.rdoc
|
394
406
|
- doc/reset_password.rdoc
|
395
407
|
- doc/session_expiration.rdoc
|
@@ -422,6 +434,7 @@ files:
|
|
422
434
|
- lib/rodauth/features/email_auth.rb
|
423
435
|
- lib/rodauth/features/email_base.rb
|
424
436
|
- lib/rodauth/features/http_basic_auth.rb
|
437
|
+
- lib/rodauth/features/json.rb
|
425
438
|
- lib/rodauth/features/jwt.rb
|
426
439
|
- lib/rodauth/features/jwt_cors.rb
|
427
440
|
- lib/rodauth/features/jwt_refresh.rb
|
@@ -533,7 +546,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
533
546
|
- !ruby/object:Gem::Version
|
534
547
|
version: '0'
|
535
548
|
requirements: []
|
536
|
-
rubygems_version: 3.
|
549
|
+
rubygems_version: 3.2.3
|
537
550
|
signing_key:
|
538
551
|
specification_version: 4
|
539
552
|
summary: Authentication and Account Management Framework for Rack Applications
|