rodauth 1.6.0 → 1.7.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8be62d375631a0d62337cc9da83782e1a765ecc1
4
- data.tar.gz: e5cc52f5bec8e0f7820b1b16ac11d96d385e0187
3
+ metadata.gz: 72d21867a8a5d725cfe2331b979ffbe31f3e9e9a
4
+ data.tar.gz: b204b666ab3b52ab94c291a660af0c6f6741772b
5
5
  SHA512:
6
- metadata.gz: cd373d957b4b636afab06b24a7c782c9b3e605de844f0083c7eb2953779715dc4fec20418984ef4cdbce93d9f65e4848eed11a8318985d52d03ecdb9b2f1301f
7
- data.tar.gz: d156aaad0e89d164a467e44c946088f28487db41a4b0cb1ec57dda6584ca36ffbb8c87daf02bcc868dcfe8322bf56fc4fa005ab9fdfd2cd0b8620bce6334d593
6
+ metadata.gz: 6e7ec902dd360cf3687097e3c8934687f8915f277334270b2acbf3a02e33314e83cb42631ae3539d8edfaa87dc50aaebeef5b184f0fdc601c1d0c8ee196156be
7
+ data.tar.gz: 49de39a38e7cb00f6869c4c0bc25f7df521f541615373d21530d802b5d390924a178b86274620ed6b08517157bd704eaad1dc5c7847e9ee2ef5df1d2ae25ac44
data/CHANGELOG CHANGED
@@ -1,3 +1,7 @@
1
+ === 1.7.0 (2016-11-22)
2
+
3
+ * Make reset password, unlock account, and verify account pages not leak keys to external servers via Referer header (jeremyevans)
4
+
1
5
  === 1.6.0 (2016-10-24)
2
6
 
