quo_vadis 1.4.0 → 2.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (191) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +11 -7
  3. data/CHANGELOG.md +22 -0
  4. data/Gemfile +11 -1
  5. data/LICENSE.txt +21 -0
  6. data/README.md +453 -127
  7. data/Rakefile +15 -9
  8. data/app/controllers/quo_vadis/confirmations_controller.rb +102 -0
  9. data/app/controllers/quo_vadis/logs_controller.rb +20 -0
  10. data/app/controllers/quo_vadis/password_resets_controller.rb +65 -0
  11. data/app/controllers/quo_vadis/passwords_controller.rb +26 -0
  12. data/app/controllers/quo_vadis/recovery_codes_controller.rb +54 -0
  13. data/app/controllers/quo_vadis/sessions_controller.rb +50 -132
  14. data/app/controllers/quo_vadis/totps_controller.rb +72 -0
  15. data/app/controllers/quo_vadis/twofas_controller.rb +26 -0
  16. data/app/mailers/quo_vadis/mailer.rb +73 -0
  17. data/app/models/quo_vadis/account.rb +59 -0
  18. data/app/models/quo_vadis/account_confirmation_token.rb +17 -0
  19. data/app/models/quo_vadis/log.rb +57 -0
  20. data/app/models/quo_vadis/password.rb +52 -0
  21. data/app/models/quo_vadis/password_reset_token.rb +17 -0
  22. data/app/models/quo_vadis/recovery_code.rb +26 -0
  23. data/app/models/quo_vadis/session.rb +55 -0
  24. data/app/models/quo_vadis/token.rb +42 -0
  25. data/app/models/quo_vadis/totp.rb +56 -0
  26. data/bin/console +15 -0
  27. data/bin/rails +21 -0
  28. data/bin/setup +8 -0
  29. data/config/locales/quo_vadis.en.yml +50 -23
  30. data/config/routes.rb +46 -12
  31. data/db/migrate/202102150904_setup.rb +48 -0
  32. data/lib/generators/quo_vadis/install_generator.rb +4 -23
  33. data/lib/quo_vadis.rb +103 -97
  34. data/lib/quo_vadis/controller.rb +228 -0
  35. data/lib/quo_vadis/crypt.rb +43 -0
  36. data/lib/quo_vadis/current_request_details.rb +11 -0
  37. data/lib/quo_vadis/defaults.rb +18 -0
  38. data/lib/quo_vadis/encrypted_type.rb +17 -0
  39. data/lib/quo_vadis/engine.rb +9 -11
  40. data/lib/quo_vadis/hmacable.rb +26 -0
  41. data/lib/quo_vadis/ip_masking.rb +31 -0
  42. data/lib/quo_vadis/model.rb +86 -0
  43. data/lib/quo_vadis/version.rb +3 -1
  44. data/quo_vadis.gemspec +20 -25
  45. data/test/dummy/README.markdown +1 -0
  46. data/test/dummy/Rakefile +2 -6
  47. data/test/dummy/app/controllers/application_controller.rb +0 -1
  48. data/test/dummy/app/controllers/articles_controller.rb +8 -11
  49. data/test/dummy/app/controllers/sign_ups_controller.rb +42 -0
  50. data/test/dummy/app/controllers/users_controller.rb +13 -5
  51. data/test/dummy/app/models/application_record.rb +3 -0
  52. data/test/dummy/app/models/article.rb +2 -1
  53. data/test/dummy/app/models/person.rb +5 -2
  54. data/test/dummy/app/models/user.rb +4 -1
  55. data/test/dummy/app/views/articles/also_secret.html.erb +1 -0
  56. data/test/dummy/app/views/articles/index.html.erb +1 -1
  57. data/test/dummy/app/views/articles/secret.html.erb +1 -0
  58. data/test/dummy/app/views/articles/very_secret.html.erb +2 -0
  59. data/test/dummy/app/views/layouts/application.html.erb +41 -25
  60. data/test/dummy/app/views/quo_vadis/confirmations/edit.html.erb +10 -0
  61. data/test/dummy/app/views/quo_vadis/confirmations/edit_email.html.erb +14 -0
  62. data/test/dummy/app/views/quo_vadis/confirmations/index.html.erb +14 -0
  63. data/test/dummy/app/views/quo_vadis/confirmations/new.html.erb +16 -0
  64. data/test/dummy/app/views/quo_vadis/logs/index.html.erb +28 -0
  65. data/test/dummy/app/views/quo_vadis/mailer/account_confirmation.text.erb +4 -0
  66. data/test/dummy/app/views/quo_vadis/mailer/email_change_notification.text.erb +8 -0
  67. data/test/dummy/app/views/quo_vadis/mailer/identifier_change_notification.text.erb +8 -0
  68. data/test/dummy/app/views/quo_vadis/mailer/password_change_notification.text.erb +8 -0
  69. data/test/dummy/app/views/quo_vadis/mailer/password_reset_notification.text.erb +8 -0
  70. data/test/dummy/app/views/quo_vadis/mailer/recovery_codes_generation_notification.text.erb +8 -0
  71. data/test/dummy/app/views/quo_vadis/mailer/reset_password.text.erb +4 -0
  72. data/test/dummy/app/views/quo_vadis/mailer/totp_reuse_notification.text.erb +6 -0
  73. data/test/dummy/app/views/quo_vadis/mailer/totp_setup_notification.text.erb +8 -0
  74. data/test/dummy/app/views/quo_vadis/mailer/twofa_deactivated_notification.text.erb +8 -0
  75. data/test/dummy/app/views/quo_vadis/password_resets/edit.html.erb +25 -0
  76. data/test/dummy/app/views/quo_vadis/password_resets/index.html.erb +5 -0
  77. data/test/dummy/app/views/quo_vadis/password_resets/new.html.erb +12 -0
  78. data/test/dummy/app/views/quo_vadis/passwords/edit.html.erb +30 -0
  79. data/test/dummy/app/views/quo_vadis/recovery_codes/challenge.html.erb +11 -0
  80. data/test/dummy/app/views/quo_vadis/recovery_codes/index.html.erb +25 -0
  81. data/test/dummy/app/views/quo_vadis/sessions/index.html.erb +26 -0
  82. data/test/dummy/app/views/quo_vadis/sessions/new.html.erb +24 -0
  83. data/test/dummy/app/views/quo_vadis/totps/challenge.html.erb +11 -0
  84. data/test/dummy/app/views/quo_vadis/totps/new.html.erb +17 -0
  85. data/test/dummy/app/views/quo_vadis/twofas/show.html.erb +20 -0
  86. data/test/dummy/app/views/sign_ups/new.html.erb +37 -0
  87. data/test/dummy/app/views/sign_ups/show.html.erb +5 -0
  88. data/test/dummy/app/views/users/new.html.erb +32 -9
  89. data/test/dummy/config.ru +6 -3
  90. data/test/dummy/config/application.rb +18 -9
  91. data/test/dummy/config/boot.rb +3 -9
  92. data/test/dummy/config/database.yml +2 -14
  93. data/test/dummy/config/environment.rb +2 -3
  94. data/test/dummy/config/initializers/quo_vadis.rb +5 -75
  95. data/test/dummy/config/routes.rb +11 -3
  96. data/test/dummy/db/migrate/202102121932_create_users.rb +10 -0
  97. data/test/dummy/db/migrate/202102121935_create_people.rb +10 -0
  98. data/test/dummy/db/schema.rb +80 -21
  99. data/test/fixtures/quo_vadis/mailer/account_confirmation.text +4 -0
  100. data/test/fixtures/quo_vadis/mailer/email_change_notification.text +8 -0
  101. data/test/fixtures/quo_vadis/mailer/identifier_change_notification.text +8 -0
  102. data/test/fixtures/quo_vadis/mailer/password_change_notification.text +8 -0
  103. data/test/fixtures/quo_vadis/mailer/password_reset_notification.text +8 -0
  104. data/test/fixtures/quo_vadis/mailer/recovery_codes_generation_notification.text +8 -0
  105. data/test/fixtures/quo_vadis/mailer/reset_password.text +4 -0
  106. data/test/fixtures/quo_vadis/mailer/totp_reuse_notification.text +6 -0
  107. data/test/fixtures/quo_vadis/mailer/totp_setup_notification.text +8 -0
  108. data/test/fixtures/quo_vadis/mailer/twofa_deactivated_notification.text +8 -0
  109. data/test/integration/account_confirmation_test.rb +145 -0
  110. data/test/integration/controller_test.rb +280 -0
  111. data/test/integration/logging_test.rb +235 -0
  112. data/test/integration/password_change_test.rb +93 -0
  113. data/test/integration/password_login_test.rb +125 -0
  114. data/test/integration/password_reset_test.rb +136 -0
  115. data/test/integration/recovery_codes_test.rb +48 -0
  116. data/test/integration/sessions_test.rb +86 -0
  117. data/test/integration/sign_up_test.rb +26 -12
  118. data/test/integration/totps_test.rb +96 -0
  119. data/test/integration/twofa_test.rb +82 -0
  120. data/test/mailers/mailer_test.rb +200 -0
  121. data/test/models/account_test.rb +34 -0
  122. data/test/models/crypt_test.rb +22 -0
  123. data/test/models/log_test.rb +16 -0
  124. data/test/models/mask_ip_test.rb +27 -0
  125. data/test/models/model_test.rb +66 -0
  126. data/test/models/password_test.rb +163 -0
  127. data/test/models/recovery_code_test.rb +54 -0
  128. data/test/models/session_test.rb +67 -0
  129. data/test/models/token_test.rb +70 -0
  130. data/test/models/totp_test.rb +68 -0
  131. data/test/quo_vadis_test.rb +39 -3
  132. data/test/test_helper.rb +42 -70
  133. metadata +123 -207
  134. data/app/controllers/controller_mixin.rb +0 -109
  135. data/app/mailers/quo_vadis/notifier.rb +0 -30
  136. data/app/models/model_mixin.rb +0 -128
  137. data/lib/generators/quo_vadis/templates/migration.rb.erb +0 -18
  138. data/lib/generators/quo_vadis/templates/quo_vadis.rb.erb +0 -96
  139. data/test/dummy/.gitignore +0 -2
  140. data/test/dummy/app/helpers/application_helper.rb +0 -2
  141. data/test/dummy/app/helpers/articles_helper.rb +0 -2
  142. data/test/dummy/app/views/articles/new.html.erb +0 -11
  143. data/test/dummy/app/views/layouts/sessions.html.erb +0 -3
  144. data/test/dummy/app/views/quo_vadis/notifier/change_password.text.erb +0 -9
  145. data/test/dummy/app/views/quo_vadis/notifier/invite.text.erb +0 -8
  146. data/test/dummy/app/views/sessions/edit.html.erb +0 -11
  147. data/test/dummy/app/views/sessions/forgotten.html.erb +0 -13
  148. data/test/dummy/app/views/sessions/invite.html.erb +0 -31
  149. data/test/dummy/app/views/sessions/new.html.erb +0 -15
  150. data/test/dummy/config/environments/development.rb +0 -26
  151. data/test/dummy/config/environments/production.rb +0 -49
  152. data/test/dummy/config/environments/test.rb +0 -37
  153. data/test/dummy/config/initializers/backtrace_silencers.rb +0 -7
  154. data/test/dummy/config/initializers/inflections.rb +0 -10
  155. data/test/dummy/config/initializers/mime_types.rb +0 -5
  156. data/test/dummy/config/initializers/rack_patch.rb +0 -16
  157. data/test/dummy/config/initializers/secret_token.rb +0 -7
  158. data/test/dummy/config/initializers/session_store.rb +0 -8
  159. data/test/dummy/config/locales/en.yml +0 -5
  160. data/test/dummy/config/locales/quo_vadis.en.yml +0 -21
  161. data/test/dummy/db/migrate/20110124125037_create_users.rb +0 -13
  162. data/test/dummy/db/migrate/20110124131535_create_articles.rb +0 -14
  163. data/test/dummy/db/migrate/20110127094709_add_authentication_to_users.rb +0 -18
  164. data/test/dummy/db/migrate/20111004112209_create_people.rb +0 -13
  165. data/test/dummy/db/migrate/20111004132342_add_authentication_to_people.rb +0 -18
  166. data/test/dummy/public/404.html +0 -26
  167. data/test/dummy/public/422.html +0 -26
  168. data/test/dummy/public/500.html +0 -26
  169. data/test/dummy/public/javascripts/application.js +0 -2
  170. data/test/dummy/public/javascripts/controls.js +0 -965
  171. data/test/dummy/public/javascripts/dragdrop.js +0 -974
  172. data/test/dummy/public/javascripts/effects.js +0 -1123
  173. data/test/dummy/public/javascripts/prototype.js +0 -6001
  174. data/test/dummy/public/javascripts/rails.js +0 -175
  175. data/test/dummy/public/stylesheets/.gitkeep +0 -0
  176. data/test/dummy/script/rails +0 -6
  177. data/test/integration/activation_test.rb +0 -108
  178. data/test/integration/authenticate_test.rb +0 -39
  179. data/test/integration/blocked_test.rb +0 -23
  180. data/test/integration/config_test.rb +0 -118
  181. data/test/integration/cookie_test.rb +0 -67
  182. data/test/integration/csrf_test.rb +0 -41
  183. data/test/integration/forgotten_test.rb +0 -93
  184. data/test/integration/helper_test.rb +0 -18
  185. data/test/integration/locale_test.rb +0 -197
  186. data/test/integration/navigation_test.rb +0 -7
  187. data/test/integration/sign_in_person_test.rb +0 -26
  188. data/test/integration/sign_in_test.rb +0 -24
  189. data/test/integration/sign_out_test.rb +0 -20
  190. data/test/support/integration_case.rb +0 -11
  191. data/test/unit/user_test.rb +0 -75
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 9cd2f1cd76d5a11353c01d7644a56b587f4e958c
4
- data.tar.gz: 34586a9d0e1ee196d3a81382e1e5c8cbb4e4052e
2
+ SHA256:
3
+ metadata.gz: aca902d10c618abd2c9c0461aac204236b4ef7565911aafb5bb12dfe1e3b25e1
4
+ data.tar.gz: 3417365d9ca59d5e17a1b28118d3c9ec439b77fb228da9968512786dd3797a12
5
5
  SHA512:
