rodauth 2.5.0 → 2.10.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.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +42 -0
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +18 -6
  5. data/doc/argon2.rdoc +49 -0
  6. data/doc/base.rdoc +3 -2
  7. data/doc/guides/migrate_password_hash_algorithm.rdoc +15 -0
  8. data/doc/json.rdoc +47 -0
  9. data/doc/jwt.rdoc +1 -28
  10. data/doc/jwt_refresh.rdoc +8 -0
  11. data/doc/login_password_requirements_base.rdoc +1 -1
  12. data/doc/recovery_codes.rdoc +2 -1
  13. data/doc/release_notes/2.10.0.txt +47 -0
  14. data/doc/release_notes/2.6.0.txt +37 -0
  15. data/doc/release_notes/2.7.0.txt +33 -0
  16. data/doc/release_notes/2.8.0.txt +20 -0
  17. data/doc/release_notes/2.9.0.txt +21 -0
  18. data/doc/remember.rdoc +1 -1
  19. data/javascript/webauthn_auth.js +9 -9
  20. data/javascript/webauthn_setup.js +9 -6
  21. data/lib/rodauth.rb +14 -6
  22. data/lib/rodauth/features/argon2.rb +69 -0
  23. data/lib/rodauth/features/base.rb +12 -3
  24. data/lib/rodauth/features/confirm_password.rb +2 -2
  25. data/lib/rodauth/features/disallow_password_reuse.rb +20 -7
  26. data/lib/rodauth/features/json.rb +189 -0
  27. data/lib/rodauth/features/jwt.rb +22 -170
  28. data/lib/rodauth/features/jwt_refresh.rb +63 -13
  29. data/lib/rodauth/features/login_password_requirements_base.rb +4 -0
  30. data/lib/rodauth/features/otp.rb +0 -2
  31. data/lib/rodauth/features/recovery_codes.rb +22 -1
  32. data/lib/rodauth/features/remember.rb +6 -1
  33. data/lib/rodauth/features/update_password_hash.rb +1 -1
  34. data/lib/rodauth/features/verify_account.rb +6 -7
  35. data/lib/rodauth/features/webauthn_verify_account.rb +1 -1
  36. data/lib/rodauth/migrations.rb +31 -5
  37. data/lib/rodauth/version.rb +1 -1
  38. metadata +55 -24
@@ -132,11 +132,16 @@ module Rodauth
132
132
  opts = Hash[remember_cookie_options]
133
133
  opts[:value] = "#{account_id}_#{convert_token_key(remember_key_value)}"
134
134
  opts[:expires] = convert_timestamp(active_remember_key_ds.get(remember_deadline_column))
135
+ opts[:path] = "/" unless opts.key?(:path)
136
+ opts[:httponly] = true unless opts.key?(:httponly)
137
+ opts[:secure] = true unless opts.key?(:secure) || !request.ssl?
135
138
  ::Rack::Utils.set_cookie_header!(response.headers, remember_cookie_key, opts)
136
139
  end
137
140
 
138
141
  def forget_login
139
- ::Rack::Utils.delete_cookie_header!(response.headers, remember_cookie_key, remember_cookie_options)
142
+ opts = Hash[remember_cookie_options]
143
+ opts[:path] = "/" unless opts.key?(:path)
144
+ ::Rack::Utils.delete_cookie_header!(response.headers, remember_cookie_key, opts)
140
145
  end
141
146
 
142
147
  def get_remember_key
@@ -20,7 +20,7 @@ module Rodauth
20
20
 
21
21
  def get_password_hash
22
22
  if hash = super
23
- @current_password_hash_cost = hash.split('$')[2].to_i
23
+ @current_password_hash_cost = extract_password_hash_cost(hash)
24
24
  end
25
25
 
26
26
  hash
@@ -47,7 +47,6 @@ module Rodauth
47
47
  :get_verify_account_key,
48
48
  :get_verify_account_email_last_sent,
49
49
  :remove_verify_account_key,
50
- :resend_verify_account_view,
51
50
  :send_verify_account_email,
52
51
  :set_verify_account_email_last_sent,
53
52
  :verify_account,
@@ -245,6 +244,12 @@ module Rodauth
245
244
  end
246
245
  end
247
246
 
247
+ def setup_account_verification
248
+ generate_verify_account_key_value
249
+ create_verify_account_key
250
+ send_verify_account_email
251
+ end
252
+
248
253
  private
249
254
 
250
255
  def _login_form_footer_links
@@ -276,12 +281,6 @@ module Rodauth
276
281
  super
277
282
  end
278
283
 
279
- def setup_account_verification
280
- generate_verify_account_key_value
281
- create_verify_account_key
282
- send_verify_account_email
283
- end
284
-
285
284
  def verify_account_check_already_logged_in
286
285
  check_already_logged_in
287
286
  end
@@ -29,7 +29,7 @@ module Rodauth
29
29
 
30
30
  def before_verify_account
31
31
  super
32
- if features.include?(:jwt) && use_jwt? && !param_or_nil(webauthn_setup_param)
32
+ if features.include?(:json) && use_json? && !param_or_nil(webauthn_setup_param)
33
33
  cred = new_webauthn_credential
34
34
  json_response[webauthn_setup_param] = cred.as_json
35
35
  json_response[webauthn_setup_challenge_param] = cred.challenge
@@ -4,7 +4,8 @@ module Rodauth
4
4
  def self.create_database_authentication_functions(db, opts={})
5
5
  table_name = opts[:table_name] || :account_password_hashes
6
6
  get_salt_name = opts[:get_salt_name] || :rodauth_get_salt
7
- valid_hash_name = opts[:valid_hash_name] || :rodauth_valid_password_hash
7
+ valid_hash_name = opts[:valid_hash_name] || :rodauth_valid_password_hash
8
+ argon2 = opts[:argon2]
8
9
 
9
10
  case db.database_type
10
11
  when :postgres
@@ -14,12 +15,21 @@ module Rodauth
14
15
  when 'uuid' then :uuid
15
16
  else :int8
16
17
  end
18
+ table_name = db.literal(table_name) unless table_name.is_a?(String)
17
19
 
20
+ argon_sql = <<END
21
+ CASE
22
+ WHEN password_hash ~ '^\\$argon2id'
23
+ THEN substring(password_hash from '\\$argon2id\\$v=\\d+\\$m=\\d+,t=\\d+,p=\\d+\\$.+\\$')
24
+ ELSE substr(password_hash, 0, 30)
25
+ END INTO salt
26
+ END
18
27
  db.run <<END
19
28
  CREATE OR REPLACE FUNCTION #{get_salt_name}(acct_id #{primary_key_type}) RETURNS text AS $$
20
29
  DECLARE salt text;
21
30
  BEGIN
22
- SELECT substr(password_hash, 0, 30) INTO salt
31
+ SELECT
32
+ #{argon2 ? argon_sql : "substr(password_hash, 0, 30) INTO salt"}
23
33
  FROM #{table_name}
24
34
  WHERE acct_id = id;
25
35
  RETURN salt;
@@ -43,12 +53,20 @@ SECURITY DEFINER
43
53
  SET search_path = #{search_path};
44
54
  END
45
55
  when :mysql
56
+ argon_sql = <<END
57
+ CASE
58
+ WHEN password_hash REGEXP '^.argon2id'
59
+ THEN left(password_hash, CHAR_LENGTH(password_hash) - INSTR(REVERSE(password_hash), '$'))
60
+ ELSE substr(password_hash, 1, 30)
61
+ END
62
+ END
46
63
  db.run <<END
47
64
  CREATE FUNCTION #{get_salt_name}(acct_id int8) RETURNS varchar(255)
48
65
  SQL SECURITY DEFINER
49
66
  READS SQL DATA
50
67
  BEGIN
