rodauth 2.12.0 → 2.13.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG +8 -0
- data/doc/base.rdoc +1 -0
- data/doc/error_reasons.rdoc +73 -0
- data/doc/release_notes/2.13.0.txt +19 -0
- data/lib/rodauth/features/active_sessions.rb +1 -1
- data/lib/rodauth/features/base.rb +15 -0
- data/lib/rodauth/features/change_login.rb +4 -4
- data/lib/rodauth/features/change_password.rb +3 -3
- data/lib/rodauth/features/close_account.rb +1 -1
- data/lib/rodauth/features/confirm_password.rb +2 -2
- data/lib/rodauth/features/create_account.rb +4 -4
- data/lib/rodauth/features/disallow_common_passwords.rb +1 -1
- data/lib/rodauth/features/disallow_password_reuse.rb +1 -1
- data/lib/rodauth/features/email_auth.rb +2 -0
- data/lib/rodauth/features/jwt_refresh.rb +3 -1
- data/lib/rodauth/features/lockout.rb +4 -2
- data/lib/rodauth/features/login.rb +3 -3
- data/lib/rodauth/features/login_password_requirements_base.rb +15 -6
- data/lib/rodauth/features/otp.rb +7 -6
- data/lib/rodauth/features/password_complexity.rb +4 -4
- data/lib/rodauth/features/recovery_codes.rb +2 -2
- data/lib/rodauth/features/remember.rb +1 -1
- data/lib/rodauth/features/reset_password.rb +5 -4
- data/lib/rodauth/features/session_expiration.rb +1 -0
- data/lib/rodauth/features/single_session.rb +1 -0
- data/lib/rodauth/features/sms_codes.rb +10 -5
- data/lib/rodauth/features/two_factor_base.rb +4 -1
- data/lib/rodauth/features/verify_account.rb +5 -1
- data/lib/rodauth/features/verify_login_change.rb +3 -2
- data/lib/rodauth/features/webauthn.rb +15 -14
- data/lib/rodauth/features/webauthn_login.rb +1 -1
- data/lib/rodauth/version.rb +1 -1
- data/templates/button.str +1 -1
- data/templates/change-password.str +2 -2
- data/templates/global-logout-field.str +1 -1
- data/templates/login-confirm-field.str +2 -2
- data/templates/login-display.str +2 -2
- data/templates/login-field.str +2 -2
- data/templates/otp-auth-code-field.str +2 -2
- data/templates/otp-setup.str +2 -2
- data/templates/password-confirm-field.str +2 -2
- data/templates/password-field.str +2 -2
- data/templates/recovery-auth.str +2 -2
- data/templates/remember.str +1 -1
- data/templates/sms-code-field.str +2 -2
- data/templates/sms-setup.str +2 -2
- data/templates/webauthn-remove.str +1 -1
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f01d42c90dd22a88566f17b3e77b9495dc1431f004f2f54865cff45a3874ce43
|
4
|
+
data.tar.gz: b09c0a44b2b4f6ab1eb795b11a69ec7acd1d4ed5ac4abbe45d8bb4072cb61e0f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2934f2824b7c805f6400fab52aad9c4aaca2f3bbfb4584688619b0b24b9e052a3cecc4b36b6eb7379e13f2a9bf2bc64e0efac077d932e390270401966223e2ae
|
7
|
+
data.tar.gz: c1dcf6d140117743baa62ba0715c99584bb80b8aa933f596424f242c2ffb6a31c7d25f0fdba65fed4b1bd93d63692502c7c63b36a1f2b793083b1972c5313304
|
data/CHANGELOG
CHANGED
@@ -1,3 +1,11 @@
|
|
1
|
+
=== 2.13.0 (2021-05-22)
|
2
|
+
|
3
|
+
* Make jwt_refresh expired access token support work when using rodauth.check_active_sessions before calling r.rodauth (renchap) (#165)
|
4
|
+
|
5
|
+
* Update default templates to add classes for Bootstrap 5 compatibility (janko) (#164)
|
6
|
+
|
7
|
+
* Add set_error_reason configuration method to allow applications more finer grained error handling (renchap, jeremyevans) (#162)
|
8
|
+
|
1
9
|
=== 2.12.0 (2021-04-22)
|
2
10
|
|
3
11
|
* Add configuration methods to active_sessions plugin to control the inserting and updating of rows (janko) (#159)
|
data/doc/base.rdoc
CHANGED
@@ -105,6 +105,7 @@ random_key :: A randomly generated string, used for creating tokens.
|
|
105
105
|
redirect(path) :: Redirect the request to the given path.
|
106
106
|
session_value :: The value for session_key in the current session.
|
107
107
|
set_error_flash(message) :: Set the current error flash to the given message.
|
108
|
+
set_error_reason(reason) :: You can override this method to customize handling of specific error types (does nothing by default). Each separate error type has a separate reason symbol, you can see the {list of error reason symbols}[rdoc-ref:doc/error_reasons.rdoc].
|
108
109
|
set_notice_flash(message) :: Set the next notice flash to the given message.
|
109
110
|
set_notice_now_flash(message) :: Set the current notice flash to the given message.
|
110
111
|
set_redirect_error_flash(message) :: Set the next error flash to the given message.
|
@@ -0,0 +1,73 @@
|
|
1
|
+
= Error Reasons
|
2
|
+
|
3
|
+
Rodauth allows for customizing response status codes and error
|
4
|
+
messages for each type of error. However, in some cases, the
|
5
|
+
response status code is too coarse for desired error handling
|
6
|
+
by the application (since many error types use the same status
|
7
|
+
code), and using the error message is too fragile since it may
|
8
|
+
be translated.
|
9
|
+
|
10
|
+
For this reason, Rodauth associates a fine grained reason for
|
11
|
+
each type of error. If an error occurs in Rodauth, it will
|
12
|
+
call the +set_error_reason+ method with a symbol for the
|
13
|
+
specific type of error. By default, this method does not do
|
14
|
+
anything, but you can use the +set_error_reason+ configuration
|
15
|
+
method to customize the error handling.
|
16
|
+
|
17
|
+
These are the currently supported error type symbols that
|
18
|
+
Rodauth will call +set_error_reason+ with:
|
19
|
+
|
20
|
+
* :account_locked_out
|
21
|
+
* :already_an_account_with_this_login
|
22
|
+
* :already_an_unverified_account_with_this_login
|
23
|
+
* :duplicate_webauthn_id
|
24
|
+
* :inactive_session
|
25
|
+
* :invalid_email_auth_key
|
26
|
+
* :invalid_otp_auth_code
|
27
|
+
* :invalid_otp_secret
|
28
|
+
* :invalid_password
|
29
|
+
* :invalid_password_pattern
|
30
|
+
* :invalid_phone_number
|
31
|
+
* :invalid_previous_password
|
32
|
+
* :invalid_recovery_code
|
33
|
+
* :invalid_remember_param
|
34
|
+
* :invalid_reset_password_key
|
35
|
+
* :invalid_sms_code
|
36
|
+
* :invalid_sms_confirmation_code
|
37
|
+
* :invalid_unlock_account_key
|
38
|
+
* :invalid_verify_account_key
|
39
|
+
* :invalid_verify_login_change_key
|
40
|
+
* :invalid_webauthn_auth_param
|
41
|
+
* :invalid_webauthn_remove_param
|
42
|
+
* :invalid_webauthn_setup_param
|
43
|
+
* :invalid_webauthn_sign_count
|
44
|
+
* :login_not_valid_email
|
45
|
+
* :login_required
|
46
|
+
* :login_too_long
|
47
|
+
* :login_too_short
|
48
|
+
* :logins_do_not_match
|
49
|
+
* :no_current_sms_code
|
50
|
+
* :no_matching_login
|
51
|
+
* :not_enough_character_groups_in_password
|
52
|
+
* :otp_locked_out
|
53
|
+
* :password_authentication_required
|
54
|
+
* :password_contains_null_byte
|
55
|
+
* :password_does_not_meet_requirements
|
56
|
+
* :password_in_dictionary
|
57
|
+
* :password_is_one_of_the_most_common
|
58
|
+
* :password_same_as_previous_password
|
59
|
+
* :password_too_short
|
60
|
+
* :passwords_do_not_match
|
61
|
+
* :same_as_current_login
|
62
|
+
* :same_as_existing_password
|
63
|
+
* :session_expired
|
64
|
+
* :sms_already_setup
|
65
|
+
* :sms_locked_out
|
66
|
+
* :sms_needs_confirmation
|
67
|
+
* :sms_not_setup
|
68
|
+
* :too_many_repeating_characters_in_password
|
69
|
+
* :two_factor_already_authenticated
|
70
|
+
* :two_factor_need_authentication
|
71
|
+
* :two_factor_not_setup
|
72
|
+
* :unverified_account
|
73
|
+
* :webauthn_not_setup
|
@@ -0,0 +1,19 @@
|
|
1
|
+
= New Features
|
2
|
+
|
3
|
+
* A set_error_reason configuration method has been added. This method
|
4
|
+
is called whenever a error occurs in Rodauth, with a symbol
|
5
|
+
describing the error. The default implementation of this method does
|
6
|
+
nothing, it has been added to make it easier for Rodauth users to
|
7
|
+
implement custom handling for specific error types. See the Rodauth
|
8
|
+
documentation for this method to see the list of symbols this method
|
9
|
+
can be called with.
|
10
|
+
|
11
|
+
= Other Improvements
|
12
|
+
|
13
|
+
* When using active_sessions and jwt_refresh together, and allowing for
|
14
|
+
expired JWTs when refreshing, you can now call
|
15
|
+
rodauth.check_active_session before r.rodauth. Previously, this
|
16
|
+
did not work, and you had to call rodauth.check_active_session
|
17
|
+
after r.rodauth.
|
18
|
+
|
19
|
+
* The default templates now also support Bootstrap 5.
|
@@ -57,6 +57,7 @@ module Rodauth
|
|
57
57
|
def no_longer_active_session
|
58
58
|
clear_session
|
59
59
|
set_redirect_error_status inactive_session_error_status
|
60
|
+
set_error_reason :inactive_session
|
60
61
|
set_redirect_error_flash active_sessions_error_flash
|
61
62
|
redirect active_sessions_redirect
|
62
63
|
end
|
@@ -176,4 +177,3 @@ module Rodauth
|
|
176
177
|
end
|
177
178
|
end
|
178
179
|
end
|
179
|
-
|
@@ -100,6 +100,7 @@ module Rodauth
|
|
100
100
|
:set_notice_flash,
|
101
101
|
:set_notice_now_flash,
|
102
102
|
:set_redirect_error_flash,
|
103
|
+
:set_error_reason,
|
103
104
|
:set_title,
|
104
105
|
:translate,
|
105
106
|
:update_session
|
@@ -294,6 +295,7 @@ module Rodauth
|
|
294
295
|
|
295
296
|
def login_required
|
296
297
|
set_redirect_error_status(login_required_error_status)
|
298
|
+
set_error_reason :login_required
|
297
299
|
set_redirect_error_flash require_login_error_flash
|
298
300
|
redirect require_login_redirect
|
299
301
|
end
|
@@ -539,6 +541,11 @@ module Rodauth
|
|
539
541
|
def set_response_error_status(status)
|
540
542
|
response.status = status
|
541
543
|
end
|
544
|
+
|
545
|
+
def set_response_error_reason_status(reason, status)
|
546
|
+
set_error_reason(reason)
|
547
|
+
set_response_error_status(status)
|
548
|
+
end
|
542
549
|
|
543
550
|
def throw_error(field, error)
|
544
551
|
set_field_error(field, error)
|
@@ -550,6 +557,14 @@ module Rodauth
|
|
550
557
|
throw_error(field, error)
|
551
558
|
end
|
552
559
|
|
560
|
+
def set_error_reason(reason)
|
561
|
+
end
|
562
|
+
|
563
|
+
def throw_error_reason(reason, status, field, message)
|
564
|
+
set_error_reason(reason)
|
565
|
+
throw_error_status(status, field, message)
|
566
|
+
end
|
567
|
+
|
553
568
|
def use_date_arithmetic?
|
554
569
|
set_deadline_values?
|
555
570
|
end
|
@@ -30,7 +30,7 @@ module Rodauth
|
|
30
30
|
r.post do
|
31
31
|
catch_error do
|
32
32
|
if change_login_requires_password? && !password_match?(param(password_param))
|
33
|
-
|
33
|
+
throw_error_reason(:invalid_password, invalid_password_error_status, password_param, invalid_password_message)
|
34
34
|
end
|
35
35
|
|
36
36
|
login = param(login_param)
|
@@ -39,7 +39,7 @@ module Rodauth
|
|
39
39
|
end
|
40
40
|
|
41
41
|
if require_login_confirmation? && login != param(login_confirm_param)
|
42
|
-
|
42
|
+
throw_error_reason(:logins_do_not_match, unmatched_field_error_status, login_param, logins_do_not_match_message)
|
43
43
|
end
|
44
44
|
|
45
45
|
transaction do
|
@@ -65,7 +65,7 @@ module Rodauth
|
|
65
65
|
|
66
66
|
def change_login(login)
|
67
67
|
if account_ds.get(login_column).downcase == login.downcase
|
68
|
-
|
68
|
+
set_login_requirement_error_message(:same_as_current_login, same_as_current_login_message)
|
69
69
|
return false
|
70
70
|
end
|
71
71
|
|
@@ -82,7 +82,7 @@ module Rodauth
|
|
82
82
|
updated = nil
|
83
83
|
raised = raises_uniqueness_violation?{updated = update_account({login_column=>login}, account_ds.exclude(login_column=>login)) == 1}
|
84
84
|
if raised
|
85
|
-
|
85
|
+
set_login_requirement_error_message(:already_an_account_with_this_login, already_an_account_with_this_login_message)
|
86
86
|
end
|
87
87
|
updated && !raised
|
88
88
|
end
|
@@ -33,16 +33,16 @@ module Rodauth
|
|
33
33
|
r.post do
|
34
34
|
catch_error do
|
35
35
|
if change_password_requires_password? && !password_match?(param(password_param))
|
36
|
-
|
36
|
+
throw_error_reason(:invalid_previous_password, invalid_password_error_status, password_param, invalid_previous_password_message)
|
37
37
|
end
|
38
38
|
|
39
39
|
password = param(new_password_param)
|
40
40
|
if require_password_confirmation? && password != param(password_confirm_param)
|
41
|
-
|
41
|
+
throw_error_reason(:passwords_do_not_match, unmatched_field_error_status, new_password_param, passwords_do_not_match_message)
|
42
42
|
end
|
43
43
|
|
44
44
|
if password_match?(password)
|
45
|
-
|
45
|
+
throw_error_reason(:same_as_existing_password, invalid_field_error_status, new_password_param, same_as_existing_password_message)
|
46
46
|
end
|
47
47
|
|
48
48
|
unless password_meets_requirements?(password)
|
@@ -35,7 +35,7 @@ module Rodauth
|
|
35
35
|
r.post do
|
36
36
|
catch_error do
|
37
37
|
if close_account_requires_password? && !password_match?(param(password_param))
|
38
|
-
|
38
|
+
throw_error_reason(:invalid_password, invalid_password_error_status, password_param, invalid_password_message)
|
39
39
|
end
|
40
40
|
|
41
41
|
transaction do
|
@@ -40,7 +40,7 @@ module Rodauth
|
|
40
40
|
set_notice_flash confirm_password_notice_flash
|
41
41
|
redirect confirm_password_redirect
|
42
42
|
else
|
43
|
-
|
43
|
+
set_response_error_reason_status(:invalid_password, invalid_password_error_status)
|
44
44
|
set_field_error(password_param, invalid_password_message)
|
45
45
|
set_error_flash confirm_password_error_flash
|
46
46
|
confirm_password_view
|
@@ -53,6 +53,7 @@ module Rodauth
|
|
53
53
|
|
54
54
|
if require_password_authentication? && has_password?
|
55
55
|
set_redirect_error_status(password_authentication_required_error_status)
|
56
|
+
set_error_reason :password_authentication_required
|
56
57
|
set_redirect_error_flash password_authentication_required_error_flash
|
57
58
|
set_session_value(confirm_password_redirect_session_key, request.fullpath)
|
58
59
|
redirect password_authentication_required_redirect
|
@@ -89,4 +90,3 @@ module Rodauth
|
|
89
90
|
end
|
90
91
|
end
|
91
92
|
end
|
92
|
-
|
@@ -43,7 +43,7 @@ module Rodauth
|
|
43
43
|
|
44
44
|
catch_error do
|
45
45
|
if require_login_confirmation? && login != param(login_confirm_param)
|
46
|
-
|
46
|
+
throw_error_reason(:logins_do_not_match, unmatched_field_error_status, login_param, logins_do_not_match_message)
|
47
47
|
end
|
48
48
|
|
49
49
|
unless login_meets_requirements?(login)
|
@@ -52,11 +52,11 @@ module Rodauth
|
|
52
52
|
|
53
53
|
if create_account_set_password?
|
54
54
|
if require_password_confirmation? && password != param(password_confirm_param)
|
55
|
-
|
55
|
+
throw_error_reason(:passwords_do_not_match, unmatched_field_error_status, password_param, passwords_do_not_match_message)
|
56
56
|
end
|
57
57
|
|
58
58
|
unless password_meets_requirements?(password)
|
59
|
-
|
59
|
+
throw_error_reason(:password_does_not_meet_requirements, invalid_field_error_status, password_param, password_does_not_meet_requirements_message)
|
60
60
|
end
|
61
61
|
|
62
62
|
if account_password_hash_column
|
@@ -100,7 +100,7 @@ module Rodauth
|
|
100
100
|
raised = raises_uniqueness_violation?{id = db[accounts_table].insert(account)}
|
101
101
|
|
102
102
|
if raised
|
103
|
-
|
103
|
+
set_login_requirement_error_message(:already_an_account_with_this_login, already_an_account_with_this_login_message)
|
104
104
|
end
|
105
105
|
|
106
106
|
if id
|
@@ -32,7 +32,7 @@ module Rodauth
|
|
32
32
|
|
33
33
|
def password_not_one_of_the_most_common?(password)
|
34
34
|
return true unless password_one_of_most_common?(password)
|
35
|
-
|
35
|
+
set_password_requirement_error_message(:password_is_one_of_the_most_common, password_is_one_of_the_most_common_message)
|
36
36
|
false
|
37
37
|
end
|
38
38
|
end
|
@@ -65,7 +65,7 @@ module Rodauth
|
|
65
65
|
end
|
66
66
|
|
67
67
|
return true unless match
|
68
|
-
|
68
|
+
set_password_requirement_error_message(:password_same_as_previous_password, password_same_as_previous_password_message)
|
69
69
|
false
|
70
70
|
end
|
71
71
|
|
@@ -58,6 +58,7 @@ module Rodauth
|
|
58
58
|
_email_auth_request
|
59
59
|
else
|
60
60
|
set_redirect_error_status(no_matching_login_error_status)
|
61
|
+
set_error_reason :no_matching_login
|
61
62
|
set_redirect_error_flash email_auth_request_error_flash
|
62
63
|
end
|
63
64
|
|
@@ -90,6 +91,7 @@ module Rodauth
|
|
90
91
|
key = session[email_auth_session_key] || param(email_auth_key_param)
|
91
92
|
unless account_from_email_auth_key(key)
|
92
93
|
set_redirect_error_status(invalid_key_error_status)
|
94
|
+
set_error_reason :invalid_email_auth_key
|
93
95
|
set_redirect_error_flash email_auth_error_flash
|
94
96
|
redirect email_auth_email_sent_redirect
|
95
97
|
end
|
@@ -32,6 +32,8 @@ module Rodauth
|
|
32
32
|
)
|
33
33
|
|
34
34
|
route do |r|
|
35
|
+
# For backward compatibility, unused in core Rodauth
|
36
|
+
# RODAUTH3: Remove
|
35
37
|
@jwt_refresh_route = true
|
36
38
|
before_jwt_refresh_route
|
37
39
|
|
@@ -135,7 +137,7 @@ module Rodauth
|
|
135
137
|
end
|
136
138
|
|
137
139
|
def _jwt_decode_opts
|
138
|
-
if allow_refresh_with_expired_jwt_access_token? &&
|
140
|
+
if allow_refresh_with_expired_jwt_access_token? && request.path == jwt_refresh_path
|
139
141
|
Hash[super].merge!(:verify_expiration=>false)
|
140
142
|
else
|
141
143
|
super
|
@@ -84,6 +84,7 @@ module Rodauth
|
|
84
84
|
set_notice_flash unlock_account_request_notice_flash
|
85
85
|
else
|
86
86
|
set_redirect_error_status(no_matching_login_error_status)
|
87
|
+
set_error_reason :no_matching_login
|
87
88
|
set_redirect_error_flash no_matching_login_message.to_s.capitalize
|
88
89
|
end
|
89
90
|
|
@@ -116,6 +117,7 @@ module Rodauth
|
|
116
117
|
key = session[unlock_account_session_key] || param(unlock_account_key_param)
|
117
118
|
unless account_from_unlock_key(key)
|
118
119
|
set_redirect_error_status invalid_key_error_status
|
120
|
+
set_error_reason :invalid_unlock_account_key
|
119
121
|
set_redirect_error_flash no_matching_unlock_account_key_error_flash
|
120
122
|
redirect unlock_account_request_redirect
|
121
123
|
end
|
@@ -134,7 +136,7 @@ module Rodauth
|
|
134
136
|
set_notice_flash unlock_account_notice_flash
|
135
137
|
redirect unlock_account_redirect
|
136
138
|
else
|
137
|
-
|
139
|
+
set_response_error_reason_status(:invalid_password, invalid_password_error_status)
|
138
140
|
set_field_error(password_param, invalid_password_message)
|
139
141
|
set_error_flash unlock_account_error_flash
|
140
142
|
unlock_account_view
|
@@ -271,7 +273,7 @@ module Rodauth
|
|
271
273
|
end
|
272
274
|
|
273
275
|
def show_lockout_page
|
274
|
-
|
276
|
+
set_response_error_reason_status(:account_locked_out, lockout_error_status)
|
275
277
|
set_error_flash login_lockout_error_flash
|
276
278
|
response.write unlock_account_request_view
|
277
279
|
request.halt
|
@@ -39,13 +39,13 @@ module Rodauth
|
|
39
39
|
|
40
40
|
catch_error do
|
41
41
|
unless account_from_login(param(login_param))
|
42
|
-
|
42
|
+
throw_error_reason(:no_matching_login, no_matching_login_error_status, login_param, no_matching_login_message)
|
43
43
|
end
|
44
44
|
|
45
45
|
before_login_attempt
|
46
46
|
|
47
47
|
unless open_account?
|
48
|
-
|
48
|
+
throw_error_reason(:unverified_account, unopen_account_error_status, login_param, unverified_account_message)
|
49
49
|
end
|
50
50
|
|
51
51
|
if use_multi_phase_login?
|
@@ -61,7 +61,7 @@ module Rodauth
|
|
61
61
|
|
62
62
|
unless password_match?(param(password_param))
|
63
63
|
after_login_failure
|
64
|
-
|
64
|
+
throw_error_reason(:invalid_password, login_error_status, password_param, invalid_password_message)
|
65
65
|
end
|
66
66
|
|
67
67
|
login('password')
|
@@ -81,6 +81,11 @@ module Rodauth
|
|
81
81
|
def password_too_short_message
|
82
82
|
"minimum #{password_minimum_length} characters"
|
83
83
|
end
|
84
|
+
|
85
|
+
def set_password_requirement_error_message(reason, message)
|
86
|
+
set_error_reason(reason)
|
87
|
+
@password_requirement_message = message
|
88
|
+
end
|
84
89
|
|
85
90
|
def login_does_not_meet_requirements_message
|
86
91
|
"invalid login#{", #{login_requirement_message}" if login_requirement_message}"
|
@@ -93,13 +98,18 @@ module Rodauth
|
|
93
98
|
def login_too_short_message
|
94
99
|
"minimum #{login_minimum_length} characters"
|
95
100
|
end
|
101
|
+
|
102
|
+
def set_login_requirement_error_message(reason, message)
|
103
|
+
set_error_reason(reason)
|
104
|
+
@login_requirement_message = message
|
105
|
+
end
|
96
106
|
|
97
107
|
def login_meets_length_requirements?(login)
|
98
108
|
if login_minimum_length > login.length
|
99
|
-
|
109
|
+
set_login_requirement_error_message(:login_too_short, login_too_short_message)
|
100
110
|
false
|
101
111
|
elsif login_maximum_length < login.length
|
102
|
-
|
112
|
+
set_login_requirement_error_message(:login_too_long, login_too_long_message)
|
103
113
|
false
|
104
114
|
else
|
105
115
|
true
|
@@ -109,7 +119,7 @@ module Rodauth
|
|
109
119
|
def login_meets_email_requirements?(login)
|
110
120
|
return true unless require_email_address_logins?
|
111
121
|
return true if login_valid_email?(login)
|
112
|
-
|
122
|
+
set_login_requirement_error_message(:login_not_valid_email, login_not_valid_email_message)
|
113
123
|
return false
|
114
124
|
end
|
115
125
|
|
@@ -119,13 +129,13 @@ module Rodauth
|
|
119
129
|
|
120
130
|
def password_meets_length_requirements?(password)
|
121
131
|
return true if password_minimum_length <= password.length
|
122
|
-
|
132
|
+
set_password_requirement_error_message(:password_too_short, password_too_short_message)
|
123
133
|
false
|
124
134
|
end
|
125
135
|
|
126
136
|
def password_does_not_contain_null_byte?(password)
|
127
137
|
return true unless password.include?("\0")
|
128
|
-
|
138
|
+
set_password_requirement_error_message(:password_contains_null_byte, contains_null_byte_message)
|
129
139
|
false
|
130
140
|
end
|
131
141
|
|
@@ -150,4 +160,3 @@ module Rodauth
|
|
150
160
|
end
|
151
161
|
end
|
152
162
|
end
|
153
|
-
|
data/lib/rodauth/features/otp.rb
CHANGED
@@ -103,7 +103,7 @@ module Rodauth
|
|
103
103
|
require_otp_setup
|
104
104
|
|
105
105
|
if otp_locked_out?
|
106
|
-
|
106
|
+
set_response_error_reason_status(:otp_locked_out, lockout_error_status)
|
107
107
|
set_redirect_error_flash otp_lockout_error_flash
|
108
108
|
redirect otp_lockout_redirect
|
109
109
|
end
|
@@ -122,7 +122,7 @@ module Rodauth
|
|
122
122
|
|
123
123
|
otp_record_authentication_failure
|
124
124
|
after_otp_authentication_failure
|
125
|
-
|
125
|
+
set_response_error_reason_status(:invalid_otp_auth_code, invalid_key_error_status)
|
126
126
|
set_field_error(otp_auth_param, otp_invalid_auth_code_message)
|
127
127
|
set_error_flash otp_auth_error_flash
|
128
128
|
otp_auth_view
|
@@ -149,7 +149,7 @@ module Rodauth
|
|
149
149
|
catch_error do
|
150
150
|
unless otp_valid_key?(secret)
|
151
151
|
otp_tmp_key(otp_new_secret)
|
152
|
-
|
152
|
+
throw_error_reason(:invalid_otp_secret, invalid_field_error_status, otp_setup_param, otp_invalid_secret_message)
|
153
153
|
end
|
154
154
|
|
155
155
|
if otp_keys_use_hmac?
|
@@ -159,11 +159,11 @@ module Rodauth
|
|
159
159
|
end
|
160
160
|
|
161
161
|
unless two_factor_password_match?(param(password_param))
|
162
|
-
|
162
|
+
throw_error_reason(:invalid_password, invalid_password_error_status, password_param, invalid_password_message)
|
163
163
|
end
|
164
164
|
|
165
165
|
unless otp_valid_code?(param(otp_auth_param))
|
166
|
-
|
166
|
+
throw_error_reason(:invalid_otp_auth_code, invalid_key_error_status, otp_auth_param, otp_invalid_auth_code_message)
|
167
167
|
end
|
168
168
|
|
169
169
|
transaction do
|
@@ -206,7 +206,7 @@ module Rodauth
|
|
206
206
|
redirect otp_disable_redirect
|
207
207
|
end
|
208
208
|
|
209
|
-
|
209
|
+
set_response_error_reason_status(:invalid_password, invalid_password_error_status)
|
210
210
|
set_field_error(password_param, invalid_password_message)
|
211
211
|
set_error_flash otp_disable_error_flash
|
212
212
|
otp_disable_view
|
@@ -226,6 +226,7 @@ module Rodauth
|
|
226
226
|
def require_otp_setup
|
227
227
|
unless otp_exists?
|
228
228
|
set_redirect_error_status(two_factor_not_setup_error_status)
|
229
|
+
set_error_reason :two_factor_not_setup
|
229
230
|
set_redirect_error_flash two_factor_not_setup_error_flash
|
230
231
|
redirect two_factor_need_setup_redirect
|
231
232
|
end
|
@@ -54,21 +54,21 @@ module Rodauth
|
|
54
54
|
def password_has_enough_character_groups?(password)
|
55
55
|
return true if password.length > password_max_length_for_groups_check
|
56
56
|
return true if password_character_groups.select{|re| password =~ re}.length >= password_min_groups
|
57
|
-
|
57
|
+
set_password_requirement_error_message(:not_enough_character_groups_in_password, password_not_enough_character_groups_message)
|
58
58
|
false
|
59
59
|
end
|
60
60
|
|
61
61
|
def password_has_no_invalid_pattern?(password)
|
62
62
|
return true unless password_invalid_pattern
|
63
63
|
return true if password !~ password_invalid_pattern
|
64
|
-
|
64
|
+
set_password_requirement_error_message(:invalid_password_pattern, password_invalid_pattern_message)
|
65
65
|
false
|
66
66
|
end
|
67
67
|
|
68
68
|
def password_not_too_many_repeating_characters?(password)
|
69
69
|
return true if password_max_repeating_characters < 2
|
70
70
|
return true if password !~ /(.)(\1){#{password_max_repeating_characters-1}}/
|
71
|
-
|
71
|
+
set_password_requirement_error_message(:too_many_repeating_characters_in_password, password_too_many_repeating_characters_message)
|
72
72
|
false
|
73
73
|
end
|
74
74
|
|
@@ -77,7 +77,7 @@ module Rodauth
|
|
77
77
|
return true unless password =~ /\A(?:\d*)([A-Za-z!@$+|][A-Za-z!@$+|0134578]+[A-Za-z!@$+|])(?:\d*)\z/
|
78
78
|
word = $1.downcase.tr('!@$+|0134578', 'iastloleastb')
|
79
79
|
return true if !dict.include?(word)
|
80
|
-
|
80
|
+
set_password_requirement_error_message(:password_in_dictionary, password_in_dictionary_message)
|
81
81
|
false
|
82
82
|
end
|
83
83
|
end
|
@@ -76,7 +76,7 @@ module Rodauth
|
|
76
76
|
two_factor_authenticate('recovery_code')
|
77
77
|
end
|
78
78
|
|
79
|
-
|
79
|
+
set_response_error_reason_status(:invalid_recovery_code, invalid_key_error_status)
|
80
80
|
set_field_error(recovery_codes_param, invalid_recovery_code_message)
|
81
81
|
set_error_flash invalid_recovery_code_error_flash
|
82
82
|
recovery_auth_view
|
@@ -119,7 +119,7 @@ module Rodauth
|
|
119
119
|
set_error_flash view_recovery_codes_error_flash
|
120
120
|
end
|
121
121
|
|
122
|
-
|
122
|
+
set_response_error_reason_status(:invalid_password, invalid_password_error_status)
|
123
123
|
set_field_error(password_param, invalid_password_message)
|
124
124
|
recovery_codes_view
|
125
125
|
end
|
@@ -74,7 +74,7 @@ module Rodauth
|
|
74
74
|
set_notice_flash remember_notice_flash
|
75
75
|
redirect remember_redirect
|
76
76
|
else
|
77
|
-
|
77
|
+
set_response_error_reason_status(:invalid_remember_param, invalid_field_error_status)
|
78
78
|
set_error_flash remember_error_flash
|
79
79
|
remember_view
|
80
80
|
end
|
@@ -68,11 +68,11 @@ module Rodauth
|
|
68
68
|
r.post do
|
69
69
|
catch_error do
|
70
70
|
unless account_from_login(param(login_param))
|
71
|
-
|
71
|
+
throw_error_reason(:no_matching_login, no_matching_login_error_status, login_param, no_matching_login_message)
|
72
72
|
end
|
73
73
|
|
74
74
|
unless open_account?
|
75
|
-
|
75
|
+
throw_error_reason(:unverified_account, unopen_account_error_status, login_param, unverified_account_message)
|
76
76
|
end
|
77
77
|
|
78
78
|
if reset_password_email_recently_sent?
|
@@ -123,6 +123,7 @@ module Rodauth
|
|
123
123
|
key = session[reset_password_session_key] || param(reset_password_key_param)
|
124
124
|
unless account_from_reset_password_key(key)
|
125
125
|
set_redirect_error_status(invalid_key_error_status)
|
126
|
+
set_error_reason :invalid_reset_password_key
|
126
127
|
set_redirect_error_flash reset_password_error_flash
|
127
128
|
redirect reset_password_email_sent_redirect
|
128
129
|
end
|
@@ -130,11 +131,11 @@ module Rodauth
|
|
130
131
|
password = param(password_param)
|
131
132
|
catch_error do
|
132
133
|
if password_match?(password)
|
133
|
-
|
134
|
+
throw_error_reason(:same_as_existing_password, invalid_field_error_status, password_param, same_as_existing_password_message)
|
134
135
|
end
|
135
136
|
|
136
137
|
if require_password_confirmation? && password != param(password_confirm_param)
|
137
|
-
|
138
|
+
throw_error_reason(:passwords_do_not_match, unmatched_field_error_status, password_param, passwords_do_not_match_message)
|
138
139
|
end
|
139
140
|
|
140
141
|
unless password_meets_requirements?(password)
|
@@ -146,7 +146,7 @@ module Rodauth
|
|
146
146
|
sms_set_code(nil)
|
147
147
|
end
|
148
148
|
|
149
|
-
|
149
|
+
set_response_error_reason_status(:no_current_sms_code, invalid_key_error_status)
|
150
150
|
set_redirect_error_flash no_current_sms_code_error_flash
|
151
151
|
redirect sms_request_redirect
|
152
152
|
end
|
@@ -169,7 +169,7 @@ module Rodauth
|
|
169
169
|
end
|
170
170
|
end
|
171
171
|
|
172
|
-
|
172
|
+
set_response_error_reason_status(:invalid_sms_code, invalid_key_error_status)
|
173
173
|
set_field_error(sms_code_param, sms_invalid_code_message)
|
174
174
|
set_error_flash sms_invalid_code_error_flash
|
175
175
|
sms_auth_view
|
@@ -186,6 +186,7 @@ module Rodauth
|
|
186
186
|
|
187
187
|
if sms_needs_confirmation?
|
188
188
|
set_redirect_error_status(sms_needs_confirmation_error_status)
|
189
|
+
set_error_reason :sms_needs_confirmation
|
189
190
|
set_redirect_error_flash sms_needs_confirmation_error_flash
|
190
191
|
redirect sms_needs_confirmation_redirect
|
191
192
|
end
|
@@ -199,13 +200,13 @@ module Rodauth
|
|
199
200
|
r.post do
|
200
201
|
catch_error do
|
201
202
|
unless two_factor_password_match?(param(password_param))
|
202
|
-
|
203
|
+
throw_error_reason(:invalid_password, invalid_password_error_status, password_param, invalid_password_message)
|
203
204
|
end
|
204
205
|
|
205
206
|
phone = sms_normalize_phone(param(sms_phone_param))
|
206
207
|
|
207
208
|
unless sms_valid_phone?(phone)
|
208
|
-
|
209
|
+
throw_error_reason(:invalid_phone_number, invalid_field_error_status, sms_phone_param, sms_invalid_phone_message)
|
209
210
|
end
|
210
211
|
|
211
212
|
transaction do
|
@@ -254,6 +255,7 @@ module Rodauth
|
|
254
255
|
|
255
256
|
sms_confirm_failure
|
256
257
|
set_redirect_error_status(invalid_key_error_status)
|
258
|
+
set_error_reason :invalid_sms_confirmation_code
|
257
259
|
set_redirect_error_flash sms_invalid_confirmation_code_error_flash
|
258
260
|
redirect sms_needs_setup_redirect
|
259
261
|
end
|
@@ -282,7 +284,7 @@ module Rodauth
|
|
282
284
|
redirect sms_disable_redirect
|
283
285
|
end
|
284
286
|
|
285
|
-
|
287
|
+
set_response_error_reason_status(:invalid_password, invalid_password_error_status)
|
286
288
|
set_field_error(password_param, invalid_password_message)
|
287
289
|
set_error_flash sms_disable_error_flash
|
288
290
|
sms_disable_view
|
@@ -302,6 +304,7 @@ module Rodauth
|
|
302
304
|
def require_sms_setup
|
303
305
|
unless sms_setup?
|
304
306
|
set_redirect_error_status(two_factor_not_setup_error_status)
|
307
|
+
set_error_reason :sms_not_setup
|
305
308
|
set_redirect_error_flash sms_not_setup_error_flash
|
306
309
|
redirect sms_needs_setup_redirect
|
307
310
|
end
|
@@ -310,6 +313,7 @@ module Rodauth
|
|
310
313
|
def require_sms_not_setup
|
311
314
|
if sms_setup?
|
312
315
|
set_redirect_error_status(sms_already_setup_error_status)
|
316
|
+
set_error_reason :sms_already_setup
|
313
317
|
set_redirect_error_flash sms_already_setup_error_flash
|
314
318
|
redirect sms_already_setup_redirect
|
315
319
|
end
|
@@ -320,6 +324,7 @@ module Rodauth
|
|
320
324
|
|
321
325
|
if sms_locked_out?
|
322
326
|
set_redirect_error_status(lockout_error_status)
|
327
|
+
set_error_reason :sms_locked_out
|
323
328
|
set_redirect_error_flash sms_lockout_error_flash
|
324
329
|
redirect sms_lockout_redirect
|
325
330
|
end
|
@@ -106,7 +106,7 @@ module Rodauth
|
|
106
106
|
redirect two_factor_disable_redirect
|
107
107
|
end
|
108
108
|
|
109
|
-
|
109
|
+
set_response_error_reason_status(:invalid_password, invalid_password_error_status)
|
110
110
|
set_field_error(password_param, invalid_password_message)
|
111
111
|
set_error_flash two_factor_disable_error_flash
|
112
112
|
two_factor_disable_view
|
@@ -144,6 +144,7 @@ module Rodauth
|
|
144
144
|
return if uses_two_factor_authentication?
|
145
145
|
|
146
146
|
set_redirect_error_status(two_factor_not_setup_error_status)
|
147
|
+
set_error_reason :two_factor_not_setup
|
147
148
|
set_redirect_error_flash two_factor_not_setup_error_flash
|
148
149
|
redirect two_factor_need_setup_redirect
|
149
150
|
end
|
@@ -151,6 +152,7 @@ module Rodauth
|
|
151
152
|
def require_two_factor_not_authenticated(auth_type = nil)
|
152
153
|
if two_factor_authenticated? || (auth_type && two_factor_login_type_match?(auth_type))
|
153
154
|
set_redirect_error_status(two_factor_already_authenticated_error_status)
|
155
|
+
set_error_reason :two_factor_already_authenticated
|
154
156
|
set_redirect_error_flash two_factor_already_authenticated_error_flash
|
155
157
|
redirect two_factor_already_authenticated_redirect
|
156
158
|
end
|
@@ -162,6 +164,7 @@ module Rodauth
|
|
162
164
|
set_session_value(two_factor_auth_redirect_session_key, request.fullpath)
|
163
165
|
end
|
164
166
|
set_redirect_error_status(two_factor_need_authentication_error_status)
|
167
|
+
set_error_reason :two_factor_need_authentication
|
165
168
|
set_redirect_error_flash two_factor_need_authentication_error_flash
|
166
169
|
redirect two_factor_auth_required_redirect
|
167
170
|
end
|
@@ -87,6 +87,7 @@ module Rodauth
|
|
87
87
|
set_notice_flash verify_account_email_sent_notice_flash
|
88
88
|
else
|
89
89
|
set_redirect_error_status(no_matching_login_error_status)
|
90
|
+
set_error_reason :no_matching_login
|
90
91
|
set_redirect_error_flash verify_account_resend_error_flash
|
91
92
|
end
|
92
93
|
|
@@ -120,6 +121,7 @@ module Rodauth
|
|
120
121
|
key = session[verify_account_session_key] || param(verify_account_key_param)
|
121
122
|
unless account_from_verify_account_key(key)
|
122
123
|
set_redirect_error_status(invalid_key_error_status)
|
124
|
+
set_error_reason :invalid_verify_account_key
|
123
125
|
set_redirect_error_flash verify_account_error_flash
|
124
126
|
redirect verify_account_redirect
|
125
127
|
end
|
@@ -129,7 +131,7 @@ module Rodauth
|
|
129
131
|
password = param(password_param)
|
130
132
|
|
131
133
|
if require_password_confirmation? && password != param(password_confirm_param)
|
132
|
-
|
134
|
+
throw_error_reason(:passwords_do_not_match, unmatched_field_error_status, password_param, passwords_do_not_match_message)
|
133
135
|
end
|
134
136
|
|
135
137
|
unless password_meets_requirements?(password)
|
@@ -192,6 +194,7 @@ module Rodauth
|
|
192
194
|
def new_account(login)
|
193
195
|
if account_from_login(login) && allow_resending_verify_account_email?
|
194
196
|
set_redirect_error_status(unopen_account_error_status)
|
197
|
+
set_error_reason :already_an_unverified_account_with_this_login
|
195
198
|
set_error_flash attempt_to_create_unverified_account_error_flash
|
196
199
|
response.write resend_verify_account_view
|
197
200
|
request.halt
|
@@ -269,6 +272,7 @@ module Rodauth
|
|
269
272
|
def before_login_attempt
|
270
273
|
unless open_account?
|
271
274
|
set_redirect_error_status(unopen_account_error_status)
|
275
|
+
set_error_reason :unverified_account
|
272
276
|
set_error_flash attempt_to_login_to_unverified_account_error_flash
|
273
277
|
response.write resend_verify_account_view
|
274
278
|
request.halt
|
@@ -74,6 +74,7 @@ module Rodauth
|
|
74
74
|
key = session[verify_login_change_session_key] || param(verify_login_change_key_param)
|
75
75
|
unless account_from_verify_login_change_key(key)
|
76
76
|
set_redirect_error_status(invalid_key_error_status)
|
77
|
+
set_error_reason :invalid_verify_login_change_key
|
77
78
|
set_redirect_error_flash verify_login_change_error_flash
|
78
79
|
redirect verify_login_change_redirect
|
79
80
|
end
|
@@ -82,6 +83,7 @@ module Rodauth
|
|
82
83
|
before_verify_login_change
|
83
84
|
unless verify_login_change
|
84
85
|
set_redirect_error_status(invalid_key_error_status)
|
86
|
+
set_error_reason :already_an_account_with_this_login
|
85
87
|
set_redirect_error_flash verify_login_change_duplicate_account_error_flash
|
86
88
|
redirect verify_login_change_duplicate_account_redirect
|
87
89
|
end
|
@@ -151,7 +153,7 @@ module Rodauth
|
|
151
153
|
|
152
154
|
def update_login(login)
|
153
155
|
if _account_from_login(login)
|
154
|
-
|
156
|
+
set_login_requirement_error_message(:already_an_account_with_this_login, already_an_account_with_this_login_message)
|
155
157
|
return false
|
156
158
|
end
|
157
159
|
|
@@ -213,4 +215,3 @@ module Rodauth
|
|
213
215
|
end
|
214
216
|
end
|
215
217
|
end
|
216
|
-
|
@@ -182,7 +182,7 @@ module Rodauth
|
|
182
182
|
end
|
183
183
|
|
184
184
|
if throw_error
|
185
|
-
|
185
|
+
throw_error_reason(:duplicate_webauthn_id, invalid_field_error_status, webauthn_setup_param, webauthn_duplicate_webauthn_id_message)
|
186
186
|
end
|
187
187
|
|
188
188
|
set_notice_flash webauthn_setup_notice_flash
|
@@ -207,17 +207,17 @@ module Rodauth
|
|
207
207
|
r.post do
|
208
208
|
catch_error do
|
209
209
|
unless webauthn_id = param_or_nil(webauthn_remove_param)
|
210
|
-
|
210
|
+
throw_error_reason(:invalid_webauthn_remove_param, invalid_field_error_status, webauthn_remove_param, webauthn_invalid_remove_param_message)
|
211
211
|
end
|
212
212
|
|
213
213
|
unless two_factor_password_match?(param(password_param))
|
214
|
-
|
214
|
+
throw_error_reason(:invalid_password, invalid_password_error_status, password_param, invalid_password_message)
|
215
215
|
end
|
216
216
|
|
217
217
|
transaction do
|
218
218
|
before_webauthn_remove
|
219
219
|
unless remove_webauthn_key(webauthn_id)
|
220
|
-
|
220
|
+
throw_error_reason(:invalid_webauthn_remove_param, invalid_field_error_status, webauthn_remove_param, webauthn_invalid_remove_param_message)
|
221
221
|
end
|
222
222
|
if authenticated_webauthn_id == webauthn_id && two_factor_login_type_match?('webauthn')
|
223
223
|
webauthn_remove_authenticated_session
|
@@ -342,7 +342,7 @@ module Rodauth
|
|
342
342
|
end
|
343
343
|
|
344
344
|
def handle_webauthn_sign_count_verification_error
|
345
|
-
|
345
|
+
throw_error_reason(:invalid_webauthn_sign_count, invalid_field_error_status, webauthn_auth_param, webauthn_invalid_sign_count_message)
|
346
346
|
end
|
347
347
|
|
348
348
|
def add_webauthn_credential(webauthn_credential)
|
@@ -392,6 +392,7 @@ module Rodauth
|
|
392
392
|
def require_webauthn_setup
|
393
393
|
unless webauthn_setup?
|
394
394
|
set_redirect_error_status(webauthn_not_setup_error_status)
|
395
|
+
set_error_reason :webauthn_not_setup
|
395
396
|
set_redirect_error_flash webauthn_not_setup_error_flash
|
396
397
|
redirect two_factor_need_setup_redirect
|
397
398
|
end
|
@@ -450,23 +451,23 @@ module Rodauth
|
|
450
451
|
begin
|
451
452
|
auth_data = JSON.parse(auth_data)
|
452
453
|
rescue
|
453
|
-
|
454
|
+
throw_error_reason(:invalid_webauthn_auth_param, invalid_field_error_status, webauthn_auth_param, webauthn_invalid_auth_param_message)
|
454
455
|
end
|
455
456
|
when Hash
|
456
457
|
# nothing
|
457
458
|
else
|
458
|
-
|
459
|
+
throw_error_reason(:invalid_webauthn_auth_param, invalid_field_error_status, webauthn_auth_param, webauthn_invalid_auth_param_message)
|
459
460
|
end
|
460
461
|
|
461
462
|
begin
|
462
463
|
webauthn_credential = WebAuthn::Credential.from_get(auth_data)
|
463
464
|
unless valid_webauthn_credential_auth?(webauthn_credential)
|
464
|
-
|
465
|
+
throw_error_reason(:invalid_webauthn_auth_param, invalid_key_error_status, webauthn_auth_param, webauthn_invalid_auth_param_message)
|
465
466
|
end
|
466
467
|
rescue WebAuthn::SignCountVerificationError
|
467
468
|
handle_webauthn_sign_count_verification_error
|
468
469
|
rescue WebAuthn::Error, RuntimeError, NoMethodError
|
469
|
-
|
470
|
+
throw_error_reason(:invalid_webauthn_auth_param, invalid_field_error_status, webauthn_auth_param, webauthn_invalid_auth_param_message)
|
470
471
|
end
|
471
472
|
|
472
473
|
webauthn_credential
|
@@ -478,25 +479,25 @@ module Rodauth
|
|
478
479
|
begin
|
479
480
|
setup_data = JSON.parse(setup_data)
|
480
481
|
rescue
|
481
|
-
|
482
|
+
throw_error_reason(:invalid_webauthn_setup_param, invalid_field_error_status, webauthn_setup_param, webauthn_invalid_setup_param_message)
|
482
483
|
end
|
483
484
|
when Hash
|
484
485
|
# nothing
|
485
486
|
else
|
486
|
-
|
487
|
+
throw_error_reason(:invalid_webauthn_setup_param, invalid_field_error_status, webauthn_setup_param, webauthn_invalid_setup_param_message)
|
487
488
|
end
|
488
489
|
|
489
490
|
unless two_factor_password_match?(param(password_param))
|
490
|
-
|
491
|
+
throw_error_reason(:invalid_password, invalid_password_error_status, password_param, invalid_password_message)
|
491
492
|
end
|
492
493
|
|
493
494
|
begin
|
494
495
|
webauthn_credential = WebAuthn::Credential.from_create(setup_data)
|
495
496
|
unless valid_new_webauthn_credential?(webauthn_credential)
|
496
|
-
|
497
|
+
throw_error_reason(:invalid_webauthn_setup_param, invalid_field_error_status, webauthn_setup_param, webauthn_invalid_setup_param_message)
|
497
498
|
end
|
498
499
|
rescue WebAuthn::Error, RuntimeError, NoMethodError
|
499
|
-
|
500
|
+
throw_error_reason(:invalid_webauthn_setup_param, invalid_field_error_status, webauthn_setup_param, webauthn_invalid_setup_param_message)
|
500
501
|
end
|
501
502
|
|
502
503
|
webauthn_credential
|
@@ -17,7 +17,7 @@ module Rodauth
|
|
17
17
|
r.post do
|
18
18
|
catch_error do
|
19
19
|
unless account_from_login(param(login_param)) && 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
|
|
23
23
|
webauthn_credential = webauthn_auth_credential_from_form_submission
|
data/lib/rodauth/version.rb
CHANGED
data/templates/button.str
CHANGED
@@ -2,8 +2,8 @@
|
|
2
2
|
#{rodauth.change_password_additional_form_tags}
|
3
3
|
#{rodauth.csrf_tag}
|
4
4
|
#{rodauth.render('password-field') if rodauth.change_password_requires_password?}
|
5
|
-
<div class="form-group">
|
6
|
-
<label for="new-password">#{rodauth.new_password_label}#{rodauth.input_field_label_suffix}</label>
|
5
|
+
<div class="form-group mb-3">
|
6
|
+
<label for="new-password" class="form-label">#{rodauth.new_password_label}#{rodauth.input_field_label_suffix}</label>
|
7
7
|
#{rodauth.input_field_string(rodauth.new_password_param, 'new-password', :type => 'password', :autocomplete=>"new-password")}
|
8
8
|
</div>
|
9
9
|
#{rodauth.render('password-confirm-field') if rodauth.require_password_confirmation?}
|
@@ -1,4 +1,4 @@
|
|
1
|
-
<div class="form-group">
|
1
|
+
<div class="form-group mb-3">
|
2
2
|
<div class="form-check checkbox">
|
3
3
|
<input type="checkbox" name="#{rodauth.global_logout_param}" class="form-check-input" id="global-logout" value="t"/>
|
4
4
|
<label class="rodauth-global-logout-label form-check-label" for="global-logout">#{rodauth.global_logout_label}</label>
|
@@ -1,4 +1,4 @@
|
|
1
|
-
<div class="form-group">
|
2
|
-
<label for="login-confirm">#{rodauth.login_confirm_label}#{rodauth.input_field_label_suffix}</label>
|
1
|
+
<div class="form-group mb-3">
|
2
|
+
<label for="login-confirm" class="form-label">#{rodauth.login_confirm_label}#{rodauth.input_field_label_suffix}</label>
|
3
3
|
#{rodauth.input_field_string(rodauth.login_confirm_param, 'login-confirm', :type=>rodauth.login_input_type, :autocomplete=>rodauth.login_uses_email? ? "email" : "on")}
|
4
4
|
</div>
|
data/templates/login-display.str
CHANGED
@@ -1,5 +1,5 @@
|
|
1
|
-
<div class="form-group">
|
1
|
+
<div class="form-group mb-3">
|
2
2
|
#{rodauth.login_hidden_field}
|
3
|
-
<label for="login">#{rodauth.login_label}</label>
|
3
|
+
<label for="login" class="form-label">#{rodauth.login_label}</label>
|
4
4
|
<div class="form-control-plaintext form-control-static">#{h rodauth.param(rodauth.login_param)}</div>
|
5
5
|
</div>
|
data/templates/login-field.str
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
<div class="form-group">
|
2
|
-
<label for="login">#{rodauth.login_label}#{rodauth.input_field_label_suffix}</label>
|
1
|
+
<div class="form-group mb-3">
|
2
|
+
<label for="login" class="form-label">#{rodauth.login_label}#{rodauth.input_field_label_suffix}</label>
|
3
3
|
#{rodauth.input_field_string(rodauth.login_param, 'login', :type=>rodauth.login_input_type, :autocomplete=>rodauth.login_uses_email? ? "email" : "on")}
|
4
4
|
</div>
|
@@ -1,5 +1,5 @@
|
|
1
|
-
<div class="form-group">
|
2
|
-
<label for="otp-auth-code">#{rodauth.otp_auth_label}#{rodauth.input_field_label_suffix}</label>
|
1
|
+
<div class="form-group mb-3">
|
2
|
+
<label for="otp-auth-code" class="form-label">#{rodauth.otp_auth_label}#{rodauth.input_field_label_suffix}</label>
|
3
3
|
<div class="row">
|
4
4
|
<div class="col-sm-3">
|
5
5
|
#{rodauth.input_field_string(rodauth.otp_auth_param, 'otp-auth-code', :value=>'', :autocomplete=>"off", :inputmode=>'numeric')}
|
data/templates/otp-setup.str
CHANGED
@@ -3,14 +3,14 @@
|
|
3
3
|
<input type="hidden" id="otp-key" name="#{rodauth.otp_setup_param}" value="#{rodauth.otp_user_key}" />
|
4
4
|
#{"<input type=\"hidden\" id=\"otp-hmac-secret\" name=\"#{rodauth.otp_setup_raw_param}\" value=\"#{rodauth.otp_key}\" />" if rodauth.otp_keys_use_hmac?}
|
5
5
|
#{rodauth.csrf_tag}
|
6
|
-
<div class="form-group">
|
6
|
+
<div class="form-group mb-3">
|
7
7
|
<p>#{rodauth.otp_secret_label}: #{rodauth.otp_user_key}</p>
|
8
8
|
<p>#{rodauth.otp_provisioning_uri_label}: #{rodauth.otp_provisioning_uri}</p>
|
9
9
|
</div>
|
10
10
|
|
11
11
|
<div class="row">
|
12
12
|
<div class="col-lg-6 col-lg">
|
13
|
-
<div class="form-group">
|
13
|
+
<div class="form-group mb-3">
|
14
14
|
<p>#{rodauth.otp_qr_code}</p>
|
15
15
|
</div>
|
16
16
|
</div>
|
@@ -1,4 +1,4 @@
|
|
1
|
-
<div class="form-group">
|
2
|
-
<label for="password-confirm">#{rodauth.password_confirm_label}#{rodauth.input_field_label_suffix}</label>
|
1
|
+
<div class="form-group mb-3">
|
2
|
+
<label for="password-confirm" class="form-label">#{rodauth.password_confirm_label}#{rodauth.input_field_label_suffix}</label>
|
3
3
|
#{rodauth.input_field_string(rodauth.password_confirm_param, 'password-confirm', :type => 'password', :autocomplete=>'new-password')}
|
4
4
|
</div>
|
@@ -1,4 +1,4 @@
|
|
1
|
-
<div class="form-group">
|
2
|
-
<label for="password">#{rodauth.password_label}#{rodauth.input_field_label_suffix}</label>
|
1
|
+
<div class="form-group mb-3">
|
2
|
+
<label for="password" class="form-label">#{rodauth.password_label}#{rodauth.input_field_label_suffix}</label>
|
3
3
|
#{rodauth.input_field_string(rodauth.password_param, 'password', :type => 'password', :autocomplete=>rodauth.password_field_autocomplete_value)}
|
4
4
|
</div>
|
data/templates/recovery-auth.str
CHANGED
@@ -1,8 +1,8 @@
|
|
1
1
|
<form method="post" class="rodauth" role="form" id="recovery-auth-form">
|
2
2
|
#{rodauth.recovery_auth_additional_form_tags}
|
3
3
|
#{rodauth.csrf_tag}
|
4
|
-
<div class="form-group">
|
5
|
-
<label for="recovery-code">#{rodauth.recovery_codes_label}#{rodauth.input_field_label_suffix}</label>
|
4
|
+
<div class="form-group mb-3">
|
5
|
+
<label for="recovery-code" class="form-label">#{rodauth.recovery_codes_label}#{rodauth.input_field_label_suffix}</label>
|
6
6
|
#{rodauth.input_field_string(rodauth.recovery_codes_param, 'recovery-code', :value => '', :autocomplete=>'off')}
|
7
7
|
</div>
|
8
8
|
#{rodauth.button(rodauth.recovery_auth_button)}
|
data/templates/remember.str
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
<form method="post" class="rodauth" role="form" id="remember-form">
|
2
2
|
#{rodauth.remember_additional_form_tags}
|
3
3
|
#{rodauth.csrf_tag}
|
4
|
-
<fieldset class="form-group">
|
4
|
+
<fieldset class="form-group mb-3">
|
5
5
|
<div class="form-check radio">
|
6
6
|
<input type="radio" name="#{rodauth.remember_param}" id="remember-remember" value="#{h rodauth.remember_remember_param_value}" class="form-check-input"/>
|
7
7
|
<label class="form-check-label" for="remember-remember">#{rodauth.remember_remember_label}</label>
|
@@ -1,5 +1,5 @@
|
|
1
|
-
<div class="form-group">
|
2
|
-
<label for="sms-code">#{rodauth.sms_code_label}#{rodauth.input_field_label_suffix}</label>
|
1
|
+
<div class="form-group mb-3">
|
2
|
+
<label for="sms-code" class="form-label">#{rodauth.sms_code_label}#{rodauth.input_field_label_suffix}</label>
|
3
3
|
<div class="row">
|
4
4
|
<div class="col-sm-3">
|
5
5
|
#{rodauth.input_field_string(rodauth.sms_code_param, 'sms-code', :value => '', :autocomplete=>'one-time-code', :inputmode=>'numeric')}
|
data/templates/sms-setup.str
CHANGED
@@ -2,8 +2,8 @@
|
|
2
2
|
#{rodauth.sms_setup_additional_form_tags}
|
3
3
|
#{rodauth.csrf_tag}
|
4
4
|
#{rodauth.render('password-field') if rodauth.two_factor_modifications_require_password?}
|
5
|
-
<div class="form-group">
|
6
|
-
<label for="sms-phone">#{rodauth.sms_phone_label}#{rodauth.input_field_label_suffix}</label>
|
5
|
+
<div class="form-group mb-3">
|
6
|
+
<label for="sms-phone" class="form-label">#{rodauth.sms_phone_label}#{rodauth.input_field_label_suffix}</label>
|
7
7
|
<div class="row">
|
8
8
|
<div class="col-sm-3">
|
9
9
|
#{rodauth.input_field_string(rodauth.sms_phone_param, 'sms-phone', :type=>rodauth.sms_phone_input_type, :autocomplete=>'tel')}
|
@@ -2,7 +2,7 @@
|
|
2
2
|
#{rodauth.webauthn_remove_additional_form_tags}
|
3
3
|
#{rodauth.csrf_tag}
|
4
4
|
#{rodauth.render('password-field') if rodauth.two_factor_modifications_require_password?}
|
5
|
-
<fieldset class="form-group">
|
5
|
+
<fieldset class="form-group mb-3">
|
6
6
|
#{(usage = rodauth.account_webauthn_usage; last_id = usage.keys.last; usage;).map do |id, last_use|
|
7
7
|
input = rodauth.input_field_string(rodauth.webauthn_remove_param, "webauthn-remove-#{h id}", :type=>'radio', :class=>"form-check-input", :skip_error_message=>true, :value=>id, :required=>false)
|
8
8
|
label = "<label class=\"rodauth-webauthn-id form-check-label\" for=\"webauthn-remove-#{h id}\">Last Use: #{last_use}</label>"
|
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.13.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: 2021-
|
11
|
+
date: 2021-05-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: sequel
|
@@ -266,6 +266,7 @@ extra_rdoc_files:
|
|
266
266
|
- doc/disallow_password_reuse.rdoc
|
267
267
|
- doc/email_auth.rdoc
|
268
268
|
- doc/email_base.rdoc
|
269
|
+
- doc/error_reasons.rdoc
|
269
270
|
- doc/http_basic_auth.rdoc
|
270
271
|
- doc/json.rdoc
|
271
272
|
- doc/jwt.rdoc
|
@@ -323,6 +324,7 @@ extra_rdoc_files:
|
|
323
324
|
- doc/release_notes/2.10.0.txt
|
324
325
|
- doc/release_notes/2.11.0.txt
|
325
326
|
- doc/release_notes/2.12.0.txt
|
327
|
+
- doc/release_notes/2.13.0.txt
|
326
328
|
- doc/release_notes/2.2.0.txt
|
327
329
|
- doc/release_notes/2.3.0.txt
|
328
330
|
- doc/release_notes/2.4.0.txt
|
@@ -351,6 +353,7 @@ files:
|
|
351
353
|
- doc/disallow_password_reuse.rdoc
|
352
354
|
- doc/email_auth.rdoc
|
353
355
|
- doc/email_base.rdoc
|
356
|
+
- doc/error_reasons.rdoc
|
354
357
|
- doc/guides/admin_activation.rdoc
|
355
358
|
- doc/guides/already_authenticated.rdoc
|
356
359
|
- doc/guides/alternative_login.rdoc
|
@@ -417,6 +420,7 @@ files:
|
|
417
420
|
- doc/release_notes/2.10.0.txt
|
418
421
|
- doc/release_notes/2.11.0.txt
|
419
422
|
- doc/release_notes/2.12.0.txt
|
423
|
+
- doc/release_notes/2.13.0.txt
|
420
424
|
- doc/release_notes/2.2.0.txt
|
421
425
|
- doc/release_notes/2.3.0.txt
|
422
426
|
- doc/release_notes/2.4.0.txt
|