googleauth 0.4.2 → 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.
@@ -57,7 +57,7 @@ describe Google::Auth::UserRefreshCredentials do
57
57
 
58
58
  before(:example) do
59
59
  @key = OpenSSL::PKey::RSA.new(2048)
60
- @client = UserRefreshCredentials.new(
60
+ @client = UserRefreshCredentials.make_creds(
61
61
  json_key_io: StringIO.new(cred_json_text),
62
62
  scope: 'https://www.googleapis.com/auth/userinfo.profile'
63
63
  )
@@ -65,14 +65,14 @@ describe Google::Auth::UserRefreshCredentials do
65
65
 
66
66
  def make_auth_stubs(opts = {})
67
67
  access_token = opts[:access_token] || ''
68
- Faraday::Adapter::Test::Stubs.new do |stub|
69
- stub.post('/oauth2/v3/token') do |env|
70
- params = Addressable::URI.form_unencode(env[:body])
71
- want = %w(grant_type refresh_token)
72
- expect(params.assoc('grant_type')).to eq(want)
73
- build_access_token_json(access_token)
74
- end
75
- end
68
+ body = MultiJson.dump('access_token' => access_token,
69
+ 'token_type' => 'Bearer',
70
+ 'expires_in' => 3600)
71
+ stub_request(:post, 'https://www.googleapis.com/oauth2/v3/token')
72
+ .with(body: hash_including('grant_type' => 'refresh_token'))
73
+ .to_return(body: body,
74
+ status: 200,
75
+ headers: { 'Content-Type' => 'application/json' })
76
76
  end
77
77
 
78
78
  def cred_json_text(missing = nil)
@@ -142,10 +142,11 @@ describe Google::Auth::UserRefreshCredentials do
142
142
  ENV[CLIENT_SECRET_VAR] = cred_json[:client_secret]
143
143
  ENV[REFRESH_TOKEN_VAR] = cred_json[:refresh_token]
144
144
  ENV[ACCOUNT_TYPE_VAR] = cred_json[:type]
145
- expect(@clz.from_env(@scope)).to_not be_nil
146
- expect(subject.client_id).to eq(cred_json[:client_id])
147
- expect(subject.client_secret).to eq(cred_json[:client_secret])
148
- expect(subject.refresh_token).to eq(cred_json[:refresh_token])
145
+ creds = @clz.from_env(@scope)
146
+ expect(creds).to_not be_nil
147
+ expect(creds.client_id).to eq(cred_json[:client_id])
148
+ expect(creds.client_secret).to eq(cred_json[:client_secret])
149
+ expect(creds.refresh_token).to eq(cred_json[:refresh_token])
149
150
  end
150
151
  end
151
152
 
@@ -227,4 +228,67 @@ describe Google::Auth::UserRefreshCredentials do
227
228
  end
228
229
  end
229
230
  end
231
+
232
+ shared_examples 'revoked token' do
233
+ it 'should nil the refresh token' do
234
+ expect(@client.refresh_token).to be_nil
235
+ end
236
+
237
+ it 'should nil the access token' do
238
+ expect(@client.access_token).to be_nil
239
+ end
240
+
241
+ it 'should mark the token as expired' do
242
+ expect(@client.expired?).to be_truthy
243
+ end
244
+ end
245
+
246
+ describe 'when revoking a refresh token' do
247
+ let(:stub) do
248
+ stub_request(:get, 'https://accounts.google.com/o/oauth2/revoke' \
249
+ '?token=refreshtoken')
250
+ .to_return(status: 200,
251
+ headers: { 'Content-Type' => 'application/json' })
252
+ end
253
+
254
+ before(:example) do
255
+ stub
256
+ @client.revoke!
257
+ end
258
+
259
+ it_behaves_like 'revoked token'
260
+ end
261
+
262
+ describe 'when revoking an access token' do
263
+ let(:stub) do
264
+ stub_request(:get, 'https://accounts.google.com/o/oauth2/revoke' \
265
+ '?token=accesstoken')
266
+ .to_return(status: 200,
267
+ headers: { 'Content-Type' => 'application/json' })
268
+ end
269
+
270
+ before(:example) do
271
+ stub
272
+ @client.refresh_token = nil
273
+ @client.access_token = 'accesstoken'
274
+ @client.revoke!
275
+ end
276
+
277
+ it_behaves_like 'revoked token'
278
+ end
279
+
280
+ describe 'when revoking an invalid token' do
281
+ let(:stub) do
282
+ stub_request(:get, 'https://accounts.google.com/o/oauth2/revoke' \
283
+ '?token=refreshtoken')
284
+ .to_return(status: 400,
285
+ headers: { 'Content-Type' => 'application/json' })
286
+ end
287
+
288
+ it 'raises an authorization error' do
289
+ stub
290
+ expect { @client.revoke! }.to raise_error(
291
+ Signet::AuthorizationError)
292
+ end
293
+ end
230
294
  end
@@ -0,0 +1,159 @@
1
+ # Copyright 2015, Google Inc.
2
+ # All rights reserved.
3
+ #
4
+ # Redistribution and use in source and binary forms, with or without
5
+ # modification, are permitted provided that the following conditions are
6
+ # met:
7
+ #
8
+ # * Redistributions of source code must retain the above copyright
9
+ # notice, this list of conditions and the following disclaimer.
10
+ # * Redistributions in binary form must reproduce the above
11
+ # copyright notice, this list of conditions and the following disclaimer
12
+ # in the documentation and/or other materials provided with the
13
+ # distribution.
14
+ # * Neither the name of Google Inc. nor the names of its
15
+ # contributors may be used to endorse or promote products derived from
16
+ # this software without specific prior written permission.
17
+ #
18
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19
+ # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20
+ # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21
+ # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22
+ # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23
+ # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24
+ # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25
+ # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26
+ # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27
+ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
+ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
+
30
+ spec_dir = File.expand_path(File.join(File.dirname(__FILE__)))
31
+ $LOAD_PATH.unshift(spec_dir)
32
+ $LOAD_PATH.uniq!
33
+
34
+ require 'googleauth'
35
+ require 'googleauth/web_user_authorizer'
36
+ require 'uri'
37
+ require 'multi_json'
38
+ require 'spec_helper'
39
+ require 'rack'
40
+
41
+ describe Google::Auth::WebUserAuthorizer do
42
+ include TestHelpers
43
+
44
+ let(:client_id) { Google::Auth::ClientId.new('testclient', 'notasecret') }
45
+ let(:scope) { %w(email profile) }
46
+ let(:token_store) { DummyTokenStore.new }
47
+ let(:authorizer) do
48
+ Google::Auth::WebUserAuthorizer.new(client_id, scope, token_store)
49
+ end
50
+
51
+ describe '#get_authorization_url' do
52
+ let(:env) do
53
+ Rack::MockRequest.env_for(
54
+ 'http://example.com:8080/test',
55
+ 'REMOTE_ADDR' => '10.10.10.10')
56
+ end
57
+ let(:request) { Rack::Request.new(env) }
58
+ it 'should include current url in state' do
59
+ url = authorizer.get_authorization_url(request: request)
60
+ expect(url).to match(
61
+ %r{%22current_uri%22:%22http://example.com:8080/test%22})
62
+ end
63
+
64
+ it 'should include request forgery token in state' do
65
+ expect(SecureRandom).to receive(:base64).and_return('aGVsbG8=')
66
+ url = authorizer.get_authorization_url(request: request)
67
+ expect(url).to match(/%22session_id%22:%22aGVsbG8=%22/)
68
+ end
69
+
70
+ it 'should include request forgery token in session' do
71
+ expect(SecureRandom).to receive(:base64).and_return('aGVsbG8=')
72
+ authorizer.get_authorization_url(request: request)
73
+ expect(request.session['g-xsrf-token']).to eq 'aGVsbG8='
74
+ end
75
+
76
+ it 'should resolve callback against base URL' do
77
+ url = authorizer.get_authorization_url(request: request)
78
+ expect(url).to match(
79
+ %r{redirect_uri=http://example.com:8080/oauth2callback})
80
+ end
81
+
82
+ it 'should allow overriding the current URL' do
83
+ url = authorizer.get_authorization_url(
84
+ request: request,
85
+ redirect_to: '/foo')
86
+ expect(url).to match %r{%22current_uri%22:%22/foo%22}
87
+ end
88
+
89
+ it 'should pass through login hint' do
90
+ url = authorizer.get_authorization_url(
91
+ request: request,
92
+ login_hint: 'user@example.com')
93
+ expect(url).to match(/login_hint=user@example.com/)
94
+ end
95
+ end
96
+
97
+ shared_examples 'handles callback' do
98
+ let(:token_json) do
99
+ MultiJson.dump('access_token' => '1/abc123',
100
+ 'token_type' => 'Bearer',
101
+ 'expires_in' => 3600)
102
+ end
103
+
104
+ before(:example) do
105
+ stub_request(:post, 'https://www.googleapis.com/oauth2/v3/token')
106
+ .to_return(body: token_json,
107
+ status: 200,
108
+ headers: { 'Content-Type' => 'application/json' })
109
+ end
110
+
111
+ let(:env) do
112
+ Rack::MockRequest.env_for(
113
+ 'http://example.com:8080/oauth2callback?code=authcode&'\
114
+ 'state=%7B%22current_uri%22%3A%22%2Ffoo%22%2C%22'\
115
+ 'session_id%22%3A%22abc%22%7D',
116
+ 'REMOTE_ADDR' => '10.10.10.10')
117
+ end
118
+ let(:request) { Rack::Request.new(env) }
119
+
120
+ before(:example) do
121
+ request.session['g-xsrf-token'] = 'abc'
122
+ end
123
+
124
+ it 'should return credentials when valid code present' do
125
+ expect(credentials).to be_instance_of(
126
+ Google::Auth::UserRefreshCredentials)
127
+ end
128
+
129
+ it 'should return next URL to redirect to' do
130
+ expect(next_url).to eq '/foo'
131
+ end
132
+
133
+ it 'should fail if xrsf token in session and does not match request' do
134
+ request.session['g-xsrf-token'] = '123'
135
+ expect { credentials }.to raise_error(Signet::AuthorizationError)
136
+ end
137
+ end
138
+
139
+ describe '#handle_auth_callback' do
140
+ let(:result) { authorizer.handle_auth_callback('user1', request) }
141
+ let(:credentials) { result[0] }
142
+ let(:next_url) { result[1] }
143
+
144
+ it_behaves_like 'handles callback'
145
+ end
146
+
147
+ describe '#handle_auth_callback_deferred and #get_credentials' do
148
+ let(:next_url) do
149
+ Google::Auth::WebUserAuthorizer.handle_auth_callback_deferred(request)
150
+ end
151
+
152
+ let(:credentials) do
153
+ next_url
154
+ authorizer.get_credentials('user1', request)
155
+ end
156
+
157
+ it_behaves_like 'handles callback'
158
+ end
159
+ end
@@ -39,13 +39,21 @@ $LOAD_PATH.uniq!
39
39
  require 'simplecov'
40
40
  require 'coveralls'
41
41
 
42
- SimpleCov.formatter = Coveralls::SimpleCov::Formatter
42
+ SimpleCov.formatters = [
43
+ Coveralls::SimpleCov::Formatter,
44
+ SimpleCov::Formatter::HTMLFormatter
45
+ ]
43
46
  SimpleCov.start
44
47
 
45
48
  require 'faraday'
46
49
  require 'rspec'
47
50
  require 'logging'
48
51
  require 'rspec/logging_helper'
52
+ require 'webmock/rspec'
53
+ require 'multi_json'
54
+
55
+ # Preload adapter to work around Rubinius error with FakeFS
56
+ MultiJson.use(:json_gem)
49
57
 
50
58
  # Allow Faraday to support test stubs
51
59
  Faraday::Adapter.load_middleware(:test)
@@ -55,4 +63,28 @@ Faraday::Adapter.load_middleware(:test)
55
63
  RSpec.configure do |config|
56
64
  include RSpec::LoggingHelper
57
65
  config.capture_log_messages
66
+ config.include WebMock::API
67
+ end
68
+
69
+ module TestHelpers
70
+ include WebMock::API
71
+ include WebMock::Matchers
72
+ end
73
+
74
+ class DummyTokenStore
75
+ def initialize
76
+ @tokens = {}
77
+ end
78
+
79
+ def load(id)
80
+ @tokens[id]
81
+ end
82
+
83
+ def store(id, token)
84
+ @tokens[id] = token
85
+ end
86
+
87
+ def delete(id)
88
+ @tokens.delete(id)
89
+ end
58
90
  end
metadata CHANGED
@@ -1,197 +1,99 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: googleauth
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.2
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tim Emiola
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-08-06 00:00:00.000000000 Z
11
+ date: 2015-12-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- type: :runtime
15
14
  name: faraday
16
- prerelease: false
17
15
  requirement: !ruby/object:Gem::Requirement
18
16
  requirements:
19
17
  - - "~>"
20
18
  - !ruby/object:Gem::Version
21
19
  version: '0.9'
20
+ type: :runtime
21
+ prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0.9'
27
27
  - !ruby/object:Gem::Dependency
28
- type: :runtime
29
28
  name: logging
30
- prerelease: false
31
29
  requirement: !ruby/object:Gem::Requirement
32
30
  requirements:
33
31
  - - "~>"
34
32
  - !ruby/object:Gem::Version
35
33
  version: '2.0'
34
+ type: :runtime
35
+ prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: '2.0'
41
41
  - !ruby/object:Gem::Dependency
42
- type: :runtime
43
42
  name: jwt
44
- prerelease: false
45
43
  requirement: !ruby/object:Gem::Requirement
46
44
  requirements:
47
45
  - - "~>"
48
46
  - !ruby/object:Gem::Version
49
47
  version: '1.4'
48
+ type: :runtime
49
+ prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
54
  version: '1.4'
55
55
  - !ruby/object:Gem::Dependency
56
- type: :runtime
57
56
  name: memoist
58
- prerelease: false
59
57
  requirement: !ruby/object:Gem::Requirement
60
58
  requirements:
61
59
  - - "~>"
62
60
  - !ruby/object:Gem::Version
63
61
  version: '0.12'
62
+ type: :runtime
63
+ prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0.12'
69
69
  - !ruby/object:Gem::Dependency
70
- type: :runtime
71
70
  name: multi_json
72
- prerelease: false
73
71
  requirement: !ruby/object:Gem::Requirement
74
72
  requirements:
75
73
  - - "~>"
76
74
  - !ruby/object:Gem::Version
77
75
  version: '1.11'
78
- version_requirements: !ruby/object:Gem::Requirement
79
- requirements:
80
- - - "~>"
81
- - !ruby/object:Gem::Version
82
- version: '1.11'
83
- - !ruby/object:Gem::Dependency
84
76
  type: :runtime
85
- name: signet
86
- prerelease: false
87
- requirement: !ruby/object:Gem::Requirement
88
- requirements:
89
- - - "~>"
90
- - !ruby/object:Gem::Version
91
- version: '0.6'
92
- version_requirements: !ruby/object:Gem::Requirement
93
- requirements:
94
- - - "~>"
95
- - !ruby/object:Gem::Version
96
- version: '0.6'
97
- - !ruby/object:Gem::Dependency
98
- type: :development
99
- name: bundler
100
- prerelease: false
101
- requirement: !ruby/object:Gem::Requirement
102
- requirements:
103
- - - "~>"
104
- - !ruby/object:Gem::Version
105
- version: '1.9'
106
- version_requirements: !ruby/object:Gem::Requirement
107
- requirements:
108
- - - "~>"
109
- - !ruby/object:Gem::Version
110
- version: '1.9'
111
- - !ruby/object:Gem::Dependency
112
- type: :development
113
- name: simplecov
114
77
  prerelease: false
115
- requirement: !ruby/object:Gem::Requirement
116
- requirements:
117
- - - "~>"
118
- - !ruby/object:Gem::Version
119
- version: '0.9'
120
78
  version_requirements: !ruby/object:Gem::Requirement
121
79
  requirements:
122
80
  - - "~>"
123
81
  - !ruby/object:Gem::Version
124
- version: '0.9'
82
+ version: '1.11'
125
83
  - !ruby/object:Gem::Dependency
126
- type: :development
127
- name: coveralls
128
- prerelease: false
84
+ name: signet
129
85
  requirement: !ruby/object:Gem::Requirement
130
86
  requirements:
131
87
  - - "~>"
132
88
  - !ruby/object:Gem::Version
133
89
  version: '0.7'
134
- version_requirements: !ruby/object:Gem::Requirement
135
- requirements:
136
- - - "~>"
137
- - !ruby/object:Gem::Version
138
- version: '0.7'
139
- - !ruby/object:Gem::Dependency
140
- type: :development
141
- name: fakefs
142
- prerelease: false
143
- requirement: !ruby/object:Gem::Requirement
144
- requirements:
145
- - - "~>"
146
- - !ruby/object:Gem::Version
147
- version: '0.6'
148
- version_requirements: !ruby/object:Gem::Requirement
149
- requirements:
150
- - - "~>"
151
- - !ruby/object:Gem::Version
152
- version: '0.6'
153
- - !ruby/object:Gem::Dependency
154
- type: :development
155
- name: rake
156
- prerelease: false
157
- requirement: !ruby/object:Gem::Requirement
158
- requirements:
159
- - - "~>"
160
- - !ruby/object:Gem::Version
161
- version: '10.0'
162
- version_requirements: !ruby/object:Gem::Requirement
163
- requirements:
164
- - - "~>"
165
- - !ruby/object:Gem::Version
166
- version: '10.0'
167
- - !ruby/object:Gem::Dependency
168
- type: :development
169
- name: rubocop
170
- prerelease: false
171
- requirement: !ruby/object:Gem::Requirement
172
- requirements:
173
- - - "~>"
174
- - !ruby/object:Gem::Version
175
- version: '0.30'
176
- version_requirements: !ruby/object:Gem::Requirement
177
- requirements:
178
- - - "~>"
179
- - !ruby/object:Gem::Version
180
- version: '0.30'
181
- - !ruby/object:Gem::Dependency
182
- type: :development
183
- name: rspec
90
+ type: :runtime
184
91
  prerelease: false
185
- requirement: !ruby/object:Gem::Requirement
186
- requirements:
187
- - - "~>"
188
- - !ruby/object:Gem::Version
189
- version: '3.0'
190
92
  version_requirements: !ruby/object:Gem::Requirement
191
93
  requirements:
192
94
  - - "~>"
193
95
  - !ruby/object:Gem::Version
194
- version: '3.0'
96
+ version: '0.7'
195
97
  description: |2
196
98
  Allows simple authorization for accessing Google APIs.
197
99
  Provide support for Application Default Credentials, as described at
@@ -214,20 +116,34 @@ files:
214
116
  - Rakefile
215
117
  - googleauth.gemspec
216
118
  - lib/googleauth.rb
119
+ - lib/googleauth/client_id.rb
217
120
  - lib/googleauth/compute_engine.rb
218
121
  - lib/googleauth/credentials_loader.rb
219
122
  - lib/googleauth/iam.rb
123
+ - lib/googleauth/scope_util.rb
220
124
  - lib/googleauth/service_account.rb
221
125
  - lib/googleauth/signet.rb
126
+ - lib/googleauth/stores/file_token_store.rb
127
+ - lib/googleauth/stores/redis_token_store.rb
128
+ - lib/googleauth/token_store.rb
129
+ - lib/googleauth/user_authorizer.rb
222
130
  - lib/googleauth/user_refresh.rb
223
131
  - lib/googleauth/version.rb
132
+ - lib/googleauth/web_user_authorizer.rb
224
133
  - spec/googleauth/apply_auth_examples.rb
134
+ - spec/googleauth/client_id_spec.rb
225
135
  - spec/googleauth/compute_engine_spec.rb
226
136
  - spec/googleauth/get_application_default_spec.rb
227
137
  - spec/googleauth/iam_spec.rb
138
+ - spec/googleauth/scope_util_spec.rb
228
139
  - spec/googleauth/service_account_spec.rb
229
140
  - spec/googleauth/signet_spec.rb
141
+ - spec/googleauth/stores/file_token_store_spec.rb
142
+ - spec/googleauth/stores/redis_token_store_spec.rb
143
+ - spec/googleauth/stores/store_examples.rb
144
+ - spec/googleauth/user_authorizer_spec.rb
230
145
  - spec/googleauth/user_refresh_spec.rb
146
+ - spec/googleauth/web_user_authorizer_spec.rb
231
147
  - spec/spec_helper.rb
232
148
  homepage: https://github.com/google/google-auth-library-ruby
233
149
  licenses:
@@ -249,16 +165,24 @@ required_rubygems_version: !ruby/object:Gem::Requirement
249
165
  version: '0'
250
166
  requirements: []
251
167
  rubyforge_project:
252
- rubygems_version: 2.4.8
168
+ rubygems_version: 2.4.3
253
169
  signing_key:
254
170
  specification_version: 4
255
171
  summary: Google Auth Library for Ruby
256
172
  test_files:
257
173
  - spec/googleauth/apply_auth_examples.rb
174
+ - spec/googleauth/client_id_spec.rb
258
175
  - spec/googleauth/compute_engine_spec.rb
259
176
  - spec/googleauth/get_application_default_spec.rb
260
177
  - spec/googleauth/iam_spec.rb
178
+ - spec/googleauth/scope_util_spec.rb
261
179
  - spec/googleauth/service_account_spec.rb
262
180
  - spec/googleauth/signet_spec.rb
181
+ - spec/googleauth/stores/file_token_store_spec.rb
182
+ - spec/googleauth/stores/redis_token_store_spec.rb
183
+ - spec/googleauth/stores/store_examples.rb
184
+ - spec/googleauth/user_authorizer_spec.rb
263
185
  - spec/googleauth/user_refresh_spec.rb
186
+ - spec/googleauth/web_user_authorizer_spec.rb
264
187
  - spec/spec_helper.rb
188
+ has_rdoc: