rodauth 2.5.0 → 2.10.0

Sign up to get free protection for your applications and to get access to all the features.
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