module Rodauth

  1. lib/rodauth.rb
  2. lib/rodauth/features/account_expiration.rb
  3. lib/rodauth/features/active_sessions.rb
  4. lib/rodauth/features/argon2.rb
  5. lib/rodauth/features/audit_logging.rb
  6. lib/rodauth/features/base.rb
  7. lib/rodauth/features/change_login.rb
  8. lib/rodauth/features/change_password.rb
  9. lib/rodauth/features/change_password_notify.rb
  10. lib/rodauth/features/close_account.rb
  11. lib/rodauth/features/confirm_password.rb
  12. lib/rodauth/features/create_account.rb
  13. lib/rodauth/features/disallow_common_passwords.rb
  14. lib/rodauth/features/disallow_password_reuse.rb
  15. lib/rodauth/features/email_auth.rb
  16. lib/rodauth/features/email_base.rb
  17. lib/rodauth/features/http_basic_auth.rb
  18. lib/rodauth/features/internal_request.rb
  19. lib/rodauth/features/json.rb
  20. lib/rodauth/features/jwt.rb
  21. lib/rodauth/features/jwt_cors.rb
  22. lib/rodauth/features/jwt_refresh.rb
  23. lib/rodauth/features/lockout.rb
  24. lib/rodauth/features/login.rb
  25. lib/rodauth/features/login_password_requirements_base.rb
  26. lib/rodauth/features/logout.rb
  27. lib/rodauth/features/otp.rb
  28. lib/rodauth/features/password_complexity.rb
  29. lib/rodauth/features/password_expiration.rb
  30. lib/rodauth/features/password_grace_period.rb
  31. lib/rodauth/features/password_pepper.rb
  32. lib/rodauth/features/path_class_methods.rb
  33. lib/rodauth/features/recovery_codes.rb
  34. lib/rodauth/features/remember.rb
  35. lib/rodauth/features/reset_password.rb
  36. lib/rodauth/features/reset_password_notify.rb
  37. lib/rodauth/features/session_expiration.rb
  38. lib/rodauth/features/single_session.rb
  39. lib/rodauth/features/sms_codes.rb
  40. lib/rodauth/features/two_factor_base.rb
  41. lib/rodauth/features/update_password_hash.rb
  42. lib/rodauth/features/verify_account.rb
  43. lib/rodauth/features/verify_account_grace_period.rb
  44. lib/rodauth/features/verify_login_change.rb
  45. lib/rodauth/features/webauthn.rb
  46. lib/rodauth/features/webauthn_login.rb
  47. lib/rodauth/features/webauthn_verify_account.rb
  48. lib/rodauth/migrations.rb
  49. lib/rodauth/version.rb
  50. show all

:nocov:

Methods

Public Class

  1. configure
  2. create_database_authentication_functions
  3. create_database_previous_password_check_functions
  4. drop_database_authentication_functions
  5. drop_database_previous_password_check_functions
  6. lib
  7. load_dependencies
  8. new
  9. version

Public Instance

  1. _account_from_email_auth_key
  2. _account_from_login
  3. _account_from_refresh_token
  4. _account_from_reset_password_key
  5. _account_from_session
  6. _account_from_unlock_key
  7. _account_from_verify_account_key
  8. _account_from_verify_login_change_key
  9. _account_refresh_token_split
  10. _around_rodauth
  11. _email_auth_request
  12. _email_auth_request_and_redirect
  13. _field_attributes
  14. _field_error_attributes
  15. _filter_links
  16. _formatted_field_error
  17. _get_remember_cookie
  18. _json_response_body
  19. _jwt_decode_opts
  20. _login
  21. _login_form_footer
  22. _login_form_footer_links
  23. _multi_phase_login_forms
  24. _new_account
  25. _otp
  26. _otp_add_key
  27. _otp_key
  28. _otp_tmp_key
  29. _recovery_codes
  30. _return_json_response
  31. _setup_account_lockouts_hash
  32. _sms
  33. _template_opts
  34. _two_factor_auth_links
  35. _two_factor_remove_all_from_session
  36. _two_factor_remove_links
  37. _two_factor_setup_links
  38. _update_login
  39. _view
  40. _view_opts
  41. account!
  42. account_activity_ds
  43. account_ds
  44. account_expired?
  45. account_expired_at
  46. account_from_email_auth_key
  47. account_from_key
  48. account_from_login
  49. account_from_refresh_token
  50. account_from_remember_cookie
  51. account_from_reset_password_key
  52. account_from_session
  53. account_from_unlock_key
  54. account_from_verify_account_key
  55. account_from_verify_login_change_key
  56. account_id
  57. account_in_unverified_grace_period?
  58. account_initial_status_value
  59. account_lockouts_ds
  60. account_login_failures_ds
  61. account_password_hash_column
  62. account_session_status_filter
  63. account_table_ds
  64. account_webauthn_ids
  65. account_webauthn_usage
  66. account_webauthn_user_id
  67. active_remember_key_ds
  68. active_sessions_ds
  69. active_sessions_insert_hash
  70. active_sessions_update_hash
  71. add_active_session
  72. add_audit_log
  73. add_field_error_class
  74. add_previous_password_hash
  75. add_recovery_code
  76. add_recovery_codes
  77. add_remember_key
  78. add_webauthn_credential
  79. after_change_password
  80. after_close_account
  81. after_create_account
  82. after_login
  83. after_login_entered_during_multi_phase_login
  84. after_login_failure
  85. after_logout
  86. after_otp_disable
  87. after_refresh_token
  88. after_reset_password
  89. after_sms_disable
  90. after_webauthn_remove
  91. allow_email_auth?
  92. allow_resending_verify_account_email?
  93. already_logged_in
  94. argon2_hash_algorithm?
  95. argon2_hash_cost
  96. argon2_password_hash_match?
  97. argon2_salt_option
  98. audit_log_ds
  99. audit_log_insert_hash
  100. audit_log_message
  101. audit_log_message_default
  102. audit_log_metadata
  103. auth_class_eval
  104. authenticated?
  105. authenticated_by
  106. authenticated_webauthn_id
  107. auto_add_missing_recovery_codes
  108. auto_remove_recovery_codes
  109. autocomplete_for_field?
  110. autologin_session
  111. autologin_type
  112. base32_encode
  113. base_url
  114. before_change_login_route
  115. before_change_password_route
  116. before_create_account_route
  117. before_login_attempt
  118. before_logout
  119. before_otp_setup_route
  120. before_reset_password
  121. before_reset_password_request
  122. before_rodauth
  123. before_two_factor_auth_route
  124. before_two_factor_manage_route
  125. before_unlock_account
  126. before_unlock_account_request
  127. before_verify_account
  128. before_verify_account_route
  129. before_view_recovery_codes
  130. before_webauthn_auth_route
  131. before_webauthn_login_route
  132. before_webauthn_remove_route
  133. before_webauthn_setup_route
  134. button
  135. button_opts
  136. can_add_recovery_codes?
  137. catch_error
  138. change_login
  139. change_login_notice_flash
  140. change_login_requires_password?
  141. change_password_requires_password?
  142. check_account_expiration
  143. check_active_session
  144. check_already_logged_in
  145. check_csrf
  146. check_csrf?
  147. check_password_change_allowed
  148. check_session_expiration
  149. check_single_session
  150. clear_cached_otp
  151. clear_invalid_login_attempts
  152. clear_session
  153. close_account
  154. close_account_requires_password?
  155. compute_hmac
  156. compute_raw_hmac
  157. confirm_password
  158. confirm_password_redirect
  159. convert_email_token_key
  160. convert_session_key
  161. convert_timestamp
  162. convert_token_id
  163. convert_token_id_to_integer
  164. convert_token_key
  165. create_account_autologin?
  166. create_account_notice_flash
  167. create_account_set_password?
  168. create_email
  169. create_email_auth_key
  170. create_email_to
  171. create_reset_password_key
  172. create_verify_account_key
  173. create_verify_login_change_email
  174. create_verify_login_change_key
  175. csrf_tag
  176. currently_active_session?
  177. database_function_password_match?
  178. db
  179. delete_account
  180. delete_account_on_close?
  181. disable_remember_login
  182. domain
  183. email_auth_ds
  184. email_auth_email_link
  185. email_auth_email_recently_sent?
  186. email_auth_key_insert_hash
  187. email_auth_request_form
  188. email_from
  189. email_to
  190. expire_session
  191. extend_remember_deadline
  192. extend_remember_deadline_while_logged_in?
  193. extract_password_hash_cost
  194. features
  195. field_attributes
  196. field_error
  197. field_error_attributes
  198. flash
  199. forget_login
  200. formatted_field_error
  201. function_name
  202. generate_active_sessions_key
  203. generate_email_auth_key_value
  204. generate_refresh_token
  205. generate_remember_key_value
  206. generate_reset_password_key_value
  207. generate_unlock_account_key
  208. generate_verify_account_key_value
  209. generate_verify_login_change_key_value
  210. get_active_refresh_token
  211. get_activity_timestamp
  212. get_email_auth_email_last_sent
  213. get_email_auth_key
  214. get_password_changed_at
  215. get_password_hash
  216. get_password_reset_key
  217. get_remember_key
  218. get_reset_password_email_last_sent
  219. get_unlock_account_email_last_sent
  220. get_unlock_account_key
  221. get_verify_account_email_last_sent
  222. get_verify_account_key
  223. get_verify_login_change_login_and_key
  224. handle_duplicate_active_session_id
  225. handle_webauthn_sign_count_verification_error
  226. has_password?
  227. hook_action
  228. http_basic_auth
  229. inactive_session_cond
  230. include_success_messages?
  231. input_field_string
  232. inputmode_for_field?
  233. internal_request?
  234. internal_request_configuration
  235. invalid_login_attempted
  236. invalid_previous_password_message
  237. json_request?
  238. json_response
  239. jwt_cors_allow?
  240. jwt_payload
  241. jwt_refresh_token_account_ds
  242. jwt_refresh_token_account_token_ds
  243. jwt_refresh_token_ds
  244. jwt_refresh_token_insert_hash
  245. jwt_refresh_token_match?
  246. jwt_secret
  247. jwt_session_hash
  248. jwt_token
  249. last_account_activity_at
  250. last_account_login_at
  251. load_memory
  252. loaded_templates
  253. locked_out?
  254. logged_in_via_remember_key?
  255. login
  256. login_confirm_label
  257. login_does_not_meet_requirements_message
  258. login_failed_reset_password_request_form
  259. login_form_footer_links
  260. login_hidden_field
  261. login_input_type
  262. login_meets_email_requirements?
  263. login_meets_length_requirements?
  264. login_meets_requirements?
  265. login_required
  266. login_return_to_requested_location_path
  267. login_session
  268. login_too_long_message
  269. login_too_many_bytes_message
  270. login_too_short_message
  271. login_uses_email?
  272. login_valid_email?
  273. logout
  274. logout_additional_form_tags
  275. modifications_require_password?
  276. new_account
  277. new_recovery_code
  278. new_webauthn_credential
  279. no_longer_active_session
  280. normalize_session_or_flash_key
  281. null_byte_parameter_value
  282. only_json?
  283. open_account?
  284. otp_add_key
  285. otp_available?
  286. otp_exists?
  287. otp_hmac_secret
  288. otp_issuer
  289. otp_key_ds
  290. otp_keys_use_hmac?
  291. otp_last_use
  292. otp_locked_out?
  293. otp_new_secret
  294. otp_provisioning_name
  295. otp_provisioning_uri
  296. otp_qr_code
  297. otp_record_authentication_failure
  298. otp_remove
  299. otp_remove_auth_failures
  300. otp_tmp_key
  301. otp_update_last_use
  302. otp_user_key
  303. otp_valid_code?
  304. otp_valid_key?
  305. over_max_bytesize_param_value
  306. param
  307. param_or_nil
  308. password_confirm_label
  309. password_does_not_contain_null_byte?
  310. password_does_not_meet_requirements_message
  311. password_doesnt_match_previous_password?
  312. password_expiration_ds
  313. password_expired?
  314. password_field_autocomplete_value
  315. password_has_enough_character_groups?
  316. password_has_no_invalid_pattern?
  317. password_hash
  318. password_hash_cost
  319. password_hash_ds
  320. password_hash_match?
  321. password_hash_using_salt
  322. password_match?
  323. password_meets_length_requirements?
  324. password_meets_requirements?
  325. password_not_in_dictionary?
  326. password_not_one_of_the_most_common?
  327. password_not_too_many_repeating_characters?
  328. password_one_of_most_common?
  329. password_recently_entered?
  330. password_reset_ds
  331. password_too_long_message
  332. password_too_many_bytes_message
  333. password_too_short_message
  334. possible_authentication_methods
  335. post_configure
  336. previous_password_ds
  337. raises_uniqueness_violation?
  338. random_key
  339. raw_param
  340. recovery_code_match?
  341. recovery_codes_available?
  342. recovery_codes_ds
  343. recovery_codes_primary?
  344. recovery_codes_remove
  345. redirect
  346. redirect_two_factor_authenticated
  347. remember_key_ds
  348. remember_login
  349. remembered_session_id
  350. remove_active_session
  351. remove_all_active_sessions
  352. remove_all_webauthn_keys_and_user_ids
  353. remove_current_session
  354. remove_email_auth_key
  355. remove_inactive_sessions
  356. remove_jwt_refresh_token_key
  357. remove_lockout_metadata
  358. remove_remember_key
  359. remove_reset_password_key
  360. remove_session_value
  361. remove_verify_account_key
  362. remove_verify_login_change_key
  363. remove_webauthn_key
  364. render
  365. render_multi_phase_login_forms
  366. request
  367. require_account
  368. require_account_session
  369. require_authentication
  370. require_current_password
  371. require_http_basic_auth
  372. require_login
  373. require_login_confirmation?
  374. require_otp_setup
  375. require_password_authentication
  376. require_password_authentication?
  377. require_sms_available
  378. require_sms_not_setup
  379. require_sms_setup
  380. require_two_factor_authenticated
  381. require_two_factor_not_authenticated
  382. require_two_factor_setup
  383. require_webauthn_setup
  384. rescue_jwt_payload
  385. reset_password_email_link
  386. reset_password_email_recently_sent?
  387. reset_password_key_insert_hash
  388. reset_single_session_key
  389. response
  390. retry_on_uniqueness_violation
  391. return_json_response
  392. return_response
  393. route!
  394. route_path
  395. route_url
  396. save_account
  397. send_email
  398. send_verify_login_change_email
  399. serialize_audit_log_metadata
  400. session
  401. session_inactivity_deadline_condition
  402. session_jwt
  403. session_lifetime_deadline_condition
  404. session_value
  405. set_deadline_value
  406. set_deadline_values?
  407. set_email_auth_email_last_sent
  408. set_error_flash
  409. set_error_reason
  410. set_expired
  411. set_field_error
  412. set_http_basic_auth_error_response
  413. set_jwt
  414. set_jwt_refresh_token_hmac_session_key
  415. set_jwt_token
  416. set_last_password_entry
  417. set_login_requirement_error_message
  418. set_new_account_password
  419. set_notice_flash
  420. set_notice_now_flash
  421. set_password
  422. set_password_requirement_error_message
  423. set_redirect_error_flash
  424. set_redirect_error_status
  425. set_remember_cookie
  426. set_reset_password_email_last_sent
  427. set_response_error_reason_status
  428. set_response_error_status
  429. set_session_value
  430. set_single_session_key
  431. set_title
  432. set_unlock_account_email_last_sent
  433. set_verify_account_email_last_sent
  434. setup_account_verification
  435. show_lockout_page
  436. single_session_ds
  437. skip_login_field_on_login?
  438. skip_password_field_on_login?
  439. skip_status_checks?
  440. sms_auth_message
  441. sms_available?
  442. sms_code
  443. sms_code_issued_at
  444. sms_code_match?
  445. sms_codes_primary?
  446. sms_confirm
  447. sms_confirm_failure
  448. sms_confirm_message
  449. sms_confirmation_match?
  450. sms_current_auth?
  451. sms_disable
  452. sms_ds
  453. sms_failures
  454. sms_locked_out?
  455. sms_needs_confirmation?
  456. sms_new_auth_code
  457. sms_new_confirm_code
  458. sms_normalize_phone
  459. sms_phone
  460. sms_record_failure
  461. sms_remove_failures
  462. sms_send
  463. sms_send_auth_code
  464. sms_send_confirm_code
  465. sms_set_code
  466. sms_setup
  467. sms_setup?
  468. sms_valid_phone?
  469. split_token
  470. template_path
  471. throw_basic_auth_error
  472. throw_error
  473. throw_error_reason
  474. throw_error_status
  475. timing_safe_eql?
  476. token_link
  477. token_param_value
  478. transaction
  479. translate
  480. two_factor_auth_links
  481. two_factor_authenticate
  482. two_factor_authenticated?
  483. two_factor_authentication_setup?
  484. two_factor_login_type_match?
  485. two_factor_modifications_require_password?
  486. two_factor_password_match?
  487. two_factor_remove
  488. two_factor_remove_auth_failures
  489. two_factor_remove_links
  490. two_factor_remove_session
  491. two_factor_setup_links
  492. two_factor_update_session
  493. unique_constraint_violation_class
  494. unlock_account
  495. unlock_account_email_link
  496. unlock_account_email_recently_sent?
  497. unverified_grace_period_expired?
  498. update_account
  499. update_activity
  500. update_current_session?
  501. update_hash_ds
  502. update_last_activity
  503. update_last_login
  504. update_login
  505. update_password_changed_at
  506. update_password_hash?
  507. update_session
  508. update_single_session_key
  509. update_sms
  510. use_database_authentication_functions?
  511. use_date_arithmetic?
  512. use_json?
  513. use_jwt?
  514. use_multi_phase_login?
  515. use_request_specific_csrf_tokens?
  516. uses_two_factor_authentication?
  517. valid_jwt?
  518. valid_login_entered?
  519. valid_new_webauthn_credential?
  520. valid_webauthn_credential_auth?
  521. verified_account?
  522. verify_account
  523. verify_account_check_already_logged_in
  524. verify_account_ds
  525. verify_account_email_link
  526. verify_account_email_recently_sent?
  527. verify_account_email_resend
  528. verify_account_key_insert_hash
  529. verify_account_set_password?
  530. verify_account_view
  531. verify_login_change
  532. verify_login_change_ds
  533. verify_login_change_email_body
  534. verify_login_change_email_link
  535. verify_login_change_key_insert_hash
  536. verify_login_change_old_login
  537. view
  538. webauthn_account_id
  539. webauthn_auth_additional_form_tags
  540. webauthn_auth_credential_from_form_submission
  541. webauthn_auth_form_path
  542. webauthn_authenticator_selection
  543. webauthn_credential_options_for_get
  544. webauthn_extensions
  545. webauthn_key_insert_hash
  546. webauthn_keys_ds
  547. webauthn_origin
  548. webauthn_remove_authenticated_session
  549. webauthn_rp_id
  550. webauthn_rp_name
  551. webauthn_setup?
  552. webauthn_setup_credential_from_form_submission
  553. webauthn_update_session
  554. webauthn_user_ids_ds
  555. webauthn_user_name

Constants

FEATURES = {}  
INVALID_DOMAIN = "invalidurl @@.com"  
MAJOR = 2  

The major version of Rodauth, updated only for major changes that are likely to require modification to apps using Rodauth.

MINOR = 29  

The minor version of Rodauth, updated for new feature releases of Rodauth.

TINY = 0  

The patch version of Rodauth, updated only for bug fixes from the last feature release.

VERSION = "#{MAJOR}.#{MINOR}.#{TINY}".freeze  

The full version of Rodauth as a string

VERSION_NUMBER = MAJOR*10000 + MINOR*100 + TINY  

The full version of Rodauth as a number (1.17.0 => 11700)

Public Instance Aliases

account_session_value -> account_id
ignore_uniqueness_violation -> raises_uniqueness_violation?

If you just want to ignore uniqueness violations, this alias makes more sense.

logged_in? -> session_value
raised_uniqueness_violation -> raises_uniqueness_violation?

If you would like to operate/reraise the exception, this alias makes more sense.

Public Class methods

configure(app, opts={}, &block)
[show source]
   # File lib/rodauth.rb
