omniauth-google-oauth2 0.4.1 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.rubocop.yml +20 -0
- data/.travis.yml +4 -12
- data/CHANGELOG.md +17 -0
- data/Gemfile +2 -4
- data/README.md +85 -83
- data/Rakefile +3 -2
- data/examples/Gemfile +4 -2
- data/examples/config.ru +82 -7
- data/examples/omni_auth.rb +8 -20
- data/lib/omniauth-google-oauth2.rb +3 -1
- data/lib/omniauth/google_oauth2.rb +3 -1
- data/lib/omniauth/google_oauth2/version.rb +3 -1
- data/lib/omniauth/strategies/google_oauth2.rb +64 -52
- data/omniauth-google-oauth2.gemspec +17 -11
- data/spec/omniauth/strategies/google_oauth2_spec.rb +206 -120
- data/spec/rubocop_spec.rb +9 -0
- data/spec/spec_helper.rb +3 -1
- metadata +31 -15
- data/examples/auth.js +0 -43
data/examples/omni_auth.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# Google's OAuth2 docs. Make sure you are familiar with all the options
|
2
4
|
# before attempting to configure this gem.
|
3
5
|
# https://developers.google.com/accounts/docs/OAuth2Login
|
@@ -6,40 +8,26 @@ Rails.application.config.middleware.use OmniAuth::Builder do
|
|
6
8
|
# Default usage, this will give you offline access and a refresh token
|
7
9
|
# using default scopes 'email' and 'profile'
|
8
10
|
#
|
9
|
-
provider :google_oauth2, ENV['GOOGLE_KEY'], ENV['GOOGLE_SECRET'],
|
10
|
-
:scope => 'email,profile'
|
11
|
-
}
|
11
|
+
provider :google_oauth2, ENV['GOOGLE_KEY'], ENV['GOOGLE_SECRET'], scope: 'email,profile'
|
12
12
|
|
13
13
|
# Manual setup for offline access with a refresh token.
|
14
14
|
#
|
15
|
-
# provider :google_oauth2, ENV['GOOGLE_KEY'], ENV['GOOGLE_SECRET'],
|
16
|
-
# :access_type => 'offline',
|
17
|
-
# }
|
15
|
+
# provider :google_oauth2, ENV['GOOGLE_KEY'], ENV['GOOGLE_SECRET'], access_type: 'offline'
|
18
16
|
|
19
17
|
# Custom scope supporting youtube. If you are customizing scopes, remember
|
20
18
|
# to include the default scopes 'email' and 'profile'
|
21
19
|
#
|
22
|
-
# provider :google_oauth2, ENV['GOOGLE_KEY'], ENV['GOOGLE_SECRET'],
|
23
|
-
# :scope => 'http://gdata.youtube.com,email,profile,plus.me'
|
24
|
-
# }
|
20
|
+
# provider :google_oauth2, ENV['GOOGLE_KEY'], ENV['GOOGLE_SECRET'], scope: 'http://gdata.youtube.com,email,profile,plus.me'
|
25
21
|
|
26
22
|
# Custom scope for users only using Google for account creation/auth and do not require a refresh token.
|
27
23
|
#
|
28
|
-
# provider :google_oauth2, ENV['GOOGLE_KEY'], ENV['GOOGLE_SECRET'],
|
29
|
-
# :access_type => 'online',
|
30
|
-
# :prompt => ''
|
31
|
-
# }
|
24
|
+
# provider :google_oauth2, ENV['GOOGLE_KEY'], ENV['GOOGLE_SECRET'], access_type: 'online', prompt: ''
|
32
25
|
|
33
26
|
# To include information about people in your circles you must include the 'plus.login' scope.
|
34
27
|
#
|
35
|
-
# provider :google_oauth2, ENV['GOOGLE_KEY'], ENV['GOOGLE_SECRET'],
|
36
|
-
# :skip_friends => false,
|
37
|
-
# :scope => "email,profile,plus.login"
|
38
|
-
# }
|
28
|
+
# provider :google_oauth2, ENV['GOOGLE_KEY'], ENV['GOOGLE_SECRET'], skip_friends: false, scope: 'email,profile,plus.login'
|
39
29
|
|
40
30
|
# If you need to acquire whether user picture is a default one or uploaded by user.
|
41
31
|
#
|
42
|
-
# provider :google_oauth2, ENV['GOOGLE_KEY'], ENV['GOOGLE_SECRET'],
|
43
|
-
# :skip_image_info => false
|
44
|
-
# }
|
32
|
+
# provider :google_oauth2, ENV['GOOGLE_KEY'], ENV['GOOGLE_SECRET'], skip_image_info: false
|
45
33
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'multi_json'
|
2
4
|
require 'jwt'
|
3
5
|
require 'omniauth/strategies/oauth2'
|
@@ -5,23 +7,24 @@ require 'uri'
|
|
5
7
|
|
6
8
|
module OmniAuth
|
7
9
|
module Strategies
|
10
|
+
# Main class for Google OAuth2 strategy.
|
8
11
|
class GoogleOauth2 < OmniAuth::Strategies::OAuth2
|
9
|
-
BASE_SCOPE_URL =
|
10
|
-
BASE_SCOPES = %w[profile email openid]
|
11
|
-
DEFAULT_SCOPE =
|
12
|
+
BASE_SCOPE_URL = 'https://www.googleapis.com/auth/'
|
13
|
+
BASE_SCOPES = %w[profile email openid].freeze
|
14
|
+
DEFAULT_SCOPE = 'email,profile'
|
12
15
|
|
13
16
|
option :name, 'google_oauth2'
|
14
17
|
option :skip_friends, true
|
15
18
|
option :skip_image_info, true
|
16
19
|
option :skip_jwt, false
|
17
20
|
option :jwt_leeway, 60
|
18
|
-
option :authorize_options, [
|
21
|
+
option :authorize_options, %i[access_type hd login_hint prompt request_visible_actions scope state redirect_uri include_granted_scopes openid_realm]
|
22
|
+
option :authorized_client_ids, []
|
19
23
|
|
20
|
-
option :client_options,
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
}
|
24
|
+
option :client_options,
|
25
|
+
site: 'https://accounts.google.com',
|
26
|
+
authorize_url: '/o/oauth2/auth',
|
27
|
+
token_url: '/o/oauth2/token'
|
25
28
|
|
26
29
|
def authorize_params
|
27
30
|
super.tap do |params|
|
@@ -29,30 +32,27 @@ module OmniAuth
|
|
29
32
|
params[k] = request.params[k.to_s] unless [nil, ''].include?(request.params[k.to_s])
|
30
33
|
end
|
31
34
|
|
32
|
-
|
33
|
-
scope_list = raw_scope.split(" ").map {|item| item.split(",")}.flatten
|
34
|
-
scope_list.map! { |s| s =~ /^https?:\/\// || BASE_SCOPES.include?(s) ? s : "#{BASE_SCOPE_URL}#{s}" }
|
35
|
-
params[:scope] = scope_list.join(" ")
|
35
|
+
params[:scope] = get_scope(params)
|
36
36
|
params[:access_type] = 'offline' if params[:access_type].nil?
|
37
37
|
params['openid.realm'] = params.delete(:openid_realm) unless params[:openid_realm].nil?
|
38
38
|
|
39
|
-
session['omniauth.state'] = params[:state] if params[
|
39
|
+
session['omniauth.state'] = params[:state] if params[:state]
|
40
40
|
end
|
41
41
|
end
|
42
42
|
|
43
|
-
uid { raw_info['sub']
|
43
|
+
uid { raw_info['sub'] }
|
44
44
|
|
45
45
|
info do
|
46
|
-
prune!(
|
47
|
-
:
|
48
|
-
:
|
49
|
-
:
|
50
|
-
:
|
51
|
-
:
|
52
|
-
:
|
53
|
-
|
46
|
+
prune!(
|
47
|
+
name: raw_info['name'],
|
48
|
+
email: verified_email,
|
49
|
+
first_name: raw_info['given_name'],
|
50
|
+
last_name: raw_info['family_name'],
|
51
|
+
image: image_url,
|
52
|
+
urls: {
|
53
|
+
google: raw_info['profile']
|
54
54
|
}
|
55
|
-
|
55
|
+
)
|
56
56
|
end
|
57
57
|
|
58
58
|
extra do
|
@@ -60,18 +60,17 @@ module OmniAuth
|
|
60
60
|
hash[:id_token] = access_token['id_token']
|
61
61
|
if !options[:skip_jwt] && !access_token['id_token'].nil?
|
62
62
|
hash[:id_info] = JWT.decode(
|
63
|
-
access_token['id_token'], nil, false,
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
}).first
|
63
|
+
access_token['id_token'], nil, false, verify_iss: true,
|
64
|
+
iss: 'accounts.google.com',
|
65
|
+
verify_aud: true,
|
66
|
+
aud: options.client_id,
|
67
|
+
verify_sub: false,
|
68
|
+
verify_expiration: true,
|
69
|
+
verify_not_before: true,
|
70
|
+
verify_iat: true,
|
71
|
+
verify_jti: false,
|
72
|
+
leeway: options[:jwt_leeway]
|
73
|
+
).first
|
75
74
|
end
|
76
75
|
hash[:raw_info] = raw_info unless skip_info?
|
77
76
|
hash[:raw_friend_info] = raw_friend_info(raw_info['sub']) unless skip_info? || options[:skip_friends]
|
@@ -92,10 +91,24 @@ module OmniAuth
|
|
92
91
|
end
|
93
92
|
|
94
93
|
def custom_build_access_token
|
95
|
-
access_token =
|
94
|
+
access_token = get_access_token(request)
|
95
|
+
|
96
|
+
verify_hd(access_token)
|
97
|
+
access_token
|
98
|
+
end
|
99
|
+
alias build_access_token custom_build_access_token
|
100
|
+
|
101
|
+
private
|
102
|
+
|
103
|
+
def callback_url
|
104
|
+
options[:redirect_uri] || (full_host + script_name + callback_path)
|
105
|
+
end
|
106
|
+
|
107
|
+
def get_access_token(request)
|
96
108
|
if request.xhr? && request.params['code']
|
97
109
|
verifier = request.params['code']
|
98
|
-
|
110
|
+
redirect_uri = request.params['redirect_uri'] || 'postmessage'
|
111
|
+
client.auth_code.get_token(verifier, get_token_options(redirect_uri), deep_symbolize(options.auth_token_params || {}))
|
99
112
|
elsif request.params['code'] && request.params['redirect_uri']
|
100
113
|
verifier = request.params['code']
|
101
114
|
redirect_uri = request.params['redirect_uri']
|
@@ -103,23 +116,20 @@ module OmniAuth
|
|
103
116
|
elsif verify_token(request.params['access_token'])
|
104
117
|
::OAuth2::AccessToken.from_hash(client, request.params.dup)
|
105
118
|
else
|
106
|
-
verifier = request.params[
|
119
|
+
verifier = request.params['code']
|
107
120
|
client.auth_code.get_token(verifier, get_token_options(callback_url), deep_symbolize(options.auth_token_params))
|
108
121
|
end
|
109
|
-
|
110
|
-
verify_hd(access_token)
|
111
|
-
access_token
|
112
122
|
end
|
113
|
-
alias_method :build_access_token, :custom_build_access_token
|
114
123
|
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
124
|
+
def get_scope(params)
|
125
|
+
raw_scope = params[:scope] || DEFAULT_SCOPE
|
126
|
+
scope_list = raw_scope.split(' ').map { |item| item.split(',') }.flatten
|
127
|
+
scope_list.map! { |s| s =~ %r{^https?://} || BASE_SCOPES.include?(s) ? s : "#{BASE_SCOPE_URL}#{s}" }
|
128
|
+
scope_list.join(' ')
|
119
129
|
end
|
120
130
|
|
121
131
|
def get_token_options(redirect_uri)
|
122
|
-
{ :
|
132
|
+
{ redirect_uri: redirect_uri }.merge(token_params.to_hash(symbolize_keys: true))
|
123
133
|
end
|
124
134
|
|
125
135
|
def prune!(hash)
|
@@ -151,7 +161,7 @@ module OmniAuth
|
|
151
161
|
end
|
152
162
|
|
153
163
|
def image_size_opts_passed?
|
154
|
-
|
164
|
+
options[:image_size] || options[:image_aspect_ratio]
|
155
165
|
end
|
156
166
|
|
157
167
|
def image_params
|
@@ -172,7 +182,7 @@ module OmniAuth
|
|
172
182
|
return nil if query_parameters.nil?
|
173
183
|
|
174
184
|
params = CGI.parse(query_parameters)
|
175
|
-
stripped_params = params.delete_if { |key| key ==
|
185
|
+
stripped_params = params.delete_if { |key| key == 'sz' }
|
176
186
|
|
177
187
|
# don't return an empty Hash since that would result
|
178
188
|
# in URLs with a trailing ? character: http://image.url?
|
@@ -185,15 +195,17 @@ module OmniAuth
|
|
185
195
|
return false unless access_token
|
186
196
|
raw_response = client.request(:get, 'https://www.googleapis.com/oauth2/v3/tokeninfo',
|
187
197
|
params: { access_token: access_token }).parsed
|
188
|
-
raw_response['aud'] == options.client_id
|
198
|
+
raw_response['aud'] == options.client_id || options.authorized_client_ids.include?(raw_response['aud'])
|
189
199
|
end
|
190
200
|
|
191
201
|
def verify_hd(access_token)
|
192
202
|
return true unless options.hd
|
193
203
|
@raw_info ||= access_token.get('https://www.googleapis.com/plus/v1/people/me/openIdConnect').parsed
|
204
|
+
|
205
|
+
options.hd = options.hd.call if options.hd.is_a? Proc
|
194
206
|
allowed_hosted_domains = Array(options.hd)
|
195
207
|
|
196
|
-
raise CallbackError.new(:invalid_hd,
|
208
|
+
raise CallbackError.new(:invalid_hd, 'Invalid Hosted Domain') unless allowed_hosted_domains.include? @raw_info['hd']
|
197
209
|
true
|
198
210
|
end
|
199
211
|
end
|
@@ -1,26 +1,32 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
|
-
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require File.expand_path(
|
5
|
+
File.join('..', 'lib', 'omniauth', 'google_oauth2', 'version'),
|
6
|
+
__FILE__
|
7
|
+
)
|
3
8
|
|
4
9
|
Gem::Specification.new do |gem|
|
5
|
-
gem.name =
|
10
|
+
gem.name = 'omniauth-google-oauth2'
|
6
11
|
gem.version = OmniAuth::GoogleOauth2::VERSION
|
7
12
|
gem.license = 'MIT'
|
8
|
-
gem.summary = %
|
9
|
-
gem.description = %
|
10
|
-
gem.authors = [
|
11
|
-
gem.email = [
|
12
|
-
gem.homepage =
|
13
|
+
gem.summary = %(A Google OAuth2 strategy for OmniAuth 1.x)
|
14
|
+
gem.description = %(A Google OAuth2 strategy for OmniAuth 1.x. This allows you to login to Google with your ruby app.)
|
15
|
+
gem.authors = ['Josh Ellithorpe', 'Yury Korolev']
|
16
|
+
gem.email = ['quest@mac.com']
|
17
|
+
gem.homepage = 'https://github.com/zquestz/omniauth-google-oauth2'
|
13
18
|
|
14
19
|
gem.files = `git ls-files`.split("\n")
|
15
|
-
gem.require_paths = [
|
20
|
+
gem.require_paths = ['lib']
|
16
21
|
|
17
22
|
gem.required_ruby_version = '>= 2.0'
|
18
23
|
|
19
24
|
gem.add_runtime_dependency 'omniauth', '>= 1.1.1'
|
20
25
|
gem.add_runtime_dependency 'omniauth-oauth2', '>= 1.3.1'
|
21
|
-
gem.add_runtime_dependency 'jwt', '~> 1.5
|
26
|
+
gem.add_runtime_dependency 'jwt', '~> 1.5'
|
22
27
|
gem.add_runtime_dependency 'multi_json', '~> 1.3'
|
23
28
|
|
24
|
-
gem.add_development_dependency 'rspec', '
|
25
|
-
gem.add_development_dependency 'rake'
|
29
|
+
gem.add_development_dependency 'rspec', '~> 3.6'
|
30
|
+
gem.add_development_dependency 'rake', '~> 12.0'
|
31
|
+
gem.add_development_dependency 'rubocop', '~> 0.49'
|
26
32
|
end
|
@@ -1,19 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'spec_helper'
|
2
4
|
require 'omniauth-google-oauth2'
|
3
5
|
|
4
6
|
describe OmniAuth::Strategies::GoogleOauth2 do
|
5
|
-
let(:request) { double('Request', :
|
6
|
-
let(:app)
|
7
|
+
let(:request) { double('Request', params: {}, cookies: {}, env: {}) }
|
8
|
+
let(:app) do
|
7
9
|
lambda do
|
8
|
-
[200, {}, [
|
10
|
+
[200, {}, ['Hello.']]
|
9
11
|
end
|
10
|
-
|
12
|
+
end
|
11
13
|
|
12
14
|
subject do
|
13
15
|
OmniAuth::Strategies::GoogleOauth2.new(app, 'appid', 'secret', @options || {}).tap do |strategy|
|
14
|
-
allow(strategy).to receive(:request)
|
16
|
+
allow(strategy).to receive(:request) do
|
15
17
|
request
|
16
|
-
|
18
|
+
end
|
17
19
|
end
|
18
20
|
end
|
19
21
|
|
@@ -38,40 +40,59 @@ describe OmniAuth::Strategies::GoogleOauth2 do
|
|
38
40
|
expect(subject.client.options[:token_url]).to eq('/o/oauth2/token')
|
39
41
|
end
|
40
42
|
|
41
|
-
describe
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
43
|
+
describe 'overrides' do
|
44
|
+
context 'as strings' do
|
45
|
+
it 'should allow overriding the site' do
|
46
|
+
@options = { client_options: { 'site' => 'https://example.com' } }
|
47
|
+
expect(subject.client.site).to eq('https://example.com')
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'should allow overriding the authorize_url' do
|
51
|
+
@options = { client_options: { 'authorize_url' => 'https://example.com' } }
|
52
|
+
expect(subject.client.options[:authorize_url]).to eq('https://example.com')
|
53
|
+
end
|
46
54
|
|
47
|
-
|
48
|
-
|
49
|
-
|
55
|
+
it 'should allow overriding the token_url' do
|
56
|
+
@options = { client_options: { 'token_url' => 'https://example.com' } }
|
57
|
+
expect(subject.client.options[:token_url]).to eq('https://example.com')
|
58
|
+
end
|
50
59
|
end
|
51
60
|
|
52
|
-
|
53
|
-
|
54
|
-
|
61
|
+
context 'as symbols' do
|
62
|
+
it 'should allow overriding the site' do
|
63
|
+
@options = { client_options: { site: 'https://example.com' } }
|
64
|
+
expect(subject.client.site).to eq('https://example.com')
|
65
|
+
end
|
66
|
+
|
67
|
+
it 'should allow overriding the authorize_url' do
|
68
|
+
@options = { client_options: { authorize_url: 'https://example.com' } }
|
69
|
+
expect(subject.client.options[:authorize_url]).to eq('https://example.com')
|
70
|
+
end
|
71
|
+
|
72
|
+
it 'should allow overriding the token_url' do
|
73
|
+
@options = { client_options: { token_url: 'https://example.com' } }
|
74
|
+
expect(subject.client.options[:token_url]).to eq('https://example.com')
|
75
|
+
end
|
55
76
|
end
|
56
77
|
end
|
57
78
|
end
|
58
79
|
|
59
|
-
describe
|
60
|
-
[
|
80
|
+
describe '#authorize_options' do
|
81
|
+
%i[access_type hd login_hint prompt scope state].each do |k|
|
61
82
|
it "should support #{k}" do
|
62
|
-
@options = {k => 'http://someval'}
|
83
|
+
@options = { k => 'http://someval' }
|
63
84
|
expect(subject.authorize_params[k.to_s]).to eq('http://someval')
|
64
85
|
end
|
65
86
|
end
|
66
87
|
|
67
|
-
describe
|
88
|
+
describe 'redirect_uri' do
|
68
89
|
it 'should default to nil' do
|
69
90
|
@options = {}
|
70
91
|
expect(subject.authorize_params['redirect_uri']).to eq(nil)
|
71
92
|
end
|
72
93
|
|
73
94
|
it 'should set the redirect_uri parameter if present' do
|
74
|
-
@options = {:
|
95
|
+
@options = { redirect_uri: 'https://example.com' }
|
75
96
|
expect(subject.authorize_params['redirect_uri']).to eq('https://example.com')
|
76
97
|
end
|
77
98
|
end
|
@@ -83,51 +104,56 @@ describe OmniAuth::Strategies::GoogleOauth2 do
|
|
83
104
|
end
|
84
105
|
|
85
106
|
it 'should set the access_type parameter if present' do
|
86
|
-
@options = {:
|
107
|
+
@options = { access_type: 'online' }
|
87
108
|
expect(subject.authorize_params['access_type']).to eq('online')
|
88
109
|
end
|
89
110
|
end
|
90
111
|
|
91
112
|
describe 'hd' do
|
92
|
-
it
|
113
|
+
it 'should default to nil' do
|
93
114
|
expect(subject.authorize_params['hd']).to eq(nil)
|
94
115
|
end
|
95
116
|
|
96
117
|
it 'should set the hd (hosted domain) parameter if present' do
|
97
|
-
@options = {:
|
118
|
+
@options = { hd: 'example.com' }
|
98
119
|
expect(subject.authorize_params['hd']).to eq('example.com')
|
99
120
|
end
|
121
|
+
|
122
|
+
it 'should set the hd parameter and work with nil hd (gmail)' do
|
123
|
+
@options = { hd: nil }
|
124
|
+
expect(subject.authorize_params['hd']).to eq(nil)
|
125
|
+
end
|
100
126
|
end
|
101
127
|
|
102
128
|
describe 'login_hint' do
|
103
|
-
it
|
129
|
+
it 'should default to nil' do
|
104
130
|
expect(subject.authorize_params['login_hint']).to eq(nil)
|
105
131
|
end
|
106
132
|
|
107
133
|
it 'should set the login_hint parameter if present' do
|
108
|
-
@options = {:
|
134
|
+
@options = { login_hint: 'john@example.com' }
|
109
135
|
expect(subject.authorize_params['login_hint']).to eq('john@example.com')
|
110
136
|
end
|
111
137
|
end
|
112
138
|
|
113
139
|
describe 'prompt' do
|
114
|
-
it
|
140
|
+
it 'should default to nil' do
|
115
141
|
expect(subject.authorize_params['prompt']).to eq(nil)
|
116
142
|
end
|
117
143
|
|
118
144
|
it 'should set the prompt parameter if present' do
|
119
|
-
@options = {:
|
145
|
+
@options = { prompt: 'consent select_account' }
|
120
146
|
expect(subject.authorize_params['prompt']).to eq('consent select_account')
|
121
147
|
end
|
122
148
|
end
|
123
149
|
|
124
150
|
describe 'request_visible_actions' do
|
125
|
-
it
|
151
|
+
it 'should default to nil' do
|
126
152
|
expect(subject.authorize_params['request_visible_actions']).to eq(nil)
|
127
153
|
end
|
128
154
|
|
129
155
|
it 'should set the request_visible_actions parameter if present' do
|
130
|
-
@options = {:
|
156
|
+
@options = { request_visible_actions: 'something' }
|
131
157
|
expect(subject.authorize_params['request_visible_actions']).to eq('something')
|
132
158
|
end
|
133
159
|
end
|
@@ -138,29 +164,29 @@ describe OmniAuth::Strategies::GoogleOauth2 do
|
|
138
164
|
end
|
139
165
|
|
140
166
|
it 'should set the include_granted_scopes parameter if present' do
|
141
|
-
@options = {:
|
167
|
+
@options = { include_granted_scopes: 'true' }
|
142
168
|
expect(subject.authorize_params['include_granted_scopes']).to eq('true')
|
143
169
|
end
|
144
170
|
end
|
145
171
|
|
146
172
|
describe 'scope' do
|
147
173
|
it 'should expand scope shortcuts' do
|
148
|
-
@options = {:
|
174
|
+
@options = { scope: 'plus.me' }
|
149
175
|
expect(subject.authorize_params['scope']).to eq('https://www.googleapis.com/auth/plus.me')
|
150
176
|
end
|
151
177
|
|
152
178
|
it 'should leave base scopes as is' do
|
153
|
-
@options = {:
|
179
|
+
@options = { scope: 'profile' }
|
154
180
|
expect(subject.authorize_params['scope']).to eq('profile')
|
155
181
|
end
|
156
182
|
|
157
183
|
it 'should join scopes' do
|
158
|
-
@options = {:
|
184
|
+
@options = { scope: 'profile,email' }
|
159
185
|
expect(subject.authorize_params['scope']).to eq('profile email')
|
160
186
|
end
|
161
187
|
|
162
188
|
it 'should deal with whitespace when joining scopes' do
|
163
|
-
@options = {:
|
189
|
+
@options = { scope: 'profile, email' }
|
164
190
|
expect(subject.authorize_params['scope']).to eq('profile email')
|
165
191
|
end
|
166
192
|
|
@@ -169,56 +195,58 @@ describe OmniAuth::Strategies::GoogleOauth2 do
|
|
169
195
|
end
|
170
196
|
|
171
197
|
it 'should support space delimited scopes' do
|
172
|
-
@options = {:
|
198
|
+
@options = { scope: 'profile email' }
|
173
199
|
expect(subject.authorize_params['scope']).to eq('profile email')
|
174
200
|
end
|
175
201
|
|
176
|
-
it
|
177
|
-
@options = {:
|
202
|
+
it 'should support extremely badly formed scopes' do
|
203
|
+
@options = { scope: 'profile email,foo,steve yeah http://example.com' }
|
178
204
|
expect(subject.authorize_params['scope']).to eq('profile email https://www.googleapis.com/auth/foo https://www.googleapis.com/auth/steve https://www.googleapis.com/auth/yeah http://example.com')
|
179
205
|
end
|
180
206
|
end
|
181
207
|
|
182
208
|
describe 'state' do
|
183
209
|
it 'should set the state parameter' do
|
184
|
-
@options = {:
|
210
|
+
@options = { state: 'some_state' }
|
185
211
|
expect(subject.authorize_params['state']).to eq('some_state')
|
212
|
+
expect(subject.authorize_params[:state]).to eq('some_state')
|
186
213
|
expect(subject.session['omniauth.state']).to eq('some_state')
|
187
214
|
end
|
188
215
|
|
189
216
|
it 'should set the omniauth.state dynamically' do
|
190
|
-
allow(subject).to receive(:request) { double('Request',
|
217
|
+
allow(subject).to receive(:request) { double('Request', params: { 'state' => 'some_state' }, env: {}) }
|
191
218
|
expect(subject.authorize_params['state']).to eq('some_state')
|
219
|
+
expect(subject.authorize_params[:state]).to eq('some_state')
|
192
220
|
expect(subject.session['omniauth.state']).to eq('some_state')
|
193
221
|
end
|
194
222
|
end
|
195
223
|
|
196
|
-
describe
|
224
|
+
describe 'overrides' do
|
197
225
|
it 'should include top-level options that are marked as :authorize_options' do
|
198
|
-
@options = {:
|
226
|
+
@options = { authorize_options: %i[scope foo request_visible_actions], scope: 'http://bar', foo: 'baz', hd: 'wow', request_visible_actions: 'something' }
|
199
227
|
expect(subject.authorize_params['scope']).to eq('http://bar')
|
200
228
|
expect(subject.authorize_params['foo']).to eq('baz')
|
201
229
|
expect(subject.authorize_params['hd']).to eq(nil)
|
202
230
|
expect(subject.authorize_params['request_visible_actions']).to eq('something')
|
203
231
|
end
|
204
232
|
|
205
|
-
describe
|
206
|
-
[
|
233
|
+
describe 'request overrides' do
|
234
|
+
%i[access_type hd login_hint prompt scope state].each do |k|
|
207
235
|
context "authorize option #{k}" do
|
208
|
-
let(:request) { double('Request', :
|
236
|
+
let(:request) { double('Request', params: { k.to_s => 'http://example.com' }, cookies: {}, env: {}) }
|
209
237
|
|
210
238
|
it "should set the #{k} authorize option dynamically in the request" do
|
211
|
-
@options = {k
|
239
|
+
@options = { k: '' }
|
212
240
|
expect(subject.authorize_params[k.to_s]).to eq('http://example.com')
|
213
241
|
end
|
214
242
|
end
|
215
243
|
end
|
216
244
|
|
217
|
-
describe
|
218
|
-
let(:request) { double('Request', :
|
245
|
+
describe 'custom authorize_options' do
|
246
|
+
let(:request) { double('Request', params: { 'foo' => 'something' }, cookies: {}, env: {}) }
|
219
247
|
|
220
|
-
it
|
221
|
-
@options = {:
|
248
|
+
it 'should support request overrides from custom authorize_options' do
|
249
|
+
@options = { authorize_options: [:foo], foo: '' }
|
222
250
|
expect(subject.authorize_params['foo']).to eq('something')
|
223
251
|
end
|
224
252
|
end
|
@@ -228,7 +256,7 @@ describe OmniAuth::Strategies::GoogleOauth2 do
|
|
228
256
|
|
229
257
|
describe '#authorize_params' do
|
230
258
|
it 'should include any authorize params passed in the :authorize_params option' do
|
231
|
-
@options = {:
|
259
|
+
@options = { authorize_params: { request_visible_actions: 'something', foo: 'bar', baz: 'zip' }, hd: 'wow', bad: 'not_included' }
|
232
260
|
expect(subject.authorize_params['request_visible_actions']).to eq('something')
|
233
261
|
expect(subject.authorize_params['foo']).to eq('bar')
|
234
262
|
expect(subject.authorize_params['baz']).to eq('zip')
|
@@ -239,15 +267,15 @@ describe OmniAuth::Strategies::GoogleOauth2 do
|
|
239
267
|
|
240
268
|
describe '#token_params' do
|
241
269
|
it 'should include any token params passed in the :token_params option' do
|
242
|
-
@options = {:
|
270
|
+
@options = { token_params: { foo: 'bar', baz: 'zip' } }
|
243
271
|
expect(subject.token_params['foo']).to eq('bar')
|
244
272
|
expect(subject.token_params['baz']).to eq('zip')
|
245
273
|
end
|
246
274
|
end
|
247
275
|
|
248
|
-
describe
|
276
|
+
describe '#token_options' do
|
249
277
|
it 'should include top-level options that are marked as :token_options' do
|
250
|
-
@options = {:
|
278
|
+
@options = { token_options: %i[scope foo], scope: 'bar', foo: 'baz', bad: 'not_included' }
|
251
279
|
expect(subject.token_params['scope']).to eq('bar')
|
252
280
|
expect(subject.token_params['foo']).to eq('baz')
|
253
281
|
expect(subject.token_params['bad']).to eq(nil)
|
@@ -260,10 +288,9 @@ describe OmniAuth::Strategies::GoogleOauth2 do
|
|
260
288
|
end
|
261
289
|
|
262
290
|
it 'should set the callback_path parameter if present' do
|
263
|
-
@options = {:
|
291
|
+
@options = { callback_path: '/auth/foo/callback' }
|
264
292
|
expect(subject.callback_path).to eq('/auth/foo/callback')
|
265
293
|
end
|
266
|
-
|
267
294
|
end
|
268
295
|
|
269
296
|
describe '#extra' do
|
@@ -271,9 +298,9 @@ describe OmniAuth::Strategies::GoogleOauth2 do
|
|
271
298
|
OAuth2::Client.new('abc', 'def') do |builder|
|
272
299
|
builder.request :url_encoded
|
273
300
|
builder.adapter :test do |stub|
|
274
|
-
stub.get('/plus/v1/people/me/openIdConnect') {
|
275
|
-
stub.get('/plus/v1/people/12345/people/visible') {
|
276
|
-
stub.get('/plus/v1/people/12345?fields=image') {
|
301
|
+
stub.get('/plus/v1/people/me/openIdConnect') { [200, { 'content-type' => 'application/json' }, '{"sub": "12345"}'] }
|
302
|
+
stub.get('/plus/v1/people/12345/people/visible') { [200, { 'content-type' => 'application/json' }, '[{"foo":"bar"}]'] }
|
303
|
+
stub.get('/plus/v1/people/12345?fields=image') { [200, { 'content-type' => 'application/json' }, '{"image":"imageData"}'] }
|
277
304
|
end
|
278
305
|
end
|
279
306
|
end
|
@@ -290,18 +317,18 @@ describe OmniAuth::Strategies::GoogleOauth2 do
|
|
290
317
|
'nbf' => Time.now.to_i - 60,
|
291
318
|
'iat' => Time.now.to_i,
|
292
319
|
'aud' => 'appid',
|
293
|
-
'iss' => 'accounts.google.com'
|
320
|
+
'iss' => 'accounts.google.com'
|
294
321
|
}
|
295
322
|
id_token = JWT.encode(token_info, 'secret')
|
296
|
-
let(:access_token) { OAuth2::AccessToken.from_hash(client,
|
323
|
+
let(:access_token) { OAuth2::AccessToken.from_hash(client, 'id_token' => id_token) }
|
297
324
|
|
298
325
|
it 'should include id_token when set on the access_token' do
|
299
|
-
expect(subject.extra).to include(:
|
326
|
+
expect(subject.extra).to include(id_token: id_token)
|
300
327
|
end
|
301
328
|
|
302
329
|
it 'should include id_info when id_token is set on the access_token and skip_jwt is false' do
|
303
330
|
subject.options[:skip_jwt] = false
|
304
|
-
expect(subject.extra).to include(:
|
331
|
+
expect(subject.extra).to include(id_info: token_info)
|
305
332
|
end
|
306
333
|
|
307
334
|
it 'should not include id_info when id_token is set on the access_token and skip_jwt is true' do
|
@@ -310,7 +337,7 @@ describe OmniAuth::Strategies::GoogleOauth2 do
|
|
310
337
|
end
|
311
338
|
|
312
339
|
it 'should include id_info when id_token is set on the access_token by default' do
|
313
|
-
expect(subject.extra).to include(:
|
340
|
+
expect(subject.extra).to include(id_info: token_info)
|
314
341
|
end
|
315
342
|
end
|
316
343
|
|
@@ -367,7 +394,7 @@ describe OmniAuth::Strategies::GoogleOauth2 do
|
|
367
394
|
before { subject.options[:skip_friends] = false }
|
368
395
|
|
369
396
|
it 'should not include raw_friend_info' do
|
370
|
-
expect(subject.extra[:raw_friend_info]).to eq([{'foo' => 'bar'}])
|
397
|
+
expect(subject.extra[:raw_friend_info]).to eq([{ 'foo' => 'bar' }])
|
371
398
|
end
|
372
399
|
end
|
373
400
|
end
|
@@ -397,7 +424,7 @@ describe OmniAuth::Strategies::GoogleOauth2 do
|
|
397
424
|
before { subject.options[:skip_image_info] = false }
|
398
425
|
|
399
426
|
it 'should include raw_image_info' do
|
400
|
-
expect(subject.extra[:raw_image_info]).to eq(
|
427
|
+
expect(subject.extra[:raw_image_info]).to eq('image' => 'imageData')
|
401
428
|
end
|
402
429
|
end
|
403
430
|
end
|
@@ -406,92 +433,92 @@ describe OmniAuth::Strategies::GoogleOauth2 do
|
|
406
433
|
|
407
434
|
describe 'populate auth hash urls' do
|
408
435
|
it 'should populate url map in auth hash if link present in raw_info' do
|
409
|
-
allow(subject).to receive(:raw_info) { {'name' => 'Foo', 'profile' => 'https://plus.google.com/123456'} }
|
410
|
-
expect(subject.info[:urls][
|
436
|
+
allow(subject).to receive(:raw_info) { { 'name' => 'Foo', 'profile' => 'https://plus.google.com/123456' } }
|
437
|
+
expect(subject.info[:urls][:google]).to eq('https://plus.google.com/123456')
|
411
438
|
end
|
412
439
|
|
413
440
|
it 'should not populate url map in auth hash if no link present in raw_info' do
|
414
|
-
allow(subject).to receive(:raw_info) { {'name' => 'Foo'} }
|
441
|
+
allow(subject).to receive(:raw_info) { { 'name' => 'Foo' } }
|
415
442
|
expect(subject.info).not_to have_key(:urls)
|
416
443
|
end
|
417
444
|
end
|
418
445
|
|
419
446
|
describe 'image options' do
|
420
|
-
it
|
421
|
-
@options = {:
|
422
|
-
allow(subject).to receive(:raw_info) { {'name' => 'User Without Pic'} }
|
447
|
+
it 'should have no image if a picture is not present' do
|
448
|
+
@options = { image_aspect_ratio: 'square' }
|
449
|
+
allow(subject).to receive(:raw_info) { { 'name' => 'User Without Pic' } }
|
423
450
|
expect(subject.info[:image]).to be_nil
|
424
451
|
end
|
425
452
|
|
426
|
-
describe
|
453
|
+
describe 'when a picture is returned from google' do
|
427
454
|
it 'should return the image with size specified in the `image_size` option' do
|
428
|
-
@options = {:
|
429
|
-
allow(subject).to receive(:raw_info) { {'picture' => 'https://lh3.googleusercontent.com/url/photo.jpg'} }
|
455
|
+
@options = { image_size: 50 }
|
456
|
+
allow(subject).to receive(:raw_info) { { 'picture' => 'https://lh3.googleusercontent.com/url/photo.jpg' } }
|
430
457
|
expect(subject.info[:image]).to eq('https://lh3.googleusercontent.com/url/s50/photo.jpg')
|
431
458
|
end
|
432
459
|
|
433
460
|
it 'should handle a picture with too many slashes correctly' do
|
434
|
-
@options = {:
|
435
|
-
allow(subject).to receive(:raw_info) { {'picture' => 'https://lh3.googleusercontent.com/url//photo.jpg'} }
|
461
|
+
@options = { image_size: 50 }
|
462
|
+
allow(subject).to receive(:raw_info) { { 'picture' => 'https://lh3.googleusercontent.com/url//photo.jpg' } }
|
436
463
|
expect(subject.info[:image]).to eq('https://lh3.googleusercontent.com/url/s50/photo.jpg')
|
437
464
|
end
|
438
465
|
|
439
466
|
it 'should handle a picture with a size query parameter correctly' do
|
440
|
-
@options = {:
|
441
|
-
allow(subject).to receive(:raw_info) { {'picture' => 'https://lh3.googleusercontent.com/url/photo.jpg?sz=50'} }
|
467
|
+
@options = { image_size: 50 }
|
468
|
+
allow(subject).to receive(:raw_info) { { 'picture' => 'https://lh3.googleusercontent.com/url/photo.jpg?sz=50' } }
|
442
469
|
expect(subject.info[:image]).to eq('https://lh3.googleusercontent.com/url/s50/photo.jpg')
|
443
470
|
end
|
444
471
|
|
445
472
|
it 'should handle a picture with a size query parameter and other valid query parameters correctly' do
|
446
|
-
@options = {:
|
447
|
-
allow(subject).to receive(:raw_info) { {'picture' => 'https://lh3.googleusercontent.com/url/photo.jpg?sz=50&hello=true&life=42'} }
|
473
|
+
@options = { image_size: 50 }
|
474
|
+
allow(subject).to receive(:raw_info) { { 'picture' => 'https://lh3.googleusercontent.com/url/photo.jpg?sz=50&hello=true&life=42' } }
|
448
475
|
expect(subject.info[:image]).to eq('https://lh3.googleusercontent.com/url/s50/photo.jpg?hello=true&life=42')
|
449
476
|
end
|
450
477
|
|
451
478
|
it 'should handle a picture with other valid query parameters correctly' do
|
452
|
-
@options = {:
|
453
|
-
allow(subject).to receive(:raw_info) { {'picture' => 'https://lh3.googleusercontent.com/url/photo.jpg?hello=true&life=42'} }
|
479
|
+
@options = { image_size: 50 }
|
480
|
+
allow(subject).to receive(:raw_info) { { 'picture' => 'https://lh3.googleusercontent.com/url/photo.jpg?hello=true&life=42' } }
|
454
481
|
expect(subject.info[:image]).to eq('https://lh3.googleusercontent.com/url/s50/photo.jpg?hello=true&life=42')
|
455
482
|
end
|
456
483
|
|
457
484
|
it 'should return the image with width and height specified in the `image_size` option' do
|
458
|
-
@options = {:
|
459
|
-
allow(subject).to receive(:raw_info) { {'picture' => 'https://lh3.googleusercontent.com/url/photo.jpg'} }
|
485
|
+
@options = { image_size: { width: 50, height: 40 } }
|
486
|
+
allow(subject).to receive(:raw_info) { { 'picture' => 'https://lh3.googleusercontent.com/url/photo.jpg' } }
|
460
487
|
expect(subject.info[:image]).to eq('https://lh3.googleusercontent.com/url/w50-h40/photo.jpg')
|
461
488
|
end
|
462
489
|
|
463
490
|
it 'should return square image when `image_aspect_ratio` is specified' do
|
464
|
-
@options = {:
|
465
|
-
allow(subject).to receive(:raw_info) { {'picture' => 'https://lh3.googleusercontent.com/url/photo.jpg'} }
|
491
|
+
@options = { image_aspect_ratio: 'square' }
|
492
|
+
allow(subject).to receive(:raw_info) { { 'picture' => 'https://lh3.googleusercontent.com/url/photo.jpg' } }
|
466
493
|
expect(subject.info[:image]).to eq('https://lh3.googleusercontent.com/url/c/photo.jpg')
|
467
494
|
end
|
468
495
|
|
469
496
|
it 'should return square sized image when `image_aspect_ratio` and `image_size` is set' do
|
470
|
-
@options = {:
|
471
|
-
allow(subject).to receive(:raw_info) { {'picture' => 'https://lh3.googleusercontent.com/url/photo.jpg'} }
|
497
|
+
@options = { image_aspect_ratio: 'square', image_size: 50 }
|
498
|
+
allow(subject).to receive(:raw_info) { { 'picture' => 'https://lh3.googleusercontent.com/url/photo.jpg' } }
|
472
499
|
expect(subject.info[:image]).to eq('https://lh3.googleusercontent.com/url/s50-c/photo.jpg')
|
473
500
|
end
|
474
501
|
|
475
502
|
it 'should return square sized image when `image_aspect_ratio` and `image_size` has height and width' do
|
476
|
-
@options = {:
|
477
|
-
allow(subject).to receive(:raw_info) { {'picture' => 'https://lh3.googleusercontent.com/url/photo.jpg'} }
|
503
|
+
@options = { image_aspect_ratio: 'square', image_size: { width: 50, height: 40 } }
|
504
|
+
allow(subject).to receive(:raw_info) { { 'picture' => 'https://lh3.googleusercontent.com/url/photo.jpg' } }
|
478
505
|
expect(subject.info[:image]).to eq('https://lh3.googleusercontent.com/url/w50-h40-c/photo.jpg')
|
479
506
|
end
|
480
507
|
|
481
508
|
it 'should return original image if image url does not end in `photo.jpg`' do
|
482
|
-
@options = {:
|
483
|
-
allow(subject).to receive(:raw_info) { {'picture' => 'https://lh3.googleusercontent.com/url/photograph.jpg'} }
|
509
|
+
@options = { image_size: 50 }
|
510
|
+
allow(subject).to receive(:raw_info) { { 'picture' => 'https://lh3.googleusercontent.com/url/photograph.jpg' } }
|
484
511
|
expect(subject.info[:image]).to eq('https://lh3.googleusercontent.com/url/photograph.jpg')
|
485
512
|
end
|
486
513
|
end
|
487
514
|
|
488
515
|
it 'should return original image if no options are provided' do
|
489
|
-
allow(subject).to receive(:raw_info) { {'picture' => 'https://lh3.googleusercontent.com/url/photo.jpg'} }
|
516
|
+
allow(subject).to receive(:raw_info) { { 'picture' => 'https://lh3.googleusercontent.com/url/photo.jpg' } }
|
490
517
|
expect(subject.info[:image]).to eq('https://lh3.googleusercontent.com/url/photo.jpg')
|
491
518
|
end
|
492
519
|
|
493
520
|
it 'should return correct image if google image url has double https' do
|
494
|
-
allow(subject).to receive(:raw_info) { {'picture' => 'https:https://lh3.googleusercontent.com/url/photo.jpg'} }
|
521
|
+
allow(subject).to receive(:raw_info) { { 'picture' => 'https:https://lh3.googleusercontent.com/url/photo.jpg' } }
|
495
522
|
expect(subject.info[:image]).to eq('https://lh3.googleusercontent.com/url/photo.jpg')
|
496
523
|
end
|
497
524
|
end
|
@@ -505,7 +532,21 @@ describe OmniAuth::Strategies::GoogleOauth2 do
|
|
505
532
|
auth_code = double(:auth_code)
|
506
533
|
allow(client).to receive(:auth_code).and_return(auth_code)
|
507
534
|
expect(subject).to receive(:client).and_return(client)
|
508
|
-
expect(auth_code).to receive(:get_token).with('valid_code', { :
|
535
|
+
expect(auth_code).to receive(:get_token).with('valid_code', { redirect_uri: 'postmessage' }, {})
|
536
|
+
|
537
|
+
expect(subject).not_to receive(:orig_build_access_token)
|
538
|
+
subject.build_access_token
|
539
|
+
end
|
540
|
+
|
541
|
+
it 'should use a hybrid authorization request_uri if this is an AJAX request (mobile) with a code parameter' do
|
542
|
+
allow(request).to receive(:xhr?).and_return(true)
|
543
|
+
allow(request).to receive(:params).and_return('code' => 'valid_code', 'redirect_uri' => '')
|
544
|
+
|
545
|
+
client = double(:client)
|
546
|
+
auth_code = double(:auth_code)
|
547
|
+
allow(client).to receive(:auth_code).and_return(auth_code)
|
548
|
+
expect(subject).to receive(:client).and_return(client)
|
549
|
+
expect(auth_code).to receive(:get_token).with('valid_code', { redirect_uri: '' }, {})
|
509
550
|
|
510
551
|
expect(subject).not_to receive(:orig_build_access_token)
|
511
552
|
subject.build_access_token
|
@@ -519,7 +560,7 @@ describe OmniAuth::Strategies::GoogleOauth2 do
|
|
519
560
|
auth_code = double(:auth_code)
|
520
561
|
allow(client).to receive(:auth_code).and_return(auth_code)
|
521
562
|
expect(subject).to receive(:client).and_return(client)
|
522
|
-
expect(auth_code).to receive(:get_token).with('valid_code', { :
|
563
|
+
expect(auth_code).to receive(:get_token).with('valid_code', { redirect_uri: 'redirect_uri' }, {})
|
523
564
|
|
524
565
|
expect(subject).not_to receive(:orig_build_access_token)
|
525
566
|
subject.build_access_token
|
@@ -547,7 +588,7 @@ describe OmniAuth::Strategies::GoogleOauth2 do
|
|
547
588
|
allow(subject).to receive(:callback_url).and_return('redirect_uri_without_query_string')
|
548
589
|
|
549
590
|
expect(subject).to receive(:client).and_return(client)
|
550
|
-
expect(auth_code).to receive(:get_token).with('valid_code', { :
|
591
|
+
expect(auth_code).to receive(:get_token).with('valid_code', { redirect_uri: 'redirect_uri_without_query_string' }, {})
|
551
592
|
subject.build_access_token
|
552
593
|
end
|
553
594
|
end
|
@@ -557,19 +598,19 @@ describe OmniAuth::Strategies::GoogleOauth2 do
|
|
557
598
|
subject.options.client_options[:connection_build] = proc do |builder|
|
558
599
|
builder.request :url_encoded
|
559
600
|
builder.adapter :test do |stub|
|
560
|
-
stub.get('/oauth2/v3/tokeninfo?access_token=valid_access_token') do
|
561
|
-
[200, {'Content-Type' => 'application/json; charset=UTF-8'}, MultiJson.encode(
|
562
|
-
:
|
563
|
-
:
|
564
|
-
:
|
565
|
-
:
|
566
|
-
:
|
567
|
-
:
|
568
|
-
:
|
601
|
+
stub.get('/oauth2/v3/tokeninfo?access_token=valid_access_token') do
|
602
|
+
[200, { 'Content-Type' => 'application/json; charset=UTF-8' }, MultiJson.encode(
|
603
|
+
aud: '000000000000.apps.googleusercontent.com',
|
604
|
+
sub: '123456789',
|
605
|
+
email_verified: 'true',
|
606
|
+
email: 'example@example.com',
|
607
|
+
access_type: 'offline',
|
608
|
+
scope: 'profile email',
|
609
|
+
expires_in: 436
|
569
610
|
)]
|
570
611
|
end
|
571
|
-
stub.get('/oauth2/v3/tokeninfo?access_token=invalid_access_token') do
|
572
|
-
[400, {'Content-Type' => 'application/json; charset=UTF-8'}, MultiJson.encode(:
|
612
|
+
stub.get('/oauth2/v3/tokeninfo?access_token=invalid_access_token') do
|
613
|
+
[400, { 'Content-Type' => 'application/json; charset=UTF-8' }, MultiJson.encode(error_description: 'Invalid Value')]
|
573
614
|
end
|
574
615
|
end
|
575
616
|
end
|
@@ -580,14 +621,19 @@ describe OmniAuth::Strategies::GoogleOauth2 do
|
|
580
621
|
expect(subject.send(:verify_token, 'valid_access_token')).to eq(true)
|
581
622
|
end
|
582
623
|
|
624
|
+
it 'should verify token if access_token is valid and app_id authorized' do
|
625
|
+
subject.options.authorized_client_ids = ['000000000000.apps.googleusercontent.com']
|
626
|
+
expect(subject.send(:verify_token, 'valid_access_token')).to eq(true)
|
627
|
+
end
|
628
|
+
|
583
629
|
it 'should not verify token if access_token is valid but app_id is false' do
|
584
630
|
expect(subject.send(:verify_token, 'valid_access_token')).to eq(false)
|
585
631
|
end
|
586
632
|
|
587
633
|
it 'should raise error if access_token is invalid' do
|
588
|
-
expect
|
634
|
+
expect do
|
589
635
|
subject.send(:verify_token, 'invalid_access_token')
|
590
|
-
|
636
|
+
end.to raise_error(OAuth2::Error)
|
591
637
|
end
|
592
638
|
end
|
593
639
|
|
@@ -596,9 +642,9 @@ describe OmniAuth::Strategies::GoogleOauth2 do
|
|
596
642
|
OAuth2::Client.new('abc', 'def') do |builder|
|
597
643
|
builder.request :url_encoded
|
598
644
|
builder.adapter :test do |stub|
|
599
|
-
stub.get('/plus/v1/people/me/openIdConnect') do
|
600
|
-
[200, {'Content-Type' => 'application/json; charset=UTF-8'}, MultiJson.encode(
|
601
|
-
:
|
645
|
+
stub.get('/plus/v1/people/me/openIdConnect') do
|
646
|
+
[200, { 'Content-Type' => 'application/json; charset=UTF-8' }, MultiJson.encode(
|
647
|
+
hd: 'example.com'
|
602
648
|
)]
|
603
649
|
end
|
604
650
|
end
|
@@ -606,6 +652,36 @@ describe OmniAuth::Strategies::GoogleOauth2 do
|
|
606
652
|
end
|
607
653
|
let(:access_token) { OAuth2::AccessToken.from_hash(client, {}) }
|
608
654
|
|
655
|
+
context 'when domain is nil' do
|
656
|
+
let(:client) do
|
657
|
+
OAuth2::Client.new('abc', 'def') do |builder|
|
658
|
+
builder.request :url_encoded
|
659
|
+
builder.adapter :test do |stub|
|
660
|
+
stub.get('/plus/v1/people/me/openIdConnect') do
|
661
|
+
[200, { 'Content-Type' => 'application/json; charset=UTF-8' }, MultiJson.encode({})]
|
662
|
+
end
|
663
|
+
end
|
664
|
+
end
|
665
|
+
end
|
666
|
+
|
667
|
+
it 'should verify hd if options hd is set and correct' do
|
668
|
+
subject.options.hd = nil
|
669
|
+
expect(subject.send(:verify_hd, access_token)).to eq(true)
|
670
|
+
end
|
671
|
+
|
672
|
+
it 'should verify hd if options hd is set as an array and is correct' do
|
673
|
+
subject.options.hd = ['example.com', 'example.co', nil]
|
674
|
+
expect(subject.send(:verify_hd, access_token)).to eq(true)
|
675
|
+
end
|
676
|
+
|
677
|
+
it 'should raise an exception if nil is not included' do
|
678
|
+
subject.options.hd = ['example.com', 'example.co']
|
679
|
+
expect do
|
680
|
+
subject.send(:verify_hd, access_token)
|
681
|
+
end.to raise_error(OmniAuth::Strategies::OAuth2::CallbackError)
|
682
|
+
end
|
683
|
+
end
|
684
|
+
|
609
685
|
it 'should verify hd if options hd is not set' do
|
610
686
|
expect(subject.send(:verify_hd, access_token)).to eq(true)
|
611
687
|
end
|
@@ -616,22 +692,32 @@ describe OmniAuth::Strategies::GoogleOauth2 do
|
|
616
692
|
end
|
617
693
|
|
618
694
|
it 'should verify hd if options hd is set as an array and is correct' do
|
619
|
-
subject.options.hd = ['example.com', 'example.co']
|
695
|
+
subject.options.hd = ['example.com', 'example.co', nil]
|
696
|
+
expect(subject.send(:verify_hd, access_token)).to eq(true)
|
697
|
+
end
|
698
|
+
|
699
|
+
it 'should verify hd if options hd is set as an Proc and is correct' do
|
700
|
+
subject.options.hd = proc { 'example.com' }
|
701
|
+
expect(subject.send(:verify_hd, access_token)).to eq(true)
|
702
|
+
end
|
703
|
+
|
704
|
+
it 'should verify hd if options hd is set as an Proc returning an array and is correct' do
|
705
|
+
subject.options.hd = proc { ['example.com', 'example.co'] }
|
620
706
|
expect(subject.send(:verify_hd, access_token)).to eq(true)
|
621
707
|
end
|
622
708
|
|
623
709
|
it 'should raise error if options hd is set and wrong' do
|
624
710
|
subject.options.hd = 'invalid.com'
|
625
|
-
expect
|
711
|
+
expect do
|
626
712
|
subject.send(:verify_hd, access_token)
|
627
|
-
|
713
|
+
end.to raise_error(OmniAuth::Strategies::GoogleOauth2::CallbackError)
|
628
714
|
end
|
629
715
|
|
630
716
|
it 'should raise error if options hd is set as an array and is not correct' do
|
631
717
|
subject.options.hd = ['invalid.com', 'invalid.co']
|
632
|
-
expect
|
718
|
+
expect do
|
633
719
|
subject.send(:verify_hd, access_token)
|
634
|
-
|
720
|
+
end.to raise_error(OmniAuth::Strategies::GoogleOauth2::CallbackError)
|
635
721
|
end
|
636
722
|
end
|
637
723
|
end
|