rodauth-rails 1.8.0 → 1.10.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +22 -0
- data/README.md +155 -243
- data/lib/generators/rodauth/install_generator.rb +1 -1
- data/lib/generators/rodauth/migration/active_record/active_sessions.erb +2 -2
- data/lib/generators/rodauth/migration/active_record/audit_logging.erb +2 -2
- data/lib/generators/rodauth/migration/active_record/email_auth.erb +1 -1
- data/lib/generators/rodauth/migration/active_record/otp.erb +1 -1
- data/lib/generators/rodauth/migration/active_record/password_expiration.erb +1 -1
- data/lib/generators/rodauth/migration/active_record/reset_password.erb +1 -1
- data/lib/generators/rodauth/migration/active_record/sms_codes.erb +1 -1
- data/lib/generators/rodauth/migration/active_record/verify_account.erb +2 -2
- data/lib/generators/rodauth/migration/active_record/webauthn.erb +1 -1
- data/lib/generators/rodauth/migration_generator.rb +2 -22
- data/lib/generators/rodauth/templates/app/mailers/rodauth_mailer.rb.tt +7 -7
- data/lib/generators/rodauth/templates/app/misc/rodauth_main.rb.tt +1 -1
- data/lib/generators/rodauth/templates/app/views/rodauth/_login_form.html.erb +1 -1
- data/lib/generators/rodauth/templates/app/views/rodauth/login.html.erb +2 -2
- data/lib/generators/rodauth/templates/app/views/rodauth/multi_phase_login.html.erb +2 -2
- data/lib/generators/rodauth/templates/app/views/rodauth/tailwind/_login_form.html.erb +1 -1
- data/lib/generators/rodauth/templates/app/views/rodauth/tailwind/login.html.erb +2 -2
- data/lib/generators/rodauth/templates/app/views/rodauth/tailwind/multi_phase_login.html.erb +2 -2
- data/lib/generators/rodauth/templates/app/views/rodauth/tailwind/webauthn_autofill.html.erb +10 -0
- data/lib/generators/rodauth/templates/app/views/rodauth/webauthn_autofill.html.erb +10 -0
- data/lib/generators/rodauth/templates/app/views/rodauth_mailer/unlock_account.text.erb +1 -1
- data/lib/generators/rodauth/templates/db/migrate/create_rodauth.rb.tt +1 -1
- data/lib/generators/rodauth/views_generator.rb +3 -12
- data/lib/rodauth/rails/app.rb +7 -9
- data/lib/rodauth/rails/feature/base.rb +5 -29
- data/lib/rodauth/rails/feature/render.rb +1 -1
- data/lib/rodauth/rails/railtie.rb +2 -6
- data/lib/rodauth/rails/version.rb +1 -1
- data/lib/rodauth/rails.rb +10 -10
- data/rodauth-rails.gemspec +2 -2
- metadata +9 -9
- data/lib/generators/rodauth/templates/app/views/rodauth/_login_form_header.html.erb +0 -3
- data/lib/generators/rodauth/templates/app/views/rodauth/tailwind/_login_form_header.html.erb +0 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: adfcbce27e52d0a53b5cd670489635c841dff9e2809c92be059286943894db6c
|
4
|
+
data.tar.gz: e98584823e926c810bc66366496df5fb3c8eed0f38e291b76b9f132480941a9c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 845b037926a9372522da9b3507b5fd2959454bc24198f72a7832d9025ccd27f9bac3790823577e1e68c3a1e1a076472e1629825973c37cc932e2b63299e1408b
|
7
|
+
data.tar.gz: af417d7bbe9732c677ca15c6796817554fe68d5f8f3db8001b56a736db33382f3efd8f86952509d038f45f449f76d3c9ea61f1a7f5a29c1cef5f45e72cf1c9ce
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,25 @@
|
|
1
|
+
## 1.10.0 (2023-07-26)
|
2
|
+
|
3
|
+
* Add `Rodauth::Rails.lib` for easier usage of Rodauth as a library in Rails apps (@janko)
|
4
|
+
|
5
|
+
## 1.9.0 (2023-05-22)
|
6
|
+
|
7
|
+
* Add support for webauthn_autofill feature to the views generator (@janko)
|
8
|
+
|
9
|
+
* Generate view templates for two_factor_base feature only if explicitly specified (@janko)
|
10
|
+
|
11
|
+
* Set `login_param "email"` in generated Rodauth configuration (@janko)
|
12
|
+
|
13
|
+
* Handle Trilogy adapter in generators (@janko)
|
14
|
+
|
15
|
+
* Use `email_subject_prefix` in generated mailer (@janko)
|
16
|
+
|
17
|
+
* Fix typo in `unlock_account` email template (@zavan)
|
18
|
+
|
19
|
+
* Retrieve current account using `account!` in `#rails_account` method (@janko)
|
20
|
+
|
21
|
+
* Drop support for Rails 4.2 (@janko)
|
22
|
+
|
1
23
|
## 1.8.0 (2023-02-25)
|
2
24
|
|
3
25
|
* Add table argument to `rodauth:install` generator (@janko)
|
data/README.md
CHANGED
@@ -24,6 +24,7 @@ Provides Rails integration for the [Rodauth] authentication framework.
|
|
24
24
|
* [How to build an OIDC provider using rodauth-oauth on Rails](https://honeyryderchuck.gitlab.io/httpx/2021/03/15/oidc-provider-on-rails-using-rodauth-oauth.html)
|
25
25
|
* [What It Took to Build a Rails Integration for Rodauth](https://janko.io/what-it-took-to-build-a-rails-integration-for-rodauth/)
|
26
26
|
* [Social Login in Rails with Rodauth](https://janko.io/social-login-in-rails-with-rodauth/)
|
27
|
+
* [Passkey Authentication with Rodauth](https://janko.io/passkey-authentication-with-rodauth/)
|
27
28
|
|
28
29
|
## Why Rodauth?
|
29
30
|
|
@@ -31,16 +32,13 @@ There are already several popular authentication solutions for Rails (Devise,
|
|
31
32
|
Sorcery, Clearance, Authlogic), so why would you choose Rodauth? Here are some
|
32
33
|
of the advantages that stand out for me:
|
33
34
|
|
34
|
-
* multifactor authentication ([TOTP][otp], [SMS codes][sms_codes], [recovery codes][recovery_codes], [
|
35
|
+
* multifactor authentication ([TOTP][otp], [SMS codes][sms_codes], [recovery codes][recovery_codes], [passkeys][webauthn])
|
35
36
|
* standardized [JSON API support][json] for every feature (including [JWT][jwt])
|
36
37
|
* enterprise security features ([password complexity][password_complexity], [disallow password reuse][disallow_password_reuse], [password expiration][password_expiration], [session expiration][session_expiration], [single session][single_session], [account expiration][account_expiration])
|
37
|
-
* [email
|
38
|
-
* [audit logging][audit_logging]
|
38
|
+
* passwordless authentication ([email][email_auth], [passkeys][webauthn_login])
|
39
|
+
* [audit logging][audit_logging] for any action
|
39
40
|
* ability to protect password hashes even in case of SQL injection ([more details][password protection])
|
40
|
-
*
|
41
|
-
* uniform configuration DSL (any setting can be static or dynamic)
|
42
|
-
* consistent before/after hooks around everything
|
43
|
-
* dedicated object encapsulating all authentication logic
|
41
|
+
* uniform configuration DSL with before/after hooks around everything
|
44
42
|
|
45
43
|
### Sequel
|
46
44
|
|
@@ -188,25 +186,6 @@ current_account #=> #<Account id=123 email="user@example.com">
|
|
188
186
|
current_account.email #=> "user@example.com"
|
189
187
|
```
|
190
188
|
|
191
|
-
If the session is logged in, but the account doesn't exist in the database, the
|
192
|
-
session will be reset.
|
193
|
-
|
194
|
-
#### Custom account model
|
195
|
-
|
196
|
-
The `#rails_account` method will try to infer the account model class from the
|
197
|
-
configured accounts table name. However, if the model class cannot be inferred
|
198
|
-
from the table name, you can configure it manually:
|
199
|
-
|
200
|
-
```rb
|
201
|
-
# app/misc/rodauth_main.rb
|
202
|
-
class RodauthMain < Rodauth::Rails::Auth
|
203
|
-
configure do
|
204
|
-
# ...
|
205
|
-
rails_account_model { Authentication::Account } # custom model name
|
206
|
-
end
|
207
|
-
end
|
208
|
-
```
|
209
|
-
|
210
189
|
### Requiring authentication
|
211
190
|
|
212
191
|
You'll likely want to require authentication for certain parts of your app,
|
@@ -222,8 +201,8 @@ class RodauthApp < Rodauth::Rails::App
|
|
222
201
|
# ...
|
223
202
|
r.rodauth # route rodauth requests
|
224
203
|
|
225
|
-
# require authentication for /dashboard/*
|
226
|
-
if r.path.start_with?("/dashboard")
|
204
|
+
# require authentication for /dashboard/* routes
|
205
|
+
if r.path.start_with?("/dashboard")
|
227
206
|
rodauth.require_account # redirect to login page if not authenticated
|
228
207
|
end
|
229
208
|
end
|
@@ -248,12 +227,6 @@ class DashboardController < ApplicationController
|
|
248
227
|
before_action :authenticate
|
249
228
|
end
|
250
229
|
```
|
251
|
-
```rb
|
252
|
-
# app/controllers/posts_controller.rb
|
253
|
-
class PostsController < ApplicationController
|
254
|
-
before_action :authenticate, except: [:index, :show]
|
255
|
-
end
|
256
|
-
```
|
257
230
|
|
258
231
|
#### Routing constraints
|
259
232
|
|
@@ -282,42 +255,83 @@ Rails.application.routes.draw do
|
|
282
255
|
end
|
283
256
|
```
|
284
257
|
|
285
|
-
|
258
|
+
You can specify a different Rodauth configuration by passing the configuration name:
|
286
259
|
|
287
260
|
```rb
|
288
261
|
# config/routes.rb
|
289
262
|
Rails.application.routes.draw do
|
290
|
-
|
291
|
-
constraints Rodauth::Rails.authenticated { |rodauth| rodauth.rails_account.admin? } do
|
263
|
+
constraints Rodauth::Rails.authenticated(:admin) do
|
292
264
|
# ...
|
293
265
|
end
|
294
266
|
end
|
295
267
|
```
|
296
268
|
|
297
|
-
|
269
|
+
If you need something more custom, you can always create the routing constraint
|
270
|
+
manually:
|
298
271
|
|
299
272
|
```rb
|
300
273
|
# config/routes.rb
|
301
274
|
Rails.application.routes.draw do
|
302
|
-
constraints
|
303
|
-
#
|
275
|
+
constraints -> (r) { !r.env["rodauth"].logged_in? } do # or env["rodauth.admin"]
|
276
|
+
# routes when the user is not logged in
|
304
277
|
end
|
305
278
|
end
|
306
279
|
```
|
307
280
|
|
308
|
-
|
309
|
-
|
281
|
+
### Controller
|
282
|
+
|
283
|
+
Your Rodauth configuration is connected to a Rails controller (`RodauthController` by default), and
|
284
|
+
it automatically executes any callbacks and rescue handlers defined on it (or the parent controller)
|
285
|
+
around Rodauth endpoints.
|
310
286
|
|
311
287
|
```rb
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
288
|
+
class RodauthController < ApplicationController
|
289
|
+
before_action :set_locale # executes before Rodauth endpoints
|
290
|
+
rescue_from("MyApp::SomeError") { |exception| ... } # rescues around Rodauth endpoints
|
291
|
+
end
|
292
|
+
```
|
293
|
+
|
294
|
+
#### Calling controller methods
|
295
|
+
|
296
|
+
You can call any controller methods from your Rodauth configuration via `rails_controller_eval`:
|
297
|
+
|
298
|
+
```rb
|
299
|
+
# app/controllers/application_controller.rb
|
300
|
+
class ApplicationController < ActionController::Base
|
301
|
+
private
|
302
|
+
def setup_tracking(account_id)
|
303
|
+
# ... some implementation ...
|
304
|
+
end
|
305
|
+
end
|
306
|
+
```
|
307
|
+
```rb
|
308
|
+
# app/misc/rodauth_main.rb
|
309
|
+
class RodauthMain < Rodauth::Rails::Auth
|
310
|
+
configure do
|
311
|
+
after_create_account do
|
312
|
+
rails_controller_eval { setup_tracking(account_id) }
|
313
|
+
end
|
316
314
|
end
|
317
315
|
end
|
318
316
|
```
|
319
317
|
|
320
|
-
###
|
318
|
+
### Rails URL helpers
|
319
|
+
|
320
|
+
Inside Rodauth configuration and the `route` block you can access Rails route
|
321
|
+
helpers through `#rails_routes`:
|
322
|
+
|
323
|
+
```rb
|
324
|
+
# app/misc/rodauth_main.rb
|
325
|
+
class RodauthMain < Rodauth::Rails::Auth
|
326
|
+
configure do
|
327
|
+
login_redirect { rails_routes.activity_path }
|
328
|
+
change_password_redirect { rails_routes.profile_path }
|
329
|
+
change_login_redirect { rails_routes.profile_path }
|
330
|
+
end
|
331
|
+
end
|
332
|
+
```
|
333
|
+
|
334
|
+
## Views
|
321
335
|
|
322
336
|
The templates built into Rodauth are useful when getting started, but soon
|
323
337
|
you'll want to start editing the markup. You can run the following command to
|
@@ -349,10 +363,10 @@ $ rails generate rodauth:views --all
|
|
349
363
|
Use `--name` to generate views for a different Rodauth configuration:
|
350
364
|
|
351
365
|
```sh
|
352
|
-
$ rails generate rodauth:views webauthn --name admin
|
366
|
+
$ rails generate rodauth:views webauthn two_factor_base --name admin
|
353
367
|
```
|
354
368
|
|
355
|
-
|
369
|
+
### Page titles
|
356
370
|
|
357
371
|
The generated configuration sets `title_instance_variable` to make page titles
|
358
372
|
available in your views via `@page_title` instance variable, which you can then
|
@@ -362,9 +376,7 @@ use in your layout:
|
|
362
376
|
# app/misc/rodauth_main.rb
|
363
377
|
class RodauthMain < Rodauth::Rails::Auth
|
364
378
|
configure do
|
365
|
-
# ...
|
366
379
|
title_instance_variable :@page_title
|
367
|
-
# ...
|
368
380
|
end
|
369
381
|
end
|
370
382
|
```
|
@@ -376,28 +388,11 @@ end
|
|
376
388
|
<title><%= @page_title || "Default title" %></title>
|
377
389
|
<!-- ... -->
|
378
390
|
</head>
|
379
|
-
|
380
|
-
<!-- ... -->
|
381
|
-
</body>
|
391
|
+
<!-- ... -->
|
382
392
|
</html>
|
383
393
|
```
|
384
394
|
|
385
|
-
|
386
|
-
generated Rodauth views, giving it the result of the corresponding
|
387
|
-
`*_page_title` method:
|
388
|
-
|
389
|
-
```erb
|
390
|
-
<!-- app/views/rodauth/login.html.erb -->
|
391
|
-
<%= content_for :page_title, rodauth.login_page_title %>
|
392
|
-
<!-- ... -->
|
393
|
-
```
|
394
|
-
```erb
|
395
|
-
<!-- app/views/rodauth/change_password.html.erb -->
|
396
|
-
<%= content_for :page_title, rodauth.change_password_page_title %>
|
397
|
-
<!-- ... -->
|
398
|
-
```
|
399
|
-
|
400
|
-
#### Layout
|
395
|
+
### Layout
|
401
396
|
|
402
397
|
To use different layouts for different Rodauth views, you can compare the
|
403
398
|
request path in the layout method:
|
@@ -425,7 +420,7 @@ class RodauthController < ApplicationController
|
|
425
420
|
end
|
426
421
|
```
|
427
422
|
|
428
|
-
|
423
|
+
### Turbo
|
429
424
|
|
430
425
|
[Turbo] has been disabled by default on all built-in and generated view
|
431
426
|
templates, because some Rodauth actions (multi-phase login, adding recovery
|
@@ -434,7 +429,7 @@ codes) aren't Turbo-compatible, as they return 200 responses on POST requests.
|
|
434
429
|
That being said, most of Rodauth *is* Turbo-compatible, so feel free to enable
|
435
430
|
Turbo for actions where you want to use it.
|
436
431
|
|
437
|
-
|
432
|
+
## Mailer
|
438
433
|
|
439
434
|
The install generator will create `RodauthMailer` with default email templates,
|
440
435
|
and configure Rodauth features that send emails as part of the authentication
|
@@ -443,73 +438,45 @@ flow to use it.
|
|
443
438
|
```rb
|
444
439
|
# app/mailers/rodauth_mailer.rb
|
445
440
|
class RodauthMailer < ApplicationMailer
|
446
|
-
def verify_account(account_id, key)
|
447
|
-
|
448
|
-
end
|
449
|
-
def
|
450
|
-
|
451
|
-
end
|
452
|
-
def verify_login_change(account_id, old_login, new_login, key)
|
453
|
-
# ...
|
454
|
-
end
|
455
|
-
def password_changed(account_id)
|
456
|
-
# ...
|
457
|
-
end
|
458
|
-
# def email_auth(account_id, key)
|
459
|
-
# ...
|
460
|
-
# end
|
461
|
-
# def unlock_account(account_id, key)
|
462
|
-
# ...
|
463
|
-
# end
|
441
|
+
def verify_account(account_id, key) ... end
|
442
|
+
def reset_password(account_id, key) ... end
|
443
|
+
def verify_login_change(account_id, key) ... end
|
444
|
+
def password_changed(account_id) ... end
|
445
|
+
# def email_auth(account_id, key) ... end
|
446
|
+
# def unlock_account(account_id, key) ... end
|
464
447
|
end
|
465
448
|
```
|
466
449
|
```rb
|
467
450
|
# app/misc/rodauth_main.rb
|
468
451
|
class RodauthMain < Rodauth::Rails::Auth
|
469
452
|
configure do
|
470
|
-
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
end
|
477
|
-
create_verify_login_change_email do |_login|
|
478
|
-
RodauthMailer.verify_login_change(account_id, verify_login_change_old_login, verify_login_change_new_login, verify_login_change_key_value)
|
479
|
-
end
|
480
|
-
create_password_changed_email do
|
481
|
-
RodauthMailer.password_changed(account_id)
|
482
|
-
end
|
483
|
-
# create_email_auth_email do
|
484
|
-
# RodauthMailer.email_auth(account_id, email_auth_key_value)
|
485
|
-
# end
|
486
|
-
# create_unlock_account_email do
|
487
|
-
# RodauthMailer.unlock_account(account_id, unlock_account_key_value)
|
488
|
-
# end
|
453
|
+
create_reset_password_email { RodauthMailer.reset_password(account_id, reset_password_key_value) }
|
454
|
+
create_verify_account_email { RodauthMailer.verify_account(account_id, verify_account_key_value) }
|
455
|
+
create_verify_login_change_email { |_login| RodauthMailer.verify_login_change(account_id, verify_login_change_key_value) }
|
456
|
+
create_password_changed_email { RodauthMailer.password_changed(account_id) }
|
457
|
+
# create_email_auth_email { RodauthMailer.email_auth(account_id, email_auth_key_value) }
|
458
|
+
# create_unlock_account_email { RodauthMailer.unlock_account(account_id, unlock_account_key_value) }
|
489
459
|
send_email do |email|
|
490
460
|
# queue email delivery on the mailer after the transaction commits
|
491
461
|
db.after_commit { email.deliver_later }
|
492
462
|
end
|
493
|
-
# ...
|
494
463
|
end
|
495
464
|
end
|
496
465
|
```
|
497
466
|
|
498
467
|
This configuration calls `#deliver_later`, which uses Active Job to deliver
|
499
|
-
emails in a background job.
|
500
|
-
|
501
|
-
deliveries. However, if you want to send emails synchronously, you can modify
|
502
|
-
the configuration to call `#deliver_now` instead.
|
468
|
+
emails in a background job. If you want to send emails synchronously, you can
|
469
|
+
modify the configuration to call `#deliver_now` instead.
|
503
470
|
|
504
471
|
If you're using a background processing library without an Active Job adapter,
|
505
472
|
or a 3rd-party service for sending transactional emails, see [this wiki
|
506
473
|
page][custom mailer worker] on how to set it up.
|
507
474
|
|
508
|
-
|
475
|
+
## Migrations
|
509
476
|
|
510
477
|
The install generator will create a migration for tables used by the Rodauth
|
511
478
|
features enabled by default. For any additional features, you can use the
|
512
|
-
migration generator
|
479
|
+
migration generator to create the required tables:
|
513
480
|
|
514
481
|
```sh
|
515
482
|
$ rails generate rodauth:migration otp sms_codes recovery_codes
|
@@ -525,10 +492,10 @@ class CreateRodauthOtpSmsCodesRecoveryCodes < ActiveRecord::Migration
|
|
525
492
|
end
|
526
493
|
```
|
527
494
|
|
528
|
-
|
495
|
+
### Table prefix
|
529
496
|
|
530
497
|
If you're storing account records in a table other than `accounts`, you'll want
|
531
|
-
to specify the
|
498
|
+
to specify the appropriate table prefix when generating new migrations:
|
532
499
|
|
533
500
|
```sh
|
534
501
|
$ rails generate rodauth:migration base active_sessions --prefix user
|
@@ -549,7 +516,7 @@ class CreateRodauthUserBaseActiveSessions < ActiveRecord::Migration
|
|
549
516
|
end
|
550
517
|
```
|
551
518
|
|
552
|
-
|
519
|
+
### Custom migration name
|
553
520
|
|
554
521
|
You can change the default migration name:
|
555
522
|
|
@@ -573,37 +540,23 @@ tables used by enabled authentication features.
|
|
573
540
|
|
574
541
|
```rb
|
575
542
|
class Account < ActiveRecord::Base # Sequel::Model
|
576
|
-
include Rodauth::Rails.model # or
|
543
|
+
include Rodauth::Rails.model # or Rodauth::Rails.model(:admin)
|
577
544
|
end
|
578
545
|
```
|
579
|
-
|
580
|
-
The password attribute can be used to set or clear the password hash. It
|
581
|
-
handles both storing the password hash in a column on the accounts table, or in
|
582
|
-
a separate table.
|
583
|
-
|
584
546
|
```rb
|
547
|
+
# setting password hash
|
585
548
|
account = Account.create!(email: "user@example.com", password: "secret123")
|
586
|
-
|
587
|
-
# when password hash is stored in a column on the accounts table
|
588
549
|
account.password_hash #=> "$2a$12$k/Ub1I2iomi84RacqY89Hu4.M0vK7klRnRtzorDyvOkVI.hKhkNw."
|
589
550
|
|
590
|
-
#
|
591
|
-
account.
|
592
|
-
account.password_hash.password_hash #=> "$2a$12$k/Ub1..." (inaccessible when using database authentication functions)
|
593
|
-
|
594
|
-
account.password = nil # clears password hash
|
551
|
+
# clearing password hash
|
552
|
+
account.password = nil
|
595
553
|
account.password_hash #=> nil
|
596
|
-
```
|
597
|
-
|
598
|
-
The associations are defined for tables used by enabled authentication features:
|
599
554
|
|
600
|
-
|
555
|
+
# associations
|
601
556
|
account.remember_key #=> #<Account::RememberKey> (record from `account_remember_keys` table)
|
602
557
|
account.active_session_keys #=> [#<Account::ActiveSessionKey>,...] (records from `account_active_session_keys` table)
|
603
558
|
```
|
604
559
|
|
605
|
-
See the [rodauth-model] documentation for more details.
|
606
|
-
|
607
560
|
## Multiple configurations
|
608
561
|
|
609
562
|
If you need to handle multiple types of accounts that require different
|
@@ -649,43 +602,9 @@ Then in your application you can reference the secondary Rodauth instance:
|
|
649
602
|
rodauth(:admin).login_path #=> "/admin/login"
|
650
603
|
```
|
651
604
|
|
652
|
-
|
653
|
-
configuration to the database
|
654
|
-
that
|
655
|
-
|
656
|
-
### Sharing configuration
|
657
|
-
|
658
|
-
If there are common settings that you want to share between Rodauth
|
659
|
-
configurations, you can do so via inheritance:
|
660
|
-
|
661
|
-
```rb
|
662
|
-
# app/misc/rodauth_base.rb
|
663
|
-
class RodauthBase < Rodauth::Rails::Auth
|
664
|
-
# common settings that are shared between multiple configurations
|
665
|
-
configure do
|
666
|
-
enable :login, :logout
|
667
|
-
login_return_to_requested_location? true
|
668
|
-
logout_redirect "/"
|
669
|
-
# ...
|
670
|
-
end
|
671
|
-
end
|
672
|
-
```
|
673
|
-
```rb
|
674
|
-
# app/misc/rodauth_main.rb
|
675
|
-
class RodauthMain < RodauthBase # inherit common settings
|
676
|
-
configure do
|
677
|
-
# ... customize main ...
|
678
|
-
end
|
679
|
-
end
|
680
|
-
```
|
681
|
-
```rb
|
682
|
-
# app/misc/rodauth_admin.rb
|
683
|
-
class RodauthAdmin < RodauthBase # inherit common settings
|
684
|
-
configure do
|
685
|
-
# ... customize admin ...
|
686
|
-
end
|
687
|
-
end
|
688
|
-
```
|
605
|
+
You'll likely want to save the information of which account belongs to which
|
606
|
+
configuration to the database, see [this guide][account types] on how you can do
|
607
|
+
that. Note that you can also [share configuration via inheritance][inheritance].
|
689
608
|
|
690
609
|
## Outside of a request
|
691
610
|
|
@@ -772,6 +691,34 @@ Rodauth::Rails.rodauth(session: { two_factor_auth_setup: true })
|
|
772
691
|
Rodauth::Rails.rodauth(:admin, params: { "param" => "value" })
|
773
692
|
```
|
774
693
|
|
694
|
+
### Using as a library
|
695
|
+
|
696
|
+
Rodauth offers a `Rodauth.lib` method for configuring Rodauth so that it can be used as a library, instead of routing requests (see [internal_request] feature). This gem provides a `Rodauth::Rails.lib` counterpart that does the same but with Rails integration:
|
697
|
+
|
698
|
+
```rb
|
699
|
+
# app/misc/rodauth_main.rb
|
700
|
+
require "rodauth/rails"
|
701
|
+
require "sequel/core"
|
702
|
+
|
703
|
+
RodauthMain = Rodauth::Rails.lib do
|
704
|
+
enable :create_account, :login, :close_account
|
705
|
+
db Sequel.postgres(extensions: :activerecord_connection, keep_reference: false)
|
706
|
+
# ...
|
707
|
+
end
|
708
|
+
```
|
709
|
+
```rb
|
710
|
+
RodauthMain.create_account(login: "email@example.com", password: "secret123")
|
711
|
+
RodauthMain.login(login: "email@example.com", password: "secret123")
|
712
|
+
RodauthMain.close_account(account_login: "email@example.com")
|
713
|
+
```
|
714
|
+
|
715
|
+
Note that you'll want to skip requiring `rodauth-rails` on Rails boot, so that it doesn't insert the middleware automatically, and remove the initializer.
|
716
|
+
|
717
|
+
```rb
|
718
|
+
# Gemfile
|
719
|
+
gem "rodauth-rails", require: false
|
720
|
+
```
|
721
|
+
|
775
722
|
## Testing
|
776
723
|
|
777
724
|
For system and integration tests, which run the whole middleware stack,
|
@@ -791,13 +738,13 @@ end
|
|
791
738
|
```
|
792
739
|
|
793
740
|
One can write `ActionDispatch::IntegrationTest` test helpers for `login` and
|
794
|
-
`logout` by making requests to the
|
741
|
+
`logout` by making requests to the Rodauth endpoints:
|
795
742
|
|
796
743
|
```rb
|
797
744
|
# test/controllers/articles_controller_test.rb
|
798
745
|
class ArticlesControllerTest < ActionDispatch::IntegrationTest
|
799
|
-
def login(
|
800
|
-
post "/login", params: {
|
746
|
+
def login(email, password)
|
747
|
+
post "/login", params: { email: email, password: password }
|
801
748
|
assert_redirected_to "/"
|
802
749
|
end
|
803
750
|
|
@@ -849,87 +796,48 @@ methods:
|
|
849
796
|
| `rails_controller` | Controller class to use for rendering and CSRF protection. |
|
850
797
|
| `rails_account_model` | Model class connected with the accounts table. |
|
851
798
|
|
799
|
+
```rb
|
800
|
+
class RodauthMain < Rodauth::Rails::Auth
|
801
|
+
configure do
|
802
|
+
rails_controller { Authentication::RodauthController }
|
803
|
+
rails_account_model { Authentication::Account }
|
804
|
+
end
|
805
|
+
end
|
806
|
+
```
|
807
|
+
|
852
808
|
For the list of configuration methods provided by Rodauth, see the [feature
|
853
809
|
documentation].
|
854
810
|
|
855
811
|
### Defining custom methods
|
856
812
|
|
857
813
|
All Rodauth configuration methods are just syntax sugar for defining instance
|
858
|
-
methods on the auth class. You can also define your own custom methods
|
859
|
-
auth class:
|
814
|
+
methods on the auth class. You can also define your own custom methods:
|
860
815
|
|
861
816
|
```rb
|
862
817
|
class RodauthMain < Rodauth::Rails::Auth
|
863
818
|
configure do
|
864
|
-
# ...
|
865
819
|
password_match? { |password| ldap_valid?(password) }
|
866
|
-
# ...
|
867
820
|
end
|
868
821
|
|
869
|
-
|
870
|
-
|
871
|
-
db[:account_identities].where(account_id: account_id).all
|
822
|
+
def admin?
|
823
|
+
rails_account.admin?
|
872
824
|
end
|
873
825
|
|
874
826
|
private
|
875
827
|
|
876
|
-
# Example LDAP authentication
|
877
828
|
def ldap_valid?(password)
|
878
829
|
SimpleLdapAuthenticator.valid?(account[:email], password)
|
879
830
|
end
|
880
831
|
end
|
881
832
|
```
|
882
833
|
```rb
|
883
|
-
rodauth.
|
884
|
-
```
|
885
|
-
|
886
|
-
### Rails URL helpers
|
887
|
-
|
888
|
-
Inside Rodauth configuration and the `route` block you can access Rails route
|
889
|
-
helpers through `#rails_routes`:
|
890
|
-
|
891
|
-
```rb
|
892
|
-
# app/misc/rodauth_main.rb
|
893
|
-
class RodauthMain < Rodauth::Rails::Auth
|
894
|
-
configure do
|
895
|
-
login_redirect { rails_routes.activity_path }
|
896
|
-
change_password_redirect { rails_routes.profile_path }
|
897
|
-
change_login_redirect { rails_routes.profile_path }
|
898
|
-
end
|
899
|
-
end
|
900
|
-
```
|
901
|
-
|
902
|
-
### Calling controller methods
|
903
|
-
|
904
|
-
When using Rodauth before/after hooks or generally overriding your Rodauth
|
905
|
-
configuration, in some cases you might want to call methods defined on your
|
906
|
-
controllers. You can do so with `rails_controller_eval`, for example:
|
907
|
-
|
908
|
-
```rb
|
909
|
-
# app/controllers/application_controller.rb
|
910
|
-
class ApplicationController < ActionController::Base
|
911
|
-
private
|
912
|
-
def setup_tracking(account_id)
|
913
|
-
# ... some implementation ...
|
914
|
-
end
|
915
|
-
end
|
916
|
-
```
|
917
|
-
```rb
|
918
|
-
# app/misc/rodauth_main.rb
|
919
|
-
class RodauthMain < Rodauth::Rails::Auth
|
920
|
-
configure do
|
921
|
-
after_create_account do
|
922
|
-
rails_controller_eval { setup_tracking(account_id) }
|
923
|
-
end
|
924
|
-
end
|
925
|
-
end
|
834
|
+
rodauth.admin? #=> true
|
926
835
|
```
|
927
836
|
|
928
837
|
### Single-file configuration
|
929
838
|
|
930
|
-
If you would prefer
|
931
|
-
|
932
|
-
anonymous auth class.
|
839
|
+
If you would prefer, you can have all your Rodauth logic contained inside the
|
840
|
+
Rodauth app class:
|
933
841
|
|
934
842
|
```rb
|
935
843
|
# app/misc/rodauth_app.rb
|
@@ -952,6 +860,19 @@ class RodauthApp < Rodauth::Rails::App
|
|
952
860
|
end
|
953
861
|
```
|
954
862
|
|
863
|
+
### Manually inserting middleware
|
864
|
+
|
865
|
+
You can choose to insert the Rodauth middleware somewhere earlier than
|
866
|
+
in front of the Rails router:
|
867
|
+
|
868
|
+
```rb
|
869
|
+
Rodauth::Rails.configure do |config|
|
870
|
+
config.middleware = false # disable auto-insertion
|
871
|
+
end
|
872
|
+
|
873
|
+
Rails.application.config.middleware.insert_before AnotherMiddleware, Rodauth::Rails::Middleware
|
874
|
+
```
|
875
|
+
|
955
876
|
## How it works
|
956
877
|
|
957
878
|
### Rack middleware
|
@@ -966,16 +887,6 @@ $ rails middleware
|
|
966
887
|
# run MyApp::Application.routes
|
967
888
|
```
|
968
889
|
|
969
|
-
It can be inserted at any point in the middleware stack:
|
970
|
-
|
971
|
-
```rb
|
972
|
-
Rodauth::Rails.configure do |config|
|
973
|
-
config.middleware = false # disable auto-insertion
|
974
|
-
end
|
975
|
-
|
976
|
-
Rails.application.config.middleware.insert_before AnotherMiddleware, Rodauth::Rails::Middleware
|
977
|
-
```
|
978
|
-
|
979
890
|
The middleware retrieves the Rodauth app via `Rodauth::Rails.app`, which is
|
980
891
|
specified as a string to keep the class autoloadable and reloadable in
|
981
892
|
development.
|
@@ -1227,12 +1138,12 @@ conduct](CODE_OF_CONDUCT.md).
|
|
1227
1138
|
[sms_codes]: http://rodauth.jeremyevans.net/rdoc/files/doc/sms_codes_rdoc.html
|
1228
1139
|
[recovery_codes]: http://rodauth.jeremyevans.net/rdoc/files/doc/recovery_codes_rdoc.html
|
1229
1140
|
[webauthn]: http://rodauth.jeremyevans.net/rdoc/files/doc/webauthn_rdoc.html
|
1141
|
+
[webauthn_login]: http://rodauth.jeremyevans.net/rdoc/files/doc/webauthn_login_rdoc.html
|
1230
1142
|
[json]: http://rodauth.jeremyevans.net/rdoc/files/doc/json_rdoc.html
|
1231
1143
|
[jwt]: http://rodauth.jeremyevans.net/rdoc/files/doc/jwt_rdoc.html
|
1232
1144
|
[email_auth]: http://rodauth.jeremyevans.net/rdoc/files/doc/email_auth_rdoc.html
|
1233
1145
|
[audit_logging]: http://rodauth.jeremyevans.net/rdoc/files/doc/audit_logging_rdoc.html
|
1234
1146
|
[password protection]: https://github.com/jeremyevans/rodauth#label-Password+Hash+Access+Via+Database+Functions
|
1235
|
-
[bruteforce tokens]: https://github.com/jeremyevans/rodauth#label-Tokens
|
1236
1147
|
[password_complexity]: http://rodauth.jeremyevans.net/rdoc/files/doc/password_complexity_rdoc.html
|
1237
1148
|
[disallow_password_reuse]: http://rodauth.jeremyevans.net/rdoc/files/doc/disallow_password_reuse_rdoc.html
|
1238
1149
|
[password_expiration]: http://rodauth.jeremyevans.net/rdoc/files/doc/password_expiration_rdoc.html
|
@@ -1247,3 +1158,4 @@ conduct](CODE_OF_CONDUCT.md).
|
|
1247
1158
|
[Turbo]: https://turbo.hotwired.dev/
|
1248
1159
|
[rodauth-model]: https://github.com/janko/rodauth-model
|
1249
1160
|
[JSON API]: https://github.com/janko/rodauth-rails/wiki/JSON-API
|
1161
|
+
[inheritance]: http://rodauth.jeremyevans.net/rdoc/files/doc/guides/share_configuration_rdoc.html
|