omniauth-google-oauth2 0.4.1 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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 +1,3 @@
1
- require File.join('omniauth', 'google_oauth2')
1
+ # frozen_string_literal: true
2
+
3
+ require 'omniauth/google_oauth2'
@@ -1 +1,3 @@
1
- require File.join('omniauth', 'strategies', 'google_oauth2')
1
+ # frozen_string_literal: true
2
+
3
+ require 'omniauth/strategies/google_oauth2'
@@ -1,5 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module OmniAuth
2
4
  module GoogleOauth2
3
- VERSION = "0.4.1"
5
+ VERSION = '0.5.0'
4
6
  end
5
7
  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 = "https://www.googleapis.com/auth/"
10
- BASE_SCOPES = %w[profile email openid]
11
- DEFAULT_SCOPE = "email,profile"
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, [:access_type, :hd, :login_hint, :prompt, :request_visible_actions, :scope, :state, :redirect_uri, :include_granted_scopes, :openid_realm]
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
- :site => 'https://accounts.google.com',
22
- :authorize_url => '/o/oauth2/auth',
23
- :token_url => '/o/oauth2/token'
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
- raw_scope = params[:scope] || DEFAULT_SCOPE
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['state']
39
+ session['omniauth.state'] = params[:state] if params[:state]
40
40
  end
41
41
  end
42
42
 
43
- uid { raw_info['sub'] || verified_email }
43
+ uid { raw_info['sub'] }
44
44
 
