quo_vadis 1.4.0 → 2.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.gitignore +11 -7
- data/CHANGELOG.md +22 -0
- data/Gemfile +11 -1
- data/LICENSE.txt +21 -0
- data/README.md +453 -127
- data/Rakefile +15 -9
- data/app/controllers/quo_vadis/confirmations_controller.rb +102 -0
- data/app/controllers/quo_vadis/logs_controller.rb +20 -0
- data/app/controllers/quo_vadis/password_resets_controller.rb +65 -0
- data/app/controllers/quo_vadis/passwords_controller.rb +26 -0
- data/app/controllers/quo_vadis/recovery_codes_controller.rb +54 -0
- data/app/controllers/quo_vadis/sessions_controller.rb +50 -132
- data/app/controllers/quo_vadis/totps_controller.rb +72 -0
- data/app/controllers/quo_vadis/twofas_controller.rb +26 -0
- data/app/mailers/quo_vadis/mailer.rb +73 -0
- data/app/models/quo_vadis/account.rb +59 -0
- data/app/models/quo_vadis/account_confirmation_token.rb +17 -0
- data/app/models/quo_vadis/log.rb +57 -0
- data/app/models/quo_vadis/password.rb +52 -0
- data/app/models/quo_vadis/password_reset_token.rb +17 -0
- data/app/models/quo_vadis/recovery_code.rb +26 -0
- data/app/models/quo_vadis/session.rb +55 -0
- data/app/models/quo_vadis/token.rb +42 -0
- data/app/models/quo_vadis/totp.rb +56 -0
- data/bin/console +15 -0
- data/bin/rails +21 -0
- data/bin/setup +8 -0
- data/config/locales/quo_vadis.en.yml +50 -23
- data/config/routes.rb +46 -12
- data/db/migrate/202102150904_setup.rb +48 -0
- data/lib/generators/quo_vadis/install_generator.rb +4 -23
- data/lib/quo_vadis.rb +103 -97
- data/lib/quo_vadis/controller.rb +228 -0
- data/lib/quo_vadis/crypt.rb +43 -0
- data/lib/quo_vadis/current_request_details.rb +11 -0
- data/lib/quo_vadis/defaults.rb +18 -0
- data/lib/quo_vadis/encrypted_type.rb +17 -0
- data/lib/quo_vadis/engine.rb +9 -11
- data/lib/quo_vadis/hmacable.rb +26 -0
- data/lib/quo_vadis/ip_masking.rb +31 -0
- data/lib/quo_vadis/model.rb +86 -0
- data/lib/quo_vadis/version.rb +3 -1
- data/quo_vadis.gemspec +20 -25
- data/test/dummy/README.markdown +1 -0
- data/test/dummy/Rakefile +2 -6
- data/test/dummy/app/controllers/application_controller.rb +0 -1
- data/test/dummy/app/controllers/articles_controller.rb +8 -11
- data/test/dummy/app/controllers/sign_ups_controller.rb +42 -0
- data/test/dummy/app/controllers/users_controller.rb +13 -5
- data/test/dummy/app/models/application_record.rb +3 -0
- data/test/dummy/app/models/article.rb +2 -1
- data/test/dummy/app/models/person.rb +5 -2
- data/test/dummy/app/models/user.rb +4 -1
- data/test/dummy/app/views/articles/also_secret.html.erb +1 -0
- data/test/dummy/app/views/articles/index.html.erb +1 -1
- data/test/dummy/app/views/articles/secret.html.erb +1 -0
- data/test/dummy/app/views/articles/very_secret.html.erb +2 -0
- data/test/dummy/app/views/layouts/application.html.erb +41 -25
- data/test/dummy/app/views/quo_vadis/confirmations/edit.html.erb +10 -0
- data/test/dummy/app/views/quo_vadis/confirmations/edit_email.html.erb +14 -0
- data/test/dummy/app/views/quo_vadis/confirmations/index.html.erb +14 -0
- data/test/dummy/app/views/quo_vadis/confirmations/new.html.erb +16 -0
- data/test/dummy/app/views/quo_vadis/logs/index.html.erb +28 -0
- data/test/dummy/app/views/quo_vadis/mailer/account_confirmation.text.erb +4 -0
- data/test/dummy/app/views/quo_vadis/mailer/email_change_notification.text.erb +8 -0
- data/test/dummy/app/views/quo_vadis/mailer/identifier_change_notification.text.erb +8 -0
- data/test/dummy/app/views/quo_vadis/mailer/password_change_notification.text.erb +8 -0
- data/test/dummy/app/views/quo_vadis/mailer/password_reset_notification.text.erb +8 -0
- data/test/dummy/app/views/quo_vadis/mailer/recovery_codes_generation_notification.text.erb +8 -0
- data/test/dummy/app/views/quo_vadis/mailer/reset_password.text.erb +4 -0
- data/test/dummy/app/views/quo_vadis/mailer/totp_reuse_notification.text.erb +6 -0
- data/test/dummy/app/views/quo_vadis/mailer/totp_setup_notification.text.erb +8 -0
- data/test/dummy/app/views/quo_vadis/mailer/twofa_deactivated_notification.text.erb +8 -0
- data/test/dummy/app/views/quo_vadis/password_resets/edit.html.erb +25 -0
- data/test/dummy/app/views/quo_vadis/password_resets/index.html.erb +5 -0
- data/test/dummy/app/views/quo_vadis/password_resets/new.html.erb +12 -0
- data/test/dummy/app/views/quo_vadis/passwords/edit.html.erb +30 -0
- data/test/dummy/app/views/quo_vadis/recovery_codes/challenge.html.erb +11 -0
- data/test/dummy/app/views/quo_vadis/recovery_codes/index.html.erb +25 -0
- data/test/dummy/app/views/quo_vadis/sessions/index.html.erb +26 -0
- data/test/dummy/app/views/quo_vadis/sessions/new.html.erb +24 -0
- data/test/dummy/app/views/quo_vadis/totps/challenge.html.erb +11 -0
- data/test/dummy/app/views/quo_vadis/totps/new.html.erb +17 -0
- data/test/dummy/app/views/quo_vadis/twofas/show.html.erb +20 -0
- data/test/dummy/app/views/sign_ups/new.html.erb +37 -0
- data/test/dummy/app/views/sign_ups/show.html.erb +5 -0
- data/test/dummy/app/views/users/new.html.erb +32 -9
- data/test/dummy/config.ru +6 -3
- data/test/dummy/config/application.rb +18 -9
- data/test/dummy/config/boot.rb +3 -9
- data/test/dummy/config/database.yml +2 -14
- data/test/dummy/config/environment.rb +2 -3
- data/test/dummy/config/initializers/quo_vadis.rb +5 -75
- data/test/dummy/config/routes.rb +11 -3
- data/test/dummy/db/migrate/202102121932_create_users.rb +10 -0
- data/test/dummy/db/migrate/202102121935_create_people.rb +10 -0
- data/test/dummy/db/schema.rb +80 -21
- data/test/fixtures/quo_vadis/mailer/account_confirmation.text +4 -0
- data/test/fixtures/quo_vadis/mailer/email_change_notification.text +8 -0
- data/test/fixtures/quo_vadis/mailer/identifier_change_notification.text +8 -0
- data/test/fixtures/quo_vadis/mailer/password_change_notification.text +8 -0
- data/test/fixtures/quo_vadis/mailer/password_reset_notification.text +8 -0
- data/test/fixtures/quo_vadis/mailer/recovery_codes_generation_notification.text +8 -0
- data/test/fixtures/quo_vadis/mailer/reset_password.text +4 -0
- data/test/fixtures/quo_vadis/mailer/totp_reuse_notification.text +6 -0
- data/test/fixtures/quo_vadis/mailer/totp_setup_notification.text +8 -0
- data/test/fixtures/quo_vadis/mailer/twofa_deactivated_notification.text +8 -0
- data/test/integration/account_confirmation_test.rb +145 -0
- data/test/integration/controller_test.rb +280 -0
- data/test/integration/logging_test.rb +235 -0
- data/test/integration/password_change_test.rb +93 -0
- data/test/integration/password_login_test.rb +125 -0
- data/test/integration/password_reset_test.rb +136 -0
- data/test/integration/recovery_codes_test.rb +48 -0
- data/test/integration/sessions_test.rb +86 -0
- data/test/integration/sign_up_test.rb +26 -12
- data/test/integration/totps_test.rb +96 -0
- data/test/integration/twofa_test.rb +82 -0
- data/test/mailers/mailer_test.rb +200 -0
- data/test/models/account_test.rb +34 -0
- data/test/models/crypt_test.rb +22 -0
- data/test/models/log_test.rb +16 -0
- data/test/models/mask_ip_test.rb +27 -0
- data/test/models/model_test.rb +66 -0
- data/test/models/password_test.rb +163 -0
- data/test/models/recovery_code_test.rb +54 -0
- data/test/models/session_test.rb +67 -0
- data/test/models/token_test.rb +70 -0
- data/test/models/totp_test.rb +68 -0
- data/test/quo_vadis_test.rb +39 -3
- data/test/test_helper.rb +42 -70
- metadata +123 -207
- data/app/controllers/controller_mixin.rb +0 -109
- data/app/mailers/quo_vadis/notifier.rb +0 -30
- data/app/models/model_mixin.rb +0 -128
- data/lib/generators/quo_vadis/templates/migration.rb.erb +0 -18
- data/lib/generators/quo_vadis/templates/quo_vadis.rb.erb +0 -96
- data/test/dummy/.gitignore +0 -2
- data/test/dummy/app/helpers/application_helper.rb +0 -2
- data/test/dummy/app/helpers/articles_helper.rb +0 -2
- data/test/dummy/app/views/articles/new.html.erb +0 -11
- data/test/dummy/app/views/layouts/sessions.html.erb +0 -3
- data/test/dummy/app/views/quo_vadis/notifier/change_password.text.erb +0 -9
- data/test/dummy/app/views/quo_vadis/notifier/invite.text.erb +0 -8
- data/test/dummy/app/views/sessions/edit.html.erb +0 -11
- data/test/dummy/app/views/sessions/forgotten.html.erb +0 -13
- data/test/dummy/app/views/sessions/invite.html.erb +0 -31
- data/test/dummy/app/views/sessions/new.html.erb +0 -15
- data/test/dummy/config/environments/development.rb +0 -26
- data/test/dummy/config/environments/production.rb +0 -49
- data/test/dummy/config/environments/test.rb +0 -37
- data/test/dummy/config/initializers/backtrace_silencers.rb +0 -7
- data/test/dummy/config/initializers/inflections.rb +0 -10
- data/test/dummy/config/initializers/mime_types.rb +0 -5
- data/test/dummy/config/initializers/rack_patch.rb +0 -16
- data/test/dummy/config/initializers/secret_token.rb +0 -7
- data/test/dummy/config/initializers/session_store.rb +0 -8
- data/test/dummy/config/locales/en.yml +0 -5
- data/test/dummy/config/locales/quo_vadis.en.yml +0 -21
- data/test/dummy/db/migrate/20110124125037_create_users.rb +0 -13
- data/test/dummy/db/migrate/20110124131535_create_articles.rb +0 -14
- data/test/dummy/db/migrate/20110127094709_add_authentication_to_users.rb +0 -18
- data/test/dummy/db/migrate/20111004112209_create_people.rb +0 -13
- data/test/dummy/db/migrate/20111004132342_add_authentication_to_people.rb +0 -18
- data/test/dummy/public/404.html +0 -26
- data/test/dummy/public/422.html +0 -26
- data/test/dummy/public/500.html +0 -26
- data/test/dummy/public/javascripts/application.js +0 -2
- data/test/dummy/public/javascripts/controls.js +0 -965
- data/test/dummy/public/javascripts/dragdrop.js +0 -974
- data/test/dummy/public/javascripts/effects.js +0 -1123
- data/test/dummy/public/javascripts/prototype.js +0 -6001
- data/test/dummy/public/javascripts/rails.js +0 -175
- data/test/dummy/public/stylesheets/.gitkeep +0 -0
- data/test/dummy/script/rails +0 -6
- data/test/integration/activation_test.rb +0 -108
- data/test/integration/authenticate_test.rb +0 -39
- data/test/integration/blocked_test.rb +0 -23
- data/test/integration/config_test.rb +0 -118
- data/test/integration/cookie_test.rb +0 -67
- data/test/integration/csrf_test.rb +0 -41
- data/test/integration/forgotten_test.rb +0 -93
- data/test/integration/helper_test.rb +0 -18
- data/test/integration/locale_test.rb +0 -197
- data/test/integration/navigation_test.rb +0 -7
- data/test/integration/sign_in_person_test.rb +0 -26
- data/test/integration/sign_in_test.rb +0 -24
- data/test/integration/sign_out_test.rb +0 -20
- data/test/support/integration_case.rb +0 -11
- data/test/unit/user_test.rb +0 -75
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: aca902d10c618abd2c9c0461aac204236b4ef7565911aafb5bb12dfe1e3b25e1
|
4
|
+
data.tar.gz: 3417365d9ca59d5e17a1b28118d3c9ec439b77fb228da9968512786dd3797a12
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5ffdeced9bd86b0a64fe21f3491f3ad03cb2098f0687b663ab794c37e278383ad235df856d8a18bf8e73108d602661990992dd033cbc1358849b8824ac25aff6
|
7
|
+
data.tar.gz: 59c52478f7a5bc8ee0befe682ee520feec894c6fefe875cc84395e827ae62f9cbf5eb588862cf8eb3888b5b0ba102700b61f5d401156dc9eff893e05307d1787
|
data/.gitignore
CHANGED
@@ -1,8 +1,12 @@
|
|
1
|
-
|
2
|
-
|
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
|
-
|
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
|
-
|
3
|
+
Multifactor authentication for your Rails 6 app.
|
4
4
|
|
5
|
-
|
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
|
-
|
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
|
-
|
10
|
+
## Features
|
18
11
|
|
19
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
35
|
+
## Installation
|
38
36
|
|
39
|
-
|
37
|
+
Add the gem to your Gemfile:
|
40
38
|
|
41
|
-
|
39
|
+
```ruby
|
40
|
+
gem 'quo_vadis', '~> 2.0'
|
41
|
+
```
|
42
42
|
|
43
|
-
|
43
|
+
Then run `bundle install`.
|
44
44
|
|
45
|
-
|
46
|
-
authenticates
|
47
|
-
end
|
45
|
+
Next, add the database tables:
|
48
46
|
|
49
|
-
|
47
|
+
```
|
48
|
+
rails quo_vadis:install:migrations && rails db:migrate
|
49
|
+
```
|
50
50
|
|
51
|
-
|
51
|
+
All the database tables are prefixed with `qv_`.
|
52
52
|
|
53
|
-
|
54
|
-
before_filter :authenticate, :except => [:index, :show]
|
55
|
-
end
|
53
|
+
Finally, copy the example views across:
|
56
54
|
|
57
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
67
|
+
Your model must have an identifier, e.g. `:email` (default) or `:username`, with a uniqueness validation.
|
70
68
|
|
71
|
-
|
69
|
+
All you need do is add a call to `authenticates`, somewhere after your identifier's uniqueness validation.
|
72
70
|
|
73
|
-
|
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
|
-
|
73
|
+
```ruby
|
74
|
+
class User < ApplicationRecord
|
75
|
+
validates :email, uniqueness: {case_sensitive: false}
|
76
|
+
authenticates
|
77
|
+
end
|
78
|
+
```
|
81
79
|
|
82
|
-
|
80
|
+
If instead you had a `Person` model with a `:username` identifier:
|
83
81
|
|
84
|
-
|
82
|
+
```ruby
|
83
|
+
class Person < ApplicationRecord
|
84
|
+
validates :username, uniqueness: {case_sensitive: false}
|
85
|
+
authenticates identifier: :username
|
86
|
+
end
|
87
|
+
```
|
85
88
|
|
86
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
96
|
+
### Controllers
|
97
97
|
|
98
|
-
|
98
|
+
You can use these methods in your controllers.
|
99
99
|
|
100
|
-
|
100
|
+
__`require_password_authentication`__
|
101
101
|
|
102
|
-
|
102
|
+
Use this to restrict actions to password-authenticated users. It is aliased to `:require_authentication` for convenience.
|
103
103
|
|
104
|
-
|
105
|
-
|
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
|
-
|
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
|
-
|
114
|
+
```ruby
|
115
|
+
class BarsController < ApplicationController
|
116
|
+
before_action :require_two_factor_authentication
|
117
|
+
end
|
118
|
+
```
|
111
119
|
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
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
|
-
|
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
|
-
|
153
|
+
```ruby
|
154
|
+
link_to 'Log in', quo_vadis.login_path
|
155
|
+
```
|
128
156
|
|
129
|
-
|
157
|
+
When you are customising QuoVadis's views, you must prefix your app's routes with `main_app.`. For example:
|
130
158
|
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
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
|
-
|
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. [
|
149
|
-
2. [
|
150
|
-
3.
|
151
|
-
4. [
|
152
|
-
5.
|
153
|
-
|
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
|
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
|
-
|
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
|
-
|
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
|
-
|
324
|
+
### Change password
|
165
325
|
|
166
|
-
|
326
|
+
To change their password, the user must provide their current one as well as the new one.
|
167
327
|
|
168
|
-
|
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
|
-
|
330
|
+
After the password has been changed, the user is redirected to the first of:
|
171
331
|
|
172
|
-
|
332
|
+
- your route named `:after_password_change`, if any;
|
333
|
+
- your root route.
|
173
334
|
|
174
|
-
|
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
|
-
|
340
|
+
The user can reset their password if they lose it. The flow is:
|
181
341
|
|
182
|
-
|
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
|
-
|
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
|
-
|
350
|
+
See the Configuration section below for how to set QuoVadis's emails' from addresses, headers, etc.
|
187
351
|
|
188
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
528
|
+
You can override any of the messages with your own locale file at `config/locales/quo_vadis.en.yml`.
|
203
529
|
|
204
|
-
|
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
|
533
|
+
## Intellectual Property
|
208
534
|
|
209
|
-
Copyright 2011
|
535
|
+
Copyright 2011-2021 Andrew Stewart (boss@airbladesoftware.com).
|
210
536
|
|
211
537
|
Released under the MIT licence.
|