rodauth-rails 0.6.1 → 0.9.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/CHANGELOG.md +38 -0
- data/README.md +369 -47
- data/lib/generators/rodauth/install_generator.rb +9 -4
- data/lib/generators/rodauth/templates/app/lib/rodauth_app.rb +23 -24
- data/lib/rodauth/rails.rb +20 -0
- data/lib/rodauth/rails/app.rb +9 -7
- data/lib/rodauth/rails/app/flash.rb +5 -3
- data/lib/rodauth/rails/feature.rb +40 -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: 60fda35b195285a7c9cc14e07153d80faa9e939cf2944fbb04e1360baf30e306
|
4
|
+
data.tar.gz: 1f89bcfff28e6d08287fa67a9fe9228a2d61f15a8a9cdecb9fcf138137d72c47
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8e4ed3afbe7a114ba36f19541d1c8c8ee62de07526400230b1386f027b05876cd78ad88bdb40cae9767e74f83d1532d4939d97d03657662933f81d7086df34d9
|
7
|
+
data.tar.gz: cae1fc15a86f1b2e2423a8e54f36b844f610ba23ff74fd9ced132200e9816260028682c0efea1dcf19cf8a722a7ae49882c8d31c670e268e229117b4f6fb84f2
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,41 @@
|
|
1
|
+
## 0.9.0 (2021-02-07)
|
2
|
+
|
3
|
+
* Load Roda's JSON support by default, so that enabling `json`/`jwt` feature is all that's needed (@janko)
|
4
|
+
|
5
|
+
* Bump Rodauth dependency to 2.9+ (@janko)
|
6
|
+
|
7
|
+
* Add `--json` option for `rodauth:install` generator for configuring `json` feature (@janko)
|
8
|
+
|
9
|
+
* Add `--jwt` option for `rodauth:install` generator for configuring `jwt` feature (@janko)
|
10
|
+
|
11
|
+
* Remove the `--api` option from `rodauth:install` generator (@janko)
|
12
|
+
|
13
|
+
## 0.8.2 (2021-01-10)
|
14
|
+
|
15
|
+
* Reset Rails session on `#clear_session`, protecting from potential session fixation attacks (@janko)
|
16
|
+
|
17
|
+
## 0.8.1 (2021-01-04)
|
18
|
+
|
19
|
+
* Fix blank email body when `json: true` and `ActionController::API` descendant are used (@janko)
|
20
|
+
|
21
|
+
* Make view and email rendering work when there are multiple configurations and one is `json: :only` (@janko)
|
22
|
+
|
23
|
+
* Don't attempt to protect against forgery when `ActionController::API` descendant is used (@janko)
|
24
|
+
|
25
|
+
* Mark content of rodauth built-in partials as HTML-safe (@janko)
|
26
|
+
|
27
|
+
## 0.8.0 (2021-01-03)
|
28
|
+
|
29
|
+
* Add `--api` option to `rodauth:install` generator for choosing JSON-only configuration (@janko)
|
30
|
+
|
31
|
+
* Don't blow up when a Rodauth request is made using an unsupported HTTP verb (@janko)
|
32
|
+
|
33
|
+
## 0.7.0 (2020-11-27)
|
34
|
+
|
35
|
+
* Add `#rails_controller_eval` method for running code in context of a controller instance (@janko)
|
36
|
+
|
37
|
+
* Detect `secret_key_base` from credentials and `$SECRET_KEY_BASE` environment variable (@janko)
|
38
|
+
|
1
39
|
## 0.6.1 (2020-11-25)
|
2
40
|
|
3
41
|
* Generate the Rodauth controller for API-only Rails apps as well (@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,14 +41,49 @@ 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
|
63
|
+
|
64
|
+
## Upgrading
|
65
|
+
|
66
|
+
### Upgrading to 0.7.0
|
67
|
+
|
68
|
+
Starting from version 0.7.0, rodauth-rails now correctly detects Rails
|
69
|
+
application's `secret_key_base` when setting default `hmac_secret`, including
|
70
|
+
when it's set via credentials or `$SECRET_KEY_BASE` environment variable. This
|
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.
|
73
|
+
|
74
|
+
However, if you've already been using rodauth-rails in production, where the
|
75
|
+
`secret_key_base` is set via credentials or environment variable and `hmac_secret`
|
76
|
+
was not explicitly set, the fact that your authentication will now start using
|
77
|
+
HMACs has backwards compatibility considerations. See the [Rodauth
|
78
|
+
documentation][hmac] for instructions on how to safely transition, or just set
|
79
|
+
`hmac_secret nil` in your Rodauth configuration.
|
16
80
|
|
17
81
|
## Installation
|
18
82
|
|
19
83
|
Add the gem to your Gemfile:
|
20
84
|
|
21
85
|
```rb
|
22
|
-
gem "rodauth-rails", "~> 0.
|
86
|
+
gem "rodauth-rails", "~> 0.9"
|
23
87
|
|
24
88
|
# gem "jwt", require: false # for JWT feature
|
25
89
|
# gem "rotp", require: false # for OTP feature
|
@@ -31,10 +95,19 @@ Then run `bundle install`.
|
|
31
95
|
|
32
96
|
Next, run the install generator:
|
33
97
|
|
34
|
-
```
|
98
|
+
```sh
|
35
99
|
$ rails generate rodauth:install
|
36
100
|
```
|
37
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
|
+
|
38
111
|
The generator will create the following files:
|
39
112
|
|
40
113
|
* Rodauth migration at `db/migrate/*_create_rodauth.rb`
|
@@ -168,14 +241,12 @@ Using this information, we could add some basic authentication links to our
|
|
168
241
|
navigation header:
|
169
242
|
|
170
243
|
```erb
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
<% end %>
|
178
|
-
</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 %>
|
179
250
|
```
|
180
251
|
|
181
252
|
These routes are fully functional, feel free to visit them and interact with the
|
@@ -191,7 +262,7 @@ retrieves the corresponding account record:
|
|
191
262
|
```rb
|
192
263
|
# app/controllers/application_controller.rb
|
193
264
|
class ApplicationController < ActionController::Base
|
194
|
-
before_action :current_account, if: -> { rodauth.
|
265
|
+
before_action :current_account, if: -> { rodauth.logged_in? }
|
195
266
|
|
196
267
|
private
|
197
268
|
|
@@ -365,7 +436,7 @@ $ rails generate rodauth:mailer
|
|
365
436
|
```
|
366
437
|
|
367
438
|
This will create a `RodauthMailer` with the associated mailer views in
|
368
|
-
`app/views/rodauth_mailer` directory
|
439
|
+
`app/views/rodauth_mailer` directory:
|
369
440
|
|
370
441
|
```rb
|
371
442
|
# app/mailers/rodauth_mailer.rb
|
@@ -417,9 +488,9 @@ end
|
|
417
488
|
```
|
418
489
|
|
419
490
|
This approach can be used even if you're using a 3rd-party service for
|
420
|
-
transactional emails, where emails are sent via
|
421
|
-
|
422
|
-
|
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.
|
423
494
|
|
424
495
|
### Migrations
|
425
496
|
|
@@ -441,36 +512,67 @@ class CreateRodauthOtpSmsCodesRecoveryCodes < ActiveRecord::Migration
|
|
441
512
|
end
|
442
513
|
```
|
443
514
|
|
444
|
-
###
|
445
|
-
|
446
|
-
JSON API support in Rodauth is provided by the [JWT feature]. First you'll need
|
447
|
-
to add the [JWT gem] to your Gemfile:
|
448
|
-
|
449
|
-
```rb
|
450
|
-
gem "jwt"
|
451
|
-
```
|
515
|
+
### Multiple configurations
|
452
516
|
|
453
|
-
|
454
|
-
|
517
|
+
If you need to handle multiple types of accounts that require different
|
518
|
+
authentication logic, you can create different configurations for them:
|
455
519
|
|
456
520
|
```rb
|
457
521
|
# app/lib/rodauth_app.rb
|
458
522
|
class RodauthApp < Rodauth::Rails::App
|
459
|
-
|
523
|
+
# primary configuration
|
524
|
+
configure do
|
460
525
|
# ...
|
461
|
-
|
462
|
-
|
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) }
|
463
540
|
# ...
|
464
541
|
end
|
465
542
|
end
|
466
543
|
```
|
467
544
|
|
468
|
-
|
469
|
-
Rails app is in API-only mode, instead of `json: true` pass `json: :only` to
|
470
|
-
the configure method.
|
545
|
+
Then in your application you can reference the secondary Rodauth instance:
|
471
546
|
|
472
|
-
|
473
|
-
|
547
|
+
```rb
|
548
|
+
rodauth(:admin).login_path #=> "/admin/login"
|
549
|
+
```
|
550
|
+
|
551
|
+
### Calling controller methods
|
552
|
+
|
553
|
+
When using Rodauth before/after hooks or generally overriding your Rodauth
|
554
|
+
configuration, in some cases you might want to call methods defined on your
|
555
|
+
controllers. You can do so with `rails_controller_eval`, for example:
|
556
|
+
|
557
|
+
```rb
|
558
|
+
# app/controllers/application_controller.rb
|
559
|
+
class ApplicationController < ActionController::Base
|
560
|
+
private
|
561
|
+
def setup_tracking(account_id)
|
562
|
+
# ... some implementation ...
|
563
|
+
end
|
564
|
+
end
|
565
|
+
```
|
566
|
+
```rb
|
567
|
+
# app/lib/rodauth_app.rb
|
568
|
+
class RodauthApp < Rodauth::Rails::App
|
569
|
+
configure do
|
570
|
+
after_create_account do
|
571
|
+
rails_controller_eval { setup_tracking(account_id) }
|
572
|
+
end
|
573
|
+
end
|
574
|
+
end
|
575
|
+
```
|
474
576
|
|
475
577
|
### Rodauth instance
|
476
578
|
|
@@ -479,7 +581,7 @@ Rodauth operations outside of the request context. rodauth-rails gives you the
|
|
479
581
|
ability to retrieve the Rodauth instance:
|
480
582
|
|
481
583
|
```rb
|
482
|
-
rodauth = Rodauth::Rails.rodauth # or Rodauth::Rails.rodauth(:
|
584
|
+
rodauth = Rodauth::Rails.rodauth # or Rodauth::Rails.rodauth(:admin)
|
483
585
|
|
484
586
|
rodauth.login_url #=> "https://example.com/login"
|
485
587
|
rodauth.account_from_login("user@example.com") # loads user by email
|
@@ -510,8 +612,8 @@ The Rodauth app stores the `Rodauth::Auth` instance in the Rack env hash, which
|
|
510
612
|
is then available in your Rails app:
|
511
613
|
|
512
614
|
```rb
|
513
|
-
request.env["rodauth"]
|
514
|
-
request.env["rodauth.
|
615
|
+
request.env["rodauth"] #=> #<Rodauth::Auth>
|
616
|
+
request.env["rodauth.admin"] #=> #<Rodauth::Auth> (if using multiple configurations)
|
515
617
|
```
|
516
618
|
|
517
619
|
For convenience, this object can be accessed via the `#rodauth` method in views
|
@@ -520,14 +622,14 @@ and controllers:
|
|
520
622
|
```rb
|
521
623
|
class MyController < ApplicationController
|
522
624
|
def my_action
|
523
|
-
rodauth
|
524
|
-
rodauth(:
|
625
|
+
rodauth #=> #<Rodauth::Auth>
|
626
|
+
rodauth(:admin) #=> #<Rodauth::Auth> (if using multiple configurations)
|
525
627
|
end
|
526
628
|
end
|
527
629
|
```
|
528
630
|
```erb
|
529
|
-
<% rodauth
|
530
|
-
<% rodauth(:
|
631
|
+
<% rodauth #=> #<Rodauth::Auth> %>
|
632
|
+
<% rodauth(:admin) #=> #<Rodauth::Auth> (if using multiple configurations) %>
|
531
633
|
```
|
532
634
|
|
533
635
|
### App
|
@@ -542,13 +644,38 @@ integration for Rodauth:
|
|
542
644
|
* runs Action Controller callbacks & rescue handlers around Rodauth actions
|
543
645
|
* uses Action Mailer for sending emails
|
544
646
|
|
545
|
-
The `configure
|
647
|
+
The `configure` method wraps configuring the Rodauth plugin, forwarding
|
546
648
|
any additional [plugin options].
|
547
649
|
|
548
650
|
```rb
|
549
|
-
|
550
|
-
configure
|
551
|
-
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
|
552
679
|
```
|
553
680
|
|
554
681
|
### Sequel
|
@@ -559,11 +686,156 @@ function calls).
|
|
559
686
|
|
560
687
|
If ActiveRecord is used in the application, the `rodauth:install` generator
|
561
688
|
will have automatically configured Sequel to reuse ActiveRecord's database
|
562
|
-
connection
|
689
|
+
connection, using the [sequel-activerecord_connection] gem.
|
563
690
|
|
564
691
|
This means that, from the usage perspective, Sequel can be considered just
|
565
692
|
as an implementation detail of Rodauth.
|
566
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
|
+
## OmniAuth
|
733
|
+
|
734
|
+
While Rodauth doesn't yet come with [OmniAuth] integration, we can build one
|
735
|
+
ourselves using the existing Rodauth API.
|
736
|
+
|
737
|
+
In order to allow the user to login via multiple external providers, let's
|
738
|
+
create an `account_identities` table that will have a many-to-one relationship
|
739
|
+
with the `accounts` table:
|
740
|
+
|
741
|
+
```sh
|
742
|
+
$ rails generate model AccountIdentity
|
743
|
+
```
|
744
|
+
```rb
|
745
|
+
# db/migrate/*_create_account_identities.rb
|
746
|
+
class CreateAccountIdentities < ActiveRecord::Migration
|
747
|
+
def change
|
748
|
+
create_table :account_identities do |t|
|
749
|
+
t.references :account, null: false, foreign_key: { on_delete: :cascade }
|
750
|
+
t.string :provider, null: false
|
751
|
+
t.string :uid, null: false
|
752
|
+
t.jsonb :info, null: false, default: {} # adjust JSON column type for your database
|
753
|
+
|
754
|
+
t.timestamps
|
755
|
+
|
756
|
+
t.index [:provider, :uid], unique: true
|
757
|
+
end
|
758
|
+
end
|
759
|
+
end
|
760
|
+
```
|
761
|
+
```rb
|
762
|
+
# app/models/account_identity.rb
|
763
|
+
class AcccountIdentity < ApplicationRecord
|
764
|
+
belongs_to :account
|
765
|
+
end
|
766
|
+
```
|
767
|
+
```rb
|
768
|
+
# app/models/account.rb
|
769
|
+
class Account < ApplicationRecord
|
770
|
+
has_many :identities, class_name: "AccountIdentity"
|
771
|
+
end
|
772
|
+
```
|
773
|
+
|
774
|
+
Let's assume we want to implement Facebook login, and have added the
|
775
|
+
corresponding OmniAuth strategy to the middleware stack, together with an
|
776
|
+
authorization link on the login form:
|
777
|
+
|
778
|
+
```rb
|
779
|
+
Rails.application.config.middleware.use OmniAuth::Builder do
|
780
|
+
provider :facebook, ENV["FACEBOOK_APP_ID"], ENV["FACEBOOK_APP_SECRET"],
|
781
|
+
scope: "email", callback_path: "/auth/facebook/callback"
|
782
|
+
end
|
783
|
+
```
|
784
|
+
```erb
|
785
|
+
<%= link_to "Login via Facebook", "/auth/facebook" %>
|
786
|
+
```
|
787
|
+
|
788
|
+
Let's implement the OmniAuth callback endpoint on our Rodauth controller:
|
789
|
+
|
790
|
+
```rb
|
791
|
+
# config/routes.rb
|
792
|
+
Rails.application.routes.draw do
|
793
|
+
# ...
|
794
|
+
get "/auth/:provider/callback", to: "rodauth#omniauth"
|
795
|
+
end
|
796
|
+
```
|
797
|
+
```rb
|
798
|
+
# app/controllres/rodauth_controller.rb
|
799
|
+
class RodauthController < ApplicationController
|
800
|
+
def omniauth
|
801
|
+
auth = request.env["omniauth.auth"]
|
802
|
+
|
803
|
+
# attempt to find existing identity directly
|
804
|
+
identity = AccountIdentity.find_by(provider: auth["provider"], uid: auth["uid"])
|
805
|
+
|
806
|
+
if identity
|
807
|
+
# update any external info changes
|
808
|
+
identity.update!(info: auth["info"])
|
809
|
+
# set account from identity
|
810
|
+
account = identity.account
|
811
|
+
end
|
812
|
+
|
813
|
+
# attempt to find an existing account by email
|
814
|
+
account ||= Account.find_by(email: auth["info"]["email"])
|
815
|
+
|
816
|
+
# disallow login if account is not verified
|
817
|
+
if account && account.status != rodauth.account_open_status_value
|
818
|
+
redirect_to rodauth.login_path, alert: rodauth.unverified_account_message
|
819
|
+
return
|
820
|
+
end
|
821
|
+
|
822
|
+
# create new account if it doesn't exist
|
823
|
+
unless account
|
824
|
+
account = Account.create!(email: auth["info"]["email"])
|
825
|
+
end
|
826
|
+
|
827
|
+
# create new identity if it doesn't exist
|
828
|
+
unless identity
|
829
|
+
account.identities.create!(provider: auth["provider"], uid: auth["uid"], info: auth["info"])
|
830
|
+
end
|
831
|
+
|
832
|
+
# login with Rodauth
|
833
|
+
rodauth.account_from_login(account.email)
|
834
|
+
rodauth.login("omniauth")
|
835
|
+
end
|
836
|
+
end
|
837
|
+
```
|
838
|
+
|
567
839
|
## Configuring
|
568
840
|
|
569
841
|
For the list of configuration methods provided by Rodauth, see the [feature
|
@@ -597,6 +869,37 @@ Rodauth::Rails.configure do |config|
|
|
597
869
|
end
|
598
870
|
```
|
599
871
|
|
872
|
+
## Custom extensions
|
873
|
+
|
874
|
+
When developing custom extensions for Rodauth inside your Rails project, it's
|
875
|
+
better to use plain modules (at least in the beginning), because Rodauth
|
876
|
+
feature API doesn't yet support Zeitwerk reloading well.
|
877
|
+
|
878
|
+
```rb
|
879
|
+
# app/lib/rodauth_argon2.rb
|
880
|
+
module RodauthArgon2
|
881
|
+
def password_hash(password)
|
882
|
+
Argon2::Password.create(password, t_cost: password_hash_cost, m_cost: password_hash_cost)
|
883
|
+
end
|
884
|
+
|
885
|
+
def password_hash_match?(hash, password)
|
886
|
+
Argon2::Password.verify_password(password, hash)
|
887
|
+
end
|
888
|
+
end
|
889
|
+
```
|
890
|
+
```rb
|
891
|
+
# app/lib/rodauth_app.rb
|
892
|
+
class RodauthApp < Rodauth::Rails::App
|
893
|
+
configure do
|
894
|
+
# ...
|
895
|
+
auth_class_eval do
|
896
|
+
include RodauthArgon2
|
897
|
+
end
|
898
|
+
# ...
|
899
|
+
end
|
900
|
+
end
|
901
|
+
```
|
902
|
+
|
600
903
|
## Testing
|
601
904
|
|
602
905
|
If you're writing system tests, it's generally better to go through the actual
|
@@ -669,6 +972,8 @@ Rodauth method for creating database functions:
|
|
669
972
|
|
670
973
|
```rb
|
671
974
|
# db/migrate/*_create_rodauth_database_functions.rb
|
975
|
+
require "rodauth/migrations"
|
976
|
+
|
672
977
|
class CreateRodauthDatabaseFunctions < ActiveRecord::Migration
|
673
978
|
def up
|
674
979
|
Rodauth.create_database_authentication_functions(DB)
|
@@ -733,7 +1038,6 @@ conduct](https://github.com/janko/rodauth-rails/blob/master/CODE_OF_CONDUCT.md).
|
|
733
1038
|
[Rodauth]: https://github.com/jeremyevans/rodauth
|
734
1039
|
[Sequel]: https://github.com/jeremyevans/sequel
|
735
1040
|
[feature documentation]: http://rodauth.jeremyevans.net/documentation.html
|
736
|
-
[JWT feature]: http://rodauth.jeremyevans.net/rdoc/files/doc/jwt_rdoc.html
|
737
1041
|
[JWT gem]: https://github.com/jwt/ruby-jwt
|
738
1042
|
[Bootstrap]: https://getbootstrap.com/
|
739
1043
|
[Roda]: http://roda.jeremyevans.net/
|
@@ -742,3 +1046,21 @@ conduct](https://github.com/janko/rodauth-rails/blob/master/CODE_OF_CONDUCT.md).
|
|
742
1046
|
[Rodauth migration]: http://rodauth.jeremyevans.net/rdoc/files/README_rdoc.html#label-Creating+tables
|
743
1047
|
[sequel-activerecord_connection]: https://github.com/janko/sequel-activerecord_connection
|
744
1048
|
[plugin options]: http://rodauth.jeremyevans.net/rdoc/files/README_rdoc.html#label-Plugin+Options
|
1049
|
+
[hmac]: http://rodauth.jeremyevans.net/rdoc/files/README_rdoc.html#label-HMAC
|
1050
|
+
[OmniAuth]: https://github.com/omniauth/omniauth
|
1051
|
+
[otp]: http://rodauth.jeremyevans.net/rdoc/files/doc/otp_rdoc.html
|
1052
|
+
[sms_codes]: http://rodauth.jeremyevans.net/rdoc/files/doc/sms_codes_rdoc.html
|
1053
|
+
[recovery_codes]: http://rodauth.jeremyevans.net/rdoc/files/doc/recovery_codes_rdoc.html
|
1054
|
+
[webauthn]: http://rodauth.jeremyevans.net/rdoc/files/doc/webauthn_rdoc.html
|
1055
|
+
[json]: http://rodauth.jeremyevans.net/rdoc/files/doc/json_rdoc.html
|
1056
|
+
[jwt]: http://rodauth.jeremyevans.net/rdoc/files/doc/jwt_rdoc.html
|
1057
|
+
[email_auth]: http://rodauth.jeremyevans.net/rdoc/files/doc/email_auth_rdoc.html
|
1058
|
+
[audit_logging]: http://rodauth.jeremyevans.net/rdoc/files/doc/audit_logging_rdoc.html
|
1059
|
+
[password protection]: https://github.com/jeremyevans/rodauth#label-Password+Hash+Access+Via+Database+Functions
|
1060
|
+
[bruteforce tokens]: https://github.com/jeremyevans/rodauth#label-Tokens
|
1061
|
+
[password_complexity]: http://rodauth.jeremyevans.net/rdoc/files/doc/password_complexity_rdoc.html
|
1062
|
+
[disallow_password_reuse]: http://rodauth.jeremyevans.net/rdoc/files/doc/disallow_password_reuse_rdoc.html
|
1063
|
+
[password_expiration]: http://rodauth.jeremyevans.net/rdoc/files/doc/password_expiration_rdoc.html
|
1064
|
+
[session_expiration]: http://rodauth.jeremyevans.net/rdoc/files/doc/session_expiration_rdoc.html
|
1065
|
+
[single_session]: http://rodauth.jeremyevans.net/rdoc/files/doc/single_session_rdoc.html
|
1066
|
+
[account_expiration]: http://rodauth.jeremyevans.net/rdoc/files/doc/account_expiration_rdoc.html
|
@@ -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
|
@@ -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
@@ -32,6 +32,26 @@ module Rodauth
|
|
32
32
|
scope.rodauth(name)
|
33
33
|
end
|
34
34
|
|
35
|
+
if ::Rails.gem_version >= Gem::Version.new("5.2")
|
36
|
+
def secret_key_base
|
37
|
+
::Rails.application.secret_key_base
|
38
|
+
end
|
39
|
+
else
|
40
|
+
def secret_key_base
|
41
|
+
::Rails.application.secrets.secret_key_base
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
if ::Rails.gem_version >= Gem::Version.new("5.0")
|
46
|
+
def api_only?
|
47
|
+
::Rails.application.config.api_only
|
48
|
+
end
|
49
|
+
else
|
50
|
+
def api_only?
|
51
|
+
false
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
35
55
|
def configure
|
36
56
|
yield self
|
37
57
|
end
|
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
|
+
if defined?(ActionDispatch::Flash) # not in API-only mode
|
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
|
|
@@ -27,7 +29,7 @@ module Rodauth
|
|
27
29
|
set_deadline_values? true
|
28
30
|
|
29
31
|
# use HMACs for additional security
|
30
|
-
hmac_secret { ::Rails.
|
32
|
+
hmac_secret { Rodauth::Rails.secret_key_base }
|
31
33
|
|
32
34
|
# evaluate user configuration
|
33
35
|
instance_exec(&block)
|
@@ -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,11 +44,25 @@ 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
|
50
55
|
end
|
51
56
|
|
57
|
+
# Evaluates the block in context of a Rodauth controller instance.
|
58
|
+
def rails_controller_eval(&block)
|
59
|
+
rails_controller_instance.instance_exec(&block)
|
60
|
+
end
|
61
|
+
|
62
|
+
def button(*)
|
63
|
+
super.html_safe
|
64
|
+
end
|
65
|
+
|
52
66
|
private
|
53
67
|
|
54
68
|
# Runs controller callbacks and rescue handlers around Rodauth actions.
|
@@ -63,20 +77,22 @@ module Rodauth
|
|
63
77
|
|
64
78
|
if rails_controller_instance.performed?
|
65
79
|
rails_controller_response
|
66
|
-
|
80
|
+
elsif result
|
67
81
|
result[1].merge!(rails_controller_instance.response.headers)
|
68
82
|
throw :halt, result
|
83
|
+
else
|
84
|
+
result
|
69
85
|
end
|
70
86
|
end
|
71
87
|
|
72
88
|
# Runs any #(before|around|after)_action controller callbacks.
|
73
89
|
def rails_controller_callbacks
|
74
90
|
# don't verify CSRF token as part of callbacks, Rodauth will do that
|
75
|
-
|
91
|
+
rails_controller_forgery_protection { false }
|
76
92
|
|
77
93
|
rails_controller_instance.run_callbacks(:process_action) do
|
78
94
|
# turn the setting back to default so that form tags generate CSRF tags
|
79
|
-
|
95
|
+
rails_controller_forgery_protection { rails_controller.allow_forgery_protection }
|
80
96
|
|
81
97
|
yield
|
82
98
|
end
|
@@ -116,7 +132,7 @@ module Rodauth
|
|
116
132
|
|
117
133
|
# Calls the Rails renderer, returning nil if a template is missing.
|
118
134
|
def rails_render(*args)
|
119
|
-
return if
|
135
|
+
return if rails_api_controller?
|
120
136
|
|
121
137
|
rails_controller_instance.render_to_string(*args)
|
122
138
|
rescue ActionView::MissingTemplate
|
@@ -143,6 +159,13 @@ module Rodauth
|
|
143
159
|
rails_controller_instance.send(:form_authenticity_token)
|
144
160
|
end
|
145
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
|
+
|
146
169
|
# Instances of the configured controller with current request's env hash.
|
147
170
|
def _rails_controller_instance
|
148
171
|
controller = rails_controller.new
|
@@ -154,27 +177,29 @@ module Rodauth
|
|
154
177
|
end
|
155
178
|
|
156
179
|
if ActionPack.version >= Gem::Version.new("5.0")
|
157
|
-
# Controller class to use for view rendering, CSRF protection, and
|
158
|
-
# running any registered action callbacks and rescue_from handlers.
|
159
|
-
def rails_controller
|
160
|
-
only_json? ? ActionController::API : ActionController::Base
|
161
|
-
end
|
162
|
-
|
163
180
|
def prepare_rails_controller(controller, rails_request)
|
164
181
|
controller.set_request! rails_request
|
165
182
|
controller.set_response! rails_controller.make_response!(rails_request)
|
166
183
|
end
|
167
184
|
else
|
168
|
-
def rails_controller
|
169
|
-
ActionController::Base
|
170
|
-
end
|
171
|
-
|
172
185
|
def prepare_rails_controller(controller, rails_request)
|
173
186
|
controller.send(:set_response!, rails_request)
|
174
187
|
controller.instance_variable_set(:@_request, rails_request)
|
175
188
|
end
|
176
189
|
end
|
177
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
|
+
|
178
203
|
# ActionMailer subclass for correct email delivering.
|
179
204
|
class Mailer < ActionMailer::Base
|
180
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.0
|
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-07 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"
|