omniauth 2.1.4 → 2.3.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/LICENSE.md +1 -1
- data/README.md +170 -29
- data/SECURITY.md +5 -3
- data/lib/omniauth/auth_hash.rb +32 -6
- data/lib/omniauth/authenticity_token_protection.rb +6 -4
- data/lib/omniauth/builder.rb +9 -6
- data/lib/omniauth/failure_endpoint.rb +4 -4
- data/lib/omniauth/form.rb +5 -7
- data/lib/omniauth/key_store.rb +2 -10
- data/lib/omniauth/strategies/developer.rb +3 -5
- data/lib/omniauth/strategy/class_methods.rb +118 -0
- data/lib/omniauth/strategy/fetchers.rb +57 -0
- data/lib/omniauth/strategy/hosts.rb +48 -0
- data/lib/omniauth/strategy/paths.rb +140 -0
- data/lib/omniauth/strategy/sign_ins.rb +57 -0
- data/lib/omniauth/strategy/test_mode.rb +53 -0
- data/lib/omniauth/strategy.rb +149 -361
- data/lib/omniauth/test/phony_session.rb +1 -1
- data/lib/omniauth/test/strategy_test_case.rb +8 -9
- data/lib/omniauth/version.rb +1 -1
- data/lib/omniauth.rb +28 -25
- data/sig/manifest.yaml +5 -0
- data/sig/omniauth.rbs +662 -0
- metadata +30 -59
- data/.github/FUNDING.yml +0 -2
- data/.github/ISSUE_TEMPLATE.md +0 -20
- data/.github/dependabot.yml +0 -18
- data/.github/workflows/jruby.yml +0 -28
- data/.github/workflows/main.yml +0 -64
- data/.github/workflows/truffle_ruby.yml +0 -24
- data/.gitignore +0 -14
- data/.rspec +0 -2
- data/.rubocop.yml +0 -69
- data/.yardopts +0 -4
- data/Gemfile +0 -24
- data/Rakefile +0 -53
- data/omniauth.gemspec +0 -26
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 50ca36a1e5d776acd239b6bf0795352777cbbb9d4cfb6cdad37b35fa42071e30
|
|
4
|
+
data.tar.gz: 5042edc2920336a00c334faeed9ef80957f83b470ce97c9dd79056d93ba11959
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: b3a700e831fec507055fec1860e78be412699562972e2fddd79018d7a07dd0751d650d415bb8921c0207c593fe27871768d084742c6707bbb44bbf52f6222e86
|
|
7
|
+
data.tar.gz: 0f7776d3a2446974cf8fc9a93f0eaae46c92b3c20becbf4321daa64dd50dd89dbf25d618fef2ac8acd22ee5e9ec586e2db075f62670e5f2344a5907931f10bf7
|
data/LICENSE.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
Copyright (c) 2010-
|
|
1
|
+
Copyright (c) 2010-2026 Michael Bleigh and Intridea, Inc.
|
|
2
2
|
|
|
3
3
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
4
4
|
of this software and associated documentation files (the "Software"), to deal
|
data/README.md
CHANGED
|
@@ -4,18 +4,18 @@
|
|
|
4
4
|
[][githubactions]
|
|
5
5
|
[][githubactionstruffle]
|
|
6
6
|
[][githubactionsjruby]
|
|
7
|
-
[][qlty]
|
|
8
8
|
[][coveralls]
|
|
9
9
|
|
|
10
10
|
[gem]: https://rubygems.org/gems/omniauth
|
|
11
11
|
[githubactions]: https://github.com/omniauth/omniauth/actions/workflows/main.yml
|
|
12
12
|
[githubactionstruffle]: https://github.com/omniauth/omniauth/actions/workflows/truffle_ruby.yml
|
|
13
13
|
[githubactionsjruby]: https://github.com/omniauth/omniauth/actions/workflows/jruby.yml
|
|
14
|
-
[
|
|
14
|
+
[qlty]: https://qlty.sh/gh/omniauth/projects/omniauth
|
|
15
15
|
[coveralls]: https://coveralls.io/r/omniauth/omniauth
|
|
16
16
|
|
|
17
17
|
This is the documentation for the in-development branch of OmniAuth.
|
|
18
|
-
You can find the documentation for the latest stable release [here](https://github.com/omniauth/omniauth/tree/v2.
|
|
18
|
+
You can find the documentation for the latest stable release [here](https://github.com/omniauth/omniauth/tree/v2.3.0)
|
|
19
19
|
|
|
20
20
|
## An Introduction
|
|
21
21
|
OmniAuth is a library that standardizes multi-provider authentication for
|
|
@@ -102,21 +102,39 @@ environment information on the callback request. It is entirely up to
|
|
|
102
102
|
you how you want to implement the particulars of your application's
|
|
103
103
|
authentication flow.
|
|
104
104
|
|
|
105
|
-
##
|
|
105
|
+
## Cross-Site Request Forgery (CSRF) protection
|
|
106
106
|
|
|
107
|
-
|
|
107
|
+
OmniAuth protects the request phase (`POST /auth/:provider`) against
|
|
108
|
+
[CSRF attacks](https://owasp.org/www-community/attacks/csrf) by default.
|
|
109
|
+
It uses [`OmniAuth::AuthenticityTokenProtection`](./lib/omniauth/authenticity_token_protection.rb),
|
|
110
|
+
a subclass of `Rack::Protection::AuthenticityToken` from the
|
|
111
|
+
[rack-protection](https://rubygems.org/gems/rack-protection) gem.
|
|
112
|
+
|
|
113
|
+
You can pass `Rack::Protection::AuthenticityToken` options to match how
|
|
114
|
+
your app stores its token. For example, to work with
|
|
115
|
+
[rack_csrf](https://github.com/baldowl/rack_csrf):
|
|
108
116
|
|
|
109
117
|
```ruby
|
|
110
|
-
OmniAuth::AuthenticityTokenProtection.default_options(
|
|
118
|
+
OmniAuth::AuthenticityTokenProtection.default_options(
|
|
119
|
+
key: "csrf.token",
|
|
120
|
+
authenticity_param: "_csrf"
|
|
121
|
+
)
|
|
111
122
|
```
|
|
112
123
|
|
|
124
|
+
`Rack::Protection::AuthenticityToken` expects Base64-encoded tokens. If
|
|
125
|
+
your app handles CSRF tokens differently, use the `allow_if` option to
|
|
126
|
+
implement your own check.
|
|
127
|
+
|
|
128
|
+
For Rails, see [Rails (without Devise)](#rails-without-devise). For
|
|
129
|
+
more options, see the
|
|
130
|
+
[rack-protection documentation](https://www.rubydoc.info/gems/rack-protection/Rack/Protection/AuthenticityToken).
|
|
131
|
+
|
|
113
132
|
## Rails (without Devise)
|
|
114
|
-
To get started, add the
|
|
133
|
+
To get started, add the gem
|
|
115
134
|
|
|
116
135
|
**Gemfile**:
|
|
117
136
|
```ruby
|
|
118
137
|
gem 'omniauth'
|
|
119
|
-
gem "omniauth-rails_csrf_protection"
|
|
120
138
|
```
|
|
121
139
|
|
|
122
140
|
Then insert OmniAuth as a middleware
|
|
@@ -126,8 +144,14 @@ Then insert OmniAuth as a middleware
|
|
|
126
144
|
Rails.application.config.middleware.use OmniAuth::Builder do
|
|
127
145
|
provider :developer if Rails.env.development?
|
|
128
146
|
end
|
|
147
|
+
|
|
148
|
+
OmniAuth.config.request_validation_phase = OmniAuth::AuthenticityTokenProtection.new(key: :_csrf_token)
|
|
129
149
|
```
|
|
130
150
|
|
|
151
|
+
The last line makes OmniAuth check the CSRF token Rails stores in the
|
|
152
|
+
session (`_csrf_token`), so the request phase uses the same token as
|
|
153
|
+
your forms.
|
|
154
|
+
|
|
131
155
|
Additional providers can be added here in the future. Next we wire it
|
|
132
156
|
all up using routes, a controller and a login view.
|
|
133
157
|
|
|
@@ -147,16 +171,14 @@ class SessionsController < ApplicationController
|
|
|
147
171
|
|
|
148
172
|
def create
|
|
149
173
|
user_info = request.env['omniauth.auth']
|
|
150
|
-
raise user_info # Your own session management should be placed here.
|
|
174
|
+
raise user_info.inspect # Your own session management should be placed here.
|
|
151
175
|
end
|
|
152
176
|
end
|
|
153
177
|
```
|
|
154
178
|
|
|
155
179
|
**app/views/sessions/new.html.erb**:
|
|
156
180
|
```erb
|
|
157
|
-
<%=
|
|
158
|
-
<button type='submit'>Login with Developer</button>
|
|
159
|
-
<% end %>
|
|
181
|
+
<%= button_to "Login with Developer", "/auth/developer", data: { turbo: false } %>
|
|
160
182
|
```
|
|
161
183
|
|
|
162
184
|
Now if you visit `/login` and click the Login button, you should see the
|
|
@@ -208,9 +230,42 @@ to `STDOUT` but you can configure this using `OmniAuth.config.logger`:
|
|
|
208
230
|
OmniAuth.config.logger = Rails.logger
|
|
209
231
|
```
|
|
210
232
|
|
|
233
|
+
## Full Host
|
|
234
|
+
OmniAuth builds the callback URL it sends to the provider from the
|
|
235
|
+
request's scheme and host. The host comes from the `Host` header, or
|
|
236
|
+
from `X-Forwarded-Host` or `Forwarded` when present, and a client can
|
|
237
|
+
forge any of them. A forged host sends the provider a `redirect_uri` on
|
|
238
|
+
someone else's site, so unless your app or a proxy in front of it
|
|
239
|
+
checks the host (as Rails does with `config.hosts`), tell OmniAuth which
|
|
240
|
+
host to use.
|
|
241
|
+
|
|
242
|
+
The simplest way is to set the host yourself, either for every provider
|
|
243
|
+
or for one, as a string or as a proc that takes the Rack env. A proc
|
|
244
|
+
shouldn't return a host taken from the request without checking it.
|
|
245
|
+
|
|
246
|
+
```ruby
|
|
247
|
+
OmniAuth.config.full_host = 'https://example.com'
|
|
248
|
+
provider :twitter, ENV['KEY'], ENV['SECRET'], full_host: 'https://admin.example.com'
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
A provider's `full_host` option takes precedence over `OmniAuth.config.full_host`.
|
|
252
|
+
|
|
253
|
+
If your app serves several hosts, list them instead. A string matches
|
|
254
|
+
the whole host, ignoring case, and a regexp must match the whole host.
|
|
255
|
+
A request on any other host fails with `invalid_host`.
|
|
256
|
+
|
|
257
|
+
```ruby
|
|
258
|
+
OmniAuth.config.allowed_hosts = ['example.com', /[a-z0-9-]+\.example\.com/]
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
Until one of these is set, OmniAuth logs a warning at the start of every
|
|
262
|
+
request phase.
|
|
263
|
+
|
|
211
264
|
## Origin Param
|
|
212
|
-
The `origin`
|
|
213
|
-
and where, should you choose to use it, they'd want to return to.
|
|
265
|
+
The `origin` parameter is typically used to inform where a user came from
|
|
266
|
+
and where, should you choose to use it, they'd want to return to. Send it in
|
|
267
|
+
the query string or, since the request phase is a POST, as a field in the
|
|
268
|
+
request form, e.g. `<input type="hidden" name="origin" value="[URL]">`.
|
|
214
269
|
Omniauth supports the following settings which can be configured on a provider level:
|
|
215
270
|
|
|
216
271
|
**Default**:
|
|
@@ -235,24 +290,110 @@ POST /auth/twitter
|
|
|
235
290
|
# Note that `omniauth.origin` will always be blank.
|
|
236
291
|
```
|
|
237
292
|
|
|
293
|
+
**Validate the origin before redirecting to it.** It comes from a request
|
|
294
|
+
parameter or the `Referer` header, so anyone can set it to any URL.
|
|
295
|
+
Redirecting to it unchecked (for example `redirect_to
|
|
296
|
+
request.env['omniauth.origin']`) makes your app an open redirect. Only
|
|
297
|
+
follow it if it's a path on your own site, and fall back to a default
|
|
298
|
+
otherwise:
|
|
299
|
+
|
|
300
|
+
```ruby
|
|
301
|
+
# A local path: starts with one slash, not // or /\ (which browsers
|
|
302
|
+
# treat as another host).
|
|
303
|
+
origin = request.env['omniauth.origin'].to_s
|
|
304
|
+
redirect_to(origin.match?(%r{\A/(?![/\\])}) ? origin : root_path)
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
The `Referer` fallback gives a full URL, which this check rejects. To
|
|
308
|
+
accept those too, parse the URL and compare its host with your own.
|
|
309
|
+
|
|
310
|
+
## The Rack Environment
|
|
311
|
+
OmniAuth passes information to your application in the Rack environment
|
|
312
|
+
(`request.env` in Rails).
|
|
313
|
+
|
|
314
|
+
On the callback request (`/auth/:provider/callback`):
|
|
315
|
+
|
|
316
|
+
| Key | Value |
|
|
317
|
+
| --- | --- |
|
|
318
|
+
| `omniauth.auth` | The [Authentication Hash](https://github.com/omniauth/omniauth/wiki/Auth-Hash-Schema) for the user who just signed in. |
|
|
319
|
+
| `omniauth.origin` | Where the user came from, if known (see [Origin Param](#origin-param)). |
|
|
320
|
+
| `omniauth.params` | The params sent to the request phase (`/auth/:provider`), from both the query string and the form, except `authenticity_token`. An empty hash if there were none. |
|
|
321
|
+
| `omniauth.strategy` | The strategy instance handling the request. Also set on the request phase and on the setup path. |
|
|
322
|
+
|
|
323
|
+
When authentication fails, OmniAuth calls `OmniAuth.config.on_failure`
|
|
324
|
+
with the environment, which also includes:
|
|
325
|
+
|
|
326
|
+
| Key | Value |
|
|
327
|
+
| --- | --- |
|
|
328
|
+
| `omniauth.error` | The exception that caused the failure, if there was one. |
|
|
329
|
+
| `omniauth.error.type` | A symbol describing the failure, such as `:invalid_credentials`. |
|
|
330
|
+
| `omniauth.error.strategy` | The strategy instance that failed. |
|
|
331
|
+
|
|
332
|
+
`omniauth.origin` and `omniauth.params` come from the user's request, so
|
|
333
|
+
treat them like any other request params and validate them before use.
|
|
334
|
+
|
|
335
|
+
The default `on_failure` raises the error in development and otherwise
|
|
336
|
+
redirects to `/auth/failure` with the `message`, `strategy`, and
|
|
337
|
+
`origin` as query string parameters.
|
|
338
|
+
|
|
339
|
+
## Session Cookies and SameSite
|
|
340
|
+
OmniAuth keeps its state between the request and callback phases (for
|
|
341
|
+
example the OAuth `state` parameter, `omniauth.origin`, and
|
|
342
|
+
`omniauth.params`) in the Rack session. When the provider redirects or
|
|
343
|
+
POSTs back to your callback from its own domain, the browser has to send
|
|
344
|
+
your session cookie with that cross-site request, or the callback fails
|
|
345
|
+
(often with a `csrf_detected` or invalid `state` error).
|
|
346
|
+
|
|
347
|
+
- With `SameSite=Lax`, the default in Rails and in modern browsers, the
|
|
348
|
+
cookie is sent on top-level GET redirects back to your app, which covers
|
|
349
|
+
most OAuth and OpenID Connect flows.
|
|
350
|
+
- With `SameSite=Strict`, it isn't, so the callback sees an empty session.
|
|
351
|
+
Use `Lax` for the session cookie, or make the callback a same-site
|
|
352
|
+
request by first answering it with a page that immediately reloads the
|
|
353
|
+
same URL (for example with `<meta http-equiv="refresh">`), after which
|
|
354
|
+
the browser sends the cookie.
|
|
355
|
+
- Providers that POST to the callback (such as SAML's HTTP-POST binding or
|
|
356
|
+
OpenID Connect's `form_post` response mode) need `SameSite=None; Secure`.
|
|
357
|
+
|
|
358
|
+
## Several Sign-Ins at Once
|
|
359
|
+
By default the session holds one `omniauth.origin` and `omniauth.params`,
|
|
360
|
+
so if a user starts a second sign-in before the first finishes (in another
|
|
361
|
+
tab, for example), the first one's callback gets the second one's origin
|
|
362
|
+
and params.
|
|
363
|
+
|
|
364
|
+
A strategy can keep them apart when its provider sends a value from the
|
|
365
|
+
request phase back to the callback, such as OAuth 2.0's `state`. Its
|
|
366
|
+
request phase calls `remember_sign_in` with that value, and it overrides
|
|
367
|
+
`callback_sign_in_key` to return the value from the callback:
|
|
368
|
+
|
|
369
|
+
```ruby
|
|
370
|
+
def request_phase
|
|
371
|
+
state = SecureRandom.hex(24)
|
|
372
|
+
remember_sign_in(state)
|
|
373
|
+
redirect authorize_url(state)
|
|
374
|
+
end
|
|
375
|
+
|
|
376
|
+
def callback_sign_in_key
|
|
377
|
+
request.params['state']
|
|
378
|
+
end
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
OmniAuth then stores the origin and params of the latest 5 sign-ins under
|
|
382
|
+
their keys in `session['omniauth.sign_ins']`, and gives each callback its
|
|
383
|
+
own. It still sets `omniauth.origin` and `omniauth.params` in the session
|
|
384
|
+
for the latest sign-in, and falls back to them when a callback's key isn't
|
|
385
|
+
remembered.
|
|
386
|
+
|
|
238
387
|
## Resources
|
|
239
388
|
The [OmniAuth Wiki](https://github.com/omniauth/omniauth/wiki) has
|
|
240
389
|
actively maintained in-depth documentation for OmniAuth. It should be
|
|
241
390
|
your first stop if you are wondering about a more in-depth look at
|
|
242
391
|
OmniAuth, how it works, and how to use it.
|
|
243
392
|
|
|
244
|
-
## OmniAuth for Enterprise
|
|
245
|
-
|
|
246
|
-
Available as part of the Tidelift Subscription.
|
|
247
|
-
|
|
248
|
-
The maintainers of OmniAuth and thousands of other packages are working with
|
|
249
|
-
Tidelift to deliver commercial support and maintenance for the open source
|
|
250
|
-
packages you use to build your applications. Save time, reduce risk, and
|
|
251
|
-
improve code health, while paying the maintainers of the exact packages you use.
|
|
252
|
-
[Learn more.](https://tidelift.com/subscription/pkg/rubygems-omniauth?utm_source=undefined&utm_medium=referral&utm_campaign=enterprise&utm_term=repo)
|
|
253
|
-
|
|
254
393
|
## Supported Ruby Versions
|
|
255
|
-
OmniAuth
|
|
394
|
+
OmniAuth requires Ruby 2.5 or later and Rack 2.2.8 or later, including Rack 3.
|
|
395
|
+
It is tested on Ruby 2.5 through 4.0, with both Rack 2 and Rack 3, and on JRuby
|
|
396
|
+
and TruffleRuby.
|
|
256
397
|
|
|
257
398
|
## Versioning
|
|
258
399
|
This library aims to adhere to [Semantic Versioning 2.0.0][semver]. Violations
|
|
@@ -264,13 +405,13 @@ introduced with new major versions. As a result of this policy, you can (and
|
|
|
264
405
|
should) specify a dependency on this gem using the [Pessimistic Version
|
|
265
406
|
Constraint][pvc] with two digits of precision. For example:
|
|
266
407
|
|
|
267
|
-
spec.add_dependency 'omniauth', '~>
|
|
408
|
+
spec.add_dependency 'omniauth', '~> 2.2'
|
|
268
409
|
|
|
269
|
-
[semver]:
|
|
270
|
-
[pvc]:
|
|
410
|
+
[semver]: https://semver.org/
|
|
411
|
+
[pvc]: https://guides.rubygems.org/patterns/#pessimistic-version-constraint
|
|
271
412
|
|
|
272
413
|
## License
|
|
273
|
-
Copyright (c) 2010-
|
|
414
|
+
Copyright (c) 2010-2026 Michael Bleigh and Intridea, Inc. See [LICENSE][] for
|
|
274
415
|
details.
|
|
275
416
|
|
|
276
417
|
[license]: LICENSE.md
|
data/SECURITY.md
CHANGED
|
@@ -7,12 +7,14 @@ currently being supported with security updates.
|
|
|
7
7
|
|
|
8
8
|
| Version | Supported |
|
|
9
9
|
| ------- | ------------------ |
|
|
10
|
+
| 2.3.x | :white_check_mark: |
|
|
11
|
+
| 2.2.x | :white_check_mark: |
|
|
10
12
|
| 2.1.x | :white_check_mark: |
|
|
11
13
|
| 2.0.x | :white_check_mark: |
|
|
12
14
|
| <= 1.9.1 | :x: |
|
|
13
15
|
|
|
14
16
|
## Security contact information
|
|
15
17
|
|
|
16
|
-
To report a security vulnerability, please use
|
|
17
|
-
[
|
|
18
|
-
|
|
18
|
+
To report a security vulnerability, please use GitHub's
|
|
19
|
+
[private vulnerability reporting](https://github.com/omniauth/omniauth/security/advisories/new)
|
|
20
|
+
rather than opening a public issue.
|
data/lib/omniauth/auth_hash.rb
CHANGED
|
@@ -16,11 +16,12 @@ module OmniAuth
|
|
|
16
16
|
# valid info hash. See InfoHash#valid? for
|
|
17
17
|
# more details there.
|
|
18
18
|
def valid?
|
|
19
|
-
|
|
19
|
+
info = info()
|
|
20
|
+
uid? && provider? && !info.nil? && info.valid?
|
|
20
21
|
end
|
|
21
22
|
|
|
22
23
|
def regular_writer(key, value)
|
|
23
|
-
value = InfoHash.new(value) if key.
|
|
24
|
+
value = InfoHash.new(value) if key.eql?('info') && value.is_a?(Hash) && !value.is_a?(InfoHash)
|
|
24
25
|
super
|
|
25
26
|
end
|
|
26
27
|
|
|
@@ -30,12 +31,11 @@ module OmniAuth
|
|
|
30
31
|
end
|
|
31
32
|
|
|
32
33
|
def name
|
|
33
|
-
return
|
|
34
|
+
return fetch(:name) if self[:name]
|
|
34
35
|
return "#{first_name} #{last_name}".strip if first_name? || last_name?
|
|
35
36
|
return nickname if nickname?
|
|
36
|
-
return email if email?
|
|
37
37
|
|
|
38
|
-
|
|
38
|
+
email if email?
|
|
39
39
|
end
|
|
40
40
|
|
|
41
41
|
def name?
|
|
@@ -43,11 +43,37 @@ module OmniAuth
|
|
|
43
43
|
end
|
|
44
44
|
alias valid? name?
|
|
45
45
|
|
|
46
|
+
# slice, except, select, and reject return a subset of the info,
|
|
47
|
+
# which shouldn't gain a calculated name when converted with #to_hash.
|
|
48
|
+
def slice(*keys)
|
|
49
|
+
subset(super)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def except(*keys)
|
|
53
|
+
subset(super)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def select
|
|
57
|
+
subset(super)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def reject
|
|
61
|
+
subset(super)
|
|
62
|
+
end
|
|
63
|
+
|
|
46
64
|
def to_hash
|
|
47
65
|
hash = super
|
|
48
|
-
hash['name'] ||= name
|
|
66
|
+
hash['name'] ||= name unless instance_variable_defined?(:@subset)
|
|
49
67
|
hash
|
|
50
68
|
end
|
|
69
|
+
|
|
70
|
+
private
|
|
71
|
+
|
|
72
|
+
# Only whether @subset is defined matters, not its value.
|
|
73
|
+
def subset(info)
|
|
74
|
+
info.instance_variable_set(:@subset, nil)
|
|
75
|
+
info
|
|
76
|
+
end
|
|
51
77
|
end
|
|
52
78
|
end
|
|
53
79
|
end
|
|
@@ -2,9 +2,11 @@ require 'rack-protection'
|
|
|
2
2
|
|
|
3
3
|
module OmniAuth
|
|
4
4
|
class AuthenticityError < StandardError; end
|
|
5
|
+
|
|
5
6
|
class AuthenticityTokenProtection < Rack::Protection::AuthenticityToken
|
|
7
|
+
# Used as a validation hook rather than as middleware, so there's no app.
|
|
6
8
|
def initialize(options = {})
|
|
7
|
-
|
|
9
|
+
super(nil, options)
|
|
8
10
|
end
|
|
9
11
|
|
|
10
12
|
def self.call(env)
|
|
@@ -18,13 +20,13 @@ module OmniAuth
|
|
|
18
20
|
react env
|
|
19
21
|
end
|
|
20
22
|
|
|
21
|
-
|
|
23
|
+
alias call call!
|
|
22
24
|
|
|
23
25
|
private
|
|
24
26
|
|
|
25
27
|
def deny(_env)
|
|
26
|
-
OmniAuth.logger.
|
|
27
|
-
raise AuthenticityError.new(options
|
|
28
|
+
OmniAuth.logger.warn("Attack prevented by #{self.class}")
|
|
29
|
+
raise AuthenticityError.new(options.fetch(:message))
|
|
28
30
|
end
|
|
29
31
|
|
|
30
32
|
alias default_reaction deny
|
data/lib/omniauth/builder.rb
CHANGED
|
@@ -25,17 +25,18 @@ module OmniAuth
|
|
|
25
25
|
end
|
|
26
26
|
|
|
27
27
|
def options(options = false)
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
@options = options
|
|
28
|
+
case options
|
|
29
|
+
when false then @options ||= {}
|
|
30
|
+
else @options = options
|
|
31
|
+
end
|
|
31
32
|
end
|
|
32
33
|
|
|
33
34
|
def provider(klass, *args, **opts, &block)
|
|
34
|
-
if klass.
|
|
35
|
+
if klass.instance_of?(Class)
|
|
35
36
|
middleware = klass
|
|
36
37
|
else
|
|
37
38
|
begin
|
|
38
|
-
middleware =
|
|
39
|
+
middleware = Strategies.const_get(Utils.camelize(klass), false)
|
|
39
40
|
rescue NameError
|
|
40
41
|
raise(LoadError.new("Could not find matching strategy for #{klass.inspect}. You may need to install an additional gem (such as omniauth-#{klass})."))
|
|
41
42
|
end
|
|
@@ -44,8 +45,10 @@ module OmniAuth
|
|
|
44
45
|
use middleware, *args, **options.merge(opts), &block
|
|
45
46
|
end
|
|
46
47
|
|
|
48
|
+
# Rack::Builder#call rebuilds the whole middleware stack on every
|
|
49
|
+
# request. Build it on the first request and reuse it after that.
|
|
47
50
|
def call(env)
|
|
48
|
-
to_app.call(env)
|
|
51
|
+
(@built_app ||= to_app).call(env)
|
|
49
52
|
end
|
|
50
53
|
end
|
|
51
54
|
end
|
|
@@ -22,7 +22,7 @@ module OmniAuth
|
|
|
22
22
|
end
|
|
23
23
|
|
|
24
24
|
def raise_out!
|
|
25
|
-
raise(env['omniauth.error'] ||
|
|
25
|
+
raise(env['omniauth.error'] || Error.new(env['omniauth.error.type']))
|
|
26
26
|
end
|
|
27
27
|
|
|
28
28
|
def redirect_to_failure
|
|
@@ -34,7 +34,7 @@ module OmniAuth
|
|
|
34
34
|
|
|
35
35
|
def strategy_path_prefix
|
|
36
36
|
if env['omniauth.error.strategy']
|
|
37
|
-
env
|
|
37
|
+
env.fetch('omniauth.error.strategy').path_prefix
|
|
38
38
|
else
|
|
39
39
|
OmniAuth.config.path_prefix
|
|
40
40
|
end
|
|
@@ -43,13 +43,13 @@ module OmniAuth
|
|
|
43
43
|
def strategy_name_query_param
|
|
44
44
|
return '' unless env['omniauth.error.strategy']
|
|
45
45
|
|
|
46
|
-
"&strategy=#{env
|
|
46
|
+
"&strategy=#{env.fetch('omniauth.error.strategy').name}"
|
|
47
47
|
end
|
|
48
48
|
|
|
49
49
|
def origin_query_param
|
|
50
50
|
return '' unless env['omniauth.origin']
|
|
51
51
|
|
|
52
|
-
"&origin=#{Rack::Utils.escape(env
|
|
52
|
+
"&origin=#{Rack::Utils.escape(env.fetch('omniauth.origin'))}"
|
|
53
53
|
end
|
|
54
54
|
end
|
|
55
55
|
end
|
data/lib/omniauth/form.rb
CHANGED
|
@@ -13,12 +13,12 @@ module OmniAuth
|
|
|
13
13
|
@html = +'' # unary + string allows it to be mutable if strings are frozen
|
|
14
14
|
@with_custom_button = false
|
|
15
15
|
@footer = nil
|
|
16
|
-
header(options
|
|
16
|
+
header(options.fetch(:title), options.fetch(:header_info))
|
|
17
17
|
end
|
|
18
18
|
|
|
19
19
|
def self.build(options = {}, &block)
|
|
20
|
-
form =
|
|
21
|
-
if block.arity
|
|
20
|
+
form = Form.new(options)
|
|
21
|
+
if block.arity.positive?
|
|
22
22
|
yield form
|
|
23
23
|
else
|
|
24
24
|
form.instance_eval(&block)
|
|
@@ -39,13 +39,11 @@ module OmniAuth
|
|
|
39
39
|
def text_field(label, name)
|
|
40
40
|
label_field(label, name)
|
|
41
41
|
input_field('text', name)
|
|
42
|
-
self
|
|
43
42
|
end
|
|
44
43
|
|
|
45
44
|
def password_field(label, name)
|
|
46
45
|
label_field(label, name)
|
|
47
46
|
input_field('password', name)
|
|
48
|
-
self
|
|
49
47
|
end
|
|
50
48
|
|
|
51
49
|
def button(text)
|
|
@@ -58,7 +56,7 @@ module OmniAuth
|
|
|
58
56
|
end
|
|
59
57
|
|
|
60
58
|
def fieldset(legend, options = {}, &block)
|
|
61
|
-
@html << "\n<fieldset#{" style='#{options
|
|
59
|
+
@html << "\n<fieldset#{" style='#{options.fetch(:style)}'" if options[:style]}#{" id='#{options.fetch(:id)}'" if options[:id]}>\n <legend>#{legend}</legend>\n"
|
|
62
60
|
instance_eval(&block)
|
|
63
61
|
@html << "\n</fieldset>"
|
|
64
62
|
self
|
|
@@ -76,7 +74,7 @@ module OmniAuth
|
|
|
76
74
|
</head>
|
|
77
75
|
<body>
|
|
78
76
|
<h1>#{title}</h1>
|
|
79
|
-
<form method='#{options
|
|
77
|
+
<form method='#{options.fetch(:method)}' #{"action='#{options.fetch(:url)}' " if options[:url]}noValidate='noValidate'>
|
|
80
78
|
HTML
|
|
81
79
|
self
|
|
82
80
|
end
|
data/lib/omniauth/key_store.rb
CHANGED
|
@@ -3,17 +3,9 @@ require 'hashie/mash'
|
|
|
3
3
|
module OmniAuth
|
|
4
4
|
# Generic helper hash that allows method access on deeply nested keys.
|
|
5
5
|
class KeyStore < ::Hashie::Mash
|
|
6
|
-
# Disables warnings
|
|
6
|
+
# Disables Hashie's warnings when a key overrides a Mash method
|
|
7
7
|
def self.override_logging
|
|
8
|
-
|
|
9
|
-
return unless Gem::Version.new(Hashie::VERSION) >= Gem::Version.new('3.5.0')
|
|
10
|
-
|
|
11
|
-
if respond_to?(:disable_warnings)
|
|
12
|
-
disable_warnings
|
|
13
|
-
else
|
|
14
|
-
define_method(:log_built_in_message) { |*| }
|
|
15
|
-
private :log_built_in_message
|
|
16
|
-
end
|
|
8
|
+
disable_warnings
|
|
17
9
|
end
|
|
18
10
|
|
|
19
11
|
# Disable on loading of the class
|
|
@@ -37,7 +37,8 @@ module OmniAuth
|
|
|
37
37
|
def request_phase
|
|
38
38
|
form = OmniAuth::Form.new(:title => 'User Info', :url => callback_path, :method => 'get')
|
|
39
39
|
options.fields.each do |field|
|
|
40
|
-
|
|
40
|
+
name = field.to_s
|
|
41
|
+
form.text_field name.capitalize.tr('_', ' '), name
|
|
41
42
|
end
|
|
42
43
|
form.button 'Sign In'
|
|
43
44
|
form.to_response
|
|
@@ -48,10 +49,7 @@ module OmniAuth
|
|
|
48
49
|
end
|
|
49
50
|
|
|
50
51
|
info do
|
|
51
|
-
options.fields.
|
|
52
|
-
hash[field] = request.params[field.to_s]
|
|
53
|
-
hash
|
|
54
|
-
end
|
|
52
|
+
options.fields.collect { |field| [field, request.params[field.to_s]] }.to_h
|
|
55
53
|
end
|
|
56
54
|
end
|
|
57
55
|
end
|