46 def self.configure(app, opts={}, &block)
47   json_opt = app.opts[:rodauth_json] = opts.fetch(:json, app.opts[:rodauth_json])
48   csrf = app.opts[:rodauth_csrf] = opts.fetch(:csrf, app.opts[:rodauth_csrf])
49   app.opts[:rodauth_route_csrf] = case csrf
50   when false, :rack_csrf
51     false
52   else
53     json_opt != :only
54   end
55   auth_class = (app.opts[:rodauths] ||= {})[opts[:name]] ||= opts[:auth_class] || Class.new(Auth)
56   if !auth_class.roda_class
57     auth_class.roda_class = app
58   elsif auth_class.roda_class != app
59     auth_class = app.opts[:rodauths][opts[:name]] = Class.new(auth_class)
60     auth_class.roda_class = app
61   end
62   auth_class.class_eval{@configuration_name = opts[:name] unless defined?(@configuration_name)}
63   auth_class.configure(&block) if block
64   auth_class.allocate.post_configure if auth_class.method_defined?(:post_configure)
65 end
create_database_authentication_functions(db, opts={})
[show source]
    # File lib/rodauth/migrations.rb
  4   def self.create_database_authentication_functions(db, opts={})
  5     table_name = opts[:table_name] || :account_password_hashes
  6     get_salt_name = opts[:get_salt_name] || :rodauth_get_salt
  7     valid_hash_name = opts[:valid_hash_name] || :rodauth_valid_password_hash
  8     argon2 = opts[:argon2]
  9 
 10     case db.database_type
 11     when :postgres
 12       search_path = opts[:search_path] || 'public, pg_temp'
 13       primary_key_type =
 14         case db.schema(table_name).find { |row| row.first == :id }[1][:db_type]
 15         when 'uuid' then :uuid
 16         else :int8
 17         end
 18       table_name = db.literal(table_name) unless table_name.is_a?(String)
 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
 27       db.run <<END
 28 CREATE OR REPLACE FUNCTION #{get_salt_name}(acct_id #{primary_key_type}) RETURNS text AS $$
 29 DECLARE salt text;
 30 BEGIN
 31 SELECT
 32 #{argon2 ? argon_sql : "substr(password_hash, 0, 30) INTO salt"}
 33 FROM #{table_name}
 34 WHERE acct_id = id;
 35 RETURN salt;
 36 END;
 37 $$ LANGUAGE plpgsql
 38 SECURITY DEFINER
 39 SET search_path = #{search_path};
 40 END
 41 
 42       db.run <<END
 43 CREATE OR REPLACE FUNCTION #{valid_hash_name}(acct_id #{primary_key_type}, hash text) RETURNS boolean AS $$
 44 DECLARE valid boolean;
 45 BEGIN
 46 SELECT password_hash = hash INTO valid 
 47 FROM #{table_name}
 48 WHERE acct_id = id;
 49 RETURN valid;
 50 END;
 51 $$ LANGUAGE plpgsql
 52 SECURITY DEFINER
 53 SET search_path = #{search_path};
 54 END
 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
 63       db.run <<END
 64 CREATE FUNCTION #{get_salt_name}(acct_id int8) RETURNS varchar(255)
 65 SQL SECURITY DEFINER
 66 READS SQL DATA
 67 BEGIN
 68 RETURN (SELECT
 69 #{argon2 ? argon_sql : "substr(password_hash, 1, 30)"}
 70 FROM #{table_name}
 71 WHERE acct_id = id);
 72 END;
 73 END
 74 
 75       db.run <<END
 76 CREATE FUNCTION #{valid_hash_name}(acct_id int8, hash varchar(255)) RETURNS tinyint(1)
 77 SQL SECURITY DEFINER
 78 READS SQL DATA
 79 BEGIN
 80 DECLARE valid tinyint(1);
 81 DECLARE csr CURSOR FOR 
 82 SELECT password_hash = hash
 83 FROM #{table_name}
 84 WHERE acct_id = id;
 85 OPEN csr;
 86 FETCH csr INTO valid;
 87 CLOSE csr;
 88 RETURN valid;
 89 END;
 90 END
 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
 99       db.run <<END
100 CREATE FUNCTION #{get_salt_name}(@account_id bigint) RETURNS nvarchar(255)
101 WITH EXECUTE AS OWNER
102 AS
103 BEGIN
104 DECLARE @salt nvarchar(255);
105 SELECT @salt =
106 #{argon2 ? argon_sql : "substring(password_hash, 0, 30)"}
107 FROM #{table_name}
108 WHERE id = @account_id;
109 RETURN @salt;
110 END;
111 END
112 
113       db.run <<END
114 CREATE FUNCTION #{valid_hash_name}(@account_id bigint, @hash nvarchar(255)) RETURNS bit
115 WITH EXECUTE AS OWNER
116 AS
117 BEGIN
118 DECLARE @valid bit;
119 DECLARE @ph nvarchar(255);
120 SELECT @ph = password_hash
121 FROM #{table_name}
122 WHERE id = @account_id;
123 IF(@hash = @ph)
124   SET @valid = 1;
125 ELSE
126   SET @valid = 0
127 RETURN @valid;
128 END;
129 END
130     end
131   end
create_database_previous_password_check_functions(db, opts={})
[show source]
    # File lib/rodauth/migrations.rb
153 def self.create_database_previous_password_check_functions(db, opts={})
154   create_database_authentication_functions(db, {:table_name=>:account_previous_password_hashes, :get_salt_name=>:rodauth_get_previous_salt, :valid_hash_name=>:rodauth_previous_password_hash_match}.merge(opts))
155 end
drop_database_authentication_functions(db, opts={})
[show source]
    # File lib/rodauth/migrations.rb
133 def self.drop_database_authentication_functions(db, opts={})
134   table_name = opts[:table_name] || :account_password_hashes
135   get_salt_name = opts[:get_salt_name] || :rodauth_get_salt
136   valid_hash_name = opts[:valid_hash_name] || :rodauth_valid_password_hash
137 
138   case db.database_type
139   when :postgres
140     primary_key_type =
141       case db.schema(table_name).find { |row| row.first == :id }[1][:db_type]
142       when 'uuid' then :uuid
143       else :int8
144       end
145     db.run "DROP FUNCTION #{get_salt_name}(#{primary_key_type})"
146     db.run "DROP FUNCTION #{valid_hash_name}(#{primary_key_type}, text)"
147   when :mysql, :mssql
148     db.run "DROP FUNCTION #{get_salt_name}"
149     db.run "DROP FUNCTION #{valid_hash_name}"
150   end
151 end
drop_database_previous_password_check_functions(db, opts={})
[show source]
    # File lib/rodauth/migrations.rb
157 def self.drop_database_previous_password_check_functions(db, opts={})
158   drop_database_authentication_functions(db, {:table_name=>:account_previous_password_hashes, :get_salt_name=>:rodauth_get_previous_salt, :valid_hash_name=>:rodauth_previous_password_hash_match}.merge(opts))
159 end
lib(opts={}, &block)
[show source]
   # File lib/rodauth.rb
 6 def self.lib(opts={}, &block) 
 7   require 'roda'
 8   c = Class.new(Roda)
 9   c.plugin(:rodauth, opts) do
10     enable :internal_request
11     instance_exec(&block)
12   end
13   c.freeze
14   c.rodauth
15 end
load_dependencies(app, opts={})
[show source]
   # File lib/rodauth.rb
17 def self.load_dependencies(app, opts={})
18   json_opt = opts.fetch(:json, app.opts[:rodauth_json])
19   if json_opt
20     app.plugin :json
21     app.plugin :json_parser
22   end
23 
24   unless json_opt == :only
25     unless opts[:render] == false
26       require 'tilt/string'
27       app.plugin :render
28     end
29 
30     case opts.fetch(:csrf, app.opts[:rodauth_csrf])
31     when false
32       # nothing
33     when :rack_csrf
34       # :nocov:
35       app.plugin :csrf
36       # :nocov:
37     else
38       app.plugin :route_csrf
39     end
40 
41     app.plugin :flash unless opts[:flash] == false
42     app.plugin :h
43   end
44 end
new(scope)
[show source]
    # File lib/rodauth/features/base.rb
139 def initialize(scope)
140   @scope = scope
141 end
version()
[show source]
   # File lib/rodauth/version.rb
21 def self.version
22   VERSION
23 end

Public Instance methods

_account_from_email_auth_key(token)
[show source]
    # File lib/rodauth/features/email_auth.rb
243 def _account_from_email_auth_key(token)
244   account_from_key(token, account_open_status_value){|id| get_email_auth_key(id)}
245 end
_account_from_login(login)
[show source]
    # File lib/rodauth/features/base.rb
697 def _account_from_login(login)
698   ds = account_table_ds.where(login_column=>login)
699   ds = ds.select(*account_select) if account_select
700   ds = ds.where(account_status_column=>[account_unverified_status_value, account_open_status_value]) unless skip_status_checks?
701   ds.first
702 end
_account_from_refresh_token(token)
[show source]
    # File lib/rodauth/features/jwt_refresh.rb
111 def _account_from_refresh_token(token)
112   id, token_id, key = _account_refresh_token_split(token)
113 
114   unless key &&
115          (id.to_s == session_value.to_s) &&
116          (actual = get_active_refresh_token(id, token_id)) &&
117          timing_safe_eql?(key, convert_token_key(actual)) &&
118          jwt_refresh_token_match?(key)
119     return
120   end
121 
122   ds = account_ds(id)
123   ds = ds.where(account_session_status_filter) unless skip_status_checks?
124   ds.first
125 end
_account_from_reset_password_key(token)
[show source]
    # File lib/rodauth/features/reset_password.rb
255 def _account_from_reset_password_key(token)
256   account_from_key(token, account_open_status_value){|id| get_password_reset_key(id)}
257 end
_account_from_session()
[show source]
    # File lib/rodauth/features/base.rb
704 def _account_from_session
705   ds = account_ds(session_value)
706   ds = ds.where(account_session_status_filter) unless skip_status_checks?
707   ds.first
708 end
_account_from_unlock_key(token)
[show source]
    # File lib/rodauth/features/lockout.rb
299 def _account_from_unlock_key(token)
300   account_from_key(token){|id| account_lockouts_ds(id).get(account_lockouts_key_column)}
301 end
_account_from_verify_account_key(token)
[show source]
    # File lib/rodauth/features/verify_account.rb
309 def _account_from_verify_account_key(token)
310   account_from_key(token, account_unverified_status_value){|id| get_verify_account_key(id)}
311 end
_account_from_verify_login_change_key(token)
[show source]
    # File lib/rodauth/features/verify_login_change.rb
212 def _account_from_verify_login_change_key(token)
213   account_from_key(token) do |id|
214     @verify_login_change_new_login, key = get_verify_login_change_login_and_key(id)
215     key
216   end
217 end
_account_refresh_token_split(token)
[show source]
    # File lib/rodauth/features/jwt_refresh.rb
127 def _account_refresh_token_split(token)
128   id, token = split_token(token)
129   id = convert_token_id(id)
130   return unless id && token
131 
132   token_id, key = split_token(token)
133   token_id = convert_token_id(token_id)
134   return unless token_id && key
135 
136   [id, token_id, key]
137 end
_around_rodauth()
[show source]
    # File lib/rodauth/features/base.rb
510 def _around_rodauth
511   yield
512 end
_email_auth_request()
[show source]
    # File lib/rodauth/features/email_auth.rb
185 def _email_auth_request
186   if email_auth_email_recently_sent?
187     set_redirect_error_flash email_auth_email_recently_sent_error_flash
188     redirect email_auth_email_recently_sent_redirect
189   end
190 
191   generate_email_auth_key_value
192   transaction do
193     before_email_auth_request
194     create_email_auth_key
195     send_email_auth_email
196     after_email_auth_request
197   end
198 
199   set_notice_flash email_auth_email_sent_notice_flash
200 end
_email_auth_request_and_redirect()
[show source]
    # File lib/rodauth/features/email_auth.rb
180 def _email_auth_request_and_redirect
181   _email_auth_request
182   redirect email_auth_email_sent_redirect
183 end
_field_attributes(field)
[show source]
    # File lib/rodauth/features/base.rb
716 def _field_attributes(field)
717   nil
718 end
_field_error_attributes(field)
[show source]
    # File lib/rodauth/features/base.rb
720 def _field_error_attributes(field)
721   " aria-invalid=\"true\" aria-describedby=\"#{field}_error_message\" "
722 end
_formatted_field_error(field, error)
[show source]
    # File lib/rodauth/features/base.rb
724 def _formatted_field_error(field, error)
725   "<span class=\"#{input_field_error_message_class}\" id=\"#{field}_error_message\">#{error}</span>"
726 end
_json_response_body(hash)
[show source]
    # File lib/rodauth/features/json.rb
184 def _json_response_body(hash)
185   request.send(:convert_to_json, hash)
186 end
_jwt_decode_opts()
[show source]
    # File lib/rodauth/features/jwt.rb
110 def _jwt_decode_opts
111   jwt_decode_opts
112 end
_login(auth_type)
[show source]
    # File lib/rodauth/features/login.rb
154 def _login(auth_type)
155   warn("Deprecated #_login method called, use #login instead.")
156   login(auth_type)
157 end
_multi_phase_login_forms()
[show source]
    # File lib/rodauth/features/email_auth.rb
170 def _multi_phase_login_forms
171   forms = super
172   forms << [30, email_auth_request_form, :_email_auth_request_and_redirect] if valid_login_entered? && allow_email_auth?
173   forms
174 end
_new_account(login)
[show source]
    # File lib/rodauth/features/create_account.rb
121 def _new_account(login)
122   acc = {login_column=>login}
123   unless skip_status_checks?
124     acc[account_status_column] = account_initial_status_value
125   end
126   acc
127 end
_otp()
[show source]
    # File lib/rodauth/features/otp.rb
414 def _otp
415   otp_class.new(otp_user_key, :issuer=>otp_issuer, :digits=>otp_digits, :interval=>otp_interval)
416 end
_otp_add_key(secret)
[show source]
    # File lib/rodauth/features/otp.rb
403 def _otp_add_key(secret)
404   # Uniqueness errors can't be handled here, as we can't be sure the secret provided
405   # is the same as the current secret.
406   otp_key_ds.insert(otp_keys_id_column=>session_value, otp_keys_column=>secret)
407 end
_otp_key()
[show source]
    # File lib/rodauth/features/otp.rb
409 def _otp_key
410   @otp_user_key = nil
411   otp_key_ds.get(otp_keys_column)
412 end
_otp_tmp_key(secret)
[show source]
    # File lib/rodauth/features/otp.rb
397 def _otp_tmp_key(secret)
398   @otp_tmp_key = true
399   @otp_user_key = nil
400   @otp_key = secret
401 end
_recovery_codes()
[show source]
    # File lib/rodauth/features/recovery_codes.rb
260 def _recovery_codes
261   recovery_codes_ds.select_map(recovery_codes_column)
262 end
_return_json_response()
[show source]
    # File lib/rodauth/features/json.rb
174 def _return_json_response
175   response.status ||= json_response_error_status if json_response[json_response_error_key]
176   response['Content-Type'] ||= json_response_content_type
177   return_response _json_response_body(json_response)
178 end
_setup_account_lockouts_hash(account_id, key)
[show source]
    # File lib/rodauth/features/lockout.rb
171 def _setup_account_lockouts_hash(account_id, key)
172   hash = {account_lockouts_id_column=>account_id, account_lockouts_key_column=>key}
173   set_deadline_value(hash, account_lockouts_deadline_column, account_lockouts_deadline_interval)
174   hash
175 end
_sms()
[show source]
    # File lib/rodauth/features/sms_codes.rb
499 def _sms
500   sms_ds.first
501 end
_template_opts(opts, page)

Set the template path only if there isn’t an overridden template in the application. Result should replace existing template opts.

[show source]
    # File lib/rodauth/features/base.rb
854 def _template_opts(opts, page)
855   opts = scope.send(:find_template, scope.send(:parse_template_opts, page, opts))
856   unless File.file?(scope.send(:template_path, opts))
857     opts[:path] = template_path(page)
858   end
859   opts
860 end
_two_factor_remove_all_from_session()
[show source]
    # File lib/rodauth/features/otp.rb
353 def _two_factor_remove_all_from_session
354   two_factor_remove_session('totp')
355   super
356 end
_update_login(login)
[show source]
   # File lib/rodauth/features/change_login.rb
83 def _update_login(login)
84   updated = nil
85   raised = raises_uniqueness_violation?{updated = update_account({login_column=>login}, account_ds.exclude(login_column=>login)) == 1}
86   if raised
87     set_login_requirement_error_message(:already_an_account_with_this_login, already_an_account_with_this_login_message)
88   end
89   updated && !raised
90 end
_view(meth, page)
[show source]
    # File lib/rodauth/features/base.rb
862 def _view(meth, page)
863   scope.send(meth, _view_opts(page))
864 end
_view_opts(page)
[show source]
    # File lib/rodauth/features/base.rb
843 def _view_opts(page)
844   opts = template_opts.dup
845   opts[:locals] = opts[:locals] ? opts[:locals].dup : {}
846   opts[:locals][:rodauth] = self
847   opts[:cache] = cache_templates
848   opts[:cache_key] = :"rodauth_#{page}"
849   _template_opts(opts, page)
850 end
account!()
[show source]
    # File lib/rodauth/features/base.rb
358 def account!
359   account || (session_value && account_from_session)
360 end
account_activity_ds(account_id)
[show source]
    # File lib/rodauth/features/account_expiration.rb
104 def account_activity_ds(account_id)
105   db[account_activity_table].
106     where(account_activity_id_column=>account_id)
107 end
account_ds(id=account_id)
[show source]
    # File lib/rodauth/features/base.rb
736 def account_ds(id=account_id)
737   raise ArgumentError, "invalid account id passed to account_ds" unless id
738   ds = account_table_ds.where(account_id_column=>id)
739   ds = ds.select(*account_select) if account_select
740   ds
741 end
account_expired?()
[show source]
   # File lib/rodauth/features/account_expiration.rb
54 def account_expired?
55   columns = [account_activity_last_activity_column, account_activity_last_login_column, account_activity_expired_column]
56   last_activity, last_login, expired = account_activity_ds(account_id).get(columns)
57   return true if expired
58   timestamp = convert_timestamp(expire_account_on_last_activity? ? last_activity : last_login)
59   return false unless timestamp
60   timestamp < Time.now - expire_account_after
61 end
account_expired_at()
[show source]
   # File lib/rodauth/features/account_expiration.rb
35 def account_expired_at
36   get_activity_timestamp(account_id, account_activity_expired_column)
37 end
account_from_email_auth_key(key)
[show source]
    # File lib/rodauth/features/email_auth.rb
133 def account_from_email_auth_key(key)
134   @account = _account_from_email_auth_key(key)
135 end
account_from_key(token, status_id=nil)
[show source]
   # File lib/rodauth/features/email_base.rb
65 def account_from_key(token, status_id=nil)
66   id, key = split_token(token)
67   id = convert_token_id(id)
68   return unless id && key
69 
70   return unless actual = yield(id)
71 
72   unless timing_safe_eql?(key, convert_email_token_key(actual))
73     if hmac_secret && allow_raw_email_token?
74       return unless timing_safe_eql?(key, actual)
75     else
76       return
77     end
78   end
79   ds = account_ds(id)
80   ds = ds.where(account_status_column=>status_id) if status_id && !skip_status_checks?
81   ds.first
82 end
account_from_login(login)
[show source]
    # File lib/rodauth/features/base.rb
260 def account_from_login(login)
261   @account = _account_from_login(login)
262 end
account_from_refresh_token(token)
[show source]
   # File lib/rodauth/features/jwt_refresh.rb
88 def account_from_refresh_token(token)
89   @account = _account_from_refresh_token(token)
90 end
account_from_reset_password_key(key)
[show source]
   # File lib/rodauth/features/password_expiration.rb
45 def account_from_reset_password_key(key)
46   if a = super
47     check_password_change_allowed
48   end
49   a
50 end
account_from_session()
[show source]
    # File lib/rodauth/features/base.rb
362 def account_from_session
363   @account = _account_from_session
364 end
account_from_unlock_key(key)
[show source]
    # File lib/rodauth/features/lockout.rb
222 def account_from_unlock_key(key)
223   @account = _account_from_unlock_key(key)
224 end
account_from_verify_account_key(key)
[show source]
    # File lib/rodauth/features/verify_account.rb
203 def account_from_verify_account_key(key)
204   @account = _account_from_verify_account_key(key)
205 end
account_from_verify_login_change_key(key)
[show source]
    # File lib/rodauth/features/verify_login_change.rb
122 def account_from_verify_login_change_key(key)
123   @account = _account_from_verify_login_change_key(key)
124 end
account_id()
[show source]
    # File lib/rodauth/features/base.rb
250 def account_id
251   account[account_id_column]
252 end
account_in_unverified_grace_period?()
[show source]
   # File lib/rodauth/features/verify_account_grace_period.rb
85 def account_in_unverified_grace_period?
86   return false unless account!
87   account[account_status_column] == account_unverified_status_value &&
88     verify_account_grace_period &&
89     !verify_account_ds.where(Sequel.date_add(verification_requested_at_column, :seconds=>verify_account_grace_period) > Sequel::CURRENT_TIMESTAMP).empty?
90 end
account_initial_status_value()
[show source]
    # File lib/rodauth/features/base.rb
354 def account_initial_status_value
355   account_open_status_value
356 end
account_lockouts_ds(id=account_id)
[show source]
    # File lib/rodauth/features/lockout.rb
295 def account_lockouts_ds(id=account_id)
296   db[account_lockouts_table].where(account_lockouts_id_column=>id)
297 end
account_login_failures_ds()
[show source]
    # File lib/rodauth/features/lockout.rb
291 def account_login_failures_ds
292   db[account_login_failures_table].where(account_login_failures_id_column=>account_id)
293 end
account_password_hash_column()

If the account_password_hash_column is set, the password hash is verified in ruby, it will not use a database function to do so, it will check the password hash using bcrypt.

[show source]
    # File lib/rodauth/features/base.rb
280 def account_password_hash_column
281   nil
282 end
account_session_status_filter()
[show source]
    # File lib/rodauth/features/base.rb
728 def account_session_status_filter
729   {account_status_column=>account_open_status_value}
730 end
account_table_ds()
[show source]
    # File lib/rodauth/features/base.rb
743 def account_table_ds
744   db[accounts_table]
745 end
account_webauthn_ids()
[show source]
    # File lib/rodauth/features/webauthn.rb
265 def account_webauthn_ids
266   webauthn_keys_ds.select_map(webauthn_keys_webauthn_id_column)
267 end
account_webauthn_usage()
[show source]
    # File lib/rodauth/features/webauthn.rb
269 def account_webauthn_usage
270   webauthn_keys_ds.select_hash(webauthn_keys_webauthn_id_column, webauthn_keys_last_use_column)
271 end
account_webauthn_user_id()
[show source]
    # File lib/rodauth/features/webauthn.rb
