rails_authentication 0.3.0 → 0.5.0
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.
- checksums.yaml +4 -4
- data/README.md +83 -14
- data/lib/generators/authentication/authentication_generator.rb +31 -0
- data/lib/generators/authentication/features/confirmable.rb +13 -12
- data/lib/generators/authentication/features/invitable.rb +14 -13
- data/lib/generators/authentication/features/lockable.rb +13 -12
- data/lib/generators/authentication/features/magic_link.rb +13 -12
- data/lib/generators/authentication/features/ott.rb +31 -0
- data/lib/generators/authentication/features/passkey.rb +36 -0
- data/lib/generators/authentication/features/recoverable.rb +13 -12
- data/lib/generators/authentication/features/registerable.rb +7 -6
- data/lib/generators/authentication/features/rememberable.rb +6 -5
- data/lib/generators/authentication/features/timeoutable.rb +7 -6
- data/lib/generators/authentication/features/trackable.rb +7 -6
- data/lib/generators/authentication/features/validatable.rb +5 -4
- data/lib/generators/authentication/templates/app/controllers/otts_controller.rb.tt +95 -0
- data/lib/generators/authentication/templates/app/controllers/passkey_sessions_controller.rb.tt +68 -0
- data/lib/generators/authentication/templates/app/controllers/sessions_controller.rb.tt +4 -0
- data/lib/generators/authentication/templates/app/controllers/webauthn_credentials_controller.rb.tt +43 -0
- data/lib/generators/authentication/templates/app/mailers/otts_mailer.rb.tt +6 -0
- data/lib/generators/authentication/templates/app/models/concerns/confirmable_concern.rb.tt +18 -17
- data/lib/generators/authentication/templates/app/models/concerns/ott_concern.rb.tt +50 -0
- data/lib/generators/authentication/templates/app/models/concerns/passkey_concern.rb.tt +19 -0
- data/lib/generators/authentication/templates/app/models/webauthn_credential.rb.tt +6 -0
- data/lib/generators/authentication/templates/app/views/otts/edit.html.erb.tt +79 -0
- data/lib/generators/authentication/templates/app/views/otts_mailer/ott.html.erb.tt +8 -0
- data/lib/generators/authentication/templates/app/views/otts_mailer/ott.text.erb.tt +6 -0
- data/lib/generators/authentication/templates/app/views/registrations/edit.html.erb.tt +4 -0
- data/lib/generators/authentication/templates/app/views/sessions/new.html.erb.tt +81 -0
- data/lib/generators/authentication/templates/app/views/webauthn_credentials/index.html.erb.tt +19 -0
- data/lib/generators/authentication/templates/app/views/webauthn_credentials/new.html.erb.tt +71 -0
- data/lib/generators/authentication/templates/config/initializers/webauthn.rb.tt +11 -0
- data/lib/generators/authentication/templates/db/migrate/add_ott_to_users.rb.tt +7 -0
- data/lib/generators/authentication/templates/db/migrate/add_webauthn_id_to_users.rb.tt +7 -0
- data/lib/generators/authentication/templates/db/migrate/create_webauthn_credentials.rb.tt +15 -0
- data/lib/rails_authentication/version.rb +1 -1
- metadata +19 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 6369064c5074eb057abc1ed169b7efbe7ae0758730dc6c764b86fee19f96b0d3
|
|
4
|
+
data.tar.gz: 5bdc5cb01eb60fed2449f0a1544d29102c79f917faf345f86a1a86bca6b6adc6
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: da49badfb4b8c58c2525329479154961cb10cbd6b6d683a4dbc56171198e9ad1d1f31d097455f106d47d19332a14391ee0e4370394aa23535e85b47be6ebf0f8
|
|
7
|
+
data.tar.gz: 4407fbc0f0c7daafc4324fb1e0ba7c366c4c810fa81b579bf464fd2f2e31b7d5e3da6c6e8741b189e0399a28660b4e0a728d80b1bfec63282eee3f8c0d204756
|
data/README.md
CHANGED
|
@@ -18,6 +18,8 @@ gem extends that same command to also install:
|
|
|
18
18
|
| **Lockable** | Locks the account after 5 failed attempts; unlock via email or automatically after 1 hour |
|
|
19
19
|
| **Invitable** | Invite users by email; blocks sign-in until they accept by choosing their own password |
|
|
20
20
|
| **MagicLink** (opt-in) | Passwordless magic link sign-in via email — DB-backed, single-use, expiring tokens |
|
|
21
|
+
| **Ott** (opt-in) | Passwordless sign-in via an emailed 6-digit one-time code — replaces the password sign-in form |
|
|
22
|
+
| **Passkey** (opt-in) | WebAuthn passkey sign-in alongside the password form — usernameless, no email required |
|
|
21
23
|
|
|
22
24
|
Everything is **generated into your app** as plain, readable code — controllers, views, mailers,
|
|
23
25
|
migrations, and one model concern per feature. There is no runtime dependency on this gem: after
|
|
@@ -28,7 +30,7 @@ This gem is meant to be installed temporarily. Install it long enough to run the
|
|
|
28
30
|
## Installation
|
|
29
31
|
|
|
30
32
|
Requires Rails >= 8.0 and, for the email-driven features (Confirmable, Recoverable, Lockable,
|
|
31
|
-
Invitable, MagicLink), Action Mailer.
|
|
33
|
+
Invitable, MagicLink, Ott), Action Mailer.
|
|
32
34
|
|
|
33
35
|
```ruby
|
|
34
36
|
# Gemfile
|
|
@@ -56,24 +58,46 @@ Available flags: `--skip-confirmable`, `--skip-recoverable`, `--skip-registerabl
|
|
|
56
58
|
`--skip-lockable`, `--skip-invitable`, and `--reconfirmable` (Confirmable: postpone email address
|
|
57
59
|
changes until the new address is confirmed, via an `unconfirmed_email` column).
|
|
58
60
|
|
|
59
|
-
MagicLink
|
|
61
|
+
MagicLink, Ott, and Passkey are **opt-in** features — they change the sign-in UX, so you have to
|
|
62
|
+
ask for them:
|
|
60
63
|
|
|
61
64
|
```sh
|
|
62
65
|
bin/rails generate authentication --magic-link
|
|
66
|
+
bin/rails generate authentication --ott
|
|
67
|
+
bin/rails generate authentication --passkey
|
|
63
68
|
```
|
|
64
69
|
|
|
65
|
-
|
|
66
|
-
emailed link signs the user in directly; tokens are DB-backed, single-use, and expire
|
|
67
|
-
20 minutes (`MagicLinkConcern::MAGIC_LINK_EXPIRES_IN`).
|
|
68
|
-
|
|
69
|
-
|
|
70
|
+
MagicLink adds a "Sign in with magic link" link to the sign-in page, leading to an email-only
|
|
71
|
+
form. The emailed link signs the user in directly; tokens are DB-backed, single-use, and expire
|
|
72
|
+
after 20 minutes (`MagicLinkConcern::MAGIC_LINK_EXPIRES_IN`).
|
|
73
|
+
|
|
74
|
+
Ott replaces the sign-in form: the user enters only their email address, receives a 6-digit code
|
|
75
|
+
(`OttConcern::OTT_CODE_LENGTH`) by email, and enters it on a second screen — one single-digit
|
|
76
|
+
input per digit with auto-advance and paste/autofill support (plain inline JavaScript, no
|
|
77
|
+
framework required). A "Sign in with password
|
|
78
|
+
instead" link (`/session/new?with_password=1`) toggles back to the classic password form at
|
|
79
|
+
runtime. Codes are DB-backed, single-use, expire after 10 minutes (`OttConcern::OTT_EXPIRES_IN`),
|
|
80
|
+
and are voided after 5 wrong entries (`OttConcern::OTT_MAX_ATTEMPTS`). The password machinery
|
|
81
|
+
(SessionsController#create, Recoverable, Registerable) stays generated and functional — only the
|
|
82
|
+
sign-in UI changes.
|
|
83
|
+
|
|
84
|
+
Passkey adds a "Sign in with a passkey" button to the sign-in page (no email field — the
|
|
85
|
+
browser's own discoverable-credential picker takes its place) plus an authenticated
|
|
86
|
+
`/webauthn_credentials` section where a signed-in user can register and remove passkeys (linked
|
|
87
|
+
from the account page when Registerable is enabled). Unlike every other feature here, this one
|
|
88
|
+
brings a real runtime dependency: the generator adds `gem "webauthn"` to your Gemfile for you (with
|
|
89
|
+
a reminder to run `bundle install`), since ceremony verification is delegated to it. A user can
|
|
90
|
+
register any number of passkeys, each stored as its own row in `webauthn_credentials`.
|
|
91
|
+
|
|
92
|
+
All three flows honor the other enabled features: locked, unconfirmed, or invitation-pending
|
|
93
|
+
accounts still can't sign in, and Trackable records the attempt.
|
|
70
94
|
|
|
71
95
|
Each feature adds a single `include <Feature>Concern` line to `app/models/user.rb`; all of its
|
|
72
96
|
model behavior lives in `app/models/concerns/<feature>_concern.rb`. Tunables are plain constants in
|
|
73
97
|
the generated concerns — e.g. `TimeoutableConcern::TIMEOUT_IN`, `LockableConcern::MAXIMUM_ATTEMPTS`,
|
|
74
98
|
`LockableConcern::UNLOCK_IN`, `ConfirmableConcern::CONFIRMATION_TOKEN_EXPIRES_IN`,
|
|
75
|
-
`ValidatableConcern::PASSWORD_LENGTH`, `ValidatableConcern::PASSWORD_MINIMUM_COMPLEXITY
|
|
76
|
-
there. Concerns keep the model clean.
|
|
99
|
+
`ValidatableConcern::PASSWORD_LENGTH`, `ValidatableConcern::PASSWORD_MINIMUM_COMPLEXITY`,
|
|
100
|
+
`OttConcern::OTT_CODE_LENGTH` — edit them there. Concerns keep the model clean.
|
|
77
101
|
|
|
78
102
|
### Generated routes
|
|
79
103
|
|
|
@@ -83,6 +107,9 @@ resources :confirmations, only: %i[ new create show ], param: :token
|
|
|
83
107
|
resources :unlocks, only: %i[ new create show ], param: :token
|
|
84
108
|
resources :invitations, only: %i[ new create edit update ], param: :token
|
|
85
109
|
resources :magic_links, only: %i[ new create show ], param: :token # with --magic-link
|
|
110
|
+
resource :ott, only: %i[ create edit update ] # with --ott
|
|
111
|
+
resources :webauthn_credentials, only: %i[ index new create destroy ] # with --passkey
|
|
112
|
+
resource :passkey_session, only: %i[ create ] # with --passkey
|
|
86
113
|
resource :session # from the base generator
|
|
87
114
|
resources :passwords, param: :token # from the base generator
|
|
88
115
|
```
|
|
@@ -99,11 +126,6 @@ resources :passwords, param: :token # from the base generator
|
|
|
99
126
|
sessions view with versions tailored to the features you selected. Run the generator once, up
|
|
100
127
|
front — re-running it after you've customized those files will prompt to overwrite them.
|
|
101
128
|
|
|
102
|
-
## Future Plans
|
|
103
|
-
|
|
104
|
-
- OTT (Email code)
|
|
105
|
-
- Passkey
|
|
106
|
-
|
|
107
129
|
## Development
|
|
108
130
|
|
|
109
131
|
```sh
|
|
@@ -117,6 +139,53 @@ bundle exec rspec spec/generators/lockable_spec.rb:12 # a single example
|
|
|
117
139
|
`spec/dummy` is generated (and gitignored), never hand-maintained, so the request specs always
|
|
118
140
|
exercise exactly what the templates produce.
|
|
119
141
|
|
|
142
|
+
To run the app using the dummy app generated in `spec/dummy`, run `bin/dev`
|
|
143
|
+
|
|
144
|
+
## Appraisal
|
|
145
|
+
|
|
146
|
+
Install Appraisal dependencies or when a new Appraisal is added, generate the .gemfile
|
|
147
|
+
|
|
148
|
+
```sh
|
|
149
|
+
bundle exec appraisal generate-install
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
Run tests with Appraisal
|
|
153
|
+
|
|
154
|
+
```sh
|
|
155
|
+
bin/appraisal
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
Run a specific Appraisal test
|
|
159
|
+
|
|
160
|
+
```sh
|
|
161
|
+
# rails-8.0-json-2
|
|
162
|
+
bundle exec appraisal rails-8.0-json-2 rake spec:generators
|
|
163
|
+
bundle exec appraisal rails-8.0-json-2 rake dummy:prepare
|
|
164
|
+
bundle exec appraisal rails-8.0-json-2 rake spec:requests
|
|
165
|
+
# rails-8.0-json-3
|
|
166
|
+
bundle exec appraisal rails-8.0-json-3 rake spec:generators
|
|
167
|
+
bundle exec appraisal rails-8.0-json-3 rake dummy:prepare
|
|
168
|
+
bundle exec appraisal rails-8.0-json-3 rake spec:requests
|
|
169
|
+
# rails-8.1-json-2
|
|
170
|
+
bundle exec appraisal rails-8.1-json-2 rake spec:generators
|
|
171
|
+
bundle exec appraisal rails-8.1-json-2 rake dummy:prepare
|
|
172
|
+
bundle exec appraisal rails-8.1-json-2 rake spec:requests
|
|
173
|
+
# rails-8.1-json-3
|
|
174
|
+
bundle exec appraisal rails-8.1-json-3 rake spec:generators
|
|
175
|
+
bundle exec appraisal rails-8.1-json-3 rake dummy:prepare
|
|
176
|
+
bundle exec appraisal rails-8.1-json-3 rake spec:requests
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
## json 3.0 gem compatibility
|
|
180
|
+
|
|
181
|
+
`json` 3.0 gem removed the `quirks_mode:` keyword and made `JSON.generate`/`JSON.parse`'s second argument keyword-only. Rails' `ActiveSupport::JSON` still calls both with `quirks_mode: true` positionally, so every
|
|
182
|
+
cookie/session read or write throws `ArgumentError` under json 3. `bin/prepare_dummy`
|
|
183
|
+
writes `spec/dummy/config/initializers/json_quirks_mode_compat.rb`, which prepends a shim onto
|
|
184
|
+
`JSON.generate`/`.parse` that strips `quirks_mode` and re-passes remaining options via `**opts`
|
|
185
|
+
(so it works whether the resolved `JSON.parse` still takes a positional options hash, json 2.x,
|
|
186
|
+
or keywords only, json 3.x). It no-ops under json 2.x (`Gem::Version.new(::JSON::VERSION) >=
|
|
187
|
+
Gem::Version.new("3.0")` gates it) and is safe to delete once Rails or json fixes this upstream.
|
|
188
|
+
|
|
120
189
|
## License
|
|
121
190
|
|
|
122
191
|
MIT
|
|
@@ -12,6 +12,8 @@ require_relative "features/validatable"
|
|
|
12
12
|
require_relative "features/lockable"
|
|
13
13
|
require_relative "features/invitable"
|
|
14
14
|
require_relative "features/magic_link"
|
|
15
|
+
require_relative "features/ott"
|
|
16
|
+
require_relative "features/passkey"
|
|
15
17
|
|
|
16
18
|
module RailsAuthentication
|
|
17
19
|
module Generators
|
|
@@ -44,6 +46,8 @@ module RailsAuthentication
|
|
|
44
46
|
include Features::Lockable
|
|
45
47
|
include Features::Invitable
|
|
46
48
|
include Features::MagicLink
|
|
49
|
+
include Features::Ott
|
|
50
|
+
include Features::Passkey
|
|
47
51
|
|
|
48
52
|
source_root File.expand_path("templates", __dir__)
|
|
49
53
|
|
|
@@ -60,6 +64,17 @@ module RailsAuthentication
|
|
|
60
64
|
class_option :magic_link, type: :boolean, default: false,
|
|
61
65
|
desc: "Add passwordless magic link sign-in (opt-in)"
|
|
62
66
|
|
|
67
|
+
# Also opt-in: replaces the sign-in form with an email-only form that
|
|
68
|
+
# emails a 6-digit one-time code, entered on a second screen. Password
|
|
69
|
+
# machinery stays generated and functional.
|
|
70
|
+
class_option :ott, type: :boolean, default: false,
|
|
71
|
+
desc: "Add one-time token (emailed 6-digit code) sign-in (opt-in)"
|
|
72
|
+
|
|
73
|
+
# Also opt-in: WebAuthn passkey sign-in alongside password sign-in.
|
|
74
|
+
# Requires the host app to add the `webauthn` gem itself.
|
|
75
|
+
class_option :passkey, type: :boolean, default: false,
|
|
76
|
+
desc: "Add WebAuthn passkey sign-in (opt-in; requires the webauthn gem)"
|
|
77
|
+
|
|
63
78
|
def install_base_authentication
|
|
64
79
|
say "Running Rails' built-in authentication generator", :green
|
|
65
80
|
Rails::Generators.invoke("rails:authentication", [], behavior: behavior, destination_root: destination_root)
|
|
@@ -105,6 +120,14 @@ module RailsAuthentication
|
|
|
105
120
|
generate_magic_link if magic_link?
|
|
106
121
|
end
|
|
107
122
|
|
|
123
|
+
def install_ott
|
|
124
|
+
generate_ott if ott?
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def install_passkey
|
|
128
|
+
generate_passkey if passkey?
|
|
129
|
+
end
|
|
130
|
+
|
|
108
131
|
# Runs after every feature install so the blank line separates the concern
|
|
109
132
|
# includes (if any) from the rest of the class body, no matter which features
|
|
110
133
|
# are enabled.
|
|
@@ -135,6 +158,14 @@ module RailsAuthentication
|
|
|
135
158
|
options[:magic_link]
|
|
136
159
|
end
|
|
137
160
|
|
|
161
|
+
def ott?
|
|
162
|
+
options[:ott]
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
def passkey?
|
|
166
|
+
options[:passkey]
|
|
167
|
+
end
|
|
168
|
+
|
|
138
169
|
def include_concern_in_user(concern)
|
|
139
170
|
inject_into_class "app/models/user.rb", "User", " include #{concern}\n"
|
|
140
171
|
end
|
|
@@ -5,20 +5,21 @@ module RailsAuthentication
|
|
|
5
5
|
module Features
|
|
6
6
|
module Confirmable
|
|
7
7
|
private
|
|
8
|
-
def generate_confirmable
|
|
9
|
-
template "app/models/concerns/confirmable_concern.rb"
|
|
10
|
-
include_concern_in_user "ConfirmableConcern"
|
|
11
|
-
migration_template "db/migrate/add_confirmable_to_users.rb", "db/migrate/add_confirmable_to_users.rb"
|
|
12
|
-
template "app/controllers/confirmations_controller.rb"
|
|
13
|
-
template "app/views/confirmations/new.html.erb"
|
|
14
|
-
route "resources :confirmations, only: %i[ new create show ], param: :token"
|
|
15
8
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
9
|
+
def generate_confirmable
|
|
10
|
+
template "app/models/concerns/confirmable_concern.rb"
|
|
11
|
+
include_concern_in_user "ConfirmableConcern"
|
|
12
|
+
migration_template "db/migrate/add_confirmable_to_users.rb", "db/migrate/add_confirmable_to_users.rb"
|
|
13
|
+
template "app/controllers/confirmations_controller.rb"
|
|
14
|
+
template "app/views/confirmations/new.html.erb"
|
|
15
|
+
route "resources :confirmations, only: %i[ new create show ], param: :token"
|
|
16
|
+
|
|
17
|
+
if defined?(ActionMailer::Railtie)
|
|
18
|
+
template "app/mailers/confirmations_mailer.rb"
|
|
19
|
+
template "app/views/confirmations_mailer/confirmation_instructions.html.erb"
|
|
20
|
+
template "app/views/confirmations_mailer/confirmation_instructions.text.erb"
|
|
21
21
|
end
|
|
22
|
+
end
|
|
22
23
|
end
|
|
23
24
|
end
|
|
24
25
|
end
|
|
@@ -5,21 +5,22 @@ module RailsAuthentication
|
|
|
5
5
|
module Features
|
|
6
6
|
module Invitable
|
|
7
7
|
private
|
|
8
|
-
def generate_invitable
|
|
9
|
-
template "app/models/concerns/invitable_concern.rb"
|
|
10
|
-
include_concern_in_user "InvitableConcern"
|
|
11
|
-
migration_template "db/migrate/add_invitable_to_users.rb", "db/migrate/add_invitable_to_users.rb"
|
|
12
|
-
template "app/controllers/invitations_controller.rb"
|
|
13
|
-
template "app/views/invitations/new.html.erb"
|
|
14
|
-
template "app/views/invitations/edit.html.erb"
|
|
15
|
-
route "resources :invitations, only: %i[ new create edit update ], param: :token"
|
|
16
8
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
9
|
+
def generate_invitable
|
|
10
|
+
template "app/models/concerns/invitable_concern.rb"
|
|
11
|
+
include_concern_in_user "InvitableConcern"
|
|
12
|
+
migration_template "db/migrate/add_invitable_to_users.rb", "db/migrate/add_invitable_to_users.rb"
|
|
13
|
+
template "app/controllers/invitations_controller.rb"
|
|
14
|
+
template "app/views/invitations/new.html.erb"
|
|
15
|
+
template "app/views/invitations/edit.html.erb"
|
|
16
|
+
route "resources :invitations, only: %i[ new create edit update ], param: :token"
|
|
17
|
+
|
|
18
|
+
if defined?(ActionMailer::Railtie)
|
|
19
|
+
template "app/mailers/invitations_mailer.rb"
|
|
20
|
+
template "app/views/invitations_mailer/invitation_instructions.html.erb"
|
|
21
|
+
template "app/views/invitations_mailer/invitation_instructions.text.erb"
|
|
22
22
|
end
|
|
23
|
+
end
|
|
23
24
|
end
|
|
24
25
|
end
|
|
25
26
|
end
|
|
@@ -5,20 +5,21 @@ module RailsAuthentication
|
|
|
5
5
|
module Features
|
|
6
6
|
module Lockable
|
|
7
7
|
private
|
|
8
|
-
def generate_lockable
|
|
9
|
-
template "app/models/concerns/lockable_concern.rb"
|
|
10
|
-
include_concern_in_user "LockableConcern"
|
|
11
|
-
migration_template "db/migrate/add_lockable_to_users.rb", "db/migrate/add_lockable_to_users.rb"
|
|
12
|
-
template "app/controllers/unlocks_controller.rb"
|
|
13
|
-
template "app/views/unlocks/new.html.erb"
|
|
14
|
-
route "resources :unlocks, only: %i[ new create show ], param: :token"
|
|
15
8
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
9
|
+
def generate_lockable
|
|
10
|
+
template "app/models/concerns/lockable_concern.rb"
|
|
11
|
+
include_concern_in_user "LockableConcern"
|
|
12
|
+
migration_template "db/migrate/add_lockable_to_users.rb", "db/migrate/add_lockable_to_users.rb"
|
|
13
|
+
template "app/controllers/unlocks_controller.rb"
|
|
14
|
+
template "app/views/unlocks/new.html.erb"
|
|
15
|
+
route "resources :unlocks, only: %i[ new create show ], param: :token"
|
|
16
|
+
|
|
17
|
+
if defined?(ActionMailer::Railtie)
|
|
18
|
+
template "app/mailers/unlocks_mailer.rb"
|
|
19
|
+
template "app/views/unlocks_mailer/unlock_instructions.html.erb"
|
|
20
|
+
template "app/views/unlocks_mailer/unlock_instructions.text.erb"
|
|
21
21
|
end
|
|
22
|
+
end
|
|
22
23
|
end
|
|
23
24
|
end
|
|
24
25
|
end
|
|
@@ -8,20 +8,21 @@ module RailsAuthentication
|
|
|
8
8
|
# Recoverable rework.
|
|
9
9
|
module MagicLink
|
|
10
10
|
private
|
|
11
|
-
def generate_magic_link
|
|
12
|
-
template "app/models/concerns/magic_link_concern.rb"
|
|
13
|
-
include_concern_in_user "MagicLinkConcern"
|
|
14
|
-
migration_template "db/migrate/add_magic_link_to_users.rb", "db/migrate/add_magic_link_to_users.rb"
|
|
15
|
-
template "app/controllers/magic_links_controller.rb"
|
|
16
|
-
template "app/views/magic_links/new.html.erb"
|
|
17
|
-
route "resources :magic_links, only: %i[ new create show ], param: :token"
|
|
18
11
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
12
|
+
def generate_magic_link
|
|
13
|
+
template "app/models/concerns/magic_link_concern.rb"
|
|
14
|
+
include_concern_in_user "MagicLinkConcern"
|
|
15
|
+
migration_template "db/migrate/add_magic_link_to_users.rb", "db/migrate/add_magic_link_to_users.rb"
|
|
16
|
+
template "app/controllers/magic_links_controller.rb"
|
|
17
|
+
template "app/views/magic_links/new.html.erb"
|
|
18
|
+
route "resources :magic_links, only: %i[ new create show ], param: :token"
|
|
19
|
+
|
|
20
|
+
if defined?(ActionMailer::Railtie)
|
|
21
|
+
template "app/mailers/magic_links_mailer.rb"
|
|
22
|
+
template "app/views/magic_links_mailer/magic_link.html.erb"
|
|
23
|
+
template "app/views/magic_links_mailer/magic_link.text.erb"
|
|
24
24
|
end
|
|
25
|
+
end
|
|
25
26
|
end
|
|
26
27
|
end
|
|
27
28
|
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RailsAuthentication
|
|
4
|
+
module Generators
|
|
5
|
+
module Features
|
|
6
|
+
# Opt-in (--ott): one-time token sign-in. The sign-in page becomes an
|
|
7
|
+
# email-only form; a 6-digit code is emailed and entered on a second
|
|
8
|
+
# screen. Codes are DB-backed, single-use, expire after 10 minutes, and
|
|
9
|
+
# are voided after 5 wrong attempts. Password machinery (Recoverable,
|
|
10
|
+
# Registerable, SessionsController#create) is left intact.
|
|
11
|
+
module Ott
|
|
12
|
+
private
|
|
13
|
+
|
|
14
|
+
def generate_ott
|
|
15
|
+
template "app/models/concerns/ott_concern.rb"
|
|
16
|
+
include_concern_in_user "OttConcern"
|
|
17
|
+
migration_template "db/migrate/add_ott_to_users.rb", "db/migrate/add_ott_to_users.rb"
|
|
18
|
+
template "app/controllers/otts_controller.rb"
|
|
19
|
+
template "app/views/otts/edit.html.erb"
|
|
20
|
+
route "resource :ott, only: %i[ create edit update ]"
|
|
21
|
+
|
|
22
|
+
if defined?(ActionMailer::Railtie)
|
|
23
|
+
template "app/mailers/otts_mailer.rb"
|
|
24
|
+
template "app/views/otts_mailer/ott.html.erb"
|
|
25
|
+
template "app/views/otts_mailer/ott.text.erb"
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module RailsAuthentication
|
|
4
|
+
module Generators
|
|
5
|
+
module Features
|
|
6
|
+
# Opt-in (--passkey): WebAuthn-based passkey sign-in, in addition to
|
|
7
|
+
# password sign-in. A user may register any number of passkeys
|
|
8
|
+
# (platform authenticators, security keys); sign-in is usernameless —
|
|
9
|
+
# the browser's discoverable-credential picker stands in for an email
|
|
10
|
+
# field. Ceremony verification is delegated to the `webauthn` gem —
|
|
11
|
+
# unlike everything else this gem generates, that's a real runtime
|
|
12
|
+
# dependency, so it's added straight to the host app's Gemfile.
|
|
13
|
+
module Passkey
|
|
14
|
+
private
|
|
15
|
+
|
|
16
|
+
def generate_passkey
|
|
17
|
+
gem "webauthn", comment: "Verifies WebAuthn passkey registration/authentication ceremonies"
|
|
18
|
+
say "Added the `webauthn` gem to your Gemfile — run `bundle install`.", :yellow
|
|
19
|
+
|
|
20
|
+
template "config/initializers/webauthn.rb"
|
|
21
|
+
template "app/models/concerns/passkey_concern.rb"
|
|
22
|
+
include_concern_in_user "PasskeyConcern"
|
|
23
|
+
template "app/models/webauthn_credential.rb"
|
|
24
|
+
migration_template "db/migrate/add_webauthn_id_to_users.rb", "db/migrate/add_webauthn_id_to_users.rb"
|
|
25
|
+
migration_template "db/migrate/create_webauthn_credentials.rb", "db/migrate/create_webauthn_credentials.rb"
|
|
26
|
+
template "app/controllers/webauthn_credentials_controller.rb"
|
|
27
|
+
template "app/controllers/passkey_sessions_controller.rb"
|
|
28
|
+
template "app/views/webauthn_credentials/index.html.erb"
|
|
29
|
+
template "app/views/webauthn_credentials/new.html.erb"
|
|
30
|
+
route "resources :webauthn_credentials, only: %i[ index new create destroy ]"
|
|
31
|
+
route "resource :passkey_session, only: %i[ create ], controller: \"passkey_sessions\""
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -5,20 +5,21 @@ module RailsAuthentication
|
|
|
5
5
|
module Features
|
|
6
6
|
module Recoverable
|
|
7
7
|
private
|
|
8
|
-
# Replaces the base generator's stateless generates_token_for password reset
|
|
9
|
-
# with DB-backed, revocable tokens.
|
|
10
|
-
def generate_recoverable
|
|
11
|
-
template "app/models/concerns/recoverable_concern.rb"
|
|
12
|
-
include_concern_in_user "RecoverableConcern"
|
|
13
|
-
migration_template "db/migrate/add_recoverable_to_users.rb", "db/migrate/add_recoverable_to_users.rb"
|
|
14
|
-
template "app/controllers/passwords_controller.rb", force: true
|
|
15
8
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
9
|
+
# Replaces the base generator's stateless generates_token_for password reset
|
|
10
|
+
# with DB-backed, revocable tokens.
|
|
11
|
+
def generate_recoverable
|
|
12
|
+
template "app/models/concerns/recoverable_concern.rb"
|
|
13
|
+
include_concern_in_user "RecoverableConcern"
|
|
14
|
+
migration_template "db/migrate/add_recoverable_to_users.rb", "db/migrate/add_recoverable_to_users.rb"
|
|
15
|
+
template "app/controllers/passwords_controller.rb", force: true
|
|
16
|
+
|
|
17
|
+
if defined?(ActionMailer::Railtie)
|
|
18
|
+
template "app/mailers/passwords_mailer.rb", force: true
|
|
19
|
+
template "app/views/passwords_mailer/reset.html.erb", force: true
|
|
20
|
+
template "app/views/passwords_mailer/reset.text.erb", force: true
|
|
21
21
|
end
|
|
22
|
+
end
|
|
22
23
|
end
|
|
23
24
|
end
|
|
24
25
|
end
|
|
@@ -5,12 +5,13 @@ module RailsAuthentication
|
|
|
5
5
|
module Features
|
|
6
6
|
module Registerable
|
|
7
7
|
private
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
8
|
+
|
|
9
|
+
def generate_registerable
|
|
10
|
+
template "app/controllers/registrations_controller.rb"
|
|
11
|
+
template "app/views/registrations/new.html.erb"
|
|
12
|
+
template "app/views/registrations/edit.html.erb"
|
|
13
|
+
route "resource :registration, only: %i[ new create edit update destroy ]"
|
|
14
|
+
end
|
|
14
15
|
end
|
|
15
16
|
end
|
|
16
17
|
end
|
|
@@ -5,11 +5,12 @@ module RailsAuthentication
|
|
|
5
5
|
module Features
|
|
6
6
|
module Rememberable
|
|
7
7
|
private
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
8
|
+
|
|
9
|
+
def generate_rememberable
|
|
10
|
+
template "app/models/concerns/rememberable_concern.rb"
|
|
11
|
+
include_concern_in_user "RememberableConcern"
|
|
12
|
+
migration_template "db/migrate/add_rememberable_to_users.rb", "db/migrate/add_rememberable_to_users.rb"
|
|
13
|
+
end
|
|
13
14
|
end
|
|
14
15
|
end
|
|
15
16
|
end
|
|
@@ -5,12 +5,13 @@ module RailsAuthentication
|
|
|
5
5
|
module Features
|
|
6
6
|
module Timeoutable
|
|
7
7
|
private
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
8
|
+
|
|
9
|
+
# No migration: inactivity is measured against sessions.updated_at, which the
|
|
10
|
+
# base generator's sessions table already has.
|
|
11
|
+
def generate_timeoutable
|
|
12
|
+
template "app/models/concerns/timeoutable_concern.rb"
|
|
13
|
+
include_concern_in_user "TimeoutableConcern"
|
|
14
|
+
end
|
|
14
15
|
end
|
|
15
16
|
end
|
|
16
17
|
end
|
|
@@ -5,12 +5,13 @@ module RailsAuthentication
|
|
|
5
5
|
module Features
|
|
6
6
|
module Trackable
|
|
7
7
|
private
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
8
|
+
|
|
9
|
+
def generate_trackable
|
|
10
|
+
template "app/models/concerns/trackable_concern.rb"
|
|
11
|
+
include_concern_in_user "TrackableConcern"
|
|
12
|
+
template "app/models/user_auth.rb"
|
|
13
|
+
migration_template "db/migrate/create_user_auths.rb", "db/migrate/create_user_auths.rb"
|
|
14
|
+
end
|
|
14
15
|
end
|
|
15
16
|
end
|
|
16
17
|
end
|
|
@@ -5,10 +5,11 @@ module RailsAuthentication
|
|
|
5
5
|
module Features
|
|
6
6
|
module Validatable
|
|
7
7
|
private
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
8
|
+
|
|
9
|
+
def generate_validatable
|
|
10
|
+
template "app/models/concerns/validatable_concern.rb"
|
|
11
|
+
include_concern_in_user "ValidatableConcern"
|
|
12
|
+
end
|
|
12
13
|
end
|
|
13
14
|
end
|
|
14
15
|
end
|