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.
- 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
|