273 def account_webauthn_user_id
274   unless webauthn_id = webauthn_user_ids_ds.get(webauthn_user_ids_webauthn_id_column)
275     webauthn_id = WebAuthn.generate_user_id
276     if e = raised_uniqueness_violation do
277           webauthn_user_ids_ds.insert(
278             webauthn_user_ids_account_id_column => webauthn_account_id,
279             webauthn_user_ids_webauthn_id_column => webauthn_id
280           )
281         end
282       # If two requests to create a webauthn user id are sent at the same time and an insert
283       # is attempted for both, one will fail with a unique constraint violation.  In that case
284       # it is safe for the second one to use the webauthn user id inserted by the other request.
285       # If there is still no webauthn user id at this point, then we'll just reraise the
286       # exception.
287       # :nocov:
288       raise e unless webauthn_id = webauthn_user_ids_ds.get(webauthn_user_ids_webauthn_id_column)
289       # :nocov:
290     end
291   end
292 
293   webauthn_id
294 end
active_remember_key_ds(id=account_id)
[show source]
    # File lib/rodauth/features/remember.rb
251 def active_remember_key_ds(id=account_id)
252   remember_key_ds(id).where(Sequel.expr(remember_deadline_column) > Sequel::CURRENT_TIMESTAMP)
253 end
active_sessions_ds()
[show source]
    # File lib/rodauth/features/active_sessions.rb
179 def active_sessions_ds
180   db[active_sessions_table].
181     where(active_sessions_account_id_column=>session_value)
182 end
active_sessions_insert_hash()
[show source]
    # File lib/rodauth/features/active_sessions.rb
148 def active_sessions_insert_hash
149   {active_sessions_account_id_column => session_value, active_sessions_session_id_column => compute_hmac(active_sessions_key)}
150 end
active_sessions_update_hash()
[show source]
    # File lib/rodauth/features/active_sessions.rb
152 def active_sessions_update_hash
153   {active_sessions_last_use_column => Sequel::CURRENT_TIMESTAMP}
154 end
add_active_session()
[show source]
   # File lib/rodauth/features/active_sessions.rb
66 def add_active_session
67   key = generate_active_sessions_key
68   set_session_value(session_id_session_key, key)
69   if e = raises_uniqueness_violation?{active_sessions_ds.insert(active_sessions_insert_hash)}
70     handle_duplicate_active_session_id(e)
71   end
72   nil
73 end
add_audit_log(account_id, action)
[show source]
   # File lib/rodauth/features/audit_logging.rb
39 def add_audit_log(account_id, action)
40   if hash = audit_log_insert_hash(account_id, action)
41     audit_log_ds.insert(hash)
42   end
43 end
add_field_error_class(field)
[show source]
    # File lib/rodauth/features/base.rb
180 def add_field_error_class(field)
181   if field_error(field)
182     " #{input_field_error_class}"
183   end
184 end
add_previous_password_hash(hash)
[show source]
   # File lib/rodauth/features/disallow_password_reuse.rb
25 def add_previous_password_hash(hash) 
26   ds = previous_password_ds
27 
28   unless @dont_check_previous_password
29     keep_before = ds.reverse(previous_password_id_column).
30       limit(nil, previous_passwords_to_check).
31       get(previous_password_id_column)
32 
33     if keep_before
34       ds.where(Sequel.expr(previous_password_id_column) <= keep_before).
35         delete
36     end
37   end
38 
39   # This should never raise uniqueness violations, as it uses a serial primary key
40   ds.insert(previous_password_account_id_column=>account_id, previous_password_hash_column=>hash)
41 end
add_recovery_code()
[show source]
    # File lib/rodauth/features/recovery_codes.rb
187 def add_recovery_code
188   # This should never raise uniqueness violations unless the recovery code is the same, and the odds of that
189   # are 1/256**32 assuming a good random number generator.  Still, attempt to handle that case by retrying
190   # on such a uniqueness violation.
191   retry_on_uniqueness_violation do
192     recovery_codes_ds.insert(recovery_codes_id_column=>session_value, recovery_codes_column=>new_recovery_code)
193   end
194 end
add_recovery_codes(number)
[show source]
    # File lib/rodauth/features/recovery_codes.rb
177 def add_recovery_codes(number)
178   return if number <= 0
179   transaction do
180     number.times do
181       add_recovery_code
182     end
183   end
184   remove_instance_variable(:@recovery_codes)
185 end
add_remember_key()
[show source]
    # File lib/rodauth/features/remember.rb
155 def add_remember_key
156   hash = {remember_id_column=>account_id, remember_key_column=>remember_key_value}
157   set_deadline_value(hash, remember_deadline_column, remember_deadline_interval)
158 
159   if e = raised_uniqueness_violation{remember_key_ds.insert(hash)}
160     # If inserting into the remember key table causes a violation, we can pull the
161     # existing row from the table.  If there is no invalid row, we can then reraise.
162     raise e unless @remember_key_value = active_remember_key_ds.get(remember_key_column)
163   end
164 end
add_webauthn_credential(_)
[show source]
    # File lib/rodauth/features/recovery_codes.rb
151 def add_webauthn_credential(_)
152   super if defined?(super)
153   auto_add_missing_recovery_codes
154 end
after_change_password()
[show source]
   # File lib/rodauth/features/change_password_notify.rb
11 def after_change_password
12   super
13   send_password_changed_email
14 end
after_close_account()
[show source]
    # File lib/rodauth/features/account_expiration.rb
 99 def after_close_account
100   super if defined?(super)
101   account_activity_ds(account_id).delete
102 end
after_create_account()
[show source]
   # File lib/rodauth/features/disallow_password_reuse.rb
87 def after_create_account
88   if account_password_hash_column && !(respond_to?(:verify_account_set_password?) && verify_account_set_password?)
89     add_previous_password_hash(password_hash(param(password_param)))
90   end
91   super if defined?(super)
92 end
after_login()
[show source]
    # File lib/rodauth/features/email_auth.rb
208 def after_login
209   # Remove the email auth key after any login, even if
210   # it is a password login.  This is done to invalidate
211   # the email login when a user has a password and requests
212   # email authentication, but then remembers their password
213   # and doesn't need the link.  At that point, the link
214   # that allows login access to the account becomes a
215   # security liability, and it is best to remove it.
216   remove_email_auth_key
217   super
218 end
after_login_entered_during_multi_phase_login()
[show source]
    # File lib/rodauth/features/email_auth.rb
151 def after_login_entered_during_multi_phase_login
152   # If forcing email auth, just send the email link.
153   _email_auth_request_and_redirect if force_email_auth?
154 
155   super
156 end
after_login_failure()
[show source]
    # File lib/rodauth/features/lockout.rb
258 def after_login_failure
259   invalid_login_attempted
260   super
261 end
after_logout()
[show source]
    # File lib/rodauth/features/remember.rb
227 def after_logout
228   forget_login
229   super if defined?(super)
230 end
after_otp_disable()
[show source]
    # File lib/rodauth/features/recovery_codes.rb
225 def after_otp_disable
226   super if defined?(super)
227   auto_remove_recovery_codes
228 end
after_refresh_token()
[show source]
    # File lib/rodauth/features/active_sessions.rb
116 def after_refresh_token
117   super if defined?(super)
118   if prev_key = session[session_id_session_key]
119     key = generate_active_sessions_key
120     set_session_value(session_id_session_key, key)
121     active_sessions_ds.
122       where(active_sessions_session_id_column => compute_hmac(prev_key)).
123       update(active_sessions_session_id_column => compute_hmac(key))
124   end
125 end
after_reset_password()
[show source]
   # File lib/rodauth/features/password_grace_period.rb
39 def after_reset_password
40   super if defined?(super)
41   @last_password_entry = Time.now.to_i
42 end
after_sms_disable()
[show source]
    # File lib/rodauth/features/recovery_codes.rb
230 def after_sms_disable
231   super if defined?(super)
232   auto_remove_recovery_codes
233 end
after_webauthn_remove()
[show source]
    # File lib/rodauth/features/recovery_codes.rb
235 def after_webauthn_remove
236   super if defined?(super)
237   auto_remove_recovery_codes
238 end
allow_email_auth?()
[show source]
    # File lib/rodauth/features/email_auth.rb
204 def allow_email_auth?
205   defined?(super) ? super : true
206 end
allow_resending_verify_account_email?()
[show source]
    # File lib/rodauth/features/verify_account.rb
170 def allow_resending_verify_account_email?
171   account[account_status_column] == account_unverified_status_value
172 end
already_logged_in()
[show source]
    # File lib/rodauth/features/base.rb
288 def already_logged_in
289   nil
290 end
argon2_hash_algorithm?(hash)

:nocov:

[show source]
   # File lib/rodauth/features/argon2.rb
82 def argon2_hash_algorithm?(hash)
83   hash.start_with?('$argon2id$')
84 end
argon2_hash_cost()
[show source]
   # File lib/rodauth/features/argon2.rb
71 def argon2_hash_cost
72   {t_cost: 1, m_cost: 3}
73 end
argon2_password_hash_match?(hash, password)
[show source]
   # File lib/rodauth/features/argon2.rb
86 def argon2_password_hash_match?(hash, password)
87   ::Argon2::Password.verify_password(password, hash, argon2_secret)
88 end
argon2_salt_option()
[show source]
   # File lib/rodauth/features/argon2.rb
33 def argon2_salt_option
34   :salt_do_not_supply
35 end
audit_log_ds()
[show source]
   # File lib/rodauth/features/audit_logging.rb
83 def audit_log_ds
84   ds = db[audit_logging_table]
85   # :nocov:
86   if db.database_type == :postgres
87   # :nocov:
88     # For PostgreSQL, use RETURNING NULL. This allows the feature
89     # to be used with INSERT but not SELECT permissions on the
90     # table, useful for audit logging where the database user
91     # the application is running as should not need to read the
92     # logs.
93     ds = ds.returning(nil)
94   end
95   ds
96 end
audit_log_insert_hash(account_id, action)
[show source]
   # File lib/rodauth/features/audit_logging.rb
45 def audit_log_insert_hash(account_id, action)
46   if message = audit_log_message(action)
47     {
48       audit_logging_account_id_column => account_id,
49       audit_logging_message_column => message,
50       audit_logging_metadata_column => serialize_audit_log_metadata(audit_log_metadata(action))
51     }
52   end
53 end
audit_log_message(action)
[show source]
   # File lib/rodauth/features/audit_logging.rb
63 def audit_log_message(action)
64   meth = :"audit_log_message_for_#{action}"
65   if respond_to?(meth, true)
66     send(meth)
67   else
68     audit_log_message_default(action)
69   end
70 end
audit_log_message_default(action)
[show source]
   # File lib/rodauth/features/audit_logging.rb
59 def audit_log_message_default(action)
60   action.to_s
61 end
audit_log_metadata(action)
[show source]
   # File lib/rodauth/features/audit_logging.rb
72 def audit_log_metadata(action)
73   meth = :"audit_log_metadata_for_#{action}"
74   if respond_to?(meth, true)
75     send(meth)
76   else
77     audit_log_metadata_default
78   end
79 end
auth_class_eval(&block)
[show source]
    # File lib/rodauth/features/base.rb
131 def auth_class_eval(&block)
132   auth.class_eval(&block)
133 end
authenticated?()
[show source]
    # File lib/rodauth/features/base.rb
341 def authenticated?
342   logged_in?
343 end
authenticated_by()
[show source]
    # File lib/rodauth/features/base.rb
440 def authenticated_by
441   session[authenticated_by_session_key]
442 end
authenticated_webauthn_id()
[show source]
    # File lib/rodauth/features/webauthn.rb
245 def authenticated_webauthn_id
246   session[authenticated_webauthn_id_session_key]
247 end
auto_add_missing_recovery_codes()
[show source]
    # File lib/rodauth/features/recovery_codes.rb
248 def auto_add_missing_recovery_codes
249   if auto_add_recovery_codes?
250     add_recovery_codes(recovery_codes_limit - recovery_codes.length)
251   end
252 end
auto_remove_recovery_codes()
[show source]
    # File lib/rodauth/features/recovery_codes.rb
254 def auto_remove_recovery_codes
255   if auto_remove_recovery_codes? && (%w'totp webauthn sms_code' & possible_authentication_methods).empty?
256     recovery_codes_remove
257   end
258 end
autocomplete_for_field?(_param)
[show source]
    # File lib/rodauth/features/base.rb
210 def autocomplete_for_field?(_param)
211   mark_input_fields_with_autocomplete?
212 end
autologin_session(autologin_type)
[show source]
    # File lib/rodauth/features/base.rb
453 def autologin_session(autologin_type)
454   login_session('autologin')
455   set_session_value(autologin_type_session_key, autologin_type)
456 end
autologin_type()
[show source]
    # File lib/rodauth/features/base.rb
449 def autologin_type
450   session[autologin_type_session_key]
451 end
base32_encode(data, length)
[show source]
    # File lib/rodauth/features/otp.rb
392 def base32_encode(data, length)
393   chars = 'abcdefghijklmnopqrstuvwxyz234567'
394   length.times.map{|i|chars[data[i].ord % 32]}.join
395 end
base_url()
[show source]
    # File lib/rodauth/features/base.rb
490 def base_url
491   url = String.new("#{request.scheme}://#{domain}")
492   url << ":#{request.port}" if request.port != Rack::Request::DEFAULT_PORTS[request.scheme]
493   url
494 end
before_change_login_route()
[show source]
   # File lib/rodauth/features/verify_account_grace_period.rb
58 def before_change_login_route
59   unless verified_account?
60     set_redirect_error_flash unverified_change_login_error_flash
61     redirect unverified_change_login_redirect
62   end
63   super if defined?(super)
64 end
before_change_password_route()
[show source]
   # File lib/rodauth/features/password_expiration.rb
90 def before_change_password_route
91   check_password_change_allowed
92   super
93 end
before_create_account_route()
[show source]
   # File lib/rodauth/features/disallow_password_reuse.rb
77 def before_create_account_route
78   super if defined?(super)
79   @dont_check_previous_password = true
80 end
before_login_attempt()
[show source]
    # File lib/rodauth/features/lockout.rb
246 def before_login_attempt
247   if locked_out?
248     show_lockout_page
249   end
250   super
251 end
before_logout()
[show source]
    # File lib/rodauth/features/active_sessions.rb
132 def before_logout
133   if param_or_nil(global_logout_param)
134     remove_remember_key(session_value) if respond_to?(:remove_remember_key)
135     remove_all_active_sessions
136   else
137     remove_current_session
138   end
139   super
140 end
before_otp_setup_route()
[show source]
    # File lib/rodauth/features/json.rb
134 def before_otp_setup_route
135   super if defined?(super)
136   if use_json? && otp_keys_use_hmac? && !param_or_nil(otp_setup_raw_param)
137     _otp_tmp_key(otp_new_secret)
138     json_response[otp_setup_param] = otp_user_key
139     json_response[otp_setup_raw_param] = otp_key
140   end
141 end
before_reset_password()
[show source]
   # File lib/rodauth/features/account_expiration.rb
79 def before_reset_password
80   check_account_expiration
81   super if defined?(super)
82 end
before_reset_password_request()
[show source]
   # File lib/rodauth/features/account_expiration.rb
84 def before_reset_password_request
85   check_account_expiration
86   super if defined?(super)
87 end
before_rodauth()
[show source]
    # File lib/rodauth/features/json.rb
143 def before_rodauth
144   if json_request?
145     if json_check_accept? && (accept = request.env['HTTP_ACCEPT']) && accept !~ json_accept_regexp
146       response.status = 406
147       json_response[json_response_error_key] = json_not_accepted_error_message
148       _return_json_response
149     end
150 
151     unless request.post?
152       response.status = 405
153       response.headers['Allow'] = 'POST'
154       json_response[json_response_error_key] = json_non_post_error_message
155       return_json_response
156     end
157   elsif only_json?
158     response.status = json_response_error_status
159     return_response non_json_request_error_message
160   end
161 
162   super
163 end
before_two_factor_auth_route()
[show source]
   # File lib/rodauth/features/json.rb
80 def before_two_factor_auth_route
81   super if defined?(super)
82   if use_json?
83     json_response[:auth_links] = two_factor_auth_links.sort.map{|_,link| link}
84     json_response[json_response_success_key] ||= "" if include_success_messages?
85     return_json_response
86   end
87 end
before_two_factor_manage_route()
[show source]
   # File lib/rodauth/features/json.rb
70 def before_two_factor_manage_route
71   super if defined?(super)
72   if use_json?
73     json_response[:setup_links] = two_factor_setup_links.sort.map{|_,link| link}
74     json_response[:remove_links] = two_factor_remove_links.sort.map{|_,link| link}
75     json_response[json_response_success_key] ||= "" if include_success_messages?
76     return_json_response
77   end
78 end
before_unlock_account()
[show source]
   # File lib/rodauth/features/account_expiration.rb
89 def before_unlock_account
90   check_account_expiration
91   super if defined?(super)
92 end
before_unlock_account_request()
[show source]
   # File lib/rodauth/features/account_expiration.rb
94 def before_unlock_account_request
95   check_account_expiration
96   super if defined?(super)
97 end
before_verify_account()
[show source]
   # File lib/rodauth/features/webauthn_verify_account.rb
30 def before_verify_account
31   super
32   if features.include?(:json) && use_json? && !param_or_nil(webauthn_setup_param)
33     cred = new_webauthn_credential
34     json_response[webauthn_setup_param] = cred.as_json
35     json_response[webauthn_setup_challenge_param] = cred.challenge
36     json_response[webauthn_setup_challenge_hmac_param] = compute_hmac(cred.challenge)
37   end
38   @webauthn_credential = webauthn_setup_credential_from_form_submission
39   add_webauthn_credential(@webauthn_credential)
40 end
before_verify_account_route()
[show source]
   # File lib/rodauth/features/disallow_password_reuse.rb
82 def before_verify_account_route
83   super if defined?(super)
84   @dont_check_previous_password = true
85 end
before_view_recovery_codes()
[show source]
   # File lib/rodauth/features/json.rb
89 def before_view_recovery_codes
90   super if defined?(super)
91   if use_json?
92     json_response[:codes] = recovery_codes
93     json_response[json_response_success_key] ||= "" if include_success_messages?
94   end
95 end
before_webauthn_auth_route()
[show source]
    # File lib/rodauth/features/json.rb
107 def before_webauthn_auth_route
108   super if defined?(super)
109   if use_json? && !param_or_nil(webauthn_auth_param)
110     cred = webauthn_credential_options_for_get
111     json_response[webauthn_auth_param] = cred.as_json
112     json_response[webauthn_auth_challenge_param] = cred.challenge
113     json_response[webauthn_auth_challenge_hmac_param] = compute_hmac(cred.challenge)
114   end
115 end
before_webauthn_login_route()
[show source]
    # File lib/rodauth/features/json.rb
117 def before_webauthn_login_route
118   super if defined?(super)
119   if use_json? && !param_or_nil(webauthn_auth_param) && account_from_login(param(login_param))
120     cred = webauthn_credential_options_for_get
121     json_response[webauthn_auth_param] = cred.as_json
122     json_response[webauthn_auth_challenge_param] = cred.challenge
123     json_response[webauthn_auth_challenge_hmac_param] = compute_hmac(cred.challenge)
124   end
125 end
before_webauthn_remove_route()
[show source]
    # File lib/rodauth/features/json.rb
127 def before_webauthn_remove_route
128   super if defined?(super)
129   if use_json? && !param_or_nil(webauthn_remove_param)
130     json_response[webauthn_remove_param] = account_webauthn_usage
131   end
132 end
before_webauthn_setup_route()
[show source]
    # File lib/rodauth/features/json.rb
 97 def before_webauthn_setup_route
 98   super if defined?(super)
 99   if use_json? && !param_or_nil(webauthn_setup_param)
100     cred = new_webauthn_credential
101     json_response[webauthn_setup_param] = cred.as_json
102     json_response[webauthn_setup_challenge_param] = cred.challenge
103     json_response[webauthn_setup_challenge_hmac_param] = compute_hmac(cred.challenge)
104   end
105 end
button(value, opts={})
[show source]
    # File lib/rodauth/features/base.rb
390 def button(value, opts={})
391   scope.render(button_opts(value, opts))
392 end
button_opts(value, opts)
[show source]
    # File lib/rodauth/features/base.rb
382 def button_opts(value, opts)
383   opts = Hash[template_opts].merge!(opts)
384   opts[:locals] = {:value=>value, :opts=>opts}
385   opts[:cache] = cache_templates
386   opts[:cache_key] = :rodauth_button
387   _template_opts(opts, 'button')
388 end
can_add_recovery_codes?()
[show source]
    # File lib/rodauth/features/recovery_codes.rb
173 def can_add_recovery_codes?
174   recovery_codes.length < recovery_codes_limit
175 end
catch_error(&block)
[show source]
    # File lib/rodauth/features/base.rb
601 def catch_error(&block)
602   catch(:rodauth_error, &block)
603 end
change_login(login)
[show source]
   # File lib/rodauth/features/change_login.rb
68 def change_login(login)
69   if account_ds.get(login_column).downcase == login.downcase
70     set_login_requirement_error_message(:same_as_current_login, same_as_current_login_message)
71     return false
72   end
73 
74   update_login(login)
75 end
change_login_notice_flash()
[show source]
    # File lib/rodauth/features/verify_login_change.rb
138 def change_login_notice_flash
139   change_login_needs_verification_notice_flash
140 end
change_login_requires_password?()
[show source]
   # File lib/rodauth/features/change_login.rb
64 def change_login_requires_password?
65   modifications_require_password?
66 end
change_password_requires_password?()
[show source]
   # File lib/rodauth/features/change_password.rb
68 def change_password_requires_password?
69   modifications_require_password?
70 end
check_account_expiration()
[show source]
   # File lib/rodauth/features/account_expiration.rb
