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

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 = 41  

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.

webauthn_get_relying_party_opts -> webauthn_create_relying_party_opts

Public Class methods

configure(app, opts={}, &block)
[show source]
   # File lib/rodauth.rb
48 def self.configure(app, opts={}, &block)
49   json_opt = app.opts[:rodauth_json] = opts.fetch(:json, app.opts[:rodauth_json])
50   csrf = app.opts[:rodauth_csrf] = opts.fetch(:csrf, app.opts[:rodauth_csrf])
51   app.opts[:rodauth_route_csrf] = case csrf
52   when false, :rack_csrf
53     false
54   else
55     json_opt != :only
56   end
57   auth_class = (app.opts[:rodauths] ||= {})[opts[:name]] ||= opts[:auth_class] || Class.new(Auth)
58   if !auth_class.roda_class
59     auth_class.roda_class = app
60   elsif auth_class.roda_class != app
61     auth_class = app.opts[:rodauths][opts[:name]] = Class.new(auth_class)
62     auth_class.roda_class = app
63   end
64   auth_class.class_eval{@configuration_name = opts[:name] unless defined?(@configuration_name)}
65   auth_class.configure(&block) if block
66   auth_class.allocate.post_configure if auth_class.method_defined?(:post_configure)
67 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
 8 def self.lib(opts={}, &block) 
 9   require 'roda'
10   c = Class.new(Roda)
11   c.plugin(:rodauth, opts) do
12     enable :internal_request
13     instance_exec(&block)
14   end
15   c.freeze
16   c.rodauth
17 end
load_dependencies(app, opts={}, &_)
[show source]
   # File lib/rodauth.rb
19 def self.load_dependencies(app, opts={}, &_)
20   json_opt = opts.fetch(:json, app.opts[:rodauth_json])
21   if json_opt
22     app.plugin :json
23     app.plugin :json_parser
24   end
25 
26   unless json_opt == :only
27     unless opts[:render] == false
28       require 'tilt/string'
29       app.plugin :render
30     end
31 
32     case opts.fetch(:csrf, app.opts[:rodauth_csrf])
33     when false
34       # nothing
35     when :rack_csrf
36       # :nocov:
37       app.plugin :csrf
38       # :nocov:
39     else
40       app.plugin :route_csrf
41     end
42 
43     app.plugin :flash unless opts[:flash] == false
44     app.plugin :h
45   end
46 end
new(scope)
[show source]
    # File lib/rodauth/features/base.rb
146 def initialize(scope)
147   @scope = scope
148 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
236 def _account_from_email_auth_key(token)
237   account_from_key(token, account_open_status_value){|id| get_email_auth_key(id)}
238 end
_account_from_id(id, status_id=nil)
[show source]
    # File lib/rodauth/features/base.rb
814 def _account_from_id(id, status_id=nil)
815   ds = account_ds(id)
816   ds = ds.where(account_status_column=>status_id) if status_id && !skip_status_checks?
817   ds.first
818 end
_account_from_login(login)
[show source]
    # File lib/rodauth/features/base.rb
801 def _account_from_login(login)
802   ds = account_table_ds.where(login_column=>login)
803   ds = ds.select(*account_select) if account_select
804   ds = ds.where(account_status_column=>[account_unverified_status_value, account_open_status_value]) unless skip_status_checks?
805   ds.first
806 end
_account_from_refresh_token(token)
[show source]
    # File lib/rodauth/features/jwt_refresh.rb
116 def _account_from_refresh_token(token)
117   id, token_id, key = _account_refresh_token_split(token)
118 
119   unless key &&
120          (id.to_s == session_value.to_s) &&
121          (actual = get_active_refresh_token(id, token_id)) &&
122          (timing_safe_eql?(key, convert_token_key(actual)) || (hmac_secret_rotation? && timing_safe_eql?(key, compute_old_hmac(actual)))) &&
123          jwt_refresh_token_match?(key)
124     return
125   end
126 
127   ds = account_ds(id)
128   ds = ds.where(account_session_status_filter) unless skip_status_checks?
129   ds.first
130 end
_account_from_reset_password_key(token)
[show source]
    # File lib/rodauth/features/reset_password.rb
256 def _account_from_reset_password_key(token)
257   account_from_key(token, account_open_status_value){|id| get_password_reset_key(id)}
258 end
_account_from_session()
[show source]
    # File lib/rodauth/features/base.rb
808 def _account_from_session
809   ds = account_ds(session_value)
810   ds = ds.where(account_session_status_filter) unless skip_status_checks?
811   ds.first
812 end
_account_from_unlock_key(token)
[show source]
    # File lib/rodauth/features/lockout.rb
303 def _account_from_unlock_key(token)
304   account_from_key(token){|id| account_lockouts_ds(id).get(account_lockouts_key_column)}
305 end
_account_from_verify_account_key(token)
[show source]
    # File lib/rodauth/features/verify_account.rb
307 def _account_from_verify_account_key(token)
308   account_from_key(token, account_unverified_status_value){|id| get_verify_account_key(id)}
309 end
_account_from_verify_login_change_key(token)
[show source]
    # File lib/rodauth/features/verify_login_change.rb
210 def _account_from_verify_login_change_key(token)
211   account_from_key(token) do |id|
212     @verify_login_change_new_login, key = get_verify_login_change_login_and_key(id)
213     key
214   end
215 end
_account_refresh_token_split(token)
[show source]
    # File lib/rodauth/features/jwt_refresh.rb
132 def _account_refresh_token_split(token)
133   id, token = split_token(token)
134   id = convert_token_id(id)
135   return unless id && token
136 
137   token_id, key = split_token(token)
138   token_id = convert_token_id(token_id)
139   return unless token_id && key
140 
141   [id, token_id, key]
142 end
_around_rodauth()
[show source]
    # File lib/rodauth/features/base.rb
559 def _around_rodauth
560   yield
561 end
_email_auth_request()
[show source]
    # File lib/rodauth/features/email_auth.rb
183 def _email_auth_request
184   if email_auth_email_recently_sent?
185     set_redirect_error_flash email_auth_email_recently_sent_error_flash
186     redirect email_auth_email_recently_sent_redirect
187   end
188 
189   generate_email_auth_key_value
190   transaction do
191     before_email_auth_request
192     create_email_auth_key
193     send_email_auth_email
194     after_email_auth_request
195   end
196 
197   email_auth_email_sent_response
198 end
_field_attributes(field)
[show source]
    # File lib/rodauth/features/base.rb
833 def _field_attributes(field)
834   nil
835 end
_field_error_attributes(field)
[show source]
    # File lib/rodauth/features/base.rb
837 def _field_error_attributes(field)
838   " aria-invalid=\"true\" aria-describedby=\"#{field}_error_message\" "
839 end
_formatted_field_error(field, error)
[show source]
    # File lib/rodauth/features/base.rb
841 def _formatted_field_error(field, error)
842   "<span class=\"#{input_field_error_message_class}\" id=\"#{field}_error_message\">#{error}</span>"
843 end
_json_response_body(hash)
[show source]
    # File lib/rodauth/features/json.rb
220 def _json_response_body(hash)
221   request.send(:convert_to_json, hash)
222 end
_jwt_decode_opts()
[show source]
    # File lib/rodauth/features/jwt.rb
104 def _jwt_decode_opts
105   jwt_decode_opts
106 end
_jwt_decode_secrets()
[show source]
    # File lib/rodauth/features/jwt.rb
109 def _jwt_decode_secrets
110   secrets = [jwt_secret, jwt_old_secret]
111   secrets.compact!
112   secrets
113 end
_login(auth_type)
[show source]
    # File lib/rodauth/features/login.rb
168 def _login(auth_type)
169   warn("Deprecated #_login method called, use #login instead.")
170   login(auth_type)
171 end
_login_response()
[show source]
    # File lib/rodauth/features/login.rb
148 def _login_response
149   set_notice_flash login_notice_flash
150   redirect(saved_login_redirect || login_redirect)
151 end
_merge_fixed_locals_opts(opts, fixed_locals)
[show source]
    # File lib/rodauth/features/base.rb
979 def _merge_fixed_locals_opts(opts, fixed_locals)
980   if use_template_fixed_locals? && !opts[:locals]
981     fixed_locals_opts = {default_fixed_locals: fixed_locals}
982     fixed_locals_opts.merge!(opts[:template_opts]) if opts[:template_opts]
983     opts[:template_opts] = fixed_locals_opts
984   end
985 end
_multi_phase_login_forms()
[show source]
    # File lib/rodauth/features/email_auth.rb
177 def _multi_phase_login_forms
178   forms = super
179   forms << [30, email_auth_request_form, :_email_auth_request] if valid_login_entered? && allow_email_auth?
180   forms
181 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
446 def _otp
447   _otp_for_key(otp_user_key)
448 end
_otp_add_key(secret)
[show source]
    # File lib/rodauth/features/otp.rb
431 def _otp_add_key(secret)
432   # Uniqueness errors can't be handled here, as we can't be sure the secret provided
433   # is the same as the current secret.
434   otp_key_ds.insert(otp_keys_id_column=>session_value, otp_keys_column=>secret)
435 end
_otp_for_key(key)
[show source]
    # File lib/rodauth/features/otp.rb
442 def _otp_for_key(key)
443   otp_class.new(key, :issuer=>otp_issuer, :digits=>otp_digits, :interval=>otp_interval)
444 end
_otp_interval()
[show source]
    # File lib/rodauth/features/otp.rb
423 def _otp_interval
424   otp_interval || 30
425 end
_otp_key()
[show source]
    # File lib/rodauth/features/otp.rb
437 def _otp_key
438   @otp_user_key = nil
439   otp_key_ds.get(otp_keys_column)
440 end
_otp_tmp_key(secret)
[show source]
    # File lib/rodauth/features/otp.rb
417 def _otp_tmp_key(secret)
418   @otp_tmp_key = true
419   @otp_user_key = nil
420   @otp_key = secret
421 end
_otp_valid_code?(ot_pass, otp)
[show source]
    # File lib/rodauth/features/otp.rb
262 def _otp_valid_code?(ot_pass, otp)
263   return false unless otp_exists?
264   ot_pass = ot_pass.gsub(/\s+/, '')
265   if drift = otp_drift
266     if otp.respond_to?(:verify_with_drift)
267       # :nocov:
268       otp.verify_with_drift(ot_pass, drift)
269       # :nocov:
270     else
271       otp.verify(ot_pass, :drift_behind=>drift, :drift_ahead=>drift)
272     end
273   else
274     otp.verify(ot_pass)
275   end
276 end
_otp_valid_code_for_old_secret()

Called for valid OTP codes for old secrets

[show source]
    # File lib/rodauth/features/otp.rb
428 def _otp_valid_code_for_old_secret
429 end
_override_webauthn_credential_response_verify(webauthn_credential)
[show source]
    # File lib/rodauth/features/webauthn.rb
443 def _override_webauthn_credential_response_verify(webauthn_credential)
444   # no need to override
445 end
_process_raw_hmac(hmac)
[show source]
    # File lib/rodauth/features/base.rb
563 def _process_raw_hmac(hmac)
564   s = [hmac].pack('m')
565   s.chomp!("=\n")
566   s.tr!('+/', '-_')
567   s
568 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
210 def _return_json_response
211   response.status ||= json_response_error_status if json_response_error?
212   response.headers[convert_response_header_key('content-type')] ||= json_response_content_type
213   return_response _json_response_body(json_response)
214 end
_set_otp_unlock_info()
[show source]
   # File lib/rodauth/features/json.rb
80 def _set_otp_unlock_info
81   if use_json?
82     json_response[:num_successes] = otp_unlock_num_successes
83     json_response[:required_successes] = otp_unlock_auths_required
84     json_response[:next_attempt_after] = otp_unlock_next_auth_attempt_after.to_i
85   end
86 end
_setup_account_lockouts_hash(account_id, key)
[show source]
    # File lib/rodauth/features/lockout.rb
170 def _setup_account_lockouts_hash(account_id, key)
171   hash = {account_lockouts_id_column=>account_id, account_lockouts_key_column=>key}
172   set_deadline_value(hash, account_lockouts_deadline_column, account_lockouts_deadline_interval)
173   hash
174 end
_sms()
[show source]
    # File lib/rodauth/features/sms_codes.rb
524 def _sms
525   sms_ds.first
526 end
_sms_request_response()
[show source]
    # File lib/rodauth/features/sms_codes.rb
472 def _sms_request_response
473   set_notice_flash sms_request_notice_flash
474   redirect sms_auth_redirect
475 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
989 def _template_opts(opts, page)
990   opts = scope.send(:find_template, scope.send(:parse_template_opts, page, opts))
991   unless File.file?(scope.send(:template_path, opts))
992     opts[:path] = template_path(page)
993   end
994   opts
995 end
_two_factor_auth_response()
[show source]
    # File lib/rodauth/features/two_factor_base.rb
248 def _two_factor_auth_response
249   saved_two_factor_auth_redirect = remove_session_value(two_factor_auth_redirect_session_key)
250   set_notice_flash two_factor_auth_notice_flash
251   redirect(saved_two_factor_auth_redirect || two_factor_auth_redirect)
252 end
_two_factor_remove_all_from_session()
[show source]
    # File lib/rodauth/features/otp.rb
365 def _two_factor_remove_all_from_session
366   two_factor_remove_session('totp')
367   super
368 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   change_made = updated && !raised
90   clear_tokens(:change_login) if change_made
91   change_made
92 end
_view(meth, page)
[show source]
     # File lib/rodauth/features/base.rb
 997 def _view(meth, page)
 998   unless scope.respond_to?(meth)
 999     raise ConfigurationError, "attempted to render a built-in view/email template (#{page.inspect}), but rendering is disabled"
1000   end
1001 
1002   scope.send(meth, _view_opts(page))
1003 end
_view_opts(page)
[show source]
    # File lib/rodauth/features/base.rb
969 def _view_opts(page)
970   opts = template_opts.dup
971   _merge_fixed_locals_opts(opts, '(rodauth: self.rodauth)')
972   opts[:locals] = opts[:locals] ? opts[:locals].dup : {}
973   opts[:locals][:rodauth] = self
974   opts[:cache] = cache_templates
975   opts[:cache_key] = :"rodauth_#{page}"
976   _template_opts(opts, page)
977 end
account!()
[show source]
    # File lib/rodauth/features/base.rb
387 def account!
388   account || (session_value && account_from_session)
389 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
853 def account_ds(id=account_id)
854   raise ArgumentError, "invalid account id passed to account_ds" unless id
855   ds = account_table_ds.where(account_id_column=>id)
856   ds = ds.select(*account_select) if account_select
857   ds
858 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
131 def account_from_email_auth_key(key)
132   @account = _account_from_email_auth_key(key)
133 end
account_from_id(id, status_id=nil)
[show source]
    # File lib/rodauth/features/base.rb
395 def account_from_id(id, status_id=nil)
396   @account = _account_from_id(id, status_id)
397 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 (hmac_secret && timing_safe_eql?(key, convert_email_token_key(actual))) ||
73      (hmac_secret_rotation? && timing_safe_eql?(key, compute_old_hmac(actual))) ||
74      ((!hmac_secret || allow_raw_email_token?) && timing_safe_eql?(key, actual))
75     return
76   end
77   _account_from_id(id, status_id)
78 end
account_from_login(login)
[show source]
    # File lib/rodauth/features/base.rb
282 def account_from_login(login)
283   @account = _account_from_login(login)
284 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
391 def account_from_session
392   @account = _account_from_session
393 end
account_from_unlock_key(key)
[show source]
    # File lib/rodauth/features/lockout.rb
221 def account_from_unlock_key(key)
222   @account = _account_from_unlock_key(key)
223 end
account_from_verify_account_key(key)
[show source]
    # File lib/rodauth/features/verify_account.rb
196 def account_from_verify_account_key(key)
197   @account = _account_from_verify_account_key(key)
198 end
account_from_verify_login_change_key(key)
[show source]
    # File lib/rodauth/features/verify_login_change.rb
120 def account_from_verify_login_change_key(key)
121   @account = _account_from_verify_login_change_key(key)
122 end
account_from_webauthn_login()
[show source]
   # File lib/rodauth/features/webauthn_autofill.rb
