omniauth 1.9.2 → 2.1.2

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: 35d19268ad77477704f29c8bb7aa989bc4fd087dfc75cad3757f0dba77615ab0
4
- data.tar.gz: 7d6405feca4e14d010330e2c577aa815b7593de7ebc2591e9b45c266af3e05b5
3
+ metadata.gz: 0de71776aec3f0b016291d25d87fed25bbfa49f5fcd0abcf0f7463be97111e92
4
+ data.tar.gz: dd52494efab1533e54f3a85ceab332db16e02ff6d633a00c99f52d7f089303ef
5
5
  SHA512:
6
- metadata.gz: f2f0a59be54f42f5c6747e9601599eee747d0220c8cfbfd3037e713840453c29598b325beae1e0ca8c41db8581d02cd1adada18d1dcfb5afe8cab2fb8c5c7e61
7
- data.tar.gz: 945998eec68b09718830c23c75ca2cd1ad23da58f9541d38c39ec0c4c08b587cb35827390a003c3c1fb551793d2b5a1ade0cf354236035c6489b229fa66a699f
6
+ metadata.gz: 16de198d83402c9613961994c0fe1f1c9fc709de6a546168830248c237e2fe61f0847e129f94a4bf51570cbb8beffa4e20b6542e23a342a17aa41bd8c2738200
7
+ data.tar.gz: f703bef08321f981909d950dba902989b5efb5d4c820b9f6b03c5695bbe56620e2656bfd75d527101ed3d7cdc78dd4c886f2e4991f12c01ea170e1ad900b3245
@@ -0,0 +1,2 @@
1
+ github: bobbymcwho
2
+ tidelift: rubygems/omniauth
@@ -0,0 +1,18 @@
1
+ # To get started with Dependabot version updates, you'll need to specify which
2
+ # package ecosystems to update and where the package manifests are located.
3
+ # Please see the documentation for all configuration options:
4
+ # https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
5
+
6
+ version: 2
7
+ updates:
8
+ - package-ecosystem: bundler
9
+ directory: '/'
10
+ schedule:
11
+ interval: weekly
12
+ open-pull-requests-limit: 99
13
+
14
+ - package-ecosystem: github-actions
15
+ directory: '/'
16
+ schedule:
17
+ interval: daily
18
+ open-pull-requests-limit: 99
@@ -0,0 +1,28 @@
1
+ name: JRuby
2
+ on:
3
+ push:
4
+ branches: [ master ]
5
+ pull_request:
6
+ branches: [ master ]
7
+
8
+ jobs:
9
+ test:
10
+ runs-on: ${{ matrix.os }}-latest
11
+ strategy:
12
+ fail-fast: false
13
+ matrix:
14
+ os: [ubuntu, macos]
15
+ jruby: [jruby, jruby-head]
16
+ steps:
17
+ - uses: actions/checkout@v3
18
+ - name: Set up Ruby
19
+ uses: ruby/setup-ruby@v1
20
+ with:
21
+ ruby-version: ${{ matrix.jruby }}
22
+ bundler-cache: true
23
+ env:
24
+ JRUBY_OPTS: --debug
25
+ - name: Run tests
26
+ env:
27
+ JRUBY_OPTS: --debug
28
+ run: bundle exec rake
@@ -0,0 +1,61 @@
1
+ # This workflow uses actions that are not certified by GitHub.
2
+ # They are provided by a third-party and are governed by
3
+ # separate terms of service, privacy policy, and support
4
+ # documentation.
5
+ # This workflow will download a prebuilt Ruby version, install dependencies and run tests with Rake
6
+ # For more information see: https://github.com/marketplace/actions/setup-ruby-jruby-and-truffleruby
7
+
8
+ name: Ruby
9
+
10
+ on:
11
+ push:
12
+ branches: [ master ]
13
+ pull_request:
14
+ branches: [ master ]
15
+
16
+ jobs:
17
+ test:
18
+ runs-on: ${{ matrix.os }}-latest
19
+ strategy:
20
+ fail-fast: false
21
+ matrix:
22
+ os: [ubuntu, macos]
23
+ ruby: [2.5, 2.6, 2.7, '3.0', 3.1, 3.2, head, debug]
24
+ steps:
25
+ - uses: actions/checkout@v3
26
+ - name: Set up Ruby
27
+ uses: ruby/setup-ruby@v1
28
+ with:
29
+ ruby-version: ${{ matrix.ruby }}
30
+ bundler-cache: true
31
+ - name: Run tests
32
+ run: bundle exec rake
33
+ frozen-string-compat:
34
+ runs-on: ubuntu-latest
35
+ steps:
36
+ - uses: actions/checkout@v3
37
+ - name: Set up Ruby
38
+ uses: ruby/setup-ruby@v1
39
+ with:
40
+ ruby-version: 2.6
41
+ bundler-cache: true
42
+ - name: Run tests
43
+ env:
44
+ RUBYOPT: "--enable-frozen-string-literal"
45
+ run: bundle exec rake
46
+ coveralls:
47
+ runs-on: ubuntu-latest
48
+ steps:
49
+ - uses: actions/checkout@v3
50
+ - name: Set up Ruby
51
+ uses: ruby/setup-ruby@v1
52
+ with:
53
+ ruby-version: 2.6
54
+ bundler-cache: true
55
+ - name: Run tests
56
+ run: bundle exec rake
57
+ - name: Coveralls GitHub Action
58
+ uses: coverallsapp/github-action@v2
59
+ with:
60
+ github-token: ${{ secrets.github_token }}
61
+ path-to-lcov: './coverage/lcov/omniauth.lcov'
@@ -0,0 +1,24 @@
1
+ name: TruffleRuby
2
+ on:
3
+ push:
4
+ branches: [ master ]
5
+ pull_request:
6
+ branches: [ master ]
7
+
8
+ jobs:
9
+ test:
10
+ runs-on: ${{ matrix.os }}-latest
11
+ strategy:
12
+ fail-fast: false
13
+ matrix:
14
+ os: [ubuntu, macos]
15
+ ruby: [truffleruby, truffleruby-head]
16
+ steps:
17
+ - uses: actions/checkout@v3
18
+ - name: Set up Ruby
19
+ uses: ruby/setup-ruby@v1
20
+ with:
21
+ ruby-version: ${{ matrix.ruby }}
22
+ bundler-cache: true
23
+ - name: Run tests
24
+ run: bundle exec rake
data/.gitignore CHANGED
@@ -10,3 +10,5 @@ doc/*
10
10
  log/*
11
11
  measurement/*
12
12
  pkg/*
13
+ .DS_Store
14
+ .tool-versions
data/Gemfile CHANGED
@@ -1,6 +1,6 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
- gem 'jruby-openssl', '~> 0.9.19', :platforms => :jruby
3
+ gem 'jruby-openssl', '~> 0.10.5', platforms: :jruby
4
4
  gem 'rake', '>= 12.0'
5
5
  gem 'yard', '>= 0.9.11'
6
6
 
@@ -12,16 +12,12 @@ group :development do
12
12
  end
13
13
 
14
14
  group :test do
15
- gem 'coveralls', :require => false
16
- gem 'hashie', '>= 3.4.6', '~> 4.0.0', :platforms => [:jruby_18]
17
- gem 'json', '~> 2.0.3', :platforms => %i[jruby_18 jruby_19 ruby_19]
18
- gem 'mime-types', '~> 3.1', :platforms => [:jruby_18]
19
- gem 'rack', '>= 2.0.6', :platforms => %i[jruby_18 jruby_19 ruby_19 ruby_20 ruby_21]
15
+ gem 'coveralls_reborn', '~> 0.19.0', require: false
20
16
  gem 'rack-test'
21
- gem 'rest-client', '~> 2.0.0', :platforms => [:jruby_18]
22
- gem 'rspec', '~> 3.5.0'
23
- gem 'rubocop', '>= 0.58.2', '< 0.69.0', :platforms => %i[ruby_20 ruby_21 ruby_22 ruby_23 ruby_24]
24
- gem 'tins', '~> 1.13.0', :platforms => %i[jruby_18 jruby_19 ruby_19]
17
+ gem 'rspec', '~> 3.5'
18
+ gem 'rack-freeze'
19
+ gem 'rubocop', '>= 0.58.2', '< 0.69.0', platforms: %i[ruby_22 ruby_23 ruby_24]
20
+ gem 'simplecov-lcov'
25
21
  end
26
22
 
27
23
  gemspec
data/README.md CHANGED
@@ -1,16 +1,22 @@
1
1
  # OmniAuth: Standardized Multi-Provider Authentication
2
2
 
3
3
  [![Gem Version](http://img.shields.io/gem/v/omniauth.svg)][gem]
4
- [![Build Status](http://img.shields.io/travis/omniauth/omniauth.svg)][travis]
5
- [![Code Climate](http://img.shields.io/codeclimate/github/omniauth/omniauth.svg)][codeclimate]
4
+ [![Ruby](https://github.com/omniauth/omniauth/actions/workflows/main.yml/badge.svg)][githubactions]
5
+ [![TruffleRuby](https://github.com/omniauth/omniauth/actions/workflows/truffle_ruby.yml/badge.svg)][githubactionstruffle]
6
+ [![JRuby](https://github.com/omniauth/omniauth/actions/workflows/jruby.yml/badge.svg)][githubactionsjruby]
7
+ [![Code Climate](https://api.codeclimate.com/v1/badges/ffd33970723587806744/maintainability)][codeclimate]
6
8
  [![Coverage Status](http://img.shields.io/coveralls/omniauth/omniauth.svg)][coveralls]
7
- [![Security](https://hakiri.io/github/omniauth/omniauth/master.svg)](https://hakiri.io/github/omniauth/omniauth/master)
8
9
 
9
10
  [gem]: https://rubygems.org/gems/omniauth
10
- [travis]: http://travis-ci.org/omniauth/omniauth
11
+ [githubactions]: https://github.com/omniauth/omniauth/actions/workflows/main.yml
12
+ [githubactionstruffle]: https://github.com/omniauth/omniauth/actions/workflows/truffle_ruby.yml
13
+ [githubactionsjruby]: https://github.com/omniauth/omniauth/actions/workflows/jruby.yml
11
14
  [codeclimate]: https://codeclimate.com/github/omniauth/omniauth
12
15
  [coveralls]: https://coveralls.io/r/omniauth/omniauth
13
16
 
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.1.2)
19
+
14
20
  ## An Introduction
15
21
  OmniAuth is a library that standardizes multi-provider authentication for
16
22
  web applications. It was created to be powerful, flexible, and do as
@@ -32,8 +38,8 @@ development and easily swap in other strategies later.
32
38
  ## Getting Started
33
39
  Each OmniAuth strategy is a Rack Middleware. That means that you can use
34
40
  it the same way that you use any other Rack middleware. For example, to
35
- use the built-in Developer strategy in a Sinatra application I might do
36
- this:
41
+ use the built-in Developer strategy in a Sinatra application you might
42
+ do this:
37
43
 
38
44
  ```ruby
39
45
  require 'sinatra'
@@ -45,7 +51,7 @@ class MyApplication < Sinatra::Base
45
51
  end
46
52
  ```
47
53
 
48
- Because OmniAuth is built for *multi-provider* authentication, I may
54
+ Because OmniAuth is built for *multi-provider* authentication, you may
49
55
  want to leave room to run multiple strategies. For this, the built-in
50
56
  `OmniAuth::Builder` class gives you an easy way to specify multiple
51
57
  strategies. Note that there is **no difference** between the following
@@ -82,33 +88,9 @@ environment of a request to `/auth/:provider/callback`. This hash
82
88
  contains as much information about the user as OmniAuth was able to
83
89
  glean from the utilized strategy. You should set up an endpoint in your
84
90
  application that matches to the callback URL and then performs whatever
85
- steps are necessary for your application. For example, in a Rails app I
86
- would add a line in my `routes.rb` file like this:
87
-
88
- ```ruby
89
- get '/auth/:provider/callback', to: 'sessions#create'
90
- ```
91
-
92
- And I might then have a `SessionsController` with code that looks
93
- something like this:
94
-
95
- ```ruby
96
- class SessionsController < ApplicationController
97
- def create
98
- @user = User.find_or_create_from_auth_hash(auth_hash)
99
- self.current_user = @user
100
- redirect_to '/'
101
- end
102
-
103
- protected
91
+ steps are necessary for your application.
104
92
 
105
- def auth_hash
106
- request.env['omniauth.auth']
107
- end
108
- end
109
- ```
110
-
111
- The `omniauth.auth` key in the environment hash gives me my
93
+ The `omniauth.auth` key in the environment hash provides an
112
94
  Authentication Hash which will contain information about the just
113
95
  authenticated user including a unique id, the strategy they just used
114
96
  for authentication, and personal details such as name and email address
@@ -120,35 +102,74 @@ environment information on the callback request. It is entirely up to
120
102
  you how you want to implement the particulars of your application's
121
103
  authentication flow.
122
104
 
123
- **Please note:** there is currently a CSRF vulnerability which affects OmniAuth (designated [CVE-2015-9284](https://nvd.nist.gov/vuln/detail/CVE-2015-9284)) that requires mitigation at the application level. More details on how to do this can be found on the [Wiki](https://github.com/omniauth/omniauth/wiki/Resolving-CVE-2015-9284).
105
+ ## rack_csrf
106
+
107
+ `omniauth` is not OOTB-compatible with [rack_csrf](https://github.com/baldowl/rack_csrf). In order to do so, the following code needs to be added to the application bootstrapping code:
124
108
 
125
- ## Configuring The `origin` Param
126
- The `origin` url parameter is typically used to inform where a user came from and where, should you choose to use it, they'd want to return to.
109
+ ```ruby
110
+ OmniAuth::AuthenticityTokenProtection.default_options(key: "csrf.token", authenticity_param: "_csrf")
111
+ ```
127
112
 
128
- There are three possible options:
113
+ ## Rails (without Devise)
114
+ To get started, add the following gems
129
115
 
130
- Default Flow:
116
+ **Gemfile**:
131
117
  ```ruby
132
- # /auth/twitter/?origin=[URL]
133
- # No change
134
- # If blank, `omniauth.origin` is set to HTTP_REFERER
118
+ gem 'omniauth'
119
+ gem "omniauth-rails_csrf_protection"
135
120
  ```
136
121
 
137
- Renaming Origin Param:
122
+ Then insert OmniAuth as a middleware
123
+
124
+ **config/initializers/omniauth.rb**:
138
125
  ```ruby
139
- # /auth/twitter/?return_to=[URL]
140
- # If blank, `omniauth.origin` is set to HTTP_REFERER
141
- provider :twitter, ENV['KEY'], ENV['SECRET'], origin_param: 'return_to'
126
+ Rails.application.config.middleware.use OmniAuth::Builder do
127
+ provider :developer if Rails.env.development?
128
+ end
142
129
  ```
143
130
 
144
- Disabling Origin Param:
131
+ Additional providers can be added here in the future. Next we wire it
132
+ all up using routes, a controller and a login view.
133
+
134
+ **config/routes.rb**:
135
+
145
136
  ```ruby
146
- # /auth/twitter
147
- # Origin handled externally, if need be. `omniauth.origin` is not set
148
- provider :twitter, ENV['KEY'], ENV['SECRET'], origin_param: false
137
+ get 'auth/:provider/callback', to: 'sessions#create'
138
+ get '/login', to: 'sessions#new'
139
+ ```
140
+
141
+ **app/controllers/sessions_controller.rb**:
142
+ ```ruby
143
+ class SessionsController < ApplicationController
144
+ def new
145
+ render :new
146
+ end
147
+
148
+ def create
149
+ user_info = request.env['omniauth.auth']
150
+ raise user_info # Your own session management should be placed here.
151
+ end
152
+ end
149
153
  ```
150
154
 
151
- ## Integrating OmniAuth Into Your Rails API
155
+ **app/views/sessions/new.html.erb**:
156
+ ```erb
157
+ <%= form_tag('/auth/developer', method: 'post', data: {turbo: false}) do %>
158
+ <button type='submit'>Login with Developer</button>
159
+ <% end %>
160
+ ```
161
+
162
+ Now if you visit `/login` and click the Login button, you should see the
163
+ OmniAuth developer login screen. After submitting it, you are returned to your
164
+ application at `Sessions#create`. The raise should now display all the Omniauth
165
+ details you have available to integrate it into your own user management.
166
+
167
+ If you want out of the box usermanagement, you should consider using Omniauth
168
+ through Devise. Please visit the [Devise Github page](https://github.com/heartcombo/devise#omniauth)
169
+ for more information.
170
+
171
+
172
+ ## Rails API
152
173
  The following middleware are (by default) included for session management in
153
174
  Rails applications. When using OmniAuth with a Rails API, you'll need to add
154
175
  one of these required middleware back in:
@@ -163,7 +184,7 @@ a `session_store.rb` initializer, add `use ActionDispatch::Session::CookieStore`
163
184
  and have sessions functioning as normal.
164
185
 
165
186
  To be clear: sessions may work, but your session options will be ignored
166
- (i.e the session key will default to `_session_id`). Instead of the
187
+ (i.e. the session key will default to `_session_id`). Instead of the
167
188
  initializer, you'll have to set the relevant options somewhere
168
189
  before your middleware is built (like `application.rb`) and pass them to your
169
190
  preferred middleware, like this:
@@ -187,14 +208,51 @@ to `STDOUT` but you can configure this using `OmniAuth.config.logger`:
187
208
  OmniAuth.config.logger = Rails.logger
188
209
  ```
189
210
 
211
+ ## Origin Param
212
+ The `origin` url parameter is typically used to inform where a user came from
213
+ and where, should you choose to use it, they'd want to return to.
214
+ Omniauth supports the following settings which can be configured on a provider level:
215
+
216
+ **Default**:
217
+ ```ruby
218
+ provider :twitter, ENV['KEY'], ENV['SECRET']
219
+ POST /auth/twitter/?origin=[URL]
220
+ # If the `origin` parameter is blank, `omniauth.origin` is set to HTTP_REFERER
221
+ ```
222
+
223
+ **Using a differently named origin parameter**:
224
+ ```ruby
225
+ provider :twitter, ENV['KEY'], ENV['SECRET'], origin_param: 'return_to'
226
+ POST /auth/twitter/?return_to=[URL]
227
+ # If the `return_to` parameter is blank, `omniauth.origin` is set to HTTP_REFERER
228
+ ```
229
+
230
+ **Disabled**:
231
+ ```ruby
232
+ provider :twitter, ENV['KEY'], ENV['SECRET'], origin_param: false
233
+ POST /auth/twitter
234
+ # This means the origin should be handled by your own application.
235
+ # Note that `omniauth.origin` will always be blank.
236
+ ```
237
+
190
238
  ## Resources
191
239
  The [OmniAuth Wiki](https://github.com/omniauth/omniauth/wiki) has
192
240
  actively maintained in-depth documentation for OmniAuth. It should be
193
241
  your first stop if you are wondering about a more in-depth look at
194
242
  OmniAuth, how it works, and how to use it.
195
243
 
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
+
196
254
  ## Supported Ruby Versions
197
- OmniAuth is tested under 2.1.10, 2.2.6, 2.3.3, 2.4.0, 2.5.0, and JRuby.
255
+ OmniAuth is tested under 2.5, 2.6, 2.7, 3.0, 3.1, 3.2, truffleruby, and JRuby.
198
256
 
199
257
  ## Versioning
200
258
  This library aims to adhere to [Semantic Versioning 2.0.0][semver]. Violations
data/SECURITY.md ADDED
@@ -0,0 +1,18 @@
1
+ # Security Policy
2
+
3
+ ## Supported Versions
4
+
5
+ Use this section to tell people about which versions of your project are
6
+ currently being supported with security updates.
7
+
8
+ | Version | Supported |
9
+ | ------- | ------------------ |
10
+ | 2.1.x | :white_check_mark: |
11
+ | 2.0.x | :white_check_mark: |
12
+ | <= 1.9.1 | :x: |
13
+
14
+ ## Security contact information
15
+
16
+ To report a security vulnerability, please use the
17
+ [Tidelift security contact](https://tidelift.com/security).
18
+ Tidelift will coordinate the fix and disclosure.
@@ -0,0 +1,32 @@
1
+ require 'rack-protection'
2
+
3
+ module OmniAuth
4
+ class AuthenticityError < StandardError; end
5
+ class AuthenticityTokenProtection < Rack::Protection::AuthenticityToken
6
+ def initialize(options = {})
7
+ @options = default_options.merge(options)
8
+ end
9
+
10
+ def self.call(env)
11
+ new.call!(env)
12
+ end
13
+
14
+ def call!(env)
15
+ return if accepts?(env)
16
+
17
+ instrument env
18
+ react env
19
+ end
20
+
21
+ alias_method :call, :call!
22
+
23
+ private
24
+
25
+ def deny(_env)
26
+ OmniAuth.logger.send(:warn, "Attack prevented by #{self.class}")
27
+ raise AuthenticityError.new(options[:message])
28
+ end
29
+
30
+ alias default_reaction deny
31
+ end
32
+ end
@@ -26,19 +26,18 @@ module OmniAuth
26
26
  @options = options
27
27
  end
28
28
 
29
- def provider(klass, *args, &block)
29
+ def provider(klass, *args, **opts, &block)
30
30
  if klass.is_a?(Class)
31
31
  middleware = klass
32
32
  else
33
33
  begin
34
- middleware = OmniAuth::Strategies.const_get(OmniAuth::Utils.camelize(klass.to_s).to_s)
34
+ middleware = OmniAuth::Strategies.const_get(OmniAuth::Utils.camelize(klass.to_s).to_s, false)
35
35
  rescue NameError
36
36
  raise(LoadError.new("Could not find matching strategy for #{klass.inspect}. You may need to install an additional gem (such as omniauth-#{klass})."))
37
37
  end
38
38
  end
39
39
 
40
- args.last.is_a?(Hash) ? args.push(options.merge(args.pop)) : args.push(options)
41
- use middleware, *args, &block
40
+ use middleware, *args, **options.merge(opts), &block
42
41
  end
43
42
 
44
43
  def call(env)
@@ -27,10 +27,19 @@ module OmniAuth
27
27
 
28
28
  def redirect_to_failure
29
29
  message_key = env['omniauth.error.type']
30
- new_path = "#{env['SCRIPT_NAME']}#{OmniAuth.config.path_prefix}/failure?message=#{Rack::Utils.escape(message_key)}#{origin_query_param}#{strategy_name_query_param}"
30
+
31
+ new_path = "#{env['SCRIPT_NAME']}#{strategy_path_prefix}/failure?message=#{Rack::Utils.escape(message_key)}#{origin_query_param}#{strategy_name_query_param}"
31
32
  Rack::Response.new(['302 Moved'], 302, 'Location' => new_path).finish
32
33
  end
33
34
 
35
+ def strategy_path_prefix
36
+ if env['omniauth.error.strategy']
37
+ env['omniauth.error.strategy'].path_prefix
38
+ else
39
+ OmniAuth.config.path_prefix
40
+ end
41
+ end
42
+
34
43
  def strategy_name_query_param
35
44
  return '' unless env['omniauth.error.strategy']
36
45
 
data/lib/omniauth/form.rb CHANGED
@@ -7,9 +7,10 @@ module OmniAuth
7
7
  def initialize(options = {})
8
8
  options[:title] ||= 'Authentication Info Required'
9
9
  options[:header_info] ||= ''
10
+ options[:method] ||= 'post'
10
11
  self.options = options
11
12
 
12
- @html = ''
13
+ @html = +'' # unary + string allows it to be mutable if strings are frozen
13
14
  @with_custom_button = false
14
15
  @footer = nil
15
16
  header(options[:title], options[:header_info])
@@ -75,7 +76,7 @@ module OmniAuth
75
76
  </head>
76
77
  <body>
77
78
  <h1>#{title}</h1>
78
- <form method='post' #{"action='#{options[:url]}' " if options[:url]}noValidate='noValidate'>
79
+ <form method='#{options[:method]}' #{"action='#{options[:url]}' " if options[:url]}noValidate='noValidate'>
79
80
  HTML
80
81
  self
81
82
  end
@@ -35,7 +35,7 @@ module OmniAuth
35
35
  option :uid_field, :email
36
36
 
37
37
  def request_phase
38
- form = OmniAuth::Form.new(:title => 'User Info', :url => callback_path)
38
+ form = OmniAuth::Form.new(:title => 'User Info', :url => callback_path, :method => 'get')
39
39
  options.fields.each do |field|
40
40
  form.text_field field.to_s.capitalize.tr('_', ' '), field.to_s
41
41
  end
@@ -181,17 +181,47 @@ module OmniAuth
181
181
  end
182
182
 
183
183
  @env = env
184
+
185
+ warn_if_using_get_on_request_path
186
+
184
187
  @env['omniauth.strategy'] = self if on_auth_path?
185
188
 
186
189
  return mock_call!(env) if OmniAuth.config.test_mode
187
- return options_call if on_auth_path? && options_request?
188
- return request_call if on_request_path? && OmniAuth.config.allowed_request_methods.include?(request.request_method.downcase.to_sym)
189
- return callback_call if on_callback_path?
190
- return other_phase if respond_to?(:other_phase)
190
+
191
+ begin
192
+ return options_call if on_auth_path? && options_request?
193
+ return request_call if on_request_path? && OmniAuth.config.allowed_request_methods.include?(request.request_method.downcase.to_sym)
194
+ return callback_call if on_callback_path?
195
+ return other_phase if respond_to?(:other_phase)
196
+ rescue StandardError => e
197
+ raise e if env.delete('omniauth.error.app')
198
+
199
+ return fail!(e.message, e)
200
+ end
191
201
 
192
202
  @app.call(env)
193
203
  end
194
204
 
205
+ def warn_if_using_get_on_request_path
206
+ return unless on_request_path?
207
+ return unless OmniAuth.config.allowed_request_methods.include?(:get)
208
+ return if OmniAuth.config.silence_get_warning
209
+
210
+ log :warn, <<-WARN
211
+ You are using GET as an allowed request method for OmniAuth. This may leave
212
+ you open to CSRF attacks. As of v2.0.0, OmniAuth by default allows only POST
213
+ to its own routes. You should review the following resources to guide your
214
+ mitigation:
215
+ https://github.com/omniauth/omniauth/wiki/Resolving-CVE-2015-9284
216
+ https://github.com/omniauth/omniauth/issues/960
217
+ https://nvd.nist.gov/vuln/detail/CVE-2015-9284
218
+ https://github.com/omniauth/omniauth/pull/809
219
+
220
+ You can ignore this warning by setting:
221
+ OmniAuth.config.silence_get_warning = true
222
+ WARN
223
+ end
224
+
195
225
  # Responds to an OPTIONS request.
196
226
  def options_call
197
227
  OmniAuth.config.before_options_phase.call(env) if OmniAuth.config.before_options_phase
@@ -202,17 +232,19 @@ module OmniAuth
202
232
  # Performs the steps necessary to run the request phase of a strategy.
203
233
  def request_call # rubocop:disable CyclomaticComplexity, MethodLength, PerceivedComplexity
204
234
  setup_phase
205
- log :info, 'Request phase initiated.'
235
+ log :debug, 'Request phase initiated.'
206
236
 
207
237
  # store query params from the request url, extracted in the callback_phase
208
238
  session['omniauth.params'] = request.GET
239
+
240
+ OmniAuth.config.request_validation_phase.call(env) if OmniAuth.config.request_validation_phase
209
241
  OmniAuth.config.before_request_phase.call(env) if OmniAuth.config.before_request_phase
210
242
 
211
243
  if options.form.respond_to?(:call)
212
- log :info, 'Rendering form from supplied Rack endpoint.'
244
+ log :debug, 'Rendering form from supplied Rack endpoint.'
213
245
  options.form.call(env)
214
246
  elsif options.form
215
- log :info, 'Rendering form from underlying application.'
247
+ log :debug, 'Rendering form from underlying application.'
216
248
  call_app!
217
249
  elsif !options.origin_param
218
250
  request_phase
@@ -225,12 +257,14 @@ module OmniAuth
225
257
 
226
258
  request_phase
227
259
  end
260
+ rescue OmniAuth::AuthenticityError => e
261
+ fail!(:authenticity_error, e)
228
262
  end
229
263
 
230
264
  # Performs the steps necessary to run the callback phase of a strategy.
231
265
  def callback_call
232
266
  setup_phase
233
- log :info, 'Callback phase initiated.'
267
+ log :debug, 'Callback phase initiated.'
234
268
  @env['omniauth.origin'] = session.delete('omniauth.origin')
235
269
  @env['omniauth.origin'] = nil if env['omniauth.origin'] == ''
236
270
  @env['omniauth.params'] = session.delete('omniauth.params') || {}
@@ -268,8 +302,14 @@ module OmniAuth
268
302
  # in the event that OmniAuth has been configured to be
269
303
  # in test mode.
270
304
  def mock_call!(*)
271
- return mock_request_call if on_request_path? && OmniAuth.config.allowed_request_methods.include?(request.request_method.downcase.to_sym)
272
- return mock_callback_call if on_callback_path?
305
+ begin
306
+ return mock_request_call if on_request_path? && OmniAuth.config.allowed_request_methods.include?(request.request_method.downcase.to_sym)
307
+ return mock_callback_call if on_callback_path?
308
+ rescue StandardError => e
309
+ raise e if env.delete('omniauth.error.app')
310
+
311
+ return fail!(e.message, e)
312
+ end
273
313
 
274
314
  call_app!
275
315
  end
@@ -278,7 +318,10 @@ module OmniAuth
278
318
  setup_phase
279
319
 
280
320
  session['omniauth.params'] = request.GET
321
+
322
+ OmniAuth.config.request_validation_phase.call(env) if OmniAuth.config.request_validation_phase
281
323
  OmniAuth.config.before_request_phase.call(env) if OmniAuth.config.before_request_phase
324
+
282
325
  if options.origin_param
283
326
  if request.params[options.origin_param]
284
327
  session['omniauth.origin'] = request.params[options.origin_param]
@@ -312,10 +355,10 @@ module OmniAuth
312
355
  # underlying application. This will default to `/auth/:provider/setup`.
313
356
  def setup_phase
314
357
  if options[:setup].respond_to?(:call)
315
- log :info, 'Setup endpoint detected, running now.'
358
+ log :debug, 'Setup endpoint detected, running now.'
316
359
  options[:setup].call(env)
317
360
  elsif options[:setup]
318
- log :info, 'Calling through to underlying application for setup.'
361
+ log :debug, 'Calling through to underlying application for setup.'
319
362
  setup_env = env.merge('PATH_INFO' => setup_path, 'REQUEST_METHOD' => 'GET')
320
363
  call_app!(setup_env)
321
364
  end
@@ -345,11 +388,13 @@ module OmniAuth
345
388
  end
346
389
 
347
390
  def auth_hash
348
- hash = AuthHash.new(:provider => name, :uid => uid)
349
- hash.info = info unless skip_info?
350
- hash.credentials = credentials if credentials
351
- hash.extra = extra if extra
352
- hash
391
+ credentials_data = credentials
392
+ extra_data = extra
393
+ AuthHash.new(:provider => name, :uid => uid).tap do |auth|
394
+ auth.info = info unless skip_info?
395
+ auth.credentials = credentials_data if credentials_data
396
+ auth.extra = extra_data if extra_data
397
+ end
353
398
  end
354
399
 
355
400
  # Determines whether or not user info should be retrieved. This
@@ -389,7 +434,12 @@ module OmniAuth
389
434
  end
390
435
 
391
436
  def request_path
392
- @request_path ||= options[:request_path].is_a?(String) ? options[:request_path] : "#{path_prefix}/#{name}"
437
+ @request_path ||=
438
+ if options[:request_path].is_a?(String)
439
+ options[:request_path]
440
+ else
441
+ "#{script_name}#{path_prefix}/#{name}"
442
+ end
393
443
  end
394
444
 
395
445
  def callback_path
@@ -397,7 +447,7 @@ module OmniAuth
397
447
  path = options[:callback_path] if options[:callback_path].is_a?(String)
398
448
  path ||= current_path if options[:callback_path].respond_to?(:call) && options[:callback_path].call(env)
399
449
  path ||= custom_path(:request_path)
400
- path ||= "#{path_prefix}/#{name}/callback"
450
+ path ||= "#{script_name}#{path_prefix}/#{name}/callback"
401
451
  path
402
452
  end
403
453
  end
@@ -409,7 +459,7 @@ module OmniAuth
409
459
  CURRENT_PATH_REGEX = %r{/$}.freeze
410
460
  EMPTY_STRING = ''.freeze
411
461
  def current_path
412
- @current_path ||= request.path_info.downcase.sub(CURRENT_PATH_REGEX, EMPTY_STRING)
462
+ @current_path ||= request.path.downcase.sub(CURRENT_PATH_REGEX, EMPTY_STRING)
413
463
  end
414
464
 
415
465
  def query_string
@@ -418,6 +468,9 @@ module OmniAuth
418
468
 
419
469
  def call_app!(env = @env)
420
470
  @app.call(env)
471
+ rescue StandardError => e
472
+ env['omniauth.error.app'] = true
473
+ raise e
421
474
  end
422
475
 
423
476
  def full_host
@@ -441,10 +494,11 @@ module OmniAuth
441
494
  end
442
495
 
443
496
  def callback_url
444
- full_host + script_name + callback_path + query_string
497
+ full_host + callback_path + query_string
445
498
  end
446
499
 
447
500
  def script_name
501
+ return '' if @env.nil?
448
502
  @env['SCRIPT_NAME'] || ''
449
503
  end
450
504
 
@@ -491,16 +545,15 @@ module OmniAuth
491
545
  OmniAuth.config.on_failure.call(env)
492
546
  end
493
547
 
494
- def dup
495
- super.tap do
496
- @options = @options.dup
497
- end
498
- end
499
-
500
548
  class Options < OmniAuth::KeyStore; end
501
549
 
502
550
  protected
503
551
 
552
+ def initialize_copy(*args)
553
+ super
554
+ @options = @options.dup
555
+ end
556
+
504
557
  def merge_stack(stack)
505
558
  stack.inject({}) do |a, e|
506
559
  a.merge!(e)
@@ -1,3 +1,3 @@
1
1
  module OmniAuth
2
- VERSION = '1.9.2'.freeze
2
+ VERSION = '2.1.2'.freeze
3
3
  end
data/lib/omniauth.rb CHANGED
@@ -1,3 +1,7 @@
1
+ # TODO: Fixed in https://github.com/rack/rack/pull/1610 for Rack 3
2
+ if defined?(RUBY_ENGINE) && RUBY_ENGINE == "jruby"
3
+ require 'delegate'
4
+ end
1
5
  require 'rack'
2
6
  require 'singleton'
3
7
  require 'logger'
@@ -15,6 +19,7 @@ module OmniAuth
15
19
  autoload :Form, 'omniauth/form'
16
20
  autoload :AuthHash, 'omniauth/auth_hash'
17
21
  autoload :FailureEndpoint, 'omniauth/failure_endpoint'
22
+ autoload :AuthenticityTokenProtection, 'omniauth/authenticity_token_protection'
18
23
 
19
24
  def self.strategies
20
25
  @strategies ||= []
@@ -29,20 +34,22 @@ module OmniAuth
29
34
  logger
30
35
  end
31
36
 
32
- def self.defaults
37
+ def self.defaults # rubocop:disable MethodLength
33
38
  @defaults ||= {
34
39
  :camelizations => {},
35
40
  :path_prefix => '/auth',
36
41
  :on_failure => OmniAuth::FailureEndpoint,
37
42
  :failure_raise_out_environments => ['development'],
43
+ :request_validation_phase => OmniAuth::AuthenticityTokenProtection,
38
44
  :before_request_phase => nil,
39
45
  :before_callback_phase => nil,
40
46
  :before_options_phase => nil,
41
47
  :form_css => Form::DEFAULT_CSS,
42
48
  :test_mode => false,
43
49
  :logger => default_logger,
44
- :allowed_request_methods => %i[get post],
45
- :mock_auth => {:default => AuthHash.new('provider' => 'default', 'uid' => '1234', 'info' => {'name' => 'Example User'})}
50
+ :allowed_request_methods => %i[post],
51
+ :mock_auth => {:default => AuthHash.new('provider' => 'default', 'uid' => '1234', 'info' => {'name' => 'Example User'})},
52
+ :silence_get_warning => false
46
53
  }
47
54
  end
48
55
 
@@ -74,6 +81,14 @@ module OmniAuth
74
81
  end
75
82
  end
76
83
 
84
+ def request_validation_phase(&block)
85
+ if block_given?
86
+ @request_validation_phase = block
87
+ else
88
+ @request_validation_phase
89
+ end
90
+ end
91
+
77
92
  def before_request_phase(&block)
78
93
  if block_given?
79
94
  @before_request_phase = block
@@ -111,8 +126,9 @@ module OmniAuth
111
126
  camelizations[name.to_s] = camelized.to_s
112
127
  end
113
128
 
114
- attr_writer :on_failure, :before_callback_phase, :before_options_phase, :before_request_phase
115
- attr_accessor :failure_raise_out_environments, :path_prefix, :allowed_request_methods, :form_css, :test_mode, :mock_auth, :full_host, :camelizations, :logger
129
+ attr_writer :on_failure, :before_callback_phase, :before_options_phase, :before_request_phase, :request_validation_phase
130
+ attr_accessor :failure_raise_out_environments, :path_prefix, :allowed_request_methods, :form_css,
131
+ :test_mode, :mock_auth, :full_host, :camelizations, :logger, :silence_get_warning
116
132
  end
117
133
 
118
134
  def self.config
@@ -159,7 +175,7 @@ module OmniAuth
159
175
  if first_letter_in_uppercase
160
176
  word.to_s.gsub(%r{/(.?)}) { '::' + Regexp.last_match[1].upcase }.gsub(/(^|_)(.)/) { Regexp.last_match[2].upcase }
161
177
  else
162
- word.first + camelize(word)[1..-1]
178
+ camelize(word).tap { |w| w[0] = w[0].downcase }
163
179
  end
164
180
  end
165
181
  end
data/omniauth.gemspec CHANGED
@@ -6,8 +6,9 @@ require 'omniauth/version'
6
6
 
7
7
  Gem::Specification.new do |spec|
8
8
  spec.add_dependency 'hashie', ['>= 3.4.6']
9
- spec.add_dependency 'rack', ['>= 1.6.2', '< 3']
10
- spec.add_development_dependency 'bundler', '~> 1.14'
9
+ spec.add_dependency 'rack', '>= 2.2.3'
10
+ spec.add_development_dependency 'bundler', '~> 2.0'
11
+ spec.add_dependency 'rack-protection'
11
12
  spec.add_development_dependency 'rake', '~> 12.0'
12
13
  spec.authors = ['Michael Bleigh', 'Erik Michaels-Ober', 'Tom Milewski']
13
14
  spec.description = 'A generalized Rack framework for multiple-provider authentication.'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: omniauth
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.9.2
4
+ version: 2.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michael Bleigh
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2022-08-18 00:00:00.000000000 Z
13
+ date: 2023-12-19 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: hashie
@@ -32,34 +32,42 @@ dependencies:
32
32
  requirements:
33
33
  - - ">="
34
34
  - !ruby/object:Gem::Version
35
- version: 1.6.2
36
- - - "<"
37
- - !ruby/object:Gem::Version
38
- version: '3'
35
+ version: 2.2.3
39
36
  type: :runtime
40
37
  prerelease: false
41
38
  version_requirements: !ruby/object:Gem::Requirement
42
39
  requirements:
43
40
  - - ">="
44
41
  - !ruby/object:Gem::Version
45
- version: 1.6.2
46
- - - "<"
47
- - !ruby/object:Gem::Version
48
- version: '3'
42
+ version: 2.2.3
49
43
  - !ruby/object:Gem::Dependency
50
44
  name: bundler
51
45
  requirement: !ruby/object:Gem::Requirement
52
46
  requirements:
53
47
  - - "~>"
54
48
  - !ruby/object:Gem::Version
55
- version: '1.14'
49
+ version: '2.0'
56
50
  type: :development
57
51
  prerelease: false
58
52
  version_requirements: !ruby/object:Gem::Requirement
59
53
  requirements:
60
54
  - - "~>"
61
55
  - !ruby/object:Gem::Version
62
- version: '1.14'
56
+ version: '2.0'
57
+ - !ruby/object:Gem::Dependency
58
+ name: rack-protection
59
+ requirement: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ version: '0'
64
+ type: :runtime
65
+ prerelease: false
66
+ version_requirements: !ruby/object:Gem::Requirement
67
+ requirements:
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ version: '0'
63
71
  - !ruby/object:Gem::Dependency
64
72
  name: rake
65
73
  requirement: !ruby/object:Gem::Requirement
@@ -83,18 +91,24 @@ executables: []
83
91
  extensions: []
84
92
  extra_rdoc_files: []
85
93
  files:
94
+ - ".github/FUNDING.yml"
86
95
  - ".github/ISSUE_TEMPLATE.md"
96
+ - ".github/dependabot.yml"
97
+ - ".github/workflows/jruby.yml"
98
+ - ".github/workflows/main.yml"
99
+ - ".github/workflows/truffle_ruby.yml"
87
100
  - ".gitignore"
88
101
  - ".rspec"
89
102
  - ".rubocop.yml"
90
- - ".travis.yml"
91
103
  - ".yardopts"
92
104
  - Gemfile
93
105
  - LICENSE.md
94
106
  - README.md
95
107
  - Rakefile
108
+ - SECURITY.md
96
109
  - lib/omniauth.rb
97
110
  - lib/omniauth/auth_hash.rb
111
+ - lib/omniauth/authenticity_token_protection.rb
98
112
  - lib/omniauth/builder.rb
99
113
  - lib/omniauth/failure_endpoint.rb
100
114
  - lib/omniauth/form.css
@@ -127,7 +141,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
127
141
  - !ruby/object:Gem::Version
128
142
  version: 1.3.5
129
143
  requirements: []
130
- rubygems_version: 3.2.32
144
+ rubygems_version: 3.3.26
131
145
  signing_key:
132
146
  specification_version: 4
133
147
  summary: A generalized Rack framework for multiple-provider authentication.
data/.travis.yml DELETED
@@ -1,25 +0,0 @@
1
- bundler_args: --without development
2
- before_install:
3
- - gem uninstall -v '>= 2' -i $(rvm gemdir)@global -ax bundler || true
4
- - gem install bundler -v '1.17.3'
5
- install:
6
- - bundle _1.17.3_ install --jobs=3 --retry=3
7
- cache: bundler
8
- env:
9
- global:
10
- - JRUBY_OPTS="$JRUBY_OPTS --debug"
11
- language: ruby
12
- rvm:
13
- - jruby-9000
14
- - 2.2.9
15
- - 2.3.5
16
- - 2.4.4
17
- - 2.5.3
18
- - jruby-head
19
- - ruby-head
20
- matrix:
21
- allow_failures:
22
- - rvm: jruby-head
23
- - rvm: ruby-head
24
- fast_finish: true
25
- sudo: false