6
- metadata.gz: 24da8db1b59b03a14586e650f88aa0f43f39cf7b7d58f5aa403689a36f9b86a82bfd0bf736364f797c586a94965f40427c371da5d942731bad6e4530d89cb5bc
7
- data.tar.gz: 2b40461150448705b4eaff767c30ab195d322364bc507314a7a73323a98e7e3b64a10116ae317e251b38a5c414c2e04da20337b23ced428c0f9d7c8854fded1f
6
+ metadata.gz: 5ffdeced9bd86b0a64fe21f3491f3ad03cb2098f0687b663ab794c37e278383ad235df856d8a18bf8e73108d602661990992dd033cbc1358849b8824ac25aff6
7
+ data.tar.gz: 59c52478f7a5bc8ee0befe682ee520feec894c6fefe875cc84395e827ae62f9cbf5eb588862cf8eb3888b5b0ba102700b61f5d401156dc9eff893e05307d1787
data/.gitignore CHANGED
@@ -1,8 +1,12 @@
1
- pkg/*
2
- *.gem
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+ /test/dummy/log/
10
+ /test/dummy/tmp/
11
+ /test/dummy/db/*.sqlite3
3
12
  Gemfile.lock
4
- .bundle
5
- test/dummy/log/*
6
- test/dummy/tmp/*
7
- rdoc/*
8
- NOTES
data/CHANGELOG.md CHANGED
@@ -1,6 +1,28 @@
1
1
  # CHANGELOG
2
2
 
3
3
 
4
+ ## HEAD
5
+
6
+
7
+ ## 2.0.2 (24 May 2021)
8
+
9
+ * Account confirmation: enable updating of email address.
10
+ * Account confirmation: enable direct resending of email.
11
+ * Log unknown identifier in metadata.
12
+
13
+
14
+ ## 2.0.1 (18 May 2021)
15
+
16
+ * Remove Gemfile.lock from repo.
17
+ * Move runtime dependencies into gemspec.
18
+ * Include test files in gem package (so views can be installed).
19
+
20
+
21
+ ## 2.0.0 (14 May 2021)
22
+
23
+ * Total rewrite from scratch.
24
+
25
+
4
26
  ## 1.4.0 (12 October 2016)
5
27
 
6
28
  * Internationalise emails' subject lines.
data/Gemfile CHANGED
@@ -1,3 +1,13 @@
1
- source "http://rubygems.org"
1
+ # frozen_string_literal: true
2
2
 
3
+ source "https://rubygems.org"
4
+
5
+ # Specify your gem's dependencies in quo_vadis.gemspec
3
6
  gemspec
7
+
8
+ gem "rake", "~> 13.0"
9
+
10
+ gem 'sqlite3'
11
+ gem 'capybara'
12
+
13
+ # gem "minitest", "~> 5.0"
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2021 Andy Stewart
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md CHANGED
@@ -1,211 +1,537 @@
1
- # Quo Vadis?
1
+ # Quo Vadis
2
2
 
3
- Quo Vadis adds simple username/password authentication to Rails 3 applications.
3
+ Multifactor authentication for your Rails 6 app.
4
4
 
5
- Why bother with yet another authentication gem? Well, I find all the others over-engineered. Code should be easy to use and easy to read. As far as I'm concerned, none of the others ticks both boxes.
5
+ Designed in accordance with the [OWASP Application Security Verification Standard](https://owasp.org/www-project-application-security-verification-standard/) and relevant [OWASP Cheatsheets](https://cheatsheetseries.owasp.org).
6
6
 
7
- Features:
7
+ Simple to integrate into your application. The main task is customising the example views' markup to match your look-and-feel.
8
8
 
9
- * Minimal effort to add authentication to your app: get up and running in 5 minutes.
10
- * No surprises: it does what you expect.
11
- * Easy to customise.
12
- * Uses BCrypt to encrypt passwords.
13
- * Sign in, sign out, forgotten password, authenticate actions, remember user between browser sessions, user activation.
14
- * Block accounts.
15
- * Let you choose which model(s) to authenticate (defaults to `User`).
16
9
 
17
- Forthcoming features:
10
+ ## Features
18
11
 
19
- * Generate the views for you (for now, copy the examples given below).
20
- * Let you choose the identification field (currently `username`).
21
- * HTTP basic/digest authentication (probably).
22
- * Generate model plus migration if it doesn't exist.
23
- * Detect presence of `has_secure_password` (see below) and adapt appropriately.
12
+ ### General features
24
13
 
25
- What it doesn't and won't do:
14
+ - Works with any model, e.g. `User` or `Person`.
15
+ - Works with any identifier, e.g. `:username` or `:email`.
16
+ - Minimal footprint in your models and controllers.
17
+ - Does not touch your existing database tables.
18
+ - Secrets (password, TOTP secret, 2FA recovery codes) are encrypted at rest.
26
19
 
27
- * Authorisation.
28
- * Work outside Rails 3.
29
- * OpenID, OAuth, LDAP, CAS, etc.
30
- * Separate identity from authentication services (cf OmniAuth).
31
- * Allow you to have multiple models/scope signed in simultaneously (cf Devise).
32
- * Offer so much flexibility that it takes more than 10 minutes to wrap your head around it (cf Devise, Authlogic).
20
+ ### Authentication features
33
21
 
22
+ - Authentication by password.
23
+ - Two-factor authentication (2FA) by TOTP with recovery codes as a backup factor. Can be optional or mandatory.
24
+ - Change password.
25
+ - Reset password.
26
+ - Account confirmation (optional).
27
+ - Tokens (account confirmation, password reset), TOTPs, and recovery codes are all one-time-only.
28
+ - Sessions expired after lifetime or idle time exceeded.
29
+ - Session replaced after any privilege change.
30
+ - View active sessions, log out of any of them.
31
+ - Email-notifications of updates to authentication details.
32
+ - Audit trail.
34
33
 
35
- ## Quick Start
36
34
 
37
- If this takes you more than 5 minutes, you can have your money back ;)
35
+ ## Installation
38
36
 
39
- Install and run the generator: add `gem 'quo_vadis'` to your Gemfile, run `bundle install`, then `rails generate quo_vadis:install [MODEL_NAME]` (where model name is optional and defaults to `User`).
37
+ Add the gem to your Gemfile:
40
38
 
41
- Edit and run the generated migration to add the authentication columns: `rake db:migrate`. Note the migration (currently) assumes you already have a table for your model.
39
+ ```ruby
40
+ gem 'quo_vadis', '~> 2.0'
41
+ ```
42
42
 
43
- In your `User` (or whichever) model, add `authenticates`:
43
+ Then run `bundle install`.
44
44
 
45
- class User < ActiveRecord::Base
46
- authenticates
47
- end
45
+ Next, add the database tables:
48
46
 
49
- Note Quo Vadis validates the presence and uniqueness of the username, and the presence of the password, but it's up to you to add any other validations you want.
47
+ ```
48
+ rails quo_vadis:install:migrations && rails db:migrate
49
+ ```
50
50
 
51
- Use `:authenticate` in a `before_filter` to protect your controllers' actions. For example:
51
+ All the database tables are prefixed with `qv_`.
52
52
 
53
- class ArticlesController < ActionController::Base
54
- before_filter :authenticate, :except => [:index, :show]
55
- end
53
+ Finally, copy the example views across:
56
54
 
57
- Write the sign-in view. Your sign-in form must:
55
+ ```
56
+ rails generate quo_vadis:install
57
+ ```
58
58
 
59
- * be in `app/views/sessions/new.html.:format`
60
- * POST the parameters `:username` and `:password` to `sign_in_url`
61
59
 
62
- You have to write the view yourself because you'd inevitably want to change whatever markup I generated for you. You can find an example in the [test app](https://github.com/airblade/quo_vadis/blob/master/test/dummy/app/views/sessions/new.html.erb).
60
+ ## Usage
63
61
 
64
- Remember to serve your sign in form over HTTPS -- to avoid [the credentials being stolen](http://blog.jgc.org/2011/01/code-injected-to-steal-passwords-in.html).
65
62
 
66
- In your layout, use `current_user` to retrieve the signed-in user; and `sign_in_path`, `sign_out_path`, and `forgotten_sign_in_path` as appropriate. You can also use `authenticated?`.
63
+ ### Model
67
64
 
65
+ Your model must have an `:email` attribute. All authentication-related emails will be sent to this address.
68
66
 
69
- ## Forgotten Password
67
+ Your model must have an identifier, e.g. `:email` (default) or `:username`, with a uniqueness validation.
70
68
 
71
- Here's the workflow:
69
+ All you need do is add a call to `authenticates`, somewhere after your identifier's uniqueness validation.
72
70
 
73
- 1. [Sign in page] The user clicks the "I've forgotten my password" link.
74
- 2. [Forgotten password page] The user enters their username in the form and submits it.
75
- 3. Quo Vadis emails the user a message with a change-password link. The link is valid for 3 hours.
76
- 4. [The email] The user clicks the link.
77
- 5. [Change password page] The user types in a new password and saves it.
78
- 6. Quo Vadis changes the user's password and signs the user in.
71
+ For example, let's say you have a `User` model and the identifier is `:email`:
79
72
 
80
- It'll take you about 5 minutes to implement this.
73
+ ```ruby
74
+ class User < ApplicationRecord
75
+ validates :email, uniqueness: {case_sensitive: false}
76
+ authenticates
77
+ end
78
+ ```
81
79
 
82
- On your sign-in page, link to the forgotten-password view at `forgotten_sign_in_url`.
80
+ If instead you had a `Person` model with a `:username` identifier:
83
81
 
84
- Write the forgotten-password view ([example](https://github.com/airblade/quo_vadis/blob/master/test/dummy/app/views/sessions/forgotten.html.erb)). The form must:
82
+ ```ruby
83
+ class Person < ApplicationRecord
84
+ validates :username, uniqueness: {case_sensitive: false}
85
+ authenticates identifier: :username
86
+ end
87
+ ```
85
88
 
86
- * be in `app/views/sessions/forgotten.html.:format`
87
- * POST the parameter `:username` to `forgotten_sign_in_url`
89
+ When __creating__ a model instance, include a `:password` attribute and, optionally, `:password_confirmation` attribute.
88
90
 
89
- Now write the mailer view, i.e. the email which will be sent to your forgetful users ([example](https://github.com/airblade/quo_vadis/blob/master/test/dummy/app/views/quo_vadis/notifier/change_password.text.erb)). The view must:
91
+ When __updating__ a model instance, do not include a `:password` attribute. To change someone's password, use the Change Password feature (see below).
90
92
 
91
- * be at `app/views/quo_vadis/notifier/change_password.text.erb`
92
- * render `@url` somewhere (this is the link the user clicks to go to the change-password page)
93
+ The minimum password length is configured by `QuoVadis.password_minimum_length` (12 by default).
93
94
 
94
- You can also refer to `@username` in the email view.
95
95
 
96
- Configure the email's from address in `config/initializers/quo_vadis.rb`.
96
+ ### Controllers
97
97
 
98
- Configure the default host so ActionMailer can generate the URL. In `config/environments/<env>.rb`:
98
+ You can use these methods in your controllers.
99
99
 
100
- config.action_mailer.default_url_options = {:host => 'yourdomain.com'}
100
+ __`require_password_authentication`__
101
101
 
102
- Finally, write the change-password page ([example](https://github.com/airblade/quo_vadis/blob/master/test/dummy/app/views/sessions/edit.html.erb)). The form must:
102
+ Use this to restrict actions to password-authenticated users. It is aliased to `:require_authentication` for convenience.
103
103
 
104
- * be in `app/views/sessions/edit.html.:format`
105
- * PUT the parameter `:password` to `change_password_url(params[:token])`
104
+ ```ruby
105
+ class FoosController < ApplicationController
106
+ before_action :require_password_authentication
107
+ end
108
+ ```
106
109
 
110
+ __`require_two_factor_authentication`__
107
111
 
108
- ## Sign up (directly, without activation)
112
+ Use this to restrict actions to users authenticated with both a password and a second factor. (You do not need to use `:require_password_authentication` for these actions.)
109
113
 
110
- When you create a user, you need to sign them in. Do this by calling `sign_in(user)` in your controller. For example:
114
+ ```ruby
115
+ class BarsController < ApplicationController
116
+ before_action :require_two_factor_authentication
117
+ end
118
+ ```
111
119
 
112
- # In your app
113
- class UsersController < ApplicationController
114
- def create
115
- @user = User.new params[:user]
116
- if @user.save
117
- sign_in @user # <-- NOTE: sign in your user here
118
- else
119
- render 'new'
120
- end
121
- end
122
- end
120
+ __`login(model, browser_session = true)`__
121
+
122
+ To log in a user who has authenticated with a password, call `#login(model, browser_session = true)`. For the `browser_session` argument, pass `true` to log in for the duration of the browser session, or `false` to log in for `QuoVadis.session_lifetime` (which could be the browser session anyway).
123
+
124
+ __`request_confirmation(model)`__
125
+
126
+ This is used to sent an account confirmation email to the user. See the Account Confirmation feature below for details.
127
+
128
+ __`authenticated_model`__
129
+
130
+ Call this to get the authenticated user. Feel free to alias this to `:current_user` or set it into an `ActiveSupport::CurrentAttributes` class.
131
+
132
+ Available in controllers and views.
133
+
134
+ __`logged_in?`__
135
+
136
+ Call this to find out whether a user has authenticated with a password.
137
+
138
+ Available in controllers and views.
139
+
140
+
141
+ ### Views
142
+
143
+ You can use `authenticated_model` and `logged_in?` in your views. For example:
123
144
 
124
- The `sign_in(user)` method will redirect the user appropriately (you can configure this in `config/initializers/quo_vadis.rb`), as well as running any sign-in hook you may have defined in the initializer.
145
+ ```erb
146
+ <% if logged_in? %>
147
+ <%= link_to 'My profile', authenticated_model %>
148
+ <% end %>
149
+ ```
125
150
 
151
+ In your own views, you must prefix QuoVadis's routes with `quo_vadis.`. For example:
126
152
 
127
- ## Sign up (with activation)
153
+ ```ruby
154
+ link_to 'Log in', quo_vadis.login_path
155
+ ```
128
156
 
129
- To create a user who must activate their account (via email) before they can sign in, do this:
157
+ When you are customising QuoVadis's views, you must prefix your app's routes with `main_app.`. For example:
130
158
 
131
- # In your app
132
- class UsersController < ApplicationController
133
- def create
134
- @user = User.new_for_activation params[:user] # <-- NOTE: different constructor
135
- if @user.save
136
- QuoVadis::SessionsController.new.invite_to_activate @user # <-- NOTE: email user here
137
- redirect_to root_path, notice: "Emailed sign-in instructions to #{@user.name}" # or whatever
138
- else
139
- render 'new'
140
- end
141
- end
159
+ ```ruby
160
+ link_to 'Home', main_app.root_path
161
+ ```
162
+
163
+
164
+ ## Features
165
+
166
+ The example views show the forms and fields you need. You should only need to adapt the markup to suit your app's appearance.
167
+
168
+ In the snippets below we assume a `User` model whose identifier is `:email`. You can of course use anything you like.
169
+
170
+
171
+ ### Sign up
172
+
173
+ Your new user sign-up form ([example](https://github.com/airblade/quo_vadis/blob/master/test/dummy/app/views/users/new.html.erb)) must include:
174
+
175
+ - a `:password` field;
176
+ - optionally a `:password_confirmation` field;
177
+ - a field for their identifier;
178
+ - an `:email` field if the identifier is not their email.
179
+
180
+ In your controller, use the `#login` method to log in your new user. The optional second argument sets the length of the session (defaults to the browser session) - see the description above in the Controllers section).
181
+
182
+ After logging in the user, redirect them to `qv.path_after_authentication` which resolves to a route named `:after_login`, if you have one, or your root route.
183
+
184
+ ```ruby
185
+ class UsersController < ApplicationController
186
+ def create
187
+ @user = User.new user_params
188
+ if @user.save
189
+ login @user
190
+ redirect_to qv.path_after_authentication
191
+ else
192
+ # ...
142
193
  end
194
+ end
195
+
196
+ private
143
197
 
144
- The user will receive an email with a link which takes them to a page (which you must write) where they can choose a username and password for themselves. When they submit the form their new credentials are stored and they are signed in.
198
+ def user_params
199
+ params.require(:user).permit(:name, :email, :password, :password_confirmation)
200
+ end
201
+ end
202
+ ```
203
+
204
+ ```ruby
205
+ # config/routes.rb
206
+ get '/dashboard', as: 'after_login'
207
+ ```
208
+
209
+
210
+ ### Sign up with account confirmation
145
211
 
146
212
  Here's the workflow:
147
213
 
148
- 1. [New user page, without username/password fields] You or user fills in and submits form.
149
- 2. [Users controller] Create user and invite to activate. See code snippet above.
150
- 3. Quo Vadis emails the user a message with an invitation link. The link is valid for 3 hours.
151
- 4. [The email] The user clicks the link.
152
- 5. [Invitation page] The user fills in their new username and password.
153
- 6. Quo Vadis sets the user's username and password and signs the user in.
214
+ 1. [Sign up page] The user fills in their details.
215
+ 2. [Your controller] Your code tells QuoVadis to email the user a confirmation link. The link is valid for `QuoVadis.account_confirmation_token_lifetime`.
216
+ 3. [The email] The user clicks the link.
217
+ 4. [Account-confirmation confirmation page] The user clicks a button to confirm their account. (This step is to prevent any link prefetching in the user's mail client from confirming them unintentionally.)
218
+ 5. QuoVadis confirms the user's account and logs them in.
219
+
220
+ Your new user sign-up form ([example](https://github.com/airblade/quo_vadis/blob/master/test/dummy/app/views/sign_ups/new.html.erb)) must include:
221
+
222
+ - a `:password` field;
223
+ - optionally a `:password_confirmation` field;
224
+ - a field for their identifier;
225
+ - an `:email` field if the identifier is not their email.
226
+
227
+ In your controller, call `#request_confirmation`:
228
+
229
+ ```ruby
230
+ class UsersController < ApplicationController
231
+ def create
232
+ @user = User.new user_params
233
+ if @user.save
234
+ request_confirmation @user
235
+ redirect_to quo_vadis.confirmations_path # a page where you advise the user to check their email
236
+ else
237
+ # ...
238
+ end
239
+ end
240
+
241
+ private
242
+
243
+ def user_params
244
+ params.require(:user).permit(:name, :email, :password, :password_confirmation)
245
+ end
246
+ end
247
+ ```
248
+
249
+ QuoVadis will send the user an email with a link. Write the email view ([example](https://github.com/airblade/quo_vadis/blob/master/test/dummy/app/views/quo_vadis/mailer/account_confirmation.text.erb)). It must be in `app/views/quo_vadis/mailer/account_confirmation.{text,html}.erb` and output the `@url` variable.
250
+
251
+ See the Configuration section below for how to set QuoVadis's emails' from addresses, headers, etc.
252
+
253
+ Now write the page to where the user is redirected while they wait for the email ([example](https://github.com/airblade/quo_vadis/blob/master/test/dummy/app/views/quo_vadis/confirmations/index.html.erb)). It must be in `app/views/quo_vadis/confirmations/index.html.:format`.
254
+
255
+ On that page you can show the user the address the email was sent to, enable them to update their email address if they make a mistake on the sign-up form, and provide a button to resend another email directly. If the sign-up occurred in a different browser session, you can instead link to `new_confirmation_path` where the user can request another email if need be.
256
+
257
+ Next, write the page to which the link in the email points ([example](https://github.com/airblade/quo_vadis/blob/master/test/dummy/app/views/quo_vadis/confirmations/edit.html.erb)). It must be in `app/views/quo_vadis/confirmations/edit.html.:format`.
258
+
259
+ Finally, write the page where people can put in their identifier (not their email, unless the identifier is email) again to request another confirmation email ([example](https://github.com/airblade/quo_vadis/blob/master/test/dummy/app/views/quo_vadis/confirmations/new.html.erb)). It must be in `app/views/quo_vadis/confirmations/new.html.:format`.
260
+
261
+ After the user has confirmed their account, they will be logged in and redirected to the first of these that exists:
262
+
263
+ - a route named `:after_login`;
264
+ - your root route.
265
+
266
+ So add whichever works best for you.
267
+
268
+
269
+ ### Login
270
+
271
+ Use `before_action :require_password_authentication` or `before_action :require_authentication` in your controllers.
272
+
273
+ Write the login view ([example](https://github.com/airblade/quo_vadis/blob/master/test/dummy/app/views/quo_vadis/sessions/new.html.erb)). Your login form must be in `app/views/quo_vadis/sessions/new.html.:format`. Note it must capture the user's identifier (not email, unless the identifier is email).
274
+
275
+ If you include a `remember` checkbox in your login form:
276
+
277
+ - if the user checks it, they will be logged in for `QuoVadis.session_lifetime`;
278
+ - if the user does not check it, they will be logged in for the browser session.
279
+
280
+ If you do not include a `remember` checkbox, the user will be logged in for `QuoVadis.session_lifetime`.
281
+
282
+ After authenticating the user will be redirected to the first of these that exists:
283
+
284
+ - the page they tried to view before they were redirected to the login page;
285
+ - a route named `after_login`, if any;
286
+ - your root route.
287
+
288
+
289
+ ### Two-factor authentication (2FA) or Two-step verification (2SV)
290
+
291
+ If you do not want 2FA at all, set `QuoVadis.two_factor_authentication_mandatory false` in your configuration and skip the rest of this section.
292
+
293
+ If you do want 2FA, you can choose whether it is optional or mandatory for your users by setting `QuoVadis.two_factor_authentication_mandatory <true|false>` in your configuration.
294
+
295
+ Use `before_action :require_two_factor_authentication` in your controllers (which supersedes `:require_password_authentication`). This will require the user, after authenticating with their password, to authenticate with 2FA – when 2FA is mandatory, or when it is optional and the user has set up 2FA.
296
+
297
+ Here's the workflow for a user setting up optional 2FA:
298
+
299
+ 1. User visits their 2FA overview page.
300
+ 2. [2FA overview page] User clicks a link to set up 2FA (TOTP for now).
301
+ 3. [TOTP setup page] User scans the QR code with their authenticator and enters the 6-digit one-time password.
302
+ 4. QuoVadis verifies the one-time password, generates 5 backup recovery codes, and redirects the user to the recovery codes page (or back to step 3 if the OTP is invalid).
303
+ 5. [Recovery code page] User views and hopefully saves their 5 recovery codes.
304
+
305
+ When 2FA is mandatory the workflow starts automatically at step 3 after password authentication.
306
+
307
+ In your views, have a link where users can manage their 2FA:
308
+
309
+ ```ruby
310
+ link_to '2FA', quo_vadis.twofa_path
311
+ ```
312
+
313
+ Write the 2FA overview page ([example](https://github.com/airblade/quo_vadis/blob/master/test/dummy/app/views/quo_vadis/twofas/show.html.erb)). It must be in `app/views/quo_vadis/twofas/show.html.:format`. This page allows the user to set up 2FA, deactivate or reset it, and generate new recovery codes.
314
+
315
+ Next, write the TOTP setup page ([example](https://github.com/airblade/quo_vadis/blob/master/test/dummy/app/views/quo_vadis/totps/new.html.erb)). It must be in `app/views/quo_vadis/totps/new.html.:format`. This page shows the user a QR code (and the key as text) which they scan with their authenticator.
154
316
 
155
- It'll take you about 3 minutes to implement this.
317
+ Next, write the recovery codes page ([example](https://github.com/airblade/quo_vadis/blob/master/test/dummy/app/views/quo_vadis/recovery_codes/index.html.erb)). It must be in `app/views/quo_vadis/recovery_codes/index.html.:format`. This shows the recovery codes immediately after TOTP is setup, and immediately after generating fresh recovery codes, but not otherwise.
156
318
 
157
- Update your user controller's `create` action as above.
319
+ Next, write the TOTP challenge page where a user inputs their 6-digit TOTP ([example](https://github.com/airblade/quo_vadis/blob/master/test/dummy/app/views/quo_vadis/totps/challenge.html.erb)). It must be in `app/views/quo_vadis/totps/challenge.html.:format`. It's a good idea to link to the recovery code page (`challenge_recovery_codes_path`) for any user who has lost their authenticator.
158
320
 
159
- Write the mailer view, i.e. the email which will be sent to your new users ([example](https://github.com/airblade/quo_vadis/blob/master/test/dummy/app/views/quo_vadis/notifier/invite.text.erb)). The view must:
321
+ Finally, write the recovery code challenge page where a user inputs one of their recovery codes ([example](https://github.com/airblade/quo_vadis/blob/master/test/dummy/app/views/quo_vadis/recovery_codes/challenge.html.erb)). It must be in `app/views/quo_vadis/recovery_codes/challenge.html.:format`. A recovery code can only be used once, and using one deactivates TOTP – so the user will have to set it up again next time.
160
322
 
161
- * be at `app/views/quo_vadis/notifier/invite.text.erb`
162
- * render `@url` somewhere (this is the link the user clicks to go to the invitation page)
163
323
 
164
- You can also refer to `@user` in the email view, as well as any other data you pass to `invite_to_activate`. Note that passing `:from` and/or `:subject` in the hash to `invite_to_activate` overrides the default `QuoVadis.from` and/or `I18n.t('quo_vadis.notifier.invite.subject')` respectively.
324
+ ### Change password
165
325
 
166
- Configure the email's from address in `config/initializers/quo_vadis.rb` (or pass in the data hash to `invite_to_activate`).
326
+ To change their password, the user must provide their current one as well as the new one.
167
327
 
168
- Configure the default host so ActionMailer can generate the URL. In `config/environments/<env>.rb`:
328
+ Write the change-password form ([example](https://github.com/airblade/quo_vadis/blob/master/test/dummy/app/views/quo_vadis/passwords/edit.html.erb)). It must be in `app/views/quo_vadis/passwords/edit.html.:format`.
169
329
 
170
- config.action_mailer.default_url_options = {:host => 'yourdomain.com'}
330
+ After the password has been changed, the user is redirected to the first of:
171
331
 
172
- Finally, write the invitation page ([example](https://github.com/airblade/quo_vadis/blob/master/test/dummy/app/views/sessions/invite.html.erb)). The form must:
332
+ - your route named `:after_password_change`, if any;
333
+ - your root route.
173
334
 
174
- * be in `app/views/sessions/invite.html.:format`
175
- * POST the parameters `:username` and `:password` to `activation_url(params[:token])`
335
+ A successful password change logs out any other sessions the user has (e.g. on other devices).
176
336
 
177
- If the token expires and you need to generate a new one, re-invite the user with: `invite_to_activate @user`.
178
337
 
338
+ ### Reset password
179
339
 
180
- ## Customisation
340
+ The user can reset their password if they lose it. The flow is:
181
341
 
182
- You can customise the flash messages and mailer from/subject in `config/locales/quo_vadis.en.yml`.
342
+ 1. [Request password-reset page] User enters their identifier (not their email unless the identifier is email).
343
+ 2. QuoVadis emails the user a link. The link is valid for `QuoVadis.password_reset_token_lifetime`.
344
+ 3. [The email] The user clicks the link.
345
+ 4. [Password-reset confirmation page] The user enters their new password and clicks a button.
346
+ 5. QuoVadis sets the user's password and logs them in.
183
347
 
184
- You can customise the sign-in and sign-out redirects in `config/initializers/quo_vadis.rb`; they both default to the root route. You can also hook into the sign-in and sign-out process if you need to run any other code.
348
+ First, write the page where the user requests a password-reset ([example](https://github.com/airblade/quo_vadis/blob/master/test/dummy/app/views/quo_vadis/password_resets/new.html.erb)). It must be in `app/views/quo_vadis/password_resets/new.html.:format`. Note it must capture the user's identifier (not email, unless the identifier is email).
185
349
 
186
- If you want to add other session management type features, go right ahead: create a `SessionsController` as normal and carry on.
350
+ See the Configuration section below for how to set QuoVadis's emails' from addresses, headers, etc.
187
351
 
188
- You can skip the validation of authentication attributes (password etc) by overriding `should_authenticate?` in your model. Perhaps only some of the users should be able to sign in, so you don't want to force them to have a password.
352
+ Now write the page to where the user is redirected while they wait for the email ([example](https://github.com/airblade/quo_vadis/blob/master/test/dummy/app/views/quo_vadis/password_resets/index.html.erb)). It must be in `app/views/quo_vadis/password_resets/index.html.:format`.
189
353
 
354
+ It's a good idea for that page to link to `new_password_reset_path` where the user can request another email if need be.
190
355
 
191
- ## See also
356
+ Next, write the page to which the link in the email points ([example](https://github.com/airblade/quo_vadis/blob/master/test/dummy/app/views/quo_vadis/password_resets/edit.html.erb)). It must be in `app/views/quo_vadis/password_resets/edit.html.:format`.
357
+
358
+ Finally, write the page where people can put in their identifier (not their email, unless the identifier is email) again to request another password-reset email ([example](https://github.com/airblade/quo_vadis/blob/master/test/dummy/app/views/quo_vadis/password_resets/new.html.erb)). It must be in `app/views/quo_vadis/password_resets/new.html.:format`.
359
+
360
+ After the user has reset their password, they will be logged in and redirected to the first of these that exists:
361
+
362
+ - a route named `:after_login`;
363
+ - your root route.
364
+
365
+
366
+ ### Sessions
367
+
368
+ A logged-in session lasts for either the browser session or `QuoVadis.session_lifetime`. As well as having a lifetime, a session will also expire after it has been inactive for `QuoVadis.session_idle_timeout`.
369
+
370
+ A user can view their active sessions and log out of any of them.
371
+
372
+ Write the view showing the sessions ([example](https://github.com/airblade/quo_vadis/blob/master/test/dummy/app/views/quo_vadis/sessions/index.html.erb)). It must be in `app/views/quo_vadis/sessions/index.html.:format`.
373
+
374
+
375
+ ### Audit trail
376
+
377
+ An audit trail is kept of authentication events. You can see the full list in the [`Log`](https://github.com/airblade/quo_vadis/blob/master/app/models/quo_vadis/log.rb) class.
378
+
379
+ Write the view showing the events ([example](https://github.com/airblade/quo_vadis/blob/master/test/dummy/app/views/quo_vadis/logs/index.html.erb)). It must be in `app/views/quo_vadis/logs/index.html.:format`.
380
+
381
+
382
+ ### Notifications
383
+
384
+ QuoVadis notifies users by email whenever their authentication details are changed or something suspicious happens.
385
+
386
+ Write the corresponding mailer views:
387
+
388
+ - change of email ([example](https://github.com/airblade/quo_vadis/blob/master/test/dummy/app/views/quo_vadis/mailer/email_change_notification.text.erb))
389
+ - change of identifier (unless the identifier is email) ([example](https://github.com/airblade/quo_vadis/blob/master/test/dummy/app/views/quo_vadis/mailer/identifier_change_notification.text.erb))
390
+ - change of password ([example](https://github.com/airblade/quo_vadis/blob/master/test/dummy/app/views/quo_vadis/mailer/password_change_notification.text.erb))
391
+ - reset of password ([example](https://github.com/airblade/quo_vadis/blob/master/test/dummy/app/views/quo_vadis/mailer/password_reset_notification.text.erb))
392
+ - TOTP setup ([example](https://github.com/airblade/quo_vadis/blob/master/test/dummy/app/views/quo_vadis/mailer/totp_setup_notification.text.erb))
393
+ - TOTP code used a second time ([example](https://github.com/airblade/quo_vadis/blob/master/test/dummy/app/views/quo_vadis/mailer/totp_reuse_notification.text.erb))
394
+ - 2FA deactivated ([example](https://github.com/airblade/quo_vadis/blob/master/test/dummy/app/views/quo_vadis/mailer/twofa_deactivated_notification.text.erb))
395
+ - recovery codes generated ([example](https://github.com/airblade/quo_vadis/blob/master/test/dummy/app/views/quo_vadis/mailer/recovery_codes_generation_notification.text.erb))
396
+
397
+ They must be in `app/views/quo_vadis/mailer/NAME.{text,html}.erb`.
398
+
399
+
400
+ ## Configuration
401
+
402
+ This is QuoVadis' [default configuration](https://github.com/airblade/quo_vadis/blob/master/lib/quo_vadis/defaults.rb):
403
+
404
+ ```ruby
405
+ QuoVadis.configure do
406
+ password_minimum_length 12
407
+ mask_ips false
408
+ cookie_name '__Host-qv'
409
+ session_lifetime :session
410
+ session_lifetime_extend_to_end_of_day false
411
+ session_idle_timeout :lifetime
412
+ password_reset_token_lifetime 10.minutes
413
+ accounts_require_confirmation false
414
+ account_confirmation_token_lifetime 10.minutes
415
+ mail_headers ({ from: 'Example App <support@example.com>' })
416
+ enqueue_transactional_emails true
417
+ app_name Rails.app_class.to_s.deconstantize # for the TOTP QR code
418
+ two_factor_authentication_mandatory true
419
+ mount_point '/'
420
+ end
421
+ ```
422
+
423
+ You can override any of it with a similarly structured file in `config/initializers/quo_vadis.rb`.
424
+
425
+ Here are the options in detail:
426
+
427
+ __`password_minimum_length`__ (integer)
428
+
429
+ The minimum number of characters for a password.
430
+
431
+ __`mask_ips`__ (boolean)
432
+
433
+ Whether to mask the IP address in the sessions list and the audit trail.
434
+
435
+ Masking means setting the last octet (IPv4) or the last 80 bits (IPv6) to 0.
436
+
437
+ __`cookie_name`__ (string)
438
+
439
+ The name of the cookie QuoVadis uses to store the session identifier. The `__Host-` prefix is [recommended](https://developer.mozilla.org/en-US/docs/Web/API/document/cookie).
440
+
441
+ __`session_lifetime`__ (`:session` | `ActiveSupport::Duration` | integer)
442
+
443
+ The lifetime of a logged-in session. Use `:session` for the browser session, or a `Duration` or number of seconds.
444
+
445
+ __`session_lifetime_extend_to_end_of_day`__ (boolean)
446
+
447
+ Whether to extend the session's lifetime to the end of the day it will expire on.
448
+
449
+ Set `true` to reduce the chance of a user being logged out while actively using your application.
450
+
451
+ __`session_idle_timeout`__ (`:lifetime` | `ActiveSupport::Duration` | integer)
452
+
453
+ The logged-in session is expired if the user isn't seen for this `Duration` or number of seconds. Use `:lifetime` to set the idle timeout to the session's lifetime (i.e. to turn off the idle timeout).
454
+
455
+ __`password_reset_token_lifetime`__ (`ActiveSupport::Duration` | integer)
456
+
457
+ The `Duration` or number of seconds for which a password-reset token is valid.
458
+
459
+ __`accounts_require_confirmation`__ (boolean)
460
+
461
+ Whether new users must confirm their account before they can log in.
462
+
463
+ __`account_confirmation_token_lifetime`__ (`ActiveSupport::Duration` | integer)
464
+
465
+ The `Duration` or number of seconds for which an account-confirmation token is valid.
466
+
467
+ __`mail_headers`__ (hash)
468
+
469
+ Mail headers which QuoVadis' emails should have.
470
+
471
+ __`enqueue_transactional_emails`__ (boolean)
472
+
473
+ Set `true` if account-confirmation and password-reset emails should be queued for later delivery (`#deliver_later`) or `false` if they should be sent inline (`#deliver_now`).
474
+
475
+ __`app_name`__ (string)
476
+
477
+ Used in the provisioning URI for the TOTP QR code.
478
+
479
+ __`two_factor_authentication_mandatory`__ (boolean)
480
+
481
+ Whether users must set up and use a second authentication factor.
482
+
483
+ __`mount_point`__ (string)
484
+
485
+ The path prefix for QuoVadis's routes.
486
+
487
+ For example, the default login path is at `/login`. If you set `mount_point` to `/auth`, the login path would be `/auth/login`.
488
+
489
+ #### Rails configuration
490
+
491
+ __Mailer URLs__
492
+
493
+ You must also configure the mailer host so URLs are generated correctly in emails:
494
+
495
+ ```ruby
496
+ config.action_mailer.default_url_options: { host: 'example.com' }
497
+ ```
498
+
499
+ __Layouts__
500
+
501
+ You can specify QuoVadis's controllers' layouts in a `#to_prepare` block in your application configuration. For example:
502
+
503
+ ```ruby
504
+ # config/application.rb
505
+ module YourApp
506
+ class Application < Rails::Application
507
+ config.to_prepare do
508
+ QuoVadis::ConfirmationsController.layout 'your_layout'
509
+ end
510
+ end
511
+ end
512
+ ```
192
513
 
193
- * Rails 3 edge's [ActiveModel::SecurePassword](https://github.com/rails/rails/blob/master/activemodel/lib/active_model/secure_password.rb). It's `has_secure_password` class method is similar to Quo Vadis's `authenticates` class method.
194
- * [RailsCast 250: Authentication from Scratch](http://railscasts.com/episodes/250-authentication-from-scratch).
514
+ __Routes__
195
515
 
516
+ You can set up your post-authentication and post-password-change routes. If you don't, you must have a root route. For example:
196
517
 
197
- ## What's up with the name?
518
+ ```ruby
519
+ # config/routes.rb
520
+ get '/dashboard', to: 'dashboards#show', as: 'after_login'
521
+ get '/profile', to: 'profiles#show', as: 'after_password_change'
522
+ ```
198
523
 
199
- Roman sentries used to challenge intruders with, "Halt! Who goes there?"; quo vadis is Latin for "Who goes there?". At least that's what my Latin teacher told us, but I was 8 years old then so I may not be remembering this entirely accurately.
524
+ ### I18n
200
525
 
526
+ All QuoVadis' flash messages are set via [i18n](https://github.com/airblade/quo_vadis/blob/master/config/locales/quo_vadis.en.yml).
201
527
 
202
- ## Questions, Problems, Feedback
528
+ You can override any of the messages with your own locale file at `config/locales/quo_vadis.en.yml`.
203
529
 
204
- Please use the GitHub [issue tracker](https://github.com/airblade/quo_vadis/issues) or email me.
530
+ If you don't want a specific flash message at all, give the key an empty value in your locale file.
205
531
 
206
532
 
207
- ## Intellectual property
533
+ ## Intellectual Property
208
534
 
209
- Copyright 2011 Andy Stewart (boss@airbladesoftware.com).
535
+ Copyright 2011-2021 Andrew Stewart (boss@airbladesoftware.com).
210
536
 
211
537
  Released under the MIT licence.