rodauth 1.23.0 → 2.4.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 +184 -0
- data/MIT-LICENSE +1 -1
- data/README.rdoc +221 -79
- data/doc/account_expiration.rdoc +12 -26
- data/doc/active_sessions.rdoc +49 -0
- data/doc/audit_logging.rdoc +44 -0
- data/doc/base.rdoc +76 -128
- data/doc/change_login.rdoc +7 -14
- data/doc/change_password.rdoc +9 -13
- data/doc/change_password_notify.rdoc +2 -2
- data/doc/close_account.rdoc +9 -16
- data/doc/confirm_password.rdoc +12 -5
- data/doc/create_account.rdoc +11 -22
- data/doc/disallow_password_reuse.rdoc +6 -13
- data/doc/email_auth.rdoc +15 -14
- data/doc/email_base.rdoc +5 -15
- data/doc/guides/admin_activation.rdoc +46 -0
- data/doc/guides/already_authenticated.rdoc +10 -0
- data/doc/guides/alternative_login.rdoc +46 -0
- data/doc/guides/create_account_programmatically.rdoc +38 -0
- data/doc/guides/delay_password.rdoc +25 -0
- data/doc/guides/email_only.rdoc +16 -0
- data/doc/guides/i18n.rdoc +26 -0
- data/doc/{internals.rdoc → guides/internals.rdoc} +0 -0
- data/doc/guides/links.rdoc +12 -0
- data/doc/guides/login_return.rdoc +37 -0
- data/doc/guides/password_column.rdoc +25 -0
- data/doc/guides/password_confirmation.rdoc +37 -0
- data/doc/guides/password_requirements.rdoc +30 -0
- data/doc/guides/paths.rdoc +36 -0
- data/doc/guides/query_params.rdoc +9 -0
- data/doc/guides/redirects.rdoc +17 -0
- data/doc/guides/registration_field.rdoc +68 -0
- data/doc/guides/require_mfa.rdoc +30 -0
- data/doc/guides/reset_password_autologin.rdoc +21 -0
- data/doc/guides/status_column.rdoc +28 -0
- data/doc/guides/totp_or_recovery.rdoc +16 -0
- data/doc/http_basic_auth.rdoc +10 -1
- data/doc/jwt.rdoc +22 -22
- data/doc/jwt_cors.rdoc +2 -3
- data/doc/jwt_refresh.rdoc +23 -8
- data/doc/lockout.rdoc +17 -15
- data/doc/login.rdoc +17 -2
- data/doc/login_password_requirements_base.rdoc +18 -37
- data/doc/logout.rdoc +2 -2
- data/doc/otp.rdoc +25 -19
- data/doc/password_complexity.rdoc +10 -26
- data/doc/password_expiration.rdoc +11 -25
- data/doc/password_grace_period.rdoc +16 -2
- data/doc/password_pepper.rdoc +44 -0
- data/doc/recovery_codes.rdoc +18 -12
- data/doc/release_notes/2.0.0.txt +361 -0
- data/doc/release_notes/2.1.0.txt +31 -0
- data/doc/release_notes/2.2.0.txt +39 -0
- data/doc/release_notes/2.3.0.txt +37 -0
- data/doc/release_notes/2.4.0.txt +22 -0
- data/doc/remember.rdoc +40 -64
- data/doc/reset_password.rdoc +12 -9
- data/doc/session_expiration.rdoc +1 -0
- data/doc/single_session.rdoc +16 -25
- data/doc/sms_codes.rdoc +24 -14
- data/doc/two_factor_base.rdoc +60 -22
- data/doc/verify_account.rdoc +14 -12
- data/doc/verify_account_grace_period.rdoc +6 -2
- data/doc/verify_login_change.rdoc +9 -8
- data/doc/webauthn.rdoc +115 -0
- data/doc/webauthn_login.rdoc +15 -0
- data/doc/webauthn_verify_account.rdoc +9 -0
- data/javascript/webauthn_auth.js +45 -0
- data/javascript/webauthn_setup.js +35 -0
- data/lib/roda/plugins/rodauth.rb +1 -1
- data/lib/rodauth.rb +33 -28
- data/lib/rodauth/features/account_expiration.rb +5 -5
- data/lib/rodauth/features/active_sessions.rb +158 -0
- data/lib/rodauth/features/audit_logging.rb +98 -0
- data/lib/rodauth/features/base.rb +152 -49
- data/lib/rodauth/features/change_password_notify.rb +1 -1
- data/lib/rodauth/features/close_account.rb +8 -6
- data/lib/rodauth/features/confirm_password.rb +40 -2
- data/lib/rodauth/features/create_account.rb +8 -13
- data/lib/rodauth/features/disallow_common_passwords.rb +1 -1
- data/lib/rodauth/features/disallow_password_reuse.rb +5 -3
- data/lib/rodauth/features/email_auth.rb +30 -28
- data/lib/rodauth/features/email_base.rb +3 -3
- data/lib/rodauth/features/http_basic_auth.rb +55 -35
- data/lib/rodauth/features/jwt.rb +63 -16
- data/lib/rodauth/features/jwt_cors.rb +15 -15
- data/lib/rodauth/features/jwt_refresh.rb +42 -13
- data/lib/rodauth/features/lockout.rb +11 -13
- data/lib/rodauth/features/login.rb +58 -13
- data/lib/rodauth/features/login_password_requirements_base.rb +13 -8
- data/lib/rodauth/features/otp.rb +76 -82
- data/lib/rodauth/features/password_complexity.rb +8 -13
- data/lib/rodauth/features/password_expiration.rb +1 -1
- data/lib/rodauth/features/password_grace_period.rb +17 -10
- data/lib/rodauth/features/password_pepper.rb +45 -0
- data/lib/rodauth/features/recovery_codes.rb +47 -51
- data/lib/rodauth/features/remember.rb +13 -27
- data/lib/rodauth/features/reset_password.rb +25 -25
- data/lib/rodauth/features/session_expiration.rb +7 -10
- data/lib/rodauth/features/single_session.rb +8 -6
- data/lib/rodauth/features/sms_codes.rb +58 -68
- data/lib/rodauth/features/two_factor_base.rb +134 -30
- data/lib/rodauth/features/verify_account.rb +28 -20
- data/lib/rodauth/features/verify_account_grace_period.rb +18 -9
- data/lib/rodauth/features/verify_login_change.rb +11 -10
- data/lib/rodauth/features/webauthn.rb +505 -0
- data/lib/rodauth/features/webauthn_login.rb +70 -0
- data/lib/rodauth/features/webauthn_verify_account.rb +46 -0
- data/lib/rodauth/migrations.rb +16 -5
- data/lib/rodauth/version.rb +2 -2
- data/templates/button.str +1 -3
- data/templates/change-login.str +1 -2
- data/templates/change-password.str +3 -5
- data/templates/close-account.str +2 -2
- data/templates/confirm-password.str +1 -1
- data/templates/create-account.str +1 -1
- data/templates/email-auth-request-form.str +1 -2
- data/templates/email-auth.str +1 -1
- data/templates/global-logout-field.str +6 -0
- data/templates/login-confirm-field.str +2 -4
- data/templates/login-display.str +3 -2
- data/templates/login-field.str +2 -4
- data/templates/login-form-footer.str +6 -0
- data/templates/login-form.str +7 -0
- data/templates/login.str +1 -9
- data/templates/logout.str +1 -1
- data/templates/multi-phase-login.str +3 -0
- data/templates/otp-auth-code-field.str +5 -3
- data/templates/otp-auth.str +1 -1
- data/templates/otp-disable.str +1 -1
- data/templates/otp-setup.str +3 -3
- data/templates/password-confirm-field.str +2 -4
- data/templates/password-field.str +2 -4
- data/templates/recovery-auth.str +3 -6
- data/templates/recovery-codes.str +1 -1
- data/templates/remember.str +15 -20
- data/templates/reset-password-request.str +2 -2
- data/templates/reset-password.str +1 -2
- data/templates/sms-auth.str +1 -1
- data/templates/sms-code-field.str +5 -3
- data/templates/sms-confirm.str +1 -2
- data/templates/sms-disable.str +1 -2
- data/templates/sms-request.str +1 -1
- data/templates/sms-setup.str +6 -4
- data/templates/two-factor-auth.str +5 -0
- data/templates/two-factor-disable.str +6 -0
- data/templates/two-factor-manage.str +16 -0
- data/templates/unlock-account-request.str +2 -2
- data/templates/unlock-account.str +1 -1
- data/templates/verify-account-resend.str +1 -1
- data/templates/verify-account.str +1 -2
- data/templates/verify-login-change.str +1 -1
- data/templates/webauthn-auth.str +11 -0
- data/templates/webauthn-remove.str +14 -0
- data/templates/webauthn-setup.str +12 -0
- metadata +96 -13
- data/doc/verify_change_login.rdoc +0 -11
- data/lib/rodauth/features/verify_change_login.rb +0 -20
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# frozen-string-literal: true
|
|
2
|
+
|
|
3
|
+
module Rodauth
|
|
4
|
+
Feature.define(:password_pepper, :PasswordPepper) do
|
|
5
|
+
depends :login_password_requirements_base
|
|
6
|
+
|
|
7
|
+
auth_value_method :password_pepper, nil
|
|
8
|
+
auth_value_method :previous_password_peppers, [""]
|
|
9
|
+
auth_value_method :password_pepper_update?, true
|
|
10
|
+
|
|
11
|
+
def password_match?(password)
|
|
12
|
+
if (result = super) && @previous_pepper_matched && password_pepper_update?
|
|
13
|
+
set_password(password)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
result
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
private
|
|
20
|
+
|
|
21
|
+
def password_hash(password)
|
|
22
|
+
super(password + password_pepper.to_s)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def password_hash_match?(hash, password)
|
|
26
|
+
return super if password_pepper.nil?
|
|
27
|
+
|
|
28
|
+
return true if super(hash, password + password_pepper)
|
|
29
|
+
|
|
30
|
+
@previous_pepper_matched = previous_password_peppers.any? do |pepper|
|
|
31
|
+
super(hash, password + pepper)
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def database_function_password_match?(name, hash_id, password, salt)
|
|
36
|
+
return super if password_pepper.nil?
|
|
37
|
+
|
|
38
|
+
return true if super(name, hash_id, password + password_pepper, salt)
|
|
39
|
+
|
|
40
|
+
@previous_pepper_matched = previous_password_peppers.any? do |pepper|
|
|
41
|
+
super(name, hash_id, password + pepper, salt)
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
@@ -17,11 +17,11 @@ module Rodauth
|
|
|
17
17
|
button 'Authenticate via Recovery Code', 'recovery_auth'
|
|
18
18
|
button 'View Authentication Recovery Codes', 'view_recovery_codes'
|
|
19
19
|
|
|
20
|
-
error_flash "Error authenticating via recovery code
|
|
21
|
-
error_flash "Unable to add recovery codes
|
|
22
|
-
error_flash "Unable to view recovery codes
|
|
20
|
+
error_flash "Error authenticating via recovery code", 'invalid_recovery_code'
|
|
21
|
+
error_flash "Unable to add recovery codes", 'add_recovery_codes'
|
|
22
|
+
error_flash "Unable to view recovery codes", 'view_recovery_codes'
|
|
23
23
|
|
|
24
|
-
notice_flash "Additional authentication recovery codes have been added
|
|
24
|
+
notice_flash "Additional authentication recovery codes have been added", 'recovery_codes_added'
|
|
25
25
|
|
|
26
26
|
redirect(:recovery_auth){recovery_auth_path}
|
|
27
27
|
redirect(:add_recovery_codes){recovery_codes_path}
|
|
@@ -32,15 +32,19 @@ module Rodauth
|
|
|
32
32
|
view 'recovery-codes', 'View Authentication Recovery Codes', 'recovery_codes'
|
|
33
33
|
|
|
34
34
|
auth_value_method :add_recovery_codes_param, 'add'
|
|
35
|
-
|
|
36
|
-
auth_value_method :
|
|
35
|
+
translatable_method :add_recovery_codes_heading, '<h2>Add Additional Recovery Codes</h2>'
|
|
36
|
+
auth_value_method :auto_add_recovery_codes?, false
|
|
37
|
+
translatable_method :invalid_recovery_code_message, "Invalid recovery code"
|
|
37
38
|
auth_value_method :recovery_codes_limit, 16
|
|
38
39
|
auth_value_method :recovery_codes_column, :code
|
|
39
40
|
auth_value_method :recovery_codes_id_column, :id
|
|
40
|
-
|
|
41
|
+
translatable_method :recovery_codes_label, 'Recovery Code'
|
|
41
42
|
auth_value_method :recovery_codes_param, 'recovery-code'
|
|
42
43
|
auth_value_method :recovery_codes_table, :account_recovery_codes
|
|
43
44
|
|
|
45
|
+
translatable_method :recovery_auth_link_text, "Authenticate Using Recovery Code"
|
|
46
|
+
translatable_method :recovery_codes_link_text, "View Authentication Recovery Codes"
|
|
47
|
+
|
|
44
48
|
auth_cached_method :recovery_codes
|
|
45
49
|
|
|
46
50
|
auth_value_methods(
|
|
@@ -59,7 +63,7 @@ module Rodauth
|
|
|
59
63
|
require_login
|
|
60
64
|
require_account_session
|
|
61
65
|
require_two_factor_setup
|
|
62
|
-
require_two_factor_not_authenticated
|
|
66
|
+
require_two_factor_not_authenticated('recovery_code')
|
|
63
67
|
before_recovery_auth_route
|
|
64
68
|
|
|
65
69
|
r.get do
|
|
@@ -69,7 +73,7 @@ module Rodauth
|
|
|
69
73
|
r.post do
|
|
70
74
|
if recovery_code_match?(param(recovery_codes_param))
|
|
71
75
|
before_recovery_auth
|
|
72
|
-
two_factor_authenticate(
|
|
76
|
+
two_factor_authenticate('recovery_code')
|
|
73
77
|
end
|
|
74
78
|
|
|
75
79
|
set_response_error_status(invalid_key_error_status)
|
|
@@ -124,61 +128,24 @@ module Rodauth
|
|
|
124
128
|
|
|
125
129
|
attr_accessor :recovery_codes_button
|
|
126
130
|
|
|
127
|
-
def two_factor_need_setup_redirect
|
|
128
|
-
super || (add_recovery_codes_redirect if recovery_codes_primary?)
|
|
129
|
-
end
|
|
130
|
-
|
|
131
|
-
def two_factor_auth_required_redirect
|
|
132
|
-
super || (recovery_auth_redirect if recovery_codes_primary?)
|
|
133
|
-
end
|
|
134
|
-
|
|
135
|
-
def two_factor_auth_fallback_redirect
|
|
136
|
-
recovery_auth_redirect
|
|
137
|
-
end
|
|
138
|
-
|
|
139
131
|
def two_factor_remove
|
|
140
132
|
super
|
|
141
133
|
recovery_codes_remove
|
|
142
134
|
end
|
|
143
135
|
|
|
144
|
-
def two_factor_authentication_setup?
|
|
145
|
-
super || (recovery_codes_primary? && !recovery_codes.empty?)
|
|
146
|
-
end
|
|
147
|
-
|
|
148
|
-
def otp_auth_form_footer
|
|
149
|
-
"#{super if defined?(super)}<p><a href=\"#{recovery_auth_path}\">Authenticate using recovery code</a></p>"
|
|
150
|
-
end
|
|
151
|
-
|
|
152
|
-
def otp_lockout_redirect
|
|
153
|
-
recovery_auth_redirect
|
|
154
|
-
end
|
|
155
|
-
|
|
156
|
-
def otp_lockout_error_flash
|
|
157
|
-
"#{super if defined?(super)} Can use recovery code to unlock."
|
|
158
|
-
end
|
|
159
|
-
|
|
160
136
|
def otp_add_key
|
|
161
137
|
super if defined?(super)
|
|
162
|
-
|
|
138
|
+
auto_add_missing_recovery_codes
|
|
163
139
|
end
|
|
164
140
|
|
|
165
141
|
def sms_confirm
|
|
166
142
|
super if defined?(super)
|
|
167
|
-
|
|
168
|
-
end
|
|
169
|
-
|
|
170
|
-
def otp_remove
|
|
171
|
-
super if defined?(super)
|
|
172
|
-
unless recovery_codes_primary?
|
|
173
|
-
recovery_codes_remove
|
|
174
|
-
end
|
|
143
|
+
auto_add_missing_recovery_codes
|
|
175
144
|
end
|
|
176
145
|
|
|
177
|
-
def
|
|
146
|
+
def add_webauthn_credential(_)
|
|
178
147
|
super if defined?(super)
|
|
179
|
-
|
|
180
|
-
recovery_codes_remove
|
|
181
|
-
end
|
|
148
|
+
auto_add_missing_recovery_codes
|
|
182
149
|
end
|
|
183
150
|
|
|
184
151
|
def recovery_codes_remove
|
|
@@ -221,14 +188,43 @@ module Rodauth
|
|
|
221
188
|
end
|
|
222
189
|
end
|
|
223
190
|
|
|
191
|
+
def possible_authentication_methods
|
|
192
|
+
methods = super
|
|
193
|
+
methods << 'recovery_code' unless recovery_codes_ds.empty?
|
|
194
|
+
methods
|
|
195
|
+
end
|
|
196
|
+
|
|
224
197
|
private
|
|
225
198
|
|
|
199
|
+
def _two_factor_auth_links
|
|
200
|
+
links = super
|
|
201
|
+
links << [40, recovery_auth_path, recovery_auth_link_text] unless recovery_codes_ds.empty?
|
|
202
|
+
links
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
def _two_factor_setup_links
|
|
206
|
+
links = super
|
|
207
|
+
links << [40, recovery_codes_path, recovery_codes_link_text] if (recovery_codes_primary? || uses_two_factor_authentication?)
|
|
208
|
+
links
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
def _two_factor_remove_all_from_session
|
|
212
|
+
two_factor_remove_session('recovery_code')
|
|
213
|
+
super
|
|
214
|
+
end
|
|
215
|
+
|
|
226
216
|
def new_recovery_code
|
|
227
217
|
random_key
|
|
228
218
|
end
|
|
229
219
|
|
|
230
220
|
def recovery_codes_primary?
|
|
231
|
-
(features & [:otp, :sms_codes]).empty?
|
|
221
|
+
(features & [:otp, :sms_codes, :webauthn]).empty?
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
def auto_add_missing_recovery_codes
|
|
225
|
+
if auto_add_recovery_codes?
|
|
226
|
+
add_recovery_codes(recovery_codes_limit - recovery_codes.length)
|
|
227
|
+
end
|
|
232
228
|
end
|
|
233
229
|
|
|
234
230
|
def _recovery_codes
|
|
@@ -2,8 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
module Rodauth
|
|
4
4
|
Feature.define(:remember, :Remember) do
|
|
5
|
-
depends :confirm_password
|
|
6
|
-
|
|
7
5
|
notice_flash "Your remember setting has been updated"
|
|
8
6
|
error_flash "There was an error updating your remember setting"
|
|
9
7
|
loaded_templates %w'remember'
|
|
@@ -17,11 +15,10 @@ module Rodauth
|
|
|
17
15
|
redirect
|
|
18
16
|
|
|
19
17
|
auth_value_method :raw_remember_token_deadline, nil
|
|
20
|
-
auth_value_method :remember_cookie_options, {}
|
|
18
|
+
auth_value_method :remember_cookie_options, {}.freeze
|
|
21
19
|
auth_value_method :extend_remember_deadline?, false
|
|
22
|
-
auth_value_method :remember_period, {:days=>14}
|
|
23
|
-
|
|
24
|
-
auth_value_method :remember_deadline_interval, {:days=>14}
|
|
20
|
+
auth_value_method :remember_period, {:days=>14}.freeze
|
|
21
|
+
auth_value_method :remember_deadline_interval, {:days=>14}.freeze
|
|
25
22
|
auth_value_method :remember_id_column, :id
|
|
26
23
|
auth_value_method :remember_key_column, :key
|
|
27
24
|
auth_value_method :remember_deadline_column, :deadline
|
|
@@ -31,13 +28,12 @@ module Rodauth
|
|
|
31
28
|
auth_value_method :remember_remember_param_value, 'remember'
|
|
32
29
|
auth_value_method :remember_forget_param_value, 'forget'
|
|
33
30
|
auth_value_method :remember_disable_param_value, 'disable'
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
31
|
+
translatable_method :remember_remember_label, 'Remember Me'
|
|
32
|
+
translatable_method :remember_forget_label, 'Forget Me'
|
|
33
|
+
translatable_method :remember_disable_label, 'Disable Remember Me'
|
|
37
34
|
|
|
38
35
|
auth_methods(
|
|
39
36
|
:add_remember_key,
|
|
40
|
-
:clear_remembered_session_key,
|
|
41
37
|
:disable_remember_login,
|
|
42
38
|
:forget_login,
|
|
43
39
|
:generate_remember_key_value,
|
|
@@ -62,7 +58,9 @@ module Rodauth
|
|
|
62
58
|
if [remember_remember_param_value, remember_forget_param_value, remember_disable_param_value].include?(remember)
|
|
63
59
|
transaction do
|
|
64
60
|
before_remember
|
|
61
|
+
# :nocov:
|
|
65
62
|
case remember
|
|
63
|
+
# :nocov:
|
|
66
64
|
when remember_remember_param_value
|
|
67
65
|
remember_login
|
|
68
66
|
when remember_forget_param_value
|
|
@@ -109,9 +107,9 @@ module Rodauth
|
|
|
109
107
|
return
|
|
110
108
|
end
|
|
111
109
|
|
|
112
|
-
|
|
110
|
+
set_session_value(session_key, id)
|
|
113
111
|
account = account_from_session
|
|
114
|
-
|
|
112
|
+
remove_session_value(session_key)
|
|
115
113
|
|
|
116
114
|
unless account
|
|
117
115
|
remove_remember_key(id)
|
|
@@ -120,9 +118,8 @@ module Rodauth
|
|
|
120
118
|
end
|
|
121
119
|
|
|
122
120
|
before_load_memory
|
|
123
|
-
|
|
121
|
+
login_session('remember')
|
|
124
122
|
|
|
125
|
-
set_session_value(remembered_session_key, true)
|
|
126
123
|
if extend_remember_deadline?
|
|
127
124
|
active_remember_key_ds(id).update(remember_deadline_column=>Sequel.date_add(Sequel::CURRENT_TIMESTAMP, remember_period))
|
|
128
125
|
remember_login
|
|
@@ -133,9 +130,7 @@ module Rodauth
|
|
|
133
130
|
def remember_login
|
|
134
131
|
get_remember_key
|
|
135
132
|
opts = Hash[remember_cookie_options]
|
|
136
|
-
|
|
137
|
-
key = compute_hmac(key) if hmac_secret
|
|
138
|
-
opts[:value] = "#{account_id}_#{key}"
|
|
133
|
+
opts[:value] = "#{account_id}_#{convert_token_key(remember_key_value)}"
|
|
139
134
|
opts[:expires] = convert_timestamp(active_remember_key_ds.get(remember_deadline_column))
|
|
140
135
|
::Rack::Utils.set_cookie_header!(response.headers, remember_cookie_key, opts)
|
|
141
136
|
end
|
|
@@ -174,12 +169,8 @@ module Rodauth
|
|
|
174
169
|
remember_key_ds(id).delete
|
|
175
170
|
end
|
|
176
171
|
|
|
177
|
-
def clear_remembered_session_key
|
|
178
|
-
session.delete(remembered_session_key)
|
|
179
|
-
end
|
|
180
|
-
|
|
181
172
|
def logged_in_via_remember_key?
|
|
182
|
-
|
|
173
|
+
authenticated_by.include?('remember')
|
|
183
174
|
end
|
|
184
175
|
|
|
185
176
|
private
|
|
@@ -194,11 +185,6 @@ module Rodauth
|
|
|
194
185
|
super if defined?(super)
|
|
195
186
|
end
|
|
196
187
|
|
|
197
|
-
def after_confirm_password
|
|
198
|
-
super
|
|
199
|
-
clear_remembered_session_key
|
|
200
|
-
end
|
|
201
|
-
|
|
202
188
|
attr_reader :remember_key_value
|
|
203
189
|
|
|
204
190
|
def generate_remember_key_value
|
|
@@ -4,8 +4,6 @@ module Rodauth
|
|
|
4
4
|
Feature.define(:reset_password, :ResetPassword) do
|
|
5
5
|
depends :login, :email_base, :login_password_requirements_base
|
|
6
6
|
|
|
7
|
-
def_deprecated_alias :no_matching_reset_password_key_error_flash, :no_matching_reset_password_key_message
|
|
8
|
-
|
|
9
7
|
notice_flash "Your password has been reset"
|
|
10
8
|
notice_flash "An email has been sent to you with a link to reset the password for your account", 'reset_password_email_sent'
|
|
11
9
|
error_flash "There was an error resetting your password"
|
|
@@ -28,20 +26,19 @@ module Rodauth
|
|
|
28
26
|
redirect(:reset_password_email_recently_sent){default_post_email_redirect}
|
|
29
27
|
|
|
30
28
|
auth_value_method :reset_password_deadline_column, :deadline
|
|
31
|
-
auth_value_method :reset_password_deadline_interval, {:days=>1}
|
|
32
|
-
|
|
29
|
+
auth_value_method :reset_password_deadline_interval, {:days=>1}.freeze
|
|
30
|
+
translatable_method :reset_password_email_subject, 'Reset Password'
|
|
33
31
|
auth_value_method :reset_password_key_param, 'key'
|
|
34
32
|
auth_value_method :reset_password_autologin?, false
|
|
35
33
|
auth_value_method :reset_password_table, :account_password_reset_keys
|
|
36
34
|
auth_value_method :reset_password_id_column, :id
|
|
37
35
|
auth_value_method :reset_password_key_column, :key
|
|
38
|
-
auth_value_method :reset_password_email_last_sent_column,
|
|
39
|
-
|
|
36
|
+
auth_value_method :reset_password_email_last_sent_column, :email_last_sent
|
|
37
|
+
translatable_method :reset_password_explanatory_text, "<p>If you have forgotten your password, you can request a password reset:</p>"
|
|
40
38
|
auth_value_method :reset_password_skip_resend_email_within, 300
|
|
39
|
+
translatable_method :reset_password_request_link_text, "Forgot Password?"
|
|
41
40
|
session_key :reset_password_session_key, :reset_password_key
|
|
42
41
|
|
|
43
|
-
auth_value_methods :reset_password_request_link
|
|
44
|
-
|
|
45
42
|
auth_methods(
|
|
46
43
|
:create_reset_password_key,
|
|
47
44
|
:create_reset_password_email,
|
|
@@ -69,7 +66,15 @@ module Rodauth
|
|
|
69
66
|
end
|
|
70
67
|
|
|
71
68
|
r.post do
|
|
72
|
-
|
|
69
|
+
catch_error do
|
|
70
|
+
unless account_from_login(param(login_param))
|
|
71
|
+
throw_error_status(no_matching_login_error_status, login_param, no_matching_login_message)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
unless open_account?
|
|
75
|
+
throw_error_status(unopen_account_error_status, login_param, unverified_account_message)
|
|
76
|
+
end
|
|
77
|
+
|
|
73
78
|
if reset_password_email_recently_sent?
|
|
74
79
|
set_redirect_error_flash reset_password_email_recently_sent_error_flash
|
|
75
80
|
redirect reset_password_email_recently_sent_redirect
|
|
@@ -84,12 +89,11 @@ module Rodauth
|
|
|
84
89
|
end
|
|
85
90
|
|
|
86
91
|
set_notice_flash reset_password_email_sent_notice_flash
|
|
87
|
-
|
|
88
|
-
set_redirect_error_status(no_matching_login_error_status)
|
|
89
|
-
set_redirect_error_flash reset_password_request_error_flash
|
|
92
|
+
redirect reset_password_email_sent_redirect
|
|
90
93
|
end
|
|
91
94
|
|
|
92
|
-
|
|
95
|
+
set_error_flash reset_password_request_error_flash
|
|
96
|
+
reset_password_request_view
|
|
93
97
|
end
|
|
94
98
|
end
|
|
95
99
|
|
|
@@ -99,7 +103,7 @@ module Rodauth
|
|
|
99
103
|
|
|
100
104
|
r.get do
|
|
101
105
|
if key = param_or_nil(reset_password_key_param)
|
|
102
|
-
|
|
106
|
+
set_session_value(reset_password_session_key, key)
|
|
103
107
|
redirect(r.path)
|
|
104
108
|
end
|
|
105
109
|
|
|
@@ -107,7 +111,7 @@ module Rodauth
|
|
|
107
111
|
if account_from_reset_password_key(key)
|
|
108
112
|
reset_password_view
|
|
109
113
|
else
|
|
110
|
-
|
|
114
|
+
remove_session_value(reset_password_session_key)
|
|
111
115
|
set_redirect_error_flash no_matching_reset_password_key_error_flash
|
|
112
116
|
redirect require_login_redirect
|
|
113
117
|
end
|
|
@@ -144,10 +148,10 @@ module Rodauth
|
|
|
144
148
|
end
|
|
145
149
|
|
|
146
150
|
if reset_password_autologin?
|
|
147
|
-
|
|
151
|
+
autologin_session('reset_password')
|
|
148
152
|
end
|
|
149
153
|
|
|
150
|
-
|
|
154
|
+
remove_session_value(reset_password_session_key)
|
|
151
155
|
set_notice_flash reset_password_notice_flash
|
|
152
156
|
redirect reset_password_redirect
|
|
153
157
|
end
|
|
@@ -192,14 +196,6 @@ module Rodauth
|
|
|
192
196
|
ds.get(reset_password_key_column)
|
|
193
197
|
end
|
|
194
198
|
|
|
195
|
-
def login_form_footer
|
|
196
|
-
super + reset_password_request_link
|
|
197
|
-
end
|
|
198
|
-
|
|
199
|
-
def reset_password_request_link
|
|
200
|
-
"<p><a href=\"#{reset_password_request_path}\">Forgot Password?</a></p>"
|
|
201
|
-
end
|
|
202
|
-
|
|
203
199
|
def set_reset_password_email_last_sent
|
|
204
200
|
password_reset_ds.update(reset_password_email_last_sent_column=>Sequel::CURRENT_TIMESTAMP) if reset_password_email_last_sent_column
|
|
205
201
|
end
|
|
@@ -214,6 +210,10 @@ module Rodauth
|
|
|
214
210
|
|
|
215
211
|
private
|
|
216
212
|
|
|
213
|
+
def _login_form_footer_links
|
|
214
|
+
super << [20, reset_password_request_path, reset_password_request_link_text]
|
|
215
|
+
end
|
|
216
|
+
|
|
217
217
|
def reset_password_email_recently_sent?
|
|
218
218
|
(email_last_sent = get_reset_password_email_last_sent) && (Time.now - email_last_sent < reset_password_skip_resend_email_within)
|
|
219
219
|
end
|
|
@@ -2,16 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
module Rodauth
|
|
4
4
|
Feature.define(:session_expiration, :SessionExpiration) do
|
|
5
|
-
error_flash "This session has expired, please login again
|
|
5
|
+
error_flash "This session has expired, please login again"
|
|
6
|
+
redirect{require_login_redirect}
|
|
6
7
|
|
|
7
8
|
auth_value_method :max_session_lifetime, 86400
|
|
8
9
|
session_key :session_created_session_key, :session_created_at
|
|
10
|
+
auth_value_method :session_expiration_error_status, 401
|
|
9
11
|
auth_value_method :session_expiration_default, true
|
|
10
12
|
auth_value_method :session_inactivity_timeout, 1800
|
|
11
13
|
session_key :session_last_activity_session_key, :last_session_activity_at
|
|
12
14
|
|
|
13
|
-
auth_value_methods :session_expiration_redirect
|
|
14
|
-
|
|
15
15
|
def check_session_expiration
|
|
16
16
|
return unless logged_in?
|
|
17
17
|
|
|
@@ -37,19 +37,16 @@ module Rodauth
|
|
|
37
37
|
|
|
38
38
|
def expire_session
|
|
39
39
|
clear_session
|
|
40
|
+
set_redirect_error_status session_expiration_error_status
|
|
40
41
|
set_redirect_error_flash session_expiration_error_flash
|
|
41
42
|
redirect session_expiration_redirect
|
|
42
43
|
end
|
|
43
44
|
|
|
44
|
-
def session_expiration_redirect
|
|
45
|
-
require_login_redirect
|
|
46
|
-
end
|
|
47
|
-
|
|
48
|
-
private
|
|
49
|
-
|
|
50
45
|
def update_session
|
|
51
46
|
super
|
|
52
|
-
|
|
47
|
+
t = Time.now.to_i
|
|
48
|
+
set_session_value(session_last_activity_session_key, t)
|
|
49
|
+
set_session_value(session_created_session_key, t)
|
|
53
50
|
end
|
|
54
51
|
end
|
|
55
52
|
end
|