45 def account_from_webauthn_login
46   return super if param_or_nil(login_param)
47 
48   credential_id = webauthn_auth_data["id"]
49   account_id = db[webauthn_keys_table]
50     .where(webauthn_keys_webauthn_id_column => credential_id)
51     .get(webauthn_keys_account_id_column)
52 
53   unless account_id
54     throw_error_reason(:invalid_webauthn_id, invalid_field_error_status, webauthn_auth_param, webauthn_invalid_webauthn_id_message)
55   end
56 
57   account_from_id(account_id)
58 end
account_id()
[show source]
    # File lib/rodauth/features/base.rb
272 def account_id
273   account[account_id_column]
274 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
383 def account_initial_status_value
384   account_open_status_value
385 end
account_lockouts_ds(id=account_id)
[show source]
    # File lib/rodauth/features/lockout.rb
299 def account_lockouts_ds(id=account_id)
300   db[account_lockouts_table].where(account_lockouts_id_column=>id)
301 end
account_login_failures_ds()
[show source]
    # File lib/rodauth/features/lockout.rb
295 def account_login_failures_ds
296   db[account_login_failures_table].where(account_login_failures_id_column=>account_id)
297 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
306 def account_password_hash_column
307   nil
308 end
account_session_status_filter()
[show source]
    # File lib/rodauth/features/base.rb
845 def account_session_status_filter
846   {account_status_column=>account_open_status_value}
847 end
account_table_ds()
[show source]
    # File lib/rodauth/features/base.rb
860 def account_table_ds
861   db[accounts_table]
862 end
account_webauthn_ids()
[show source]
    # File lib/rodauth/features/webauthn.rb
271 def account_webauthn_ids
272   webauthn_keys_ds.select_map(webauthn_keys_webauthn_id_column)
273 end
account_webauthn_usage()
[show source]
    # File lib/rodauth/features/webauthn.rb
275 def account_webauthn_usage
276   webauthn_keys_ds.select_hash(webauthn_keys_webauthn_id_column, webauthn_keys_last_use_column)
277 end
account_webauthn_user_id()
[show source]
    # File lib/rodauth/features/webauthn.rb
279 def account_webauthn_user_id
280   unless webauthn_id = webauthn_user_ids_ds.get(webauthn_user_ids_webauthn_id_column)
281     webauthn_id = WebAuthn.generate_user_id
282     if e = raised_uniqueness_violation do
283           webauthn_user_ids_ds.insert(
284             webauthn_user_ids_account_id_column => webauthn_account_id,
285             webauthn_user_ids_webauthn_id_column => webauthn_id
286           )
287         end
288       # If two requests to create a webauthn user id are sent at the same time and an insert
289       # is attempted for both, one will fail with a unique constraint violation.  In that case
290       # it is safe for the second one to use the webauthn user id inserted by the other request.
291       # If there is still no webauthn user id at this point, then we'll just reraise the
292       # exception.
293       # :nocov:
294       raise e unless webauthn_id = webauthn_user_ids_ds.get(webauthn_user_ids_webauthn_id_column)
295       # :nocov:
296     end
297   end
298 
299   webauthn_id
300 end
active_remember_key_ds(id=account_id)
[show source]
    # File lib/rodauth/features/remember.rb
265 def active_remember_key_ds(id=account_id)
266   remember_key_ds(id).where(Sequel.expr(remember_deadline_column) > Sequel::CURRENT_TIMESTAMP)
267 end
active_sessions_ds()
[show source]
    # File lib/rodauth/features/active_sessions.rb
204 def active_sessions_ds
205   db[active_sessions_table].
206     where(active_sessions_account_id_column=>session_value || account_id)
207 end
active_sessions_insert_hash()
[show source]
    # File lib/rodauth/features/active_sessions.rb
167 def active_sessions_insert_hash
168   {active_sessions_account_id_column => session_value, active_sessions_session_id_column => compute_hmac(active_sessions_key)}
169 end
active_sessions_update_hash()
[show source]
    # File lib/rodauth/features/active_sessions.rb
171 def active_sessions_update_hash
172   h = {active_sessions_last_use_column => Sequel::CURRENT_TIMESTAMP}
173 
174   if hmac_secret_rotation?
175     h[active_sessions_session_id_column] = compute_hmac(session[session_id_session_key])
176   end
177 
178   h
179 end
add_active_session()
[show source]
   # File lib/rodauth/features/active_sessions.rb
68 def add_active_session
69   key = generate_active_sessions_key
70   set_session_value(session_id_session_key, key)
71   if e = raises_uniqueness_violation?{active_sessions_ds.insert(active_sessions_insert_hash)}
72     handle_duplicate_active_session_id(e)
73   end
74   nil
75 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
187 def add_field_error_class(field)
188   if field_error(field)
189     " #{input_field_error_class}"
190   end
191 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
159 def add_remember_key
160   hash = {remember_id_column=>account_id, remember_key_column=>remember_key_value}
161   set_deadline_value(hash, remember_deadline_column, remember_deadline_interval)
162 
163   if e = raised_uniqueness_violation{remember_key_ds.insert(hash)}
164     # If inserting into the remember key table causes a violation, we can pull the
165     # existing row from the table.  If there is no invalid row, we can then reraise.
166     raise e unless @remember_key_value = active_remember_key_ds.get(remember_key_column)
167   end
168 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
206 def after_login
207   # Remove the email auth key after any login, even if
208   # it is a password login.  This is done to invalidate
209   # the email login when a user has a password and requests
210   # email authentication, but then remembers their password
211   # and doesn't need the link.  At that point, the link
212   # that allows login access to the account becomes a
213   # security liability, and it is best to remove it.
214   remove_email_auth_key
215   super
216 end
after_login_entered_during_multi_phase_login()
[show source]
    # File lib/rodauth/features/email_auth.rb
149 def after_login_entered_during_multi_phase_login
150   # If forcing email auth, just send the email link.
151   _email_auth_request if force_email_auth?
152 
153   super
154 end
after_login_failure()
[show source]
    # File lib/rodauth/features/lockout.rb
266 def after_login_failure
267   invalid_login_attempted
268   super
269 end
after_logout()
[show source]
    # File lib/rodauth/features/remember.rb
241 def after_logout
242   forget_login
243   super if defined?(super)
244 end
after_otp_authentication_failure()
[show source]
   # File lib/rodauth/features/otp_lockout_email.rb
18 def after_otp_authentication_failure
19   super
20 
21   if otp_locked_out? && send_otp_locked_out_email?
22     send_otp_locked_out_email
23   end
24 end
after_otp_disable()
[show source]
   # File lib/rodauth/features/otp_modify_email.rb
18 def after_otp_disable
19   super
20   send_otp_disabled_email
21 end
after_otp_setup()
[show source]
   # File lib/rodauth/features/otp_modify_email.rb
13 def after_otp_setup
14   super
15   send_otp_setup_email
16 end
after_otp_unlock_auth_failure()
[show source]
   # File lib/rodauth/features/json.rb
96 def after_otp_unlock_auth_failure
97   super if defined?(super)
98   _set_otp_unlock_info
99 end
after_otp_unlock_auth_success()
[show source]
   # File lib/rodauth/features/json.rb
88 def after_otp_unlock_auth_success
89   super if defined?(super)
90   if otp_locked_out?
91     _set_otp_unlock_info
92     json_response[:deadline] = otp_unlock_deadline.to_i
93   end
94 end
after_otp_unlock_not_yet_available()
[show source]
    # File lib/rodauth/features/json.rb
101 def after_otp_unlock_not_yet_available
102   super if defined?(super)
103   _set_otp_unlock_info
104 end
after_refresh_token()
[show source]
    # File lib/rodauth/features/active_sessions.rb
135 def after_refresh_token
136   super if defined?(super)
137   if prev_key = session[session_id_session_key]
138     key = generate_active_sessions_key
139     set_session_value(session_id_session_key, key)
140     active_sessions_ds.
141       where(active_sessions_session_id_column => compute_hmacs(prev_key)).
142       update(active_sessions_session_id_column => compute_hmac(key))
143   end
144 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
after_webauthn_setup()
[show source]
   # File lib/rodauth/features/webauthn_modify_email.rb
13 def after_webauthn_setup
14   super
15   send_webauthn_authenticator_added_email
16 end
allow_email_auth?()
[show source]
    # File lib/rodauth/features/email_auth.rb
202 def allow_email_auth?
203   defined?(super) ? super : true
204 end
allow_resending_verify_account_email?()
[show source]
    # File lib/rodauth/features/verify_account.rb
163 def allow_resending_verify_account_email?
164   account[account_status_column] == account_unverified_status_value
165 end
already_logged_in()
[show source]
    # File lib/rodauth/features/base.rb
314 def already_logged_in
315   nil
316 end
argon2_hash_algorithm?(hash)

:nocov:

[show source]
    # File lib/rodauth/features/argon2.rb
105 def argon2_hash_algorithm?(hash)
106   hash.start_with?('$argon2id$')
107 end
argon2_hash_cost()
[show source]
   # File lib/rodauth/features/argon2.rb
76 def argon2_hash_cost
77   { t_cost: 1, m_cost: 5, p_cost: 1 }
78 end
argon2_password_hash_match?(hash, password)
[show source]
    # File lib/rodauth/features/argon2.rb
109 def argon2_password_hash_match?(hash, password)
110   ret = ::Argon2::Password.verify_password(password, hash, argon2_secret)
111 
112   if ret == false && argon2_old_secret != argon2_secret && (ret = ::Argon2::Password.verify_password(password, hash, argon2_old_secret))
113     @update_password_hash = true
114   end
115 
116   ret
117 end
argon2_password_hash_using_salt_and_secret(password, salt, secret)
[show source]
   # File lib/rodauth/features/argon2.rb
60 def argon2_password_hash_using_salt_and_secret(password, salt, secret)
61   argon2_params = Hash[extract_password_hash_cost(salt)]
62   argon2_params[argon2_salt_option] = salt.split('$').last.unpack("m")[0]
63   argon2_params[:secret] = secret
64   ::Argon2::Password.new(argon2_params).create(password)
65 end
argon2_salt_option()
[show source]
   # File lib/rodauth/features/argon2.rb
34 def argon2_salt_option
35   :salt_do_not_supply
36 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
137 def auth_class_eval(&block)
138   auth.class_eval(&block)
139 end
authenticated?()
[show source]
    # File lib/rodauth/features/base.rb
370 def authenticated?
371   logged_in?
372 end
authenticated_by()
[show source]
    # File lib/rodauth/features/base.rb
474 def authenticated_by
475   session[authenticated_by_session_key]
476 end
authenticated_webauthn_id()
[show source]
    # File lib/rodauth/features/webauthn.rb
251 def authenticated_webauthn_id
252   session[authenticated_webauthn_id_session_key]
253 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
217 def autocomplete_for_field?(_param)
218   mark_input_fields_with_autocomplete?
219 end
autologin_session(autologin_type)
[show source]
    # File lib/rodauth/features/base.rb
487 def autologin_session(autologin_type)
488   login_session('autologin')
489   set_session_value(autologin_type_session_key, autologin_type)
490 end
autologin_type()
[show source]
    # File lib/rodauth/features/base.rb
483 def autologin_type
484   session[autologin_type_session_key]
485 end
base32_encode(data, length)
[show source]
    # File lib/rodauth/features/otp.rb
412 def base32_encode(data, length)
413   chars = 'abcdefghijklmnopqrstuvwxyz234567'
414   length.times.map{|i|chars[data[i].ord % 32]}.join
415 end
base_url()
[show source]
    # File lib/rodauth/features/base.rb
533 def base_url
534   url = String.new("#{request.scheme}://#{domain}")
535   url << ":#{request.port}" if request.port != Rack::Request::DEFAULT_PORTS[request.scheme]
536   url
537 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
254 def before_login_attempt
255   if locked_out?
256     show_lockout_page
257   end
258   super
259 end
before_logout()
[show source]
    # File lib/rodauth/features/active_sessions.rb
151 def before_logout
152   if param_or_nil(global_logout_param)
153     remove_remember_key(session_value) if respond_to?(:remove_remember_key)
154     remove_all_active_sessions
155   else
156     remove_current_session
157   end
158   super
159 end
before_otp_setup_route()
[show source]
    # File lib/rodauth/features/json.rb
170 def before_otp_setup_route
171   super if defined?(super)
172   if use_json? && otp_keys_use_hmac? && !param_or_nil(otp_setup_raw_param)
173     _otp_tmp_key(otp_new_secret)
174     json_response[otp_setup_param] = otp_user_key
175     json_response[otp_setup_raw_param] = otp_key
176   end
177 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
179 def before_rodauth
180   if json_request?
181     if json_check_accept? && (accept = request.env['HTTP_ACCEPT']) && accept !~ json_accept_regexp
182       response.status = 406
183       json_response[json_response_error_key] = json_not_accepted_error_message
184       _return_json_response
185     end
186 
187     unless request.post?
188       response.status = 405
189       set_response_header('allow', 'POST')
190       json_response[json_response_error_key] = json_non_post_error_message
191       return_json_response
192     end
193   elsif only_json?
194     response.status = json_response_error_status
195     return_response non_json_request_error_message
196   end
197 
198   super
199 end
before_two_factor_auth_route()
[show source]
    # File lib/rodauth/features/json.rb
116 def before_two_factor_auth_route
117   super if defined?(super)
118   if use_json?
119     json_response[:auth_links] = two_factor_auth_links.sort.map{|_,link| link}
120     json_response[json_response_success_key] ||= "" if include_success_messages?
121     return_json_response
122   end
123 end
before_two_factor_manage_route()
[show source]
    # File lib/rodauth/features/json.rb
106 def before_two_factor_manage_route
107   super if defined?(super)
108   if use_json?
109     json_response[:setup_links] = two_factor_setup_links.sort.map{|_,link| link}
110     json_response[:remove_links] = two_factor_remove_links.sort.map{|_,link| link}
111     json_response[json_response_success_key] ||= "" if include_success_messages?
112     return_json_response
113   end
114 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
125 def before_view_recovery_codes
126   super if defined?(super)
127   if use_json?
128     json_response[:codes] = recovery_codes
129     json_response[json_response_success_key] ||= "" if include_success_messages?
130   end
131 end
before_webauthn_auth_route()
[show source]
    # File lib/rodauth/features/json.rb
143 def before_webauthn_auth_route
144   super if defined?(super)
145   if use_json? && !param_or_nil(webauthn_auth_param)
146     cred = webauthn_credential_options_for_get
147     json_response[webauthn_auth_param] = cred.as_json
148     json_response[webauthn_auth_challenge_param] = cred.challenge
149     json_response[webauthn_auth_challenge_hmac_param] = compute_hmac(cred.challenge)
150   end
151 end
before_webauthn_login_route()
[show source]
    # File lib/rodauth/features/json.rb
153 def before_webauthn_login_route
154   super if defined?(super)
155   if use_json? && !param_or_nil(webauthn_auth_param) && webauthn_login_options?
156     cred = webauthn_credential_options_for_get
157     json_response[webauthn_auth_param] = cred.as_json
158     json_response[webauthn_auth_challenge_param] = cred.challenge
159     json_response[webauthn_auth_challenge_hmac_param] = compute_hmac(cred.challenge)
160   end
161 end
before_webauthn_remove_route()
[show source]
    # File lib/rodauth/features/json.rb
163 def before_webauthn_remove_route
164   super if defined?(super)
165   if use_json? && !param_or_nil(webauthn_remove_param)
166     json_response[webauthn_remove_param] = account_webauthn_usage
167   end
168 end
before_webauthn_setup_route()
[show source]
    # File lib/rodauth/features/json.rb
133 def before_webauthn_setup_route
134   super if defined?(super)
135   if use_json? && !param_or_nil(webauthn_setup_param)
136     cred = new_webauthn_credential
137     json_response[webauthn_setup_param] = cred.as_json
138     json_response[webauthn_setup_challenge_param] = cred.challenge
139     json_response[webauthn_setup_challenge_hmac_param] = compute_hmac(cred.challenge)
140   end
141 end
button(value, opts={})
[show source]
    # File lib/rodauth/features/base.rb