51
- RETURN (SELECT substr(password_hash, 1, 30)
68
+ RETURN (SELECT
69
+ #{argon2 ? argon_sql : "substr(password_hash, 1, 30)"}
52
70
  FROM #{table_name}
53
71
  WHERE acct_id = id);
54
72
  END;
@@ -71,13 +89,21 @@ RETURN valid;
71
89
  END;
72
90
  END
73
91
  when :mssql
92
+ argon_sql = <<END
93
+ CASE
94
+ WHEN password_hash LIKE '[$]argon2id%'
95
+ THEN left(password_hash, len(password_hash) - charindex('$', reverse(password_hash)))
96
+ ELSE substring(password_hash, 0, 30)
97
+ END
98
+ END
74
99
  db.run <<END
75
100
  CREATE FUNCTION #{get_salt_name}(@account_id bigint) RETURNS nvarchar(255)
76
101
  WITH EXECUTE AS OWNER
77
102
  AS
78
103
  BEGIN
79
104
  DECLARE @salt nvarchar(255);
80
- SELECT @salt = substring(password_hash, 0, 30)
105
+ SELECT @salt =
106
+ #{argon2 ? argon_sql : "substring(password_hash, 0, 30)"}
81
107
  FROM #{table_name}
82
108
  WHERE id = @account_id;
83
109
  RETURN @salt;
@@ -107,7 +133,7 @@ END
107
133
  def self.drop_database_authentication_functions(db, opts={})
108
134
  table_name = opts[:table_name] || :account_password_hashes
109
135
  get_salt_name = opts[:get_salt_name] || :rodauth_get_salt
110
- valid_hash_name = opts[:valid_hash_name] || :rodauth_valid_password_hash
136
+ valid_hash_name = opts[:valid_hash_name] || :rodauth_valid_password_hash
111
137
 
112
138
  case db.database_type
113
139
  when :postgres
@@ -6,7 +6,7 @@ module Rodauth
6
6
  MAJOR = 2
7
7
 
8
8
  # The minor version of Rodauth, updated for new feature releases of Rodauth.
9
- MINOR = 5
9
+ MINOR = 10
10
10
 
11
11
  # The patch version of Rodauth, updated only for bug fixes from the last
12
12
  # feature release.
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.5.0
4
+ version: 2.10.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: 2020-10-22 00:00:00.000000000 Z
11
+ date: 2021-02-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: sequel
@@ -80,6 +80,20 @@ dependencies:
80
80
  - - ">="
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: argon2
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '2'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '2'
83
97
  - !ruby/object:Gem::Dependency
84
98
  name: mail
85
99
  requirement: !ruby/object:Gem::Requirement
@@ -140,14 +154,14 @@ dependencies:
140
154
  name: webauthn
141
155
  requirement: !ruby/object:Gem::Requirement
142
156
  requirements:
143
- - - ">"
157
+ - - ">="
144
158
  - !ruby/object:Gem::Version
145
159
  version: '2'
146
160
  type: :development
147
161
  prerelease: false
148
162
  version_requirements: !ruby/object:Gem::Requirement
149
163
  requirements:
150
- - - ">"
164
+ - - ">="
151
165
  - !ruby/object:Gem::Version
152
166
  version: '2'
153
167
  - !ruby/object:Gem::Dependency
@@ -237,28 +251,35 @@ extra_rdoc_files:
237
251
  - README.rdoc
238
252
  - CHANGELOG
239
253
  - MIT-LICENSE
240
- - doc/change_password_notify.rdoc
241
254
  - doc/account_expiration.rdoc
255
+ - doc/active_sessions.rdoc
256
+ - doc/argon2.rdoc
257
+ - doc/audit_logging.rdoc
242
258
  - doc/base.rdoc
243
259
  - doc/change_login.rdoc
244
260
  - doc/change_password.rdoc
245
- - doc/confirm_password.rdoc
261
+ - doc/change_password_notify.rdoc
246
262
  - doc/close_account.rdoc
247
- - doc/http_basic_auth.rdoc
263
+ - doc/confirm_password.rdoc
248
264
  - doc/create_account.rdoc
249
- - doc/email_base.rdoc
250
265
  - doc/disallow_common_passwords.rdoc
251
266
  - doc/disallow_password_reuse.rdoc
252
- - doc/password_complexity.rdoc
267
+ - doc/email_auth.rdoc
268
+ - doc/email_base.rdoc
269
+ - doc/http_basic_auth.rdoc
270
+ - doc/json.rdoc
253
271
  - doc/jwt.rdoc
272
+ - doc/jwt_cors.rdoc
273
+ - doc/jwt_refresh.rdoc
254
274
  - doc/lockout.rdoc
255
275
  - doc/login.rdoc
276
+ - doc/login_password_requirements_base.rdoc
256
277
  - doc/logout.rdoc
257
278
  - doc/otp.rdoc
258
- - doc/login_password_requirements_base.rdoc
259
- - doc/jwt_cors.rdoc
279
+ - doc/password_complexity.rdoc
260
280
  - doc/password_expiration.rdoc
261
281
  - doc/password_grace_period.rdoc
282
+ - doc/password_pepper.rdoc
262
283
  - doc/recovery_codes.rdoc
263
284
  - doc/remember.rdoc
264
285
  - doc/reset_password.rdoc
@@ -268,17 +289,11 @@ extra_rdoc_files:
268
289
  - doc/two_factor_base.rdoc
269
290
  - doc/update_password_hash.rdoc
270
291
  - doc/verify_account.rdoc
271
- - doc/email_auth.rdoc
272
- - doc/jwt_refresh.rdoc
273
292
  - doc/verify_account_grace_period.rdoc
274
293
  - doc/verify_login_change.rdoc
275
294
  - doc/webauthn.rdoc
276
295
  - doc/webauthn_login.rdoc
277
296
  - doc/webauthn_verify_account.rdoc
278
- - doc/active_sessions.rdoc
279
- - doc/audit_logging.rdoc
280
- - doc/password_pepper.rdoc
281
- - doc/release_notes/1.17.0.txt
282
297
  - doc/release_notes/1.0.0.txt
283
298
  - doc/release_notes/1.1.0.txt
284
299
  - doc/release_notes/1.10.0.txt
@@ -288,7 +303,14 @@ extra_rdoc_files:
288
303
  - doc/release_notes/1.14.0.txt
289
304
  - doc/release_notes/1.15.0.txt
290
305
  - doc/release_notes/1.16.0.txt
306
+ - doc/release_notes/1.17.0.txt
307
+ - doc/release_notes/1.18.0.txt
308
+ - doc/release_notes/1.19.0.txt
291
309
  - doc/release_notes/1.2.0.txt
310
+ - doc/release_notes/1.20.0.txt
311
+ - doc/release_notes/1.21.0.txt
312
+ - doc/release_notes/1.22.0.txt
313
+ - doc/release_notes/1.23.0.txt
292
314
  - doc/release_notes/1.3.0.txt
293
315
  - doc/release_notes/1.4.0.txt
294
316
  - doc/release_notes/1.5.0.txt
@@ -296,18 +318,17 @@ extra_rdoc_files:
296
318
  - doc/release_notes/1.7.0.txt
297
319
  - doc/release_notes/1.8.0.txt
298
320
  - doc/release_notes/1.9.0.txt
299
- - doc/release_notes/1.18.0.txt
300
- - doc/release_notes/1.19.0.txt
301
- - doc/release_notes/1.20.0.txt
302
- - doc/release_notes/1.21.0.txt
303
- - doc/release_notes/1.22.0.txt
304
- - doc/release_notes/1.23.0.txt
305
321
  - doc/release_notes/2.0.0.txt
306
322
  - doc/release_notes/2.1.0.txt
323
+ - doc/release_notes/2.10.0.txt
307
324
  - doc/release_notes/2.2.0.txt
308
325
  - doc/release_notes/2.3.0.txt
309
326
  - doc/release_notes/2.4.0.txt
310
327
  - doc/release_notes/2.5.0.txt
328
+ - doc/release_notes/2.6.0.txt
329
+ - doc/release_notes/2.7.0.txt
330
+ - doc/release_notes/2.8.0.txt
331
+ - doc/release_notes/2.9.0.txt
311
332
  files:
312
333
  - CHANGELOG
313
334
  - MIT-LICENSE
@@ -315,6 +336,7 @@ files:
315
336
  - dict/top-10_000-passwords.txt
316
337
  - doc/account_expiration.rdoc
317
338
  - doc/active_sessions.rdoc
339
+ - doc/argon2.rdoc
318
340
  - doc/audit_logging.rdoc
319
341
  - doc/base.rdoc
320
342
  - doc/change_login.rdoc
@@ -337,6 +359,7 @@ files:
337
359
  - doc/guides/internals.rdoc
338
360
  - doc/guides/links.rdoc
339
361
  - doc/guides/login_return.rdoc
362
+ - doc/guides/migrate_password_hash_algorithm.rdoc
340
363
  - doc/guides/password_column.rdoc
341
364
  - doc/guides/password_confirmation.rdoc
342
365
  - doc/guides/password_requirements.rdoc
@@ -349,6 +372,7 @@ files:
349
372
  - doc/guides/status_column.rdoc
350
373
  - doc/guides/totp_or_recovery.rdoc
351
374
  - doc/http_basic_auth.rdoc
375
+ - doc/json.rdoc
352
376
  - doc/jwt.rdoc
353
377
  - doc/jwt_cors.rdoc
354
378
  - doc/jwt_refresh.rdoc
@@ -388,10 +412,15 @@ files:
388
412
  - doc/release_notes/1.9.0.txt
389
413
  - doc/release_notes/2.0.0.txt
390
414
  - doc/release_notes/2.1.0.txt
415
+ - doc/release_notes/2.10.0.txt
391
416
  - doc/release_notes/2.2.0.txt
392
417
  - doc/release_notes/2.3.0.txt
393
418
  - doc/release_notes/2.4.0.txt
394
419
  - doc/release_notes/2.5.0.txt
420
+ - doc/release_notes/2.6.0.txt
421
+ - doc/release_notes/2.7.0.txt
422
+ - doc/release_notes/2.8.0.txt
423
+ - doc/release_notes/2.9.0.txt
395
424
  - doc/remember.rdoc
396
425
  - doc/reset_password.rdoc
397
426
  - doc/session_expiration.rdoc
@@ -411,6 +440,7 @@ files:
411
440
  - lib/rodauth.rb
412
441
  - lib/rodauth/features/account_expiration.rb
413
442
  - lib/rodauth/features/active_sessions.rb
443
+ - lib/rodauth/features/argon2.rb
414
444
  - lib/rodauth/features/audit_logging.rb
415
445
  - lib/rodauth/features/base.rb
416
446
  - lib/rodauth/features/change_login.rb
@@ -424,6 +454,7 @@ files:
424
454
  - lib/rodauth/features/email_auth.rb
425
455
  - lib/rodauth/features/email_base.rb
426
456
  - lib/rodauth/features/http_basic_auth.rb
457
+ - lib/rodauth/features/json.rb
427
458
  - lib/rodauth/features/jwt.rb
428
459
  - lib/rodauth/features/jwt_cors.rb
429
460
  - lib/rodauth/features/jwt_refresh.rb
@@ -535,7 +566,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
535
566
  - !ruby/object:Gem::Version
536
567
  version: '0'
537
568
  requirements: []
538
- rubygems_version: 3.1.4
569
+ rubygems_version: 3.2.3
539
570
  signing_key:
540
571
  specification_version: 4
541
572
  summary: Authentication and Account Management Framework for Rack Applications