63 def check_account_expiration
64   if account_expired?
65     set_expired unless account_expired_at
66     set_redirect_error_flash account_expiration_error_flash
67     redirect account_expiration_redirect
68   end
69   update_last_login
70 end
check_active_session()
[show source]
   # File lib/rodauth/features/active_sessions.rb
52 def check_active_session
53   if logged_in? && !currently_active_session?
54     no_longer_active_session
55   end
56 end
check_already_logged_in()
[show source]
    # File lib/rodauth/features/base.rb
284 def check_already_logged_in
285   already_logged_in if logged_in?
286 end
check_csrf()
[show source]
    # File lib/rodauth/features/base.rb
366 def check_csrf
367   scope.check_csrf!(check_csrf_opts, &check_csrf_block)
368 end
check_csrf?()
[show source]
    # File lib/rodauth/features/base.rb
659 def check_csrf?
660   scope.opts[:rodauth_route_csrf]
661 end
check_password_change_allowed()
[show source]
   # File lib/rodauth/features/password_expiration.rb
30 def check_password_change_allowed
31   if password_changed_at = get_password_changed_at
32     if password_changed_at > Time.now - allow_password_change_after
33       set_redirect_error_flash password_not_changeable_yet_error_flash
34       redirect password_not_changeable_yet_redirect
35     end
36   end
37 end
check_session_expiration()
[show source]
   # File lib/rodauth/features/session_expiration.rb
15 def check_session_expiration
16   return unless logged_in?
17 
18   unless session.has_key?(session_last_activity_session_key) && session.has_key?(session_created_session_key)
19     if session_expiration_default
20       expire_session
21     end
22 
23     return
24   end
25 
26   time = Time.now.to_i
27 
28   if session[session_last_activity_session_key] + session_inactivity_timeout < time
29     expire_session
30   end
31   set_session_value(session_last_activity_session_key, time)
32 
33   if session[session_created_session_key] + max_session_lifetime < time
34     expire_session
35   end
36 end
check_single_session()
[show source]
   # File lib/rodauth/features/single_session.rb
51 def check_single_session
52   if logged_in? && !currently_active_session?
53     no_longer_active_session
54   end
55 end
clear_cached_otp()
[show source]
    # File lib/rodauth/features/otp.rb
358 def clear_cached_otp
359   remove_instance_variable(:@otp) if defined?(@otp)
360 end
clear_invalid_login_attempts()
[show source]
    # File lib/rodauth/features/lockout.rb
167 def clear_invalid_login_attempts
168   unlock_account
169 end
clear_session()
[show source]
    # File lib/rodauth/features/base.rb
300 def clear_session
301   if scope.respond_to?(:clear_session)
302     scope.clear_session
303   else
304     session.clear
305   end
306 end
close_account()
[show source]
   # File lib/rodauth/features/close_account.rb
66 def close_account
67   unless skip_status_checks?
68     update_account(account_status_column=>account_closed_status_value)
69   end
70 
71   unless account_password_hash_column
72     password_hash_ds.delete
73   end
74 end
close_account_requires_password?()
[show source]
   # File lib/rodauth/features/close_account.rb
62 def close_account_requires_password?
63   modifications_require_password?
64 end
compute_hmac(data)

Return urlsafe base64 HMAC for data, assumes hmac_secret is set.

[show source]
    # File lib/rodauth/features/base.rb
244 def compute_hmac(data)
245   s = [compute_raw_hmac(data)].pack('m').chomp!("=\n")
246   s.tr!('+/', '-_')
247   s
248 end
compute_raw_hmac(data)
[show source]
    # File lib/rodauth/features/base.rb
710 def compute_raw_hmac(data)
711   raise ArgumentError, "hmac_secret not set" unless hmac_secret
712 
713   OpenSSL::HMAC.digest(OpenSSL::Digest::SHA256.new, hmac_secret, data)
714 end
confirm_password()
[show source]
   # File lib/rodauth/features/confirm_password.rb
63 def confirm_password
64   authenticated_by.delete('autologin')
65   authenticated_by.delete('remember')
66   authenticated_by.delete('email_auth')
67   authenticated_by.delete('password')
68   authenticated_by.unshift("password")
69   remove_session_value(autologin_type_session_key)
70   nil
71 end
confirm_password_redirect()
[show source]
   # File lib/rodauth/features/confirm_password.rb
73 def confirm_password_redirect
74   remove_session_value(confirm_password_redirect_session_key) || default_redirect
75 end
convert_email_token_key(key)
[show source]
   # File lib/rodauth/features/email_base.rb
61 def convert_email_token_key(key)
62   convert_token_key(key)
63 end
convert_session_key(key)
[show source]
    # File lib/rodauth/features/base.rb
580 def convert_session_key(key)
581   key = :"#{session_key_prefix}#{key}" if session_key_prefix
582   normalize_session_or_flash_key(key)
583 end
convert_timestamp(timestamp)

This is needed for jdbc/sqlite, which returns timestamp columns as strings

[show source]
    # File lib/rodauth/features/base.rb
752 def convert_timestamp(timestamp)
753   timestamp = db.to_application_timestamp(timestamp) if timestamp.is_a?(String)
754   timestamp
755 end
convert_token_id(id)
[show source]
    # File lib/rodauth/features/base.rb
534 def convert_token_id(id)
535   if convert_token_id_to_integer?
536     convert_token_id_to_integer(id)
537   else
538     id
539   end
540 end
convert_token_id_to_integer(id)
[show source]
    # File lib/rodauth/features/base.rb
542 def convert_token_id_to_integer(id)
543   if id = (Integer(id, 10) rescue nil)
544     if id > 9223372036854775807 || id < -9223372036854775808
545       # Only allow 64-bit signed integer range to avoid problems on PostgreSQL
546       id = nil
547     end
548   end
549 
550   id
551 end
convert_token_key(key)
[show source]
    # File lib/rodauth/features/base.rb
522 def convert_token_key(key)
523   if key && hmac_secret
524     compute_hmac(key)
525   else
526     key
527   end
528 end
create_account_autologin?()
[show source]
    # File lib/rodauth/features/verify_account.rb
223 def create_account_autologin?
224   false
225 end
create_account_notice_flash()
[show source]
    # File lib/rodauth/features/verify_account.rb
190 def create_account_notice_flash
191   verify_account_email_sent_notice_flash
192 end
create_account_set_password?()
[show source]
    # File lib/rodauth/features/verify_account.rb
227 def create_account_set_password?
228   return false if verify_account_set_password?
229   super
230 end
create_email(subject, body)
[show source]
   # File lib/rodauth/features/email_base.rb
40 def create_email(subject, body)
41   create_email_to(email_to, subject, body)
42 end
create_email_auth_key()
[show source]
    # File lib/rodauth/features/email_auth.rb
104 def create_email_auth_key
105   transaction do
106     if email_auth_key_value = get_email_auth_key(account_id)
107       set_email_auth_email_last_sent
108       @email_auth_key_value = email_auth_key_value
109     elsif e = raised_uniqueness_violation{email_auth_ds.insert(email_auth_key_insert_hash)}
110       # If inserting into the email auth table causes a violation, we can pull the
111       # existing email auth key from the table, or reraise.
112       raise e unless @email_auth_key_value = get_email_auth_key(account_id)
113     end
114   end
115 end
create_email_to(to, subject, body)
[show source]
   # File lib/rodauth/features/email_base.rb
44 def create_email_to(to, subject, body)
45   m = Mail.new
46   m.from = email_from
47   m.to = to
48   m.subject = "#{email_subject_prefix}#{subject}"
49   m.body = body
50   m
51 end
create_reset_password_key()
[show source]
    # File lib/rodauth/features/reset_password.rb
166 def create_reset_password_key
167   transaction do
168     if reset_password_key_value = get_password_reset_key(account_id)
169       set_reset_password_email_last_sent
170       @reset_password_key_value = reset_password_key_value
171     elsif e = raised_uniqueness_violation{password_reset_ds.insert(reset_password_key_insert_hash)}
172       # If inserting into the reset password table causes a violation, we can pull the
173       # existing reset password key from the table, or reraise.
174       raise e unless @reset_password_key_value = get_password_reset_key(account_id)
175     end
176   end
177 end
create_verify_account_key()
[show source]
    # File lib/rodauth/features/verify_account.rb
288 def create_verify_account_key
289   ds = verify_account_ds
290   transaction do
291     if ds.empty?
292       if e = raised_uniqueness_violation{ds.insert(verify_account_key_insert_hash)}
293         # If inserting into the verify account table causes a violation, we can pull the
294         # key from the verify account table, or reraise.
295         raise e unless @verify_account_key_value = get_verify_account_key(account_id)
296       end
297     end
298   end
299 end
create_verify_login_change_email(login)
[show source]
    # File lib/rodauth/features/verify_login_change.rb
200 def create_verify_login_change_email(login)
201   create_email_to(login, verify_login_change_email_subject, verify_login_change_email_body)
202 end
create_verify_login_change_key(login)
[show source]
    # File lib/rodauth/features/verify_login_change.rb
178 def create_verify_login_change_key(login)
179   ds = verify_login_change_ds
180   transaction do
181     ds.where((Sequel::CURRENT_TIMESTAMP > verify_login_change_deadline_column) | ~Sequel.expr(verify_login_change_login_column=>login)).delete
182     if e = raised_uniqueness_violation{ds.insert(verify_login_change_key_insert_hash(login))}
183       old_login, key = get_verify_login_change_login_and_key(account_id)
184       # If inserting into the verify login change table causes a violation, we can pull the
185       # key from the verify login change table if the logins match, or reraise.
186       @verify_login_change_key_value = if old_login.downcase == login.downcase
187         key
188       end
189       raise e unless @verify_login_change_key_value
190     end
191   end
192 end
csrf_tag(path=request.path)
[show source]
    # File lib/rodauth/features/base.rb
370 def csrf_tag(path=request.path)
371   return unless scope.respond_to?(:csrf_tag)
372 
373   if use_request_specific_csrf_tokens?
374     scope.csrf_tag(path)
375   else
376     # :nocov:
377     scope.csrf_tag
378     # :nocov:
379   end
380 end
currently_active_session?()
[show source]
   # File lib/rodauth/features/active_sessions.rb
38 def currently_active_session?
39   return false unless session_id = session[session_id_session_key]
40 
41   remove_inactive_sessions
42   ds = active_sessions_ds.
43     where(active_sessions_session_id_column => compute_hmac(session_id))
44 
45   if update_current_session?
46     ds.update(active_sessions_update_hash) == 1
47   else
48     ds.count == 1
49   end
50 end
database_function_password_match?(name, hash_id, password, salt)
[show source]
    # File lib/rodauth/features/base.rb
514 def database_function_password_match?(name, hash_id, password, salt)
515   db.get(Sequel.function(function_name(name), hash_id, password_hash_using_salt(password, salt)))
516 end
db()
[show source]
    # File lib/rodauth/features/base.rb
268 def db
269   Sequel::DATABASES.first or raise "Sequel database connection is missing"
270 end
delete_account()
[show source]
   # File lib/rodauth/features/close_account.rb
76 def delete_account
77   account_ds.delete
78 end
delete_account_on_close?()
[show source]
   # File lib/rodauth/features/close_account.rb
80 def delete_account_on_close?
81   skip_status_checks?
82 end
disable_remember_login()
[show source]
    # File lib/rodauth/features/remember.rb
151 def disable_remember_login
152   remove_remember_key
153 end
domain()
[show source]
    # File lib/rodauth/features/base.rb
496 def domain
497   request.host
498 end
email_auth_ds(id=account_id)
[show source]
    # File lib/rodauth/features/email_auth.rb
239 def email_auth_ds(id=account_id)
240   db[email_auth_table].where(email_auth_id_column=>id)
241 end
email_auth_email_recently_sent?()
[show source]
    # File lib/rodauth/features/email_auth.rb
176 def email_auth_email_recently_sent?
177   (email_last_sent = get_email_auth_email_last_sent) && (Time.now - email_last_sent < email_auth_skip_resend_email_within)
178 end
email_auth_key_insert_hash()
[show source]
    # File lib/rodauth/features/email_auth.rb
233 def email_auth_key_insert_hash
234   hash = {email_auth_id_column=>account_id, email_auth_key_column=>email_auth_key_value}
235   set_deadline_value(hash, email_auth_deadline_column, email_auth_deadline_interval)
236   hash
237 end
email_auth_request_form()
[show source]
    # File lib/rodauth/features/email_auth.rb
147 def email_auth_request_form
148   render('email-auth-request-form')
149 end
email_from()
[show source]
   # File lib/rodauth/features/email_base.rb
26 def email_from
27   "webmaster@#{domain}"
28 end
email_to()
[show source]
   # File lib/rodauth/features/email_base.rb
30 def email_to
31   account[login_column]
32 end
expire_session()
[show source]
   # File lib/rodauth/features/session_expiration.rb
38 def expire_session
39   clear_session
40   set_redirect_error_status session_expiration_error_status
41   set_error_reason :session_expired
42   set_redirect_error_flash session_expiration_error_flash
43   redirect session_expiration_redirect
44 end
extend_remember_deadline()
[show source]
    # File lib/rodauth/features/remember.rb
198 def extend_remember_deadline
199   active_remember_key_ds.update(remember_deadline_column=>Sequel.date_add(Sequel::CURRENT_TIMESTAMP, remember_period))
200   remember_login
201 end
extend_remember_deadline_while_logged_in?()
[show source]
    # File lib/rodauth/features/remember.rb
186 def extend_remember_deadline_while_logged_in?
187   return false unless extend_remember_deadline?
188 
189   if extended_at = session[remember_deadline_extended_session_key]
190     extended_at + extend_remember_deadline_period < Time.now.to_i
191   elsif logged_in_via_remember_key?
192     # Handle existing sessions before the change to extend remember deadline
193     # while logged in.
194     true
195   end
196 end
extract_password_hash_cost(hash)
[show source]
   # File lib/rodauth/features/argon2.rb
63 def extract_password_hash_cost(hash)
64   return super unless argon2_hash_algorithm?(hash )
65 
66   /\A\$argon2id\$v=\d+\$m=(\d+),t=(\d+)/ =~ hash
67   { t_cost: $2.to_i, m_cost: Math.log2($1.to_i).to_i }
68 end
features()
[show source]
    # File lib/rodauth/features/base.rb
143 def features
144   self.class.features
145 end
field_attributes(field)
[show source]
    # File lib/rodauth/features/base.rb
218 def field_attributes(field)
219   _field_attributes(field) || default_field_attributes
220 end
field_error(field)
[show source]
    # File lib/rodauth/features/base.rb
175 def field_error(field)
176   return nil unless @field_errors
177   @field_errors[field]
178 end
field_error_attributes(field)
[show source]
    # File lib/rodauth/features/base.rb
222 def field_error_attributes(field)
223   if field_error(field)
224     _field_error_attributes(field)
225   end
226 end
flash()
[show source]
    # File lib/rodauth/features/base.rb
159 def flash
160   scope.flash
161 end
forget_login()
[show source]
    # File lib/rodauth/features/remember.rb
134 def forget_login
135   opts = Hash[remember_cookie_options]
136   opts[:path] = "/" unless opts.key?(:path)
137   ::Rack::Utils.delete_cookie_header!(response.headers, remember_cookie_key, opts)
138 end
formatted_field_error(field)
[show source]
    # File lib/rodauth/features/base.rb
228 def formatted_field_error(field)
229   if error = field_error(field)
230     _formatted_field_error(field, error)
231   end
232 end
function_name(name)
[show source]
    # File lib/rodauth/features/base.rb
663 def function_name(name)
664   if db.database_type == :mssql
665     # :nocov:
666     "dbo.#{name}"
667     # :nocov:
668   else
669     name
670   end
671 end
generate_active_sessions_key()
[show source]
    # File lib/rodauth/features/active_sessions.rb
144 def generate_active_sessions_key
145   @active_sessions_key = random_key
146 end
generate_email_auth_key_value()
[show source]
    # File lib/rodauth/features/email_auth.rb
225 def generate_email_auth_key_value
226   @email_auth_key_value = random_key
227 end
generate_refresh_token()
[show source]
    # File lib/rodauth/features/jwt_refresh.rb
183 def generate_refresh_token
184   hash = jwt_refresh_token_insert_hash
185   [account_id, jwt_refresh_token_ds.insert(hash), convert_token_key(hash[jwt_refresh_token_key_column])].join(token_separator)
186 end
generate_remember_key_value()
[show source]
    # File lib/rodauth/features/remember.rb
239 def generate_remember_key_value
240   @remember_key_value = random_key
241 end
generate_reset_password_key_value()
[show source]
    # File lib/rodauth/features/reset_password.rb
233 def generate_reset_password_key_value
234   @reset_password_key_value = random_key
235 end
generate_unlock_account_key()
[show source]
    # File lib/rodauth/features/lockout.rb
268 def generate_unlock_account_key
269   random_key
270 end
generate_verify_account_key_value()
[show source]
    # File lib/rodauth/features/verify_account.rb
284 def generate_verify_account_key_value
285   @verify_account_key_value = random_key
286 end
generate_verify_login_change_key_value()
[show source]
    # File lib/rodauth/features/verify_login_change.rb
174 def generate_verify_login_change_key_value
175   @verify_login_change_key_value = random_key
176 end
get_active_refresh_token(account_id, token_id)
[show source]
    # File lib/rodauth/features/jwt_refresh.rb
156 def get_active_refresh_token(account_id, token_id)
157   jwt_refresh_token_account_ds(account_id).
158     where(Sequel::CURRENT_TIMESTAMP > jwt_refresh_token_deadline_column).
159     delete
160 
161   jwt_refresh_token_account_token_ds(account_id, token_id).
162     get(jwt_refresh_token_key_column)
163 end
get_activity_timestamp(account_id, column)
[show source]
    # File lib/rodauth/features/account_expiration.rb
109 def get_activity_timestamp(account_id, column)
110   convert_timestamp(account_activity_ds(account_id).get(column))
111 end
get_email_auth_email_last_sent()
[show source]
    # File lib/rodauth/features/email_auth.rb
121 def get_email_auth_email_last_sent
122   if column = email_auth_email_last_sent_column
123     if ts = email_auth_ds.get(column)
124       convert_timestamp(ts)
125     end
126   end
127 end
get_email_auth_key(id)
[show source]
    # File lib/rodauth/features/email_auth.rb
141 def get_email_auth_key(id)
142   ds = email_auth_ds(id)
143   ds.where(Sequel::CURRENT_TIMESTAMP > email_auth_deadline_column).delete
144   ds.get(email_auth_key_column)
145 end
get_password_changed_at()
[show source]
   # File lib/rodauth/features/password_expiration.rb
26 def get_password_changed_at
27   convert_timestamp(password_expiration_ds.get(password_expiration_changed_at_column))
28 end
get_password_hash()

Get the password hash for the user. When using database authentication functions, note that only the salt is returned.

[show source]
    # File lib/rodauth/features/base.rb
685 def get_password_hash
686   if account_password_hash_column
687     account![account_password_hash_column]
688   elsif use_database_authentication_functions?
689     db.get(Sequel.function(function_name(:rodauth_get_salt), account ? account_id : session_value))
690   else
691     # :nocov:
692     password_hash_ds.get(password_hash_column)
693     # :nocov:
694   end
695 end
get_password_reset_key(id)
[show source]
    # File lib/rodauth/features/reset_password.rb
191 def get_password_reset_key(id)
192   ds = password_reset_ds(id)
193   ds.where(Sequel::CURRENT_TIMESTAMP > reset_password_deadline_column).delete
194   ds.get(reset_password_key_column)
195 end
get_remember_key()
[show source]
    # File lib/rodauth/features/remember.rb
140 def get_remember_key
141   unless @remember_key_value = active_remember_key_ds.get(remember_key_column)
142    generate_remember_key_value
143    transaction do
144      remove_remember_key
145      add_remember_key
146    end
147   end
148   nil
149 end
get_reset_password_email_last_sent()
[show source]
    # File lib/rodauth/features/reset_password.rb
201 def get_reset_password_email_last_sent
202   if column = reset_password_email_last_sent_column
203     if ts = password_reset_ds.get(column)
204       convert_timestamp(ts)
205     end
206   end
207 end
get_unlock_account_email_last_sent()
[show source]
    # File lib/rodauth/features/lockout.rb
230 def get_unlock_account_email_last_sent
231   if column = account_lockouts_email_last_sent_column
232     if ts = account_lockouts_ds.get(column)
233       convert_timestamp(ts)
234     end
235   end
236 end
get_unlock_account_key()
[show source]
    # File lib/rodauth/features/lockout.rb
218 def get_unlock_account_key
219   account_lockouts_ds.get(account_lockouts_key_column)
220 end
get_verify_account_email_last_sent()
[show source]
    # File lib/rodauth/features/verify_account.rb
236 def get_verify_account_email_last_sent
237   if column = verify_account_email_last_sent_column
238     if ts = verify_account_ds.get(column)
239       convert_timestamp(ts)
240     end
241   end
242 end
get_verify_account_key(id)
[show source]
    # File lib/rodauth/features/verify_account.rb
215 def get_verify_account_key(id)
216   verify_account_ds(id).get(verify_account_key_column)
217 end
get_verify_login_change_login_and_key(id)
[show source]
    # File lib/rodauth/features/verify_login_change.rb
134 def get_verify_login_change_login_and_key(id)
135   verify_login_change_ds(id).get([verify_login_change_login_column, verify_login_change_key_column])
136 end
handle_duplicate_active_session_id(_e)
[show source]
   # File lib/rodauth/features/active_sessions.rb