424 def button(value, opts={})
425   scope.render(button_opts(value, opts))
426 end
button_fixed_locals()
[show source]
    # File lib/rodauth/features/base.rb
607 def button_fixed_locals
608   '(value:, opts:)'
609 end
button_opts(value, opts)
[show source]
    # File lib/rodauth/features/base.rb
415 def button_opts(value, opts)
416   opts = Hash[template_opts].merge!(opts)
417   _merge_fixed_locals_opts(opts, button_fixed_locals)
418   opts[:locals] = {:value=>value, :opts=>opts}
419   opts[:cache] = cache_templates
420   opts[:cache_key] = :rodauth_button
421   _template_opts(opts, 'button')
422 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
707 def catch_error(&block)
708   catch(:rodauth_error, &block)
709 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
136 def change_login_notice_flash
137   change_login_needs_verification_notice_flash
138 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
54 def check_active_session
55   if logged_in? && !currently_active_session?
56     no_longer_active_session
57   end
58 end
check_already_logged_in()
[show source]
    # File lib/rodauth/features/base.rb
310 def check_already_logged_in
311   already_logged_in if logged_in?
312 end
check_csrf()
[show source]
    # File lib/rodauth/features/base.rb
399 def check_csrf
400   scope.check_csrf!(check_csrf_opts, &check_csrf_block)
401 end
check_csrf?()
[show source]
    # File lib/rodauth/features/base.rb
769 def check_csrf?
770   scope.opts[:rodauth_route_csrf]
771 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
52 def check_single_session
53   if logged_in? && !currently_active_session?
54     no_longer_active_session
55   end
56 end
clear_cached_otp()
[show source]
    # File lib/rodauth/features/otp.rb
370 def clear_cached_otp
371   remove_instance_variable(:@otp) if defined?(@otp)
372 end
clear_invalid_login_attempts()
[show source]
    # File lib/rodauth/features/lockout.rb
166 def clear_invalid_login_attempts
167   unlock_account
168 end
clear_session()
[show source]
    # File lib/rodauth/features/base.rb
326 def clear_session
327   if use_scope_clear_session?
328     scope.clear_session
329   else
330     session.clear
331   end
332 end
clear_tokens(reason)
[show source]
    # File lib/rodauth/features/active_sessions.rb
128 def clear_tokens(reason)
129   super
130   remove_all_active_sessions_except_current
131 end
close_account()
[show source]
   # File lib/rodauth/features/close_account.rb
67 def close_account
68   unless skip_status_checks?
69     update_account(account_status_column=>account_closed_status_value)
70   end
71 
72   unless account_password_hash_column
73     password_hash_ds.delete
74   end
75 end
close_account_requires_password?()
[show source]
   # File lib/rodauth/features/close_account.rb
63 def close_account_requires_password?
64   modifications_require_password?
65 end
compute_hmac(data)

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

[show source]
    # File lib/rodauth/features/base.rb
251 def compute_hmac(data)
252   _process_raw_hmac(compute_raw_hmac(data))
253 end
compute_hmacs(data)

Return array of hmacs. Array has two strings if hmac_old_secret is set, or one string otherwise.

[show source]
    # File lib/rodauth/features/base.rb
262 def compute_hmacs(data)
263   hmacs = [compute_hmac(data)]
264 
265   if hmac_old_secret
266     hmacs << compute_old_hmac(data)
267   end
268 
269   hmacs
270 end
compute_old_hmac(data)

Return urlsafe base64 HMAC for data using hmac_old_secret, assumes hmac_old_secret is set.

[show source]
    # File lib/rodauth/features/base.rb
256 def compute_old_hmac(data)
257   _process_raw_hmac(compute_raw_hmac_with_secret(data, hmac_old_secret))
258 end
compute_raw_hmac(data)
[show source]
    # File lib/rodauth/features/base.rb
824 def compute_raw_hmac(data)
825   raise ConfigurationError, "hmac_secret not set" unless hmac_secret
826   compute_raw_hmac_with_secret(data, hmac_secret)
827 end
compute_raw_hmac_with_secret(data, secret)
[show source]
    # File lib/rodauth/features/base.rb
829 def compute_raw_hmac_with_secret(data, secret)
830   OpenSSL::HMAC.digest(OpenSSL::Digest::SHA256.new, secret, data)
831 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_response_header_key(key)
[show source]
    # File lib/rodauth/features/base.rb
575 def convert_response_header_key(key)
576   key
577 end
convert_session_key(key)
[show source]
    # File lib/rodauth/features/base.rb
686 def convert_session_key(key)
687   key = :"#{session_key_prefix}#{key}" if session_key_prefix
688   normalize_session_or_flash_key(key)
689 end
convert_timestamp(timestamp)

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

[show source]
    # File lib/rodauth/features/base.rb
869 def convert_timestamp(timestamp)
870   timestamp = db.to_application_timestamp(timestamp) if timestamp.is_a?(String)
871   timestamp
872 end
convert_token_id(id)
[show source]
    # File lib/rodauth/features/base.rb
640 def convert_token_id(id)
641   if convert_token_id_to_integer?
642     convert_token_id_to_integer(id)
643   else
644     id
645   end
646 end
convert_token_id_to_integer(id)
[show source]
    # File lib/rodauth/features/base.rb
648 def convert_token_id_to_integer(id)
649   if id = (Integer(id, 10) rescue nil)
650     if id > 9223372036854775807 || id < -9223372036854775808
651       # Only allow 64-bit signed integer range to avoid problems on PostgreSQL
652       id = nil
653     end
654   end
655 
656   id
657 end
convert_token_key(key)
[show source]
    # File lib/rodauth/features/base.rb
628 def convert_token_key(key)
629   if key && hmac_secret
630     compute_hmac(key)
631   else
632     key
633   end
634 end
create_account_autologin?()
[show source]
    # File lib/rodauth/features/verify_account.rb
216 def create_account_autologin?
217   false
218 end
create_account_notice_flash()
[show source]
    # File lib/rodauth/features/verify_account.rb
183 def create_account_notice_flash
184   verify_account_email_sent_notice_flash
185 end
create_account_set_password?()
[show source]
    # File lib/rodauth/features/verify_account.rb
220 def create_account_set_password?
221   return false if verify_account_set_password?
222   super
223 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
102 def create_email_auth_key
103   transaction do
104     if email_auth_key_value = get_email_auth_key(account_id)
105       set_email_auth_email_last_sent
106       @email_auth_key_value = email_auth_key_value
107     elsif e = raised_uniqueness_violation{email_auth_ds.insert(email_auth_key_insert_hash)}
108       # If inserting into the email auth table causes a violation, we can pull the
109       # existing email auth key from the table, or reraise.
110       raise e unless @email_auth_key_value = get_email_auth_key(account_id)
111     end
112   end
113 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
163 def create_reset_password_key
164   transaction do
165     if reset_password_key_value = get_password_reset_key(account_id)
166       set_reset_password_email_last_sent
167       @reset_password_key_value = reset_password_key_value
168     elsif e = raised_uniqueness_violation{password_reset_ds.insert(reset_password_key_insert_hash)}
169       # If inserting into the reset password table causes a violation, we can pull the
170       # existing reset password key from the table, or reraise.
171       raise e unless @reset_password_key_value = get_password_reset_key(account_id)
172     end
173   end
174 end
create_verify_account_key()
[show source]
    # File lib/rodauth/features/verify_account.rb
286 def create_verify_account_key
287   ds = verify_account_ds
288   transaction do
289     if ds.empty?
290       if e = raised_uniqueness_violation{ds.insert(verify_account_key_insert_hash)}
291         # If inserting into the verify account table causes a violation, we can pull the
292         # key from the verify account table, or reraise.
293         raise e unless @verify_account_key_value = get_verify_account_key(account_id)
294       end
295     end
296   end
297 end
create_verify_login_change_email(login)
[show source]
    # File lib/rodauth/features/verify_login_change.rb
198 def create_verify_login_change_email(login)
199   create_email_to(login, verify_login_change_email_subject, verify_login_change_email_body)
200 end
create_verify_login_change_key(login)
[show source]
    # File lib/rodauth/features/verify_login_change.rb
176 def create_verify_login_change_key(login)
177   ds = verify_login_change_ds
178   transaction do
179     ds.where((Sequel::CURRENT_TIMESTAMP > verify_login_change_deadline_column) | ~Sequel.expr(verify_login_change_login_column=>login)).delete
180     if e = raised_uniqueness_violation{ds.insert(verify_login_change_key_insert_hash(login))}
181       old_login, key = get_verify_login_change_login_and_key(account_id)
182       # If inserting into the verify login change table causes a violation, we can pull the
183       # key from the verify login change table if the logins match, or reraise.
184       @verify_login_change_key_value = if old_login.downcase == login.downcase
185         key
186       end
187       raise e unless @verify_login_change_key_value
188     end
189   end
190 end
csrf_tag(path=request.path)
[show source]
    # File lib/rodauth/features/base.rb
403 def csrf_tag(path=request.path)
404   return unless scope.respond_to?(:csrf_tag)
405 
406   if use_request_specific_csrf_tokens?
407     scope.csrf_tag(path)
408   else
409     # :nocov:
410     scope.csrf_tag
411     # :nocov:
412   end
413 end
currently_active_session?()
[show source]
   # File lib/rodauth/features/active_sessions.rb
40 def currently_active_session?
41   return false unless session_id = session[session_id_session_key]
42 
43   remove_inactive_sessions
44   ds = active_sessions_ds.
45     where(active_sessions_session_id_column => compute_hmacs(session_id))
46 
47   if update_current_session?
48     ds.update(active_sessions_update_hash) == 1
49   else
50     ds.count == 1
51   end
52 end
database_function_password_match?(name, hash_id, password, salt)
[show source]
    # File lib/rodauth/features/argon2.rb
119 def database_function_password_match?(name, hash_id, password, salt)
120   return true if super
121 
122   if use_argon2? && argon2_hash_algorithm?(salt) && argon2_old_secret != argon2_secret && (ret = db.get(Sequel.function(function_name(name), hash_id, argon2_password_hash_using_salt_and_secret(password, salt, argon2_old_secret))))
123     @update_password_hash = true
124   end
125 
126   !!ret
127 end
db()
[show source]
    # File lib/rodauth/features/base.rb
290 def db
291   Sequel::DATABASES.first or raise "Sequel database connection is missing"
292 end
delete_account()
[show source]
   # File lib/rodauth/features/close_account.rb
77 def delete_account
78   account_ds.delete
79 end
delete_account_on_close?()
[show source]
   # File lib/rodauth/features/close_account.rb
81 def delete_account_on_close?
82   skip_status_checks?
83 end
disable_remember_login()
[show source]
    # File lib/rodauth/features/remember.rb
155 def disable_remember_login
156   remove_remember_key
157 end
domain()
[show source]
    # File lib/rodauth/features/base.rb
539 def domain
540   request.host
541 end
email_auth_ds(id=account_id)
[show source]
    # File lib/rodauth/features/email_auth.rb
232 def email_auth_ds(id=account_id)
233   db[email_auth_table].where(email_auth_id_column=>id)
234 end
email_auth_email_recently_sent?()
[show source]
    # File lib/rodauth/features/email_auth.rb
166 def email_auth_email_recently_sent?
167   (email_last_sent = get_email_auth_email_last_sent) && (Time.now - email_last_sent < email_auth_skip_resend_email_within)
168 end
email_auth_key_insert_hash()
[show source]
    # File lib/rodauth/features/email_auth.rb
226 def email_auth_key_insert_hash
227   hash = {email_auth_id_column=>account_id, email_auth_key_column=>email_auth_key_value}
228   set_deadline_value(hash, email_auth_deadline_column, email_auth_deadline_interval)
229   hash
230 end
email_auth_request_form()
[show source]
    # File lib/rodauth/features/email_auth.rb
145 def email_auth_request_form
146   render('email-auth-request-form')
147 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
212 def extend_remember_deadline
213   active_remember_key_ds.update(remember_deadline_column=>Sequel.date_add(Sequel::CURRENT_TIMESTAMP, remember_period))
214   remember_login
215 end
extend_remember_deadline_while_logged_in?()
[show source]
    # File lib/rodauth/features/remember.rb
200 def extend_remember_deadline_while_logged_in?
201   return false unless extend_remember_deadline?
202 
203   if extended_at = session[remember_deadline_extended_session_key]
204     extended_at + extend_remember_deadline_period < Time.now.to_i
205   elsif logged_in_via_remember_key?
206     # Handle existing sessions before the change to extend remember deadline
207     # while logged in.
208     true
209   end
210 end
extract_password_hash_cost(hash)
[show source]
   # File lib/rodauth/features/argon2.rb
68 def extract_password_hash_cost(hash)
69   return super unless argon2_hash_algorithm?(hash)
70 
71   /\A\$argon2id\$v=\d+\$m=(\d+),t=(\d+),p=(\d+)/ =~ hash
72   { t_cost: $2.to_i, m_cost: Math.log2($1.to_i).to_i, p_cost: $3.to_i }
73 end
features()
[show source]
    # File lib/rodauth/features/base.rb
150 def features
151   self.class.features
152 end
field_attributes(field)
[show source]
    # File lib/rodauth/features/base.rb
225 def field_attributes(field)
226   _field_attributes(field) || default_field_attributes
227 end
field_error(field)
[show source]
    # File lib/rodauth/features/base.rb
182 def field_error(field)
183   return nil unless @field_errors
184   @field_errors[field]
185 end
field_error_attributes(field)
[show source]
    # File lib/rodauth/features/base.rb
229 def field_error_attributes(field)
230   if field_error(field)
231     _field_error_attributes(field)
232   end
233 end
flash()
[show source]
    # File lib/rodauth/features/base.rb
166 def flash
167   scope.flash
168 end
forget_login()
[show source]
    # File lib/rodauth/features/remember.rb
138 def forget_login
139   opts = Hash[remember_cookie_options]
140   opts[:path] = "/" unless opts.key?(:path)
141   ::Rack::Utils.delete_cookie_header!(response.headers, remember_cookie_key, opts)
142 end
formatted_field_error(field)
[show source]
    # File lib/rodauth/features/base.rb
235 def formatted_field_error(field)
236   if error = field_error(field)
237     _formatted_field_error(field, error)
238   end
239 end
function_name(name)
[show source]
    # File lib/rodauth/features/base.rb
773 def function_name(name)
774   if db.database_type == :mssql
775     # :nocov:
776     "dbo.#{name}"
777     # :nocov:
778   else
779     name
780   end
781 end
generate_active_sessions_key()
[show source]
    # File lib/rodauth/features/active_sessions.rb
163 def generate_active_sessions_key
164   @active_sessions_key = random_key
165 end
generate_email_auth_key_value()
[show source]
    # File lib/rodauth/features/email_auth.rb
218 def generate_email_auth_key_value
219   @email_auth_key_value = random_key
220 end
generate_refresh_token()
[show source]
    # File lib/rodauth/features/jwt_refresh.rb
190 def generate_refresh_token
191   hash = jwt_refresh_token_insert_hash
192   [account_id, jwt_refresh_token_ds.insert(hash), convert_token_key(hash[jwt_refresh_token_key_column])].join(token_separator)
193 end
generate_remember_key_value()
[show source]
    # File lib/rodauth/features/remember.rb
253 def generate_remember_key_value
254   @remember_key_value = random_key
255 end
generate_reset_password_key_value()
[show source]
    # File lib/rodauth/features/reset_password.rb
234 def generate_reset_password_key_value
235   @reset_password_key_value = random_key
236 end
generate_unlock_account_key()
[show source]
    # File lib/rodauth/features/lockout.rb
276 def generate_unlock_account_key
277   random_key
278 end
generate_verify_account_key_value()
[show source]
    # File lib/rodauth/features/verify_account.rb
282 def generate_verify_account_key_value
283   @verify_account_key_value = random_key
284 end
generate_verify_login_change_key_value()
[show source]
    # File lib/rodauth/features/verify_login_change.rb
