rodauth-omniauth 0.5.0 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bcd1857e0bfd2329c4df0476d8f5091bac5f45c9bd47de6c8c3ef53a99bf0a64
4
- data.tar.gz: 57ddd4e9b6e8baf00b66da1f580b01762a0c118f7c962f520a026f6ef94bbfc3
3
+ metadata.gz: c91c4429c36390bbede1d97214cdb6a40c5a6f5d9255c379f3b17d026cee88c9
4
+ data.tar.gz: 8e09d6d3c5d4d9eb0022dd5696e1370fc82c22bd068ec5b883212f2117ae3c47
5
5
  SHA512:
6
- metadata.gz: 9bebec705884e246bd20bee55771711d3fff5d82c9c7f711099e09ac1196e2af8ce0c5d9e1456035da429e33c7439d7ae8c2350b6b33c6081c54f74a93992b74
7
- data.tar.gz: 53be14c4e20dff0c17e988b46cc7e0c700b810c6fc7a4440eb94a63abeee9659f9ad880427ce7205dd0fe9c6757b6e48a6e1e99411b1304dba8f011327936246
6
+ metadata.gz: 03e77668f1f2c2076f003ac455c1f57dcfd5b60f7096cc77e5fe0918bf6484814ab02304eb9286e5323c42c2115102b262edb55dc41174dc0574c9ae0e6c84cc
7
+ data.tar.gz: f90369c94f3d9baf82dda2490ff716e543cd6cd09a6c8b856b2ba41c0594bcce69a489755520e2aea898eaf6907611d31d53c7cbf2a5f3f0fff51a457511012d
data/README.md CHANGED
@@ -10,6 +10,10 @@ Add the gem to your project:
10
10
  $ bundle add rodauth-omniauth
11
11
  ```
12
12
 
13
+ > [!NOTE]
14
+ > Rodauth's CSRF protection will be used for the request validation phase, so there is no need for gems like `omniauth-rails_csrf_protection`.
15
+
16
+
13
17
  ## Usage
14
18
 
15
19
  You'll first need to create the table for storing external identities:
@@ -46,17 +50,16 @@ Then enable the `omniauth` feature and register providers in your Rodauth config
46
50
  $ bundle add omniauth-facebook omniauth-twitter, omniauth-google-oauth2
47
51
  ```
48
52
  ```rb
49
- plugin :rodauth do
50
- enable :omniauth
53
+ # in your Rodauth configuration
54
+ enable :omniauth
51
55
 
52
- omniauth_provider :facebook, ENV["FACEBOOK_APP_ID"], ENV["FACEBOOK_APP_SECRET"], scope: "email"
53
- omniauth_provider :twitter, ENV["TWITTER_API_KEY"], ENV["TWITTER_API_SECRET"]
54
- omniauth_provider :google_oauth2, ENV["GOOGLE_CLIENT_ID"], ENV["GOOGLE_CLIENT_SECRET"], name: :google
55
- end
56
+ omniauth_provider :facebook, ENV["FACEBOOK_APP_ID"], ENV["FACEBOOK_APP_SECRET"], scope: "email"
57
+ omniauth_provider :twitter, ENV["TWITTER_API_KEY"], ENV["TWITTER_API_SECRET"]
58
+ omniauth_provider :google_oauth2, ENV["GOOGLE_CLIENT_ID"], ENV["GOOGLE_CLIENT_SECRET"], name: :google
56
59
  ```
57
60
 
58
- > [!NOTE]
59
- > It is important to note that `rodauth-omniauth` requires OmniAuth 2.x, so it's only compatible with providers gems that support it.
61
+ > [!WARNING]
62
+ > The `rodauth-omniauth` gem requires OmniAuth 2.x, so it's only compatible with providers gems that support it.
60
63
 
61
64
  You can now add authentication links to your login form:
62
65
 
@@ -88,6 +91,24 @@ account.identities #=> [#<Account::Identity ...>, ...]
88
91
 
89
92
  Currently, provider login is required to return the user's email address, and account creation is assumed not to require additional fields that need to be entered manually. There is currently also no built-in functionality for connecting/removing external identities when signed in. Both features are planned for future versions.
90
93
 
94
+ ### Timestamps
95
+
96
+ If you want to know when an external identity was used first or last, you may want to add timestamp columns to the identities table:
97
+
98
+ ```rb
99
+ create_table :account_identities do |t|
100
+ # ...
101
+ t.timestamps
102
+ end
103
+ ```
104
+
105
+ In that case, you'll need to make sure the column values are populated on create/update:
106
+
107
+ ```rb
108
+ omniauth_identity_insert_hash { super().merge(created_at: Time.now) }
109
+ omniauth_identity_update_hash { { updated_at: Time.now } }
110
+ ```
111
+
91
112
  ### Login
92
113
 
93
114
  After provider login, you can perform custom logic at the start of the callback request:
@@ -148,6 +169,31 @@ rodauth.omniauth_request_path(:google, action: "login") #=> "/auth/github?action
148
169
  omniauth_create_account? { omniauth_params["action"] != "login" }