75 def handle_duplicate_active_session_id(_e)
76   # Do nothing by default as session is already tracked.  This will result in
77   # the current session and the existing session with the same id
78   # being tracked together, so that a logout of one will logout
79   # the other, and updating the last use on one will update the other,
80   # but this should be acceptable.  However, this can be overridden if different
81   # behavior is desired.
82 end
handle_webauthn_sign_count_verification_error()
[show source]
    # File lib/rodauth/features/webauthn.rb
347 def handle_webauthn_sign_count_verification_error
348   throw_error_reason(:invalid_webauthn_sign_count, invalid_field_error_status, webauthn_auth_param, webauthn_invalid_sign_count_message) 
349 end
has_password?()
[show source]
    # File lib/rodauth/features/base.rb
673 def has_password?
674   return @has_password if defined?(@has_password)
675   return false unless account || session_value
676   @has_password = !!get_password_hash
677 end
hook_action(hook_type, action)
[show source]
   # File lib/rodauth/features/audit_logging.rb
31 def hook_action(hook_type, action)
32   super
33   # In after_logout, session is already cleared, so use before_logout in that case
34   if (hook_type == :after || action == :logout) && (id = account ? account_id : session_value)
35     add_audit_log(id, action)
36   end
37 end
http_basic_auth()
[show source]
   # File lib/rodauth/features/http_basic_auth.rb
34 def http_basic_auth
35   return @checked_http_basic_auth if defined?(@checked_http_basic_auth)
36 
37   @checked_http_basic_auth = nil
38   return unless token = ((v = request.env['HTTP_AUTHORIZATION']) && v[/\A *Basic (.*)\Z/, 1])
39 
40   username, password = token.unpack("m*").first.split(/:/, 2)
41   return unless username && password
42 
43   catch_error do
44     unless account_from_login(username)
45       throw_basic_auth_error(login_param, no_matching_login_message)
46     end
47 
48     before_login_attempt
49 
50     unless open_account?
51       throw_basic_auth_error(login_param, no_matching_login_message)
52     end
53 
54     unless password_match?(password)
55       after_login_failure
56       throw_basic_auth_error(password_param, invalid_password_message)
57     end
58 
59     transaction do
60       before_login
61       login_session('password')
62       after_login
63     end
64 
65     @checked_http_basic_auth = true
66     return true
67   end
68 
69   nil
70 end
inactive_session_cond()
[show source]
    # File lib/rodauth/features/active_sessions.rb
168 def inactive_session_cond
169   cond = session_inactivity_deadline_condition
170   cond2 = session_lifetime_deadline_condition
171   return false unless cond || cond2
172   Sequel.|(*[cond, cond2].compact)
173 end
include_success_messages?()
[show source]
    # File lib/rodauth/features/json.rb
180 def include_success_messages?
181   !json_response_success_key.nil?
182 end
input_field_string(param, id, opts={})
[show source]
    # File lib/rodauth/features/base.rb
186 def input_field_string(param, id, opts={})
187   type = opts.fetch(:type, "text")
188 
189   unless type == "password"
190     value = opts.fetch(:value){scope.h param(param)}
191   end
192 
193   field_class = opts.fetch(:class, "form-control")
194 
195   if autocomplete_for_field?(param) && opts[:autocomplete]
196     autocomplete = "autocomplete=\"#{opts[:autocomplete]}\""
197   end
198 
199   if inputmode_for_field?(param) && opts[:inputmode]
200     inputmode = "inputmode=\"#{opts[:inputmode]}\""
201   end
202 
203   if mark_input_fields_as_required? && opts[:required] != false
204     required = "required=\"required\""
205   end
206 
207   "<input #{opts[:attr]} #{autocomplete} #{inputmode} #{required} #{field_attributes(param)} #{field_error_attributes(param)} type=\"#{type}\" class=\"#{field_class}#{add_field_error_class(param)}\" name=\"#{param}\" id=\"#{id}\" value=\"#{value}\"/> #{formatted_field_error(param) unless opts[:skip_error_message]}"
208 end
inputmode_for_field?(_param)
[show source]
    # File lib/rodauth/features/base.rb
214 def inputmode_for_field?(_param)
215   mark_input_fields_with_inputmode?
216 end
internal_request?()
[show source]
    # File lib/rodauth/features/base.rb
817 def internal_request?
818   false
819 end
internal_request_configuration(&block)
[show source]
    # File lib/rodauth/features/internal_request.rb
329 def internal_request_configuration(&block)
330   @auth.instance_exec do
331     (@internal_request_configuration_blocks ||= []) << block
332   end
333 end
invalid_login_attempted()
[show source]
    # File lib/rodauth/features/lockout.rb
177 def invalid_login_attempted
178   ds = account_login_failures_ds.
179       where(account_login_failures_id_column=>account_id)
180 
181   number = if db.database_type == :postgres
182     ds.returning(account_login_failures_number_column).
183       with_sql(:update_sql, account_login_failures_number_column=>Sequel.expr(account_login_failures_number_column)+1).
184       single_value
185   else
186     # :nocov:
187     if ds.update(account_login_failures_number_column=>Sequel.expr(account_login_failures_number_column)+1) > 0
188       ds.get(account_login_failures_number_column)
189     end
190     # :nocov:
191   end
192 
193   unless number
194     # Ignoring the violation is safe here.  It may allow slightly more than max_invalid_logins invalid logins before
195     # lockout, but allowing a few extra is OK if the race is lost.
196     ignore_uniqueness_violation{account_login_failures_ds.insert(account_login_failures_id_column=>account_id)}
197     number = 1
198   end
199 
200   if number >= max_invalid_logins
201     @unlock_account_key_value = generate_unlock_account_key
202     hash = _setup_account_lockouts_hash(account_id, unlock_account_key_value)
203 
204     if e = raised_uniqueness_violation{account_lockouts_ds.insert(hash)}
205       # If inserting into the lockout table raises a violation, we should just be able to pull the already inserted
206       # key out of it.  If that doesn't return a valid key, we should reraise the error.
207       raise e unless @unlock_account_key_value = account_lockouts_ds.get(account_lockouts_key_column)
208 
209       after_account_lockout
210       show_lockout_page
211     else
212       after_account_lockout
213       e
214     end
215   end
216 end
invalid_previous_password_message()
[show source]
   # File lib/rodauth/features/change_password.rb
72 def invalid_previous_password_message
73   invalid_password_message
74 end
json_request?()
[show source]
   # File lib/rodauth/features/json.rb
54 def json_request?
55   return @json_request if defined?(@json_request)
56   @json_request = request.content_type =~ json_request_content_type_regexp
57 end
json_response()
[show source]
    # File lib/rodauth/features/json.rb
188 def json_response
189   @json_response ||= {}
190 end
jwt_cors_allow?()
[show source]
   # File lib/rodauth/features/jwt_cors.rb
15 def jwt_cors_allow?
16   return false unless origin = request.env['HTTP_ORIGIN']
17 
18   case allowed = jwt_cors_allow_origin
19   when String
20     timing_safe_eql?(origin, allowed)
21   when Array
22     allowed.any?{|s| timing_safe_eql?(origin, s)}
23   when Regexp
24     allowed =~ origin
25   when true
26     true
27   else
28     false
29   end
30 end
jwt_payload()
[show source]
    # File lib/rodauth/features/jwt.rb
114 def jwt_payload
115   return @jwt_payload if defined?(@jwt_payload)
116   @jwt_payload = JWT.decode(jwt_token, jwt_secret, true, _jwt_decode_opts.merge(:algorithm=>jwt_algorithm))[0]
117 rescue JWT::DecodeError => e
118   rescue_jwt_payload(e)
119 end
jwt_refresh_token_account_ds(account_id)
[show source]
    # File lib/rodauth/features/jwt_refresh.rb
165 def jwt_refresh_token_account_ds(account_id)
166   jwt_refresh_token_ds.where(jwt_refresh_token_account_id_column => account_id)
167 end
jwt_refresh_token_account_token_ds(account_id, token_id)
[show source]
    # File lib/rodauth/features/jwt_refresh.rb
169 def jwt_refresh_token_account_token_ds(account_id, token_id)
170   jwt_refresh_token_account_ds(account_id).
171     where(jwt_refresh_token_id_column=>token_id)
172 end
jwt_refresh_token_ds()
[show source]
    # File lib/rodauth/features/jwt_refresh.rb
174 def jwt_refresh_token_ds
175   db[jwt_refresh_token_table]
176 end
jwt_refresh_token_insert_hash()
[show source]
    # File lib/rodauth/features/jwt_refresh.rb
188 def jwt_refresh_token_insert_hash
189   hash = {jwt_refresh_token_account_id_column => account_id, jwt_refresh_token_key_column => random_key}
190   set_deadline_value(hash, jwt_refresh_token_deadline_column, jwt_refresh_token_deadline_interval)
191   hash
192 end
jwt_refresh_token_match?(key)
[show source]
    # File lib/rodauth/features/jwt_refresh.rb
147 def jwt_refresh_token_match?(key)
148   # We don't need to match tokens if we are requiring a valid current access token
149   return true unless allow_refresh_with_expired_jwt_access_token?
150 
151   # If allowing with expired jwt access token, check the expired session contains
152   # hmac matching submitted and active refresh token.
153   timing_safe_eql?(compute_hmac(session[jwt_refresh_token_data_session_key].to_s + key), session[jwt_refresh_token_hmac_session_key].to_s)
154 end
jwt_secret()
[show source]
   # File lib/rodauth/features/jwt.rb
67 def jwt_secret
68   raise ArgumentError, "jwt_secret not set"
69 end
jwt_session_hash()
[show source]
   # File lib/rodauth/features/jwt.rb
71 def jwt_session_hash
72   jwt_session_key ? {jwt_session_key=>session} : session
73 end
jwt_token()
[show source]
   # File lib/rodauth/features/jwt.rb
79 def jwt_token
80   return @jwt_token if defined?(@jwt_token)
81 
82   if (v = request.env['HTTP_AUTHORIZATION']) && v !~ jwt_authorization_ignore
83     @jwt_token = v.sub(jwt_authorization_remove, '')
84   end
85 end
last_account_activity_at()
[show source]
   # File lib/rodauth/features/account_expiration.rb
27 def last_account_activity_at
28   get_activity_timestamp(session_value, account_activity_last_activity_column)
29 end
last_account_login_at()
[show source]
   # File lib/rodauth/features/account_expiration.rb
31 def last_account_login_at
32   get_activity_timestamp(session_value, account_activity_last_login_column)
33 end
load_memory()
[show source]
    # File lib/rodauth/features/remember.rb
114 def load_memory
115   if logged_in?
116     if extend_remember_deadline_while_logged_in?
117       account_from_session
118       extend_remember_deadline
119     end
120   elsif account_from_remember_cookie
121     before_load_memory
122     login_session('remember')
123     extend_remember_deadline if extend_remember_deadline?
124     after_load_memory
125   end
126 end
loaded_templates()
[show source]
    # File lib/rodauth/features/base.rb
757 def loaded_templates
758   []
759 end
locked_out?()
[show source]
    # File lib/rodauth/features/lockout.rb
148 def locked_out?
149   if t = convert_timestamp(account_lockouts_ds.get(account_lockouts_deadline_column))
150     if Time.now < t
151       true
152     else
153       unlock_account
154       false
155     end
156   else
157     false
158   end
159 end
logged_in_via_remember_key?()
[show source]
    # File lib/rodauth/features/remember.rb
170 def logged_in_via_remember_key?
171   authenticated_by.include?('remember')
172 end
login(auth_type)
[show source]
   # File lib/rodauth/features/login.rb
81 def login(auth_type)
82   saved_login_redirect = remove_session_value(login_redirect_session_key)
83   transaction do
84     before_login
85     login_session(auth_type)
86     yield if block_given?
87     after_login
88   end
89   set_notice_flash login_notice_flash
90   redirect(saved_login_redirect || login_redirect)
91 end
login_confirm_label()
[show source]
   # File lib/rodauth/features/login_password_requirements_base.rb
46 def login_confirm_label
47   "Confirm #{login_label}"
48 end
login_does_not_meet_requirements_message()
[show source]
    # File lib/rodauth/features/login_password_requirements_base.rb
108 def login_does_not_meet_requirements_message
109   "invalid login#{", #{login_requirement_message}" if login_requirement_message}"
110 end
login_failed_reset_password_request_form()
[show source]
    # File lib/rodauth/features/reset_password.rb
237 def login_failed_reset_password_request_form
238   render("reset-password-request")
239 end
login_hidden_field()
[show source]
    # File lib/rodauth/features/login.rb
125 def login_hidden_field
126   "<input type='hidden' name=\"#{login_param}\" value=\"#{scope.h param(login_param)}\" />"
127 end
login_input_type()
[show source]
    # File lib/rodauth/features/base.rb
292 def login_input_type
293   login_uses_email? ? 'email' : 'text'
294 end
login_meets_email_requirements?(login)
[show source]
    # File lib/rodauth/features/login_password_requirements_base.rb
144 def login_meets_email_requirements?(login)
145   return true unless require_email_address_logins?
146   return true if login_valid_email?(login)
147   set_login_requirement_error_message(:login_not_valid_email, login_not_valid_email_message)
148   return false
149 end
login_meets_length_requirements?(login)
[show source]
    # File lib/rodauth/features/login_password_requirements_base.rb
129 def login_meets_length_requirements?(login)
130   if login_minimum_length > login.length
131     set_login_requirement_error_message(:login_too_short, login_too_short_message)
132     false
133   elsif login_maximum_length < login.length
134     set_login_requirement_error_message(:login_too_long, login_too_long_message)
135     false
136   elsif login_maximum_bytes < login.bytesize
137     set_login_requirement_error_message(:login_too_many_bytes, login_too_many_bytes_message)
138     false
139   else
140     true
141   end
142 end
login_meets_requirements?(login)
[show source]
   # File lib/rodauth/features/login_password_requirements_base.rb
54 def login_meets_requirements?(login)
55   login_meets_length_requirements?(login) && \
56     login_meets_email_requirements?(login)
57 end
login_required()
[show source]
    # File lib/rodauth/features/base.rb
308 def login_required
309   set_redirect_error_status(login_required_error_status)
310   set_error_reason :login_required
311   set_redirect_error_flash require_login_error_flash
312   redirect require_login_redirect
313 end
login_return_to_requested_location_path()
[show source]
    # File lib/rodauth/features/login.rb
100 def login_return_to_requested_location_path
101   request.fullpath if request.get?
102 end
login_session(auth_type)
[show source]
    # File lib/rodauth/features/base.rb
444 def login_session(auth_type)
445   update_session
446   set_session_value(authenticated_by_session_key, [auth_type])
447 end
login_too_long_message()
[show source]
    # File lib/rodauth/features/login_password_requirements_base.rb
112 def login_too_long_message
113   "maximum #{login_maximum_length} characters"
114 end
login_too_many_bytes_message()
[show source]
    # File lib/rodauth/features/login_password_requirements_base.rb
116 def login_too_many_bytes_message
117   "maximum #{login_maximum_bytes} bytes"
118 end
login_too_short_message()
[show source]
    # File lib/rodauth/features/login_password_requirements_base.rb
120 def login_too_short_message
121   "minimum #{login_minimum_length} characters"
122 end
login_uses_email?()
[show source]
    # File lib/rodauth/features/base.rb
296 def login_uses_email?
297   login_column == :email
298 end
login_valid_email?(login)
[show source]
    # File lib/rodauth/features/login_password_requirements_base.rb
151 def login_valid_email?(login)
152   login =~ login_email_regexp
153 end
logout()
[show source]
   # File lib/rodauth/features/logout.rb
34 def logout
35   clear_session
36 end
logout_additional_form_tags()
[show source]
    # File lib/rodauth/features/active_sessions.rb
104 def logout_additional_form_tags
105   super.to_s + render('global-logout-field')
106 end
modifications_require_password?()
[show source]
    # File lib/rodauth/features/base.rb
500 def modifications_require_password?
501   has_password?
502 end
new_account(login)
[show source]
   # File lib/rodauth/features/create_account.rb
96 def new_account(login)
97   @account = _new_account(login)
98 end
new_recovery_code()
[show source]
    # File lib/rodauth/features/recovery_codes.rb
240 def new_recovery_code
241   random_key
242 end
new_webauthn_credential()
[show source]
    # File lib/rodauth/features/webauthn.rb
296 def new_webauthn_credential
297   WebAuthn::Credential.options_for_create(
298     :timeout => webauthn_setup_timeout,
299     :rp => {:name=>webauthn_rp_name, :id=>webauthn_rp_id},
300     :user => {:id=>account_webauthn_user_id, :name=>webauthn_user_name},
301     :authenticator_selection => webauthn_authenticator_selection,
302     :attestation => webauthn_attestation,
303     :extensions => webauthn_extensions,
304     :exclude => account_webauthn_ids,
305   )
306 end
no_longer_active_session()
[show source]
   # File lib/rodauth/features/active_sessions.rb
58 def no_longer_active_session
59   clear_session
60   set_redirect_error_status inactive_session_error_status
61   set_error_reason :inactive_session
62   set_redirect_error_flash active_sessions_error_flash
63   redirect active_sessions_redirect
64 end
normalize_session_or_flash_key(key)
[show source]
    # File lib/rodauth/features/base.rb
585 def normalize_session_or_flash_key(key)
586   scope.opts[:sessions_convert_symbols] ? key.to_s : key
587 end
null_byte_parameter_value(key, value)

Return nil by default for values with null bytes

[show source]
    # File lib/rodauth/features/base.rb
482 def null_byte_parameter_value(key, value)
483   nil
484 end
only_json?()
[show source]
    # File lib/rodauth/features/base.rb
403 def only_json?
404   scope.class.opts[:rodauth_json] == :only
405 end
open_account?()
[show source]
    # File lib/rodauth/features/base.rb
264 def open_account?
265   skip_status_checks? || account[account_status_column] == account_open_status_value 
266 end
otp_add_key()
[show source]
    # File lib/rodauth/features/otp.rb
271 def otp_add_key
272   _otp_add_key(otp_key)
273   super if defined?(super)
274 end
otp_available?()
[show source]
    # File lib/rodauth/features/otp.rb
242 def otp_available?
243   otp_exists? && !otp_locked_out?
244 end
otp_exists?()
[show source]
    # File lib/rodauth/features/otp.rb
246 def otp_exists?
247   !otp_key.nil?
248 end
otp_hmac_secret(key)
[show source]
    # File lib/rodauth/features/otp.rb
367 def otp_hmac_secret(key)
368   base32_encode(compute_raw_hmac(ROTP::Base32.decode(key)), key.bytesize)
369 end
otp_issuer()
[show source]
    # File lib/rodauth/features/otp.rb
302 def otp_issuer
303   domain
304 end
otp_key_ds()
[show source]
    # File lib/rodauth/features/otp.rb
418 def otp_key_ds
419   db[otp_keys_table].where(otp_keys_id_column=>session_value)
420 end
otp_keys_use_hmac?()
[show source]
    # File lib/rodauth/features/otp.rb
323 def otp_keys_use_hmac?
324   !!hmac_secret
325 end
otp_last_use()
[show source]
    # File lib/rodauth/features/otp.rb
282 def otp_last_use
283   convert_timestamp(otp_key_ds.get(otp_keys_last_use_column))
284 end
otp_locked_out?()
[show source]
    # File lib/rodauth/features/otp.rb
294 def otp_locked_out?
295   otp_key_ds.get(otp_keys_failures_column) >= otp_auth_failures_limit
296 end
otp_new_secret()
[show source]
    # File lib/rodauth/features/otp.rb
381 def otp_new_secret
382   ROTP::Base32.random_base32.downcase
383 end
otp_provisioning_name()
[show source]
    # File lib/rodauth/features/otp.rb
306 def otp_provisioning_name
307   account[login_column]
308 end
otp_provisioning_uri()
[show source]
    # File lib/rodauth/features/otp.rb
298 def otp_provisioning_uri
299   otp.provisioning_uri(otp_provisioning_name)
300 end
otp_qr_code()
[show source]
    # File lib/rodauth/features/otp.rb
310 def otp_qr_code
311   svg = RQRCode::QRCode.new(otp_provisioning_uri).as_svg(:module_size=>8, :viewbox=>true, :use_path=>true, :fill=>"fff")
312   svg.sub(/\A<\?xml version="1\.0" standalone="yes"\?>/, '')
313 end
otp_record_authentication_failure()
[show source]
    # File lib/rodauth/features/otp.rb
286 def otp_record_authentication_failure
287   otp_key_ds.update(otp_keys_failures_column=>Sequel.identifier(otp_keys_failures_column) + 1)
288 end
otp_remove()
[show source]
    # File lib/rodauth/features/otp.rb
266 def otp_remove
267   otp_key_ds.delete
268   @otp_key = nil
269 end
otp_remove_auth_failures()
[show source]
    # File lib/rodauth/features/otp.rb
290 def otp_remove_auth_failures
291   otp_key_ds.update(otp_keys_failures_column=>0)
292 end
otp_tmp_key(secret)
[show source]
    # File lib/rodauth/features/otp.rb
362 def otp_tmp_key(secret)
363   _otp_tmp_key(secret)
364   clear_cached_otp
365 end
otp_update_last_use()
[show source]
    # File lib/rodauth/features/otp.rb
276 def otp_update_last_use
277   otp_key_ds.
278     where(Sequel.date_add(otp_keys_last_use_column, :seconds=>(otp_interval||30)) < Sequel::CURRENT_TIMESTAMP).
279     update(otp_keys_last_use_column=>Sequel::CURRENT_TIMESTAMP) == 1
280 end
otp_user_key()
[show source]
    # File lib/rodauth/features/otp.rb