172 def generate_verify_login_change_key_value
173   @verify_login_change_key_value = random_key
174 end
get_active_refresh_token(account_id, token_id)
[show source]
    # File lib/rodauth/features/jwt_refresh.rb
163 def get_active_refresh_token(account_id, token_id)
164   jwt_refresh_token_account_ds(account_id).
165     where(Sequel::CURRENT_TIMESTAMP > jwt_refresh_token_deadline_column).
166     delete
167 
168   jwt_refresh_token_account_token_ds(account_id, token_id).
169     get(jwt_refresh_token_key_column)
170 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
119 def get_email_auth_email_last_sent
120   if column = email_auth_email_last_sent_column
121     if ts = email_auth_ds.get(column)
122       convert_timestamp(ts)
123     end
124   end
125 end
get_email_auth_key(id)
[show source]
    # File lib/rodauth/features/email_auth.rb
139 def get_email_auth_key(id)
140   ds = email_auth_ds(id)
141   ds.where(Sequel::CURRENT_TIMESTAMP > email_auth_deadline_column).delete
142   ds.get(email_auth_key_column)
143 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
789 def get_password_hash
790   if account_password_hash_column
791     account[account_password_hash_column] if account!
792   elsif use_database_authentication_functions?
793     db.get(Sequel.function(function_name(:rodauth_get_salt), account ? account_id : session_value))
794   else
795     # :nocov:
796     password_hash_ds.get(password_hash_column)
797     # :nocov:
798   end
799 end
get_password_reset_key(id)
[show source]
    # File lib/rodauth/features/reset_password.rb
192 def get_password_reset_key(id)
193   ds = password_reset_ds(id)
194   ds.where(Sequel::CURRENT_TIMESTAMP > reset_password_deadline_column).delete
195   ds.get(reset_password_key_column)
196 end
get_remember_key()
[show source]
    # File lib/rodauth/features/remember.rb
144 def get_remember_key
145   unless @remember_key_value = active_remember_key_ds.get(remember_key_column)
146    generate_remember_key_value
147    transaction do
148      remove_remember_key
149      add_remember_key
150    end
151   end
152   nil
153 end
get_reset_password_email_last_sent()
[show source]
    # File lib/rodauth/features/reset_password.rb
202 def get_reset_password_email_last_sent
203   if column = reset_password_email_last_sent_column
204     if ts = password_reset_ds.get(column)
205       convert_timestamp(ts)
206     end
207   end
208 end
get_unlock_account_email_last_sent()
[show source]
    # File lib/rodauth/features/lockout.rb
229 def get_unlock_account_email_last_sent
230   if column = account_lockouts_email_last_sent_column
231     if ts = account_lockouts_ds.get(column)
232       convert_timestamp(ts)
233     end
234   end
235 end
get_unlock_account_key()
[show source]
    # File lib/rodauth/features/lockout.rb
217 def get_unlock_account_key
218   account_lockouts_ds.get(account_lockouts_key_column)
219 end
get_verify_account_email_last_sent()
[show source]
    # File lib/rodauth/features/verify_account.rb
229 def get_verify_account_email_last_sent
230   if column = verify_account_email_last_sent_column
231     if ts = verify_account_ds.get(column)
232       convert_timestamp(ts)
233     end
234   end
235 end
get_verify_account_key(id)
[show source]
    # File lib/rodauth/features/verify_account.rb
208 def get_verify_account_key(id)
209   verify_account_ds(id).get(verify_account_key_column)
210 end
get_verify_login_change_login_and_key(id)
[show source]
    # File lib/rodauth/features/verify_login_change.rb
132 def get_verify_login_change_login_and_key(id)
133   verify_login_change_ds(id).get([verify_login_change_login_column, verify_login_change_key_column])
134 end
handle_duplicate_active_session_id(_e)
[show source]
   # File lib/rodauth/features/active_sessions.rb
77 def handle_duplicate_active_session_id(_e)
78   # Do nothing by default as session is already tracked.  This will result in
79   # the current session and the existing session with the same id
80   # being tracked together, so that a logout of one will logout
81   # the other, and updating the last use on one will update the other,
82   # but this should be acceptable.  However, this can be overridden if different
83   # behavior is desired.
84 end
handle_webauthn_sign_count_verification_error()
[show source]
    # File lib/rodauth/features/webauthn.rb
352 def handle_webauthn_sign_count_verification_error
353   throw_error_reason(:invalid_webauthn_sign_count, invalid_field_error_status, webauthn_auth_param, webauthn_invalid_sign_count_message) 
354 end
has_password?()
[show source]
    # File lib/rodauth/features/base.rb
551 def has_password?
552   return @has_password if defined?(@has_password)
553   return false unless account || session_value
554   @has_password = !!get_password_hash
555 end
hmac_secret_rotation?()
[show source]
    # File lib/rodauth/features/base.rb
820 def hmac_secret_rotation?
821   hmac_secret && hmac_old_secret && hmac_secret != hmac_old_secret
822 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
193 def inactive_session_cond
194   cond = session_inactivity_deadline_condition
195   cond2 = session_lifetime_deadline_condition
196   return false unless cond || cond2
197   Sequel.|(*[cond, cond2].compact)
198 end
include_success_messages?()
[show source]
    # File lib/rodauth/features/json.rb
216 def include_success_messages?
217   !json_response_success_key.nil?
218 end
input_field_string(param, id, opts={})
[show source]
    # File lib/rodauth/features/base.rb
193 def input_field_string(param, id, opts={})
194   type = opts.fetch(:type, "text")
195 
196   unless type == "password"
197     value = opts.fetch(:value){scope.h param(param)}
198   end
199 
200   field_class = opts.fetch(:class, "form-control")
201 
202   if autocomplete_for_field?(param) && opts[:autocomplete]
203     autocomplete = "autocomplete=\"#{opts[:autocomplete]}\""
204   end
205 
206   if inputmode_for_field?(param) && opts[:inputmode]
207     inputmode = "inputmode=\"#{opts[:inputmode]}\""
208   end
209 
210   if mark_input_fields_as_required? && opts[:required] != false
211     required = "required=\"required\""
212   end
213 
214   "<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]}"
215 end
inputmode_for_field?(_param)
[show source]
    # File lib/rodauth/features/base.rb
221 def inputmode_for_field?(_param)
222   mark_input_fields_with_inputmode?
223 end
internal_request?()
[show source]
    # File lib/rodauth/features/base.rb
934 def internal_request?
935   false
936 end
internal_request_configuration(&block)
[show source]
    # File lib/rodauth/features/internal_request.rb
373 def internal_request_configuration(&block)
374   @auth.instance_exec do
375     (@internal_request_configuration_blocks ||= []) << block
376   end
377 end
invalid_login_attempted()
[show source]
    # File lib/rodauth/features/lockout.rb
176 def invalid_login_attempted
177   ds = account_login_failures_ds.
178       where(account_login_failures_id_column=>account_id)
179 
180   number = if db.database_type == :postgres
181     ds.returning(account_login_failures_number_column).
182       with_sql(:update_sql, account_login_failures_number_column=>Sequel.expr(account_login_failures_number_column)+1).
183       single_value
184   else
185     # :nocov:
186     if ds.update(account_login_failures_number_column=>Sequel.expr(account_login_failures_number_column)+1) > 0
187       ds.get(account_login_failures_number_column)
188     end
189     # :nocov:
190   end
191 
192   unless number
193     # Ignoring the violation is safe here.  It may allow slightly more than max_invalid_logins invalid logins before
194     # lockout, but allowing a few extra is OK if the race is lost.
195     ignore_uniqueness_violation{account_login_failures_ds.insert(account_login_failures_id_column=>account_id)}
196     number = 1
197   end
198 
199   if number >= max_invalid_logins
200     @unlock_account_key_value = generate_unlock_account_key
201     hash = _setup_account_lockouts_hash(account_id, unlock_account_key_value)
202 
203     if e = raised_uniqueness_violation{account_lockouts_ds.insert(hash)}
204       # If inserting into the lockout table raises a violation, we should just be able to pull the already inserted
205       # key out of it.  If that doesn't return a valid key, we should reraise the error.
206       raise e unless @unlock_account_key_value = account_lockouts_ds.get(account_lockouts_key_column)
207 
208       after_account_lockout
209       show_lockout_page
210     else
211       after_account_lockout
212       e
213     end
214   end
215 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
55 def json_request?
56   return @json_request if defined?(@json_request)
57   @json_request = request.content_type =~ json_request_content_type_regexp
58 end
json_response()
[show source]
    # File lib/rodauth/features/json.rb
224 def json_response
225   @json_response ||= {}
226 end
json_response_error?()
[show source]
   # File lib/rodauth/features/json.rb
69 def json_response_error?
70   !!json_response[json_response_error_key]
71 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
122 def jwt_payload
123   return @jwt_payload if defined?(@jwt_payload)
124   @jwt_payload = JWT.decode(jwt_token, _jwt_decode_secrets, true, _jwt_decode_opts.merge(:algorithm=>jwt_algorithm))[0]
125 rescue JWT::DecodeError => e
126   rescue_jwt_payload(e)
127 end
jwt_refresh_token_account_ds(account_id)
[show source]
    # File lib/rodauth/features/jwt_refresh.rb
172 def jwt_refresh_token_account_ds(account_id)
173   jwt_refresh_token_ds.where(jwt_refresh_token_account_id_column => account_id)
174 end
jwt_refresh_token_account_token_ds(account_id, token_id)
[show source]
    # File lib/rodauth/features/jwt_refresh.rb
176 def jwt_refresh_token_account_token_ds(account_id, token_id)
177   jwt_refresh_token_account_ds(account_id).
178     where(jwt_refresh_token_id_column=>token_id)
179 end
jwt_refresh_token_ds()
[show source]
    # File lib/rodauth/features/jwt_refresh.rb
181 def jwt_refresh_token_ds
182   db[jwt_refresh_token_table]
183 end
jwt_refresh_token_insert_hash()
[show source]
    # File lib/rodauth/features/jwt_refresh.rb
195 def jwt_refresh_token_insert_hash
196   hash = {jwt_refresh_token_account_id_column => account_id, jwt_refresh_token_key_column => random_key}
197   set_deadline_value(hash, jwt_refresh_token_deadline_column, jwt_refresh_token_deadline_interval)
198   hash
199 end
jwt_refresh_token_match?(key)
[show source]
    # File lib/rodauth/features/jwt_refresh.rb
152 def jwt_refresh_token_match?(key)
153   # We don't need to match tokens if we are requiring a valid current access token
154   return true unless allow_refresh_with_expired_jwt_access_token?
155 
156   # If allowing with expired jwt access token, check the expired session contains
157   # hmac matching submitted and active refresh token.
158   s = session[jwt_refresh_token_hmac_session_key].to_s
159   h = session[jwt_refresh_token_data_session_key].to_s + key
160   timing_safe_eql?(compute_hmac(h), s) || (hmac_secret_rotation? && timing_safe_eql?(compute_old_hmac(h), s))
161 end
jwt_secret()
[show source]
   # File lib/rodauth/features/jwt.rb
66 def jwt_secret
67   raise ConfigurationError, "jwt_secret not set"
68 end
jwt_session_hash()
[show source]
   # File lib/rodauth/features/jwt.rb
70 def jwt_session_hash
71   jwt_session_key ? {jwt_session_key=>session} : session
72 end
jwt_token()
[show source]
   # File lib/rodauth/features/jwt.rb
78 def jwt_token
79   return @jwt_token if defined?(@jwt_token)
80 
81   if (v = request.env['HTTP_AUTHORIZATION']) && v !~ jwt_authorization_ignore
82     @jwt_token = v.sub(jwt_authorization_remove, '')
83   end
84 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       if account_from_session
118         extend_remember_deadline
119       else
120         forget_login
121         clear_session
122       end
123     end
124   elsif account_from_remember_cookie
125     before_load_memory
126     login_session('remember')
127     extend_remember_deadline if extend_remember_deadline?
128     after_load_memory
129   end
130 end
loaded_templates()
[show source]
    # File lib/rodauth/features/base.rb
874 def loaded_templates
875   []
876 end
locked_out?()
[show source]
    # File lib/rodauth/features/lockout.rb
147 def locked_out?
148   if t = convert_timestamp(account_lockouts_ds.get(account_lockouts_deadline_column))
149     if Time.now < t
150       true
151     else
152       unlock_account
153       false
154     end
155   else
156     false
157   end
158 end
logged_in_via_remember_key?()
[show source]
    # File lib/rodauth/features/remember.rb
174 def logged_in_via_remember_key?
175   authenticated_by.include?('remember')
176 end
login(auth_type)
[show source]
   # File lib/rodauth/features/login.rb
87 def login(auth_type)
88   @saved_login_redirect = remove_session_value(login_redirect_session_key)
89   transaction do
90     before_login
91     login_session(auth_type)
92     yield if block_given?
93     after_login
94   end
95   require_response(:_login_response)
96 end
login_confirm_label()
[show source]
   # File lib/rodauth/features/login_password_requirements_base.rb
47 def login_confirm_label
48   "Confirm #{login_label}"
49 end
login_confirmation_matches?(login, login_confirmation)
[show source]
    # File lib/rodauth/features/login_password_requirements_base.rb
131 def login_confirmation_matches?(login, login_confirmation)
132   login.casecmp?(login_confirmation)
133 end
login_does_not_meet_requirements_message()
[show source]
    # File lib/rodauth/features/login_password_requirements_base.rb
109 def login_does_not_meet_requirements_message
110   "invalid login#{", #{login_requirement_message}" if login_requirement_message}"
111 end
login_failed_reset_password_request_form()
[show source]
    # File lib/rodauth/features/reset_password.rb
238 def login_failed_reset_password_request_form
239   render("reset-password-request")
240 end
login_field_autocomplete_value()
[show source]
    # File lib/rodauth/features/base.rb
294 def login_field_autocomplete_value
295   login_uses_email? ? "email" : "on"
296 end
login_hidden_field()
[show source]
    # File lib/rodauth/features/login.rb
130 def login_hidden_field
131   "<input type='hidden' name=\"#{login_param}\" value=\"#{scope.h param(login_param)}\" />"
132 end
login_input_type()
[show source]
    # File lib/rodauth/features/base.rb
318 def login_input_type
319   login_uses_email? ? 'email' : 'text'
320 end
login_meets_email_requirements?(login)
[show source]
    # File lib/rodauth/features/login_password_requirements_base.rb
157 def login_meets_email_requirements?(login)
158   return true unless require_email_address_logins?
159   return true if login_valid_email?(login)
160   set_login_requirement_error_message(:login_not_valid_email, login_not_valid_email_message)
161   return false
162 end
login_meets_length_requirements?(login)
[show source]
    # File lib/rodauth/features/login_password_requirements_base.rb
142 def login_meets_length_requirements?(login)
143   if login_minimum_length > login.length
144     set_login_requirement_error_message(:login_too_short, login_too_short_message)
145     false
146   elsif login_maximum_length < login.length
147     set_login_requirement_error_message(:login_too_long, login_too_long_message)
148     false
149   elsif login_maximum_bytes < login.bytesize
150     set_login_requirement_error_message(:login_too_many_bytes, login_too_many_bytes_message)
151     false
152   else
153     true
154   end
155 end
login_meets_requirements?(login)
[show source]
   # File lib/rodauth/features/login_password_requirements_base.rb
55 def login_meets_requirements?(login)
56   login_meets_length_requirements?(login) && \
57     login_meets_email_requirements?(login)
58 end
login_param_value()

The normalized value of the login parameter

[show source]
    # File lib/rodauth/features/base.rb
516 def login_param_value
517   normalize_login(param(login_param))
518 end
login_required()
[show source]
    # File lib/rodauth/features/base.rb
337 def login_required
338   set_redirect_error_status(login_required_error_status)
339   set_error_reason :login_required
340   set_redirect_error_flash require_login_error_flash
341   redirect require_login_redirect
342 end
login_return_to_requested_location_path()
[show source]
    # File lib/rodauth/features/login.rb
105 def login_return_to_requested_location_path
106   request.fullpath if request.get?
107 end
login_session(auth_type)
[show source]
    # File lib/rodauth/features/base.rb
