omniauth-oauth2 1.0.0 → 1.8.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: f5cd52cdcb930eb0df65da3d7659a8e46f19db3426e0ecd8b3565b51e951331f
4
+ data.tar.gz: 6ed5b399aef49e82b265ff6175c849c44415f8b19f81ee5eb5d988ebb6c95fc8
5
+ SHA512:
6
+ metadata.gz: e6bc5b97b326e37aa1e2ebb294b3459b57ba5dbb4d1e8b7e1709ed2dc9cfb8cc3b1b6f70ebbd0d5d830834af2472afe5b34762cf63f99a508334edee0d86b15a
7
+ data.tar.gz: 5c6cea848d8c9895495f7e931a3acfcee6e5e773824714e4de8bacfdc7aa70c3e40ad5cbce92b9a0d115f1dbd1f26aea7dc2b7a7bc02b1050cf38c501c3b7d45
@@ -0,0 +1,2 @@
1
+ github: bobbymcwho
2
+ tidelift: rubygems/omniauth-oauth2
@@ -0,0 +1,67 @@
1
+ name: Ruby
2
+
3
+ on:
4
+ push:
5
+ branches: [ master ]
6
+ pull_request:
7
+ branches: [ master ]
8
+
9
+ jobs:
10
+ test:
11
+ runs-on: ubuntu-18.04
12
+ strategy:
13
+ fail-fast: false
14
+ matrix:
15
+ os: [ubuntu, macos]
16
+ ruby: [2.5, 2.6, 2.7, '3.0', 3.1, head, debug, truffleruby, truffleruby-head]
17
+ steps:
18
+ - uses: actions/checkout@v2
19
+ - name: Set up Ruby
20
+ uses: ruby/setup-ruby@v1
21
+ with:
22
+ ruby-version: ${{ matrix.ruby }}
23
+ bundler-cache: true
24
+ - name: Install dependencies
25
+ run: bundle install
26
+ - name: Run tests
27
+ run: bundle exec rake
28
+ test-jruby:
29
+ runs-on: ubuntu-18.04
30
+ strategy:
31
+ fail-fast: false
32
+ matrix:
33
+ os: [ubuntu, macos]
34
+ jruby: [jruby, jruby-head]
35
+ steps:
36
+ - uses: actions/checkout@v2
37
+ - name: Set up Ruby
38
+ uses: ruby/setup-ruby@v1
39
+ with:
40
+ ruby-version: ${{ matrix.jruby }}
41
+ bundler-cache: true
42
+ - name: Install dependencies
43
+ env:
44
+ JRUBY_OPTS: --debug
45
+ run: bundle install
46
+ - name: Run tests
47
+ env:
48
+ JRUBY_OPTS: --debug
49
+ run: bundle exec rake
50
+ coveralls:
51
+ runs-on: ubuntu-18.04
52
+ steps:
53
+ - uses: actions/checkout@v2
54
+ - name: Set up Ruby
55
+ uses: ruby/setup-ruby@v1
56
+ with:
57
+ ruby-version: 2.6
58
+ bundler-cache: true
59
+ - name: Install dependencies
60
+ run: bundle install
61
+ - name: Run tests
62
+ run: bundle exec rake
63
+ - name: Coveralls GitHub Action
64
+ uses: coverallsapp/github-action@v1.1.2
65
+ with:
66
+ github-token: ${{ secrets.github_token }}
67
+ path-to-lcov: './coverage/lcov/omniauth-oauth2.lcov'
data/.gitignore CHANGED
@@ -15,3 +15,4 @@ spec/reports
15
15
  test/tmp
16
16
  test/version_tmp
17
17
  tmp
