rodauth 2.38.0 → 2.40.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/lib/rodauth/features/base.rb +36 -0
- data/lib/rodauth/features/http_basic_auth.rb +1 -1
- data/lib/rodauth/features/json.rb +2 -2
- data/lib/rodauth/features/jwt.rb +2 -2
- data/lib/rodauth/features/jwt_cors.rb +5 -5
- data/lib/rodauth/features/login.rb +2 -1
- data/lib/rodauth/features/otp_unlock.rb +7 -0
- data/lib/rodauth/features/reset_password.rb +6 -3
- data/lib/rodauth/features/webauthn.rb +21 -9
- data/lib/rodauth/features/webauthn_autofill.rb +1 -1
- data/lib/rodauth/version.rb +1 -1
- data/templates/otp-unlock-not-available.str +0 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c1a80af909390a66924a6a3317b9234cd7b99032878b4ffd794fe621fba48b6d
|
4
|
+
data.tar.gz: cba66489bfb59d011d4d960b9b6f2d9c6c1f3f606661467ea888f6072d2f272b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f220a837ca8a81984accd87b52725633de82b7ea3452bf91bb3a43c529e4d03a785c6fccd4e5dc6c729a3f1fe33b8a8d535c25060c884dd38ef94c07d21f52ce
|
7
|
+
data.tar.gz: 91d278bf3d9e1f1eaa47ff77c98506581ece39b9ad61d6aa5588e98faf65261f804154980a8416d63cec77fe462fff2ce9e8e1186f1fcaf608f3703a94fed818
|
@@ -563,6 +563,42 @@ module Rodauth
|
|
563
563
|
s
|
564
564
|
end
|
565
565
|
|
566
|
+
if Rack.release >= '3'
|
567
|
+
def set_response_header(key, value)
|
568
|
+
response.headers[key] = value
|
569
|
+
end
|
570
|
+
|
571
|
+
def convert_response_header_key(key)
|
572
|
+
key
|
573
|
+
end
|
574
|
+
# :nocov:
|
575
|
+
else
|
576
|
+
def set_response_header(key, value)
|
577
|
+
response.headers[convert_response_header_key(key)] = value
|
578
|
+
end
|
579
|
+
|
580
|
+
# Attempt backwards compatibility on Rack < 3 by changing
|
581
|
+
# known cases from lower case to mixed case.
|
582
|
+
mixed_case_headers = {}
|
583
|
+
(<<-END).split.each { |k| mixed_case_headers[k.downcase.freeze] = k.freeze }
|
584
|
+
Access-Control-Allow-Headers
|
585
|
+
Access-Control-Allow-Methods
|
586
|
+
Access-Control-Allow-Origin
|
587
|
+
Access-Control-Expose-Headers
|
588
|
+
Access-Control-Max-Age
|
589
|
+
Allow
|
590
|
+
Authorization
|
591
|
+
Content-Type
|
592
|
+
Content-Length
|
593
|
+
WWW-Authenticate
|
594
|
+
END
|
595
|
+
mixed_case_headers.freeze
|
596
|
+
define_method(:convert_response_header_key) do |key|
|
597
|
+
mixed_case_headers.fetch(key, key)
|
598
|
+
end
|
599
|
+
end
|
600
|
+
# :nocov:
|
601
|
+
|
566
602
|
if RUBY_VERSION >= '2.1'
|
567
603
|
def button_fixed_locals
|
568
604
|
'(value:, opts:)'
|
@@ -73,7 +73,7 @@ module Rodauth
|
|
73
73
|
|
74
74
|
def set_http_basic_auth_error_response
|
75
75
|
response.status = 401
|
76
|
-
|
76
|
+
set_response_header("www-authenticate", "Basic realm=\"#{http_basic_auth_realm}\"")
|
77
77
|
end
|
78
78
|
|
79
79
|
def throw_basic_auth_error(*args)
|
@@ -186,7 +186,7 @@ module Rodauth
|
|
186
186
|
|
187
187
|
unless request.post?
|
188
188
|
response.status = 405
|
189
|
-
|
189
|
+
set_response_header('allow', 'POST')
|
190
190
|
json_response[json_response_error_key] = json_non_post_error_message
|
191
191
|
return_json_response
|
192
192
|
end
|
@@ -209,7 +209,7 @@ module Rodauth
|
|
209
209
|
|
210
210
|
def _return_json_response
|
211
211
|
response.status ||= json_response_error_status if json_response_error?
|
212
|
-
response['
|
212
|
+
response.headers[convert_response_header_key('content-type')] ||= json_response_content_type
|
213
213
|
return_response _json_response_body(json_response)
|
214
214
|
end
|
215
215
|
|
data/lib/rodauth/features/jwt.rb
CHANGED
@@ -47,7 +47,7 @@ module Rodauth
|
|
47
47
|
|
48
48
|
if session_data
|
49
49
|
if jwt_symbolize_deeply?
|
50
|
-
s = JSON.parse(JSON.
|
50
|
+
s = JSON.parse(JSON.generate(session_data), :symbolize_names=>true)
|
51
51
|
elsif scope.opts[:sessions_convert_symbols]
|
52
52
|
s = session_data
|
53
53
|
else
|
@@ -84,7 +84,7 @@ module Rodauth
|
|
84
84
|
end
|
85
85
|
|
86
86
|
def set_jwt_token(token)
|
87
|
-
|
87
|
+
set_response_header('authorization', token)
|
88
88
|
end
|
89
89
|
|
90
90
|
def use_jwt?
|
@@ -33,18 +33,18 @@ module Rodauth
|
|
33
33
|
|
34
34
|
def before_rodauth
|
35
35
|
if jwt_cors_allow?
|
36
|
-
|
36
|
+
set_response_header('access-control-allow-origin', request.env['HTTP_ORIGIN'])
|
37
37
|
|
38
38
|
# Handle CORS preflight request
|
39
39
|
if request.request_method == 'OPTIONS'
|
40
|
-
|
41
|
-
|
42
|
-
|
40
|
+
set_response_header('access-control-allow-methods', jwt_cors_allow_methods)
|
41
|
+
set_response_header('access-control-allow-headers', jwt_cors_allow_headers)
|
42
|
+
set_response_header('access-control-max-age', jwt_cors_max_age.to_s)
|
43
43
|
response.status = 204
|
44
44
|
return_response
|
45
45
|
end
|
46
46
|
|
47
|
-
|
47
|
+
set_response_header('access-control-expose-headers', jwt_cors_expose_headers)
|
48
48
|
end
|
49
49
|
|
50
50
|
super
|
@@ -15,6 +15,7 @@ module Rodauth
|
|
15
15
|
auth_value_method :login_error_status, 401
|
16
16
|
translatable_method :login_form_footer_links_heading, '<h2 class="rodauth-login-form-footer-links-heading">Other Options</h2>'
|
17
17
|
auth_value_method :login_return_to_requested_location?, false
|
18
|
+
auth_value_method :login_return_to_requested_location_max_path_size, 2048
|
18
19
|
auth_value_method :use_multi_phase_login?, false
|
19
20
|
|
20
21
|
session_key :login_redirect_session_key, :login_redirect
|
@@ -95,7 +96,7 @@ module Rodauth
|
|
95
96
|
end
|
96
97
|
|
97
98
|
def login_required
|
98
|
-
if login_return_to_requested_location? && (path = login_return_to_requested_location_path)
|
99
|
+
if login_return_to_requested_location? && (path = login_return_to_requested_location_path) && path.bytesize <= login_return_to_requested_location_max_path_size
|
99
100
|
set_session_value(login_redirect_session_key, path)
|
100
101
|
end
|
101
102
|
super
|
@@ -52,6 +52,7 @@ module Rodauth
|
|
52
52
|
:otp_unlock_auth_success,
|
53
53
|
:otp_unlock_available?,
|
54
54
|
:otp_unlock_deadline_passed?,
|
55
|
+
:otp_unlock_not_available_set_refresh_header,
|
55
56
|
:otp_unlock_refresh_tag,
|
56
57
|
)
|
57
58
|
|
@@ -72,6 +73,7 @@ module Rodauth
|
|
72
73
|
if otp_unlock_available?
|
73
74
|
otp_unlock_view
|
74
75
|
else
|
76
|
+
otp_unlock_not_available_set_refresh_header
|
75
77
|
otp_unlock_not_available_view
|
76
78
|
end
|
77
79
|
end
|
@@ -201,6 +203,7 @@ module Rodauth
|
|
201
203
|
end
|
202
204
|
|
203
205
|
def otp_unlock_refresh_tag
|
206
|
+
# RODAUTH3: Remove
|
204
207
|
"<meta http-equiv=\"refresh\" content=\"#{(otp_unlock_next_auth_attempt_after - Time.now).to_i + 1}\">"
|
205
208
|
end
|
206
209
|
|
@@ -224,6 +227,10 @@ module Rodauth
|
|
224
227
|
otp_unlock_data ? otp_unlock_data[otp_unlock_num_successes_column] : 0
|
225
228
|
end
|
226
229
|
|
230
|
+
def otp_unlock_not_available_set_refresh_header
|
231
|
+
response.headers["refresh"] = ((otp_unlock_next_auth_attempt_after - Time.now).to_i + 1).to_s
|
232
|
+
end
|
233
|
+
|
227
234
|
private
|
228
235
|
|
229
236
|
def show_otp_auth_link?
|
@@ -50,6 +50,7 @@ module Rodauth
|
|
50
50
|
:reset_password_email_link,
|
51
51
|
:reset_password_key_insert_hash,
|
52
52
|
:reset_password_key_value,
|
53
|
+
:reset_password_request_for_unverified_account,
|
53
54
|
:set_reset_password_email_last_sent
|
54
55
|
)
|
55
56
|
auth_private_methods(
|
@@ -73,9 +74,7 @@ module Rodauth
|
|
73
74
|
throw_error_reason(:no_matching_login, no_matching_login_error_status, login_param, no_matching_login_message)
|
74
75
|
end
|
75
76
|
|
76
|
-
unless open_account?
|
77
|
-
throw_error_reason(:unverified_account, unopen_account_error_status, login_param, unverified_account_message)
|
78
|
-
end
|
77
|
+
reset_password_request_for_unverified_account unless open_account?
|
79
78
|
|
80
79
|
if reset_password_email_recently_sent?
|
81
80
|
set_redirect_error_flash reset_password_email_recently_sent_error_flash
|
@@ -174,6 +173,10 @@ module Rodauth
|
|
174
173
|
end
|
175
174
|
end
|
176
175
|
|
176
|
+
def reset_password_request_for_unverified_account
|
177
|
+
throw_error_reason(:unverified_account, unopen_account_error_status, login_param, unverified_account_message)
|
178
|
+
end
|
179
|
+
|
177
180
|
def remove_reset_password_key
|
178
181
|
password_reset_ds.delete
|
179
182
|
end
|
@@ -123,7 +123,7 @@ module Rodauth
|
|
123
123
|
route(:webauthn_auth_js) do |r|
|
124
124
|
before_webauthn_auth_js_route
|
125
125
|
r.get do
|
126
|
-
|
126
|
+
set_response_header('content-type', 'text/javascript')
|
127
127
|
webauthn_auth_js
|
128
128
|
end
|
129
129
|
end
|
@@ -158,7 +158,7 @@ module Rodauth
|
|
158
158
|
route(:webauthn_setup_js) do |r|
|
159
159
|
before_webauthn_setup_js_route
|
160
160
|
r.get do
|
161
|
-
|
161
|
+
set_response_header('content-type', 'text/javascript')
|
162
162
|
webauthn_setup_js
|
163
163
|
end
|
164
164
|
end
|
@@ -410,13 +410,25 @@ module Rodauth
|
|
410
410
|
private
|
411
411
|
|
412
412
|
if WebAuthn::VERSION >= '3'
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
413
|
+
if WebAuthn::RelyingParty.instance_method(:initialize).parameters.include?([:key, :allowed_origins])
|
414
|
+
def webauthn_relying_party
|
415
|
+
# No need to memoize, only called once per request
|
416
|
+
WebAuthn::RelyingParty.new(
|
417
|
+
allowed_origins: [webauthn_origin],
|
418
|
+
id: webauthn_rp_id,
|
419
|
+
name: webauthn_rp_name,
|
420
|
+
)
|
421
|
+
end
|
422
|
+
# :nocov:
|
423
|
+
else
|
424
|
+
def webauthn_relying_party
|
425
|
+
WebAuthn::RelyingParty.new(
|
426
|
+
origin: webauthn_origin,
|
427
|
+
id: webauthn_rp_id,
|
428
|
+
name: webauthn_rp_name,
|
429
|
+
)
|
430
|
+
end
|
431
|
+
# :nocov:
|
420
432
|
end
|
421
433
|
|
422
434
|
def webauthn_create_relying_party_opts
|
data/lib/rodauth/version.rb
CHANGED
@@ -2,4 +2,3 @@
|
|
2
2
|
<p>#{rodauth.otp_unlock_required_consecutive_successes_label}: #{rodauth.otp_unlock_auths_required}</p>
|
3
3
|
<p>#{rodauth.otp_unlock_next_auth_attempt_label}: #{rodauth.otp_unlock_next_auth_attempt_after.strftime(rodauth.strftime_format)}</p>
|
4
4
|
<p>#{rodauth.otp_unlock_next_auth_attempt_refresh_label}</p>
|
5
|
-
#{rodauth.otp_unlock_refresh_tag}
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rodauth
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.40.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jeremy Evans
|
8
8
|
bindir: bin
|
9
9
|
cert_chain: []
|
10
|
-
date:
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
11
11
|
dependencies:
|
12
12
|
- !ruby/object:Gem::Dependency
|
13
13
|
name: sequel
|
@@ -402,7 +402,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
402
402
|
- !ruby/object:Gem::Version
|
403
403
|
version: '0'
|
404
404
|
requirements: []
|
405
|
-
rubygems_version: 3.6.
|
405
|
+
rubygems_version: 3.6.9
|
406
406
|
specification_version: 4
|
407
407
|
summary: Authentication and Account Management Framework for Rack Applications
|
408
408
|
test_files: []
|