478 def login_session(auth_type)
479   update_session
480   set_session_value(authenticated_by_session_key, [auth_type])
481 end
login_too_long_message()
[show source]
    # File lib/rodauth/features/login_password_requirements_base.rb
113 def login_too_long_message
114   "maximum #{login_maximum_length} characters"
115 end
login_too_many_bytes_message()
[show source]
    # File lib/rodauth/features/login_password_requirements_base.rb
117 def login_too_many_bytes_message
118   "maximum #{login_maximum_bytes} bytes"
119 end
login_too_short_message()
[show source]
    # File lib/rodauth/features/login_password_requirements_base.rb
121 def login_too_short_message
122   "minimum #{login_minimum_length} characters"
123 end
login_uses_email?()
[show source]
    # File lib/rodauth/features/base.rb
322 def login_uses_email?
323   login_column == :email
324 end
login_valid_email?(login)
[show source]
    # File lib/rodauth/features/login_password_requirements_base.rb
164 def login_valid_email?(login)
165   login =~ login_email_regexp
166 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
118 def logout_additional_form_tags
119   super.to_s + render('global-logout-field')
120 end
modifications_require_password?()
[show source]
    # File lib/rodauth/features/base.rb
543 def modifications_require_password?
544   has_password?
545 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
302 def new_webauthn_credential
303   WebAuthn::Credential.options_for_create(
304     :timeout => webauthn_setup_timeout,
305     :user => {:id=>account_webauthn_user_id, :name=>webauthn_user_name},
306     :authenticator_selection => webauthn_authenticator_selection,
307     :attestation => webauthn_attestation,
308     :extensions => webauthn_extensions,
309     :exclude => account_webauthn_ids,
310     **webauthn_create_relying_party_opts
311   )
312 end
no_longer_active_session()
[show source]
   # File lib/rodauth/features/active_sessions.rb
60 def no_longer_active_session
61   clear_session
62   set_redirect_error_status inactive_session_error_status
63   set_error_reason :inactive_session
64   set_redirect_error_flash active_sessions_error_flash
65   redirect active_sessions_redirect
66 end
normalize_login(login)
[show source]
    # File lib/rodauth/features/base.rb
520 def normalize_login(login)
521   login
522 end
normalize_session_or_flash_key(key)
[show source]
    # File lib/rodauth/features/base.rb
691 def normalize_session_or_flash_key(key)
692   scope.opts[:sessions_convert_symbols] ? key.to_s : key
693 end
null_byte_parameter_value(key, value)

Return nil by default for values with null bytes

[show source]
    # File lib/rodauth/features/base.rb
525 def null_byte_parameter_value(key, value)
526   nil
527 end
only_json?()
[show source]
    # File lib/rodauth/features/base.rb
437 def only_json?
438   scope.class.opts[:rodauth_json] == :only
439 end
open_account?()
[show source]
    # File lib/rodauth/features/base.rb
286 def open_account?
287   skip_status_checks? || account[account_status_column] == account_open_status_value 
288 end
otp_add_key()
[show source]
    # File lib/rodauth/features/otp.rb
283 def otp_add_key
284   _otp_add_key(otp_key)
285   super if defined?(super)
286 end
otp_available?()
[show source]
    # File lib/rodauth/features/otp.rb
243 def otp_available?
244   otp_exists? && !otp_locked_out?
245 end
otp_exists?()
[show source]
    # File lib/rodauth/features/otp.rb
247 def otp_exists?
248   !otp_key.nil?
249 end
otp_hmac_old_secret(key)
[show source]
    # File lib/rodauth/features/otp.rb
383 def otp_hmac_old_secret(key)
384   base32_encode(compute_raw_hmac_with_secret(ROTP::Base32.decode(key), hmac_old_secret), key.bytesize)
385 end
otp_hmac_secret(key)
[show source]
    # File lib/rodauth/features/otp.rb
379 def otp_hmac_secret(key)
380   base32_encode(compute_raw_hmac(ROTP::Base32.decode(key)), key.bytesize)
381 end
otp_issuer()
[show source]
    # File lib/rodauth/features/otp.rb
314 def otp_issuer
315   domain
316 end
otp_key_ds()
[show source]
    # File lib/rodauth/features/otp.rb
450 def otp_key_ds
451   db[otp_keys_table].where(otp_keys_id_column=>session_value)
452 end
otp_keys_use_hmac?()
[show source]
    # File lib/rodauth/features/otp.rb
335 def otp_keys_use_hmac?
336   !!hmac_secret
337 end
otp_last_use()
[show source]
    # File lib/rodauth/features/otp.rb
294 def otp_last_use
295   convert_timestamp(otp_key_ds.get(otp_keys_last_use_column))
296 end
otp_locked_out?()
[show source]
    # File lib/rodauth/features/otp.rb
306 def otp_locked_out?
307   otp_key_ds.get(otp_keys_failures_column) >= otp_auth_failures_limit
308 end
otp_lockout_redirect()
[show source]
    # File lib/rodauth/features/otp_unlock.rb
210 def otp_lockout_redirect
211   otp_unlock_path
212 end
otp_new_secret()
[show source]
    # File lib/rodauth/features/otp.rb
401 def otp_new_secret
402   ROTP::Base32.random_base32.downcase
403 end
otp_provisioning_name()
[show source]
    # File lib/rodauth/features/otp.rb
318 def otp_provisioning_name
319   account[login_column]
320 end
otp_provisioning_uri()
[show source]
    # File lib/rodauth/features/otp.rb
310 def otp_provisioning_uri
311   otp.provisioning_uri(otp_provisioning_name)
312 end
otp_qr_code()
[show source]
    # File lib/rodauth/features/otp.rb
322 def otp_qr_code
323   svg = RQRCode::QRCode.new(otp_provisioning_uri).as_svg(:module_size=>8, :viewbox=>true, :use_path=>true, :fill=>"fff")
324   svg.sub(/\A<\?xml version="1\.0" standalone="yes"\?>/, '')
325 end
otp_record_authentication_failure()
[show source]
    # File lib/rodauth/features/otp.rb
298 def otp_record_authentication_failure
299   otp_key_ds.update(otp_keys_failures_column=>Sequel.identifier(otp_keys_failures_column) + 1)
300 end
otp_remove()
[show source]
    # File lib/rodauth/features/otp.rb
278 def otp_remove
279   otp_key_ds.delete
280   @otp_key = nil
281 end
otp_remove_auth_failures()
[show source]
    # File lib/rodauth/features/otp.rb
302 def otp_remove_auth_failures
303   otp_key_ds.update(otp_keys_failures_column=>0)
304 end
otp_tmp_key(secret)
[show source]
    # File lib/rodauth/features/otp.rb
374 def otp_tmp_key(secret)
375   _otp_tmp_key(secret)
376   clear_cached_otp
377 end
otp_unlock_auth_failure()
[show source]
    # File lib/rodauth/features/otp_unlock.rb
145 def otp_unlock_auth_failure
146   h = {
147     otp_unlock_num_successes_column=>0,
148     otp_unlock_next_auth_attempt_after_column=>Sequel.date_add(Sequel::CURRENT_TIMESTAMP, :seconds=>otp_unlock_auth_failure_cooldown_seconds)
149   }
150 
151   if otp_unlock_ds.update(h) == 0
152     h[otp_unlock_id_column] = session_value
153 
154     # If row already exists when inserting, no need to do anything
155     raises_uniqueness_violation?{otp_unlock_ds.insert(h)}
156   end
157 end
otp_unlock_auth_success()
[show source]
    # File lib/rodauth/features/otp_unlock.rb
159 def otp_unlock_auth_success
160   deadline = Sequel.date_add(Sequel::CURRENT_TIMESTAMP, :seconds=>otp_unlock_success_cooldown_seconds)
161 
162   # Add WHERE to avoid possible race condition when multiple unlock auth requests
163   # are sent at the same time (only the first should increment num successes).
164   if otp_unlock_ds.
165       where(Sequel[otp_unlock_next_auth_attempt_after_column] < Sequel::CURRENT_TIMESTAMP).
166       update(
167         otp_unlock_num_successes_column=>Sequel[otp_unlock_num_successes_column]+1,
168         otp_unlock_next_auth_attempt_after_column=>deadline
169       ) == 0
170 
171     # Ignore uniqueness errors when inserting after a failed update,
172     # which could be caused due to the race condition mentioned above.
173     raises_uniqueness_violation? do
174       otp_unlock_ds.insert(
175         otp_unlock_id_column=>session_value,
176         otp_unlock_next_auth_attempt_after_column=>deadline
177       )
178     end
179   end
180 
181   @otp_unlock_data = nil
182   # :nocov:
183   if otp_unlock_data
184   # :nocov:
185     if otp_unlock_num_successes >= otp_unlock_auths_required
186       # At least the requisite number of consecutive successful unlock
187       # authentications. Unlock OTP authentication.
188       otp_key_ds.update(otp_keys_failures_column => 0)
189 
190       # Remove OTP unlock metadata when unlocking OTP authentication
191       otp_unlock_reset
192     # else
193     #  # Still need additional consecutive successful unlock attempts.
194     end
195   # else
196   #  # if row isn't available, probably the process was reset during this,
197   #  # and it's safe to do nothing in that case.
198   end
199 end
otp_unlock_available?()
[show source]
    # File lib/rodauth/features/otp_unlock.rb
115 def otp_unlock_available?
116   if otp_unlock_data
117     next_auth_attempt_after = otp_unlock_next_auth_attempt_after
118     current_timestamp = Time.now
119 
120     if (next_auth_attempt_after < current_timestamp - otp_unlock_deadline_seconds)
121       # Unlock process not fully completed within deadline, reset process
122       otp_unlock_reset
123       true
124     else
125       if next_auth_attempt_after > current_timestamp
126         # If next auth attempt after timestamp is in the future, that means the next
127         # unlock attempt cannot happen until then.
128         false 
129       else
130         if otp_unlock_num_successes == 0
131           # 0 value indicates previous attempt was a failure. Since failure cooldown
132           # period has passed, reset process so user gets full deadline period
133           otp_unlock_reset
134         end
135         true
136       end
137     end
138   else
139     # No row means no unlock attempts yet (or previous attempt was more than the
140     # deadline account, so unlocking is available
141     true
142   end
143 end
otp_unlock_data()
[show source]
    # File lib/rodauth/features/otp_unlock.rb
240 def otp_unlock_data
241   @otp_unlock_data ||= otp_unlock_ds.first
242 end
otp_unlock_deadline()
[show source]
    # File lib/rodauth/features/otp_unlock.rb
222 def otp_unlock_deadline
223   otp_unlock_next_auth_attempt_after + otp_unlock_deadline_seconds
224 end
otp_unlock_deadline_passed?()
[show source]
    # File lib/rodauth/features/otp_unlock.rb
201 def otp_unlock_deadline_passed?
202   otp_unlock_data ? (otp_unlock_next_auth_attempt_after < Time.now - otp_unlock_deadline_seconds) : false
203 end
otp_unlock_ds()
[show source]
    # File lib/rodauth/features/otp_unlock.rb
253 def otp_unlock_ds
254   db[otp_unlock_table].where(otp_unlock_id_column=>session_value)
255 end
otp_unlock_next_auth_attempt_after()
[show source]
    # File lib/rodauth/features/otp_unlock.rb
214 def otp_unlock_next_auth_attempt_after
215   if otp_unlock_data
216     convert_timestamp(otp_unlock_data[otp_unlock_next_auth_attempt_after_column])
217   else
218     Time.now
219   end
220 end
otp_unlock_not_available_set_refresh_header()
[show source]
    # File lib/rodauth/features/otp_unlock.rb
230 def otp_unlock_not_available_set_refresh_header
231   response.headers["refresh"] = ((otp_unlock_next_auth_attempt_after - Time.now).to_i + 1).to_s
232 end
otp_unlock_num_successes()
[show source]
    # File lib/rodauth/features/otp_unlock.rb
226 def otp_unlock_num_successes
227   otp_unlock_data ? otp_unlock_data[otp_unlock_num_successes_column] : 0
228 end
otp_unlock_refresh_tag()
[show source]
    # File lib/rodauth/features/otp_unlock.rb
205 def otp_unlock_refresh_tag
206   # RODAUTH3: Remove
207   "<meta http-equiv=\"refresh\" content=\"#{(otp_unlock_next_auth_attempt_after - Time.now).to_i + 1}\">"
208 end
otp_unlock_reset()
[show source]
    # File lib/rodauth/features/otp_unlock.rb
248 def otp_unlock_reset
249   otp_unlock_ds.delete
250   @otp_unlock_data = nil
251 end
otp_unlock_success_cooldown_seconds()
[show source]
    # File lib/rodauth/features/otp_unlock.rb
244 def otp_unlock_success_cooldown_seconds
245   (_otp_interval+(otp_drift||0))*2
246 end
otp_update_last_use()
[show source]
    # File lib/rodauth/features/otp.rb
288 def otp_update_last_use
289   otp_key_ds.
290     where(Sequel.date_add(otp_keys_last_use_column, :seconds=>_otp_interval) < Sequel::CURRENT_TIMESTAMP).
291     update(otp_keys_last_use_column=>Sequel::CURRENT_TIMESTAMP) == 1
292 end
otp_user_key()
[show source]
    # File lib/rodauth/features/otp.rb
327 def otp_user_key
328   @otp_user_key ||= if otp_keys_use_hmac?
329     otp_hmac_secret(otp_key)
330   else
331     otp_key
332   end
333 end
otp_valid_code?(ot_pass)
[show source]
    # File lib/rodauth/features/otp.rb
251 def otp_valid_code?(ot_pass)
252   if _otp_valid_code?(ot_pass, otp)
253     true
254   elsif hmac_secret_rotation? && _otp_valid_code?(ot_pass, _otp_for_key(otp_hmac_old_secret(otp_key)))
255     _otp_valid_code_for_old_secret
256     true
257   else
258     false
259   end
260 end
otp_valid_key?(secret)
[show source]
    # File lib/rodauth/features/otp.rb
387 def otp_valid_key?(secret)
388   return false unless secret =~ /\A([a-z2-7]{16}|[a-z2-7]{32})\z/
389   if otp_keys_use_hmac?
390     # Purposely do not allow creating new OTPs with old secrets,
391     # since OTP rotation is difficult.  The user will get shown
392     # the same page with an updated secret, which they can submit
393     # to setup OTP.
394     timing_safe_eql?(otp_hmac_secret(param(otp_setup_raw_param)), secret)
395   else
396     true
397   end
398 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
511 def over_max_bytesize_param_value(key, value)
512   nil
513 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
494 def param(key)
495   param_or_nil(key).to_s
496 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
500 def param_or_nil(key)
501   value = raw_param(key)
502   unless value.nil?
503     value = value.to_s
504     value = over_max_bytesize_param_value(key, value) if max_param_bytesize && value.bytesize > max_param_bytesize
505     value = null_byte_parameter_value(key, value) if value && value.include?("\0")
506   end
507   value
508 end
password_confirm_label()
[show source]
   # File lib/rodauth/features/login_password_requirements_base.rb
51 def password_confirm_label
52   "Confirm #{password_label}"
53 end
password_does_not_contain_null_byte?(password)
[show source]
    # File lib/rodauth/features/login_password_requirements_base.rb
183 def password_does_not_contain_null_byte?(password)
184   return true unless password.include?("\0")
185   set_password_requirement_error_message(:password_contains_null_byte, contains_null_byte_message)
186   false
187 end
password_does_not_meet_requirements_message()
[show source]
   # File lib/rodauth/features/login_password_requirements_base.rb
