omniauth-oauth2 1.2.0 → 1.8.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.github/FUNDING.yml +2 -0
- data/.github/workflows/main.yml +67 -0
- data/.rubocop.yml +55 -57
- data/CHANGELOG.md +5 -0
- data/Gemfile +13 -18
- data/README.md +14 -6
- data/Rakefile +6 -5
- data/SECURITY.md +17 -0
- data/lib/omniauth/strategies/oauth2.rb +74 -39
- data/lib/omniauth-oauth2/version.rb +1 -1
- data/lib/omniauth-oauth2.rb +2 -2
- data/omniauth-oauth2.gemspec +12 -14
- data/spec/helper.rb +22 -15
- data/spec/omniauth/strategies/oauth2_spec.rb +103 -40
- metadata +22 -47
- data/.travis.yml +0 -22
- data/Guardfile +0 -11
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: f5cd52cdcb930eb0df65da3d7659a8e46f19db3426e0ecd8b3565b51e951331f
|
4
|
+
data.tar.gz: 6ed5b399aef49e82b265ff6175c849c44415f8b19f81ee5eb5d988ebb6c95fc8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e6bc5b97b326e37aa1e2ebb294b3459b57ba5dbb4d1e8b7e1709ed2dc9cfb8cc3b1b6f70ebbd0d5d830834af2472afe5b34762cf63f99a508334edee0d86b15a
|
7
|
+
data.tar.gz: 5c6cea848d8c9895495f7e931a3acfcee6e5e773824714e4de8bacfdc7aa70c3e40ad5cbce92b9a0d115f1dbd1f26aea7dc2b7a7bc02b1050cf38c501c3b7d45
|
data/.github/FUNDING.yml
ADDED
@@ -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/.rubocop.yml
CHANGED
@@ -1,82 +1,80 @@
|
|
1
1
|
AllCops:
|
2
|
-
|
3
|
-
- 'Gemfile'
|
4
|
-
- 'Rakefile'
|
5
|
-
- 'omniauth-oauth2.gemspec'
|
6
|
-
|
7
|
-
# Avoid long parameter lists
|
8
|
-
ParameterLists:
|
9
|
-
Max: 5
|
10
|
-
CountKeywordArgs: true
|
2
|
+
NewCops: enable
|
11
3
|
|
12
|
-
|
13
|
-
|
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:
|
14
21
|
Max: 18
|
15
22
|
|
16
|
-
|
17
|
-
|
23
|
+
Metrics/BlockLength:
|
24
|
+
Exclude:
|
25
|
+
- spec/omniauth/strategies/oauth2_spec.rb
|
26
|
+
|
27
|
+
Metrics/BlockNesting:
|
18
28
|
Max: 2
|
19
29
|
|
20
|
-
|
21
|
-
|
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:
|
22
46
|
PreferredMethods:
|
23
47
|
map: 'collect'
|
24
48
|
reduce: 'inject'
|
25
49
|
find: 'detect'
|
26
50
|
find_all: 'select'
|
27
51
|
|
28
|
-
|
29
|
-
# level as the def keyword. My personal preference is to outdent these keywords
|
30
|
-
# because I think when scanning code it makes it easier to identify the
|
31
|
-
# sections of code and visually separate them. When the keyword is at the same
|
32
|
-
# level I think it sort of blends in with the def keywords and makes it harder
|
33
|
-
# to scan the code and see where the sections are.
|
34
|
-
AccessModifierIndentation:
|
35
|
-
Enabled: false
|
36
|
-
|
37
|
-
# Limit line length
|
38
|
-
LineLength:
|
52
|
+
Style/Documentation:
|
39
53
|
Enabled: false
|
40
54
|
|
41
|
-
|
42
|
-
Documentation:
|
55
|
+
Style/DoubleNegation:
|
43
56
|
Enabled: false
|
44
57
|
|
45
|
-
|
46
|
-
HashSyntax:
|
47
|
-
EnforcedStyle: hash_rockets
|
48
|
-
|
49
|
-
# No spaces inside hash literals
|
50
|
-
SpaceInsideHashLiteralBraces:
|
51
|
-
EnforcedStyle: no_space
|
52
|
-
|
53
|
-
# Allow dots at the end of lines
|
54
|
-
DotPosition:
|
58
|
+
Style/ExpandPathArguments:
|
55
59
|
Enabled: false
|
56
60
|
|
57
|
-
|
58
|
-
Encoding:
|
61
|
+
Style/FrozenStringLiteralComment:
|
59
62
|
Enabled: false
|
60
63
|
|
61
|
-
|
62
|
-
|
63
|
-
EnforcedStyle: outdent
|
64
|
+
Style/HashSyntax:
|
65
|
+
EnforcedStyle: hash_rockets
|
64
66
|
|
65
|
-
|
66
|
-
Enabled:
|
67
|
+
Style/StderrPuts:
|
68
|
+
Enabled: false
|
67
69
|
|
68
|
-
|
69
|
-
|
70
|
-
AlignWith: variable
|
70
|
+
Style/StringLiterals:
|
71
|
+
EnforcedStyle: double_quotes
|
71
72
|
|
72
|
-
|
73
|
-
|
74
|
-
IndentWhenRelativeTo: end
|
75
|
-
IndentOneStep: false
|
73
|
+
Style/TrailingCommaInArguments:
|
74
|
+
EnforcedStyleForMultiline: comma
|
76
75
|
|
77
|
-
|
78
|
-
|
76
|
+
Style/TrailingCommaInHashLiteral:
|
77
|
+
EnforcedStyleForMultiline: comma
|
79
78
|
|
80
|
-
|
81
|
-
|
82
|
-
- 'lib/omniauth-oauth2.rb'
|
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,24 +1,19 @@
|
|
1
|
-
source
|
1
|
+
source "https://rubygems.org"
|
2
2
|
|
3
|
-
gem
|
4
|
-
|
5
|
-
group :development do
|
6
|
-
platforms :ruby_19, :ruby_20, :ruby_21 do
|
7
|
-
gem 'guard'
|
8
|
-
gem 'guard-rspec'
|
9
|
-
gem 'guard-bundler'
|
10
|
-
end
|
11
|
-
end
|
3
|
+
gem "rake", "~> 13.0"
|
12
4
|
|
13
5
|
group :test do
|
14
|
-
gem
|
15
|
-
gem '
|
16
|
-
gem
|
17
|
-
gem
|
18
|
-
gem
|
19
|
-
gem
|
20
|
-
gem
|
21
|
-
gem
|
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"
|
22
17
|
end
|
23
18
|
|
24
19
|
# Specify your gem's dependencies in omniauth-oauth2.gemspec
|
data/README.md
CHANGED
@@ -1,14 +1,11 @@
|
|
1
1
|
# OmniAuth OAuth2
|
2
2
|
|
3
3
|
[![Gem Version](http://img.shields.io/gem/v/omniauth-oauth2.svg)][gem]
|
4
|
-
[![
|
5
|
-
[![Dependency Status](http://img.shields.io/gemnasium/intridea/omniauth-oauth2.svg)][gemnasium]
|
6
|
-
[![Code Climate](http://img.shields.io/codeclimate/github/intridea/omniauth-oauth2.svg)][codeclimate]
|
4
|
+
[![Code Climate](http://img.shields.io/codeclimate/maintainability/intridea/omniauth-oauth2.svg)][codeclimate]
|
7
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)
|
8
7
|
|
9
8
|
[gem]: https://rubygems.org/gems/omniauth-oauth2
|
10
|
-
[travis]: http://travis-ci.org/intridea/omniauth-oauth2
|
11
|
-
[gemnasium]: https://gemnasium.com/intridea/omniauth-oauth2
|
12
9
|
[codeclimate]: https://codeclimate.com/github/intridea/omniauth-oauth2
|
13
10
|
[coveralls]: https://coveralls.io/r/intridea/omniauth-oauth2
|
14
11
|
|
@@ -34,6 +31,10 @@ module OmniAuth
|
|
34
31
|
# initializing your consumer from the OAuth gem.
|
35
32
|
option :client_options, {:site => "https://api.somesite.com"}
|
36
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
|
+
|
37
38
|
# These are called after authentication has succeeded. If
|
38
39
|
# possible, you should try to set the UID without making
|
39
40
|
# additional calls (if the user id is returned with the token
|
@@ -64,4 +65,11 @@ end
|
|
64
65
|
|
65
66
|
That's pretty much it!
|
66
67
|
|
67
|
-
|
68
|
+
## OmniAuth-OAuth2 for Enterprise
|
69
|
+
|
70
|
+
Available as part of the Tidelift Subscription.
|
71
|
+
|
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)
|
73
|
+
|
74
|
+
## Supported Ruby Versions
|
75
|
+
OmniAuth is tested under 2.5, 2.6, 2.7, truffleruby, and JRuby.
|
data/Rakefile
CHANGED
@@ -1,18 +1,19 @@
|
|
1
1
|
#!/usr/bin/env rake
|
2
|
-
|
3
|
-
require
|
2
|
+
|
3
|
+
require "bundler/gem_tasks"
|
4
|
+
require "rspec/core/rake_task"
|
4
5
|
|
5
6
|
RSpec::Core::RakeTask.new
|
6
7
|
|
7
8
|
task :test => :spec
|
8
9
|
|
9
10
|
begin
|
10
|
-
require
|
11
|
+
require "rubocop/rake_task"
|
11
12
|
RuboCop::RakeTask.new
|
12
13
|
rescue LoadError
|
13
14
|
task :rubocop do
|
14
|
-
$stderr.puts
|
15
|
+
$stderr.puts "RuboCop is disabled"
|
15
16
|
end
|
16
17
|
end
|
17
18
|
|
18
|
-
task :default => [
|
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,10 +1,8 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
6
|
-
require 'faraday' # for Faraday::Error::TimeoutError and Faraday::Error::ConnectionFailed
|
7
|
-
require 'multi_json' # for MultiJson::DecodeError
|
1
|
+
require "oauth2"
|
2
|
+
require "omniauth"
|
3
|
+
require "securerandom"
|
4
|
+
require "socket" # for SocketError
|
5
|
+
require "timeout" # for Timeout::Error
|
8
6
|
|
9
7
|
module OmniAuth
|
10
8
|
module Strategies
|
@@ -16,17 +14,32 @@ module OmniAuth
|
|
16
14
|
class OAuth2
|
17
15
|
include OmniAuth::Strategy
|
18
16
|
|
19
|
-
|
17
|
+
def self.inherited(subclass)
|
18
|
+
OmniAuth::Strategy.included(subclass)
|
19
|
+
end
|
20
|
+
|
21
|
+
args %i[client_id client_secret]
|
20
22
|
|
21
23
|
option :client_id, nil
|
22
24
|
option :client_secret, nil
|
23
25
|
option :client_options, {}
|
24
26
|
option :authorize_params, {}
|
25
|
-
option :authorize_options, [
|
27
|
+
option :authorize_options, %i[scope state]
|
26
28
|
option :token_params, {}
|
27
29
|
option :token_options, []
|
28
30
|
option :auth_token_params, {}
|
29
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
|
+
}
|
30
43
|
|
31
44
|
attr_accessor :access_token
|
32
45
|
|
@@ -34,15 +47,11 @@ module OmniAuth
|
|
34
47
|
::OAuth2::Client.new(options.client_id, options.client_secret, deep_symbolize(options.client_options))
|
35
48
|
end
|
36
49
|
|
37
|
-
def callback_url
|
38
|
-
full_host + script_name + callback_path
|
39
|
-
end
|
40
|
-
|
41
50
|
credentials do
|
42
|
-
hash = {
|
43
|
-
hash
|
44
|
-
hash
|
45
|
-
hash
|
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?
|
46
55
|
hash
|
47
56
|
end
|
48
57
|
|
@@ -50,27 +59,34 @@ module OmniAuth
|
|
50
59
|
redirect client.auth_code.authorize_url({:redirect_uri => callback_url}.merge(authorize_params))
|
51
60
|
end
|
52
61
|
|
53
|
-
def authorize_params
|
62
|
+
def authorize_params # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
54
63
|
options.authorize_params[:state] = SecureRandom.hex(24)
|
55
|
-
|
64
|
+
|
56
65
|
if OmniAuth.config.test_mode
|
57
66
|
@env ||= {}
|
58
|
-
@env[
|
67
|
+
@env["rack.session"] ||= {}
|
59
68
|
end
|
60
|
-
|
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
|
+
|
61
77
|
params
|
62
78
|
end
|
63
79
|
|
64
80
|
def token_params
|
65
|
-
options.token_params.merge(options_for(
|
81
|
+
options.token_params.merge(options_for("token")).merge(pkce_token_params)
|
66
82
|
end
|
67
83
|
|
68
|
-
def callback_phase # rubocop:disable CyclomaticComplexity
|
69
|
-
error = request.params[
|
70
|
-
if
|
71
|
-
fail!(
|
72
|
-
elsif
|
73
|
-
fail!(
|
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"]))
|
74
90
|
else
|
75
91
|
self.access_token = build_access_token
|
76
92
|
self.access_token = access_token.refresh! if access_token.expired?
|
@@ -78,33 +94,52 @@ module OmniAuth
|
|
78
94
|
end
|
79
95
|
rescue ::OAuth2::Error, CallbackError => e
|
80
96
|
fail!(:invalid_credentials, e)
|
81
|
-
rescue ::
|
82
|
-
fail!(:invalid_response, e)
|
83
|
-
rescue ::Timeout::Error, ::Errno::ETIMEDOUT, Faraday::Error::TimeoutError => e
|
97
|
+
rescue ::Timeout::Error, ::Errno::ETIMEDOUT => e
|
84
98
|
fail!(:timeout, e)
|
85
|
-
rescue ::SocketError
|
99
|
+
rescue ::SocketError => e
|
86
100
|
fail!(:failed_to_connect, e)
|
87
101
|
end
|
88
102
|
|
89
103
|
protected
|
90
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
|
+
}
|
116
|
+
end
|
117
|
+
|
118
|
+
def pkce_token_params
|
119
|
+
return {} unless options.pkce
|
120
|
+
|
121
|
+
{:code_verifier => session.delete("omniauth.pkce.verifier")}
|
122
|
+
end
|
123
|
+
|
91
124
|
def build_access_token
|
92
|
-
verifier = request.params[
|
125
|
+
verifier = request.params["code"]
|
93
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))
|
94
127
|
end
|
95
128
|
|
96
129
|
def deep_symbolize(options)
|
97
|
-
|
98
|
-
options.each do |key, value|
|
130
|
+
options.each_with_object({}) do |(key, value), hash|
|
99
131
|
hash[key.to_sym] = value.is_a?(Hash) ? deep_symbolize(value) : value
|
100
132
|
end
|
101
|
-
hash
|
102
133
|
end
|
103
134
|
|
104
135
|
def options_for(option)
|
105
136
|
hash = {}
|
106
137
|
options.send(:"#{option}_options").select { |key| options[key] }.each do |key|
|
107
|
-
hash[key.to_sym] = options[key]
|
138
|
+
hash[key.to_sym] = if options[key].respond_to?(:call)
|
139
|
+
options[key].call(env)
|
140
|
+
else
|
141
|
+
options[key]
|
142
|
+
end
|
108
143
|
end
|
109
144
|
hash
|
110
145
|
end
|
@@ -121,11 +156,11 @@ module OmniAuth
|
|
121
156
|
end
|
122
157
|
|
123
158
|
def message
|
124
|
-
[error, error_reason, error_uri].compact.join(
|
159
|
+
[error, error_reason, error_uri].compact.join(" | ")
|
125
160
|
end
|
126
161
|
end
|
127
162
|
end
|
128
163
|
end
|
129
164
|
end
|
130
165
|
|
131
|
-
OmniAuth.config.add_camelization
|
166
|
+
OmniAuth.config.add_camelization "oauth2", "OAuth2"
|
data/lib/omniauth-oauth2.rb
CHANGED
@@ -1,2 +1,2 @@
|
|
1
|
-
require
|
2
|
-
require
|
1
|
+
require "omniauth-oauth2/version"
|
2
|
+
require "omniauth/strategies/oauth2"
|
data/omniauth-oauth2.gemspec
CHANGED
@@ -1,26 +1,24 @@
|
|
1
|
-
lib = File.expand_path(
|
1
|
+
lib = File.expand_path("../lib", __FILE__)
|
2
2
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
3
|
-
require
|
3
|
+
require "omniauth-oauth2/version"
|
4
4
|
|
5
5
|
Gem::Specification.new do |gem|
|
6
|
-
gem.add_dependency
|
7
|
-
gem.add_dependency
|
8
|
-
gem.add_dependency 'oauth2', '~> 1.0'
|
9
|
-
gem.add_dependency 'omniauth', '~> 1.2'
|
6
|
+
gem.add_dependency "oauth2", [">= 1.4", "< 3"]
|
7
|
+
gem.add_dependency "omniauth", "~> 2.0"
|
10
8
|
|
11
|
-
gem.add_development_dependency
|
9
|
+
gem.add_development_dependency "bundler", "~> 2.0"
|
12
10
|
|
13
|
-
gem.authors = [
|
14
|
-
gem.email = [
|
15
|
-
gem.description =
|
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."
|
16
14
|
gem.summary = gem.description
|
17
|
-
gem.homepage =
|
18
|
-
gem.licenses = %w
|
15
|
+
gem.homepage = "https://github.com/omniauth/omniauth-oauth2"
|
16
|
+
gem.licenses = %w[MIT]
|
19
17
|
|
20
18
|
gem.executables = `git ls-files -- bin/*`.split("\n").collect { |f| File.basename(f) }
|
21
19
|
gem.files = `git ls-files`.split("\n")
|
22
20
|
gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
23
|
-
gem.name =
|
24
|
-
gem.require_paths = %w
|
21
|
+
gem.name = "omniauth-oauth2"
|
22
|
+
gem.require_paths = %w[lib]
|
25
23
|
gem.version = OmniAuth::OAuth2::VERSION
|
26
24
|
end
|
data/spec/helper.rb
CHANGED
@@ -1,22 +1,29 @@
|
|
1
|
-
$LOAD_PATH.unshift File.expand_path(
|
2
|
-
$LOAD_PATH.unshift File.expand_path(
|
1
|
+
$LOAD_PATH.unshift File.expand_path("..", __FILE__)
|
2
|
+
$LOAD_PATH.unshift File.expand_path("../../lib", __FILE__)
|
3
3
|
|
4
|
-
|
5
|
-
require
|
4
|
+
if RUBY_VERSION >= "1.9"
|
5
|
+
require "simplecov"
|
6
|
+
require "simplecov-lcov"
|
7
|
+
require "coveralls"
|
6
8
|
|
7
|
-
SimpleCov.
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
SimpleCov
|
12
|
-
|
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
|
13
20
|
end
|
14
21
|
|
15
|
-
require
|
16
|
-
require
|
17
|
-
require
|
18
|
-
require
|
19
|
-
require
|
22
|
+
require "rspec"
|
23
|
+
require "rack/test"
|
24
|
+
require "webmock/rspec"
|
25
|
+
require "omniauth"
|
26
|
+
require "omniauth-oauth2"
|
20
27
|
|
21
28
|
RSpec.configure do |config|
|
22
29
|
config.expect_with :rspec do |c|
|
@@ -1,9 +1,9 @@
|
|
1
|
-
require
|
1
|
+
require "helper"
|
2
2
|
|
3
3
|
describe OmniAuth::Strategies::OAuth2 do
|
4
4
|
def app
|
5
5
|
lambda do |_env|
|
6
|
-
[200, {}, [
|
6
|
+
[200, {}, ["Hello."]]
|
7
7
|
end
|
8
8
|
end
|
9
9
|
let(:fresh_strategy) { Class.new(OmniAuth::Strategies::OAuth2) }
|
@@ -16,65 +16,128 @@ describe OmniAuth::Strategies::OAuth2 do
|
|
16
16
|
OmniAuth.config.test_mode = false
|
17
17
|
end
|
18
18
|
|
19
|
-
describe
|
19
|
+
describe "Subclassing Behavior" do
|
20
20
|
subject { fresh_strategy }
|
21
21
|
|
22
|
-
it
|
23
|
-
|
24
|
-
expect(
|
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)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe "#client" do
|
29
|
+
subject { fresh_strategy }
|
30
|
+
|
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")
|
25
34
|
end
|
26
35
|
|
27
|
-
it
|
28
|
-
instance = subject.new(app, :client_options => {
|
29
|
-
expect(instance.client.options[:connection_opts][:ssl]).to eq(:ca_path =>
|
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")
|
30
39
|
end
|
31
40
|
end
|
32
41
|
|
33
|
-
describe
|
42
|
+
describe "#authorize_params" do
|
34
43
|
subject { fresh_strategy }
|
35
44
|
|
36
|
-
it
|
37
|
-
instance = subject.new(
|
38
|
-
expect(instance.authorize_params[
|
39
|
-
expect(instance.authorize_params[
|
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
|
40
62
|
end
|
41
63
|
|
42
|
-
it
|
43
|
-
instance = subject.new(
|
44
|
-
expect(instance.authorize_params
|
45
|
-
expect(instance.
|
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")
|
46
68
|
end
|
47
69
|
|
48
|
-
it
|
49
|
-
instance = subject.new(
|
50
|
-
expect(instance.authorize_params
|
51
|
-
expect(instance.
|
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)
|
52
75
|
end
|
53
76
|
end
|
54
77
|
|
55
|
-
describe
|
78
|
+
describe "#token_params" do
|
56
79
|
subject { fresh_strategy }
|
57
80
|
|
58
|
-
it
|
59
|
-
instance = subject.new(
|
60
|
-
expect(instance.token_params).to eq(
|
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")
|
61
89
|
end
|
62
90
|
|
63
|
-
it
|
64
|
-
instance = subject.new(
|
65
|
-
|
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)
|
66
96
|
end
|
67
97
|
end
|
68
98
|
|
69
|
-
describe
|
70
|
-
subject { fresh_strategy }
|
71
|
-
|
72
|
-
|
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
|
73
106
|
allow(instance).to receive(:request) do
|
74
|
-
double(
|
107
|
+
double("Request", :params => params)
|
108
|
+
end
|
109
|
+
|
110
|
+
allow(instance).to receive(:session) do
|
111
|
+
double("Session", :delete => state)
|
75
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
|
119
|
+
end
|
120
|
+
|
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"
|
76
139
|
|
77
|
-
expect(instance).to receive(:fail!).with(
|
140
|
+
expect(instance).to receive(:fail!).with(:csrf_detected, anything)
|
78
141
|
instance.callback_phase
|
79
142
|
end
|
80
143
|
end
|
@@ -82,17 +145,17 @@ end
|
|
82
145
|
|
83
146
|
describe OmniAuth::Strategies::OAuth2::CallbackError do
|
84
147
|
let(:error) { Class.new(OmniAuth::Strategies::OAuth2::CallbackError) }
|
85
|
-
describe
|
148
|
+
describe "#message" do
|
86
149
|
subject { error }
|
87
|
-
it
|
88
|
-
instance = subject.new(
|
150
|
+
it "includes all of the attributes" do
|
151
|
+
instance = subject.new("error", "description", "uri")
|
89
152
|
expect(instance.message).to match(/error/)
|
90
153
|
expect(instance.message).to match(/description/)
|
91
154
|
expect(instance.message).to match(/uri/)
|
92
155
|
end
|
93
|
-
it
|
156
|
+
it "includes all of the attributes" do
|
94
157
|
instance = subject.new(nil, :symbol)
|
95
|
-
expect(instance.message).to eq(
|
158
|
+
expect(instance.message).to eq("symbol")
|
96
159
|
end
|
97
160
|
end
|
98
161
|
end
|
metadata
CHANGED
@@ -1,120 +1,96 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: omniauth-oauth2
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.8.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Michael Bleigh
|
8
8
|
- Erik Michaels-Ober
|
9
|
-
|
9
|
+
- Tom Milewski
|
10
|
+
autorequire:
|
10
11
|
bindir: bin
|
11
12
|
cert_chain: []
|
12
|
-
date:
|
13
|
+
date: 2022-06-18 00:00:00.000000000 Z
|
13
14
|
dependencies:
|
14
15
|
- !ruby/object:Gem::Dependency
|
15
|
-
name:
|
16
|
+
name: oauth2
|
16
17
|
requirement: !ruby/object:Gem::Requirement
|
17
18
|
requirements:
|
18
19
|
- - ">="
|
19
20
|
- !ruby/object:Gem::Version
|
20
|
-
version: '
|
21
|
+
version: '1.4'
|
21
22
|
- - "<"
|
22
23
|
- !ruby/object:Gem::Version
|
23
|
-
version: '
|
24
|
+
version: '3'
|
24
25
|
type: :runtime
|
25
26
|
prerelease: false
|
26
27
|
version_requirements: !ruby/object:Gem::Requirement
|
27
28
|
requirements:
|
28
29
|
- - ">="
|
29
30
|
- !ruby/object:Gem::Version
|
30
|
-
version: '
|
31
|
+
version: '1.4'
|
31
32
|
- - "<"
|
32
33
|
- !ruby/object:Gem::Version
|
33
|
-
version: '
|
34
|
-
- !ruby/object:Gem::Dependency
|
35
|
-
name: multi_json
|
36
|
-
requirement: !ruby/object:Gem::Requirement
|
37
|
-
requirements:
|
38
|
-
- - "~>"
|
39
|
-
- !ruby/object:Gem::Version
|
40
|
-
version: '1.3'
|
41
|
-
type: :runtime
|
42
|
-
prerelease: false
|
43
|
-
version_requirements: !ruby/object:Gem::Requirement
|
44
|
-
requirements:
|
45
|
-
- - "~>"
|
46
|
-
- !ruby/object:Gem::Version
|
47
|
-
version: '1.3'
|
48
|
-
- !ruby/object:Gem::Dependency
|
49
|
-
name: oauth2
|
50
|
-
requirement: !ruby/object:Gem::Requirement
|
51
|
-
requirements:
|
52
|
-
- - "~>"
|
53
|
-
- !ruby/object:Gem::Version
|
54
|
-
version: '1.0'
|
55
|
-
type: :runtime
|
56
|
-
prerelease: false
|
57
|
-
version_requirements: !ruby/object:Gem::Requirement
|
58
|
-
requirements:
|
59
|
-
- - "~>"
|
60
|
-
- !ruby/object:Gem::Version
|
61
|
-
version: '1.0'
|
34
|
+
version: '3'
|
62
35
|
- !ruby/object:Gem::Dependency
|
63
36
|
name: omniauth
|
64
37
|
requirement: !ruby/object:Gem::Requirement
|
65
38
|
requirements:
|
66
39
|
- - "~>"
|
67
40
|
- !ruby/object:Gem::Version
|
68
|
-
version: '
|
41
|
+
version: '2.0'
|
69
42
|
type: :runtime
|
70
43
|
prerelease: false
|
71
44
|
version_requirements: !ruby/object:Gem::Requirement
|
72
45
|
requirements:
|
73
46
|
- - "~>"
|
74
47
|
- !ruby/object:Gem::Version
|
75
|
-
version: '
|
48
|
+
version: '2.0'
|
76
49
|
- !ruby/object:Gem::Dependency
|
77
50
|
name: bundler
|
78
51
|
requirement: !ruby/object:Gem::Requirement
|
79
52
|
requirements:
|
80
53
|
- - "~>"
|
81
54
|
- !ruby/object:Gem::Version
|
82
|
-
version: '
|
55
|
+
version: '2.0'
|
83
56
|
type: :development
|
84
57
|
prerelease: false
|
85
58
|
version_requirements: !ruby/object:Gem::Requirement
|
86
59
|
requirements:
|
87
60
|
- - "~>"
|
88
61
|
- !ruby/object:Gem::Version
|
89
|
-
version: '
|
62
|
+
version: '2.0'
|
90
63
|
description: An abstract OAuth2 strategy for OmniAuth.
|
91
64
|
email:
|
92
65
|
- michael@intridea.com
|
93
66
|
- sferik@gmail.com
|
67
|
+
- tmilewski@gmail.com
|
94
68
|
executables: []
|
95
69
|
extensions: []
|
96
70
|
extra_rdoc_files: []
|
97
71
|
files:
|
72
|
+
- ".github/FUNDING.yml"
|
73
|
+
- ".github/workflows/main.yml"
|
98
74
|
- ".gitignore"
|
99
75
|
- ".rspec"
|
100
76
|
- ".rubocop.yml"
|
101
|
-
-
|
77
|
+
- CHANGELOG.md
|
102
78
|
- Gemfile
|
103
|
-
- Guardfile
|
104
79
|
- LICENSE.md
|
105
80
|
- README.md
|
106
81
|
- Rakefile
|
82
|
+
- SECURITY.md
|
107
83
|
- lib/omniauth-oauth2.rb
|
108
84
|
- lib/omniauth-oauth2/version.rb
|
109
85
|
- lib/omniauth/strategies/oauth2.rb
|
110
86
|
- omniauth-oauth2.gemspec
|
111
87
|
- spec/helper.rb
|
112
88
|
- spec/omniauth/strategies/oauth2_spec.rb
|
113
|
-
homepage: https://github.com/
|
89
|
+
homepage: https://github.com/omniauth/omniauth-oauth2
|
114
90
|
licenses:
|
115
91
|
- MIT
|
116
92
|
metadata: {}
|
117
|
-
post_install_message:
|
93
|
+
post_install_message:
|
118
94
|
rdoc_options: []
|
119
95
|
require_paths:
|
120
96
|
- lib
|
@@ -129,9 +105,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
129
105
|
- !ruby/object:Gem::Version
|
130
106
|
version: '0'
|
131
107
|
requirements: []
|
132
|
-
|
133
|
-
|
134
|
-
signing_key:
|
108
|
+
rubygems_version: 3.2.32
|
109
|
+
signing_key:
|
135
110
|
specification_version: 4
|
136
111
|
summary: An abstract OAuth2 strategy for OmniAuth.
|
137
112
|
test_files:
|
data/.travis.yml
DELETED
@@ -1,22 +0,0 @@
|
|
1
|
-
bundler_args: --without development
|
2
|
-
language: ruby
|
3
|
-
rvm:
|
4
|
-
- 1.8.7
|
5
|
-
- 1.9.2
|
6
|
-
- 1.9.3
|
7
|
-
- 2.0.0
|
8
|
-
- 2.1.0
|
9
|
-
- rbx-2
|
10
|
-
- ruby-head
|
11
|
-
matrix:
|
12
|
-
include:
|
13
|
-
- rvm: jruby-18mode
|
14
|
-
env: JRUBY_OPTS="$JRUBY_OPTS --debug"
|
15
|
-
- rvm: jruby-19mode
|
16
|
-
env: JRUBY_OPTS="$JRUBY_OPTS --debug"
|
17
|
-
- rvm: jruby-head
|
18
|
-
env: JRUBY_OPTS="$JRUBY_OPTS --debug"
|
19
|
-
allow_failures:
|
20
|
-
- rvm: jruby-head
|
21
|
-
- rvm: ruby-head
|
22
|
-
fast_finish: true
|
data/Guardfile
DELETED