149
170
  ```
150
171
 
172
+ You can change the default error message for when existing account wasn't found in case automatic account creation is disabled:
173
+
174
+ ```rb
175
+ omniauth_login_no_matching_account_error_flash "No existing account found"
176
+ ```
177
+
178
+ ### Multifactor authentication
179
+
180
+ By default, OmniAuth login will count only as one factor. So, if the user has multifactor authentication enabled, they will be asked to authenticate with 2nd factor when required.
181
+
182
+ If you're using OmniAuth login for SSO and want to rely on 2FA policies set on the external provider, you can have OmniAuth login count as two factors:
183
+
184
+ ```rb
185
+ omniauth_two_factors? true
186
+ ```
187
+
188
+ You can also make it conditional based on data from the external provider:
189
+
190
+ ```rb
191
+ omniauth_two_factors? do
192
+ # only count as two factors if external account uses 2FA
193
+ omniauth_extra["raw_info"]["two_factor_authentication"]
194
+ end
195
+ ```
196
+
151
197
  ### Identity data
152
198
 
153
199
  You can also store extra data on the external identities. For example, we could override the update hash to store `info`, `credentials`, and `extra` data from the auth hash into separate columns:
@@ -193,23 +239,37 @@ omniauth_identities_provider_column :provider
193
239
  omniauth_identities_uid_column :uid
194
240
  ```
195
241
 
196
- ## Base
242
+ ### Audit logging
197
243
 
198
- The `omniauth` feature builds on top of the `omniauth_base` feature, which sets up OmniAuth and routes its requests, but has no interaction with the database. So, if you would prefer to handle external logins differently, you can load just the `omniauth_base` feature, and implement your own callback phase.
244
+ If you're using the [audit_logging] feature, it can be useful to include the external provider name in the `login` audit logs:
199
245
 
200
246
  ```rb
201
- plugin :rodauth do
202
- enable :omniauth_base
247
+ enable :audit_logging
203
248
 
204
- omniauth_provider :github, ENV["GITHUB_CLIENT_ID"], ENV["GITHUB_CLIENT_SECRET"], scope: "user"
205
- omniauth_provider :apple, ENV["APPLE_CLIENT_ID"], ENV["APPLE_CLIENT_SECRET"], scope: "email name"
249
+ audit_log_metadata_for :login do
250
+ { "provider" => omniauth_provider } if authenticated_by.include?("omniauth")
206
251
  end
252
+ ```
253
+
254
+ ## Base
207
255
 
208
- route do |r|
209
- r.rodauth # routes Rodauth and OmniAuth requests
256
+ The `omniauth` feature builds on top of the `omniauth_base` feature, which sets up OmniAuth and routes its requests, but has no interaction with the database. So, if you would prefer to handle external logins differently, you can load just the `omniauth_base` feature, and implement your own callback phase.
257
+
258
+ ```rb
259
+ # in your Rodauth configuration
260
+ enable :omniauth_base
210
261
 
211
- r.get "auth", String, "callback" do
212
- # ... handle callback request ...
262
+ omniauth_provider :github, ENV["GITHUB_CLIENT_ID"], ENV["GITHUB_CLIENT_SECRET"], scope: "user"
263
+ omniauth_provider :apple, ENV["APPLE_CLIENT_ID"], ENV["APPLE_CLIENT_SECRET"], scope: "email name"
264
+ ```
265
+ ```rb
266
+ # in your routes
267
+ get "/auth/:provider/callback", to: "rodauth#omniauth_login"
268
+ ```
269
+ ```rb
270
+ class RodauthController < ApplicationController
271
+ def omniauth_login
272
+ # ...
213
273
  end
214
274
  end
215
275
  ```
@@ -307,10 +367,6 @@ omniauth_on_failure do
307
367
  end
308
368
  ```
309
369
 
310
- #### CSRF protection
311
-
312
- The default request validation phase uses Rodauth's configured CSRF protection, so there is no need for external gems such as `omniauth-rails_csrf_protection`.
313
-
314
370
  ### Inheritance
315
371
 
316
372
  The registered providers are inherited between Rodauth auth classes, so you can have fine-grained configuration for different account types.
@@ -322,15 +378,13 @@ class RodauthBase < Rodauth::Auth
322
378
  omniauth_provider :google_oauth2, ...
323
379
  end
324
380
  end
325
- ```
326
- ```rb
381
+
327
382
  class RodauthMain < RodauthBase
328
383
  configure do
329
384
  omniauth_provider :facebook, ...
330
385
  end
331
386
  end
332
- ```
333
- ```rb
387
+
334
388
  class RodauthAdmin < RodauthBase
335
389
  configure do
336
390
  omniauth_provider :twitter, ...
@@ -339,12 +393,6 @@ class RodauthAdmin < RodauthBase
339
393
  end
340
394
  ```