45
45
  info do
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']
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
- :verify_iss => true,
65
- 'iss' => 'accounts.google.com',
66
- :verify_aud => true,
67
- 'aud' => options.client_id,
68
- :verify_sub => false,
69
- :verify_expiration => true,
70
- :verify_not_before => true,
71
- :verify_iat => true,
72
- :verify_jti => false,
73
- :leeway => options[:jwt_leeway]
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
- client.auth_code.get_token(verifier, get_token_options('postmessage'), deep_symbolize(options.auth_token_params || {}))
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["code"]
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
- private
116
-
117
- def callback_url
118
- options[:redirect_uri] || (full_host + script_name + callback_path)
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
- { :redirect_uri => redirect_uri }.merge(token_params.to_hash(:symbolize_keys => true))
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
- !!(options[:image_size] || options[:image_aspect_ratio])
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 == "sz" }
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, "Invalid Hosted Domain") unless allowed_hosted_domains.include? @raw_info['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
- require File.expand_path(File.join('..', 'lib', 'omniauth', 'google_oauth2', 'version'), __FILE__)
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 = "omniauth-google-oauth2"
10
+ gem.name = 'omniauth-google-oauth2'
6
11
  gem.version = OmniAuth::GoogleOauth2::VERSION
7
12
  gem.license = 'MIT'
8
- gem.summary = %q{A Google OAuth2 strategy for OmniAuth 1.x}
9
- gem.description = %q{A Google OAuth2 strategy for OmniAuth 1.x}
10
- gem.authors = ["Josh Ellithorpe", "Yury Korolev"]
11
- gem.email = ["quest@mac.com"]
12
- gem.homepage = "https://github.com/zquestz/omniauth-google-oauth2"
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 = ["lib"]
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.2'
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', '>= 2.14.0'
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', :params => {}, :cookies => {}, :env => {}) }
6
- let(:app) {
7
+ let(:request) { double('Request', params: {}, cookies: {}, env: {}) }
8
+ let(:app) do
7
9
  lambda do
8
- [200, {}, ["Hello."]]
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 "overrides" do
42
- it 'should allow overriding the site' do
43
- @options = {:client_options => {'site' => 'https://example.com'}}
44
- expect(subject.client.site).to eq('https://example.com')
45
- end
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
- it 'should allow overriding the authorize_url' do
48
- @options = {:client_options => {'authorize_url' => 'https://example.com'}}
49
- expect(subject.client.options[:authorize_url]).to eq('https://example.com')
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
- it 'should allow overriding the token_url' do
53
- @options = {:client_options => {'token_url' => 'https://example.com'}}
54
- expect(subject.client.options[:token_url]).to eq('https://example.com')
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 "#authorize_options" do
60
- [:access_type, :hd, :login_hint, :prompt, :scope, :state].each do |k|
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 "redirect_uri" do
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 = {:redirect_uri => 'https://example.com'}
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 = {:access_type => 'online'}
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 "should default to nil" do
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 = {:hd => 'example.com'}
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 "should default to nil" do
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 = {:login_hint => 'john@example.com'}
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 "should default to nil" do
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 = {:prompt => 'consent select_account'}
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 "should default to nil" do
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 = {:request_visible_actions => 'something'}
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 = {:include_granted_scopes => 'true'}
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 = {:scope => 'plus.me'}
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 = {:scope => 'profile'}
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 = {:scope => 'profile,email'}
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 = {:scope => 'profile, email'}
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 = {:scope => 'profile email'}
198
+ @options = { scope: 'profile email' }
173
199
  expect(subject.authorize_params['scope']).to eq('profile email')
174
200
  end
175
201
 
176
- it "should support extremely badly formed scopes" do
177
- @options = {:scope => 'profile email,foo,steve yeah http://example.com'}
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 = {:state => 'some_state'}
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', {:params => {'state' => 'some_state'}, :env => {}}) }
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 "overrides" do
224
+ describe 'overrides' do
197
225
  it 'should include top-level options that are marked as :authorize_options' do
198
- @options = {:authorize_options => [:scope, :foo, :request_visible_actions], :scope => 'http://bar', :foo => 'baz', :hd => "wow", :request_visible_actions => "something"}
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 "request overrides" do
206
- [:access_type, :hd, :login_hint, :prompt, :scope, :state].each do |k|
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', :params => {k.to_s => 'http://example.com'}, :cookies => {}, :env => {}) }
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 "custom authorize_options" do
218
- let(:request) { double('Request', :params => {'foo' => 'something'}, :cookies => {}, :env => {}) }
245
+ describe 'custom authorize_options' do
246
+ let(:request) { double('Request', params: { 'foo' => 'something' }, cookies: {}, env: {}) }
219
247
 
220
- it "should support request overrides from custom authorize_options" do
221
- @options = {:authorize_options => [:foo], :foo => ''}
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 = {:authorize_params => {:request_visible_actions => 'something', :foo => 'bar', :baz => 'zip'}, :hd => 'wow', :bad => 'not_included'}
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 = {:token_params => {:foo => 'bar', :baz => 'zip'}}
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 "#token_options" do
276
+ describe '#token_options' do
249
277
  it 'should include top-level options that are marked as :token_options' do
250
- @options = {:token_options => [:scope, :foo], :scope => 'bar', :foo => 'baz', :bad => 'not_included'}
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 = {:callback_path => '/auth/foo/callback'}
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') {|env| [200, {'content-type' => 'application/json'}, '{"sub": "12345"}']}
275
- stub.get('/plus/v1/people/12345/people/visible') {|env| [200, {'content-type' => 'application/json'}, '[{"foo":"bar"}]']}
276
- stub.get('/plus/v1/people/12345?fields=image') {|env| [200, {'content-type' => 'application/json'}, '{"image":"imageData"}']}
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, {'id_token' => id_token}) }
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(:id_token => id_token)
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(:id_info => token_info)
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(:id_info => token_info)
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({'image' => 'imageData'})
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]['Google']).to eq('https://plus.google.com/123456')
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 "should have no image if a picture isn't present" do
421
- @options = {:image_aspect_ratio => 'square'}
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 "when a picture is returned from google" do
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 = {:image_size => 50}
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 = {:image_size => 50}
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 = {:image_size => 50}
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 = {:image_size => 50}
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 = {:image_size => 50}
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 = {:image_size => {:width => 50, :height => 40}}
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 = {:image_aspect_ratio => 'square'}
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 = {:image_aspect_ratio => 'square', :image_size => 50}
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 = {:image_aspect_ratio => 'square', :image_size => {:width => 50, :height => 40}}
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 = {:image_size => 50}
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', { :redirect_uri => 'postmessage'}, {})
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', { :redirect_uri => 'redirect_uri'}, {})
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', { :redirect_uri => 'redirect_uri_without_query_string'}, {})
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 |env|
561
- [200, {'Content-Type' => 'application/json; charset=UTF-8'}, MultiJson.encode(
562
- :aud => "000000000000.apps.googleusercontent.com",
563
- :sub => "123456789",
564
- :email_verified => "true",
565
- :email => "example@example.com",
566
- :access_type => "offline",
567
- :scope => "profile email",
568
- :expires_in => 436
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 |env|
572
- [400, {'Content-Type' => 'application/json; charset=UTF-8'}, MultiJson.encode(:error_description => 'Invalid Value')]
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
- }.to raise_error(OAuth2::Error)
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 |env|
600
- [200, {'Content-Type' => 'application/json; charset=UTF-8'}, MultiJson.encode(
601
- :hd => 'example.com',
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
- }.to raise_error(OmniAuth::Strategies::GoogleOauth2::CallbackError)
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
- }.to raise_error(OmniAuth::Strategies::GoogleOauth2::CallbackError)
720
+ end.to raise_error(OmniAuth::Strategies::GoogleOauth2::CallbackError)
635
721
  end
636
722
  end
637
723
  end