rodauth 2.29.0 → 2.30.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 +6 -0
- data/README.rdoc +19 -0
- data/doc/release_notes/2.30.0.txt +15 -0
- data/doc/webauthn_autofill.rdoc +14 -0
- data/doc/webauthn_login.rdoc +1 -1
- data/doc/webauthn_verify_account.rdoc +1 -1
- data/javascript/webauthn_autofill.js +38 -0
- data/lib/rodauth/features/base.rb +4 -0
- data/lib/rodauth/features/json.rb +1 -1
- data/lib/rodauth/features/remember.rb +6 -2
- data/lib/rodauth/features/webauthn.rb +30 -22
- data/lib/rodauth/features/webauthn_autofill.rb +58 -0
- data/lib/rodauth/features/webauthn_login.rb +9 -1
- data/lib/rodauth/version.rb +1 -1
- data/templates/login-field.str +1 -1
- data/templates/webauthn-autofill.str +9 -0
- metadata +10 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8270d10e6c0fbe554fc322958893f2c8069363af6455c0d17b0a7d3aafab11bd
|
4
|
+
data.tar.gz: 6eae8a9487764a9b189b27b8f1588e1516d86a6953fdabe0cff6adfd84facb5a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d4dca9a0819842a478fac05f138b07452a054c7e498821eee7e61ab49640eccc46974d38c3aea1f71bf226eb7f76b03888a6734d7ae2139bcc74aca9a24bad6c
|
7
|
+
data.tar.gz: 5075118b0c6a8b27df251a2e6bfcd45e3dacc7ba1402bf5bacfc38a50b93b424a0ccdb479b1f5541d589f5687a8424c7319a194c0b01a80c762b725065190013
|
data/CHANGELOG
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
+
=== 2.30.0 (2023-05-22)
|
2
|
+
|
3
|
+
* Make load_memory in the remember feature not raise NoMethodError if logged in when the account no longer exists (jeremyevans) (#331)
|
4
|
+
|
5
|
+
* Add webauthn_autofill feature, for supporting autofill of webauthn information on the login form (janko) (#328)
|
6
|
+
|
1
7
|
=== 2.29.0 (2023-03-22)
|
2
8
|
|
3
9
|
* Support :render=>false plugin options (davekaro) (#319)
|
data/README.rdoc
CHANGED
@@ -37,6 +37,7 @@ HTML and JSON API for all supported features.
|
|
37
37
|
* WebAuthn (Multifactor authentication via WebAuthn)
|
38
38
|
* WebAuthn Login (Passwordless login via WebAuthn)
|
39
39
|
* WebAuthn Verify Account (Passwordless WebAuthn Setup)
|
40
|
+
* WebAuthn Autofill (Autofill WebAuthn credentials on login)
|
40
41
|
* OTP (Multifactor authentication via TOTP)
|
41
42
|
* Recovery Codes (Multifactor authentication via backup codes)
|
42
43
|
* SMS Codes (Multifactor authentication via SMS)
|
@@ -318,6 +319,16 @@ bad idea), you don't need to use the PostgreSQL citext extension. Just
|
|
318
319
|
remember to modify the migration below to use +String+ instead of +citext+
|
319
320
|
for the email in that case.
|
320
321
|
|
322
|
+
=== Grant schema rights (PostgreSQL 15+)
|
323
|
+
|
324
|
+
PostgreSQL 15 changed default database security so that only the database
|
325
|
+
owner has writable access to the public schema. Rodauth expects the
|
326
|
+
+ph+ account to have writable access to the public schema when setting
|
327
|
+
things up. Temporarily grant that access (it will be revoked after the
|
328
|
+
migation has run)
|
329
|
+
|
330
|
+
psql -U postgres -c "GRANT CREATE ON SCHEMA public TO ${DATABASE_NAME}_password" ${DATABASE_NAME}
|
331
|
+
|
321
332
|
=== Using non-default schema
|
322
333
|
|
323
334
|
PostgreSQL sets up new tables in the public schema by default.
|
@@ -739,6 +750,13 @@ One thing to notice in the above migrations is that Rodauth uses additional
|
|
739
750
|
tables for additional features, instead of additional columns in a single
|
740
751
|
table.
|
741
752
|
|
753
|
+
=== Revoking schema rights (PostgreSQL 15+)
|
754
|
+
|
755
|
+
If you explicit granted access to the public schema before running the
|
756
|
+
migration, revoke it afterward:
|
757
|
+
|
758
|
+
psql -U postgres -c "REVOKE CREATE ON SCHEMA public FROM ${DATABASE_NAME}_password" ${DATABASE_NAME}
|
759
|
+
|
742
760
|
=== Locking Down (PostgreSQL only)
|
743
761
|
|
744
762
|
After running the migrations, you can increase security slightly by making
|
@@ -915,6 +933,7 @@ view the appropriate file in the doc directory.
|
|
915
933
|
* {Verify Account Grace Period}[rdoc-ref:doc/verify_account_grace_period.rdoc]
|
916
934
|
* {Verify Login Change}[rdoc-ref:doc/verify_login_change.rdoc]
|
917
935
|
* {WebAuthn}[rdoc-ref:doc/webauthn.rdoc]
|
936
|
+
* {WebAuthn Autofill}[rdoc-ref:doc/webauthn_autofill.rdoc]
|
918
937
|
* {WebAuthn Login}[rdoc-ref:doc/webauthn_login.rdoc]
|
919
938
|
* {WebAuthn Verify Account}[rdoc-ref:doc/webauthn_verify_account.rdoc]
|
920
939
|
|
@@ -0,0 +1,15 @@
|
|
1
|
+
= New Features
|
2
|
+
|
3
|
+
* A webauthn_autofill feature has been added to allow autofilling
|
4
|
+
webauthn credentials during login (also known as conditional
|
5
|
+
mediation). This allows for easier login using passkeys.
|
6
|
+
This requires a supported browser and operating system on the
|
7
|
+
client side to work.
|
8
|
+
|
9
|
+
= Other Improvements
|
10
|
+
|
11
|
+
* The load_memory method in the remember feature no longer raises
|
12
|
+
a NoMethodError if the there is a remember cookie, the session is
|
13
|
+
already logged in, and the account no longer exists. The
|
14
|
+
load_memory method now removes the remember cookie and clears the
|
15
|
+
session in that case.
|
@@ -0,0 +1,14 @@
|
|
1
|
+
= Documentation for WebAuthn Autofill Feature
|
2
|
+
|
3
|
+
The webauthn_autofill feature enables autofill UI (aka "conditional mediation")
|
4
|
+
for WebAuthn credentials, logging the user in on selection. It depends on the
|
5
|
+
webauthn_login feature.
|
6
|
+
|
7
|
+
== Auth Value Methods
|
8
|
+
|
9
|
+
webauthn_autofill_js :: The javascript code to execute on the login page to enable autofill UI.
|
10
|
+
webauthn_autofill_js_route :: The route to the webauthn autofill javascript file.
|
11
|
+
|
12
|
+
== Auth Methods
|
13
|
+
|
14
|
+
before_webauthn_autofill_js_route :: Run arbitrary code before handling a webauthn autofill javascript route.
|
data/doc/webauthn_login.rdoc
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
= Documentation for WebAuthn Verify Account Feature
|
2
2
|
|
3
|
-
The
|
3
|
+
The webauthn_verify_account feature implements setting up an WebAuthn authenticator
|
4
4
|
during the account verification process, and making such setup
|
5
5
|
a requirement for account verification. By default, it disables
|
6
6
|
asking for a password during account creation and verification,
|
@@ -0,0 +1,38 @@
|
|
1
|
+
(function() {
|
2
|
+
var pack = function(v) { return btoa(String.fromCharCode.apply(null, new Uint8Array(v))).replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, ''); };
|
3
|
+
var unpack = function(v) { return Uint8Array.from(atob(v.replace(/-/g, '+').replace(/_/g, '/')), c => c.charCodeAt(0)); };
|
4
|
+
var element = document.getElementById('webauthn-login-form');
|
5
|
+
|
6
|
+
if (!window.PublicKeyCredential || !PublicKeyCredential.isConditionalMediationAvailable) return;
|
7
|
+
|
8
|
+
PublicKeyCredential.isConditionalMediationAvailable().then(function(available) {
|
9
|
+
if (!available) return;
|
10
|
+
|
11
|
+
var opts = JSON.parse(element.getAttribute("data-credential-options"));
|
12
|
+
opts.challenge = unpack(opts.challenge);
|
13
|
+
opts.allowCredentials.forEach(function(cred) { cred.id = unpack(cred.id); });
|
14
|
+
|
15
|
+
navigator.credentials.get({mediation: "conditional", publicKey: opts}).then(function(cred) {
|
16
|
+
var rawId = pack(cred.rawId);
|
17
|
+
var authValue = {
|
18
|
+
type: cred.type,
|
19
|
+
id: rawId,
|
20
|
+
rawId: rawId,
|
21
|
+
response: {
|
22
|
+
authenticatorData: pack(cred.response.authenticatorData),
|
23
|
+
clientDataJSON: pack(cred.response.clientDataJSON),
|
24
|
+
signature: pack(cred.response.signature)
|
25
|
+
}
|
26
|
+
};
|
27
|
+
|
28
|
+
if (cred.response.userHandle) {
|
29
|
+
authValue.response.userHandle = pack(cred.response.userHandle);
|
30
|
+
}
|
31
|
+
|
32
|
+
document.getElementById('webauthn-auth').value = JSON.stringify(authValue);
|
33
|
+
|
34
|
+
element.submit();
|
35
|
+
});
|
36
|
+
});
|
37
|
+
})();
|
38
|
+
|
@@ -269,6 +269,10 @@ module Rodauth
|
|
269
269
|
Sequel::DATABASES.first or raise "Sequel database connection is missing"
|
270
270
|
end
|
271
271
|
|
272
|
+
def login_field_autocomplete_value
|
273
|
+
login_uses_email? ? "email" : "on"
|
274
|
+
end
|
275
|
+
|
272
276
|
def password_field_autocomplete_value
|
273
277
|
@password_field_autocomplete_value || 'current-password'
|
274
278
|
end
|
@@ -116,7 +116,7 @@ module Rodauth
|
|
116
116
|
|
117
117
|
def before_webauthn_login_route
|
118
118
|
super if defined?(super)
|
119
|
-
if use_json? && !param_or_nil(webauthn_auth_param) &&
|
119
|
+
if use_json? && !param_or_nil(webauthn_auth_param) && webauthn_login_options?
|
120
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
|
@@ -114,8 +114,12 @@ module Rodauth
|
|
114
114
|
def load_memory
|
115
115
|
if logged_in?
|
116
116
|
if extend_remember_deadline_while_logged_in?
|
117
|
-
account_from_session
|
118
|
-
|
117
|
+
if account_from_session
|
118
|
+
extend_remember_deadline
|
119
|
+
else
|
120
|
+
forget_login
|
121
|
+
clear_session
|
122
|
+
end
|
119
123
|
end
|
120
124
|
elsif account_from_remember_cookie
|
121
125
|
before_load_memory
|
@@ -320,7 +320,7 @@ module Rodauth
|
|
320
320
|
|
321
321
|
def webauthn_credential_options_for_get
|
322
322
|
WebAuthn::Credential.options_for_get(
|
323
|
-
:allow =>
|
323
|
+
:allow => webauthn_allow,
|
324
324
|
:timeout => webauthn_auth_timeout,
|
325
325
|
:rp_id => webauthn_rp_id,
|
326
326
|
:user_verification => webauthn_user_verification,
|
@@ -336,6 +336,10 @@ module Rodauth
|
|
336
336
|
base_url
|
337
337
|
end
|
338
338
|
|
339
|
+
def webauthn_allow
|
340
|
+
account_webauthn_ids
|
341
|
+
end
|
342
|
+
|
339
343
|
def webauthn_rp_id
|
340
344
|
webauthn_origin.sub(/\Ahttps?:\/\//, '').sub(/:\d+\z/, '')
|
341
345
|
end
|
@@ -453,21 +457,8 @@ module Rodauth
|
|
453
457
|
end
|
454
458
|
|
455
459
|
def webauthn_auth_credential_from_form_submission
|
456
|
-
case auth_data = raw_param(webauthn_auth_param)
|
457
|
-
when String
|
458
|
-
begin
|
459
|
-
auth_data = JSON.parse(auth_data)
|
460
|
-
rescue
|
461
|
-
throw_error_reason(:invalid_webauthn_auth_param, invalid_field_error_status, webauthn_auth_param, webauthn_invalid_auth_param_message)
|
462
|
-
end
|
463
|
-
when Hash
|
464
|
-
# nothing
|
465
|
-
else
|
466
|
-
throw_error_reason(:invalid_webauthn_auth_param, invalid_field_error_status, webauthn_auth_param, webauthn_invalid_auth_param_message)
|
467
|
-
end
|
468
|
-
|
469
460
|
begin
|
470
|
-
webauthn_credential = WebAuthn::Credential.from_get(
|
461
|
+
webauthn_credential = WebAuthn::Credential.from_get(webauthn_auth_data)
|
471
462
|
unless valid_webauthn_credential_auth?(webauthn_credential)
|
472
463
|
throw_error_reason(:invalid_webauthn_auth_param, invalid_key_error_status, webauthn_auth_param, webauthn_invalid_auth_param_message)
|
473
464
|
end
|
@@ -480,26 +471,28 @@ module Rodauth
|
|
480
471
|
webauthn_credential
|
481
472
|
end
|
482
473
|
|
483
|
-
def
|
484
|
-
case
|
474
|
+
def webauthn_auth_data
|
475
|
+
case auth_data = raw_param(webauthn_auth_param)
|
485
476
|
when String
|
486
477
|
begin
|
487
|
-
|
478
|
+
JSON.parse(auth_data)
|
488
479
|
rescue
|
489
|
-
throw_error_reason(:
|
480
|
+
throw_error_reason(:invalid_webauthn_auth_param, invalid_field_error_status, webauthn_auth_param, webauthn_invalid_auth_param_message)
|
490
481
|
end
|
491
482
|
when Hash
|
492
|
-
|
483
|
+
auth_data
|
493
484
|
else
|
494
|
-
throw_error_reason(:
|
485
|
+
throw_error_reason(:invalid_webauthn_auth_param, invalid_field_error_status, webauthn_auth_param, webauthn_invalid_auth_param_message)
|
495
486
|
end
|
487
|
+
end
|
496
488
|
|
489
|
+
def webauthn_setup_credential_from_form_submission
|
497
490
|
unless two_factor_password_match?(param(password_param))
|
498
491
|
throw_error_reason(:invalid_password, invalid_password_error_status, password_param, invalid_password_message)
|
499
492
|
end
|
500
493
|
|
501
494
|
begin
|
502
|
-
webauthn_credential = WebAuthn::Credential.from_create(
|
495
|
+
webauthn_credential = WebAuthn::Credential.from_create(webauthn_setup_data)
|
503
496
|
unless valid_new_webauthn_credential?(webauthn_credential)
|
504
497
|
throw_error_reason(:invalid_webauthn_setup_param, invalid_field_error_status, webauthn_setup_param, webauthn_invalid_setup_param_message)
|
505
498
|
end
|
@@ -509,5 +502,20 @@ module Rodauth
|
|
509
502
|
|
510
503
|
webauthn_credential
|
511
504
|
end
|
505
|
+
|
506
|
+
def webauthn_setup_data
|
507
|
+
case setup_data = raw_param(webauthn_setup_param)
|
508
|
+
when String
|
509
|
+
begin
|
510
|
+
JSON.parse(setup_data)
|
511
|
+
rescue
|
512
|
+
throw_error_reason(:invalid_webauthn_setup_param, invalid_field_error_status, webauthn_setup_param, webauthn_invalid_setup_param_message)
|
513
|
+
end
|
514
|
+
when Hash
|
515
|
+
setup_data
|
516
|
+
else
|
517
|
+
throw_error_reason(:invalid_webauthn_setup_param, invalid_field_error_status, webauthn_setup_param, webauthn_invalid_setup_param_message)
|
518
|
+
end
|
519
|
+
end
|
512
520
|
end
|
513
521
|
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# frozen-string-literal: true
|
2
|
+
|
3
|
+
module Rodauth
|
4
|
+
Feature.define(:webauthn_autofill, :WebauthnAutofill) do
|
5
|
+
depends :webauthn_login
|
6
|
+
|
7
|
+
auth_value_method :webauthn_autofill_js, File.binread(File.expand_path('../../../../javascript/webauthn_autofill.js', __FILE__)).freeze
|
8
|
+
|
9
|
+
route(:webauthn_autofill_js) do |r|
|
10
|
+
before_webauthn_autofill_js_route
|
11
|
+
r.get do
|
12
|
+
response['Content-Type'] = 'text/javascript'
|
13
|
+
webauthn_autofill_js
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def webauthn_allow
|
18
|
+
return [] unless logged_in? || account
|
19
|
+
super
|
20
|
+
end
|
21
|
+
|
22
|
+
def webauthn_user_verification
|
23
|
+
'preferred'
|
24
|
+
end
|
25
|
+
|
26
|
+
def webauthn_authenticator_selection
|
27
|
+
super.merge({ 'residentKey' => 'required', 'requireResidentKey' => true })
|
28
|
+
end
|
29
|
+
|
30
|
+
def login_field_autocomplete_value
|
31
|
+
request.path_info == login_path ? "#{super} webauthn" : super
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def _login_form_footer
|
37
|
+
footer = super
|
38
|
+
footer += render("webauthn-autofill") unless valid_login_entered?
|
39
|
+
footer
|
40
|
+
end
|
41
|
+
|
42
|
+
def account_from_webauthn_login
|
43
|
+
return super if param_or_nil(login_param)
|
44
|
+
|
45
|
+
credential_id = webauthn_auth_data["id"]
|
46
|
+
account_id = db[webauthn_keys_table]
|
47
|
+
.where(webauthn_keys_webauthn_id_column => credential_id)
|
48
|
+
.get(webauthn_keys_account_id_column)
|
49
|
+
|
50
|
+
@account = account_ds(account_id).first if account_id
|
51
|
+
end
|
52
|
+
|
53
|
+
def webauthn_login_options?
|
54
|
+
return true unless param_or_nil(login_param)
|
55
|
+
super
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -16,7 +16,7 @@ module Rodauth
|
|
16
16
|
|
17
17
|
r.post do
|
18
18
|
catch_error do
|
19
|
-
unless
|
19
|
+
unless account_from_webauthn_login && open_account?
|
20
20
|
throw_error_reason(:no_matching_login, no_matching_login_error_status, login_param, no_matching_login_message)
|
21
21
|
end
|
22
22
|
|
@@ -54,6 +54,14 @@ module Rodauth
|
|
54
54
|
|
55
55
|
private
|
56
56
|
|
57
|
+
def account_from_webauthn_login
|
58
|
+
account_from_login(param(login_param))
|
59
|
+
end
|
60
|
+
|
61
|
+
def webauthn_login_options?
|
62
|
+
!!account_from_webauthn_login
|
63
|
+
end
|
64
|
+
|
57
65
|
def _multi_phase_login_forms
|
58
66
|
forms = super
|
59
67
|
if valid_login_entered? && webauthn_setup?
|
data/lib/rodauth/version.rb
CHANGED
data/templates/login-field.str
CHANGED
@@ -1,4 +1,4 @@
|
|
1
1
|
<div class="form-group mb-3">
|
2
2
|
<label for="login" class="form-label">#{rodauth.login_label}#{rodauth.input_field_label_suffix}</label>
|
3
|
-
#{rodauth.input_field_string(rodauth.login_param, 'login', :type=>rodauth.login_input_type, :autocomplete=>rodauth.
|
3
|
+
#{rodauth.input_field_string(rodauth.login_param, 'login', :type=>rodauth.login_input_type, :autocomplete=>rodauth.login_field_autocomplete_value)}
|
4
4
|
</div>
|
@@ -0,0 +1,9 @@
|
|
1
|
+
<form method="post" action="#{rodauth.webauthn_login_path}" class="rodauth" role="form" id="webauthn-login-form" data-credential-options="#{h((cred = rodauth.webauthn_credential_options_for_get).as_json.to_json)}">
|
2
|
+
#{rodauth.webauthn_auth_additional_form_tags}
|
3
|
+
#{rodauth.csrf_tag(rodauth.webauthn_login_path)}
|
4
|
+
<input type="hidden" name="#{rodauth.webauthn_auth_challenge_param}" value="#{cred.challenge}" />
|
5
|
+
<input type="hidden" name="#{rodauth.webauthn_auth_challenge_hmac_param}" value="#{rodauth.compute_hmac(cred.challenge)}" />
|
6
|
+
<input class="rodauth_hidden d-none" aria-hidden="true" type="text" name="#{rodauth.webauthn_auth_param}" id="webauthn-auth" value="" />
|
7
|
+
#{rodauth.button(rodauth.webauthn_auth_button, class: "d-none")}
|
8
|
+
</form>
|
9
|
+
<script src="#{rodauth.webauthn_js_host}#{rodauth.webauthn_autofill_js_path}"></script>
|
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.30.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: 2023-
|
11
|
+
date: 2023-05-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: sequel
|
@@ -296,6 +296,7 @@ extra_rdoc_files:
|
|
296
296
|
- doc/verify_account_grace_period.rdoc
|
297
297
|
- doc/verify_login_change.rdoc
|
298
298
|
- doc/webauthn.rdoc
|
299
|
+
- doc/webauthn_autofill.rdoc
|
299
300
|
- doc/webauthn_login.rdoc
|
300
301
|
- doc/webauthn_verify_account.rdoc
|
301
302
|
- doc/release_notes/1.0.0.txt
|
@@ -346,6 +347,7 @@ extra_rdoc_files:
|
|
346
347
|
- doc/release_notes/2.28.0.txt
|
347
348
|
- doc/release_notes/2.29.0.txt
|
348
349
|
- doc/release_notes/2.3.0.txt
|
350
|
+
- doc/release_notes/2.30.0.txt
|
349
351
|
- doc/release_notes/2.4.0.txt
|
350
352
|
- doc/release_notes/2.5.0.txt
|
351
353
|
- doc/release_notes/2.6.0.txt
|
@@ -462,6 +464,7 @@ files:
|
|
462
464
|
- doc/release_notes/2.28.0.txt
|
463
465
|
- doc/release_notes/2.29.0.txt
|
464
466
|
- doc/release_notes/2.3.0.txt
|
467
|
+
- doc/release_notes/2.30.0.txt
|
465
468
|
- doc/release_notes/2.4.0.txt
|
466
469
|
- doc/release_notes/2.5.0.txt
|
467
470
|
- doc/release_notes/2.6.0.txt
|
@@ -480,9 +483,11 @@ files:
|
|
480
483
|
- doc/verify_account_grace_period.rdoc
|
481
484
|
- doc/verify_login_change.rdoc
|
482
485
|
- doc/webauthn.rdoc
|
486
|
+
- doc/webauthn_autofill.rdoc
|
483
487
|
- doc/webauthn_login.rdoc
|
484
488
|
- doc/webauthn_verify_account.rdoc
|
485
489
|
- javascript/webauthn_auth.js
|
490
|
+
- javascript/webauthn_autofill.js
|
486
491
|
- javascript/webauthn_setup.js
|
487
492
|
- lib/roda/plugins/rodauth.rb
|
488
493
|
- lib/rodauth.rb
|
@@ -530,6 +535,7 @@ files:
|
|
530
535
|
- lib/rodauth/features/verify_account_grace_period.rb
|
531
536
|
- lib/rodauth/features/verify_login_change.rb
|
532
537
|
- lib/rodauth/features/webauthn.rb
|
538
|
+
- lib/rodauth/features/webauthn_autofill.rb
|
533
539
|
- lib/rodauth/features/webauthn_login.rb
|
534
540
|
- lib/rodauth/features/webauthn_verify_account.rb
|
535
541
|
- lib/rodauth/migrations.rb
|
@@ -585,6 +591,7 @@ files:
|
|
585
591
|
- templates/verify-login-change-email.str
|
586
592
|
- templates/verify-login-change.str
|
587
593
|
- templates/webauthn-auth.str
|
594
|
+
- templates/webauthn-autofill.str
|
588
595
|
- templates/webauthn-remove.str
|
589
596
|
- templates/webauthn-setup.str
|
590
597
|
homepage: https://rodauth.jeremyevans.net
|
@@ -618,7 +625,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
618
625
|
- !ruby/object:Gem::Version
|
619
626
|
version: '0'
|
620
627
|
requirements: []
|
621
|
-
rubygems_version: 3.4.
|
628
|
+
rubygems_version: 3.4.10
|
622
629
|
signing_key:
|
623
630
|
specification_version: 4
|
624
631
|
summary: Authentication and Account Management Framework for Rack Applications
|