rodauth 1.19.1 → 1.20.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG +72 -0
- data/MIT-LICENSE +1 -1
- data/README.rdoc +100 -7
- data/doc/base.rdoc +25 -0
- data/doc/email_auth.rdoc +1 -1
- data/doc/email_base.rdoc +5 -1
- data/doc/internals.rdoc +2 -2
- data/doc/jwt_refresh.rdoc +35 -0
- data/doc/lockout.rdoc +3 -0
- data/doc/login_password_requirements_base.rdoc +4 -1
- data/doc/otp.rdoc +22 -39
- data/doc/recovery_codes.rdoc +15 -28
- data/doc/release_notes/1.20.0.txt +175 -0
- data/doc/remember.rdoc +3 -0
- data/doc/reset_password.rdoc +2 -1
- data/doc/single_session.rdoc +3 -0
- data/doc/verify_account.rdoc +4 -3
- data/doc/verify_login_change.rdoc +1 -1
- data/lib/rodauth.rb +33 -4
- data/lib/rodauth/features/base.rb +93 -10
- data/lib/rodauth/features/change_login.rb +1 -1
- data/lib/rodauth/features/confirm_password.rb +1 -1
- data/lib/rodauth/features/create_account.rb +2 -2
- data/lib/rodauth/features/disallow_password_reuse.rb +5 -3
- data/lib/rodauth/features/email_auth.rb +4 -2
- data/lib/rodauth/features/email_base.rb +12 -6
- data/lib/rodauth/features/jwt.rb +9 -0
- data/lib/rodauth/features/jwt_refresh.rb +142 -0
- data/lib/rodauth/features/lockout.rb +8 -4
- data/lib/rodauth/features/login_password_requirements_base.rb +1 -0
- data/lib/rodauth/features/otp.rb +63 -6
- data/lib/rodauth/features/recovery_codes.rb +1 -0
- data/lib/rodauth/features/remember.rb +20 -2
- data/lib/rodauth/features/reset_password.rb +5 -2
- data/lib/rodauth/features/single_session.rb +15 -2
- data/lib/rodauth/features/verify_account.rb +11 -6
- data/lib/rodauth/features/verify_login_change.rb +5 -3
- data/lib/rodauth/version.rb +2 -2
- data/spec/disallow_password_reuse_spec.rb +115 -28
- data/spec/email_auth_spec.rb +2 -2
- data/spec/jwt_refresh_spec.rb +256 -0
- data/spec/lockout_spec.rb +4 -4
- data/spec/login_spec.rb +52 -11
- data/spec/migrate/001_tables.rb +10 -0
- data/spec/migrate_travis/001_tables.rb +8 -0
- data/spec/remember_spec.rb +27 -0
- data/spec/reset_password_spec.rb +2 -2
- data/spec/rodauth_spec.rb +25 -1
- data/spec/single_session_spec.rb +20 -0
- data/spec/spec_helper.rb +29 -0
- data/spec/two_factor_spec.rb +57 -3
- data/spec/verify_account_spec.rb +18 -1
- data/spec/verify_login_change_spec.rb +2 -2
- data/templates/add-recovery-codes.str +1 -1
- data/templates/change-password.str +2 -2
- data/templates/login-confirm-field.str +2 -2
- data/templates/login-field.str +2 -2
- data/templates/otp-auth-code-field.str +2 -2
- data/templates/otp-setup.str +4 -3
- data/templates/password-confirm-field.str +2 -2
- data/templates/password-field.str +2 -2
- data/templates/recovery-auth.str +2 -2
- data/templates/reset-password-request.str +1 -1
- data/templates/sms-code-field.str +2 -2
- data/templates/sms-setup.str +2 -2
- data/templates/unlock-account-request.str +1 -1
- data/templates/unlock-account.str +1 -1
- data/templates/verify-account-resend.str +1 -1
- metadata +15 -5
data/spec/verify_account_spec.rb
CHANGED
@@ -3,10 +3,14 @@ require File.expand_path("spec_helper", File.dirname(__FILE__))
|
|
3
3
|
describe 'Rodauth verify_account feature' do
|
4
4
|
it "should support verifying accounts" do
|
5
5
|
last_sent_column = nil
|
6
|
+
secret = nil
|
7
|
+
allow_raw_token = false
|
6
8
|
rodauth do
|
7
9
|
enable :login, :create_account, :verify_account
|
8
10
|
verify_account_autologin? false
|
9
11
|
verify_account_email_last_sent_column{last_sent_column}
|
12
|
+
hmac_secret{secret}
|
13
|
+
allow_raw_email_token?{allow_raw_token}
|
10
14
|
end
|
11
15
|
roda do |r|
|
12
16
|
r.rodauth
|
@@ -73,8 +77,13 @@ describe 'Rodauth verify_account feature' do
|
|
73
77
|
|
74
78
|
link = email_link(/(\/verify-account\?key=.+)$/, 'foo@example2.com')
|
75
79
|
visit link[0...-1]
|
76
|
-
page.find('#error_flash').text.must_equal "invalid verify account key"
|
80
|
+
page.find('#error_flash').text.must_equal "There was an error verifying your account: invalid verify account key"
|
77
81
|
|
82
|
+
secret = SecureRandom.random_bytes(32)
|
83
|
+
visit link
|
84
|
+
page.find('#error_flash').text.must_equal "There was an error verifying your account: invalid verify account key"
|
85
|
+
|
86
|
+
allow_raw_token = true
|
78
87
|
visit link
|
79
88
|
click_button 'Verify Account'
|
80
89
|
page.find('#notice_flash').text.must_equal "Your account has been verified"
|
@@ -87,11 +96,13 @@ describe 'Rodauth verify_account feature' do
|
|
87
96
|
|
88
97
|
[false, true].each do |ph|
|
89
98
|
it "should support setting passwords when verifying accounts #{'with account_password_hash_column' if ph}" do
|
99
|
+
initial_secret = secret = SecureRandom.random_bytes(32)
|
90
100
|
rodauth do
|
91
101
|
enable :login, :create_account, :verify_account
|
92
102
|
account_password_hash_column :ph if ph
|
93
103
|
verify_account_autologin? false
|
94
104
|
verify_account_set_password? true
|
105
|
+
hmac_secret{secret}
|
95
106
|
end
|
96
107
|
roda do |r|
|
97
108
|
r.rodauth
|
@@ -105,6 +116,12 @@ describe 'Rodauth verify_account feature' do
|
|
105
116
|
page.find('#notice_flash').text.must_equal "An email has been sent to you with a link to verify your account"
|
106
117
|
|
107
118
|
link = email_link(/(\/verify-account\?key=.+)$/, 'foo@example2.com')
|
119
|
+
|
120
|
+
secret = SecureRandom.random_bytes(32)
|
121
|
+
visit link
|
122
|
+
page.find('#error_flash').text.must_equal "There was an error verifying your account: invalid verify account key"
|
123
|
+
|
124
|
+
secret = initial_secret
|
108
125
|
visit link
|
109
126
|
fill_in 'Password', :with=>'0123456789'
|
110
127
|
fill_in 'Confirm Password', :with=>'012345678'
|
@@ -36,7 +36,7 @@ describe 'Rodauth verify_login_change feature' do
|
|
36
36
|
logout
|
37
37
|
|
38
38
|
visit link
|
39
|
-
page.find('#error_flash').text.must_equal "invalid verify login change key"
|
39
|
+
page.find('#error_flash').text.must_equal "There was an error verifying your login change: invalid verify login change key"
|
40
40
|
|
41
41
|
visit new_link
|
42
42
|
page.title.must_equal 'Verify Login Change'
|
@@ -128,7 +128,7 @@ describe 'Rodauth verify_login_change feature' do
|
|
128
128
|
page.current_path.must_equal '/login'
|
129
129
|
|
130
130
|
visit link
|
131
|
-
page.find('#error_flash').text.must_equal "invalid verify login change key"
|
131
|
+
page.find('#error_flash').text.must_equal "There was an error verifying your login change: invalid verify login change key"
|
132
132
|
end
|
133
133
|
|
134
134
|
it "should handle uniqueness errors raised when inserting verify login change entry" do
|
@@ -1,2 +1,2 @@
|
|
1
1
|
<pre id="recovery-codes">#{rodauth.recovery_codes.map{|s| h s}.join("\n\n")}</pre>
|
2
|
-
#{"
|
2
|
+
#{"#{rodauth.add_recovery_codes_heading}#{rodauth.render('recovery-codes')}" if rodauth.can_add_recovery_codes?}
|
@@ -3,9 +3,9 @@
|
|
3
3
|
#{rodauth.csrf_tag}
|
4
4
|
#{rodauth.render('password-field') if rodauth.change_password_requires_password?}
|
5
5
|
<div class="form-group">
|
6
|
-
<label class="col-sm-2 control-label" for="new-password">#{rodauth.new_password_label}</label>
|
6
|
+
<label class="col-sm-2 control-label" for="new-password">#{rodauth.new_password_label}#{rodauth.input_field_label_suffix}</label>
|
7
7
|
<div class="col-sm-10">
|
8
|
-
|
8
|
+
#{rodauth.input_field_string(rodauth.new_password_param, 'new-password', :type => 'password')}
|
9
9
|
</div>
|
10
10
|
</div>
|
11
11
|
#{rodauth.render('password-confirm-field') if rodauth.require_password_confirmation?}
|
@@ -1,6 +1,6 @@
|
|
1
1
|
<div class="form-group">
|
2
|
-
<label class="col-sm-2 control-label" for="login-confirm">#{rodauth.login_confirm_label}</label>
|
2
|
+
<label class="col-sm-2 control-label" for="login-confirm">#{rodauth.login_confirm_label}#{rodauth.input_field_label_suffix}</label>
|
3
3
|
<div class="col-sm-10">
|
4
|
-
|
4
|
+
#{rodauth.input_field_string(rodauth.login_confirm_param, 'login-confirm', :type=>rodauth.login_input_type)}
|
5
5
|
</div>
|
6
6
|
</div>
|
data/templates/login-field.str
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
<div class="form-group">
|
2
|
-
<label class="col-sm-2 control-label" for="login">#{rodauth.login_label}</label>
|
2
|
+
<label class="col-sm-2 control-label" for="login">#{rodauth.login_label}#{rodauth.input_field_label_suffix}</label>
|
3
3
|
<div class="col-sm-10">
|
4
|
-
|
4
|
+
#{rodauth.input_field_string(rodauth.login_param, 'login', :type=>rodauth.login_input_type)}
|
5
5
|
</div>
|
6
6
|
</div>
|
@@ -1,6 +1,6 @@
|
|
1
1
|
<div class="form-group">
|
2
|
-
<label class="col-sm-4 control-label" for="otp-auth-code">#{rodauth.otp_auth_label}</label>
|
2
|
+
<label class="col-sm-4 control-label" for="otp-auth-code">#{rodauth.otp_auth_label}#{rodauth.input_field_label_suffix}</label>
|
3
3
|
<div class="col-sm-3">
|
4
|
-
|
4
|
+
#{rodauth.input_field_string(rodauth.otp_auth_param, 'otp-auth-code', :value=>'', :attr=>'autocomplete="off"' )}
|
5
5
|
</div>
|
6
6
|
</div>
|
data/templates/otp-setup.str
CHANGED
@@ -1,10 +1,11 @@
|
|
1
1
|
<form method="post" class="rodauth form-horizontal" role="form" id="otp-setup-form">
|
2
2
|
#{rodauth.otp_setup_additional_form_tags}
|
3
|
-
<input type="hidden" id="otp-key" name="#{rodauth.otp_setup_param}" value="#{rodauth.
|
3
|
+
<input type="hidden" id="otp-key" name="#{rodauth.otp_setup_param}" value="#{rodauth.otp_user_key}" />
|
4
|
+
#{"<input type=\"hidden\" id=\"otp-hmac-secret\" name=\"#{rodauth.otp_setup_raw_param}\" value=\"#{rodauth.otp_key}\" />" if rodauth.otp_keys_use_hmac?}
|
4
5
|
#{rodauth.csrf_tag}
|
5
6
|
<div class="form-group">
|
6
|
-
<p
|
7
|
-
<p
|
7
|
+
<p>#{rodauth.otp_secret_label}: #{rodauth.otp_user_key}</p>
|
8
|
+
<p>#{rodauth.otp_provisioning_uri_label}: #{rodauth.otp_provisioning_uri}</p>
|
8
9
|
</div>
|
9
10
|
|
10
11
|
<div class="row">
|
@@ -1,6 +1,6 @@
|
|
1
1
|
<div class="form-group">
|
2
|
-
<label class="col-sm-2 control-label" for="password-confirm">#{rodauth.password_confirm_label}</label>
|
2
|
+
<label class="col-sm-2 control-label" for="password-confirm">#{rodauth.password_confirm_label}#{rodauth.input_field_label_suffix}</label>
|
3
3
|
<div class="col-sm-10">
|
4
|
-
|
4
|
+
#{rodauth.input_field_string(rodauth.password_confirm_param, 'password-confirm', :type => 'password')}
|
5
5
|
</div>
|
6
6
|
</div>
|
@@ -1,6 +1,6 @@
|
|
1
1
|
<div class="form-group">
|
2
|
-
<label class="col-sm-2 control-label" for="password">#{rodauth.password_label}</label>
|
2
|
+
<label class="col-sm-2 control-label" for="password">#{rodauth.password_label}#{rodauth.input_field_label_suffix}</label>
|
3
3
|
<div class="col-sm-10">
|
4
|
-
|
4
|
+
#{rodauth.input_field_string(rodauth.password_param, 'password', :type => 'password')}
|
5
5
|
</div>
|
6
6
|
</div>
|
data/templates/recovery-auth.str
CHANGED
@@ -2,9 +2,9 @@
|
|
2
2
|
#{rodauth.recovery_auth_additional_form_tags}
|
3
3
|
#{rodauth.csrf_tag}
|
4
4
|
<div class="form-group">
|
5
|
-
<label class="col-sm-2 control-label" for="recovery_code">#{rodauth.recovery_codes_label}</label>
|
5
|
+
<label class="col-sm-2 control-label" for="recovery_code">#{rodauth.recovery_codes_label}#{rodauth.input_field_label_suffix}</label>
|
6
6
|
<div class="col-sm-10">
|
7
|
-
|
7
|
+
#{rodauth.input_field_string(rodauth.recovery_codes_param, 'recovery_code', :value => '')}
|
8
8
|
</div>
|
9
9
|
</div>
|
10
10
|
#{rodauth.button(rodauth.recovery_auth_button)}
|
@@ -1,7 +1,7 @@
|
|
1
1
|
<form action="#{rodauth.prefix}/#{rodauth.reset_password_request_route}" method="post" class="rodauth form-horizontal" role="form" id="reset-password-request-form">
|
2
2
|
#{rodauth.reset_password_request_additional_form_tags}
|
3
3
|
#{rodauth.csrf_tag("#{rodauth.prefix}/#{rodauth.reset_password_request_route}")}
|
4
|
-
|
4
|
+
#{rodauth.reset_password_explanatory_text}
|
5
5
|
#{(login = rodauth.param_or_nil(rodauth.login_param)) ? "<input type=\"hidden\" name=\"#{rodauth.login_param}\" value=\"#{h login}\"/>" : rodauth.render('login-field')}
|
6
6
|
#{rodauth.button(rodauth.reset_password_request_button)}
|
7
7
|
</form>
|
@@ -1,6 +1,6 @@
|
|
1
1
|
<div class="form-group">
|
2
|
-
<label class="col-sm-3 control-label" for="sms-code">#{rodauth.sms_code_label}</label>
|
2
|
+
<label class="col-sm-3 control-label" for="sms-code">#{rodauth.sms_code_label}#{rodauth.input_field_label_suffix}</label>
|
3
3
|
<div class="col-sm-3">
|
4
|
-
|
4
|
+
#{rodauth.input_field_string(rodauth.sms_code_param, 'sms-code', :value => '')}
|
5
5
|
</div>
|
6
6
|
</div>
|
data/templates/sms-setup.str
CHANGED
@@ -3,9 +3,9 @@
|
|
3
3
|
#{rodauth.csrf_tag}
|
4
4
|
#{rodauth.render('password-field') if rodauth.two_factor_modifications_require_password?}
|
5
5
|
<div class="form-group">
|
6
|
-
<label class="col-sm-2 control-label" for="sms-phone">#{rodauth.sms_phone_label}</label>
|
6
|
+
<label class="col-sm-2 control-label" for="sms-phone">#{rodauth.sms_phone_label}#{rodauth.input_field_label_suffix}</label>
|
7
7
|
<div class="col-sm-3">
|
8
|
-
|
8
|
+
#{rodauth.input_field_string(rodauth.sms_phone_param, 'sms-phone')}
|
9
9
|
</div>
|
10
10
|
</div>
|
11
11
|
#{rodauth.button(rodauth.sms_setup_button)}
|
@@ -2,6 +2,6 @@
|
|
2
2
|
#{rodauth.unlock_account_request_additional_form_tags}
|
3
3
|
#{rodauth.csrf_tag("#{rodauth.prefix}/#{rodauth.unlock_account_request_route}")}
|
4
4
|
<input type="hidden" name="#{rodauth.login_param}" value="#{h rodauth.param(rodauth.login_param)}"/>
|
5
|
-
|
5
|
+
#{rodauth.unlock_account_request_explanatory_text}
|
6
6
|
<input type="submit" class="btn btn-primary inline" value="#{rodauth.unlock_account_request_button}"/>
|
7
7
|
</form>
|
@@ -1,7 +1,7 @@
|
|
1
1
|
<form method="post" class="rodauth form-horizontal" role="form" id="unlock-account-form">
|
2
2
|
#{rodauth.unlock_account_additional_form_tags}
|
3
3
|
#{rodauth.csrf_tag}
|
4
|
-
|
4
|
+
#{rodauth.unlock_account_explanatory_text}
|
5
5
|
#{rodauth.render('password-field') if rodauth.unlock_account_requires_password?}
|
6
6
|
#{rodauth.button(rodauth.unlock_account_button)}
|
7
7
|
</form>
|
@@ -1,7 +1,7 @@
|
|
1
1
|
<form action="#{rodauth.prefix}/#{rodauth.verify_account_resend_route}" method="post" class="rodauth form-horizontal" role="form" id="verify-account-resend-form">
|
2
2
|
#{rodauth.verify_account_resend_additional_form_tags}
|
3
3
|
#{rodauth.csrf_tag("#{rodauth.prefix}/#{rodauth.verify_account_resend_route}")}
|
4
|
-
|
4
|
+
#{rodauth.verify_account_resend_explanatory_text}
|
5
5
|
#{(login = rodauth.param_or_nil(rodauth.login_param)) ? "<input type=\"hidden\" name=\"#{rodauth.login_param}\" value=\"#{h login}\"/>" : rodauth.render('login-field')}
|
6
6
|
#{rodauth.button(rodauth.verify_account_resend_button)}
|
7
7
|
</form>
|
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: 1.
|
4
|
+
version: 1.20.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:
|
11
|
+
date: 2019-06-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: sequel
|
@@ -229,6 +229,7 @@ extra_rdoc_files:
|
|
229
229
|
- doc/update_password_hash.rdoc
|
230
230
|
- doc/verify_account.rdoc
|
231
231
|
- doc/email_auth.rdoc
|
232
|
+
- doc/jwt_refresh.rdoc
|
232
233
|
- doc/verify_account_grace_period.rdoc
|
233
234
|
- doc/verify_login_change.rdoc
|
234
235
|
- doc/release_notes/1.17.0.txt
|
@@ -251,6 +252,7 @@ extra_rdoc_files:
|
|
251
252
|
- doc/release_notes/1.9.0.txt
|
252
253
|
- doc/release_notes/1.18.0.txt
|
253
254
|
- doc/release_notes/1.19.0.txt
|
255
|
+
- doc/release_notes/1.20.0.txt
|
254
256
|
files:
|
255
257
|
- CHANGELOG
|
256
258
|
- MIT-LICENSE
|
@@ -272,6 +274,7 @@ files:
|
|
272
274
|
- doc/http_basic_auth.rdoc
|
273
275
|
- doc/internals.rdoc
|
274
276
|
- doc/jwt.rdoc
|
277
|
+
- doc/jwt_refresh.rdoc
|
275
278
|
- doc/lockout.rdoc
|
276
279
|
- doc/login.rdoc
|
277
280
|
- doc/login_password_requirements_base.rdoc
|
@@ -294,6 +297,7 @@ files:
|
|
294
297
|
- doc/release_notes/1.18.0.txt
|
295
298
|
- doc/release_notes/1.19.0.txt
|
296
299
|
- doc/release_notes/1.2.0.txt
|
300
|
+
- doc/release_notes/1.20.0.txt
|
297
301
|
- doc/release_notes/1.3.0.txt
|
298
302
|
- doc/release_notes/1.4.0.txt
|
299
303
|
- doc/release_notes/1.5.0.txt
|
@@ -328,6 +332,7 @@ files:
|
|
328
332
|
- lib/rodauth/features/email_base.rb
|
329
333
|
- lib/rodauth/features/http_basic_auth.rb
|
330
334
|
- lib/rodauth/features/jwt.rb
|
335
|
+
- lib/rodauth/features/jwt_refresh.rb
|
331
336
|
- lib/rodauth/features/lockout.rb
|
332
337
|
- lib/rodauth/features/login.rb
|
333
338
|
- lib/rodauth/features/login_password_requirements_base.rb
|
@@ -362,6 +367,7 @@ files:
|
|
362
367
|
- spec/disallow_password_reuse_spec.rb
|
363
368
|
- spec/email_auth_spec.rb
|
364
369
|
- spec/http_basic_auth_spec.rb
|
370
|
+
- spec/jwt_refresh_spec.rb
|
365
371
|
- spec/jwt_spec.rb
|
366
372
|
- spec/lockout_spec.rb
|
367
373
|
- spec/login_spec.rb
|
@@ -432,7 +438,12 @@ files:
|
|
432
438
|
homepage: https://github.com/jeremyevans/rodauth
|
433
439
|
licenses:
|
434
440
|
- MIT
|
435
|
-
metadata:
|
441
|
+
metadata:
|
442
|
+
bug_tracker_uri: https://github.com/jeremyevans/rodauth/issues
|
443
|
+
changelog_uri: http://rodauth.jeremyevans.net/rdoc/files/CHANGELOG.html
|
444
|
+
documentation_uri: http://rodauth.jeremyevans.net/documentation.html
|
445
|
+
mailing_list_uri: https://groups.google.com/forum/#!forum/rodauth
|
446
|
+
source_code_uri: https://github.com/jeremyevans/rodauth
|
436
447
|
post_install_message:
|
437
448
|
rdoc_options:
|
438
449
|
- "--quiet"
|
@@ -455,8 +466,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
455
466
|
- !ruby/object:Gem::Version
|
456
467
|
version: '0'
|
457
468
|
requirements: []
|
458
|
-
|
459
|
-
rubygems_version: 2.7.6
|
469
|
+
rubygems_version: 3.0.3
|
460
470
|
signing_key:
|
461
471
|
specification_version: 4
|
462
472
|
summary: Authentication and Account Management Framework for Rack Applications
|