rodauth 2.26.1 → 2.28.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: f30e5f8dc756435bee2a6956764516d6697434f507e3226562659807a02b2f0a
4
- data.tar.gz: 71738c31b50b8f82f351eabf0743eb3439cf7519782a10483d16a32a3d0b709b
3
+ metadata.gz: 15ed571757453e13ded3557bd2736779546b2c759230f8ee9070976a0207899e
4
+ data.tar.gz: 9aa5adf648fa1449a75a03d62ae4907f71d41adc49e81fde8da52097042c986c
5
5
  SHA512:
6
- metadata.gz: 7b28515139d2894a9a6164e6ef6f95aebe33b8be4b54548bb4d5c616dd380c7eeb7ff9470c1ac8dc044bbcafb373b596324286f48c860375ed3e1b85aebb6b84
7
- data.tar.gz: 20445419c0e2af068dc3141976cda754e71bfcd96204c1f97215e81764afe4376a58f03cbd6d53c524364e3b56e4ae20ff34904b876a4dcc7beb89254e698b80
6
+ metadata.gz: bdae4bbe3d9c471f967a8b24741504494a4003edce0c265dba9026694d64c08f61bd74cdbf80bded79e3b2c163fe7d273fcf72741f986711891fea5e481c501f
7
+ data.tar.gz: 5c6352c91b52012c6869a149e61887a1a6e0ace76557f2c4922eb699dc4da7f08a1265c5548bff25a3f617fa0a3b565b6d00f3472822d32812ae6261a4bcc95c
data/CHANGELOG CHANGED
@@ -1,3 +1,23 @@
1
+ === 2.28.0 (2023-02-22)
2
+
3
+ * Skip rendering reset password request form on invalid internal request logins (janko) (#303)
4
+
5
+ * Make logged_in? return false if using verify_account_grace_period feature and grace_period has expired (janko) (#300)
6
+
7
+ * Make password_hash method public (janko) (#299)
8
+
9
+ * Add webauthn_key_insert_hash auth method to webauthn feature to control inserts into webauthn keys table (janko) (#298)
10
+
11
+ === 2.27.0 (2023-01-24)
12
+
13
+ * Rename webauth_credentials_for_get to webauthn_credentials_for_get for consistency (janko) (#295)
14
+
15
+ * Hide WebAuthn text inputs by default when using Bootstrap (janko) (#294)
16
+
17
+ * Attempt to avoid database errors when invalid tokens are submitted (jeremyevans)
18
+
19
+ * Allow button template to be overridden just as other templates can be (jeremyevans) (#280)
20
+
1
21
  === 2.26.1 (2022-11-08)
2
22
 
3
23
  * Fix regression in QR code generation in otp feature causing all black QR code (janko) (#279)
data/MIT-LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2015-2021 Jeremy Evans
1
+ Copyright (c) 2015-2023 Jeremy Evans
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining a copy
4
4
  of this software and associated documentation files (the "Software"), to
data/doc/base.rdoc CHANGED
@@ -35,6 +35,7 @@ cache_templates :: Whether to cache templates. True by default. It may be worth
35
35
  check_csrf? :: Whether Rodauth should use Roda's +check_csrf!+ method for checking CSRF tokens before dispatching to Rodauth routes, true by default.
36
36
  check_csrf_opts :: Options to pass to Roda's +check_csrf!+ if Rodauth calls it before dispatching.
37
37
  check_csrf_block :: Proc for block to pass to Roda's +check_csrf!+ if Rodauth calls it before dispatching.
38
+ convert_token_id_to_integer? :: Whether token ids should be converted to a valid 64-bit integer value. If not set, defaults to true if +account_id_column+ uses an integer type, and false otherwise.
38
39
  default_field_attributes :: The default attributes to use for input field tags, if field_attributes returns nil for the field.
39
40
  default_redirect :: Where to redirect after most successful actions.
40
41
  field_attributes(field) :: The attributes to use for the input field tags for the given field (parameter name).
@@ -96,6 +97,7 @@ before_login_attempt :: Run arbitrary code after an account has been located, bu
96
97
  before_rodauth :: Run arbitrary code before handling any rodauth route, but after CSRF checks if Rodauth is doing CSRF checks.
97
98
  check_csrf :: Checks CSRF token using Roda's +check_csrf!+ method.
98
99
  clear_session :: Clears the current session.
100
+ convert_token_id(id) :: Convert the token id string to an appropriate object to use for the token id (or return +nil+ to signal an invalid token id). By default, converts to a 64-bit signed integer if +convert_token_id_to_integer?+ is true.
99
101
  csrf_tag(path=request.path) :: The HTML fragment containing the CSRF tag to use, if any.
100
102
  function_name(name) :: The name of the database function to call. It's passed either :rodauth_get_salt or :rodauth_valid_password_hash.
101
103
  logged_in? :: Whether the current session is logged in.
@@ -1,13 +1,16 @@
1
1
  = Customize password requirements
2
2
 
3
3
  By default, Rodauth requires passwords to have at least 6 characters. You can
4
- modify the minimum length:
4
+ modify the minimum and maximum length:
5
5
 
6
6
  plugin :rodauth do
7
7
  enable :login, :logout, :create_account
8
8
 
9
9
  # Require passwords to have at least 8 characters
10
10
  password_minimum_length 8
11
+
12
+ # Don't allow passwords to be too long, to prevent long password DoS attacks
13
+ password_maximum_length 64
11
14
  end
12
15
 
13
16
  You can use the {disallow common passwords feature}[rdoc-ref:doc/disallow_common_passwords.rdoc]
@@ -25,6 +28,16 @@ can use the <tt>password_meets_requirements?</tt> configuration method.
25
28
  enable :login, :logout, :create_account
26
29
 
27
30
  password_meets_requirements? do |password|
28
- #true if password meets requirements, false otherwise
31
+ super(password) && password_complex_enough?(password)
32
+ end
33
+
34
+ auth_class_eval do
35
+ # If password doesn't pass custom validation, add field error with error
36
+ # reason, and return false.
37
+ def password_complex_enough?(password)
38
+ return true if password.match?(/\d/) && password.match?(/[^a-zA-Z\d]/)
39
+ set_password_requirement_error_message(:password_simple, "requires one number and one special character")
40
+ false
41
+ end
29
42
  end
30
43
  end
data/doc/json.rdoc CHANGED
@@ -15,6 +15,14 @@ an array containing the field name and the error message for that field.
15
15
  Successful requests by default store a +success+ entry with a success
16
16
  message, though that can be disabled.
17
17
 
18
+ The JSON response can be modified at any point by modifying the `json_response`
19
+ hash. The following example adds an {error reason}[rdoc-ref:doc/error_reasons.rdoc]
20
+ to the JSON response:
21
+
22
+ set_error_reason do |reason|
23
+ json_response[:error_reason] = reason
24
+ end
25
+
18
26
  The session state is managed in the rack session, so make sure that
19
27
  CSRF protection is enabled. This will be the case when passing the
20
28
  <tt>json: true</tt> option when loading the rodauth plugin. If you
@@ -0,0 +1,35 @@
1
+ = Improvements
2
+
3
+ * Token ids submitting in requests are now converted to integers if
4
+ the configuration uses an integer primary key for the accounts
5
+ table. If the configuration uses a non-integer primary key for
6
+ the accounts table, the convert_token_id configuration method can
7
+ be used, which should return the token id converted to the
8
+ appropriate type, or nil if the token id is not valid for the type.
9
+
10
+ This revised handling avoids raising a database error when an
11
+ invalid token is submitted.
12
+
13
+ * The button template can now be overridden in the same way that
14
+ other Rodauth templates can be overridden.
15
+
16
+ * When using the Bootstrap CSS framework, the text field in the
17
+ Webauthn setup and auth forms is automatically hidden. The text
18
+ field already had a rodauth-hidden class to make it easy to hide
19
+ when using other CSS frameworks.
20
+
21
+ * The email_from and email_to methods are now public instead of
22
+ private.
23
+
24
+ * A nicer error is raised if the Sequel Database object is missing.
25
+
26
+ * A regression in the TOTP QR output that resulted in the QR codes
27
+ being solid black squares has been fixed (this was fixed in
28
+ Rodauth 2.26.1).
29
+
30
+ = Backwards Compatibility
31
+
32
+ * The webauth_credentials_for_get method in the webauthn feature has
33
+ been renamed to webauthn_credentials_for_get for consistency with
34
+ other methods. The webauth_credentials_for_get method will still
35
+ work until Rodauth 3, but will issue deprecation warnings.
@@ -0,0 +1,16 @@
1
+ = New Features
2
+
3
+ * A webauthn_key_insert_hash configuration method has been added when
4
+ using the webauthn feature, making it easier to add new columns to
5
+ the webauthn key data, such as a custom name for the authenticator.
6
+
7
+ = Other Improvements
8
+
9
+ * When using the verify_account_grace_period feature, logged_in? now
10
+ returns false for sessions where the grace period has expired.
11
+
12
+ * When using the internal_request and reset_password features,
13
+ submitting an internal request for an invalid login no longer tries
14
+ to render a reset password request form.
15
+
16
+ * The password_hash method is now public.
data/doc/webauthn.rdoc CHANGED
@@ -104,9 +104,10 @@ remove_all_webauthn_keys_and_user_ids :: Remove all WebAuthn credentials and the
104
104
  remove_webauthn_key(webauthn_id) :: Remove the WebAuthn credential with the given WebAuthn ID from the current account.
105
105
  valid_new_webauthn_credential?(webauthn_credential) :: Check wheck the WebAuthn credential provided by the client during registration is valid.
106
106
  valid_webauthn_credential_auth?(webauthn_credential) :: Check wheck the WebAuthn credential provided by the client during authentication is valid.
107
- webauth_credential_options_for_get :: WebAuthn credential options to provide to the client during WebAuthn authentication.
108
107
  webauthn_auth_js_path :: The path to the WebAuthn authentication javascript.
109
108
  webauthn_auth_view :: The HTML to use for the page for authenticating via WebAuthn.
109
+ webauthn_credential_options_for_get :: WebAuthn credential options to provide to the client during WebAuthn authentication.
110
+ webauthn_key_insert_hash(webauthn_credential) :: The hash to insert into the +webauthn_keys_table+.
110
111
  webauthn_remove_authenticated_session :: Remove the authenticated WebAuthn ID, used when removing the WebAuthn credential with the ID after authenticating with it.
111
112
  webauthn_remove_view :: The HTML to use for the page for removing an existing WebAuthn authenticator.
112
113
  webauthn_setup_js_path :: The path to the WebAuthn registration javascript.
@@ -15,6 +15,18 @@ module Rodauth
15
15
  auth_value_method :argon2_secret, nil
16
16
  auth_value_method :use_argon2?, true
17
17
 
18
+ def password_hash(password)
19
+ return super unless use_argon2?
20
+
21
+ if secret = argon2_secret
22
+ argon2_params = Hash[password_hash_cost]
23
+ argon2_params[:secret] = secret
24
+ else
25
+ argon2_params = password_hash_cost
26
+ end
27
+ ::Argon2::Password.new(argon2_params).create(password)
28
+ end
29
+
18
30
  private
19
31
 
20
32
  if Argon2::VERSION != '2.1.0'
@@ -34,18 +46,6 @@ module Rodauth
34
46
  argon2_hash_cost
35
47
  end
36
48
 
37
- def password_hash(password)
38
- return super unless use_argon2?
39
-
40
- if secret = argon2_secret
41
- argon2_params = Hash[password_hash_cost]
42
- argon2_params[:secret] = secret
43
- else
44
- argon2_params = password_hash_cost
45
- end
46
- ::Argon2::Password.new(argon2_params).create(password)
47
- end
48
-
49
49
  def password_hash_match?(hash, password)
50
50
  return super unless argon2_hash_algorithm?(hash)
51
51
  argon2_password_hash_match?(hash, password)
@@ -24,6 +24,7 @@ module Rodauth
24
24
  auth_value_method :check_csrf_block, nil
25
25
  auth_value_method :check_csrf_opts, {}.freeze
26
26
  auth_value_method :default_redirect, '/'
27
+ auth_value_method :convert_token_id_to_integer?, nil
27
28
  flash_key :flash_error_key, :error
28
29
  flash_key :flash_notice_key, :notice
29
30
  auth_value_method :hmac_secret, nil
@@ -115,6 +116,7 @@ module Rodauth
115
116
  auth_private_methods(
116
117
  :account_from_login,
117
118
  :account_from_session,
119
+ :convert_token_id,
118
120
  :field_attributes,
119
121
  :field_error_attributes,
120
122
  :formatted_field_error,
@@ -264,7 +266,7 @@ module Rodauth
264
266
  end
265
267
 
266
268
  def db
267
- Sequel::DATABASES.first
269
+ Sequel::DATABASES.first or raise "Sequel database connection is missing"
268
270
  end
269
271
 
270
272
  def password_field_autocomplete_value
@@ -376,10 +378,9 @@ module Rodauth
376
378
  def button_opts(value, opts)
377
379
  opts = Hash[template_opts].merge!(opts)
378
380
  opts[:locals] = {:value=>value, :opts=>opts}
379
- opts[:path] = template_path('button')
380
381
  opts[:cache] = cache_templates
381
382
  opts[:cache_key] = :rodauth_button
382
- opts
383
+ _template_opts(opts, 'button')
383
384
  end
384
385
 
385
386
  def button(value, opts={})
@@ -402,6 +403,11 @@ module Rodauth
402
403
  def post_configure
403
404
  require 'bcrypt' if require_bcrypt?
404
405
  db.extension :date_arithmetic if use_date_arithmetic?
406
+
407
+ if convert_token_id_to_integer?.nil? && (db rescue false) && db.table_exists?(accounts_table) && db.schema(accounts_table).find{|col, v| break v[:type] == :integer if col == account_id_column}
408
+ self.class.send(:define_method, :convert_token_id_to_integer?){true}
409
+ end
410
+
405
411
  route_hash= {}
406
412
  self.class.routes.each do |meth|
407
413
  route_meth = "#{meth.to_s.sub(/\Ahandle_/, '')}_route"
@@ -521,6 +527,25 @@ module Rodauth
521
527
  token.split(token_separator, 2)
522
528
  end
523
529
 
530
+ def convert_token_id(id)
531
+ if convert_token_id_to_integer?
532
+ convert_token_id_to_integer(id)
533
+ else
534
+ id
535
+ end
536
+ end
537
+
538
+ def convert_token_id_to_integer(id)
539
+ if id = (Integer(id, 10) rescue nil)
540
+ if id > 9223372036854775807 || id < -9223372036854775808
541
+ # Only allow 64-bit signed integer range to avoid problems on PostgreSQL
542
+ id = nil
543
+ end
544
+ end
545
+
546
+ id
547
+ end
548
+
524
549
  def redirect(path)
525
550
  request.redirect(path)
526
551
  end
@@ -817,12 +842,16 @@ module Rodauth
817
842
  opts[:locals][:rodauth] = self
818
843
  opts[:cache] = cache_templates
819
844
  opts[:cache_key] = :"rodauth_#{page}"
845
+ _template_opts(opts, page)
846
+ end
820
847
 
848
+ # Set the template path only if there isn't an overridden template in the application.
849
+ # Result should replace existing template opts.
850
+ def _template_opts(opts, page)
821
851
  opts = scope.send(:find_template, scope.send(:parse_template_opts, page, opts))
822
852
  unless File.file?(scope.send(:template_path, opts))
823
853
  opts[:path] = template_path(page)
824
854
  end
825
-
826
855
  opts
827
856
  end
828
857
 
@@ -23,6 +23,14 @@ module Rodauth
23
23
  require 'mail' if require_mail?
24
24
  end
25
25
 
26
+ def email_from
27
+ "webmaster@#{domain}"
28
+ end
29
+
30
+ def email_to
31
+ account[login_column]
32
+ end
33
+
26
34
  private
27
35
 
28
36
  def send_email(email)
@@ -42,14 +50,6 @@ module Rodauth
42
50
  m
43
51
  end
44
52
 
45
- def email_from
46
- "webmaster@#{domain}"
47
- end
48
-
49
- def email_to
50
- account[login_column]
51
- end
52
-
53
53
  def token_link(route, param, key)
54
54
  route_url(route, param => token_param_value(key))
55
55
  end
@@ -64,6 +64,7 @@ module Rodauth
64
64
 
65
65
  def account_from_key(token, status_id=nil)
66
66
  id, key = split_token(token)
67
+ id = convert_token_id(id)
67
68
  return unless id && key
68
69
 
69
70
  return unless actual = yield(id)
@@ -107,7 +107,7 @@ module Rodauth
107
107
  def before_webauthn_auth_route
108
108
  super if defined?(super)
109
109
  if use_json? && !param_or_nil(webauthn_auth_param)
110
- cred = webauth_credential_options_for_get
110
+ cred = webauthn_credential_options_for_get
111
111
  json_response[webauthn_auth_param] = cred.as_json
112
112
  json_response[webauthn_auth_challenge_param] = cred.challenge
113
113
  json_response[webauthn_auth_challenge_hmac_param] = compute_hmac(cred.challenge)
@@ -117,7 +117,7 @@ module Rodauth
117
117
  def before_webauthn_login_route
118
118
  super if defined?(super)
119
119
  if use_json? && !param_or_nil(webauthn_auth_param) && account_from_login(param(login_param))
120
- cred = webauth_credential_options_for_get
120
+ cred = webauthn_credential_options_for_get
121
121
  json_response[webauthn_auth_param] = cred.as_json
122
122
  json_response[webauthn_auth_challenge_param] = cred.challenge
123
123
  json_response[webauthn_auth_challenge_hmac_param] = compute_hmac(cred.challenge)
@@ -112,7 +112,7 @@ module Rodauth
112
112
  id, token_id, key = _account_refresh_token_split(token)
113
113
 
114
114
  unless key &&
115
- (id == session_value.to_s) &&
115
+ (id.to_s == session_value.to_s) &&
116
116
  (actual = get_active_refresh_token(id, token_id)) &&
117
117
  timing_safe_eql?(key, convert_token_key(actual)) &&
118
118
  jwt_refresh_token_match?(key)
@@ -126,9 +126,11 @@ module Rodauth
126
126
 
127
127
  def _account_refresh_token_split(token)
128
128
  id, token = split_token(token)
129
+ id = convert_token_id(id)
129
130
  return unless id && token
130
131
 
131
132
  token_id, key = split_token(token)
133
+ token_id = convert_token_id(token_id)
132
134
  return unless token_id && key
133
135
 
134
136
  [id, token_id, key]
@@ -75,6 +75,10 @@ module Rodauth
75
75
  hash
76
76
  end
77
77
 
78
+ def password_hash(password)
79
+ BCrypt::Password.create(password, :cost=>password_hash_cost)
80
+ end
81
+
78
82
  private
79
83
 
80
84
  attr_reader :login_requirement_message
@@ -184,9 +188,5 @@ module Rodauth
184
188
  def extract_password_hash_cost(hash)
185
189
  hash[4, 2].to_i
186
190
  end
187
-
188
- def password_hash(password)
189
- BCrypt::Password.create(password, :cost=>password_hash_cost)
190
- end
191
191
  end
192
192
  end
@@ -16,12 +16,12 @@ module Rodauth
16
16
  result
17
17
  end
18
18
 
19
- private
20
-
21
19
  def password_hash(password)
22
20
  super(password + password_pepper.to_s)
23
21
  end
24
22
 
23
+ private
24
+
25
25
  def password_hash_match?(hash, password)
26
26
  return super if password_pepper.nil?
27
27
 
@@ -219,7 +219,7 @@ module Rodauth
219
219
  attr_reader :reset_password_key_value
220
220
 
221
221
  def after_login_failure
222
- unless only_json?
222
+ unless only_json? || internal_request?
223
223
  @login_form_header = login_failed_reset_password_request_form
224
224
  end
225
225
  super
@@ -30,6 +30,10 @@ module Rodauth
30
30
  false
31
31
  end
32
32
 
33
+ def logged_in?
34
+ super && !unverified_grace_period_expired?
35
+ end
36
+
33
37
  def require_login
34
38
  if unverified_grace_period_expired?
35
39
  clear_session
@@ -102,13 +102,16 @@ module Rodauth
102
102
  :valid_new_webauthn_credential?,
103
103
  :valid_webauthn_credential_auth?,
104
104
  :webauthn_auth_js_path,
105
- :webauth_credential_options_for_get,
105
+ :webauthn_credential_options_for_get,
106
+ :webauthn_key_insert_hash,
106
107
  :webauthn_remove_authenticated_session,
107
108
  :webauthn_setup_js_path,
108
109
  :webauthn_update_session,
109
110
  :webauthn_user_name,
110
111
  )
111
112
 
113
+ def_deprecated_alias :webauthn_credential_options_for_get, :webauth_credential_options_for_get
114
+
112
115
  route(:webauthn_auth_js) do |r|
113
116
  before_webauthn_auth_js_route
114
117
  r.get do
@@ -315,7 +318,7 @@ module Rodauth
315
318
  webauthn_credential.verify(challenge)
316
319
  end
317
320
 
318
- def webauth_credential_options_for_get
321
+ def webauthn_credential_options_for_get
319
322
  WebAuthn::Credential.options_for_get(
320
323
  :allow => account_webauthn_ids,
321
324
  :timeout => webauthn_auth_timeout,
@@ -346,12 +349,7 @@ module Rodauth
346
349
  end
347
350
 
348
351
  def add_webauthn_credential(webauthn_credential)
349
- webauthn_keys_ds.insert(
350
- webauthn_keys_account_id_column => webauthn_account_id,
351
- webauthn_keys_webauthn_id_column => webauthn_credential.id,
352
- webauthn_keys_public_key_column => webauthn_credential.public_key,
353
- webauthn_keys_sign_count_column => Integer(webauthn_credential.sign_count)
354
- )
352
+ webauthn_keys_ds.insert(webauthn_key_insert_hash(webauthn_credential))
355
353
  super if defined?(super)
356
354
  nil
357
355
  end
@@ -433,6 +431,15 @@ module Rodauth
433
431
  super
434
432
  end
435
433
 
434
+ def webauthn_key_insert_hash(webauthn_credential)
435
+ {
436
+ webauthn_keys_account_id_column => webauthn_account_id,
437
+ webauthn_keys_webauthn_id_column => webauthn_credential.id,
438
+ webauthn_keys_public_key_column => webauthn_credential.public_key,
439
+ webauthn_keys_sign_count_column => Integer(webauthn_credential.sign_count)
440
+ }
441
+ end
442
+
436
443
  def webauthn_account_id
437
444
  session_value
438
445
  end
@@ -6,11 +6,11 @@ module Rodauth
6
6
  MAJOR = 2
7
7
 
8
8
  # The minor version of Rodauth, updated for new feature releases of Rodauth.
9
- MINOR = 26
9
+ MINOR = 28
10
10
 
11
11
  # The patch version of Rodauth, updated only for bug fixes from the last
12
12
  # feature release.
13
- TINY = 1
13
+ TINY = 0
14
14
 
15
15
  # The full version of Rodauth as a string
16
16
  VERSION = "#{MAJOR}.#{MINOR}.#{TINY}".freeze
@@ -1,9 +1,9 @@
1
- <form method="post" action="#{rodauth.webauthn_auth_form_path}" class="rodauth" role="form" id="webauthn-auth-form" data-credential-options="#{h((cred = rodauth.webauth_credential_options_for_get).as_json.to_json)}">
1
+ <form method="post" action="#{rodauth.webauthn_auth_form_path}" class="rodauth" role="form" id="webauthn-auth-form" data-credential-options="#{h((cred = rodauth.webauthn_credential_options_for_get).as_json.to_json)}">
2
2
  #{rodauth.webauthn_auth_additional_form_tags}
3
3
  #{rodauth.csrf_tag(rodauth.webauthn_auth_form_path)}
4
4
  <input type="hidden" name="#{rodauth.webauthn_auth_challenge_param}" value="#{cred.challenge}" />
5
5
  <input type="hidden" name="#{rodauth.webauthn_auth_challenge_hmac_param}" value="#{rodauth.compute_hmac(cred.challenge)}" />
6
- <input class="rodauth_hidden" aria-hidden="true" type="text" name="#{rodauth.webauthn_auth_param}" id="webauthn-auth" value="" />
6
+ <input class="rodauth_hidden d-none" aria-hidden="true" type="text" name="#{rodauth.webauthn_auth_param}" id="webauthn-auth" value="" />
7
7
  <div id="webauthn-auth-button">
8
8
  #{rodauth.button(rodauth.webauthn_auth_button)}
9
9
  </div>
@@ -3,7 +3,7 @@
3
3
  #{rodauth.csrf_tag}
4
4
  <input type="hidden" name="#{rodauth.webauthn_setup_challenge_param}" value="#{cred.challenge}" />
5
5
  <input type="hidden" name="#{rodauth.webauthn_setup_challenge_hmac_param}" value="#{rodauth.compute_hmac(cred.challenge)}" />
6
- <input class="rodauth_hidden" aria-hidden="true" type="text" name="#{rodauth.webauthn_setup_param}" id="webauthn-setup" value="" />
6
+ <input class="rodauth_hidden d-none" aria-hidden="true" type="text" name="#{rodauth.webauthn_setup_param}" id="webauthn-setup" value="" />
7
7
  #{rodauth.render('password-field') if rodauth.two_factor_modifications_require_password?}
8
8
  <div id="webauthn-setup-button">
9
9
  #{rodauth.button(rodauth.webauthn_setup_button)}
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.26.1
4
+ version: 2.28.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: 2022-11-08 00:00:00.000000000 Z
11
+ date: 2023-02-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: sequel
@@ -342,6 +342,8 @@ extra_rdoc_files:
342
342
  - doc/release_notes/2.24.0.txt
343
343
  - doc/release_notes/2.25.0.txt
344
344
  - doc/release_notes/2.26.0.txt
345
+ - doc/release_notes/2.27.0.txt
346
+ - doc/release_notes/2.28.0.txt
345
347
  - doc/release_notes/2.3.0.txt
346
348
  - doc/release_notes/2.4.0.txt
347
349
  - doc/release_notes/2.5.0.txt
@@ -455,6 +457,8 @@ files:
455
457
  - doc/release_notes/2.24.0.txt
456
458
  - doc/release_notes/2.25.0.txt
457
459
  - doc/release_notes/2.26.0.txt
460
+ - doc/release_notes/2.27.0.txt
461
+ - doc/release_notes/2.28.0.txt
458
462
  - doc/release_notes/2.3.0.txt
459
463
  - doc/release_notes/2.4.0.txt
460
464
  - doc/release_notes/2.5.0.txt
@@ -612,7 +616,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
612
616
  - !ruby/object:Gem::Version
613
617
  version: '0'
614
618
  requirements: []
615
- rubygems_version: 3.3.7
619
+ rubygems_version: 3.4.6
616
620
  signing_key:
617
621
  specification_version: 4
618
622
  summary: Authentication and Account Management Framework for Rack Applications