rodauth 2.12.0 → 2.13.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 +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
|