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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f79db7dec7147665538bf0b4f8e0c6c554d88396b294f19e5a5ed26543c31d1c
4
- data.tar.gz: ea377861679a55895bc325b1cf3932970b0de9c773615ba2daecb5805704ae02
3
+ metadata.gz: c1a80af909390a66924a6a3317b9234cd7b99032878b4ffd794fe621fba48b6d
4
+ data.tar.gz: cba66489bfb59d011d4d960b9b6f2d9c6c1f3f606661467ea888f6072d2f272b
5
5
  SHA512:
6
- metadata.gz: 8e13b4dc188867866ee0eda53765091bb48f583d65957e488737b612bde4cf4ae9caa18edd2d88b3c609a7a3e25a51eec42fc5aa25e4083ea51c283310a36cb9
7
- data.tar.gz: d50e275056bf3196a025e1933ab97ecd88d784c80ec97412cf046bb9718f558da4b321f7fbf52ba09d3554059157ef67f3f407625fd65c237fd2334e170066a7
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
- response.headers["WWW-Authenticate"] = "Basic realm=\"#{http_basic_auth_realm}\""
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
- response.headers['Allow'] = 'POST'
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['Content-Type'] ||= json_response_content_type
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
 
@@ -47,7 +47,7 @@ module Rodauth
47
47
 
48
48
  if session_data
49
49
  if jwt_symbolize_deeply?
50
- s = JSON.parse(JSON.fast_generate(session_data), :symbolize_names=>true)
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
- response.headers['Authorization'] = token
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
- response['Access-Control-Allow-Origin'] = request.env['HTTP_ORIGIN']
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
- response['Access-Control-Allow-Methods'] = jwt_cors_allow_methods
41
- response['Access-Control-Allow-Headers'] = jwt_cors_allow_headers
42
- response['Access-Control-Max-Age'] = jwt_cors_max_age.to_s
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
- response['Access-Control-Expose-Headers'] = jwt_cors_expose_headers
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
- response['Content-Type'] = 'text/javascript'
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
- response['Content-Type'] = 'text/javascript'
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
- def webauthn_relying_party
414
- # No need to memoize, only called once per request
415
- WebAuthn::RelyingParty.new(
416
- origin: webauthn_origin,
417
- id: webauthn_rp_id,
418
- name: webauthn_rp_name,
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
@@ -12,7 +12,7 @@ module Rodauth
12
12
  route(:webauthn_autofill_js) do |r|
13
13
  before_webauthn_autofill_js_route
14
14
  r.get do
15
- response['Content-Type'] = 'text/javascript'
15
+ set_response_header('content-type', 'text/javascript')
16
16
  webauthn_autofill_js
17
17
  end
18
18
  end
@@ -6,7 +6,7 @@ module Rodauth
6
6
  MAJOR = 2
7
7
 
8
8
  # The minor version of Rodauth, updated for new feature releases of Rodauth.
9
- MINOR = 38
9
+ MINOR = 40
10
10
 
11
11
  # The patch version of Rodauth, updated only for bug fixes from the last
12
12
  # feature release.
@@ -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.38.0
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: 2025-01-15 00:00:00.000000000 Z
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.2
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: []