88 def password_does_not_meet_requirements_message
89   "invalid password, does not meet requirements#{" (#{password_requirement_message})" if password_requirement_message}"
90 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
298 def password_field_autocomplete_value
299   @password_field_autocomplete_value || 'current-password'
300 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
19 def password_hash(password)
20   return super unless use_argon2?
21 
22   if secret = argon2_secret
23     argon2_params = Hash[password_hash_cost]
24     argon2_params[:secret] = secret
25   else
26     argon2_params = password_hash_cost
27   end
28   ::Argon2::Password.new(argon2_params).create(password)
29 end
password_hash_cost()
[show source]
   # File lib/rodauth/features/argon2.rb
45 def password_hash_cost
46   return super unless use_argon2?
47   argon2_hash_cost
48 end
password_hash_ds()
[show source]
    # File lib/rodauth/features/base.rb
864 def password_hash_ds
865   db[password_hash_table].where(password_hash_id_column=>account ? account_id : session_value)
866 end
password_hash_match?(hash, password)
[show source]
   # File lib/rodauth/features/argon2.rb
50 def password_hash_match?(hash, password)
51   return super unless argon2_hash_algorithm?(hash)
52   argon2_password_hash_match?(hash, password)
53 end
password_hash_using_salt(password, salt)
[show source]
   # File lib/rodauth/features/argon2.rb
55 def password_hash_using_salt(password, salt)
56   return super unless argon2_hash_algorithm?(salt)
57   argon2_password_hash_using_salt_and_secret(password, salt, argon2_secret)
58 end
password_match?(password)
[show source]
    # File lib/rodauth/features/base.rb
459 def password_match?(password)
460   if hash = get_password_hash
461     if account_password_hash_column || !use_database_authentication_functions?
462       password_hash_match?(hash, password)
463     else
464       database_function_password_match?(:rodauth_valid_password_hash, account_id, password, hash)
465     end 
466   end
467 end
password_meets_length_requirements?(password)
[show source]
    # File lib/rodauth/features/login_password_requirements_base.rb
168 def password_meets_length_requirements?(password)
169   if password_minimum_length > password.length
170     set_password_requirement_error_message(:password_too_short, password_too_short_message)
171     false
172   elsif password_maximum_length && password_maximum_length < password.length
173     set_password_requirement_error_message(:password_too_long, password_too_long_message)
174     false
175   elsif password_maximum_bytes && password_maximum_bytes < password.bytesize
176     set_password_requirement_error_message(:password_too_many_bytes, password_too_many_bytes_message)
177     false
178   else
179     true
180   end
181 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
252 def password_reset_ds(id=account_id)
253   db[reset_password_table].where(reset_password_id_column=>id)
254 end
password_too_long_message()
[show source]
   # File lib/rodauth/features/login_password_requirements_base.rb
92 def password_too_long_message
93   "maximum #{password_maximum_length} characters"
94 end
password_too_many_bytes_message()
[show source]
   # File lib/rodauth/features/login_password_requirements_base.rb
96 def password_too_many_bytes_message
97   "maximum #{password_maximum_bytes} bytes"
98 end
password_too_short_message()
[show source]
    # File lib/rodauth/features/login_password_requirements_base.rb
100 def password_too_short_message
101   "minimum #{password_minimum_length} characters"
102 end
possible_authentication_methods()
[show source]
    # File lib/rodauth/features/base.rb
547 def possible_authentication_methods
548   has_password? ? ['password'] : []
549 end
post_configure()
[show source]
    # File lib/rodauth/features/base.rb
441 def post_configure
442   require 'bcrypt' if require_bcrypt?
443   db.extension :date_arithmetic if use_date_arithmetic?
444 
445   if method(:convert_token_id_to_integer?).owner == Rodauth::Base && (db rescue false) && db.table_exists?(accounts_table) && db.schema(accounts_table).find{|col, v| break v[:type] == :integer if col == account_id_column}
446     self.class.send(:define_method, :convert_token_id_to_integer?){true}
447   end
448 
449   route_hash= {}
450   self.class.routes.each do |meth|
451     route_meth = "#{meth.to_s.sub(/\Ahandle_/, '')}_route"
452     if route = send(route_meth)
453       route_hash["/#{route}"] = meth
454     end
455   end
456   self.class.route_hash = route_hash.freeze
457 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
893 def raises_uniqueness_violation?(&block)
894   transaction(:savepoint=>:only, &block)
895   false
896 rescue unique_constraint_violation_class => e
897   e
898 end
random_key()
[show source]
    # File lib/rodauth/features/base.rb
682 def random_key
683   SecureRandom.urlsafe_base64(32)
684 end
raw_param(key)
[show source]
    # File lib/rodauth/features/base.rb
529 def raw_param(key)
530   request.params[key]
531 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
659 def redirect(path)
660   request.redirect(path)
661 end
remember_key_ds(id=account_id)
[show source]
    # File lib/rodauth/features/remember.rb
261 def remember_key_ds(id=account_id)
262   db[remember_table].where(remember_id_column=>id)
263 end
remember_login()
[show source]
    # File lib/rodauth/features/remember.rb
132 def remember_login
133   get_remember_key
134   set_remember_cookie
135   set_session_value(remember_deadline_extended_session_key, Time.now.to_i) if extend_remember_deadline?
136 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 && !(valid = timing_safe_eql?(key, compute_hmac(actual)))
100     if hmac_secret_rotation? && (valid = timing_safe_eql?(key, compute_old_hmac(actual)))
101       _set_remember_cookie(id, actual, deadline)
102     elsif !(raw_remember_token_deadline && raw_remember_token_deadline > convert_timestamp(deadline))
103       return
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
92 def remove_active_session(session_id)
93   active_sessions_ds.where(active_sessions_session_id_column=>session_id).delete
94 end
remove_all_active_sessions()
[show source]
   # File lib/rodauth/features/active_sessions.rb
96 def remove_all_active_sessions
97   active_sessions_ds.delete
98 end
remove_all_active_sessions_except_current()
[show source]
    # File lib/rodauth/features/active_sessions.rb
104 def remove_all_active_sessions_except_current 
105   if session_id = session[session_id_session_key]
106     remove_all_active_sessions_except_for(session_id)
107   else
108     remove_all_active_sessions
109   end
110 end
remove_all_active_sessions_except_for(session_id)
[show source]
    # File lib/rodauth/features/active_sessions.rb
100 def remove_all_active_sessions_except_for(session_id)
101   active_sessions_ds.exclude(active_sessions_session_id_column=>compute_hmacs(session_id)).delete
102 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
86 def remove_current_session
87   if session_id = session[session_id_session_key]
88     remove_active_session(compute_hmacs(session_id))
89   end
90 end
remove_email_auth_key()
[show source]
    # File lib/rodauth/features/email_auth.rb
127 def remove_email_auth_key
128   email_auth_ds.delete
129 end
remove_inactive_sessions()
[show source]
    # File lib/rodauth/features/active_sessions.rb
112 def remove_inactive_sessions
113   if cond = inactive_session_cond
114     active_sessions_ds.where(cond).delete
115   end
116 end
remove_jwt_refresh_token_key(token)
[show source]
    # File lib/rodauth/features/jwt_refresh.rb
185 def remove_jwt_refresh_token_key(token)
186   account_id, token_id, _ = _account_refresh_token_split(token)
187   jwt_refresh_token_account_token_ds(account_id, token_id).delete
188 end
remove_lockout_metadata()
[show source]
    # File lib/rodauth/features/lockout.rb
280 def remove_lockout_metadata
281   account_login_failures_ds.delete
282   account_lockouts_ds.delete
283 end
remove_remember_key(id=account_id)
[show source]
    # File lib/rodauth/features/remember.rb
170 def remove_remember_key(id=account_id)
171   remember_key_ds(id).delete
172 end
remove_reset_password_key()
[show source]
    # File lib/rodauth/features/reset_password.rb
180 def remove_reset_password_key
181   password_reset_ds.delete
182 end
remove_session_value(key)
[show source]
    # File lib/rodauth/features/base.rb
951 def remove_session_value(key)
952   session.delete(key)
953 end
remove_verify_account_key()
[show source]
    # File lib/rodauth/features/verify_account.rb
167 def remove_verify_account_key
168   verify_account_ds.delete
169 end
remove_verify_login_change_key()
[show source]
    # File lib/rodauth/features/verify_login_change.rb
108 def remove_verify_login_change_key
109   verify_login_change_ds.delete
110 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
433 def render(page)
434   _view(:render, page)
435 end
render_multi_phase_login_forms()
[show source]
    # File lib/rodauth/features/login.rb
138 def render_multi_phase_login_forms
139   multi_phase_login_forms.sort.map{|_, form, _| form}.join("\n")
140 end
request()
[show source]
    # File lib/rodauth/features/base.rb
154 def request
155   scope.request
156 end
require_account()
[show source]
    # File lib/rodauth/features/base.rb
378 def require_account
379   require_authentication
380   require_account_session
381 end
require_account_session()
[show source]
    # File lib/rodauth/features/base.rb
700 def require_account_session
701   unless account_from_session
702     clear_session
703     login_required
704   end
705 end
require_authentication()
[show source]
    # File lib/rodauth/features/base.rb
374 def require_authentication
375   require_login
376 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
366 def require_login
367   login_required unless logged_in?
368 end
require_login_confirmation?()
[show source]
    # File lib/rodauth/features/verify_account.rb
159 def require_login_confirmation?
160   false
161 end
require_login_redirect()
[show source]
    # File lib/rodauth/features/login.rb
142 def require_login_redirect
143   login_path
144 end
require_otp_setup()
[show source]
    # File lib/rodauth/features/otp.rb
234 def require_otp_setup
235   unless otp_exists?
236     set_redirect_error_status(two_factor_not_setup_error_status)
237     set_error_reason :two_factor_not_setup
238     set_redirect_error_flash two_factor_not_setup_error_flash
239     redirect two_factor_need_setup_redirect
240   end
241 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_response(meth)
[show source]
    # File lib/rodauth/features/base.rb
942 def require_response(meth)
943   send(meth)
944   raise ConfigurationError, "#{meth.to_s.sub(/\A_/, '')} overridden without returning a response (should use redirect or request.halt)."
945 end
require_sms_available()
[show source]
    # File lib/rodauth/features/sms_codes.rb
337 def require_sms_available
338   require_sms_setup
339 
340   if sms_locked_out?
341     set_redirect_error_status(lockout_error_status)
342     set_error_reason :sms_locked_out
343     set_redirect_error_flash sms_lockout_error_flash
344     redirect sms_lockout_redirect
345   end
346 end
require_sms_not_setup()
[show source]
    # File lib/rodauth/features/sms_codes.rb
328 def require_sms_not_setup
329   if sms_setup?
330     set_redirect_error_status(sms_already_setup_error_status)
331     set_error_reason :sms_already_setup
332     set_redirect_error_flash sms_already_setup_error_flash
333     redirect sms_already_setup_redirect
334   end
335 end
require_sms_setup()
[show source]
    # File lib/rodauth/features/sms_codes.rb
319 def require_sms_setup
320   unless sms_setup?
321     set_redirect_error_status(two_factor_not_setup_error_status)
322     set_error_reason :sms_not_setup
323     set_redirect_error_flash sms_not_setup_error_flash
324     redirect sms_needs_setup_redirect
325   end
326 end
require_two_factor_authenticated()
[show source]
    # File lib/rodauth/features/two_factor_base.rb
156 def require_two_factor_authenticated
157   unless two_factor_authenticated?
158     if two_factor_auth_return_to_requested_location?
159       set_session_value(two_factor_auth_redirect_session_key, request.fullpath)
160     end
161     set_redirect_error_status(two_factor_need_authentication_error_status)
162     set_error_reason :two_factor_need_authentication
163     set_redirect_error_flash two_factor_need_authentication_error_flash
164     redirect two_factor_auth_required_redirect
165   end
166 end
require_two_factor_not_authenticated(auth_type = nil)
[show source]
    # File lib/rodauth/features/two_factor_base.rb
147 def require_two_factor_not_authenticated(auth_type = nil)
148   if two_factor_authenticated? || (auth_type && two_factor_login_type_match?(auth_type))
149     set_redirect_error_status(two_factor_already_authenticated_error_status)
150     set_error_reason :two_factor_already_authenticated
151     set_redirect_error_flash two_factor_already_authenticated_error_flash
152     redirect two_factor_already_authenticated_redirect
153   end
154 end
require_two_factor_setup()
[show source]
    # File lib/rodauth/features/two_factor_base.rb
135 def require_two_factor_setup
136   # Avoid database query if already authenticated via 2nd factor
137   return if two_factor_authenticated?
138 
139   return if uses_two_factor_authentication?
140 
141   set_redirect_error_status(two_factor_not_setup_error_status)
142   set_error_reason :two_factor_not_setup
143   set_redirect_error_flash two_factor_not_setup_error_flash
144   redirect two_factor_need_setup_redirect
145 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
129 def rescue_jwt_payload(_)
130   @jwt_payload = false
131 end
reset_password_email_recently_sent?()
[show source]
    # File lib/rodauth/features/reset_password.rb
210 def reset_password_email_recently_sent?
211   (email_last_sent = get_reset_password_email_last_sent) && (Time.now - email_last_sent < reset_password_skip_resend_email_within)
212 end
reset_password_key_insert_hash()
[show source]
    # File lib/rodauth/features/reset_password.rb
246 def reset_password_key_insert_hash
247   hash = {reset_password_id_column=>account_id, reset_password_key_column=>reset_password_key_value}
248   set_deadline_value(hash, reset_password_deadline_column, reset_password_deadline_interval)
249   hash
250 end
reset_password_request_for_unverified_account()
[show source]
    # File lib/rodauth/features/reset_password.rb
176 def reset_password_request_for_unverified_account
177   throw_error_reason(:unverified_account, unopen_account_error_status, login_param, unverified_account_message)
178 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
158 def response
159   scope.response
160 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
884 def retry_on_uniqueness_violation(&block)
885   if raises_uniqueness_violation?(&block)
886     yield
887   end
888 end
return_json_response()
[show source]
    # File lib/rodauth/features/json.rb
206 def return_json_response
207   _return_json_response
208 end
return_response(body=nil)
[show source]
    # File lib/rodauth/features/base.rb
663 def return_response(body=nil)
664   response.write(body) if body
665   request.halt
666 end
route!()
[show source]
    # File lib/rodauth/features/base.rb
170 def route!
171   if meth = self.class.route_hash[request.remaining_path]
172     send(meth)
173   end
174 
175   nil
176 end
route_path(route, opts={})
[show source]
    # File lib/rodauth/features/base.rb
668 def route_path(route, opts={})
669   path  = "#{prefix}/#{route}"
670   path += "?#{Rack::Utils.build_nested_query(opts)}" unless opts.empty?
671   path
672 end
route_url(route, opts={})
[show source]
    # File lib/rodauth/features/base.rb
674 def route_url(route, opts={})
675   "#{base_url}#{route_path(route, opts)}"
676 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
124 def send_verify_login_change_email(login)
125   send_email(create_verify_login_change_email(login))
126 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
162 def session
163   scope.session
164 end
session_inactivity_deadline_condition()
[show source]
    # File lib/rodauth/features/active_sessions.rb
181 def session_inactivity_deadline_condition
182   if deadline = session_inactivity_deadline
183     Sequel[active_sessions_last_use_column] < Sequel.date_sub(Sequel::CURRENT_TIMESTAMP, seconds: deadline)
184   end
185 end
session_jwt()
[show source]
   # File lib/rodauth/features/jwt.rb
74 def session_jwt
75   JWT.encode(jwt_session_hash, jwt_secret, jwt_algorithm)
76 end
session_lifetime_deadline_condition()
[show source]
    # File lib/rodauth/features/active_sessions.rb
187 def session_lifetime_deadline_condition
188   if deadline = session_lifetime_deadline
189     Sequel[active_sessions_created_at_column] < Sequel.date_sub(Sequel::CURRENT_TIMESTAMP, seconds: deadline)
190   end
191 end
session_value()
[show source]
    # File lib/rodauth/features/base.rb
277 def session_value
278   session[session_key]
279 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
920 def set_deadline_value(hash, column, interval)
921   if set_deadline_values?
922     # :nocov:
923     hash[column] = Sequel.date_add(Sequel::CURRENT_TIMESTAMP, interval)
924     # :nocov:
925   end
926 end
set_deadline_values?()
[show source]
    # File lib/rodauth/features/base.rb
750 def set_deadline_values?
751   db.database_type == :mysql
752 end
set_email_auth_email_last_sent()
[show source]
    # File lib/rodauth/features/email_auth.rb
115 def set_email_auth_email_last_sent
116    email_auth_ds.update(email_auth_email_last_sent_column=>Sequel::CURRENT_TIMESTAMP) if email_auth_email_last_sent_column
117 end
set_error_flash(message)
[show source]
    # File lib/rodauth/features/base.rb
350 def set_error_flash(message)
351   flash.now[flash_error_key] = message
352 end
set_error_reason(reason)
[show source]
    # File lib/rodauth/features/base.rb
738 def set_error_reason(reason)
739 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
178 def set_field_error(field, error)
179   (@field_errors ||= {})[field] = error
180 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   set_response_header("www-authenticate", "Basic realm=\"#{http_basic_auth_realm}\"")
77 end
set_jwt()
[show source]
    # File lib/rodauth/features/jwt.rb
150 def set_jwt
151   set_jwt_token(session_jwt)
152 end
set_jwt_refresh_token_hmac_session_key(token)
[show source]
    # File lib/rodauth/features/jwt_refresh.rb
201 def set_jwt_refresh_token_hmac_session_key(token)
202   if allow_refresh_with_expired_jwt_access_token?
203     key = _account_refresh_token_split(token).last
204     data = random_key
205     set_session_value(jwt_refresh_token_data_session_key, data)
206     set_session_value(jwt_refresh_token_hmac_session_key, compute_hmac(data + key))
207   end
208 end
set_jwt_token(token)
[show source]
   # File lib/rodauth/features/jwt.rb
86 def set_jwt_token(token)
87   set_response_header('authorization', token)
88 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
125 def set_login_requirement_error_message(reason, message)
126   set_error_reason(reason)
127   @login_requirement_message = message
128 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
358 def set_notice_flash(message)
359   flash[flash_notice_key] = message
360 end
set_notice_now_flash(message)
[show source]
    # File lib/rodauth/features/base.rb
362 def set_notice_now_flash(message)
363   flash.now[flash_notice_key] = message
364 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
104 def set_password_requirement_error_message(reason, message)
105   set_error_reason(reason)
106   @password_requirement_message = message
107 end
set_redirect_error_flash(message)
[show source]
    # File lib/rodauth/features/base.rb
354 def set_redirect_error_flash(message)
355   flash[flash_error_key] = message
356 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
712 def set_redirect_error_status(status)
713 end
set_reset_password_email_last_sent()
[show source]
    # File lib/rodauth/features/reset_password.rb
198 def set_reset_password_email_last_sent
199    password_reset_ds.update(reset_password_email_last_sent_column=>Sequel::CURRENT_TIMESTAMP) if reset_password_email_last_sent_column
200 end
set_response_error_reason_status(reason, status)
[show source]
    # File lib/rodauth/features/base.rb
719 def set_response_error_reason_status(reason, status)
720   set_error_reason(reason)
721   set_response_error_status(status)
722 end
set_response_error_status(status)
[show source]
    # File lib/rodauth/features/base.rb
715 def set_response_error_status(status)
716   response.status = status
717 end
set_response_header(key, value)
[show source]
    # File lib/rodauth/features/base.rb
571 def set_response_header(key, value)
572   response.headers[key] = value
573 end
set_session_value(key, value)
[show source]
    # File lib/rodauth/features/base.rb
947 def set_session_value(key, value)
948   session[key] = value
949 end
set_single_session_key(data)
[show source]
    # File lib/rodauth/features/single_session.rb
 99 def set_single_session_key(data)
100   data = compute_hmac(data) if hmac_secret
101   set_session_value(single_session_session_key, data)
102 end
set_title(title)
[show source]
    # File lib/rodauth/features/base.rb
344 def set_title(title)
345   if title_instance_variable
346     scope.instance_variable_set(title_instance_variable, title)
347   end
348 end
set_unlock_account_email_last_sent()
[show source]
    # File lib/rodauth/features/lockout.rb
237 def set_unlock_account_email_last_sent
238   account_lockouts_ds.update(account_lockouts_email_last_sent_column=>Sequel::CURRENT_TIMESTAMP) if account_lockouts_email_last_sent_column
239 end
set_verify_account_email_last_sent()
[show source]
    # File lib/rodauth/features/verify_account.rb
225 def set_verify_account_email_last_sent
226    verify_account_ds.update(verify_account_email_last_sent_column=>Sequel::CURRENT_TIMESTAMP) if verify_account_email_last_sent_column
227 end
setup_account_verification()
[show source]
    # File lib/rodauth/features/verify_account.rb
237 def setup_account_verification
238   generate_verify_account_key_value
239   create_verify_account_key
240   send_verify_account_email
241 end
show_lockout_page()
[show source]
    # File lib/rodauth/features/lockout.rb
285 def show_lockout_page
286   set_response_error_reason_status(:account_locked_out, lockout_error_status)
287   set_error_flash login_lockout_error_flash
288   return_response unlock_account_request_view
289 end
single_session_ds(id=session_value)
[show source]
    # File lib/rodauth/features/single_session.rb
104 def single_session_ds(id=session_value)
105   db[single_session_table].
106     where(single_session_id_column=>id)
107 end
skip_login_field_on_login?()
[show source]
    # File lib/rodauth/features/login.rb
116 def skip_login_field_on_login?
117   return false unless use_multi_phase_login?
118   valid_login_entered?
119 end
skip_password_field_on_login?()
[show source]
    # File lib/rodauth/features/login.rb
121 def skip_password_field_on_login?
122   return false unless use_multi_phase_login?
123   !valid_login_entered?
124 end
skip_status_checks?()
[show source]
   # File lib/rodauth/features/close_account.rb
85 def skip_status_checks?
86   false
87 end
sms_auth_message(code)
[show source]
    # File lib/rodauth/features/sms_codes.rb
399 def sms_auth_message(code)
400   "SMS authentication code for #{domain} is #{code}"
401 end
sms_available?()
[show source]
    # File lib/rodauth/features/sms_codes.rb
452 def sms_available?
453   sms_setup? && !sms_locked_out?
454 end
sms_code()
[show source]
    # File lib/rodauth/features/sms_codes.rb
431 def sms_code
432   sms[sms_code_column]
433 end
sms_code_issued_at()
[show source]
    # File lib/rodauth/features/sms_codes.rb
435 def sms_code_issued_at
436   convert_timestamp(sms[sms_issued_at_column])
437 end
sms_code_match?(code)
[show source]
    # File lib/rodauth/features/sms_codes.rb
348 def sms_code_match?(code)
349   return false unless sms_current_auth?
350   timing_safe_eql?(code, sms_code)
351 end
sms_codes_primary?()
[show source]
    # File lib/rodauth/features/sms_codes.rb
500 def sms_codes_primary?
501   (features & [:otp, :webauthn]).empty?
502 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
362 def sms_confirm_failure
363   sms_ds.delete
364 end
sms_confirm_message(code)
[show source]
    # File lib/rodauth/features/sms_codes.rb
403 def sms_confirm_message(code)
404   "SMS confirmation code for #{domain} is #{code}"
405 end
sms_confirmation_match?(code)
[show source]
    # File lib/rodauth/features/sms_codes.rb
353 def sms_confirmation_match?(code)
354   sms_needs_confirmation? && sms_code_match?(code)
355 end
sms_current_auth?()
[show source]
    # File lib/rodauth/features/sms_codes.rb
460 def sms_current_auth?
461   sms_code && sms_code_issued_at + sms_code_allowed_seconds > Time.now
462 end
sms_disable()
[show source]
    # File lib/rodauth/features/sms_codes.rb
357 def sms_disable
358   sms_ds.delete
359   @sms = nil
360 end
sms_ds()
[show source]
    # File lib/rodauth/features/sms_codes.rb
528 def sms_ds
529   db[sms_codes_table].where(sms_id_column=>session_value)
530 end
sms_failures()
[show source]
    # File lib/rodauth/features/sms_codes.rb
439 def sms_failures
440   sms[sms_failures_column]
441 end
sms_locked_out?()
[show source]
    # File lib/rodauth/features/sms_codes.rb
456 def sms_locked_out?
457   sms_failures >= sms_failure_limit
458 end
sms_needs_confirmation?()
[show source]
    # File lib/rodauth/features/sms_codes.rb
448 def sms_needs_confirmation?
449   sms && sms_failures.nil?
450 end
sms_needs_confirmation_notice_flash()
[show source]
    # File lib/rodauth/features/sms_codes.rb
407 def sms_needs_confirmation_notice_flash
408   sms_needs_confirmation_error_flash
409 end
sms_new_auth_code()
[show source]
    # File lib/rodauth/features/sms_codes.rb
508 def sms_new_auth_code
509   SecureRandom.random_number(10**sms_auth_code_length).to_s.rjust(sms_auth_code_length, "0")
510 end
sms_new_confirm_code()
[show source]
    # File lib/rodauth/features/sms_codes.rb
512 def sms_new_confirm_code
513   SecureRandom.random_number(10**sms_confirm_code_length).to_s.rjust(sms_confirm_code_length, "0")
514 end
sms_normalize_phone(phone)
[show source]
    # File lib/rodauth/features/sms_codes.rb
504 def sms_normalize_phone(phone)
505   phone.to_s.gsub(/\D+/, '')
506 end
sms_phone()
[show source]
    # File lib/rodauth/features/sms_codes.rb
427 def sms_phone
428   sms[sms_phone_column]
429 end
sms_record_failure()
[show source]
    # File lib/rodauth/features/sms_codes.rb
422 def sms_record_failure
423   update_sms(sms_failures_column=>Sequel.expr(sms_failures_column)+1)
424   sms[sms_failures_column] = sms_ds.get(sms_failures_column)
425 end
sms_remove_expired_confirm_code()
[show source]
    # File lib/rodauth/features/sms_codes.rb
415 def sms_remove_expired_confirm_code
416   db[sms_codes_table].
417     where(sms_id_column=>session_value, sms_failures_column => nil).
418     where(Sequel[sms_issued_at_column] < Sequel.date_sub(Sequel::CURRENT_TIMESTAMP, seconds: sms_confirm_deadline)).
419     delete
420 end
sms_remove_failures()
[show source]
    # File lib/rodauth/features/sms_codes.rb
373 def sms_remove_failures
374   return if sms_needs_confirmation?
375   update_hash_ds(sms, sms_ds.exclude(sms_failures_column => nil), sms_failures_column => 0, sms_code_column => nil)
376 end
sms_send(phone, message)
[show source]
    # File lib/rodauth/features/sms_codes.rb
516 def sms_send(phone, message)
517   raise ConfigurationError, "sms_send needs to be defined in the Rodauth configuration for SMS sending to work"
518 end
sms_send_auth_code()
[show source]
    # File lib/rodauth/features/sms_codes.rb
383 def sms_send_auth_code
384   code = sms_new_auth_code
385   sms_set_code(code)
386   sms_send(sms_phone, sms_auth_message(code))
387 end
sms_send_confirm_code()
[show source]
    # File lib/rodauth/features/sms_codes.rb
389 def sms_send_confirm_code
390   code = sms_new_confirm_code
391   sms_set_code(code)
392   sms_send(sms_phone, sms_confirm_message(code))
393 end
sms_set_code(code)
[show source]
    # File lib/rodauth/features/sms_codes.rb
411 def sms_set_code(code)
412  update_sms(sms_code_column=>code, sms_issued_at_column=>Sequel::CURRENT_TIMESTAMP)
413 end
sms_setup(phone_number)
[show source]
    # File lib/rodauth/features/sms_codes.rb
366 def sms_setup(phone_number)
367   # Cannot handle uniqueness violation here, as the phone number given may not match the
368   # one in the table.
369   sms_ds.insert(sms_id_column=>session_value, sms_phone_column=>phone_number, sms_failures_column => nil)
370   remove_instance_variable(:@sms) if instance_variable_defined?(:@sms)
371 end
sms_setup?()
[show source]
    # File lib/rodauth/features/sms_codes.rb
443 def sms_setup?
444   return false unless sms
445   !sms_needs_confirmation?
446 end
sms_valid_phone?(phone)
[show source]
    # File lib/rodauth/features/sms_codes.rb
395 def sms_valid_phone?(phone)
396   phone.length >= sms_phone_min_length
397 end
split_token(token)
[show source]
    # File lib/rodauth/features/base.rb
636 def split_token(token)
637   token.split(token_separator, 2)
638 end
template_path(page)
[show source]
    # File lib/rodauth/features/base.rb
849 def template_path(page)
850   File.join(File.dirname(__FILE__), '../../../templates', "#{page}.str")
851 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
728 def throw_error(field, error)
729   set_field_error(field, error)
730   throw_rodauth_error
731 end
throw_error_reason(reason, status, field, message)
[show source]
    # File lib/rodauth/features/base.rb
741 def throw_error_reason(reason, status, field, message)
742   set_error_reason(reason)
743   throw_error_status(status, field, message)
744 end
throw_error_status(status, field, error)
[show source]
    # File lib/rodauth/features/base.rb
733 def throw_error_status(status, field, error)
734   set_response_error_status(status)
735   throw_error(field, error)
736 end
throw_rodauth_error()
[show source]
    # File lib/rodauth/features/base.rb
724 def throw_rodauth_error
725   throw :rodauth_error
726 end
timing_safe_eql?(provided, actual)
[show source]
    # File lib/rodauth/features/base.rb
695 def timing_safe_eql?(provided, actual)
696   provided = provided.to_s
697   Rack::Utils.secure_compare(provided.ljust(actual.length), actual) && provided.length == actual.length
698 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
678 def transaction(opts={}, &block)
679   db.transaction(opts, &block)
680 end
translate(_key, default)
[show source]
    # File lib/rodauth/features/base.rb
245 def translate(_key, default)
246   # do not attempt to translate by default
247   default
248 end
two_factor_authenticate(type)
[show source]
    # File lib/rodauth/features/two_factor_base.rb
241 def two_factor_authenticate(type)
242   two_factor_update_session(type)
243   two_factor_remove_auth_failures
244   after_two_factor_authentication
245   require_response(:_two_factor_auth_response)
246 end
two_factor_authenticated?()
[show source]
    # File lib/rodauth/features/two_factor_base.rb
184 def two_factor_authenticated?
185   authenticated_by && authenticated_by.length >= 2
186 end
two_factor_authentication_setup?()
[show source]
    # File lib/rodauth/features/two_factor_base.rb
188 def two_factor_authentication_setup?
189   possible_authentication_methods.length >= 2
190 end
two_factor_login_type_match?(type)
[show source]
    # File lib/rodauth/features/two_factor_base.rb
198 def two_factor_login_type_match?(type)
199   authenticated_by && authenticated_by.include?(type)
200 end
two_factor_modifications_require_password?()
[show source]
    # File lib/rodauth/features/two_factor_base.rb
122 def two_factor_modifications_require_password?
123   modifications_require_password?
124 end
two_factor_partially_authenticated?()
[show source]
    # File lib/rodauth/features/two_factor_base.rb
180 def two_factor_partially_authenticated?
181   logged_in? && !two_factor_authenticated? && uses_two_factor_authentication?
182 end
two_factor_password_match?(password)
[show source]
    # File lib/rodauth/features/two_factor_base.rb
172 def two_factor_password_match?(password)
173   if two_factor_modifications_require_password?
174     password_match?(password)
175   else
176     true
177   end
178 end
two_factor_remove()
[show source]
    # File lib/rodauth/features/otp.rb
224 def two_factor_remove
225   super
226   otp_remove
227 end
two_factor_remove_auth_failures()
[show source]
    # File lib/rodauth/features/otp.rb
229 def two_factor_remove_auth_failures
230   super
231   otp_remove_auth_failures
232 end
two_factor_remove_session(type)
[show source]
    # File lib/rodauth/features/two_factor_base.rb
254 def two_factor_remove_session(type)
255   authenticated_by.delete(type)
256   remove_session_value(two_factor_setup_session_key)
257   if authenticated_by.empty?
258     clear_session
259   end
260 end
two_factor_update_session(auth_type)
[show source]
    # File lib/rodauth/features/two_factor_base.rb
262 def two_factor_update_session(auth_type)
263   authenticated_by << auth_type
264   set_session_value(two_factor_setup_session_key, true)
265 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
902 def unique_constraint_violation_class
903   if db.adapter_scheme == :jdbc && db.database_type == :sqlite
904     # :nocov:
905     Sequel::ConstraintViolation
906     # :nocov:
907   else
908     Sequel::UniqueConstraintViolation
909   end
910 end
unlock_account()
[show source]
    # File lib/rodauth/features/lockout.rb
160 def unlock_account
161   transaction do
162     remove_lockout_metadata
163   end
164 end
unlock_account_email_recently_sent?()
[show source]
    # File lib/rodauth/features/lockout.rb
241 def unlock_account_email_recently_sent?
242   (email_last_sent = get_unlock_account_email_last_sent) && (Time.now - email_last_sent < unlock_account_skip_resend_email_within)
243 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
965 def update_account(values, ds=account_ds)
966   update_hash_ds(account, ds, values)
967 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
200 def update_current_session?
201   !!session_inactivity_deadline
202 end
update_hash_ds(hash, ds, values)
[show source]
    # File lib/rodauth/features/base.rb
955 def update_hash_ds(hash, ds, values)
956   num = ds.update(values)
957   if num == 1
958     values.each do |k, v|
959       hash[k] = Sequel::CURRENT_TIMESTAMP == v ? Time.now : v
960     end
961   end
962   num
963 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
18 def update_password_hash?
19   password_hash_cost != @current_password_hash_cost || @update_password_hash
20 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
66 def update_single_session_key
67   key = random_key
68   set_single_session_key(key)
69   if single_session_ds.update(single_session_key_column=>key) == 0
70     # Don't handle uniqueness violations here.  While we could get the stored key from the
71     # database, it could lead to two sessions sharing the same key, which this feature is
72     # designed to prevent.
73     single_session_ds.insert(single_session_id_column=>session_value, single_session_key_column=>key)
74   end
75 end
update_sms(values)
[show source]
    # File lib/rodauth/features/sms_codes.rb
520 def update_sms(values)
521   update_hash_ds(sms, sms_ds, values)
522 end
use_database_authentication_functions?()
[show source]
    # File lib/rodauth/features/base.rb
754 def use_database_authentication_functions?
755   case db.database_type
756   when :postgres, :mysql, :mssql
757     true
758   else
759     # :nocov:
760     false
761     # :nocov:
762   end
763 end
use_date_arithmetic?()
[show source]
    # File lib/rodauth/features/active_sessions.rb
209 def use_date_arithmetic?
210   true
211 end
use_json?()
[show source]
   # File lib/rodauth/features/json.rb
60 def use_json?
61   json_request? || only_json?
62 end
use_jwt?()
[show source]
   # File lib/rodauth/features/jwt.rb
90 def use_jwt?
91   use_json?
92 end
use_multi_phase_login?()
[show source]
    # File lib/rodauth/features/email_auth.rb
156 def use_multi_phase_login?
157   true
158 end
use_request_specific_csrf_tokens?()
[show source]
    # File lib/rodauth/features/base.rb
765 def use_request_specific_csrf_tokens?
766   scope.opts[:rodauth_route_csrf] && scope.use_request_specific_csrf_tokens?
767 end
use_scope_clear_session?()
[show source]
    # File lib/rodauth/features/base.rb
938 def use_scope_clear_session?
939   scope.respond_to?(:clear_session)
940 end
uses_two_factor_authentication?()
[show source]
    # File lib/rodauth/features/two_factor_base.rb
192 def uses_two_factor_authentication?
193   return false unless logged_in?
194   set_session_value(two_factor_setup_session_key, two_factor_authentication_setup?) unless session.has_key?(two_factor_setup_session_key)
195   session[two_factor_setup_session_key]
196 end
valid_jwt?()
[show source]
    # File lib/rodauth/features/jwt.rb
 98 def valid_jwt?
 99   !!(jwt_token && jwt_payload)
100 end
valid_login_entered?()
[show source]
    # File lib/rodauth/features/login.rb
126 def valid_login_entered?
127   @valid_login_entered
128 end
valid_new_webauthn_credential?(webauthn_credential)
[show source]
    # File lib/rodauth/features/webauthn.rb
314 def valid_new_webauthn_credential?(webauthn_credential)
315   _override_webauthn_credential_response_verify(webauthn_credential)
316   (challenge = param_or_nil(webauthn_setup_challenge_param)) &&
317     (hmac = param_or_nil(webauthn_setup_challenge_hmac_param)) &&
318     (timing_safe_eql?(compute_hmac(challenge), hmac) || (hmac_secret_rotation? && timing_safe_eql?(compute_old_hmac(challenge), hmac))) &&
319     webauthn_credential.verify(challenge)
320 end
valid_webauthn_credential_auth?(webauthn_credential)
[show source]
    # File lib/rodauth/features/webauthn.rb
362 def valid_webauthn_credential_auth?(webauthn_credential)
363   ds = webauthn_keys_ds.where(webauthn_keys_webauthn_id_column => webauthn_credential.id)
364   pub_key, sign_count = ds.get([webauthn_keys_public_key_column, webauthn_keys_sign_count_column])
365 
366   _override_webauthn_credential_response_verify(webauthn_credential)
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) || (hmac_secret_rotation? && timing_safe_eql?(compute_old_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
171 def verify_account
172   update_account(account_status_column=>account_open_status_value) == 1
173 end
verify_account_check_already_logged_in()
[show source]
    # File lib/rodauth/features/verify_account.rb
278 def verify_account_check_already_logged_in
279   check_already_logged_in
280 end
verify_account_ds(id=account_id)
[show source]
    # File lib/rodauth/features/verify_account.rb
303 def verify_account_ds(id=account_id)
304   db[verify_account_table].where(verify_account_id_column=>id)
305 end
verify_account_email_recently_sent?()
[show source]
    # File lib/rodauth/features/verify_account.rb
243 def verify_account_email_recently_sent?
244   account && (email_last_sent = get_verify_account_email_last_sent) && (Time.now - email_last_sent < verify_account_skip_resend_email_within)
245 end
verify_account_email_resend()
[show source]
    # File lib/rodauth/features/verify_account.rb
175 def verify_account_email_resend
176   if @verify_account_key_value = get_verify_account_key(account_id)
177     set_verify_account_email_last_sent
178     send_verify_account_email
179     true
180   end
181 end
verify_account_key_insert_hash()
[show source]
    # File lib/rodauth/features/verify_account.rb
299 def verify_account_key_insert_hash
300   {verify_account_id_column=>account_id, verify_account_key_column=>verify_account_key_value}
301 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
112 def verify_login_change
113   unless res = _update_login(verify_login_change_new_login)
114     remove_verify_login_change_key
115   end
116 
117   res
118 end
verify_login_change_ds(id=account_id)
[show source]
    # File lib/rodauth/features/verify_login_change.rb
206 def verify_login_change_ds(id=account_id)
207   db[verify_login_change_table].where(verify_login_change_id_column=>id)
208 end
verify_login_change_email_body()
[show source]
    # File lib/rodauth/features/verify_login_change.rb
202 def verify_login_change_email_body
203   render('verify-login-change-email')
204 end
verify_login_change_key_insert_hash(login)
[show source]
    # File lib/rodauth/features/verify_login_change.rb
192 def verify_login_change_key_insert_hash(login)
193   hash = {verify_login_change_id_column=>account_id, verify_login_change_key_column=>verify_login_change_key_value, verify_login_change_login_column=>login}
194   set_deadline_value(hash, verify_login_change_deadline_column, verify_login_change_deadline_interval)
195   hash
196 end
verify_login_change_old_login()
[show source]
    # File lib/rodauth/features/verify_login_change.rb
140 def verify_login_change_old_login
141   account_ds.get(login_column)
142 end
view(page, title)
[show source]
    # File lib/rodauth/features/base.rb
428 def view(page, title)
429   set_title(title)
430   _view(:view, page)
431 end
webauthn_account_id()
[show source]
    # File lib/rodauth/features/webauthn.rb
503 def webauthn_account_id
504   session_value
505 end
webauthn_allow()
[show source]
    # File lib/rodauth/features/webauthn.rb
340 def webauthn_allow
341   account_webauthn_ids
342 end
webauthn_auth_additional_form_tags()
[show source]
   # File lib/rodauth/features/webauthn_login.rb
43 def webauthn_auth_additional_form_tags
44   if @webauthn_login
45     super.to_s + login_hidden_field
46   else
47     super
48   end
49 end
webauthn_auth_credential_from_form_submission()
[show source]
    # File lib/rodauth/features/webauthn.rb
515 def webauthn_auth_credential_from_form_submission
516   begin
517     webauthn_credential = webauthn_form_submission_call(:from_get, webauthn_auth_data)
518 
519     unless valid_webauthn_credential_auth?(webauthn_credential)
520       throw_error_reason(:invalid_webauthn_auth_param, invalid_key_error_status, webauthn_auth_param, webauthn_invalid_auth_param_message)
521     end
522   rescue WebAuthn::SignCountVerificationError
523     handle_webauthn_sign_count_verification_error
524   rescue WebAuthn::Error, RuntimeError, NoMethodError
525     throw_error_reason(:invalid_webauthn_auth_param, invalid_field_error_status, webauthn_auth_param, webauthn_invalid_auth_param_message) 
526   end
527 
528   webauthn_credential
529 end
webauthn_auth_data()
[show source]
    # File lib/rodauth/features/webauthn.rb
531 def webauthn_auth_data
532   case auth_data = raw_param(webauthn_auth_param)
533   when String
534     begin
535       JSON.parse(auth_data)
536     rescue
537       throw_error_reason(:invalid_webauthn_auth_param, invalid_field_error_status, webauthn_auth_param, webauthn_invalid_auth_param_message) 
538     end
539   when Hash
540     auth_data
541   else
542     throw_error_reason(:invalid_webauthn_auth_param, invalid_field_error_status, webauthn_auth_param, webauthn_invalid_auth_param_message)
543   end
544 end
webauthn_auth_form_path()
[show source]
    # File lib/rodauth/features/webauthn.rb
247 def webauthn_auth_form_path
248   webauthn_auth_path
249 end
webauthn_authenticator_selection()
[show source]
    # File lib/rodauth/features/webauthn.rb
263 def webauthn_authenticator_selection
264   {'requireResidentKey' => false, 'userVerification' => webauthn_user_verification}
265 end
webauthn_create_relying_party_opts()
[show source]
    # File lib/rodauth/features/webauthn.rb
434 def webauthn_create_relying_party_opts
435   { :relying_party => webauthn_relying_party }
436 end
webauthn_credential_options_for_get()
[show source]
    # File lib/rodauth/features/webauthn.rb
322 def webauthn_credential_options_for_get
323   WebAuthn::Credential.options_for_get(
324     :allow => webauthn_allow,
325     :timeout => webauthn_auth_timeout,
326     :user_verification => webauthn_user_verification,
327     :extensions => webauthn_extensions,
328     **webauthn_get_relying_party_opts
329   )
330 end
webauthn_extensions()
[show source]
    # File lib/rodauth/features/webauthn.rb
267 def webauthn_extensions
268   {}
269 end
webauthn_form_submission_call(meth, arg)
[show source]
    # File lib/rodauth/features/webauthn.rb
439 def webauthn_form_submission_call(meth, arg)
440   WebAuthn::Credential.public_send(meth, arg, :relying_party => webauthn_relying_party)
441 end
webauthn_key_insert_hash(webauthn_credential)
[show source]
    # File lib/rodauth/features/webauthn.rb
494 def webauthn_key_insert_hash(webauthn_credential)
495   {
496     webauthn_keys_account_id_column => webauthn_account_id,
497     webauthn_keys_webauthn_id_column => webauthn_credential.id,
498     webauthn_keys_public_key_column => webauthn_credential.public_key,
499     webauthn_keys_sign_count_column => Integer(webauthn_credential.sign_count)
500   }
501 end
webauthn_keys_ds()
[show source]
    # File lib/rodauth/features/webauthn.rb
511 def webauthn_keys_ds
512   db[webauthn_keys_table].where(webauthn_keys_account_id_column => webauthn_account_id)
513 end
webauthn_login_options?()
[show source]
   # File lib/rodauth/features/webauthn_autofill.rb
60 def webauthn_login_options?
61   return true unless param_or_nil(login_param)
62   super
63 end
webauthn_login_verification_factor?(webauthn_credential)
[show source]
   # File lib/rodauth/features/webauthn_login.rb
70 def webauthn_login_verification_factor?(webauthn_credential)
71   webauthn_login_user_verification_additional_factor? &&
72     webauthn_credential.response.authenticator_data.user_verified? &&
73     uses_two_factor_authentication?
74 end
webauthn_origin()
[show source]
    # File lib/rodauth/features/webauthn.rb
336 def webauthn_origin
337   base_url
338 end
webauthn_relying_party()
[show source]
    # File lib/rodauth/features/webauthn.rb
414 def webauthn_relying_party
415   # No need to memoize, only called once per request
416   WebAuthn::RelyingParty.new(
417     allowed_origins: [webauthn_origin],
418     id: webauthn_rp_id,
419     name: webauthn_rp_name,
420   )
421 end
webauthn_remove_authenticated_session()
[show source]
    # File lib/rodauth/features/webauthn.rb
255 def webauthn_remove_authenticated_session
256   remove_session_value(authenticated_webauthn_id_session_key)
257 end
webauthn_rp_id()
[show source]
    # File lib/rodauth/features/webauthn.rb
344 def webauthn_rp_id
345   webauthn_origin.sub(/\Ahttps?:\/\//, '').sub(/:\d+\z/, '')
346 end
webauthn_rp_name()
[show source]
    # File lib/rodauth/features/webauthn.rb
348 def webauthn_rp_name
349   webauthn_rp_id
350 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
546 def webauthn_setup_credential_from_form_submission
547   unless two_factor_password_match?(param(password_param))
548     throw_error_reason(:invalid_password, invalid_password_error_status, password_param, invalid_password_message)
549   end
550 
551   begin
552     webauthn_credential = webauthn_form_submission_call(:from_create, webauthn_setup_data)
553 
554     unless valid_new_webauthn_credential?(webauthn_credential)
555       throw_error_reason(:invalid_webauthn_setup_param, invalid_field_error_status, webauthn_setup_param, webauthn_invalid_setup_param_message) 
556     end
557   rescue WebAuthn::Error, RuntimeError, NoMethodError
558     throw_error_reason(:invalid_webauthn_setup_param, invalid_field_error_status, webauthn_setup_param, webauthn_invalid_setup_param_message) 
559   end
560 
561   webauthn_credential
562 end
webauthn_setup_data()
[show source]
    # File lib/rodauth/features/webauthn.rb
564 def webauthn_setup_data
565   case setup_data = raw_param(webauthn_setup_param)
566   when String
567     begin
568       JSON.parse(setup_data)
569     rescue
570       throw_error_reason(:invalid_webauthn_setup_param, invalid_field_error_status, webauthn_setup_param, webauthn_invalid_setup_param_message) 
571     end
572   when Hash
573     setup_data
574   else
575     throw_error_reason(:invalid_webauthn_setup_param, invalid_field_error_status, webauthn_setup_param, webauthn_invalid_setup_param_message)
576   end
577 end
webauthn_update_session(webauthn_id)
[show source]
    # File lib/rodauth/features/webauthn.rb
259 def webauthn_update_session(webauthn_id)
260   set_session_value(authenticated_webauthn_id_session_key, webauthn_id)
261 end
webauthn_user_ids_ds()
[show source]
    # File lib/rodauth/features/webauthn.rb
507 def webauthn_user_ids_ds
508   db[webauthn_user_ids_table].where(webauthn_user_ids_account_id_column => webauthn_account_id)
509 end
webauthn_user_name()
[show source]
    # File lib/rodauth/features/webauthn.rb
332 def webauthn_user_name
333   account![login_column]
334 end
webauthn_user_verification()
[show source]
   # File lib/rodauth/features/webauthn_autofill.rb
25 def webauthn_user_verification
26   'preferred'
27 end