315 def otp_user_key
316   @otp_user_key ||= if otp_keys_use_hmac?
317     otp_hmac_secret(otp_key)
318   else
319     otp_key
320   end
321 end
otp_valid_code?(ot_pass)
[show source]
    # File lib/rodauth/features/otp.rb
250 def otp_valid_code?(ot_pass)
251   return false unless otp_exists?
252   ot_pass = ot_pass.gsub(/\s+/, '')
253   if drift = otp_drift
254     if otp.respond_to?(:verify_with_drift)
255       # :nocov:
256       otp.verify_with_drift(ot_pass, drift)
257       # :nocov:
258     else
259       otp.verify(ot_pass, :drift_behind=>drift, :drift_ahead=>drift)
260     end
261   else
262     otp.verify(ot_pass)
263   end
264 end
otp_valid_key?(secret)
[show source]
    # File lib/rodauth/features/otp.rb
371 def otp_valid_key?(secret)
372   return false unless secret =~ /\A([a-z2-7]{16}|[a-z2-7]{32})\z/
373   if otp_keys_use_hmac?
374     timing_safe_eql?(otp_hmac_secret(param(otp_setup_raw_param)), secret)
375   else
376     true
377   end
378 end
over_max_bytesize_param_value(key, value)

Return nil by default for values over maximum bytesize.

[show source]
    # File lib/rodauth/features/base.rb
477 def over_max_bytesize_param_value(key, value)
478   nil
479 end
param(key)

Return a string for the parameter name. This will be an empty string if the parameter doesn’t exist.

[show source]
    # File lib/rodauth/features/base.rb
460 def param(key)
461   param_or_nil(key).to_s
462 end
param_or_nil(key)

Return a string for the parameter name, or nil if there is no parameter with that name.

[show source]
    # File lib/rodauth/features/base.rb
466 def param_or_nil(key)
467   value = raw_param(key)
468   unless value.nil?
469     value = value.to_s
470     value = over_max_bytesize_param_value(key, value) if max_param_bytesize && value.bytesize > max_param_bytesize
471     value = null_byte_parameter_value(key, value) if value && value.include?("\0")
472   end
473   value
474 end
password_confirm_label()
[show source]
   # File lib/rodauth/features/login_password_requirements_base.rb
50 def password_confirm_label
51   "Confirm #{password_label}"
52 end
password_does_not_contain_null_byte?(password)
[show source]
    # File lib/rodauth/features/login_password_requirements_base.rb
170 def password_does_not_contain_null_byte?(password)
171   return true unless password.include?("\0")
172   set_password_requirement_error_message(:password_contains_null_byte, contains_null_byte_message)
173   false
174 end
password_does_not_meet_requirements_message()
[show source]
   # File lib/rodauth/features/login_password_requirements_base.rb
