rodauth-rails 0.7.0 → 0.9.1
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/CHANGELOG.md +38 -0
- data/README.md +349 -50
- data/lib/generators/rodauth/install_generator.rb +9 -4
- data/lib/generators/rodauth/migration/base.erb +2 -2
- data/lib/generators/rodauth/templates/app/lib/rodauth_app.rb +23 -24
- data/lib/rodauth/rails.rb +10 -0
- data/lib/rodauth/rails/app.rb +8 -6
- data/lib/rodauth/rails/app/flash.rb +5 -3
- data/lib/rodauth/rails/feature.rb +35 -15
- data/lib/rodauth/rails/tasks.rake +1 -1
- data/lib/rodauth/rails/version.rb +1 -1
- data/rodauth-rails.gemspec +3 -1
- metadata +22 -9
- data/lib/rodauth/features/rails.rb +0 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: b8f8aec1dbdc745a530aabec0d63bc2681499dd36f8185faed9ea09e7184636e
|
|
4
|
+
data.tar.gz: fbc5a75976a922978a6e37fee3bef8e7f04bb0a9a324066afdf79172b33f00e9
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 89d2f6ad377ba8e3f18bc747c3bfdf53e97c1a29f2731036987e5f7c1fde14db89732cda2d09026a153d81eabe26e51e021a129f02517d4d5582fcaf392876ca
|
|
7
|
+
data.tar.gz: 648b1297a9569b436113b5921a9ae37944d808ed42a03ef57a75452a74143dcc493e7d9c34a12f31f780745db5d2b1365d5a7b602dfa303571961730566852f4
|
data/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,41 @@
|
|
|
1
|
+
## 0.9.1 (2021-02-10)
|
|
2
|
+
|
|
3
|
+
* Fix flash integration being loaded for API-only apps and causing an error (@dmitryzuev)
|
|
4
|
+
|
|
5
|
+
* Change account status column default to `unverified` in migration to match Rodauth's default (@basabin54)
|
|
6
|
+
|
|
7
|
+
## 0.9.0 (2021-02-07)
|
|
8
|
+
|
|
9
|
+
* Load Roda's JSON support by default, so that enabling `json`/`jwt` feature is all that's needed (@janko)
|
|
10
|
+
|
|
11
|
+
* Bump Rodauth dependency to 2.9+ (@janko)
|
|
12
|
+
|
|
13
|
+
* Add `--json` option for `rodauth:install` generator for configuring `json` feature (@janko)
|
|
14
|
+
|
|
15
|
+
* Add `--jwt` option for `rodauth:install` generator for configuring `jwt` feature (@janko)
|
|
16
|
+
|
|
17
|
+
* Remove the `--api` option from `rodauth:install` generator (@janko)
|
|
18
|
+
|
|
19
|
+
## 0.8.2 (2021-01-10)
|
|
20
|
+
|
|
21
|
+
* Reset Rails session on `#clear_session`, protecting from potential session fixation attacks (@janko)
|
|
22
|
+
|
|
23
|
+
## 0.8.1 (2021-01-04)
|
|
24
|
+
|
|
25
|
+
* Fix blank email body when `json: true` and `ActionController::API` descendant are used (@janko)
|
|
26
|
+
|
|
27
|
+
* Make view and email rendering work when there are multiple configurations and one is `json: :only` (@janko)
|
|
28
|
+
|
|
29
|
+
* Don't attempt to protect against forgery when `ActionController::API` descendant is used (@janko)
|
|
30
|
+
|
|
31
|
+
* Mark content of rodauth built-in partials as HTML-safe (@janko)
|
|
32
|
+
|
|
33
|
+
## 0.8.0 (2021-01-03)
|
|
34
|
+
|
|
35
|
+
* Add `--api` option to `rodauth:install` generator for choosing JSON-only configuration (@janko)
|
|
36
|
+
|
|
37
|
+
* Don't blow up when a Rodauth request is made using an unsupported HTTP verb (@janko)
|
|
38
|
+
|
|
1
39
|
## 0.7.0 (2020-11-27)
|
|
2
40
|
|
|
3
41
|
* Add `#rails_controller_eval` method for running code in context of a controller instance (@janko)
|
data/README.md
CHANGED
|
@@ -2,6 +2,35 @@
|
|
|
2
2
|
|
|
3
3
|
Provides Rails integration for the [Rodauth] authentication framework.
|
|
4
4
|
|
|
5
|
+
## Table of contents
|
|
6
|
+
|
|
7
|
+
* [Resources](#resources)
|
|
8
|
+
* [Why Rodauth?](#why-rodauth)
|
|
9
|
+
* [Upgrading](#upgrading)
|
|
10
|
+
* [Installation](#installation)
|
|
11
|
+
* [Usage](#usage)
|
|
12
|
+
- [Routes](#routes)
|
|
13
|
+
- [Current account](#current-account)
|
|
14
|
+
- [Requiring authentication](#requiring-authentication)
|
|
15
|
+
- [Views](#views)
|
|
16
|
+
- [Mailer](#mailer)
|
|
17
|
+
- [Migrations](#migrations)
|
|
18
|
+
- [Multiple configurations](#multiple-configurations)
|
|
19
|
+
- [Calling controller methods](#calling-controller-methods)
|
|
20
|
+
- [Rodauth instance](#rodauth-instance)
|
|
21
|
+
* [How it works](#how-it-works)
|
|
22
|
+
- [Middleware](#middleware)
|
|
23
|
+
- [App](#app)
|
|
24
|
+
- [Sequel](#sequel)
|
|
25
|
+
* [JSON API](#json-api)
|
|
26
|
+
* [OmniAuth](#omniauth)
|
|
27
|
+
* [Configuring](#configuring)
|
|
28
|
+
* [Custom extensions](#custom-extensions)
|
|
29
|
+
* [Testing](#testing)
|
|
30
|
+
* [Rodauth defaults](#rodauth-defaults)
|
|
31
|
+
- [Database functions](#database-functions)
|
|
32
|
+
- [Account statuses](#account-statuses)
|
|
33
|
+
|
|
5
34
|
## Resources
|
|
6
35
|
|
|
7
36
|
Useful links:
|
|
@@ -12,7 +41,25 @@ Useful links:
|
|
|
12
41
|
Articles:
|
|
13
42
|
|
|
14
43
|
* [Rodauth: A Refreshing Authentication Solution for Ruby](https://janko.io/rodauth-a-refreshing-authentication-solution-for-ruby/)
|
|
15
|
-
* [Adding Authentication in Rails
|
|
44
|
+
* [Adding Authentication in Rails with Rodauth](https://janko.io/adding-authentication-in-rails-with-rodauth/)
|
|
45
|
+
* [Adding Multifactor Authentication in Rails with Rodauth](https://janko.io/adding-multifactor-authentication-in-rails-with-rodauth/)
|
|
46
|
+
|
|
47
|
+
## Why Rodauth?
|
|
48
|
+
|
|
49
|
+
There are already several popular authentication solutions for Rails (Devise,
|
|
50
|
+
Sorcery, Clearance, Authlogic), so why would you choose Rodauth? Here are some
|
|
51
|
+
of the advantages that stand out for me:
|
|
52
|
+
|
|
53
|
+
* multifactor authentication ([TOTP][otp], [SMS codes][sms_codes], [recovery codes][recovery_codes], [WebAuthn][webauthn])
|
|
54
|
+
* standardized [JSON API support][json] for every feature (including [JWT][jwt])
|
|
55
|
+
* 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])
|
|
56
|
+
* [email authentication][email_auth] (aka "passwordless")
|
|
57
|
+
* [audit logging][audit_logging] (for any action)
|
|
58
|
+
* ability to protect password hashes even in case of SQL injection ([more details][password protection])
|
|
59
|
+
* additional bruteforce protection for tokens ([more details][bruteforce tokens])
|
|
60
|
+
* uniform configuration DSL (any setting can be static or dynamic)
|
|
61
|
+
* consistent before/after hooks around everything
|
|
62
|
+
* dedicated object encapsulating all authentication logic
|
|
16
63
|
|
|
17
64
|
## Upgrading
|
|
18
65
|
|
|
@@ -21,14 +68,14 @@ Articles:
|
|
|
21
68
|
Starting from version 0.7.0, rodauth-rails now correctly detects Rails
|
|
22
69
|
application's `secret_key_base` when setting default `hmac_secret`, including
|
|
23
70
|
when it's set via credentials or `$SECRET_KEY_BASE` environment variable. This
|
|
24
|
-
means authentication will be more secure by default, and Rodauth
|
|
25
|
-
require `hmac_secret` should now work automatically as well.
|
|
71
|
+
means that your authentication will now be more secure by default, and Rodauth
|
|
72
|
+
features that require `hmac_secret` should now work automatically as well.
|
|
26
73
|
|
|
27
74
|
However, if you've already been using rodauth-rails in production, where the
|
|
28
75
|
`secret_key_base` is set via credentials or environment variable and `hmac_secret`
|
|
29
76
|
was not explicitly set, the fact that your authentication will now start using
|
|
30
77
|
HMACs has backwards compatibility considerations. See the [Rodauth
|
|
31
|
-
documentation]
|
|
78
|
+
documentation][hmac] for instructions on how to safely transition, or just set
|
|
32
79
|
`hmac_secret nil` in your Rodauth configuration.
|
|
33
80
|
|
|
34
81
|
## Installation
|
|
@@ -36,7 +83,7 @@ documentation](hmac) for instructions on how to safely transition, or just set
|
|
|
36
83
|
Add the gem to your Gemfile:
|
|
37
84
|
|
|
38
85
|
```rb
|
|
39
|
-
gem "rodauth-rails", "~> 0.
|
|
86
|
+
gem "rodauth-rails", "~> 0.9"
|
|
40
87
|
|
|
41
88
|
# gem "jwt", require: false # for JWT feature
|
|
42
89
|
# gem "rotp", require: false # for OTP feature
|
|
@@ -48,10 +95,19 @@ Then run `bundle install`.
|
|
|
48
95
|
|
|
49
96
|
Next, run the install generator:
|
|
50
97
|
|
|
51
|
-
```
|
|
98
|
+
```sh
|
|
52
99
|
$ rails generate rodauth:install
|
|
53
100
|
```
|
|
54
101
|
|
|
102
|
+
Or if you want Rodauth endpoints to be exposed via JSON API:
|
|
103
|
+
|
|
104
|
+
```sh
|
|
105
|
+
$ rails generate rodauth:install --json # regular authentication using the Rails session
|
|
106
|
+
# or
|
|
107
|
+
$ rails generate rodauth:install --jwt # token authentication via the "Authorization" header
|
|
108
|
+
$ bundle add jwt
|
|
109
|
+
```
|
|
110
|
+
|
|
55
111
|
The generator will create the following files:
|
|
56
112
|
|
|
57
113
|
* Rodauth migration at `db/migrate/*_create_rodauth.rb`
|
|
@@ -185,14 +241,12 @@ Using this information, we could add some basic authentication links to our
|
|
|
185
241
|
navigation header:
|
|
186
242
|
|
|
187
243
|
```erb
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
<% end %>
|
|
195
|
-
</ul>
|
|
244
|
+
<% if rodauth.logged_in? %>
|
|
245
|
+
<%= link_to "Sign out", rodauth.logout_path, method: :post %>
|
|
246
|
+
<% else %>
|
|
247
|
+
<%= link_to "Sign in", rodauth.login_path %>
|
|
248
|
+
<%= link_to "Sign up", rodauth.create_account_path %>
|
|
249
|
+
<% end %>
|
|
196
250
|
```
|
|
197
251
|
|
|
198
252
|
These routes are fully functional, feel free to visit them and interact with the
|
|
@@ -208,7 +262,7 @@ retrieves the corresponding account record:
|
|
|
208
262
|
```rb
|
|
209
263
|
# app/controllers/application_controller.rb
|
|
210
264
|
class ApplicationController < ActionController::Base
|
|
211
|
-
before_action :current_account, if: -> { rodauth.
|
|
265
|
+
before_action :current_account, if: -> { rodauth.logged_in? }
|
|
212
266
|
|
|
213
267
|
private
|
|
214
268
|
|
|
@@ -382,7 +436,7 @@ $ rails generate rodauth:mailer
|
|
|
382
436
|
```
|
|
383
437
|
|
|
384
438
|
This will create a `RodauthMailer` with the associated mailer views in
|
|
385
|
-
`app/views/rodauth_mailer` directory
|
|
439
|
+
`app/views/rodauth_mailer` directory:
|
|
386
440
|
|
|
387
441
|
```rb
|
|
388
442
|
# app/mailers/rodauth_mailer.rb
|
|
@@ -434,9 +488,9 @@ end
|
|
|
434
488
|
```
|
|
435
489
|
|
|
436
490
|
This approach can be used even if you're using a 3rd-party service for
|
|
437
|
-
transactional emails, where emails are sent via
|
|
438
|
-
|
|
439
|
-
|
|
491
|
+
transactional emails, where emails are sent via HTTP instead of SMTP. Whatever
|
|
492
|
+
the `create_*_email` block returns will be passed to `send_email`, so you can
|
|
493
|
+
be creative.
|
|
440
494
|
|
|
441
495
|
### Migrations
|
|
442
496
|
|
|
@@ -458,36 +512,41 @@ class CreateRodauthOtpSmsCodesRecoveryCodes < ActiveRecord::Migration
|
|
|
458
512
|
end
|
|
459
513
|
```
|
|
460
514
|
|
|
461
|
-
###
|
|
515
|
+
### Multiple configurations
|
|
462
516
|
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
```rb
|
|
467
|
-
gem "jwt"
|
|
468
|
-
```
|
|
469
|
-
|
|
470
|
-
The following configuration will enable the Rodauth endpoints to be accessed
|
|
471
|
-
via JSON requests (in addition to HTML requests):
|
|
517
|
+
If you need to handle multiple types of accounts that require different
|
|
518
|
+
authentication logic, you can create different configurations for them:
|
|
472
519
|
|
|
473
520
|
```rb
|
|
474
521
|
# app/lib/rodauth_app.rb
|
|
475
522
|
class RodauthApp < Rodauth::Rails::App
|
|
476
|
-
|
|
523
|
+
# primary configuration
|
|
524
|
+
configure do
|
|
477
525
|
# ...
|
|
478
|
-
|
|
479
|
-
|
|
526
|
+
end
|
|
527
|
+
|
|
528
|
+
# alternative configuration
|
|
529
|
+
configure(:admin) do
|
|
530
|
+
# ... enable features ...
|
|
531
|
+
prefix "/admin"
|
|
532
|
+
session_key_prefix "admin_"
|
|
533
|
+
remember_cookie_key "_admin_remember" # if using remember feature
|
|
534
|
+
# ...
|
|
535
|
+
end
|
|
536
|
+
|
|
537
|
+
route do |r|
|
|
538
|
+
r.rodauth
|
|
539
|
+
r.on("admin") { r.rodauth(:admin) }
|
|
480
540
|
# ...
|
|
481
541
|
end
|
|
482
542
|
end
|
|
483
543
|
```
|
|
484
544
|
|
|
485
|
-
|
|
486
|
-
Rails app is in API-only mode, instead of `json: true` pass `json: :only` to
|
|
487
|
-
the configure method.
|
|
545
|
+
Then in your application you can reference the secondary Rodauth instance:
|
|
488
546
|
|
|
489
|
-
|
|
490
|
-
|
|
547
|
+
```rb
|
|
548
|
+
rodauth(:admin).login_path #=> "/admin/login"
|
|
549
|
+
```
|
|
491
550
|
|
|
492
551
|
### Calling controller methods
|
|
493
552
|
|
|
@@ -522,7 +581,7 @@ Rodauth operations outside of the request context. rodauth-rails gives you the
|
|
|
522
581
|
ability to retrieve the Rodauth instance:
|
|
523
582
|
|
|
524
583
|
```rb
|
|
525
|
-
rodauth = Rodauth::Rails.rodauth # or Rodauth::Rails.rodauth(:
|
|
584
|
+
rodauth = Rodauth::Rails.rodauth # or Rodauth::Rails.rodauth(:admin)
|
|
526
585
|
|
|
527
586
|
rodauth.login_url #=> "https://example.com/login"
|
|
528
587
|
rodauth.account_from_login("user@example.com") # loads user by email
|
|
@@ -553,8 +612,8 @@ The Rodauth app stores the `Rodauth::Auth` instance in the Rack env hash, which
|
|
|
553
612
|
is then available in your Rails app:
|
|
554
613
|
|
|
555
614
|
```rb
|
|
556
|
-
request.env["rodauth"]
|
|
557
|
-
request.env["rodauth.
|
|
615
|
+
request.env["rodauth"] #=> #<Rodauth::Auth>
|
|
616
|
+
request.env["rodauth.admin"] #=> #<Rodauth::Auth> (if using multiple configurations)
|
|
558
617
|
```
|
|
559
618
|
|
|
560
619
|
For convenience, this object can be accessed via the `#rodauth` method in views
|
|
@@ -563,14 +622,14 @@ and controllers:
|
|
|
563
622
|
```rb
|
|
564
623
|
class MyController < ApplicationController
|
|
565
624
|
def my_action
|
|
566
|
-
rodauth
|
|
567
|
-
rodauth(:
|
|
625
|
+
rodauth #=> #<Rodauth::Auth>
|
|
626
|
+
rodauth(:admin) #=> #<Rodauth::Auth> (if using multiple configurations)
|
|
568
627
|
end
|
|
569
628
|
end
|
|
570
629
|
```
|
|
571
630
|
```erb
|
|
572
|
-
<% rodauth
|
|
573
|
-
<% rodauth(:
|
|
631
|
+
<% rodauth #=> #<Rodauth::Auth> %>
|
|
632
|
+
<% rodauth(:admin) #=> #<Rodauth::Auth> (if using multiple configurations) %>
|
|
574
633
|
```
|
|
575
634
|
|
|
576
635
|
### App
|
|
@@ -585,13 +644,38 @@ integration for Rodauth:
|
|
|
585
644
|
* runs Action Controller callbacks & rescue handlers around Rodauth actions
|
|
586
645
|
* uses Action Mailer for sending emails
|
|
587
646
|
|
|
588
|
-
The `configure
|
|
647
|
+
The `configure` method wraps configuring the Rodauth plugin, forwarding
|
|
589
648
|
any additional [plugin options].
|
|
590
649
|
|
|
591
650
|
```rb
|
|
592
|
-
|
|
593
|
-
configure
|
|
594
|
-
configure(:
|
|
651
|
+
class RodauthApp < Rodauth::Rails::App
|
|
652
|
+
configure { ... } # defining default Rodauth configuration
|
|
653
|
+
configure(json: true) { ... } # passing options to the Rodauth plugin
|
|
654
|
+
configure(:admin) { ... } # defining multiple Rodauth configurations
|
|
655
|
+
end
|
|
656
|
+
```
|
|
657
|
+
|
|
658
|
+
The `route` block is provided by Roda, and it's called on each request before
|
|
659
|
+
it reaches the Rails router.
|
|
660
|
+
|
|
661
|
+
```rb
|
|
662
|
+
class RodauthApp < Rodauth::Rails::App
|
|
663
|
+
route do |r|
|
|
664
|
+
# ... called before each request ...
|
|
665
|
+
end
|
|
666
|
+
end
|
|
667
|
+
```
|
|
668
|
+
|
|
669
|
+
Since `Rodauth::Rails::App` is just a Roda subclass, you can do anything you
|
|
670
|
+
would with a Roda app, such as loading additional Roda plugins:
|
|
671
|
+
|
|
672
|
+
```rb
|
|
673
|
+
class RodauthApp < Rodauth::Rails::App
|
|
674
|
+
plugin :request_headers # easier access to request headers
|
|
675
|
+
plugin :typecast_params # methods for conversion of request params
|
|
676
|
+
plugin :default_headers, { "Foo" => "Bar" }
|
|
677
|
+
# ...
|
|
678
|
+
end
|
|
595
679
|
```
|
|
596
680
|
|
|
597
681
|
### Sequel
|
|
@@ -602,11 +686,174 @@ function calls).
|
|
|
602
686
|
|
|
603
687
|
If ActiveRecord is used in the application, the `rodauth:install` generator
|
|
604
688
|
will have automatically configured Sequel to reuse ActiveRecord's database
|
|
605
|
-
connection
|
|
689
|
+
connection, using the [sequel-activerecord_connection] gem.
|
|
606
690
|
|
|
607
691
|
This means that, from the usage perspective, Sequel can be considered just
|
|
608
692
|
as an implementation detail of Rodauth.
|
|
609
693
|
|
|
694
|
+
## JSON API
|
|
695
|
+
|
|
696
|
+
To make Rodauth endpoints accessible via JSON API, enable the [`json`][json]
|
|
697
|
+
feature:
|
|
698
|
+
|
|
699
|
+
```rb
|
|
700
|
+
# app/lib/rodauth_app.rb
|
|
701
|
+
class RodauthApp < Rodauth::Rails::App
|
|
702
|
+
configure do
|
|
703
|
+
# ...
|
|
704
|
+
enable :json
|
|
705
|
+
only_json? true # accept only JSON requests
|
|
706
|
+
# ...
|
|
707
|
+
end
|
|
708
|
+
end
|
|
709
|
+
```
|
|
710
|
+
|
|
711
|
+
This will store account session data into the Rails session. If you rather want
|
|
712
|
+
stateless token-based authentication via the `Authorization` header, enable the
|
|
713
|
+
[`jwt`][jwt] feature (which builds on top of the `json` feature) and add the
|
|
714
|
+
[JWT gem] to the Gemfile:
|
|
715
|
+
|
|
716
|
+
```sh
|
|
717
|
+
$ bundle add jwt
|
|
718
|
+
```
|
|
719
|
+
```rb
|
|
720
|
+
# app/lib/rodauth_app.rb
|
|
721
|
+
class RodauthApp < Rodauth::Rails::App
|
|
722
|
+
configure do
|
|
723
|
+
# ...
|
|
724
|
+
enable :jwt
|
|
725
|
+
jwt_secret "<YOUR_SECRET_KEY>" # store the JWT secret in a safe place
|
|
726
|
+
only_json? true # accept only JSON requests
|
|
727
|
+
# ...
|
|
728
|
+
end
|
|
729
|
+
end
|
|
730
|
+
```
|
|
731
|
+
|
|
732
|
+
If you need Cross-Origin Resource Sharing and/or JWT refresh tokens, enable the
|
|
733
|
+
corresponding Rodauth features and create the necessary tables:
|
|
734
|
+
|
|
735
|
+
```sh
|
|
736
|
+
$ rails generate rodauth:migration jwt_refresh
|
|
737
|
+
$ rails db:migrate
|
|
738
|
+
```
|
|
739
|
+
```rb
|
|
740
|
+
# app/lib/rodauth_app.rb
|
|
741
|
+
class RodauthApp < Rodauth::Rails::App
|
|
742
|
+
configure do
|
|
743
|
+
# ...
|
|
744
|
+
enable :jwt, :jwt_cors, :jwt_refresh
|
|
745
|
+
# ...
|
|
746
|
+
end
|
|
747
|
+
end
|
|
748
|
+
```
|
|
749
|
+
|
|
750
|
+
## OmniAuth
|
|
751
|
+
|
|
752
|
+
While Rodauth doesn't yet come with [OmniAuth] integration, we can build one
|
|
753
|
+
ourselves using the existing Rodauth API.
|
|
754
|
+
|
|
755
|
+
In order to allow the user to login via multiple external providers, let's
|
|
756
|
+
create an `account_identities` table that will have a many-to-one relationship
|
|
757
|
+
with the `accounts` table:
|
|
758
|
+
|
|
759
|
+
```sh
|
|
760
|
+
$ rails generate model AccountIdentity
|
|
761
|
+
```
|
|
762
|
+
```rb
|
|
763
|
+
# db/migrate/*_create_account_identities.rb
|
|
764
|
+
class CreateAccountIdentities < ActiveRecord::Migration
|
|
765
|
+
def change
|
|
766
|
+
create_table :account_identities do |t|
|
|
767
|
+
t.references :account, null: false, foreign_key: { on_delete: :cascade }
|
|
768
|
+
t.string :provider, null: false
|
|
769
|
+
t.string :uid, null: false
|
|
770
|
+
t.jsonb :info, null: false, default: {} # adjust JSON column type for your database
|
|
771
|
+
|
|
772
|
+
t.timestamps
|
|
773
|
+
|
|
774
|
+
t.index [:provider, :uid], unique: true
|
|
775
|
+
end
|
|
776
|
+
end
|
|
777
|
+
end
|
|
778
|
+
```
|
|
779
|
+
```rb
|
|
780
|
+
# app/models/account_identity.rb
|
|
781
|
+
class AcccountIdentity < ApplicationRecord
|
|
782
|
+
belongs_to :account
|
|
783
|
+
end
|
|
784
|
+
```
|
|
785
|
+
```rb
|
|
786
|
+
# app/models/account.rb
|
|
787
|
+
class Account < ApplicationRecord
|
|
788
|
+
has_many :identities, class_name: "AccountIdentity"
|
|
789
|
+
end
|
|
790
|
+
```
|
|
791
|
+
|
|
792
|
+
Let's assume we want to implement Facebook login, and have added the
|
|
793
|
+
corresponding OmniAuth strategy to the middleware stack, together with an
|
|
794
|
+
authorization link on the login form:
|
|
795
|
+
|
|
796
|
+
```rb
|
|
797
|
+
Rails.application.config.middleware.use OmniAuth::Builder do
|
|
798
|
+
provider :facebook, ENV["FACEBOOK_APP_ID"], ENV["FACEBOOK_APP_SECRET"],
|
|
799
|
+
scope: "email", callback_path: "/auth/facebook/callback"
|
|
800
|
+
end
|
|
801
|
+
```
|
|
802
|
+
```erb
|
|
803
|
+
<%= link_to "Login via Facebook", "/auth/facebook" %>
|
|
804
|
+
```
|
|
805
|
+
|
|
806
|
+
Let's implement the OmniAuth callback endpoint on our Rodauth controller:
|
|
807
|
+
|
|
808
|
+
```rb
|
|
809
|
+
# config/routes.rb
|
|
810
|
+
Rails.application.routes.draw do
|
|
811
|
+
# ...
|
|
812
|
+
get "/auth/:provider/callback", to: "rodauth#omniauth"
|
|
813
|
+
end
|
|
814
|
+
```
|
|
815
|
+
```rb
|
|
816
|
+
# app/controllres/rodauth_controller.rb
|
|
817
|
+
class RodauthController < ApplicationController
|
|
818
|
+
def omniauth
|
|
819
|
+
auth = request.env["omniauth.auth"]
|
|
820
|
+
|
|
821
|
+
# attempt to find existing identity directly
|
|
822
|
+
identity = AccountIdentity.find_by(provider: auth["provider"], uid: auth["uid"])
|
|
823
|
+
|
|
824
|
+
if identity
|
|
825
|
+
# update any external info changes
|
|
826
|
+
identity.update!(info: auth["info"])
|
|
827
|
+
# set account from identity
|
|
828
|
+
account = identity.account
|
|
829
|
+
end
|
|
830
|
+
|
|
831
|
+
# attempt to find an existing account by email
|
|
832
|
+
account ||= Account.find_by(email: auth["info"]["email"])
|
|
833
|
+
|
|
834
|
+
# disallow login if account is not verified
|
|
835
|
+
if account && account.status != rodauth.account_open_status_value
|
|
836
|
+
redirect_to rodauth.login_path, alert: rodauth.unverified_account_message
|
|
837
|
+
return
|
|
838
|
+
end
|
|
839
|
+
|
|
840
|
+
# create new account if it doesn't exist
|
|
841
|
+
unless account
|
|
842
|
+
account = Account.create!(email: auth["info"]["email"], status: rodauth.account_open_status_value)
|
|
843
|
+
end
|
|
844
|
+
|
|
845
|
+
# create new identity if it doesn't exist
|
|
846
|
+
unless identity
|
|
847
|
+
account.identities.create!(provider: auth["provider"], uid: auth["uid"], info: auth["info"])
|
|
848
|
+
end
|
|
849
|
+
|
|
850
|
+
# login with Rodauth
|
|
851
|
+
rodauth.account_from_login(account.email)
|
|
852
|
+
rodauth.login("omniauth")
|
|
853
|
+
end
|
|
854
|
+
end
|
|
855
|
+
```
|
|
856
|
+
|
|
610
857
|
## Configuring
|
|
611
858
|
|
|
612
859
|
For the list of configuration methods provided by Rodauth, see the [feature
|
|
@@ -640,6 +887,39 @@ Rodauth::Rails.configure do |config|
|
|
|
640
887
|
end
|
|
641
888
|
```
|
|
642
889
|
|
|
890
|
+
## Custom extensions
|
|
891
|
+
|
|
892
|
+
When developing custom extensions for Rodauth inside your Rails project, it's
|
|
893
|
+
better to use plain modules (at least in the beginning), because Rodauth
|
|
894
|
+
feature design doesn't yet support Zeitwerk reloading well. Here is
|
|
895
|
+
an example of an LDAP authentication extension that uses the
|
|
896
|
+
[simple_ldap_authenticator] gem.
|
|
897
|
+
|
|
898
|
+
```rb
|
|
899
|
+
# app/lib/rodauth_ldap.rb
|
|
900
|
+
module RodauthLdap
|
|
901
|
+
def require_bcrypt?
|
|
902
|
+
false
|
|
903
|
+
end
|
|
904
|
+
|
|
905
|
+
def password_match?(password)
|
|
906
|
+
SimpleLdapAuthenticator.valid?(account[:email], password)
|
|
907
|
+
end
|
|
908
|
+
end
|
|
909
|
+
```
|
|
910
|
+
```rb
|
|
911
|
+
# app/lib/rodauth_app.rb
|
|
912
|
+
class RodauthApp < Rodauth::Rails::App
|
|
913
|
+
configure do
|
|
914
|
+
# ...
|
|
915
|
+
auth_class_eval do
|
|
916
|
+
include RodauthLdap
|
|
917
|
+
end
|
|
918
|
+
# ...
|
|
919
|
+
end
|
|
920
|
+
end
|
|
921
|
+
```
|
|
922
|
+
|
|
643
923
|
## Testing
|
|
644
924
|
|
|
645
925
|
If you're writing system tests, it's generally better to go through the actual
|
|
@@ -712,6 +992,8 @@ Rodauth method for creating database functions:
|
|
|
712
992
|
|
|
713
993
|
```rb
|
|
714
994
|
# db/migrate/*_create_rodauth_database_functions.rb
|
|
995
|
+
require "rodauth/migrations"
|
|
996
|
+
|
|
715
997
|
class CreateRodauthDatabaseFunctions < ActiveRecord::Migration
|
|
716
998
|
def up
|
|
717
999
|
Rodauth.create_database_authentication_functions(DB)
|
|
@@ -776,7 +1058,6 @@ conduct](https://github.com/janko/rodauth-rails/blob/master/CODE_OF_CONDUCT.md).
|
|
|
776
1058
|
[Rodauth]: https://github.com/jeremyevans/rodauth
|
|
777
1059
|
[Sequel]: https://github.com/jeremyevans/sequel
|
|
778
1060
|
[feature documentation]: http://rodauth.jeremyevans.net/documentation.html
|
|
779
|
-
[JWT feature]: http://rodauth.jeremyevans.net/rdoc/files/doc/jwt_rdoc.html
|
|
780
1061
|
[JWT gem]: https://github.com/jwt/ruby-jwt
|
|
781
1062
|
[Bootstrap]: https://getbootstrap.com/
|
|
782
1063
|
[Roda]: http://roda.jeremyevans.net/
|
|
@@ -786,3 +1067,21 @@ conduct](https://github.com/janko/rodauth-rails/blob/master/CODE_OF_CONDUCT.md).
|
|
|
786
1067
|
[sequel-activerecord_connection]: https://github.com/janko/sequel-activerecord_connection
|
|
787
1068
|
[plugin options]: http://rodauth.jeremyevans.net/rdoc/files/README_rdoc.html#label-Plugin+Options
|
|
788
1069
|
[hmac]: http://rodauth.jeremyevans.net/rdoc/files/README_rdoc.html#label-HMAC
|
|
1070
|
+
[OmniAuth]: https://github.com/omniauth/omniauth
|
|
1071
|
+
[otp]: http://rodauth.jeremyevans.net/rdoc/files/doc/otp_rdoc.html
|
|
1072
|
+
[sms_codes]: http://rodauth.jeremyevans.net/rdoc/files/doc/sms_codes_rdoc.html
|
|
1073
|
+
[recovery_codes]: http://rodauth.jeremyevans.net/rdoc/files/doc/recovery_codes_rdoc.html
|
|
1074
|
+
[webauthn]: http://rodauth.jeremyevans.net/rdoc/files/doc/webauthn_rdoc.html
|
|
1075
|
+
[json]: http://rodauth.jeremyevans.net/rdoc/files/doc/json_rdoc.html
|
|
1076
|
+
[jwt]: http://rodauth.jeremyevans.net/rdoc/files/doc/jwt_rdoc.html
|
|
1077
|
+
[email_auth]: http://rodauth.jeremyevans.net/rdoc/files/doc/email_auth_rdoc.html
|
|
1078
|
+
[audit_logging]: http://rodauth.jeremyevans.net/rdoc/files/doc/audit_logging_rdoc.html
|
|
1079
|
+
[password protection]: https://github.com/jeremyevans/rodauth#label-Password+Hash+Access+Via+Database+Functions
|
|
1080
|
+
[bruteforce tokens]: https://github.com/jeremyevans/rodauth#label-Tokens
|
|
1081
|
+
[password_complexity]: http://rodauth.jeremyevans.net/rdoc/files/doc/password_complexity_rdoc.html
|
|
1082
|
+
[disallow_password_reuse]: http://rodauth.jeremyevans.net/rdoc/files/doc/disallow_password_reuse_rdoc.html
|
|
1083
|
+
[password_expiration]: http://rodauth.jeremyevans.net/rdoc/files/doc/password_expiration_rdoc.html
|
|
1084
|
+
[session_expiration]: http://rodauth.jeremyevans.net/rdoc/files/doc/session_expiration_rdoc.html
|
|
1085
|
+
[single_session]: http://rodauth.jeremyevans.net/rdoc/files/doc/single_session_rdoc.html
|
|
1086
|
+
[account_expiration]: http://rodauth.jeremyevans.net/rdoc/files/doc/account_expiration_rdoc.html
|
|
1087
|
+
[simple_ldap_authenticator]: https://github.com/jeremyevans/simple_ldap_authenticator
|
|
@@ -13,6 +13,9 @@ module Rodauth
|
|
|
13
13
|
source_root "#{__dir__}/templates"
|
|
14
14
|
namespace "rodauth:install"
|
|
15
15
|
|
|
16
|
+
class_option :json, type: :boolean, desc: "Configure JSON support"
|
|
17
|
+
class_option :jwt, type: :boolean, desc: "Configure JWT support"
|
|
18
|
+
|
|
16
19
|
def create_rodauth_migration
|
|
17
20
|
return unless defined?(ActiveRecord::Base)
|
|
18
21
|
|
|
@@ -74,15 +77,17 @@ module Rodauth
|
|
|
74
77
|
end
|
|
75
78
|
end
|
|
76
79
|
|
|
77
|
-
def
|
|
78
|
-
|
|
80
|
+
def json?
|
|
81
|
+
options[:json]
|
|
82
|
+
end
|
|
79
83
|
|
|
80
|
-
|
|
84
|
+
def jwt?
|
|
85
|
+
options[:jwt] || Rodauth::Rails.api_only?
|
|
81
86
|
end
|
|
82
87
|
|
|
83
88
|
def migration_features
|
|
84
89
|
features = [:base, :reset_password, :verify_account, :verify_login_change]
|
|
85
|
-
features << :remember unless
|
|
90
|
+
features << :remember unless jwt?
|
|
86
91
|
features
|
|
87
92
|
end
|
|
88
93
|
end
|
|
@@ -5,11 +5,11 @@ enable_extension "citext"
|
|
|
5
5
|
create_table :accounts<%= primary_key_type %> do |t|
|
|
6
6
|
<% case activerecord_adapter -%>
|
|
7
7
|
<% when "postgresql" -%>
|
|
8
|
-
t.citext :email, null: false, index: { unique: true, where: "status IN ('
|
|
8
|
+
t.citext :email, null: false, index: { unique: true, where: "status IN ('unverified', 'verified')" }
|
|
9
9
|
<% else -%>
|
|
10
10
|
t.string :email, null: false, index: { unique: true }
|
|
11
11
|
<% end -%>
|
|
12
|
-
t.string :status, null: false, default: "
|
|
12
|
+
t.string :status, null: false, default: "unverified"
|
|
13
13
|
end
|
|
14
14
|
|
|
15
15
|
# Used if storing password hashes in a separate table (default)
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
class RodauthApp < Rodauth::Rails::App
|
|
2
|
-
configure
|
|
2
|
+
configure do
|
|
3
3
|
# List of authentication features that are loaded.
|
|
4
4
|
enable :create_account, :verify_account, :verify_account_grace_period,
|
|
5
|
-
:login, :logout
|
|
5
|
+
:login, :logout<%= ", :remember" unless jwt? %>,
|
|
6
6
|
:reset_password, :change_password, :change_password_notify,
|
|
7
7
|
:change_login, :verify_login_change,
|
|
8
|
-
:close_account
|
|
8
|
+
:close_account<%= ", :json" if json? %><%= ", :jwt" if jwt? %>
|
|
9
9
|
|
|
10
10
|
# See the Rodauth documentation for the list of available config options:
|
|
11
11
|
# http://rodauth.jeremyevans.net/documentation.html
|
|
@@ -14,6 +14,16 @@ class RodauthApp < Rodauth::Rails::App
|
|
|
14
14
|
# The secret key used for hashing public-facing tokens for various features.
|
|
15
15
|
# Defaults to Rails `secret_key_base`, but you can use your own secret key.
|
|
16
16
|
# hmac_secret "<%= SecureRandom.hex(64) %>"
|
|
17
|
+
<% if jwt? -%>
|
|
18
|
+
|
|
19
|
+
# Set JWT secret, which is used to cryptographically protect the token.
|
|
20
|
+
jwt_secret "<%= SecureRandom.hex(64) %>"
|
|
21
|
+
<% end -%>
|
|
22
|
+
<% if json? || jwt? -%>
|
|
23
|
+
|
|
24
|
+
# Accept only JSON requests.
|
|
25
|
+
only_json? true
|
|
26
|
+
<% end -%>
|
|
17
27
|
|
|
18
28
|
# Specify the controller used for view rendering and CSRF verification.
|
|
19
29
|
rails_controller { RodauthController }
|
|
@@ -42,18 +52,6 @@ class RodauthApp < Rodauth::Rails::App
|
|
|
42
52
|
|
|
43
53
|
# Redirect to the app from login and registration pages if already logged in.
|
|
44
54
|
# already_logged_in { redirect login_redirect }
|
|
45
|
-
<% if api_only? -%>
|
|
46
|
-
|
|
47
|
-
# ==> JWT
|
|
48
|
-
# Set JWT secret, which is used to cryptographically protect the token.
|
|
49
|
-
jwt_secret "<%= SecureRandom.hex(64) %>"
|
|
50
|
-
|
|
51
|
-
# Don't require login confirmation param.
|
|
52
|
-
require_login_confirmation? false
|
|
53
|
-
|
|
54
|
-
# Don't require password confirmation param.
|
|
55
|
-
require_password_confirmation? false
|
|
56
|
-
<% end -%>
|
|
57
55
|
|
|
58
56
|
# ==> Emails
|
|
59
57
|
# Uncomment the lines below once you've imported mailer views.
|
|
@@ -80,14 +78,14 @@ class RodauthApp < Rodauth::Rails::App
|
|
|
80
78
|
# db.after_commit { email.deliver_later }
|
|
81
79
|
# end
|
|
82
80
|
|
|
83
|
-
# In the meantime you can tweak settings for emails created by Rodauth
|
|
81
|
+
# In the meantime, you can tweak settings for emails created by Rodauth.
|
|
84
82
|
# email_subject_prefix "[MyApp] "
|
|
85
83
|
# email_from "noreply@myapp.com"
|
|
86
84
|
# send_email(&:deliver_later)
|
|
87
85
|
# reset_password_email_body { "Click here to reset your password: #{reset_password_email_link}" }
|
|
88
86
|
|
|
89
87
|
# ==> Flash
|
|
90
|
-
<% unless
|
|
88
|
+
<% unless json? || jwt? -%>
|
|
91
89
|
# Match flash keys with ones already used in the Rails app.
|
|
92
90
|
# flash_notice_key :success # default is :notice
|
|
93
91
|
# flash_error_key :error # default is :alert
|
|
@@ -107,7 +105,7 @@ class RodauthApp < Rodauth::Rails::App
|
|
|
107
105
|
|
|
108
106
|
# Change minimum number of password characters required when creating an account.
|
|
109
107
|
# password_minimum_length 8
|
|
110
|
-
<% unless
|
|
108
|
+
<% unless jwt? -%>
|
|
111
109
|
|
|
112
110
|
# ==> Remember Feature
|
|
113
111
|
# Remember all logged in users.
|
|
@@ -128,13 +126,14 @@ class RodauthApp < Rodauth::Rails::App
|
|
|
128
126
|
|
|
129
127
|
# Perform additional actions after the account is created.
|
|
130
128
|
# after_create_account do
|
|
131
|
-
# Profile.create!(account_id:
|
|
129
|
+
# Profile.create!(account_id: account_id, name: param("name"))
|
|
132
130
|
# end
|
|
133
131
|
|
|
134
132
|
# Do additional cleanup after the account is closed.
|
|
135
133
|
# after_close_account do
|
|
136
|
-
# Profile.find_by!(account_id:
|
|
134
|
+
# Profile.find_by!(account_id: account_id).destroy
|
|
137
135
|
# end
|
|
136
|
+
<% unless json? || jwt? -%>
|
|
138
137
|
|
|
139
138
|
# ==> Redirects
|
|
140
139
|
# Redirect to home page after logout.
|
|
@@ -145,6 +144,7 @@ class RodauthApp < Rodauth::Rails::App
|
|
|
145
144
|
|
|
146
145
|
# Redirect to login page after password reset.
|
|
147
146
|
reset_password_redirect { login_path }
|
|
147
|
+
<% end -%>
|
|
148
148
|
|
|
149
149
|
# ==> Deadlines
|
|
150
150
|
# Change default deadlines for some actions.
|
|
@@ -156,14 +156,13 @@ class RodauthApp < Rodauth::Rails::App
|
|
|
156
156
|
|
|
157
157
|
# ==> Multiple configurations
|
|
158
158
|
# configure(:admin) do
|
|
159
|
-
# enable :http_basic_auth
|
|
160
|
-
#
|
|
159
|
+
# enable :http_basic_auth # enable different set of features
|
|
161
160
|
# prefix "/admin"
|
|
162
|
-
#
|
|
161
|
+
# session_key_prefix "admin_"
|
|
163
162
|
# end
|
|
164
163
|
|
|
165
164
|
route do |r|
|
|
166
|
-
<% unless
|
|
165
|
+
<% unless jwt? -%>
|
|
167
166
|
rodauth.load_memory # autologin remembered users
|
|
168
167
|
|
|
169
168
|
<% end -%>
|
data/lib/rodauth/rails.rb
CHANGED
data/lib/rodauth/rails/app.rb
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
require "roda"
|
|
2
|
+
require "rodauth"
|
|
3
|
+
require "rodauth/rails/feature"
|
|
2
4
|
|
|
3
5
|
module Rodauth
|
|
4
6
|
module Rails
|
|
@@ -10,13 +12,13 @@ module Rodauth
|
|
|
10
12
|
plugin :hooks
|
|
11
13
|
plugin :render, layout: false
|
|
12
14
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
end
|
|
15
|
+
unless Rodauth::Rails.api_only?
|
|
16
|
+
require "rodauth/rails/app/flash"
|
|
17
|
+
plugin Flash
|
|
18
|
+
end
|
|
18
19
|
|
|
19
|
-
|
|
20
|
+
def self.configure(name = nil, **options, &block)
|
|
21
|
+
plugin :rodauth, name: name, csrf: false, flash: false, json: true, **options do
|
|
20
22
|
# load the Rails integration
|
|
21
23
|
enable :rails
|
|
22
24
|
|
|
@@ -30,10 +30,12 @@ module Rodauth
|
|
|
30
30
|
rails_request.flash
|
|
31
31
|
end
|
|
32
32
|
|
|
33
|
-
|
|
34
|
-
|
|
33
|
+
if ActionPack.version >= Gem::Version.new("5.0")
|
|
34
|
+
def commit_flash
|
|
35
35
|
rails_request.commit_flash
|
|
36
|
-
|
|
36
|
+
end
|
|
37
|
+
else
|
|
38
|
+
def commit_flash
|
|
37
39
|
# ActionPack 4.2 automatically commits flash
|
|
38
40
|
end
|
|
39
41
|
end
|
|
@@ -26,7 +26,7 @@ module Rodauth
|
|
|
26
26
|
def render(page)
|
|
27
27
|
rails_render(partial: page.tr("-", "_"), layout: false) ||
|
|
28
28
|
rails_render(action: page.tr("-", "_"), layout: false) ||
|
|
29
|
-
super
|
|
29
|
+
super.html_safe
|
|
30
30
|
end
|
|
31
31
|
|
|
32
32
|
# Render Rails CSRF tags in Rodauth templates.
|
|
@@ -44,6 +44,11 @@ module Rodauth
|
|
|
44
44
|
true
|
|
45
45
|
end
|
|
46
46
|
|
|
47
|
+
# Reset Rails session to protect from session fixation attacks.
|
|
48
|
+
def clear_session
|
|
49
|
+
rails_controller_instance.reset_session
|
|
50
|
+
end
|
|
51
|
+
|
|
47
52
|
# Default the flash error key to Rails' default :alert.
|
|
48
53
|
def flash_error_key
|
|
49
54
|
:alert
|
|
@@ -54,6 +59,10 @@ module Rodauth
|
|
|
54
59
|
rails_controller_instance.instance_exec(&block)
|
|
55
60
|
end
|
|
56
61
|
|
|
62
|
+
def button(*)
|
|
63
|
+
super.html_safe
|
|
64
|
+
end
|
|
65
|
+
|
|
57
66
|
private
|
|
58
67
|
|
|
59
68
|
# Runs controller callbacks and rescue handlers around Rodauth actions.
|
|
@@ -68,20 +77,22 @@ module Rodauth
|
|
|
68
77
|
|
|
69
78
|
if rails_controller_instance.performed?
|
|
70
79
|
rails_controller_response
|
|
71
|
-
|
|
80
|
+
elsif result
|
|
72
81
|
result[1].merge!(rails_controller_instance.response.headers)
|
|
73
82
|
throw :halt, result
|
|
83
|
+
else
|
|
84
|
+
result
|
|
74
85
|
end
|
|
75
86
|
end
|
|
76
87
|
|
|
77
88
|
# Runs any #(before|around|after)_action controller callbacks.
|
|
78
89
|
def rails_controller_callbacks
|
|
79
90
|
# don't verify CSRF token as part of callbacks, Rodauth will do that
|
|
80
|
-
|
|
91
|
+
rails_controller_forgery_protection { false }
|
|
81
92
|
|
|
82
93
|
rails_controller_instance.run_callbacks(:process_action) do
|
|
83
94
|
# turn the setting back to default so that form tags generate CSRF tags
|
|
84
|
-
|
|
95
|
+
rails_controller_forgery_protection { rails_controller.allow_forgery_protection }
|
|
85
96
|
|
|
86
97
|
yield
|
|
87
98
|
end
|
|
@@ -121,7 +132,7 @@ module Rodauth
|
|
|
121
132
|
|
|
122
133
|
# Calls the Rails renderer, returning nil if a template is missing.
|
|
123
134
|
def rails_render(*args)
|
|
124
|
-
return if
|
|
135
|
+
return if rails_api_controller?
|
|
125
136
|
|
|
126
137
|
rails_controller_instance.render_to_string(*args)
|
|
127
138
|
rescue ActionView::MissingTemplate
|
|
@@ -148,6 +159,13 @@ module Rodauth
|
|
|
148
159
|
rails_controller_instance.send(:form_authenticity_token)
|
|
149
160
|
end
|
|
150
161
|
|
|
162
|
+
# allows/disables forgery protection
|
|
163
|
+
def rails_controller_forgery_protection(&value)
|
|
164
|
+
return if rails_api_controller?
|
|
165
|
+
|
|
166
|
+
rails_controller_instance.allow_forgery_protection = value.call
|
|
167
|
+
end
|
|
168
|
+
|
|
151
169
|
# Instances of the configured controller with current request's env hash.
|
|
152
170
|
def _rails_controller_instance
|
|
153
171
|
controller = rails_controller.new
|
|
@@ -159,27 +177,29 @@ module Rodauth
|
|
|
159
177
|
end
|
|
160
178
|
|
|
161
179
|
if ActionPack.version >= Gem::Version.new("5.0")
|
|
162
|
-
# Controller class to use for view rendering, CSRF protection, and
|
|
163
|
-
# running any registered action callbacks and rescue_from handlers.
|
|
164
|
-
def rails_controller
|
|
165
|
-
only_json? ? ActionController::API : ActionController::Base
|
|
166
|
-
end
|
|
167
|
-
|
|
168
180
|
def prepare_rails_controller(controller, rails_request)
|
|
169
181
|
controller.set_request! rails_request
|
|
170
182
|
controller.set_response! rails_controller.make_response!(rails_request)
|
|
171
183
|
end
|
|
172
184
|
else
|
|
173
|
-
def rails_controller
|
|
174
|
-
ActionController::Base
|
|
175
|
-
end
|
|
176
|
-
|
|
177
185
|
def prepare_rails_controller(controller, rails_request)
|
|
178
186
|
controller.send(:set_response!, rails_request)
|
|
179
187
|
controller.instance_variable_set(:@_request, rails_request)
|
|
180
188
|
end
|
|
181
189
|
end
|
|
182
190
|
|
|
191
|
+
def rails_api_controller?
|
|
192
|
+
defined?(ActionController::API) && rails_controller <= ActionController::API
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
def rails_controller
|
|
196
|
+
if only_json? && Rodauth::Rails.api_only?
|
|
197
|
+
ActionController::API
|
|
198
|
+
else
|
|
199
|
+
ActionController::Base
|
|
200
|
+
end
|
|
201
|
+
end
|
|
202
|
+
|
|
183
203
|
# ActionMailer subclass for correct email delivering.
|
|
184
204
|
class Mailer < ActionMailer::Base
|
|
185
205
|
def create_email(**options)
|
data/rodauth-rails.gemspec
CHANGED
|
@@ -17,8 +17,10 @@ Gem::Specification.new do |spec|
|
|
|
17
17
|
spec.require_paths = ["lib"]
|
|
18
18
|
|
|
19
19
|
spec.add_dependency "railties", ">= 4.2", "< 7"
|
|
20
|
-
spec.add_dependency "rodauth", "~> 2.
|
|
20
|
+
spec.add_dependency "rodauth", "~> 2.9"
|
|
21
21
|
spec.add_dependency "sequel-activerecord_connection", "~> 1.1"
|
|
22
22
|
spec.add_dependency "tilt"
|
|
23
23
|
spec.add_dependency "bcrypt"
|
|
24
|
+
|
|
25
|
+
spec.add_development_dependency "jwt"
|
|
24
26
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: rodauth-rails
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.9.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Janko Marohnić
|
|
8
|
-
autorequire:
|
|
8
|
+
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2021-02-10 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: railties
|
|
@@ -36,14 +36,14 @@ dependencies:
|
|
|
36
36
|
requirements:
|
|
37
37
|
- - "~>"
|
|
38
38
|
- !ruby/object:Gem::Version
|
|
39
|
-
version: '2.
|
|
39
|
+
version: '2.9'
|
|
40
40
|
type: :runtime
|
|
41
41
|
prerelease: false
|
|
42
42
|
version_requirements: !ruby/object:Gem::Requirement
|
|
43
43
|
requirements:
|
|
44
44
|
- - "~>"
|
|
45
45
|
- !ruby/object:Gem::Version
|
|
46
|
-
version: '2.
|
|
46
|
+
version: '2.9'
|
|
47
47
|
- !ruby/object:Gem::Dependency
|
|
48
48
|
name: sequel-activerecord_connection
|
|
49
49
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -86,6 +86,20 @@ dependencies:
|
|
|
86
86
|
- - ">="
|
|
87
87
|
- !ruby/object:Gem::Version
|
|
88
88
|
version: '0'
|
|
89
|
+
- !ruby/object:Gem::Dependency
|
|
90
|
+
name: jwt
|
|
91
|
+
requirement: !ruby/object:Gem::Requirement
|
|
92
|
+
requirements:
|
|
93
|
+
- - ">="
|
|
94
|
+
- !ruby/object:Gem::Version
|
|
95
|
+
version: '0'
|
|
96
|
+
type: :development
|
|
97
|
+
prerelease: false
|
|
98
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
99
|
+
requirements:
|
|
100
|
+
- - ">="
|
|
101
|
+
- !ruby/object:Gem::Version
|
|
102
|
+
version: '0'
|
|
89
103
|
description: Provides Rails integration for Rodauth.
|
|
90
104
|
email:
|
|
91
105
|
- janko.marohnic@gmail.com
|
|
@@ -187,7 +201,6 @@ files:
|
|
|
187
201
|
- lib/generators/rodauth/templates/db/migrate/create_rodauth.rb
|
|
188
202
|
- lib/generators/rodauth/views_generator.rb
|
|
189
203
|
- lib/rodauth-rails.rb
|
|
190
|
-
- lib/rodauth/features/rails.rb
|
|
191
204
|
- lib/rodauth/rails.rb
|
|
192
205
|
- lib/rodauth/rails/app.rb
|
|
193
206
|
- lib/rodauth/rails/app/flash.rb
|
|
@@ -203,7 +216,7 @@ homepage: https://github.com/janko/rodauth-rails
|
|
|
203
216
|
licenses:
|
|
204
217
|
- MIT
|
|
205
218
|
metadata: {}
|
|
206
|
-
post_install_message:
|
|
219
|
+
post_install_message:
|
|
207
220
|
rdoc_options: []
|
|
208
221
|
require_paths:
|
|
209
222
|
- lib
|
|
@@ -218,8 +231,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
218
231
|
- !ruby/object:Gem::Version
|
|
219
232
|
version: '0'
|
|
220
233
|
requirements: []
|
|
221
|
-
rubygems_version: 3.
|
|
222
|
-
signing_key:
|
|
234
|
+
rubygems_version: 3.2.3
|
|
235
|
+
signing_key:
|
|
223
236
|
specification_version: 4
|
|
224
237
|
summary: Provides Rails integration for Rodauth.
|
|
225
238
|
test_files: []
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
require "rodauth/rails/feature"
|