18
+ *.swp
data/.rubocop.yml ADDED
@@ -0,0 +1,80 @@
1
+ AllCops:
2
+ NewCops: enable
3
+
4
+ Gemspec/RequiredRubyVersion:
5
+ Enabled: false
6
+
7
+ Layout/AccessModifierIndentation:
8
+ EnforcedStyle: outdent
9
+
10
+ Layout/LineLength:
11
+ AllowURI: true
12
+ Enabled: false
13
+
14
+ Layout/SpaceInsideHashLiteralBraces:
15
+ EnforcedStyle: no_space
16
+
17
+ Lint/MissingSuper:
18
+ Enabled: false
19
+
20
+ Metrics/AbcSize:
21
+ Max: 18
22
+
23
+ Metrics/BlockLength:
24
+ Exclude:
25
+ - spec/omniauth/strategies/oauth2_spec.rb
26
+
27
+ Metrics/BlockNesting:
28
+ Max: 2
29
+
30
+ Metrics/ClassLength:
31
+ Max: 110
32
+
33
+ Metrics/MethodLength:
34
+ CountComments: false
35
+ Max: 10
36
+
37
+ Metrics/ParameterLists:
38
+ Max: 4
39
+ CountKeywordArgs: true
40
+
41
+ Naming/FileName:
42
+ Exclude:
43
+ - lib/omniauth-oauth2.rb
44
+
45
+ Style/CollectionMethods:
46
+ PreferredMethods:
47
+ map: 'collect'
48
+ reduce: 'inject'
49
+ find: 'detect'
50
+ find_all: 'select'
51
+
52
+ Style/Documentation:
53
+ Enabled: false
54
+
55
+ Style/DoubleNegation:
56
+ Enabled: false
57
+
58
+ Style/ExpandPathArguments:
59
+ Enabled: false
60
+
61
+ Style/FrozenStringLiteralComment:
62
+ Enabled: false
63
+
64
+ Style/HashSyntax:
65
+ EnforcedStyle: hash_rockets
66
+
67
+ Style/StderrPuts:
68
+ Enabled: false
69
+
70
+ Style/StringLiterals:
71
+ EnforcedStyle: double_quotes
72
+
73
+ Style/TrailingCommaInArguments:
74
+ EnforcedStyleForMultiline: comma
75
+
76
+ Style/TrailingCommaInHashLiteral:
77
+ EnforcedStyleForMultiline: comma
78
+
79
+ Style/TrailingCommaInArrayLiteral:
80
+ EnforcedStyleForMultiline: comma
data/CHANGELOG.md ADDED
@@ -0,0 +1,5 @@
1
+ ## [v1.8.0](https://github.com/omniauth/omniauth-oauth2/releases/tag/v1.7.3)
2
+ - Relaxes allowed versions of the oauth2 gem. [#146](https://github.com/omniauth/omniauth-oauth2/pull/146)
3
+ - Requires omniauth `~> 2.0` [#152](https://github.com/omniauth/omniauth-oauth2/pull/152)
4
+
5
+ Please see https://github.com/omniauth/omniauth-oauth2/releases for changelog prior to 1.8.0
data/Gemfile CHANGED
@@ -1,12 +1,20 @@
1
- source 'http://rubygems.org'
1
+ source "https://rubygems.org"
2
2
 
3
- # Specify your gem's dependencies in omniauth-oauth2.gemspec
4
- gemspec
3
+ gem "rake", "~> 13.0"
5
4
 
6
- group :development, :test do
7
- gem 'guard'
8
- gem 'guard-rspec'
9
- gem 'guard-bundler'
10
- gem 'growl'
11
- gem 'rb-fsevent'
5
+ group :test do
6
+ gem "addressable", "~> 2.3.8", :platforms => %i[jruby ruby_18]
7
+ gem 'coveralls_reborn', '~> 0.19.0', require: false
8
+ gem "json", :platforms => %i[jruby ruby_18 ruby_19]
9
+ gem "mime-types", "~> 1.25", :platforms => %i[jruby ruby_18]
10
+ gem "rack-test"
11
+ gem "rest-client", "~> 1.8.0", :platforms => %i[jruby ruby_18]
12
+ gem "rspec", "~> 3.2"
13
+ gem "rubocop", ">= 0.51", :platforms => %i[ruby_19 ruby_20 ruby_21 ruby_22 ruby_23 ruby_24]
14
+ gem 'simplecov-lcov'
15
+ gem 'tins', '~> 1.13', :platforms => %i[jruby_18 jruby_19 ruby_19]
16
+ gem "webmock", "~> 3.0"
12
17
  end
18
+
19
+ # Specify your gem's dependencies in omniauth-oauth2.gemspec
20
+ gemspec
data/LICENSE.md ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (C) 2014 Michael Bleigh, Erik Michaels-Ober and Intridea, Inc.
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ THE SOFTWARE.
data/README.md CHANGED
@@ -1,78 +1,75 @@
1
1
  # OmniAuth OAuth2
2
2
 
3
- **Note:** This gem is designed to work with the unreleased OmniAuth 1.0
4
- library. It will not be officially released on RubyGems.org until
5
- OmniAuth 1.0 is released.
3
+ [![Gem Version](http://img.shields.io/gem/v/omniauth-oauth2.svg)][gem]
4
+ [![Code Climate](http://img.shields.io/codeclimate/maintainability/intridea/omniauth-oauth2.svg)][codeclimate]
5
+ [![Coverage Status](http://img.shields.io/coveralls/intridea/omniauth-oauth2.svg)][coveralls]
6
+ [![Security](https://hakiri.io/github/omniauth/omniauth-oauth2/master.svg)](https://hakiri.io/github/omniauth/omniauth-oauth2/master)
6
7
 
7
- This gem contains a generic OAuth2 strategy for OmniAuth. It is meant to
8
- serve as a building block strategy for other strategies and not to be
9
- used independently (since it has no inherent way to gather uid and user
10
- info).
8
+ [gem]: https://rubygems.org/gems/omniauth-oauth2
9
+ [codeclimate]: https://codeclimate.com/github/intridea/omniauth-oauth2
10
+ [coveralls]: https://coveralls.io/r/intridea/omniauth-oauth2
11
+
12
+ This gem contains a generic OAuth2 strategy for OmniAuth. It is meant to serve
13
+ as a building block strategy for other strategies and not to be used
14
+ independently (since it has no inherent way to gather uid and user info).
11
15
 
12
16
  ## Creating an OAuth2 Strategy
13
17
 
14
- To create an OmniAuth OAuth2 strategy using this gem, you can simply
15
- subclass it and add a few extra methods like so:
16
-
17
- require 'omniauth-oauth'
18
-
19
- module OmniAuth
20
- module Strategies
21
- class SomeSite < OmniAuth::Strategies::OAuth2
22
- # Give your strategy a name.
23
- option :name, "some_site"
24
-
25
- # This is where you pass the options you would pass when
26
- # initializing your consumer from the OAuth gem.
27
- option :client_options, {:site => "https://api.somesite.com"}
28
-
29
- # These are called after authentication has succeeded. If
30
- # possible, you should try to set the UID without making
31
- # additional calls (if the user id is returned with the token
32
- # or as a URI parameter). This may not be possible with all
33
- # providers.
34
- uid{ raw_info['id'] }
35
-
36
- info do
37
- {
38
- :name => raw_info['name'],
39
- :email => raw_info['email']
40
- }
41
- end
42
-
43
- extra do
44
- {
45
- 'raw_info' => raw_info
46
- }
47
- end
48
-
49
- def raw_info
50
- @raw_info ||= access_token.get('/me').parsed
51
- end
52
- end
18
+ To create an OmniAuth OAuth2 strategy using this gem, you can simply subclass
19
+ it and add a few extra methods like so:
20
+
21
+ ```ruby
22
+ require 'omniauth-oauth2'
23
+
24
+ module OmniAuth
25
+ module Strategies
26
+ class SomeSite < OmniAuth::Strategies::OAuth2
27
+ # Give your strategy a name.
28
+ option :name, "some_site"
29
+
30
+ # This is where you pass the options you would pass when
31
+ # initializing your consumer from the OAuth gem.
32
+ option :client_options, {:site => "https://api.somesite.com"}
33
+
34
+ # You may specify that your strategy should use PKCE by setting
35
+ # the pkce option to true: https://tools.ietf.org/html/rfc7636
36
+ option :pkce, true
37
+
38
+ # These are called after authentication has succeeded. If
39
+ # possible, you should try to set the UID without making
40
+ # additional calls (if the user id is returned with the token
41
+ # or as a URI parameter). This may not be possible with all
42
+ # providers.
43
+ uid{ raw_info['id'] }
44
+
45
+ info do
46
+ {
47
+ :name => raw_info['name'],
48
+ :email => raw_info['email']
49
+ }
50
+ end
51
+
52
+ extra do
53
+ {
54
+ 'raw_info' => raw_info
55
+ }
56
+ end
57
+
58
+ def raw_info
59
+ @raw_info ||= access_token.get('/me').parsed
53
60
  end
54
61
  end
62
+ end
63
+ end
64
+ ```
55
65
 
56
66
  That's pretty much it!
57
67
 
58
- ## License
59
-
60
- Copyright (C) 2011 by Michael Bleigh and Intridea, Inc.
68
+ ## OmniAuth-OAuth2 for Enterprise
61
69
 
62
- Permission is hereby granted, free of charge, to any person obtaining a copy
63
- of this software and associated documentation files (the "Software"), to deal
64
- in the Software without restriction, including without limitation the rights
65
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
66
- copies of the Software, and to permit persons to whom the Software is
67
- furnished to do so, subject to the following conditions:
70
+ Available as part of the Tidelift Subscription.
68
71
 
69
- The above copyright notice and this permission notice shall be included in
70
- all copies or substantial portions of the Software.
72
+ The maintainers of OmniAuth-OAuth2 and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source packages you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the exact packages you use. [Learn more.](https://tidelift.com/subscription/pkg/rubygems-omniauth-oauth2?utm_source=undefined&utm_medium=referral&utm_campaign=enterprise)
71
73
 
72
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
73
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
74
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
75
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
76
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
77
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
78
- THE SOFTWARE.
74
+ ## Supported Ruby Versions
75
+ OmniAuth is tested under 2.5, 2.6, 2.7, truffleruby, and JRuby.
data/Rakefile CHANGED
@@ -1,9 +1,19 @@
1
1
  #!/usr/bin/env rake
2
- require "bundler/gem_tasks"
3
- require 'rspec/core/rake_task'
4
2
 
5
- desc 'Default: run specs.'
6
- task :default => :spec
3
+ require "bundler/gem_tasks"
4
+ require "rspec/core/rake_task"
7
5
 
8
- desc "Run specs"
9
6
  RSpec::Core::RakeTask.new
7
+
8
+ task :test => :spec
9
+
10
+ begin
11
+ require "rubocop/rake_task"
12
+ RuboCop::RakeTask.new
13
+ rescue LoadError
14
+ task :rubocop do
15
+ $stderr.puts "RuboCop is disabled"
16
+ end
17
+ end
18
+
19
+ task :default => %i[spec rubocop]
data/SECURITY.md ADDED
@@ -0,0 +1,17 @@
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
+ | 1.7.x | :white_check_mark: |
11
+ | <= 1.6.x | :x: |
12
+
13
+ ## Security contact information
14
+
15
+ To report a security vulnerability, please use the
16
+ [Tidelift security contact](https://tidelift.com/security).
17
+ Tidelift will coordinate the fix and disclosure.
@@ -1,7 +1,8 @@
1
- require 'cgi'
2
- require 'uri'
3
- require 'oauth2'
4
- require 'omniauth'
1
+ require "oauth2"
2
+ require "omniauth"
3
+ require "securerandom"
4
+ require "socket" # for SocketError
5
+ require "timeout" # for Timeout::Error
5
6
 
6
7
  module OmniAuth
7
8
  module Strategies
@@ -13,31 +14,44 @@ module OmniAuth
13
14
  class OAuth2
14
15
  include OmniAuth::Strategy
15
16
 
16
- args [:client_id, :client_secret]
17
+ def self.inherited(subclass)
18
+ OmniAuth::Strategy.included(subclass)
19
+ end
20
+
21
+ args %i[client_id client_secret]
17
22
 
18
23
  option :client_id, nil
19
24
  option :client_secret, nil
20
25
  option :client_options, {}
21
26
  option :authorize_params, {}
22
- option :authorize_options, [:scope]
27
+ option :authorize_options, %i[scope state]
23
28
  option :token_params, {}
24
29
  option :token_options, []
30
+ option :auth_token_params, {}
31
+ option :provider_ignores_state, false
32
+ option :pkce, false
33
+ option :pkce_verifier, nil
34
+ option :pkce_options, {
35
+ :code_challenge => proc { |verifier|
36
+ Base64.urlsafe_encode64(
37
+ Digest::SHA2.digest(verifier),
38
+ :padding => false,
39
+ )
40
+ },
41
+ :code_challenge_method => "S256",
42
+ }
25
43
 
26
44
  attr_accessor :access_token
27
45
 
28
46
  def client
29
- ::OAuth2::Client.new(options.client_id, options.client_secret, options.client_options.inject({}){|h,(k,v)| h[k.to_sym] = v; h})
30
- end
31
-
32
- def callback_url
33
- full_host + script_name + callback_path
47
+ ::OAuth2::Client.new(options.client_id, options.client_secret, deep_symbolize(options.client_options))
34
48
  end
35
49
 
36
50
  credentials do
37
- hash = {'token' => access_token.token}
38
- hash.merge!('refresh_token' => access_token.refresh_token) if access_token.expires? && access_token.refresh_token
39
- hash.merge!('expires_at' => access_token.expires_at) if access_token.expires?
40
- hash.merge!('expires' => access_token.expires?)
51
+ hash = {"token" => access_token.token}
52
+ hash["refresh_token"] = access_token.refresh_token if access_token.expires? && access_token.refresh_token
53
+ hash["expires_at"] = access_token.expires_at if access_token.expires?
54
+ hash["expires"] = access_token.expires?
41
55
  hash
42
56
  end
43
57
 
@@ -45,36 +59,89 @@ module OmniAuth
45
59
  redirect client.auth_code.authorize_url({:redirect_uri => callback_url}.merge(authorize_params))
46
60
  end
47
61
 
48
- def authorize_params
49
- options.authorize_params.merge(options.authorize_options.inject({}){|h,k| h[k.to_sym] = options[k] if options[k]; h})
62
+ def authorize_params # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
63
+ options.authorize_params[:state] = SecureRandom.hex(24)
64
+
65
+ if OmniAuth.config.test_mode
66
+ @env ||= {}
67
+ @env["rack.session"] ||= {}
68
+ end
69
+
70
+ params = options.authorize_params
71
+ .merge(options_for("authorize"))
72
+ .merge(pkce_authorize_params)
73
+
74
+ session["omniauth.pkce.verifier"] = options.pkce_verifier if options.pkce
75
+ session["omniauth.state"] = params[:state]
76
+
77
+ params
50
78
  end
51
79
 
52
80
  def token_params
53
- options.token_params.merge(options.token_options.inject({}){|h,k| h[k.to_sym] = options[k] if options[k]; h})
81
+ options.token_params.merge(options_for("token")).merge(pkce_token_params)
54
82
  end
55
83
 
56
- def callback_phase
57
- if request.params['error'] || request.params['error_reason']
58
- raise CallbackError.new(request.params['error'], request.params['error_description'] || request.params['error_reason'], request.params['error_uri'])
84
+ def callback_phase # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
85
+ error = request.params["error_reason"] || request.params["error"]
86
+ if !options.provider_ignores_state && (request.params["state"].to_s.empty? || request.params["state"] != session.delete("omniauth.state"))
87
+ fail!(:csrf_detected, CallbackError.new(:csrf_detected, "CSRF detected"))
88
+ elsif error
89
+ fail!(error, CallbackError.new(request.params["error"], request.params["error_description"] || request.params["error_reason"], request.params["error_uri"]))
90
+ else
91
+ self.access_token = build_access_token
92
+ self.access_token = access_token.refresh! if access_token.expired?
93
+ super
59
94
  end
60
-
61
- self.access_token = build_access_token
62
- self.access_token = client.auth_code.refresh_token(access_token.refresh_token) if access_token.expired?
63
-
64
- super
65
95
  rescue ::OAuth2::Error, CallbackError => e
66
96
  fail!(:invalid_credentials, e)
67
- rescue ::MultiJson::DecodeError => e
68
- fail!(:invalid_response, e)
69
97
  rescue ::Timeout::Error, ::Errno::ETIMEDOUT => e
70
98
  fail!(:timeout, e)
99
+ rescue ::SocketError => e
100
+ fail!(:failed_to_connect, e)
101
+ end
102
+
103
+ protected
104
+
105
+ def pkce_authorize_params
106
+ return {} unless options.pkce
107
+
108
+ options.pkce_verifier = SecureRandom.hex(64)
109
+
110
+ # NOTE: see https://tools.ietf.org/html/rfc7636#appendix-A
111
+ {
112
+ :code_challenge => options.pkce_options[:code_challenge]
113
+ .call(options.pkce_verifier),
114
+ :code_challenge_method => options.pkce_options[:code_challenge_method],
115
+ }
71
116
  end
72
117
 
73
- protected
118
+ def pkce_token_params
119
+ return {} unless options.pkce
120
+
121
+ {:code_verifier => session.delete("omniauth.pkce.verifier")}
122
+ end
74
123
 
75
124
  def build_access_token
76
- verifier = request.params['code']
77
- client.auth_code.get_token(verifier, {:redirect_uri => callback_url}.merge(options.token_params.to_hash(:symbolize_keys => true)))
125
+ verifier = request.params["code"]
126
+ client.auth_code.get_token(verifier, {:redirect_uri => callback_url}.merge(token_params.to_hash(:symbolize_keys => true)), deep_symbolize(options.auth_token_params))
127
+ end
128
+
129
+ def deep_symbolize(options)
130
+ options.each_with_object({}) do |(key, value), hash|
131
+ hash[key.to_sym] = value.is_a?(Hash) ? deep_symbolize(value) : value
132
+ end
133
+ end
134
+
135
+ def options_for(option)
136
+ hash = {}
137
+ options.send(:"#{option}_options").select { |key| options[key] }.each do |key|
138
+ hash[key.to_sym] = if options[key].respond_to?(:call)
139
+ options[key].call(env)
140
+ else
141
+ options[key]
142
+ end
143
+ end
144
+ hash
78
145
  end
79
146
 
80
147
  # An error that is indicated in the OAuth 2.0 callback.
@@ -82,13 +149,18 @@ module OmniAuth
82
149
  class CallbackError < StandardError
83
150
  attr_accessor :error, :error_reason, :error_uri
84
151
 
85
- def initialize(error, error_reason=nil, error_uri=nil)
152
+ def initialize(error, error_reason = nil, error_uri = nil)
86
153
  self.error = error
87
154
  self.error_reason = error_reason
88
155
  self.error_uri = error_uri
89
156
  end
157
+
158
+ def message
159
+ [error, error_reason, error_uri].compact.join(" | ")
160
+ end
90
161
  end
91
162
  end
92
163
  end
93
164
  end
94
- OmniAuth.config.add_camelization 'oauth2', 'OAuth2'
165
+
166
+ OmniAuth.config.add_camelization "oauth2", "OAuth2"
@@ -1,5 +1,5 @@
1
1
  module OmniAuth
2
2
  module OAuth2
3
- VERSION = "1.0.0"
3
+ VERSION = "1.8.0".freeze
4
4
  end
5
5
  end
@@ -1,2 +1,2 @@
1
1
  require "omniauth-oauth2/version"
2
- require 'omniauth/strategies/oauth2'
2
+ require "omniauth/strategies/oauth2"
@@ -1,25 +1,24 @@
1
- # -*- encoding: utf-8 -*-
2
- require File.expand_path('../lib/omniauth-oauth2/version', __FILE__)
1
+ lib = File.expand_path("../lib", __FILE__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+ require "omniauth-oauth2/version"
3
4
 
4
5
  Gem::Specification.new do |gem|
5
- gem.add_dependency 'omniauth', '~> 1.0'
6
- gem.add_dependency 'oauth2', '~> 0.5.0'
6
+ gem.add_dependency "oauth2", [">= 1.4", "< 3"]
7
+ gem.add_dependency "omniauth", "~> 2.0"
7
8
 
8
- gem.add_development_dependency 'rspec', '~> 2.7'
9
- gem.add_development_dependency 'rack-test'
10
- gem.add_development_dependency 'webmock'
11
- gem.add_development_dependency 'simplecov'
9
+ gem.add_development_dependency "bundler", "~> 2.0"
12
10
 
13
- gem.authors = ["Michael Bleigh"]
14
- gem.email = ["michael@intridea.com"]
15
- gem.description = %q{An abstract OAuth2 strategy for OmniAuth.}
16
- gem.summary = %q{An abstract OAuth2 strategy for OmniAuth.}
17
- gem.homepage = "https://github.com/intridea/omniauth-oauth2"
11
+ gem.authors = ["Michael Bleigh", "Erik Michaels-Ober", "Tom Milewski"]
12
+ gem.email = ["michael@intridea.com", "sferik@gmail.com", "tmilewski@gmail.com"]
13
+ gem.description = "An abstract OAuth2 strategy for OmniAuth."
14
+ gem.summary = gem.description
15
+ gem.homepage = "https://github.com/omniauth/omniauth-oauth2"
16
+ gem.licenses = %w[MIT]
18
17
 
19
- gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
18
+ gem.executables = `git ls-files -- bin/*`.split("\n").collect { |f| File.basename(f) }
20
19
  gem.files = `git ls-files`.split("\n")
21
20
  gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
22
21
  gem.name = "omniauth-oauth2"
23
- gem.require_paths = ["lib"]
22
+ gem.require_paths = %w[lib]
24
23
  gem.version = OmniAuth::OAuth2::VERSION
25
24
  end
data/spec/helper.rb ADDED
@@ -0,0 +1,35 @@
1
+ $LOAD_PATH.unshift File.expand_path("..", __FILE__)
2
+ $LOAD_PATH.unshift File.expand_path("../../lib", __FILE__)
3
+
4
+ if RUBY_VERSION >= "1.9"
5
+ require "simplecov"
6
+ require "simplecov-lcov"
7
+ require "coveralls"
8
+
9
+ SimpleCov::Formatter::LcovFormatter.config.report_with_single_file = true
10
+
11
+ SimpleCov.formatters = [
12
+ SimpleCov::Formatter::HTMLFormatter,
13
+ SimpleCov::Formatter::LcovFormatter,
14
+ Coveralls::SimpleCov::Formatter
15
+ ]
16
+
17
+ SimpleCov.start do
18
+ minimum_coverage(78.48)
19
+ end
20
+ end
21
+
22
+ require "rspec"
23
+ require "rack/test"
24
+ require "webmock/rspec"
25
+ require "omniauth"
26
+ require "omniauth-oauth2"
27
+
28
+ RSpec.configure do |config|
29
+ config.expect_with :rspec do |c|
30
+ c.syntax = :expect
31
+ end
32
+ config.extend OmniAuth::Test::StrategyMacros, :type => :strategy
33
+ config.include Rack::Test::Methods
34
+ config.include WebMock::API
35
+ end
@@ -1,43 +1,161 @@
1
- require 'spec_helper'
1
+ require "helper"
2
2
 
3
3
  describe OmniAuth::Strategies::OAuth2 do
4
- def app; lambda{|env| [200, {}, ["Hello."]]} end
5
- let(:fresh_strategy){ Class.new(OmniAuth::Strategies::OAuth2) }
4
+ def app
5
+ lambda do |_env|
6
+ [200, {}, ["Hello."]]
7
+ end
8
+ end
9
+ let(:fresh_strategy) { Class.new(OmniAuth::Strategies::OAuth2) }
10
+
11
+ before do
12
+ OmniAuth.config.test_mode = true
13
+ end
14
+
15
+ after do
16
+ OmniAuth.config.test_mode = false
17
+ end
6
18
 
7
- describe '#client' do
8
- subject{ fresh_strategy }
19
+ describe "Subclassing Behavior" do
20
+ subject { fresh_strategy }
9
21
 
10
- it 'should be initialized with symbolized client_options' do
11
- instance = subject.new(app, :client_options => {'authorize_url' => 'https://example.com'})
12
- instance.client.options[:authorize_url].should == 'https://example.com'
22
+ it "performs the OmniAuth::Strategy included hook" do
23
+ expect(OmniAuth.strategies).to include(OmniAuth::Strategies::OAuth2)
24
+ expect(OmniAuth.strategies).to include(subject)
13
25
  end
14
26
  end
15
27
 
16
- describe '#authorize_params' do
28
+ describe "#client" do
17
29
  subject { fresh_strategy }
18
30
 
19
- it 'should include any authorize params passed in the :authorize_params option' do
20
- instance = subject.new('abc', 'def', :authorize_params => {:foo => 'bar', :baz => 'zip'})
21
- instance.authorize_params.should == {'foo' => 'bar', 'baz' => 'zip'}
31
+ it "is initialized with symbolized client_options" do
32
+ instance = subject.new(app, :client_options => {"authorize_url" => "https://example.com"})
33
+ expect(instance.client.options[:authorize_url]).to eq("https://example.com")
22
34
  end
23
35
 
24
- it 'should include top-level options that are marked as :authorize_options' do
25
- instance = subject.new('abc', 'def', :authorize_options => [:scope, :foo], :scope => 'bar', :foo => 'baz')
26
- instance.authorize_params.should == {'scope' => 'bar', 'foo' => 'baz'}
36
+ it "sets ssl options as connection options" do
37
+ instance = subject.new(app, :client_options => {"ssl" => {"ca_path" => "foo"}})
38
+ expect(instance.client.options[:connection_opts][:ssl]).to eq(:ca_path => "foo")
27
39
  end
28
40
  end
29
41
 
30
- describe '#token_params' do
42
+ describe "#authorize_params" do
31
43
  subject { fresh_strategy }
32
44
 
33
- it 'should include any authorize params passed in the :authorize_params option' do
34
- instance = subject.new('abc', 'def', :token_params => {:foo => 'bar', :baz => 'zip'})
35
- instance.token_params.should == {'foo' => 'bar', 'baz' => 'zip'}
45
+ it "includes any authorize params passed in the :authorize_params option" do
46
+ instance = subject.new("abc", "def", :authorize_params => {:foo => "bar", :baz => "zip"})
47
+ expect(instance.authorize_params["foo"]).to eq("bar")
48
+ expect(instance.authorize_params["baz"]).to eq("zip")
49
+ end
50
+
51
+ it "includes top-level options that are marked as :authorize_options" do
52
+ instance = subject.new("abc", "def", :authorize_options => %i[scope foo state], :scope => "bar", :foo => "baz")
53
+ expect(instance.authorize_params["scope"]).to eq("bar")
54
+ expect(instance.authorize_params["foo"]).to eq("baz")
55
+ expect(instance.authorize_params["state"]).not_to be_empty
56
+ end
57
+
58
+ it "includes random state in the authorize params" do
59
+ instance = subject.new("abc", "def")
60
+ expect(instance.authorize_params.keys).to eq(["state"])
61
+ expect(instance.session["omniauth.state"]).not_to be_empty
62
+ end
63
+
64
+ it "includes custom state in the authorize params" do
65
+ instance = subject.new("abc", "def", :state => proc { "qux" })
66
+ expect(instance.authorize_params.keys).to eq(["state"])
67
+ expect(instance.session["omniauth.state"]).to eq("qux")
68
+ end
69
+
70
+ it "includes PKCE parameters if enabled" do
71
+ instance = subject.new("abc", "def", :pkce => true)
72
+ expect(instance.authorize_params[:code_challenge]).to be_a(String)
73
+ expect(instance.authorize_params[:code_challenge_method]).to eq("S256")
74
+ expect(instance.session["omniauth.pkce.verifier"]).to be_a(String)
75
+ end
76
+ end
77
+
78
+ describe "#token_params" do
79
+ subject { fresh_strategy }
80
+
81
+ it "includes any authorize params passed in the :authorize_params option" do
82
+ instance = subject.new("abc", "def", :token_params => {:foo => "bar", :baz => "zip"})
83
+ expect(instance.token_params).to eq("foo" => "bar", "baz" => "zip")
84
+ end
85
+
86
+ it "includes top-level options that are marked as :authorize_options" do
87
+ instance = subject.new("abc", "def", :token_options => %i[scope foo], :scope => "bar", :foo => "baz")
88
+ expect(instance.token_params).to eq("scope" => "bar", "foo" => "baz")
89
+ end
90
+
91
+ it "includes the PKCE code_verifier if enabled" do
92
+ instance = subject.new("abc", "def", :pkce => true)
93
+ # setup session
94
+ instance.authorize_params
95
+ expect(instance.token_params[:code_verifier]).to be_a(String)
96
+ end
97
+ end
98
+
99
+ describe "#callback_phase" do
100
+ subject(:instance) { fresh_strategy.new("abc", "def") }
101
+
102
+ let(:params) { {"error_reason" => "user_denied", "error" => "access_denied", "state" => state} }
103
+ let(:state) { "secret" }
104
+
105
+ before do
106
+ allow(instance).to receive(:request) do
107
+ double("Request", :params => params)
108
+ end
109
+
110
+ allow(instance).to receive(:session) do
111
+ double("Session", :delete => state)
112
+ end
113
+ end
114
+
115
+ it "calls fail with the error received" do
116
+ expect(instance).to receive(:fail!).with("user_denied", anything)
117
+
118
+ instance.callback_phase
36
119
  end
37
120
 
38
- it 'should include top-level options that are marked as :authorize_options' do
39
- instance = subject.new('abc', 'def', :token_options => [:scope, :foo], :scope => 'bar', :foo => 'baz')
40
- instance.token_params.should == {'scope' => 'bar', 'foo' => 'baz'}
121
+ it "calls fail with the error received if state is missing and CSRF verification is disabled" do
122
+ params["state"] = nil
123
+ instance.options.provider_ignores_state = true
124
+
125
+ expect(instance).to receive(:fail!).with("user_denied", anything)
126
+
127
+ instance.callback_phase
128
+ end
129
+
130
+ it "calls fail with a CSRF error if the state is missing" do
131
+ params["state"] = nil
132
+
133
+ expect(instance).to receive(:fail!).with(:csrf_detected, anything)
134
+ instance.callback_phase
135
+ end
136
+
137
+ it "calls fail with a CSRF error if the state is invalid" do
138
+ params["state"] = "invalid"
139
+
140
+ expect(instance).to receive(:fail!).with(:csrf_detected, anything)
141
+ instance.callback_phase
142
+ end
143
+ end
144
+ end
145
+
146
+ describe OmniAuth::Strategies::OAuth2::CallbackError do
147
+ let(:error) { Class.new(OmniAuth::Strategies::OAuth2::CallbackError) }
148
+ describe "#message" do
149
+ subject { error }
150
+ it "includes all of the attributes" do
151
+ instance = subject.new("error", "description", "uri")
152
+ expect(instance.message).to match(/error/)
153
+ expect(instance.message).to match(/description/)
154
+ expect(instance.message).to match(/uri/)
155
+ end
156
+ it "includes all of the attributes" do
157
+ instance = subject.new(nil, :symbol)
158
+ expect(instance.message).to eq("symbol")
41
159
  end
42
160
  end
43
161
  end
metadata CHANGED
@@ -1,125 +1,114 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: omniauth-oauth2
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
5
- prerelease:
4
+ version: 1.8.0
6
5
  platform: ruby
7
6
  authors:
8
7
  - Michael Bleigh
9
- autorequire:
8
+ - Erik Michaels-Ober
9
+ - Tom Milewski
10
+ autorequire:
10
11
  bindir: bin
11
12
  cert_chain: []
12
- date: 2011-11-02 00:00:00.000000000Z
13
+ date: 2022-06-18 00:00:00.000000000 Z
13
14
  dependencies:
14
15
  - !ruby/object:Gem::Dependency
15
- name: omniauth
16
- requirement: &70244359505740 !ruby/object:Gem::Requirement
17
- none: false
16
+ name: oauth2
17
+ requirement: !ruby/object:Gem::Requirement
18
18
  requirements:
19
- - - ~>
19
+ - - ">="
20
+ - !ruby/object:Gem::Version
21
+ version: '1.4'
22
+ - - "<"
20
23
  - !ruby/object:Gem::Version
21
- version: '1.0'
24
+ version: '3'
22
25
  type: :runtime
23
26
  prerelease: false
24
- version_requirements: *70244359505740
25
- - !ruby/object:Gem::Dependency
26
- name: oauth2
27
- requirement: &70244359505120 !ruby/object:Gem::Requirement
28
- none: false
27
+ version_requirements: !ruby/object:Gem::Requirement
29
28
  requirements:
30
- - - ~>
29
+ - - ">="
31
30
  - !ruby/object:Gem::Version
32
- version: 0.5.0
33
- type: :runtime
34
- prerelease: false
35
- version_requirements: *70244359505120
31
+ version: '1.4'
32
+ - - "<"
33
+ - !ruby/object:Gem::Version
34
+ version: '3'
36
35
  - !ruby/object:Gem::Dependency
37
- name: rspec
38
- requirement: &70244359504360 !ruby/object:Gem::Requirement
39
- none: false
36
+ name: omniauth
37
+ requirement: !ruby/object:Gem::Requirement
40
38
  requirements:
41
- - - ~>
39
+ - - "~>"
42
40
  - !ruby/object:Gem::Version
43
- version: '2.7'
44
- type: :development
41
+ version: '2.0'
42
+ type: :runtime
45
43
  prerelease: false
46
- version_requirements: *70244359504360
47
- - !ruby/object:Gem::Dependency
48
- name: rack-test
49
- requirement: &70244359503620 !ruby/object:Gem::Requirement
50
- none: false
44
+ version_requirements: !ruby/object:Gem::Requirement
51
45
  requirements:
52
- - - ! '>='
46
+ - - "~>"
53
47
  - !ruby/object:Gem::Version
54
- version: '0'
55
- type: :development
56
- prerelease: false
57
- version_requirements: *70244359503620
48
+ version: '2.0'
58
49
  - !ruby/object:Gem::Dependency
59
- name: webmock
60
- requirement: &70244359502240 !ruby/object:Gem::Requirement
61
- none: false
50
+ name: bundler
51
+ requirement: !ruby/object:Gem::Requirement
62
52
  requirements:
63
- - - ! '>='
53
+ - - "~>"
64
54
  - !ruby/object:Gem::Version
65
- version: '0'
55
+ version: '2.0'
66
56
  type: :development
67
57
  prerelease: false
68
- version_requirements: *70244359502240
69
- - !ruby/object:Gem::Dependency
70
- name: simplecov
71
- requirement: &70244359501400 !ruby/object:Gem::Requirement
72
- none: false
58
+ version_requirements: !ruby/object:Gem::Requirement
73
59
  requirements:
74
- - - ! '>='
60
+ - - "~>"
75
61
  - !ruby/object:Gem::Version
76
- version: '0'
77
- type: :development
78
- prerelease: false
79
- version_requirements: *70244359501400
62
+ version: '2.0'
80
63
  description: An abstract OAuth2 strategy for OmniAuth.
81
64
  email:
82
65
  - michael@intridea.com
66
+ - sferik@gmail.com
67
+ - tmilewski@gmail.com
83
68
  executables: []
84
69
  extensions: []
85
70
  extra_rdoc_files: []
86
71
  files:
87
- - .gitignore
88
- - .rspec
72
+ - ".github/FUNDING.yml"
73
+ - ".github/workflows/main.yml"
74
+ - ".gitignore"
75
+ - ".rspec"
76
+ - ".rubocop.yml"
77
+ - CHANGELOG.md
89
78
  - Gemfile
90
- - Guardfile
79
+ - LICENSE.md
91
80
  - README.md
92
81
  - Rakefile
82
+ - SECURITY.md
93
83
  - lib/omniauth-oauth2.rb
94
84
  - lib/omniauth-oauth2/version.rb
95
85
  - lib/omniauth/strategies/oauth2.rb
96
86
  - omniauth-oauth2.gemspec
87
+ - spec/helper.rb
97
88
  - spec/omniauth/strategies/oauth2_spec.rb
98
- - spec/spec_helper.rb
99
- homepage: https://github.com/intridea/omniauth-oauth2
100
- licenses: []
101
- post_install_message:
89
+ homepage: https://github.com/omniauth/omniauth-oauth2
90
+ licenses:
91
+ - MIT
92
+ metadata: {}
93
+ post_install_message:
102
94
  rdoc_options: []
103
95
  require_paths:
104
96
  - lib
105
97
  required_ruby_version: !ruby/object:Gem::Requirement
106
- none: false
107
98
  requirements:
108
- - - ! '>='
99
+ - - ">="
109
100
  - !ruby/object:Gem::Version
110
101
  version: '0'
111
102
  required_rubygems_version: !ruby/object:Gem::Requirement
112
- none: false
113
103
  requirements:
114
- - - ! '>='
104
+ - - ">="
115
105
  - !ruby/object:Gem::Version
116
106
  version: '0'
117
107
  requirements: []
118
- rubyforge_project:
119
- rubygems_version: 1.8.10
120
- signing_key:
121
- specification_version: 3
108
+ rubygems_version: 3.2.32
109
+ signing_key:
110
+ specification_version: 4
122
111
  summary: An abstract OAuth2 strategy for OmniAuth.
123
112
  test_files:
113
+ - spec/helper.rb
124
114
  - spec/omniauth/strategies/oauth2_spec.rb
125
- - spec/spec_helper.rb
data/Guardfile DELETED
@@ -1,11 +0,0 @@
1
- guard 'rspec', :version => 2 do
2
- watch(%r{^spec/.+_spec\.rb$})
3
- watch(%r{^lib/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
4
- watch('spec/spec_helper.rb') { "spec" }
5
- end
6
-
7
-
8
- guard 'bundler' do
9
- watch('Gemfile')
10
- watch(/^.+\.gemspec/)
11
- end
data/spec/spec_helper.rb DELETED
@@ -1,16 +0,0 @@
1
- $:.unshift File.expand_path('..', __FILE__)
2
- $:.unshift File.expand_path('../../lib', __FILE__)
3
- require 'simplecov'
4
- SimpleCov.start
5
- require 'rspec'
6
- require 'rack/test'
7
- require 'webmock/rspec'
8
- require 'omniauth'
9
- require 'omniauth-oauth2'
10
-
11
- RSpec.configure do |config|
12
- config.include WebMock::API
13
- config.include Rack::Test::Methods
14
- config.extend OmniAuth::Test::StrategyMacros, :type => :strategy
15
- end
16
-