341
395
  ```rb
342
- class RodauthApp < Roda
343
- plugin :rodauth, auth_class: RodauthMain
344
- plugin :rodauth, auth_class: RodauthAdmin, name: :admin
345
- end
346
- ```
347
- ```rb
348
396
  rodauth.omniauth_providers #=> [:google_oauth2, :facebook]
349
397
  rodauth(:admin).omniauth_providers #=> [:google_oauth2, :twitter, :github]
350
398
  ```
@@ -379,6 +427,9 @@ Content-Type: application/json
379
427
  { "success": "You have been logged in" }
380
428
  ```
381
429
 
430
+ > [!NOTE]
431
+ > Unless you're using JWT, make sure you're persisting cookies across requests, as most OmniAuth strategies rely on session storage.
432
+
382
433
  If there was an OmniAuth failure, the error type will be included in the response:
383
434
 
384
435
  ```http
@@ -432,3 +483,4 @@ Everyone interacting in the rodauth-omniauth project's codebases, issue trackers
432
483
  [rodauth-model]: https://github.com/janko/rodauth-model
433
484
  [rodauth-rails]: https://github.com/janko/rodauth-rails
434
485
  [omniauth-oauth2]: https://github.com/omniauth/omniauth-oauth2
486
+ [audit_logging]: https://rodauth.jeremyevans.net/rdoc/files/doc/audit_logging_rdoc.html
@@ -20,6 +20,7 @@ module Rodauth
20
20
  auth_value_method :omniauth_identities_account_id_column, :account_id
21
21
  auth_value_method :omniauth_identities_provider_column, :provider
22
22
  auth_value_method :omniauth_identities_uid_column, :uid
23
+ auth_value_method :omniauth_two_factors?, false
23
24
 
24
25
  auth_value_methods(
25
26
  :omniauth_verify_account?,
@@ -97,7 +98,9 @@ module Rodauth
97
98
  end
98
99
  end
99
100
 
100
- login("omniauth")
101
+ login("omniauth") do
102
+ two_factor_update_session("omniauth-two") if omniauth_second_factor?
103
+ end
101
104
  end
102
105
 
103
106
  def retrieve_omniauth_identity
@@ -126,7 +129,7 @@ module Rodauth
126
129
 
127
130
  def possible_authentication_methods
128
131
  methods = super
129
- methods << "omniauth" unless methods.include?("password") || omniauth_account_identities_ds.empty?
132
+ methods << "omniauth" unless methods.include?("password") || (features.include?(:email_auth) && allow_email_auth?) || omniauth_account_identities_ds.empty?
130
133
  methods
131
134
  end
132
135
 
@@ -142,12 +145,12 @@ module Rodauth
142
145
  remove_omniauth_identities
143
146
  end
144
147
 
145
- def allow_email_auth?
146
- (defined?(super) ? super : true) && omniauth_account_identities_ds.empty?
147
- end
148
-
149
148
  attr_reader :omniauth_identity
150
149
 
150
+ def omniauth_second_factor?
151
+ features.include?(:two_factor_base) && uses_two_factor_authentication? && omniauth_two_factors?
152
+ end
153
+
151
154
  def omniauth_verify_account?
152
155
  features.include?(:verify_account) && account[login_column] == omniauth_email
153
156
  end
@@ -209,7 +212,7 @@ module Rodauth
209
212
  end
210
213
 
211
214
  def _account_from_omniauth_identity
212
- account_ds(omniauth_identity_account_id).first
215
+ _account_from_id(omniauth_identity_account_id)
213
216
  end
214
217
 
215
218
  def omniauth_identity_id
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |spec|
2
2
  spec.name = "rodauth-omniauth"
3
- spec.version = "0.5.0"
3
+ spec.version = "0.6.0"
4
4
  spec.authors = ["Janko Marohnić"]
5
5
  spec.email = ["janko@hey.com"]
6
6
 
@@ -17,7 +17,7 @@ Gem::Specification.new do |spec|
17
17
  spec.files = Dir["README.md", "LICENSE.txt", "*.gemspec", "lib/**/*", "locales/**/*"]
18
18
  spec.require_paths = ["lib"]
19
19
 
20
- spec.add_dependency "rodauth", "~> 2.13"
20
+ spec.add_dependency "rodauth", "~> 2.36"
21
21
  spec.add_dependency "omniauth", "~> 2.0"
22
22
 
23
23
  spec.add_development_dependency "minitest"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rodauth-omniauth
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Janko Marohnić
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-10-10 00:00:00.000000000 Z
11
+ date: 2024-11-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rodauth
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '2.13'
19
+ version: '2.36'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '2.13'
26
+ version: '2.36'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: omniauth
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -212,7 +212,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
212
212
  - !ruby/object:Gem::Version
213
213
  version: '0'
214
214
  requirements: []
215
- rubygems_version: 3.5.11
215
+ rubygems_version: 3.5.23
216
216
  signing_key:
217
217
  specification_version: 4
218
218
  summary: Rodauth extension for logging in and creating account via OmniAuth authentication.