87 def password_does_not_meet_requirements_message
88   "invalid password, does not meet requirements#{" (#{password_requirement_message})" if password_requirement_message}"
89 end
password_doesnt_match_previous_password?(password)
[show source]
   # File lib/rodauth/features/disallow_password_reuse.rb
50 def password_doesnt_match_previous_password?(password)
51   match = if use_database_authentication_functions?
52     salts = previous_password_ds.
53       select_map([previous_password_id_column, Sequel.function(function_name(:rodauth_get_previous_salt), previous_password_id_column).as(:salt)])
54     return true if salts.empty?
55 
56     salts.any? do |hash_id, salt|
57       database_function_password_match?(:rodauth_previous_password_hash_match, hash_id, password, salt)
58     end
59   else
60     # :nocov:
61     previous_password_ds.select_map(previous_password_hash_column).any? do |hash|
62       password_hash_match?(hash, password)
63     end
64     # :nocov:
65   end
66 
67   return true unless match
68   set_password_requirement_error_message(:password_same_as_previous_password, password_same_as_previous_password_message)
69   false
70 end
password_expiration_ds()
[show source]
    # File lib/rodauth/features/password_expiration.rb
107 def password_expiration_ds
108   db[password_expiration_table].where(password_expiration_id_column=>account_id)
109 end
password_expired?()
[show source]
   # File lib/rodauth/features/password_expiration.rb
68 def password_expired?
69   if password_changed_at = session[password_changed_at_session_key]
70     return password_changed_at + require_password_change_after < Time.now.to_i
71   end
72 
73   account_from_session
74   if password_changed_at = get_password_changed_at
75     set_session_value(password_changed_at_session_key, password_changed_at.to_i)
76     password_changed_at + require_password_change_after < Time.now
77   else
78     set_session_value(password_changed_at_session_key, password_expiration_default ? 0 : 2147483647)
79     password_expiration_default
80   end
81 end
password_field_autocomplete_value()
[show source]
    # File lib/rodauth/features/base.rb
272 def password_field_autocomplete_value
273   @password_field_autocomplete_value || 'current-password'
274 end
password_has_enough_character_groups?(password)
[show source]
   # File lib/rodauth/features/password_complexity.rb
54 def password_has_enough_character_groups?(password)
55   return true if password.length > password_max_length_for_groups_check
56   return true if password_character_groups.select{|re| password =~ re}.length >= password_min_groups
57   set_password_requirement_error_message(:not_enough_character_groups_in_password, password_not_enough_character_groups_message)
58   false
59 end
password_has_no_invalid_pattern?(password)
[show source]
   # File lib/rodauth/features/password_complexity.rb
61 def password_has_no_invalid_pattern?(password)
62   return true unless password_invalid_pattern
63   return true if password !~ password_invalid_pattern
64   set_password_requirement_error_message(:invalid_password_pattern, password_invalid_pattern_message)
65   false
66 end
password_hash(password)
[show source]
   # File lib/rodauth/features/argon2.rb
18 def password_hash(password)
19   return super unless use_argon2?
20 
21   if secret = argon2_secret
22     argon2_params = Hash[password_hash_cost]
23     argon2_params[:secret] = secret
24   else
25     argon2_params = password_hash_cost
26   end
27   ::Argon2::Password.new(argon2_params).create(password)
28 end
password_hash_cost()
[show source]
   # File lib/rodauth/features/argon2.rb
44 def password_hash_cost
45   return super unless use_argon2?
46   argon2_hash_cost 
47 end
password_hash_ds()
[show source]
    # File lib/rodauth/features/base.rb
747 def password_hash_ds
748   db[password_hash_table].where(password_hash_id_column=>account ? account_id : session_value)
749 end
password_hash_match?(hash, password)
[show source]
   # File lib/rodauth/features/argon2.rb
49 def password_hash_match?(hash, password)
50   return super unless argon2_hash_algorithm?(hash)
51   argon2_password_hash_match?(hash, password)
52 end
password_hash_using_salt(password, salt)
[show source]
   # File lib/rodauth/features/argon2.rb
54 def password_hash_using_salt(password, salt)
55   return super unless argon2_hash_algorithm?(salt)
56 
57   argon2_params = Hash[extract_password_hash_cost(salt)]
58   argon2_params[argon2_salt_option] = Base64.decode64(salt.split('$').last)
59   argon2_params[:secret] = argon2_secret
60   ::Argon2::Password.new(argon2_params).create(password)
61 end
password_match?(password)
[show source]
    # File lib/rodauth/features/base.rb
425 def password_match?(password)
426   if hash = get_password_hash
427     if account_password_hash_column || !use_database_authentication_functions?
428       password_hash_match?(hash, password)
429     else
430       database_function_password_match?(:rodauth_valid_password_hash, account_id, password, hash)
431     end 
432   end
433 end
password_meets_length_requirements?(password)
[show source]
    # File lib/rodauth/features/login_password_requirements_base.rb
155 def password_meets_length_requirements?(password)
156   if password_minimum_length > password.length
157     set_password_requirement_error_message(:password_too_short, password_too_short_message)
158     false
159   elsif password_maximum_length && password_maximum_length < password.length
160     set_password_requirement_error_message(:password_too_long, password_too_long_message)
161     false
162   elsif password_maximum_bytes && password_maximum_bytes < password.bytesize
163     set_password_requirement_error_message(:password_too_many_bytes, password_too_many_bytes_message)
164     false
165   else
166     true
167   end
168 end
password_meets_requirements?(password)
[show source]
   # File lib/rodauth/features/disallow_common_passwords.rb
13 def password_meets_requirements?(password)
14   super && password_not_one_of_the_most_common?(password)
15 end
password_not_in_dictionary?(password)
[show source]
   # File lib/rodauth/features/password_complexity.rb
75 def password_not_in_dictionary?(password)
76   return true unless dict = password_dictionary
77   return true unless password =~ /\A(?:\d*)([A-Za-z!@$+|][A-Za-z!@$+|0134578]+[A-Za-z!@$+|])(?:\d*)\z/
78   word = $1.downcase.tr('!@$+|0134578', 'iastloleastb')
79   return true if !dict.include?(word)
80   set_password_requirement_error_message(:password_in_dictionary, password_in_dictionary_message)
81   false
82 end
password_not_one_of_the_most_common?(password)
[show source]
   # File lib/rodauth/features/disallow_common_passwords.rb
33 def password_not_one_of_the_most_common?(password)
34   return true unless password_one_of_most_common?(password)
35   set_password_requirement_error_message(:password_is_one_of_the_most_common, password_is_one_of_the_most_common_message)
36   false
37 end
password_not_too_many_repeating_characters?(password)
[show source]
   # File lib/rodauth/features/password_complexity.rb
68 def password_not_too_many_repeating_characters?(password)
69   return true if password_max_repeating_characters < 2
70   return true if password !~ /(.)(\1){#{password_max_repeating_characters-1}}/ 
71   set_password_requirement_error_message(:too_many_repeating_characters_in_password, password_too_many_repeating_characters_message)
72   false
73 end
password_one_of_most_common?(password)
[show source]
   # File lib/rodauth/features/disallow_common_passwords.rb
27 def password_one_of_most_common?(password)
28   most_common_passwords.include?(password)
29 end
password_recently_entered?()
[show source]
   # File lib/rodauth/features/password_grace_period.rb
22 def password_recently_entered?
23   return false unless last_password_entry = session[last_password_entry_session_key]
24   last_password_entry + password_grace_period > Time.now.to_i
25 end
password_reset_ds(id=account_id)
[show source]
    # File lib/rodauth/features/reset_password.rb
251 def password_reset_ds(id=account_id)
252   db[reset_password_table].where(reset_password_id_column=>id)
253 end
password_too_long_message()
[show source]
   # File lib/rodauth/features/login_password_requirements_base.rb
91 def password_too_long_message
92   "maximum #{password_maximum_length} characters"
93 end
password_too_many_bytes_message()
[show source]
   # File lib/rodauth/features/login_password_requirements_base.rb
95 def password_too_many_bytes_message
96   "maximum #{password_maximum_bytes} bytes"
97 end
password_too_short_message()
[show source]
    # File lib/rodauth/features/login_password_requirements_base.rb
 99 def password_too_short_message
100   "minimum #{password_minimum_length} characters"
101 end
possible_authentication_methods()
[show source]
    # File lib/rodauth/features/base.rb
504 def possible_authentication_methods
505   has_password? ? ['password'] : []
506 end
post_configure()
[show source]
    # File lib/rodauth/features/base.rb
407 def post_configure
408   require 'bcrypt' if require_bcrypt?
409   db.extension :date_arithmetic if use_date_arithmetic?
410 
411   if convert_token_id_to_integer?.nil? && (db rescue false) && db.table_exists?(accounts_table) && db.schema(accounts_table).find{|col, v| break v[:type] == :integer if col == account_id_column}
412     self.class.send(:define_method, :convert_token_id_to_integer?){true}
413   end
414 
415   route_hash= {}
416   self.class.routes.each do |meth|
417     route_meth = "#{meth.to_s.sub(/\Ahandle_/, '')}_route"
418     if route = send(route_meth)
419       route_hash["/#{route}"] = meth
420     end
421   end
422   self.class.route_hash = route_hash.freeze
423 end
previous_password_ds()
[show source]
   # File lib/rodauth/features/disallow_password_reuse.rb
94 def previous_password_ds
95   db[previous_password_hash_table].where(previous_password_account_id_column=>account_id)
96 end
raises_uniqueness_violation?(&block)

In cases where retrying on uniqueness violations cannot work, this will detect whether a uniqueness violation is raised by the block and return the exception if so. This method should be used if you don’t care about the exception itself.

[show source]
    # File lib/rodauth/features/base.rb
776 def raises_uniqueness_violation?(&block)
777   transaction(:savepoint=>:only, &block)
778   false
779 rescue unique_constraint_violation_class => e
780   e
781 end
random_key()
[show source]
    # File lib/rodauth/features/base.rb
576 def random_key
577   SecureRandom.urlsafe_base64(32)
578 end
raw_param(key)
[show source]
    # File lib/rodauth/features/base.rb
486 def raw_param(key)
487   request.params[key]
488 end
recovery_code_match?(code)
[show source]
    # File lib/rodauth/features/recovery_codes.rb
160 def recovery_code_match?(code)
161   recovery_codes.each do |s|
162     if timing_safe_eql?(code, s)
163       recovery_codes_ds.where(recovery_codes_column=>code).delete
164       if recovery_codes_primary?
165         add_recovery_code
166       end
167       return true
168     end
169   end
170   false
171 end
recovery_codes_available?()
[show source]
    # File lib/rodauth/features/recovery_codes.rb
196 def recovery_codes_available?
197   !recovery_codes_ds.empty?
198 end
recovery_codes_ds()
[show source]
    # File lib/rodauth/features/recovery_codes.rb
264 def recovery_codes_ds
265   db[recovery_codes_table].where(recovery_codes_id_column=>session_value)
266 end
recovery_codes_primary?()
[show source]
    # File lib/rodauth/features/recovery_codes.rb
244 def recovery_codes_primary?
245   (features & [:otp, :sms_codes, :webauthn]).empty?
246 end
recovery_codes_remove()
[show source]
    # File lib/rodauth/features/recovery_codes.rb
156 def recovery_codes_remove
157   recovery_codes_ds.delete
158 end
redirect(path)
[show source]
    # File lib/rodauth/features/base.rb
553 def redirect(path)
554   request.redirect(path)
555 end
redirect_two_factor_authenticated()
[show source]
    # File lib/rodauth/features/two_factor_base.rb
254 def redirect_two_factor_authenticated
255   saved_two_factor_auth_redirect = remove_session_value(two_factor_auth_redirect_session_key)
256   redirect saved_two_factor_auth_redirect || two_factor_auth_redirect
257 end
remember_key_ds(id=account_id)
[show source]
    # File lib/rodauth/features/remember.rb
247 def remember_key_ds(id=account_id)
248   db[remember_table].where(remember_id_column=>id)
249 end
remember_login()
[show source]
    # File lib/rodauth/features/remember.rb
128 def remember_login
129   get_remember_key
130   set_remember_cookie
131   set_session_value(remember_deadline_extended_session_key, Time.now.to_i) if extend_remember_deadline?
132 end
remembered_session_id()
[show source]
    # File lib/rodauth/features/remember.rb
 91 def remembered_session_id
 92   return unless cookie = _get_remember_cookie
 93   id, key = cookie.split('_', 2)
 94   return unless id && key
 95 
 96   actual, deadline = active_remember_key_ds(id).get([remember_key_column, remember_deadline_column])
 97   return unless actual
 98 
 99   if hmac_secret
100     unless valid = timing_safe_eql?(key, compute_hmac(actual))
101       unless raw_remember_token_deadline && raw_remember_token_deadline > convert_timestamp(deadline)
102         return
103       end
104     end
105   end
106 
107   unless valid || timing_safe_eql?(key, actual)
108     return
109   end
110 
111   id
112 end
remove_active_session(session_id)
[show source]
   # File lib/rodauth/features/active_sessions.rb
90 def remove_active_session(session_id)
91   active_sessions_ds.where(active_sessions_session_id_column=>session_id).delete
92 end
remove_all_active_sessions()
[show source]
   # File lib/rodauth/features/active_sessions.rb
94 def remove_all_active_sessions
95   active_sessions_ds.delete
96 end
remove_all_webauthn_keys_and_user_ids()
[show source]
    # File lib/rodauth/features/webauthn.rb
381 def remove_all_webauthn_keys_and_user_ids
382   webauthn_user_ids_ds.delete
383   webauthn_keys_ds.delete
384 end
remove_current_session()
[show source]
   # File lib/rodauth/features/active_sessions.rb
84 def remove_current_session
85   if session_id = session[session_id_session_key]
86     remove_active_session(compute_hmac(session_id))
87   end
88 end
remove_email_auth_key()
[show source]
    # File lib/rodauth/features/email_auth.rb
129 def remove_email_auth_key
130   email_auth_ds.delete
131 end
remove_inactive_sessions()
[show source]
    # File lib/rodauth/features/active_sessions.rb
 98 def remove_inactive_sessions
 99   if cond = inactive_session_cond
100     active_sessions_ds.where(cond).delete
101   end
102 end
remove_jwt_refresh_token_key(token)
[show source]
    # File lib/rodauth/features/jwt_refresh.rb
178 def remove_jwt_refresh_token_key(token)
179   account_id, token_id, _ = _account_refresh_token_split(token)
180   jwt_refresh_token_account_token_ds(account_id, token_id).delete
181 end
remove_lockout_metadata()
[show source]
    # File lib/rodauth/features/lockout.rb
272 def remove_lockout_metadata
273   account_login_failures_ds.delete
274   account_lockouts_ds.delete
275 end
remove_remember_key(id=account_id)
[show source]
    # File lib/rodauth/features/remember.rb
166 def remove_remember_key(id=account_id)
167   remember_key_ds(id).delete
168 end
remove_reset_password_key()
[show source]
    # File lib/rodauth/features/reset_password.rb
179 def remove_reset_password_key
180   password_reset_ds.delete
181 end
remove_session_value(key)
[show source]
    # File lib/rodauth/features/base.rb
825 def remove_session_value(key)
826   session.delete(key)
827 end
remove_verify_account_key()
[show source]
    # File lib/rodauth/features/verify_account.rb
174 def remove_verify_account_key
175   verify_account_ds.delete
176 end
remove_verify_login_change_key()
[show source]
    # File lib/rodauth/features/verify_login_change.rb
110 def remove_verify_login_change_key
111   verify_login_change_ds.delete
112 end
remove_webauthn_key(webauthn_id)
[show source]
    # File lib/rodauth/features/webauthn.rb
377 def remove_webauthn_key(webauthn_id)
378   webauthn_keys_ds.where(webauthn_keys_webauthn_id_column=>webauthn_id).delete == 1
379 end
render(page)
[show source]
    # File lib/rodauth/features/base.rb
399 def render(page)
400   _view(:render, page)
401 end
render_multi_phase_login_forms()
[show source]
    # File lib/rodauth/features/login.rb
133 def render_multi_phase_login_forms
134   multi_phase_login_forms.sort.map{|_, form, _| form}.join("\n")
135 end
request()
[show source]
    # File lib/rodauth/features/base.rb
147 def request
148   scope.request
149 end
require_account()
[show source]
    # File lib/rodauth/features/base.rb
349 def require_account
350   require_authentication
351   require_account_session
352 end
require_account_session()
[show source]
    # File lib/rodauth/features/base.rb
594 def require_account_session
595   unless account_from_session
596     clear_session
597     login_required
598   end
599 end
require_authentication()
[show source]
    # File lib/rodauth/features/base.rb
345 def require_authentication
346   require_login
347 end
require_current_password()
[show source]
   # File lib/rodauth/features/password_expiration.rb
61 def require_current_password
62   if authenticated? && password_expired? && password_change_needed_redirect != request.path_info
63     set_redirect_error_flash password_expiration_error_flash
64     redirect password_change_needed_redirect
65   end
66 end
require_http_basic_auth()
[show source]
   # File lib/rodauth/features/http_basic_auth.rb
27 def require_http_basic_auth
28   unless http_basic_auth
29     set_http_basic_auth_error_response
30     return_response
31   end
32 end
require_login()
[show source]
    # File lib/rodauth/features/base.rb
337 def require_login
338   login_required unless logged_in?
339 end
require_login_confirmation?()
[show source]
    # File lib/rodauth/features/verify_account.rb
166 def require_login_confirmation?
167   false
168 end
require_otp_setup()
[show source]
    # File lib/rodauth/features/otp.rb
233 def require_otp_setup
234   unless otp_exists?
235     set_redirect_error_status(two_factor_not_setup_error_status)
236     set_error_reason :two_factor_not_setup
237     set_redirect_error_flash two_factor_not_setup_error_flash
238     redirect two_factor_need_setup_redirect
239   end
240 end
require_password_authentication()
[show source]
   # File lib/rodauth/features/confirm_password.rb
51 def require_password_authentication
52   require_login
53 
54   if require_password_authentication? && has_password?
55     set_redirect_error_status(password_authentication_required_error_status)
56     set_error_reason :password_authentication_required
57     set_redirect_error_flash password_authentication_required_error_flash
58     set_session_value(confirm_password_redirect_session_key, request.fullpath)
59     redirect password_authentication_required_redirect
60   end
61 end
require_password_authentication?()
[show source]
   # File lib/rodauth/features/confirm_password.rb
87 def require_password_authentication?
88   return true if defined?(super) && super
89   !authenticated_by.include?('password')
90 end
require_sms_available()
[show source]
    # File lib/rodauth/features/sms_codes.rb
329 def require_sms_available
330   require_sms_setup
331 
332   if sms_locked_out?
333     set_redirect_error_status(lockout_error_status)
334     set_error_reason :sms_locked_out
335     set_redirect_error_flash sms_lockout_error_flash
336     redirect sms_lockout_redirect
337   end
338 end
require_sms_not_setup()
[show source]
    # File lib/rodauth/features/sms_codes.rb
320 def require_sms_not_setup
321   if sms_setup?
322     set_redirect_error_status(sms_already_setup_error_status)
323     set_error_reason :sms_already_setup
324     set_redirect_error_flash sms_already_setup_error_flash
325     redirect sms_already_setup_redirect
326   end
327 end
require_sms_setup()
[show source]
    # File lib/rodauth/features/sms_codes.rb
311 def require_sms_setup
312   unless sms_setup?
313     set_redirect_error_status(two_factor_not_setup_error_status)
314     set_error_reason :sms_not_setup
315     set_redirect_error_flash sms_not_setup_error_flash
316     redirect sms_needs_setup_redirect
317   end
318 end
require_two_factor_authenticated()
[show source]
    # File lib/rodauth/features/two_factor_base.rb
165 def require_two_factor_authenticated
166   unless two_factor_authenticated?
167     if two_factor_auth_return_to_requested_location?
168       set_session_value(two_factor_auth_redirect_session_key, request.fullpath)
169     end
170     set_redirect_error_status(two_factor_need_authentication_error_status)
171     set_error_reason :two_factor_need_authentication
172     set_redirect_error_flash two_factor_need_authentication_error_flash
173     redirect two_factor_auth_required_redirect
174   end
175 end
require_two_factor_not_authenticated(auth_type = nil)
[show source]
    # File lib/rodauth/features/two_factor_base.rb
156 def require_two_factor_not_authenticated(auth_type = nil)
157   if two_factor_authenticated? || (auth_type && two_factor_login_type_match?(auth_type))
158     set_redirect_error_status(two_factor_already_authenticated_error_status)
159     set_error_reason :two_factor_already_authenticated
160     set_redirect_error_flash two_factor_already_authenticated_error_flash
161     redirect two_factor_already_authenticated_redirect
162   end
163 end
require_two_factor_setup()
[show source]
    # File lib/rodauth/features/two_factor_base.rb
144 def require_two_factor_setup
145   # Avoid database query if already authenticated via 2nd factor
146   return if two_factor_authenticated?
147 
148   return if uses_two_factor_authentication?
149 
150   set_redirect_error_status(two_factor_not_setup_error_status)
151   set_error_reason :two_factor_not_setup
152   set_redirect_error_flash two_factor_not_setup_error_flash
153   redirect two_factor_need_setup_redirect
154 end
require_webauthn_setup()
[show source]
    # File lib/rodauth/features/webauthn.rb
390 def require_webauthn_setup
391   unless webauthn_setup?
392     set_redirect_error_status(webauthn_not_setup_error_status)
393     set_error_reason :webauthn_not_setup
394     set_redirect_error_flash webauthn_not_setup_error_flash
395     redirect two_factor_need_setup_redirect
396   end
397 end
rescue_jwt_payload(_)
[show source]
    # File lib/rodauth/features/jwt.rb
121 def rescue_jwt_payload(_)
122   @jwt_payload = false
123 end
reset_password_email_recently_sent?()
[show source]
    # File lib/rodauth/features/reset_password.rb
215 def reset_password_email_recently_sent?
216   (email_last_sent = get_reset_password_email_last_sent) && (Time.now - email_last_sent < reset_password_skip_resend_email_within)
217 end
reset_password_key_insert_hash()
[show source]
    # File lib/rodauth/features/reset_password.rb
245 def reset_password_key_insert_hash
246   hash = {reset_password_id_column=>account_id, reset_password_key_column=>reset_password_key_value}
247   set_deadline_value(hash, reset_password_deadline_column, reset_password_deadline_interval)
248   hash
249 end
reset_single_session_key()
[show source]
   # File lib/rodauth/features/single_session.rb
22 def reset_single_session_key
23   if logged_in?
24     single_session_ds.update(single_session_key_column=>random_key)
25   end
26 end
response()
[show source]
    # File lib/rodauth/features/base.rb
151 def response
152   scope.response
153 end
retry_on_uniqueness_violation(&block)

This is used to avoid race conditions when using the pattern of inserting when an update affects no rows. In such cases, if a row is inserted between the update and the insert, the insert will fail with a uniqueness error, but retrying will work. It is possible for it to fail again, but only if the row is deleted before the update and readded before the insert, which is very unlikely to happen. In such cases, raising an exception is acceptable.

[show source]
    # File lib/rodauth/features/base.rb
767 def retry_on_uniqueness_violation(&block)
768   if raises_uniqueness_violation?(&block)
769     yield
770   end
771 end
return_json_response()
[show source]
    # File lib/rodauth/features/json.rb
170 def return_json_response
171   _return_json_response
172 end
return_response(body=nil)
[show source]
    # File lib/rodauth/features/base.rb
557 def return_response(body=nil)
558   response.write(body) if body
559   request.halt
560 end
route!()
[show source]
    # File lib/rodauth/features/base.rb
163 def route!
164   if meth = self.class.route_hash[request.remaining_path]
165     send(meth)
166   end
167 
168   nil
169 end
route_path(route, opts={})
[show source]
    # File lib/rodauth/features/base.rb
562 def route_path(route, opts={})
563   path  = "#{prefix}/#{route}"
564   path += "?#{Rack::Utils.build_nested_query(opts)}" unless opts.empty?
565   path
566 end
route_url(route, opts={})
[show source]
    # File lib/rodauth/features/base.rb
568 def route_url(route, opts={})
569   "#{base_url}#{route_path(route, opts)}"
570 end
save_account()
[show source]
    # File lib/rodauth/features/create_account.rb
100 def save_account
101   id = nil
102   raised = raises_uniqueness_violation?{id = db[accounts_table].insert(account)}
103 
104   if raised
105     set_login_requirement_error_message(:already_an_account_with_this_login, already_an_account_with_this_login_message)
106   end
107 
108   if id
109     account[account_id_column] = id
110   end
111 
112   id && !raised
113 end
send_email(email)
[show source]
   # File lib/rodauth/features/email_base.rb
36 def send_email(email)
37   email.deliver!
38 end
send_verify_login_change_email(login)
[show source]
    # File lib/rodauth/features/verify_login_change.rb
126 def send_verify_login_change_email(login)
127   send_email(create_verify_login_change_email(login))
128 end
serialize_audit_log_metadata(metadata)
[show source]
   # File lib/rodauth/features/audit_logging.rb
55 def serialize_audit_log_metadata(metadata)
56   metadata.to_json unless metadata.nil?
57 end
session()
[show source]
    # File lib/rodauth/features/base.rb
155 def session
156   scope.session
157 end
session_inactivity_deadline_condition()
[show source]
    # File lib/rodauth/features/active_sessions.rb
156 def session_inactivity_deadline_condition
157   if deadline = session_inactivity_deadline
158     Sequel[active_sessions_last_use_column] < Sequel.date_sub(Sequel::CURRENT_TIMESTAMP, seconds: deadline)
159   end
160 end
session_jwt()
[show source]
   # File lib/rodauth/features/jwt.rb
75 def session_jwt
76   JWT.encode(jwt_session_hash, jwt_secret, jwt_algorithm)
77 end
session_lifetime_deadline_condition()
[show source]
    # File lib/rodauth/features/active_sessions.rb
162 def session_lifetime_deadline_condition
163   if deadline = session_lifetime_deadline
164     Sequel[active_sessions_created_at_column] < Sequel.date_sub(Sequel::CURRENT_TIMESTAMP, seconds: deadline)
165   end
166 end
session_value()
[show source]
    # File lib/rodauth/features/base.rb
255 def session_value
256   session[session_key]
257 end
set_deadline_value(hash, column, interval)

This is needed on MySQL, which doesn’t support non constant defaults other than CURRENT_TIMESTAMP.

[show source]
    # File lib/rodauth/features/base.rb
803 def set_deadline_value(hash, column, interval)
804   if set_deadline_values?
805     # :nocov:
806     hash[column] = Sequel.date_add(Sequel::CURRENT_TIMESTAMP, interval)
807     # :nocov:
808   end
809 end
set_deadline_values?()
[show source]
    # File lib/rodauth/features/base.rb
640 def set_deadline_values?
641   db.database_type == :mysql
642 end
set_email_auth_email_last_sent()
[show source]
    # File lib/rodauth/features/email_auth.rb
117 def set_email_auth_email_last_sent
118    email_auth_ds.update(email_auth_email_last_sent_column=>Sequel::CURRENT_TIMESTAMP) if email_auth_email_last_sent_column
119 end
set_error_flash(message)
[show source]
    # File lib/rodauth/features/base.rb
321 def set_error_flash(message)
322   flash.now[flash_error_key] = message
323 end
set_error_reason(reason)
[show source]
    # File lib/rodauth/features/base.rb
628 def set_error_reason(reason)
629 end
set_expired()
[show source]
   # File lib/rodauth/features/account_expiration.rb
49 def set_expired
50   update_activity(account_id, account_activity_expired_column)
51   after_account_expiration
52 end
set_field_error(field, error)
[show source]
    # File lib/rodauth/features/base.rb
171 def set_field_error(field, error)
172   (@field_errors ||= {})[field] = error
173 end
set_http_basic_auth_error_response()
[show source]
   # File lib/rodauth/features/http_basic_auth.rb
74 def set_http_basic_auth_error_response
75   response.status = 401
76   response.headers["WWW-Authenticate"] = "Basic realm=\"#{http_basic_auth_realm}\""
77 end
set_jwt()
[show source]
    # File lib/rodauth/features/jwt.rb
142 def set_jwt
143   set_jwt_token(session_jwt)
144 end
set_jwt_refresh_token_hmac_session_key(token)
[show source]
    # File lib/rodauth/features/jwt_refresh.rb
194 def set_jwt_refresh_token_hmac_session_key(token)
195   if allow_refresh_with_expired_jwt_access_token?
196     key = _account_refresh_token_split(token).last
197     data = random_key
198     set_session_value(jwt_refresh_token_data_session_key, data)
199     set_session_value(jwt_refresh_token_hmac_session_key, compute_hmac(data + key))
200   end
201 end
set_jwt_token(token)
[show source]
   # File lib/rodauth/features/jwt.rb
87 def set_jwt_token(token)
88   response.headers['Authorization'] = token
89 end
set_last_password_entry()
[show source]
   # File lib/rodauth/features/password_grace_period.rb
44 def set_last_password_entry
45   set_session_value(last_password_entry_session_key, Time.now.to_i)
46 end
set_login_requirement_error_message(reason, message)
[show source]
    # File lib/rodauth/features/login_password_requirements_base.rb
124 def set_login_requirement_error_message(reason, message)
125   set_error_reason(reason)
126   @login_requirement_message = message
127 end
set_new_account_password(password)
[show source]
   # File lib/rodauth/features/create_account.rb
92 def set_new_account_password(password)
93   account[account_password_hash_column] = password_hash(password)
94 end
set_notice_flash(message)
[show source]
    # File lib/rodauth/features/base.rb
329 def set_notice_flash(message)
330   flash[flash_notice_key] = message
331 end
set_notice_now_flash(message)
[show source]
    # File lib/rodauth/features/base.rb
333 def set_notice_now_flash(message)
334   flash.now[flash_notice_key] = message
335 end
set_password(password)
[show source]
   # File lib/rodauth/features/disallow_password_reuse.rb
19 def set_password(password)
20   hash = super
21   add_previous_password_hash(hash)
22   hash
23 end
set_password_requirement_error_message(reason, message)
[show source]
    # File lib/rodauth/features/login_password_requirements_base.rb
103 def set_password_requirement_error_message(reason, message)
104   set_error_reason(reason)
105   @password_requirement_message = message
106 end
set_redirect_error_flash(message)
[show source]
    # File lib/rodauth/features/base.rb
325 def set_redirect_error_flash(message)
326   flash[flash_error_key] = message
327 end
set_redirect_error_status(status)

Don’t set an error status when redirecting in an error case, as a redirect status is needed.

[show source]
    # File lib/rodauth/features/base.rb
606 def set_redirect_error_status(status)
607 end
set_reset_password_email_last_sent()
[show source]
    # File lib/rodauth/features/reset_password.rb
197 def set_reset_password_email_last_sent
198    password_reset_ds.update(reset_password_email_last_sent_column=>Sequel::CURRENT_TIMESTAMP) if reset_password_email_last_sent_column
199 end
set_response_error_reason_status(reason, status)
[show source]
    # File lib/rodauth/features/base.rb
613 def set_response_error_reason_status(reason, status)
614   set_error_reason(reason)
615   set_response_error_status(status)
616 end
set_response_error_status(status)
[show source]
    # File lib/rodauth/features/base.rb
609 def set_response_error_status(status)
610   response.status = status
611 end
set_session_value(key, value)
[show source]
    # File lib/rodauth/features/base.rb
821 def set_session_value(key, value)
822   session[key] = value
823 end
set_single_session_key(data)
[show source]
   # File lib/rodauth/features/single_session.rb
93 def set_single_session_key(data)
94   data = compute_hmac(data) if hmac_secret
95   set_session_value(single_session_session_key, data)
96 end
set_title(title)
[show source]
    # File lib/rodauth/features/base.rb
315 def set_title(title)
316   if title_instance_variable
317     scope.instance_variable_set(title_instance_variable, title)
318   end
319 end
set_unlock_account_email_last_sent()
[show source]
    # File lib/rodauth/features/lockout.rb
238 def set_unlock_account_email_last_sent
239   account_lockouts_ds.update(account_lockouts_email_last_sent_column=>Sequel::CURRENT_TIMESTAMP) if account_lockouts_email_last_sent_column
240 end
set_verify_account_email_last_sent()
[show source]
    # File lib/rodauth/features/verify_account.rb
232 def set_verify_account_email_last_sent
233    verify_account_ds.update(verify_account_email_last_sent_column=>Sequel::CURRENT_TIMESTAMP) if verify_account_email_last_sent_column
234 end
setup_account_verification()
[show source]
    # File lib/rodauth/features/verify_account.rb
244 def setup_account_verification
245   generate_verify_account_key_value
246   create_verify_account_key
247   send_verify_account_email
248 end
show_lockout_page()
[show source]
    # File lib/rodauth/features/lockout.rb
277 def show_lockout_page
278   set_response_error_reason_status(:account_locked_out, lockout_error_status)
279   set_error_flash login_lockout_error_flash
280   return_response unlock_account_request_view
281 end
single_session_ds()
[show source]
    # File lib/rodauth/features/single_session.rb
 98 def single_session_ds
 99   db[single_session_table].
100     where(single_session_id_column=>session_value)
101 end
skip_login_field_on_login?()
[show source]
    # File lib/rodauth/features/login.rb
111 def skip_login_field_on_login?
112   return false unless use_multi_phase_login?
113   valid_login_entered?
114 end
skip_password_field_on_login?()
[show source]
    # File lib/rodauth/features/login.rb
116 def skip_password_field_on_login?
117   return false unless use_multi_phase_login?
118   !valid_login_entered?
119 end
skip_status_checks?()
[show source]
   # File lib/rodauth/features/close_account.rb
84 def skip_status_checks?
85   false
86 end
sms_auth_message(code)
[show source]
    # File lib/rodauth/features/sms_codes.rb
390 def sms_auth_message(code)
391   "SMS authentication code for #{domain} is #{code}"
392 end
sms_available?()
[show source]
    # File lib/rodauth/features/sms_codes.rb
432 def sms_available?
433   sms_setup? && !sms_locked_out?
434 end
sms_code()
[show source]
    # File lib/rodauth/features/sms_codes.rb
411 def sms_code
412   sms[sms_code_column]
413 end
sms_code_issued_at()
[show source]
    # File lib/rodauth/features/sms_codes.rb
415 def sms_code_issued_at
416   convert_timestamp(sms[sms_issued_at_column])
417 end
sms_code_match?(code)
[show source]
    # File lib/rodauth/features/sms_codes.rb
340 def sms_code_match?(code)
341   return false unless sms_current_auth?
342   timing_safe_eql?(code, sms_code)
343 end
sms_codes_primary?()
[show source]
    # File lib/rodauth/features/sms_codes.rb
475 def sms_codes_primary?
476   (features & [:otp, :webauthn]).empty?
477 end
sms_confirm()
[show source]
    # File lib/rodauth/features/recovery_codes.rb
146 def sms_confirm
147   super if defined?(super)
148   auto_add_missing_recovery_codes
149 end
sms_confirm_failure()
[show source]
    # File lib/rodauth/features/sms_codes.rb
354 def sms_confirm_failure
355   sms_ds.delete
356 end
sms_confirm_message(code)
[show source]
    # File lib/rodauth/features/sms_codes.rb
394 def sms_confirm_message(code)
395   "SMS confirmation code for #{domain} is #{code}"
396 end
sms_confirmation_match?(code)
[show source]
    # File lib/rodauth/features/sms_codes.rb
345 def sms_confirmation_match?(code)
346   sms_needs_confirmation? && sms_code_match?(code)
347 end
sms_current_auth?()
[show source]
    # File lib/rodauth/features/sms_codes.rb
440 def sms_current_auth?
441   sms_code && sms_code_issued_at + sms_code_allowed_seconds > Time.now
442 end
sms_disable()
[show source]
    # File lib/rodauth/features/sms_codes.rb
349 def sms_disable
350   sms_ds.delete
351   @sms = nil
352 end
sms_ds()
[show source]
    # File lib/rodauth/features/sms_codes.rb
503 def sms_ds
504   db[sms_codes_table].where(sms_id_column=>session_value)
505 end
sms_failures()
[show source]
    # File lib/rodauth/features/sms_codes.rb
419 def sms_failures
420   sms[sms_failures_column]
421 end
sms_locked_out?()
[show source]
    # File lib/rodauth/features/sms_codes.rb
436 def sms_locked_out?
437   sms_failures >= sms_failure_limit
438 end
sms_needs_confirmation?()
[show source]
    # File lib/rodauth/features/sms_codes.rb
428 def sms_needs_confirmation?
429   sms && sms_failures.nil?
430 end
sms_new_auth_code()
[show source]
    # File lib/rodauth/features/sms_codes.rb
483 def sms_new_auth_code
484   SecureRandom.random_number(10**sms_auth_code_length).to_s.rjust(sms_auth_code_length, "0")
485 end
sms_new_confirm_code()
[show source]
    # File lib/rodauth/features/sms_codes.rb
487 def sms_new_confirm_code
488   SecureRandom.random_number(10**sms_confirm_code_length).to_s.rjust(sms_confirm_code_length, "0")
489 end
sms_normalize_phone(phone)
[show source]
    # File lib/rodauth/features/sms_codes.rb
479 def sms_normalize_phone(phone)
480   phone.to_s.gsub(/\D+/, '')
481 end
sms_phone()
[show source]
    # File lib/rodauth/features/sms_codes.rb
407 def sms_phone
408   sms[sms_phone_column]
409 end
sms_record_failure()
[show source]
    # File lib/rodauth/features/sms_codes.rb
402 def sms_record_failure
403   update_sms(sms_failures_column=>Sequel.expr(sms_failures_column)+1)
404   sms[sms_failures_column] = sms_ds.get(sms_failures_column)
405 end
sms_remove_failures()
[show source]
    # File lib/rodauth/features/sms_codes.rb
365 def sms_remove_failures
366   update_sms(sms_failures_column => 0, sms_code_column => nil)
367 end
sms_send(phone, message)
[show source]
    # File lib/rodauth/features/sms_codes.rb
491 def sms_send(phone, message)
492   raise NotImplementedError, "sms_send needs to be defined in the Rodauth configuration for SMS sending to work"
493 end
sms_send_auth_code()
[show source]
    # File lib/rodauth/features/sms_codes.rb
374 def sms_send_auth_code
375   code = sms_new_auth_code
376   sms_set_code(code)
377   sms_send(sms_phone, sms_auth_message(code))
378 end
sms_send_confirm_code()
[show source]
    # File lib/rodauth/features/sms_codes.rb
380 def sms_send_confirm_code
381   code = sms_new_confirm_code
382   sms_set_code(code)
383   sms_send(sms_phone, sms_confirm_message(code))
384 end
sms_set_code(code)
[show source]
    # File lib/rodauth/features/sms_codes.rb
398 def sms_set_code(code)
399  update_sms(sms_code_column=>code, sms_issued_at_column=>Sequel::CURRENT_TIMESTAMP)
400 end
sms_setup(phone_number)
[show source]
    # File lib/rodauth/features/sms_codes.rb
358 def sms_setup(phone_number)
359   # Cannot handle uniqueness violation here, as the phone number given may not match the
360   # one in the table.
361   sms_ds.insert(sms_id_column=>session_value, sms_phone_column=>phone_number)
362   remove_instance_variable(:@sms) if instance_variable_defined?(:@sms)
363 end
sms_setup?()
[show source]
    # File lib/rodauth/features/sms_codes.rb
423 def sms_setup?
424   return false unless sms
425   !sms_needs_confirmation?
426 end
sms_valid_phone?(phone)
[show source]
    # File lib/rodauth/features/sms_codes.rb
386 def sms_valid_phone?(phone)
387   phone.length >= sms_phone_min_length
388 end
split_token(token)
[show source]
    # File lib/rodauth/features/base.rb
530 def split_token(token)
531   token.split(token_separator, 2)
532 end
template_path(page)
[show source]
    # File lib/rodauth/features/base.rb
732 def template_path(page)
733   File.join(File.dirname(__FILE__), '../../../templates', "#{page}.str")
734 end
throw_basic_auth_error(*args)
[show source]
   # File lib/rodauth/features/http_basic_auth.rb
79 def throw_basic_auth_error(*args)
80   set_http_basic_auth_error_response
81   throw_error(*args) 
82 end
throw_error(field, error)
[show source]
    # File lib/rodauth/features/base.rb
618 def throw_error(field, error)
619   set_field_error(field, error)
620   throw :rodauth_error
621 end
throw_error_reason(reason, status, field, message)
[show source]
    # File lib/rodauth/features/base.rb
631 def throw_error_reason(reason, status, field, message)
632   set_error_reason(reason)
633   throw_error_status(status, field, message)
634 end
throw_error_status(status, field, error)
[show source]
    # File lib/rodauth/features/base.rb
623 def throw_error_status(status, field, error)
624   set_response_error_status(status)
625   throw_error(field, error)
626 end
timing_safe_eql?(provided, actual)
[show source]
    # File lib/rodauth/features/base.rb
589 def timing_safe_eql?(provided, actual)
590   provided = provided.to_s
591   Rack::Utils.secure_compare(provided.ljust(actual.length), actual) && provided.length == actual.length
592 end
token_param_value(key)
[show source]
   # File lib/rodauth/features/email_base.rb
57 def token_param_value(key)
58   "#{account_id}#{token_separator}#{convert_email_token_key(key)}"
59 end
transaction(opts={}, &block)
[show source]
    # File lib/rodauth/features/base.rb
572 def transaction(opts={}, &block)
573   db.transaction(opts, &block)
574 end
translate(_key, default)
[show source]
    # File lib/rodauth/features/base.rb
238 def translate(_key, default)
239   # do not attempt to translate by default
240   default
241 end
two_factor_authenticate(type)
[show source]
    # File lib/rodauth/features/two_factor_base.rb
246 def two_factor_authenticate(type)
247   two_factor_update_session(type)
248   two_factor_remove_auth_failures
249   after_two_factor_authentication
250   set_notice_flash two_factor_auth_notice_flash
251   redirect_two_factor_authenticated
252 end
two_factor_authenticated?()
[show source]
    # File lib/rodauth/features/two_factor_base.rb
189 def two_factor_authenticated?
190   authenticated_by && authenticated_by.length >= 2
191 end
two_factor_authentication_setup?()
[show source]
    # File lib/rodauth/features/two_factor_base.rb
193 def two_factor_authentication_setup?
194   possible_authentication_methods.length >= 2
195 end
two_factor_login_type_match?(type)
[show source]
    # File lib/rodauth/features/two_factor_base.rb
203 def two_factor_login_type_match?(type)
204   authenticated_by && authenticated_by.include?(type)
205 end
two_factor_modifications_require_password?()
[show source]
    # File lib/rodauth/features/two_factor_base.rb
120 def two_factor_modifications_require_password?
121   modifications_require_password?
122 end
two_factor_password_match?(password)
[show source]
    # File lib/rodauth/features/two_factor_base.rb
181 def two_factor_password_match?(password)
182   if two_factor_modifications_require_password?
183     password_match?(password)
184   else
185     true
186   end
187 end
two_factor_remove()
[show source]
    # File lib/rodauth/features/otp.rb
223 def two_factor_remove
224   super
225   otp_remove
226 end
two_factor_remove_auth_failures()
[show source]
    # File lib/rodauth/features/otp.rb
228 def two_factor_remove_auth_failures
229   super
230   otp_remove_auth_failures
231 end
two_factor_remove_session(type)
[show source]
    # File lib/rodauth/features/two_factor_base.rb
259 def two_factor_remove_session(type)
260   authenticated_by.delete(type)
261   remove_session_value(two_factor_setup_session_key)
262   if authenticated_by.empty?
263     clear_session
264   end
265 end
two_factor_update_session(auth_type)
[show source]
    # File lib/rodauth/features/two_factor_base.rb
267 def two_factor_update_session(auth_type)
268   authenticated_by << auth_type
269   set_session_value(two_factor_setup_session_key, true)
270 end
unique_constraint_violation_class()

Work around jdbc/sqlite issue where it only raises ConstraintViolation and not UniqueConstraintViolation.

[show source]
    # File lib/rodauth/features/base.rb
785 def unique_constraint_violation_class
786   if db.adapter_scheme == :jdbc && db.database_type == :sqlite
787     # :nocov:
788     Sequel::ConstraintViolation
789     # :nocov:
790   else
791     Sequel::UniqueConstraintViolation
792   end
793 end
unlock_account()
[show source]
    # File lib/rodauth/features/lockout.rb
161 def unlock_account
162   transaction do
163     remove_lockout_metadata
164   end
165 end
unlock_account_email_recently_sent?()
[show source]
    # File lib/rodauth/features/lockout.rb
283 def unlock_account_email_recently_sent?
284   (email_last_sent = get_unlock_account_email_last_sent) && (Time.now - email_last_sent < unlock_account_skip_resend_email_within)
285 end
unverified_grace_period_expired?()
[show source]
   # File lib/rodauth/features/verify_account_grace_period.rb
92 def unverified_grace_period_expired?
93   return false unless expires_at = session[unverified_account_session_key]
94   expires_at.is_a?(Integer) && Time.now.to_i > expires_at
95 end
update_account(values, ds=account_ds)
[show source]
    # File lib/rodauth/features/base.rb
839 def update_account(values, ds=account_ds)
840   update_hash_ds(account, ds, values)
841 end
update_activity(account_id, *columns)
[show source]
    # File lib/rodauth/features/account_expiration.rb
113 def update_activity(account_id, *columns)
114   ds = account_activity_ds(account_id)
115   hash = {}
116   columns.each do |c|
117     hash[c] = Sequel::CURRENT_TIMESTAMP
118   end
119   if ds.update(hash) == 0
120     hash[account_activity_id_column] = account_id
121     hash[account_activity_last_activity_column] ||= Sequel::CURRENT_TIMESTAMP
122     hash[account_activity_last_login_column] ||= Sequel::CURRENT_TIMESTAMP
123     # It is safe to ignore uniqueness violations here, as a concurrent insert would also use current timestamps.
124     ignore_uniqueness_violation{ds.insert(hash)}
125   end
126 end
update_current_session?()
[show source]
    # File lib/rodauth/features/active_sessions.rb
175 def update_current_session?
176   !!session_inactivity_deadline
177 end
update_hash_ds(hash, ds, values)
[show source]
    # File lib/rodauth/features/base.rb
829 def update_hash_ds(hash, ds, values)
830   num = ds.update(values)
831   if num == 1
832     values.each do |k, v|
833       hash[k] = Sequel::CURRENT_TIMESTAMP == v ? Time.now : v
834     end
835   end
836   num
837 end
update_last_activity()
[show source]
   # File lib/rodauth/features/account_expiration.rb
43 def update_last_activity
44   if session_value
45     update_activity(session_value, account_activity_last_activity_column)
46   end
47 end
update_last_login()
[show source]
   # File lib/rodauth/features/account_expiration.rb
39 def update_last_login
40   update_activity(account_id, account_activity_last_login_column, account_activity_last_activity_column)
41 end
update_login(login)
[show source]
   # File lib/rodauth/features/change_login.rb
79 def update_login(login)
80   _update_login(login)
81 end
update_password_changed_at()
[show source]
   # File lib/rodauth/features/password_expiration.rb
52 def update_password_changed_at
53   ds = password_expiration_ds
54   if ds.update(password_expiration_changed_at_column=>Sequel::CURRENT_TIMESTAMP) == 0
55     # Ignoring the violation is safe here, since a concurrent insert would also set it to the
56     # current timestamp.
57     ignore_uniqueness_violation{ds.insert(password_expiration_id_column=>account_id)}
58   end
59 end
update_password_hash?()
[show source]
   # File lib/rodauth/features/update_password_hash.rb
17 def update_password_hash?
18   password_hash_cost != @current_password_hash_cost
19 end
update_session()
[show source]
   # File lib/rodauth/features/account_expiration.rb
72 def update_session
73   check_account_expiration
74   super
75 end
update_single_session_key()
[show source]
   # File lib/rodauth/features/single_session.rb
65 def update_single_session_key
66   key = random_key
67   set_single_session_key(key)
68   if single_session_ds.update(single_session_key_column=>key) == 0
69     # Don't handle uniqueness violations here.  While we could get the stored key from the
70     # database, it could lead to two sessions sharing the same key, which this feature is
71     # designed to prevent.
72     single_session_ds.insert(single_session_id_column=>session_value, single_session_key_column=>key)
73   end
74 end
update_sms(values)
[show source]
    # File lib/rodauth/features/sms_codes.rb
495 def update_sms(values)
496   update_hash_ds(sms, sms_ds, values)
497 end
use_database_authentication_functions?()
[show source]
    # File lib/rodauth/features/base.rb
644 def use_database_authentication_functions?
645   case db.database_type
646   when :postgres, :mysql, :mssql
647     true
648   else
649     # :nocov:
650     false
651     # :nocov:
652   end
653 end
use_date_arithmetic?()
[show source]
    # File lib/rodauth/features/active_sessions.rb
184 def use_date_arithmetic?
185   true
186 end
use_json?()
[show source]
   # File lib/rodauth/features/json.rb
59 def use_json?
60   json_request? || only_json?
61 end
use_jwt?()
[show source]
   # File lib/rodauth/features/jwt.rb
91 def use_jwt?
92   use_json?
93 end
use_multi_phase_login?()
[show source]
    # File lib/rodauth/features/email_auth.rb
158 def use_multi_phase_login?
159   true
160 end
use_request_specific_csrf_tokens?()
[show source]
    # File lib/rodauth/features/base.rb
655 def use_request_specific_csrf_tokens?
656   scope.opts[:rodauth_route_csrf] && scope.use_request_specific_csrf_tokens?
657 end
uses_two_factor_authentication?()
[show source]
    # File lib/rodauth/features/two_factor_base.rb
197 def uses_two_factor_authentication?
198   return false unless logged_in?
199   set_session_value(two_factor_setup_session_key, two_factor_authentication_setup?) unless session.has_key?(two_factor_setup_session_key)
200   session[two_factor_setup_session_key]
201 end
valid_jwt?()
[show source]
    # File lib/rodauth/features/jwt.rb
 99 def valid_jwt?
100   !!(jwt_token && jwt_payload)
101 end
valid_login_entered?()
[show source]
    # File lib/rodauth/features/login.rb
121 def valid_login_entered?
122   @valid_login_entered
123 end
valid_new_webauthn_credential?(webauthn_credential)
[show source]
    # File lib/rodauth/features/webauthn.rb
308 def valid_new_webauthn_credential?(webauthn_credential)
309   # Hack around inability to override expected_origin
310   origin = webauthn_origin
311   webauthn_credential.response.define_singleton_method(:verify) do |expected_challenge, expected_origin = nil, **kw|
312     super(expected_challenge, expected_origin || origin, **kw)
313   end
314 
315   (challenge = param_or_nil(webauthn_setup_challenge_param)) &&
316     (hmac = param_or_nil(webauthn_setup_challenge_hmac_param)) &&
317     timing_safe_eql?(compute_hmac(challenge), hmac) &&
318     webauthn_credential.verify(challenge)
319 end
valid_webauthn_credential_auth?(webauthn_credential)
[show source]
    # File lib/rodauth/features/webauthn.rb
357 def valid_webauthn_credential_auth?(webauthn_credential)
358   ds = webauthn_keys_ds.where(webauthn_keys_webauthn_id_column => webauthn_credential.id)
359   pub_key, sign_count = ds.get([webauthn_keys_public_key_column, webauthn_keys_sign_count_column])
360 
361   # Hack around inability to override expected_origin
362   origin = webauthn_origin
363   webauthn_credential.response.define_singleton_method(:verify) do |expected_challenge, expected_origin = nil, **kw|
364     super(expected_challenge, expected_origin || origin, **kw)
365   end
366 
367   (challenge = param_or_nil(webauthn_auth_challenge_param)) &&
368     (hmac = param_or_nil(webauthn_auth_challenge_hmac_param)) &&
369     timing_safe_eql?(compute_hmac(challenge), hmac) &&
370     webauthn_credential.verify(challenge, public_key: pub_key, sign_count: sign_count) &&
371     ds.update(
372       webauthn_keys_sign_count_column => Integer(webauthn_credential.sign_count),
373       webauthn_keys_last_use_column => Sequel::CURRENT_TIMESTAMP
374     ) == 1
375 end
verified_account?()
[show source]
   # File lib/rodauth/features/verify_account_grace_period.rb
17 def verified_account?
18   logged_in? && !session[unverified_account_session_key]
19 end
verify_account()
[show source]
    # File lib/rodauth/features/verify_account.rb
178 def verify_account
179   update_account(account_status_column=>account_open_status_value) == 1
180 end
verify_account_check_already_logged_in()
[show source]
    # File lib/rodauth/features/verify_account.rb
280 def verify_account_check_already_logged_in
281   check_already_logged_in
282 end
verify_account_ds(id=account_id)
[show source]
    # File lib/rodauth/features/verify_account.rb
305 def verify_account_ds(id=account_id)
306   db[verify_account_table].where(verify_account_id_column=>id)
307 end
verify_account_email_recently_sent?()
[show source]
    # File lib/rodauth/features/verify_account.rb
260 def verify_account_email_recently_sent?
261   (email_last_sent = get_verify_account_email_last_sent) && (Time.now - email_last_sent < verify_account_skip_resend_email_within)
262 end
verify_account_email_resend()
[show source]
    # File lib/rodauth/features/verify_account.rb
182 def verify_account_email_resend
183   if @verify_account_key_value = get_verify_account_key(account_id)
184     set_verify_account_email_last_sent
185     send_verify_account_email
186     true
187   end
188 end
verify_account_key_insert_hash()
[show source]
    # File lib/rodauth/features/verify_account.rb
301 def verify_account_key_insert_hash
302   {verify_account_id_column=>account_id, verify_account_key_column=>verify_account_key_value}
303 end
verify_account_set_password?()
[show source]
   # File lib/rodauth/features/verify_account_grace_period.rb
29 def verify_account_set_password?
30   false
31 end
verify_account_view()
[show source]
  # File lib/rodauth/features/webauthn_verify_account.rb
7 def verify_account_view
8   webauthn_setup_view
9 end
verify_login_change()
[show source]
    # File lib/rodauth/features/verify_login_change.rb
114 def verify_login_change
115   unless res = _update_login(verify_login_change_new_login)
116     remove_verify_login_change_key
117   end
118 
119   res
120 end
verify_login_change_ds(id=account_id)
[show source]
    # File lib/rodauth/features/verify_login_change.rb
208 def verify_login_change_ds(id=account_id)
209   db[verify_login_change_table].where(verify_login_change_id_column=>id)
210 end
verify_login_change_email_body()
[show source]
    # File lib/rodauth/features/verify_login_change.rb
204 def verify_login_change_email_body
205   render('verify-login-change-email')
206 end
verify_login_change_key_insert_hash(login)
[show source]
    # File lib/rodauth/features/verify_login_change.rb
194 def verify_login_change_key_insert_hash(login)
195   hash = {verify_login_change_id_column=>account_id, verify_login_change_key_column=>verify_login_change_key_value, verify_login_change_login_column=>login}
196   set_deadline_value(hash, verify_login_change_deadline_column, verify_login_change_deadline_interval)
197   hash
198 end
verify_login_change_old_login()
[show source]
    # File lib/rodauth/features/verify_login_change.rb
142 def verify_login_change_old_login
143   account_ds.get(login_column)
144 end
view(page, title)
[show source]
    # File lib/rodauth/features/base.rb
394 def view(page, title)
395   set_title(title)
396   _view(:view, page)
397 end
webauthn_account_id()
[show source]
    # File lib/rodauth/features/webauthn.rb
443 def webauthn_account_id
444   session_value
445 end
webauthn_auth_additional_form_tags()
[show source]
   # File lib/rodauth/features/webauthn_login.rb
35 def webauthn_auth_additional_form_tags
36   if @webauthn_login
37     super.to_s + login_hidden_field
38   else
39     super
40   end
41 end
webauthn_auth_credential_from_form_submission()
[show source]
    # File lib/rodauth/features/webauthn.rb
455 def webauthn_auth_credential_from_form_submission
456   case auth_data = raw_param(webauthn_auth_param)
457   when String
458     begin
459       auth_data = JSON.parse(auth_data)
460     rescue
461       throw_error_reason(:invalid_webauthn_auth_param, invalid_field_error_status, webauthn_auth_param, webauthn_invalid_auth_param_message) 
462     end
463   when Hash
464     # nothing
465   else
466     throw_error_reason(:invalid_webauthn_auth_param, invalid_field_error_status, webauthn_auth_param, webauthn_invalid_auth_param_message)
467   end
468 
469   begin
470     webauthn_credential = WebAuthn::Credential.from_get(auth_data)
471     unless valid_webauthn_credential_auth?(webauthn_credential)
472       throw_error_reason(:invalid_webauthn_auth_param, invalid_key_error_status, webauthn_auth_param, webauthn_invalid_auth_param_message)
473     end
474   rescue WebAuthn::SignCountVerificationError
475     handle_webauthn_sign_count_verification_error
476   rescue WebAuthn::Error, RuntimeError, NoMethodError
477     throw_error_reason(:invalid_webauthn_auth_param, invalid_field_error_status, webauthn_auth_param, webauthn_invalid_auth_param_message) 
478   end
479 
480   webauthn_credential
481 end
webauthn_auth_form_path()
[show source]
    # File lib/rodauth/features/webauthn.rb
241 def webauthn_auth_form_path
242   webauthn_auth_path
243 end
webauthn_authenticator_selection()
[show source]
    # File lib/rodauth/features/webauthn.rb
257 def webauthn_authenticator_selection
258   {'requireResidentKey' => false, 'userVerification' => webauthn_user_verification}
259 end
webauthn_credential_options_for_get()
[show source]
    # File lib/rodauth/features/webauthn.rb
321 def webauthn_credential_options_for_get
322   WebAuthn::Credential.options_for_get(
323     :allow => account_webauthn_ids,
324     :timeout => webauthn_auth_timeout,
325     :rp_id => webauthn_rp_id,
326     :user_verification => webauthn_user_verification,
327     :extensions => webauthn_extensions,
328   )
329 end
webauthn_extensions()
[show source]
    # File lib/rodauth/features/webauthn.rb
261 def webauthn_extensions
262   {}
263 end
webauthn_key_insert_hash(webauthn_credential)
[show source]
    # File lib/rodauth/features/webauthn.rb
434 def webauthn_key_insert_hash(webauthn_credential)
435   {
436     webauthn_keys_account_id_column => webauthn_account_id,
437     webauthn_keys_webauthn_id_column => webauthn_credential.id,
438     webauthn_keys_public_key_column => webauthn_credential.public_key,
439     webauthn_keys_sign_count_column => Integer(webauthn_credential.sign_count)
440   }
441 end
webauthn_keys_ds()
[show source]
    # File lib/rodauth/features/webauthn.rb
451 def webauthn_keys_ds
452   db[webauthn_keys_table].where(webauthn_keys_account_id_column => webauthn_account_id)
453 end
webauthn_origin()
[show source]
    # File lib/rodauth/features/webauthn.rb
335 def webauthn_origin
336   base_url
337 end
webauthn_remove_authenticated_session()
[show source]
    # File lib/rodauth/features/webauthn.rb
249 def webauthn_remove_authenticated_session
250   remove_session_value(authenticated_webauthn_id_session_key)
251 end
webauthn_rp_id()
[show source]
    # File lib/rodauth/features/webauthn.rb
339 def webauthn_rp_id
340   webauthn_origin.sub(/\Ahttps?:\/\//, '').sub(/:\d+\z/, '')
341 end
webauthn_rp_name()
[show source]
    # File lib/rodauth/features/webauthn.rb
343 def webauthn_rp_name
344   webauthn_rp_id
345 end
webauthn_setup?()
[show source]
    # File lib/rodauth/features/webauthn.rb
386 def webauthn_setup?
387   !webauthn_keys_ds.empty?
388 end
webauthn_setup_credential_from_form_submission()
[show source]
    # File lib/rodauth/features/webauthn.rb
483 def webauthn_setup_credential_from_form_submission
484   case setup_data = raw_param(webauthn_setup_param)
485   when String
486     begin
487       setup_data = JSON.parse(setup_data)
488     rescue
489       throw_error_reason(:invalid_webauthn_setup_param, invalid_field_error_status, webauthn_setup_param, webauthn_invalid_setup_param_message) 
490     end
491   when Hash
492     # nothing
493   else
494     throw_error_reason(:invalid_webauthn_setup_param, invalid_field_error_status, webauthn_setup_param, webauthn_invalid_setup_param_message)
495   end
496 
497   unless two_factor_password_match?(param(password_param))
498     throw_error_reason(:invalid_password, invalid_password_error_status, password_param, invalid_password_message)
499   end
500 
501   begin
502     webauthn_credential = WebAuthn::Credential.from_create(setup_data)
503     unless valid_new_webauthn_credential?(webauthn_credential)
504       throw_error_reason(:invalid_webauthn_setup_param, invalid_field_error_status, webauthn_setup_param, webauthn_invalid_setup_param_message) 
505     end
506   rescue WebAuthn::Error, RuntimeError, NoMethodError
507     throw_error_reason(:invalid_webauthn_setup_param, invalid_field_error_status, webauthn_setup_param, webauthn_invalid_setup_param_message) 
508   end
509 
510   webauthn_credential
511 end
webauthn_update_session(webauthn_id)
[show source]
    # File lib/rodauth/features/webauthn.rb
253 def webauthn_update_session(webauthn_id)
254   set_session_value(authenticated_webauthn_id_session_key, webauthn_id)
255 end
webauthn_user_ids_ds()
[show source]
    # File lib/rodauth/features/webauthn.rb
447 def webauthn_user_ids_ds
448   db[webauthn_user_ids_table].where(webauthn_user_ids_account_id_column => webauthn_account_id)
449 end
webauthn_user_name()
[show source]
    # File lib/rodauth/features/webauthn.rb
331 def webauthn_user_name
332   account![login_column]
333 end