3
7
  * Add http_basic_auth feature (TiagoCardoso1983, jeremyevans) (#12)
@@ -161,9 +161,10 @@ Example:
161
161
  psql -U postgres -c "CREATE EXTENSION citext" ${DATABASE_NAME}
162
162
 
163
163
  Note that on Heroku, this extension can be loaded using a standard database
164
- account. If you don't want to support case sensitive logins, you don't
165
- need to use the PostgreSQL citext extension. Just remember to modify the
166
- migration below to use +String+ instead of +citext+ for the email.
164
+ account. If you want logins to be case sensitive (generally considered a
165
+ bad idea), you don't need to use the PostgreSQL citext extension. Just
166
+ remember to modify the migration below to use +String+ instead of +citext+
167
+ for the email in that case.
167
168
 
168
169
  === Create database accounts
169
170
 
data/Rakefile CHANGED
@@ -61,9 +61,10 @@ end
61
61
 
62
62
  desc "Run specs with -w, some warnings filtered"
63
63
  task "spec_w" do
64
- ENV['RUBYOPT'] ? (ENV['RUBYOPT'] += " -w") : (ENV['RUBYOPT'] = '-w')
65
- rake = ENV['RAKE'] || "#{FileUtils::RUBY} -S rake"
66
- sh %{#{rake} 2>&1 | egrep -v \": warning: instance variable @.* not initialized|: warning: method redefined; discarding old|: warning: previous definition of|: warning: statement not reached"}
64
+ rubyopt = ENV['RUBYOPT']
65
+ ENV['RUBYOPT'] = "#{rubyopt} -w"
66
+ spec.call('WARNING'=>'1')
67
+ ENV['RUBYOPT'] = rubyopt
67
68
  end
68
69
 
69
70
  desc "Setup database used for testing on PostgreSQL"
@@ -51,6 +51,7 @@ unlock_account_requires_password? :: Whether a password is required when unlocki
51
51
  false by default. May want to set to true if not
52
52
  allowing password resets.
53
53
  unlock_account_route :: Alias for lockout_route.
54
+ unlock_account_session_key :: The key in the session to hold the unlock account key temporarily.
54
55
 
55
56
  == Auth Methods
56
57
 
@@ -0,0 +1,6 @@
1
+ = Improvements
2
+
3
+ * The reset password, unlock account, and verify account features now
4
+ temporarily store the feature-specific keys in the session instead
5
+ of keeping them as parameters, which avoids leaking the keys to
6
+ asset hosts or other external servers via the HTTP Referer header.
@@ -40,6 +40,7 @@ reset_password_request_error_flash :: The flash error to show if not able to sen
40
40
  password email.
41
41
  reset_password_request_route :: The route to the reset password request action.
42
42
  reset_password_route :: The route to the reset password action.
43
+ reset_password_session_key :: The key in the session to hold the reset password key temporarily.
43
44
  reset_password_table :: The name of the reset password keys table.
44
45
 
45
46
  == Auth Methods
@@ -40,6 +40,7 @@ verify_account_resend_error_flash :: The flash error to show if unable to resend
40
40
  verify account email.
41
41
  verify_account_resend_route :: The route to the verify account resend action.
42
42
  verify_account_route :: The route to the verify account action.
43
+ verify_account_session_key :: The key in the session to hold the verify account key temporarily.
43
44
  verify_account_table :: The name of the verify account keys table.
44
45
 
45
46
  == Auth Methods
@@ -43,7 +43,6 @@ module Rodauth
43
43
  private
44
44
 
45
45
  def password_doesnt_match_previous_password?(password)
46
- id = account_id
47
46
  match = if use_database_authentication_functions?
48
47
  salts = previous_password_ds.
49
48
  select_map([previous_password_id_column, Sequel.function(function_name(:rodauth_get_previous_salt), previous_password_id_column).as(:salt)])
@@ -35,6 +35,7 @@ module Rodauth
35
35
  auth_value_method :unlock_account_email_subject, 'Unlock Account'
36
36
  auth_value_method :unlock_account_key_param, 'key'
37
37
  auth_value_method :unlock_account_requires_password?, false
38
+ auth_value_method :unlock_account_session_key, :unlock_account_key
38
39
 
39
40
  auth_value_methods(
40
41
  :unlock_account_redirect,
@@ -81,16 +82,24 @@ module Rodauth
81
82
  before_unlock_account_route
82
83
 
83
84
  r.get do
84
- if account_from_unlock_key(param(unlock_account_key_param))
85
- unlock_account_view
86
- else
87
- set_redirect_error_flash no_matching_unlock_account_key_message
88
- redirect require_login_redirect
85
+ if key = param_or_nil(unlock_account_key_param)
86
+ session[unlock_account_session_key] = key
87
+ redirect(r.path)
88
+ end
89
+
90
+ if key = session[unlock_account_session_key]
91
+ if account_from_unlock_key(key)
92
+ unlock_account_view
93
+ else
94
+ session[unlock_account_session_key] = nil
95
+ set_redirect_error_flash no_matching_unlock_account_key_message
96
+ redirect require_login_redirect
97
+ end
89
98
  end
90
99
  end
91
100
 
92
101
  r.post do
93
- key = param(unlock_account_key_param)
102
+ key = session[unlock_account_session_key] || param(unlock_account_key_param)
94
103
  unless account_from_unlock_key(key)
95
104
  set_redirect_error_flash no_matching_unlock_account_key_message
96
105
  redirect unlock_account_request_redirect
@@ -106,6 +115,7 @@ module Rodauth
106
115
  end
107
116
  end
108
117
 
118
+ session[unlock_account_session_key] = nil
109
119
  set_notice_flash unlock_account_notice_flash
110
120
  redirect unlock_account_redirect
111
121
  else
@@ -31,7 +31,7 @@ module Rodauth
31
31
  super
32
32
  return if singleton_methods.map(&:to_sym).include?(:password_dictionary)
33
33
 
34
- case dictionary_file = password_dictionary_file
34
+ case password_dictionary_file
35
35
  when false
36
36
  return
37
37
  when nil
@@ -29,6 +29,7 @@ module Rodauth
29
29
  auth_value_method :reset_password_table, :account_password_reset_keys
30
30
  auth_value_method :reset_password_id_column, :id
31
31
  auth_value_method :reset_password_key_column, :key
32
+ auth_value_method :reset_password_session_key, :reset_password_key
32
33
 
33
34
  auth_value_methods :reset_password_email_sent_redirect
34
35
 
@@ -76,9 +77,15 @@ module Rodauth
76
77
 
77
78
  r.get do
78
79
  if key = param_or_nil(reset_password_key_param)
80
+ session[reset_password_session_key] = key
81
+ redirect(r.path)
82
+ end
83
+
84
+ if key = session[reset_password_session_key]
79
85
  if account_from_reset_password_key(key)
80
86
  reset_password_view
81
87
  else
88
+ session[reset_password_session_key] = nil
82
89
  set_redirect_error_flash no_matching_reset_password_key_message
83
90
  redirect require_login_redirect
84
91
  end
@@ -86,7 +93,7 @@ module Rodauth
86
93
  end
87
94
 
88
95
  r.post do
89
- key = param(reset_password_key_param)
96
+ key = session[reset_password_session_key] || param(reset_password_key_param)
90
97
  unless account_from_reset_password_key(key)
91
98
  set_redirect_error_flash reset_password_error_flash
92
99
  redirect reset_password_email_sent_redirect
@@ -117,6 +124,7 @@ module Rodauth
117
124
  update_session
118
125
  end
119
126
 
127
+ session[reset_password_session_key] = nil
120
128
  set_notice_flash reset_password_notice_flash
121
129
  redirect reset_password_redirect
122
130
  end
@@ -30,6 +30,7 @@ module Rodauth
30
30
  auth_value_method :verify_account_table, :account_verification_keys
31
31
  auth_value_method :verify_account_id_column, :id
32
32
  auth_value_method :verify_account_key_column, :key
33
+ auth_value_method :verify_account_session_key, :verify_account_key
33
34
 
34
35
  auth_value_methods :verify_account_key_value
35
36
 
@@ -76,9 +77,15 @@ module Rodauth
76
77
 
77
78
  r.get do
78
79
  if key = param_or_nil(verify_account_key_param)
80
+ session[verify_account_session_key] = key
81
+ redirect(r.path)
82
+ end
83
+
84
+ if key = session[verify_account_session_key]
79
85
  if account_from_verify_account_key(key)
80
86
  verify_account_view
81
87
  else
88
+ session[verify_account_session_key] = nil
82
89
  set_redirect_error_flash no_matching_verify_account_key_message
83
90
  redirect require_login_redirect
84
91
  end
@@ -86,7 +93,7 @@ module Rodauth
86
93
  end
87
94
 
88
95
  r.post do
89
- key = param(verify_account_key_param)
96
+ key = session[verify_account_session_key] || param(verify_account_key_param)
90
97
  unless account_from_verify_account_key(key)
91
98
  set_redirect_error_flash verify_account_error_flash
92
99
  redirect verify_account_redirect
@@ -103,6 +110,7 @@ module Rodauth
103
110
  update_session
104
111
  end
105
112
 
113
+ session[verify_account_session_key] = nil
106
114
  set_notice_flash verify_account_notice_flash
107
115
  redirect verify_account_redirect
108
116
  end
@@ -1,7 +1,7 @@
1
1
  # frozen-string-literal: true
2
2
 
3
3
  module Rodauth
4
- VERSION = '1.6.0'.freeze
4
+ VERSION = '1.7.0'.freeze
5
5
 
6
6
  def self.version
7
7
  VERSION
@@ -48,7 +48,9 @@ describe 'Rodauth password complexity feature' do
48
48
  it "should support default dictionary" do
49
49
  default_dictionary = '/usr/share/dict/words'
50
50
  skip("#{default_dictionary} not present") unless File.file?(default_dictionary)
51
- password = File.read(default_dictionary).split.sort_by{|w| w.length}.last
51
+ pass = File.read(default_dictionary).split.sort_by{|w| w.length}.last
52
+ skip("#{default_dictionary} empty") unless pass
53
+ pass = pass.downcase.gsub(/[^a-z]/, '')
52
54
 
53
55
  rodauth do
54
56
  enable :login, :change_password, :password_complexity
@@ -78,7 +80,6 @@ describe 'Rodauth password complexity feature' do
78
80
  it "should support no dictionary" do
79
81
  default_dictionary = '/usr/share/dict/words'
80
82
  skip("#{default_dictionary} not present") unless File.file?(default_dictionary)
81
- password = File.read(default_dictionary).split.sort_by{|w| w.length}.last
82
83
 
83
84
  rodauth do
84
85
  enable :login, :change_password, :password_complexity
@@ -113,7 +113,7 @@ describe 'Rodauth reset_password feature' do
113
113
 
114
114
  login(:pass=>'01234567')
115
115
  click_button 'Request Password Reset'
116
- link = email_link(/(\/reset-password\?key=.+)$/)
116
+ email_link(/(\/reset-password\?key=.+)$/)
117
117
 
118
118
  login
119
119
 
@@ -187,7 +187,6 @@ describe 'Rodauth' do
187
187
  end
188
188
 
189
189
  it "should support account_select setting for choosing account columns" do
190
- warning = nil
191
190
  rodauth do
192
191
  enable :login
193
192
  account_select [:id, :email]
@@ -1,5 +1,12 @@
1
1
  $: << 'lib'
2
2
 
3
+ if ENV['WARNING']
4
+ require 'warning'
5
+ Warning.ignore([:missing_ivar, :missing_gvar, :fixnum])
6
+ #Warning.ignore(/warning: URI\.escape is obsolete\n\z/)
7
+ Warning.ignore(:method_redefined, File.dirname(File.dirname(__FILE__)))
8
+ end
9
+
3
10
  if ENV['COVERAGE']
4
11
  require 'coverage'
5
12
  require 'simplecov'
@@ -1,6 +1,5 @@
1
1
  <form method="post" class="rodauth form-horizontal" role="form" id="reset-password-form">
2
2
  #{rodauth.reset_password_additional_form_tags}
3
- <input type="hidden" name="#{rodauth.reset_password_key_param}" value="#{h request[rodauth.reset_password_key_param]}" />
4
3
  #{rodauth.csrf_tag}
5
4
  #{rodauth.render('password-field')}
6
5
  #{rodauth.render('password-confirm-field') if rodauth.require_password_confirmation?}
@@ -1,7 +1,6 @@
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
- <input type="hidden" name="#{rodauth.unlock_account_key_param}" value="#{h request[rodauth.unlock_account_key_param]}"/>
5
4
  <p>This account is currently locked out. You can unlock the account.</p>
6
5
  #{rodauth.render('password-field') if rodauth.unlock_account_requires_password?}
7
6
  #{rodauth.button(rodauth.unlock_account_button)}
@@ -1,6 +1,5 @@
1
1
  <form method="post" class="rodauth form-horizontal" role="form" id="verify-account-form">
2
2
  #{rodauth.verify_account_additional_form_tags}
3
- <input type="hidden" name="#{rodauth.verify_account_key_param}" value="#{h request[rodauth.verify_account_key_param]}" />
4
3
  #{rodauth.csrf_tag}
5
4
  #{rodauth.button(rodauth.verify_account_button)}
6
5
  </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.6.0
4
+ version: 1.7.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: 2016-10-24 00:00:00.000000000 Z
11
+ date: 2016-11-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: sequel
@@ -233,6 +233,7 @@ extra_rdoc_files:
233
233
  - doc/release_notes/1.4.0.txt
234
234
  - doc/release_notes/1.5.0.txt
235
235
  - doc/release_notes/1.6.0.txt
236
+ - doc/release_notes/1.7.0.txt
236
237
  files:
237
238
  - CHANGELOG
238
239
  - MIT-LICENSE
@@ -265,6 +266,7 @@ files:
265
266
  - doc/release_notes/1.4.0.txt
266
267
  - doc/release_notes/1.5.0.txt
267
268
  - doc/release_notes/1.6.0.txt
269
+ - doc/release_notes/1.7.0.txt
268
270
  - doc/remember.rdoc
269
271
  - doc/reset_password.rdoc
270
272
  - doc/session_expiration.rdoc
@@ -404,7 +406,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
404
406
  version: '0'
405
407
  requirements: []
406
408
  rubyforge_project:
407
- rubygems_version: 2.6.6
409
+ rubygems_version: 2.6.8
408
410
  signing_key:
409
411
  specification_version: 4
410
412
  summary: Authentication and Account Management Framework for Rack Applications