blob: 37e69ea5f19e0883750abaaeca5031614472ed27 [file] [log] [blame]
Joe Gregorioccc79542011-02-19 00:05:26 -05001#!/usr/bin/python2.4
2#
3# Copyright 2010 Google Inc.
4#
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16
17
Joe Gregorio0bc70912011-05-24 15:30:49 -040018"""Oauth2client tests
Joe Gregorioccc79542011-02-19 00:05:26 -050019
Joe Gregorio0bc70912011-05-24 15:30:49 -040020Unit tests for oauth2client.
Joe Gregorioccc79542011-02-19 00:05:26 -050021"""
22
23__author__ = 'jcgregorio@google.com (Joe Gregorio)'
24
Joe Gregorio8b4c1732011-12-06 11:28:29 -050025import base64
Joe Gregorio562b7312011-09-15 09:06:38 -040026import datetime
Joe Gregorioe1de4162011-02-23 11:30:29 -050027import httplib2
Joe Gregorio32d852d2012-06-14 09:08:18 -040028import os
Joe Gregorioccc79542011-02-19 00:05:26 -050029import unittest
30import urlparse
Joe Gregorioe1de4162011-02-23 11:30:29 -050031
Joe Gregorioccc79542011-02-19 00:05:26 -050032try:
33 from urlparse import parse_qs
34except ImportError:
35 from cgi import parse_qs
36
Joe Gregorio83f2ee62012-12-06 15:25:54 -050037from apiclient.http import HttpMock
Joe Gregorioccc79542011-02-19 00:05:26 -050038from apiclient.http import HttpMockSequence
Joe Gregorio549230c2012-01-11 10:38:05 -050039from oauth2client.anyjson import simplejson
Joe Gregorioccc79542011-02-19 00:05:26 -050040from oauth2client.client import AccessTokenCredentials
41from oauth2client.client import AccessTokenCredentialsError
42from oauth2client.client import AccessTokenRefreshError
JacobMoshenko8e905102011-06-20 09:53:10 -040043from oauth2client.client import AssertionCredentials
Joe Gregorio08cdcb82012-03-14 00:09:33 -040044from oauth2client.client import Credentials
Joe Gregorioccc79542011-02-19 00:05:26 -050045from oauth2client.client import FlowExchangeError
Joe Gregorio08cdcb82012-03-14 00:09:33 -040046from oauth2client.client import MemoryCache
Joe Gregorio83f2ee62012-12-06 15:25:54 -050047from oauth2client.client import NonAsciiHeaderError
Joe Gregorioccc79542011-02-19 00:05:26 -050048from oauth2client.client import OAuth2Credentials
49from oauth2client.client import OAuth2WebServerFlow
Joe Gregoriof2326c02012-02-09 12:18:44 -050050from oauth2client.client import OOB_CALLBACK_URN
Joe Gregorio0bd8c412013-01-03 17:17:46 -050051from oauth2client.client import REFRESH_STATUS_CODES
Joe Gregorio8b4c1732011-12-06 11:28:29 -050052from oauth2client.client import VerifyJwtTokenError
53from oauth2client.client import _extract_id_token
Joe Gregorio32d852d2012-06-14 09:08:18 -040054from oauth2client.client import credentials_from_clientsecrets_and_code
Joe Gregorio83f2ee62012-12-06 15:25:54 -050055from oauth2client.client import credentials_from_code
Joe Gregorioc29aaa92012-07-16 16:16:31 -040056from oauth2client.client import flow_from_clientsecrets
Joe Gregorio0bd8c412013-01-03 17:17:46 -050057from oauth2client.clientsecrets import _loadfile
Joe Gregorio32d852d2012-06-14 09:08:18 -040058
59DATA_DIR = os.path.join(os.path.dirname(__file__), 'data')
60
Joe Gregorio68a8cfe2012-08-03 16:17:40 -040061
Joe Gregorio32d852d2012-06-14 09:08:18 -040062def datafile(filename):
63 return os.path.join(DATA_DIR, filename)
Joe Gregorioccc79542011-02-19 00:05:26 -050064
Joe Gregorio68a8cfe2012-08-03 16:17:40 -040065
Joe Gregorioc29aaa92012-07-16 16:16:31 -040066def load_and_cache(existing_file, fakename, cache_mock):
67 client_type, client_info = _loadfile(datafile(existing_file))
68 cache_mock.cache[fakename] = {client_type: client_info}
69
Joe Gregorio68a8cfe2012-08-03 16:17:40 -040070
Joe Gregorioc29aaa92012-07-16 16:16:31 -040071class CacheMock(object):
72 def __init__(self):
73 self.cache = {}
74
75 def get(self, key, namespace=''):
76 # ignoring namespace for easier testing
77 return self.cache.get(key, None)
78
79 def set(self, key, value, namespace=''):
80 # ignoring namespace for easier testing
81 self.cache[key] = value
82
Joe Gregorioccc79542011-02-19 00:05:26 -050083
Joe Gregorio08cdcb82012-03-14 00:09:33 -040084class CredentialsTests(unittest.TestCase):
85
86 def test_to_from_json(self):
87 credentials = Credentials()
88 json = credentials.to_json()
89 restored = Credentials.new_from_json(json)
90
91
Joe Gregorio83f2ee62012-12-06 15:25:54 -050092class BasicCredentialsTests(unittest.TestCase):
Joe Gregorioccc79542011-02-19 00:05:26 -050093
94 def setUp(self):
95 access_token = "foo"
96 client_id = "some_client_id"
97 client_secret = "cOuDdkfjxxnv+"
98 refresh_token = "1/0/a.df219fjls0"
Joe Gregorio562b7312011-09-15 09:06:38 -040099 token_expiry = datetime.datetime.utcnow()
Joe Gregorioccc79542011-02-19 00:05:26 -0500100 token_uri = "https://www.google.com/accounts/o8/oauth2/token"
101 user_agent = "refresh_checker/1.0"
102 self.credentials = OAuth2Credentials(
103 access_token, client_id, client_secret,
104 refresh_token, token_expiry, token_uri,
105 user_agent)
106
107 def test_token_refresh_success(self):
Joe Gregorio0bd8c412013-01-03 17:17:46 -0500108 for status_code in REFRESH_STATUS_CODES:
Joe Gregorio7c7c6b12012-07-16 16:31:01 -0400109 http = HttpMockSequence([
110 ({'status': status_code}, ''),
111 ({'status': '200'}, '{"access_token":"1/3w","expires_in":3600}'),
112 ({'status': '200'}, 'echo_request_headers'),
113 ])
114 http = self.credentials.authorize(http)
115 resp, content = http.request("http://example.com")
116 self.assertEqual('Bearer 1/3w', content['Authorization'])
117 self.assertFalse(self.credentials.access_token_expired)
Joe Gregorioccc79542011-02-19 00:05:26 -0500118
119 def test_token_refresh_failure(self):
Joe Gregorio0bd8c412013-01-03 17:17:46 -0500120 for status_code in REFRESH_STATUS_CODES:
Joe Gregorio7c7c6b12012-07-16 16:31:01 -0400121 http = HttpMockSequence([
122 ({'status': status_code}, ''),
123 ({'status': '400'}, '{"error":"access_denied"}'),
124 ])
125 http = self.credentials.authorize(http)
126 try:
127 http.request("http://example.com")
128 self.fail("should raise AccessTokenRefreshError exception")
129 except AccessTokenRefreshError:
130 pass
131 self.assertTrue(self.credentials.access_token_expired)
Joe Gregorioccc79542011-02-19 00:05:26 -0500132
133 def test_non_401_error_response(self):
134 http = HttpMockSequence([
135 ({'status': '400'}, ''),
136 ])
137 http = self.credentials.authorize(http)
138 resp, content = http.request("http://example.com")
139 self.assertEqual(400, resp.status)
140
Joe Gregorio562b7312011-09-15 09:06:38 -0400141 def test_to_from_json(self):
142 json = self.credentials.to_json()
143 instance = OAuth2Credentials.from_json(json)
Joe Gregorio654f4a22012-02-09 14:15:44 -0500144 self.assertEqual(OAuth2Credentials, type(instance))
Joe Gregorio1daa71b2011-09-15 18:12:14 -0400145 instance.token_expiry = None
146 self.credentials.token_expiry = None
147
Joe Gregorio654f4a22012-02-09 14:15:44 -0500148 self.assertEqual(instance.__dict__, self.credentials.__dict__)
Joe Gregorio562b7312011-09-15 09:06:38 -0400149
Joe Gregorio83f2ee62012-12-06 15:25:54 -0500150 def test_no_unicode_in_request_params(self):
151 access_token = u'foo'
152 client_id = u'some_client_id'
153 client_secret = u'cOuDdkfjxxnv+'
154 refresh_token = u'1/0/a.df219fjls0'
155 token_expiry = unicode(datetime.datetime.utcnow())
156 token_uri = u'https://www.google.com/accounts/o8/oauth2/token'
157 user_agent = u'refresh_checker/1.0'
158 credentials = OAuth2Credentials(access_token, client_id, client_secret,
159 refresh_token, token_expiry, token_uri,
160 user_agent)
161
162 http = HttpMock(headers={'status': '200'})
163 http = credentials.authorize(http)
164 http.request(u'http://example.com', method=u'GET', headers={
165 u'foo': u'bar'
166 })
167 for k, v in http.headers.iteritems():
168 self.assertEqual(str, type(k))
169 self.assertEqual(str, type(v))
170
171 # Test again with unicode strings that can't simple be converted to ASCII.
172 try:
173 http.request(
174 u'http://example.com', method=u'GET', headers={u'foo': u'\N{COMET}'})
175 self.fail('Expected exception to be raised.')
176 except NonAsciiHeaderError:
177 pass
178
Joe Gregorioccc79542011-02-19 00:05:26 -0500179
180class AccessTokenCredentialsTests(unittest.TestCase):
181
182 def setUp(self):
183 access_token = "foo"
184 user_agent = "refresh_checker/1.0"
185 self.credentials = AccessTokenCredentials(access_token, user_agent)
186
187 def test_token_refresh_success(self):
Joe Gregorio0bd8c412013-01-03 17:17:46 -0500188 for status_code in REFRESH_STATUS_CODES:
Joe Gregorio7c7c6b12012-07-16 16:31:01 -0400189 http = HttpMockSequence([
190 ({'status': status_code}, ''),
191 ])
192 http = self.credentials.authorize(http)
193 try:
194 resp, content = http.request("http://example.com")
195 self.fail("should throw exception if token expires")
196 except AccessTokenCredentialsError:
197 pass
198 except Exception:
199 self.fail("should only throw AccessTokenCredentialsError")
Joe Gregorioccc79542011-02-19 00:05:26 -0500200
201 def test_non_401_error_response(self):
202 http = HttpMockSequence([
203 ({'status': '400'}, ''),
204 ])
205 http = self.credentials.authorize(http)
Joe Gregorio83cd4392011-06-20 10:11:35 -0400206 resp, content = http.request('http://example.com')
Joe Gregorioccc79542011-02-19 00:05:26 -0500207 self.assertEqual(400, resp.status)
208
Joe Gregorio83cd4392011-06-20 10:11:35 -0400209 def test_auth_header_sent(self):
210 http = HttpMockSequence([
211 ({'status': '200'}, 'echo_request_headers'),
212 ])
213 http = self.credentials.authorize(http)
214 resp, content = http.request('http://example.com')
Joe Gregorio654f4a22012-02-09 14:15:44 -0500215 self.assertEqual('Bearer foo', content['Authorization'])
Joe Gregorioccc79542011-02-19 00:05:26 -0500216
Joe Gregorio8b4c1732011-12-06 11:28:29 -0500217
JacobMoshenko8e905102011-06-20 09:53:10 -0400218class TestAssertionCredentials(unittest.TestCase):
219 assertion_text = "This is the assertion"
220 assertion_type = "http://www.google.com/assertionType"
221
222 class AssertionCredentialsTestImpl(AssertionCredentials):
223
224 def _generate_assertion(self):
225 return TestAssertionCredentials.assertion_text
226
227 def setUp(self):
228 user_agent = "fun/2.0"
229 self.credentials = self.AssertionCredentialsTestImpl(self.assertion_type,
Joe Gregorio68a8cfe2012-08-03 16:17:40 -0400230 user_agent=user_agent)
JacobMoshenko8e905102011-06-20 09:53:10 -0400231
232 def test_assertion_body(self):
233 body = urlparse.parse_qs(self.credentials._generate_refresh_request_body())
Joe Gregorio654f4a22012-02-09 14:15:44 -0500234 self.assertEqual(self.assertion_text, body['assertion'][0])
235 self.assertEqual(self.assertion_type, body['assertion_type'][0])
JacobMoshenko8e905102011-06-20 09:53:10 -0400236
237 def test_assertion_refresh(self):
238 http = HttpMockSequence([
239 ({'status': '200'}, '{"access_token":"1/3w"}'),
240 ({'status': '200'}, 'echo_request_headers'),
241 ])
242 http = self.credentials.authorize(http)
243 resp, content = http.request("http://example.com")
Joe Gregorio654f4a22012-02-09 14:15:44 -0500244 self.assertEqual('Bearer 1/3w', content['Authorization'])
JacobMoshenko8e905102011-06-20 09:53:10 -0400245
246
Joe Gregorio8b4c1732011-12-06 11:28:29 -0500247class ExtractIdTokenText(unittest.TestCase):
248 """Tests _extract_id_token()."""
249
250 def test_extract_success(self):
251 body = {'foo': 'bar'}
252 payload = base64.urlsafe_b64encode(simplejson.dumps(body)).strip('=')
253 jwt = 'stuff.' + payload + '.signature'
254
255 extracted = _extract_id_token(jwt)
Joe Gregorio654f4a22012-02-09 14:15:44 -0500256 self.assertEqual(extracted, body)
Joe Gregorio8b4c1732011-12-06 11:28:29 -0500257
258 def test_extract_failure(self):
259 body = {'foo': 'bar'}
260 payload = base64.urlsafe_b64encode(simplejson.dumps(body)).strip('=')
261 jwt = 'stuff.' + payload
262
263 self.assertRaises(VerifyJwtTokenError, _extract_id_token, jwt)
264
Joe Gregorio68a8cfe2012-08-03 16:17:40 -0400265
Joe Gregorioccc79542011-02-19 00:05:26 -0500266class OAuth2WebServerFlowTest(unittest.TestCase):
267
268 def setUp(self):
269 self.flow = OAuth2WebServerFlow(
270 client_id='client_id+1',
271 client_secret='secret+1',
272 scope='foo',
Joe Gregorio68a8cfe2012-08-03 16:17:40 -0400273 redirect_uri=OOB_CALLBACK_URN,
Joe Gregorioccc79542011-02-19 00:05:26 -0500274 user_agent='unittest-sample/1.0',
275 )
276
277 def test_construct_authorize_url(self):
Joe Gregorio68a8cfe2012-08-03 16:17:40 -0400278 authorize_url = self.flow.step1_get_authorize_url()
Joe Gregorioccc79542011-02-19 00:05:26 -0500279
280 parsed = urlparse.urlparse(authorize_url)
281 q = parse_qs(parsed[4])
Joe Gregorio654f4a22012-02-09 14:15:44 -0500282 self.assertEqual('client_id+1', q['client_id'][0])
283 self.assertEqual('code', q['response_type'][0])
284 self.assertEqual('foo', q['scope'][0])
Joe Gregorio68a8cfe2012-08-03 16:17:40 -0400285 self.assertEqual(OOB_CALLBACK_URN, q['redirect_uri'][0])
Joe Gregorio654f4a22012-02-09 14:15:44 -0500286 self.assertEqual('offline', q['access_type'][0])
Joe Gregorio69a0aca2011-11-03 10:47:32 -0400287
Joe Gregorio32f73192012-10-23 16:13:44 -0400288 def test_override_flow_via_kwargs(self):
289 """Passing kwargs to override defaults."""
Joe Gregorio69a0aca2011-11-03 10:47:32 -0400290 flow = OAuth2WebServerFlow(
291 client_id='client_id+1',
292 client_secret='secret+1',
293 scope='foo',
Joe Gregorio68a8cfe2012-08-03 16:17:40 -0400294 redirect_uri=OOB_CALLBACK_URN,
Joe Gregorio69a0aca2011-11-03 10:47:32 -0400295 user_agent='unittest-sample/1.0',
Joe Gregorio32f73192012-10-23 16:13:44 -0400296 access_type='online',
297 response_type='token'
Joe Gregorio69a0aca2011-11-03 10:47:32 -0400298 )
Joe Gregorio68a8cfe2012-08-03 16:17:40 -0400299 authorize_url = flow.step1_get_authorize_url()
Joe Gregorio69a0aca2011-11-03 10:47:32 -0400300
301 parsed = urlparse.urlparse(authorize_url)
302 q = parse_qs(parsed[4])
Joe Gregorio654f4a22012-02-09 14:15:44 -0500303 self.assertEqual('client_id+1', q['client_id'][0])
Joe Gregorio32f73192012-10-23 16:13:44 -0400304 self.assertEqual('token', q['response_type'][0])
Joe Gregorio654f4a22012-02-09 14:15:44 -0500305 self.assertEqual('foo', q['scope'][0])
Joe Gregorio68a8cfe2012-08-03 16:17:40 -0400306 self.assertEqual(OOB_CALLBACK_URN, q['redirect_uri'][0])
Joe Gregorio654f4a22012-02-09 14:15:44 -0500307 self.assertEqual('online', q['access_type'][0])
Joe Gregorioccc79542011-02-19 00:05:26 -0500308
309 def test_exchange_failure(self):
310 http = HttpMockSequence([
JacobMoshenko8e905102011-06-20 09:53:10 -0400311 ({'status': '400'}, '{"error":"invalid_request"}'),
Joe Gregorioccc79542011-02-19 00:05:26 -0500312 ])
313
314 try:
Joe Gregorio68a8cfe2012-08-03 16:17:40 -0400315 credentials = self.flow.step2_exchange('some random code', http=http)
Joe Gregorioccc79542011-02-19 00:05:26 -0500316 self.fail("should raise exception if exchange doesn't get 200")
317 except FlowExchangeError:
318 pass
319
Joe Gregorioddb969a2012-07-11 11:04:12 -0400320 def test_urlencoded_exchange_failure(self):
321 http = HttpMockSequence([
322 ({'status': '400'}, "error=invalid_request"),
323 ])
324
325 try:
Joe Gregorio68a8cfe2012-08-03 16:17:40 -0400326 credentials = self.flow.step2_exchange('some random code', http=http)
Joe Gregorioddb969a2012-07-11 11:04:12 -0400327 self.fail("should raise exception if exchange doesn't get 200")
328 except FlowExchangeError, e:
329 self.assertEquals('invalid_request', str(e))
330
331 def test_exchange_failure_with_json_error(self):
332 # Some providers have "error" attribute as a JSON object
333 # in place of regular string.
334 # This test makes sure no strange object-to-string coversion
335 # exceptions are being raised instead of FlowExchangeError.
336 http = HttpMockSequence([
337 ({'status': '400'},
338 """ {"error": {
339 "type": "OAuthException",
340 "message": "Error validating verification code."} }"""),
341 ])
342
343 try:
Joe Gregorio68a8cfe2012-08-03 16:17:40 -0400344 credentials = self.flow.step2_exchange('some random code', http=http)
Joe Gregorioddb969a2012-07-11 11:04:12 -0400345 self.fail("should raise exception if exchange doesn't get 200")
346 except FlowExchangeError, e:
347 pass
348
Joe Gregorioccc79542011-02-19 00:05:26 -0500349 def test_exchange_success(self):
350 http = HttpMockSequence([
351 ({'status': '200'},
352 """{ "access_token":"SlAV32hkKG",
353 "expires_in":3600,
354 "refresh_token":"8xLOxBtZp8" }"""),
355 ])
356
Joe Gregorio68a8cfe2012-08-03 16:17:40 -0400357 credentials = self.flow.step2_exchange('some random code', http=http)
Joe Gregorio654f4a22012-02-09 14:15:44 -0500358 self.assertEqual('SlAV32hkKG', credentials.access_token)
359 self.assertNotEqual(None, credentials.token_expiry)
360 self.assertEqual('8xLOxBtZp8', credentials.refresh_token)
Joe Gregorioccc79542011-02-19 00:05:26 -0500361
Joe Gregorioddb969a2012-07-11 11:04:12 -0400362 def test_urlencoded_exchange_success(self):
363 http = HttpMockSequence([
364 ({'status': '200'}, "access_token=SlAV32hkKG&expires_in=3600"),
365 ])
366
Joe Gregorio68a8cfe2012-08-03 16:17:40 -0400367 credentials = self.flow.step2_exchange('some random code', http=http)
Joe Gregorioddb969a2012-07-11 11:04:12 -0400368 self.assertEqual('SlAV32hkKG', credentials.access_token)
369 self.assertNotEqual(None, credentials.token_expiry)
370
371 def test_urlencoded_expires_param(self):
372 http = HttpMockSequence([
373 # Note the "expires=3600" where you'd normally
374 # have if named "expires_in"
375 ({'status': '200'}, "access_token=SlAV32hkKG&expires=3600"),
376 ])
377
Joe Gregorio68a8cfe2012-08-03 16:17:40 -0400378 credentials = self.flow.step2_exchange('some random code', http=http)
Joe Gregorioddb969a2012-07-11 11:04:12 -0400379 self.assertNotEqual(None, credentials.token_expiry)
380
Joe Gregorioccc79542011-02-19 00:05:26 -0500381 def test_exchange_no_expires_in(self):
382 http = HttpMockSequence([
383 ({'status': '200'}, """{ "access_token":"SlAV32hkKG",
384 "refresh_token":"8xLOxBtZp8" }"""),
385 ])
386
Joe Gregorio68a8cfe2012-08-03 16:17:40 -0400387 credentials = self.flow.step2_exchange('some random code', http=http)
Joe Gregorio654f4a22012-02-09 14:15:44 -0500388 self.assertEqual(None, credentials.token_expiry)
Joe Gregorioccc79542011-02-19 00:05:26 -0500389
Joe Gregorioddb969a2012-07-11 11:04:12 -0400390 def test_urlencoded_exchange_no_expires_in(self):
391 http = HttpMockSequence([
392 # This might be redundant but just to make sure
393 # urlencoded access_token gets parsed correctly
394 ({'status': '200'}, "access_token=SlAV32hkKG"),
395 ])
396
Joe Gregorio68a8cfe2012-08-03 16:17:40 -0400397 credentials = self.flow.step2_exchange('some random code', http=http)
Joe Gregorioddb969a2012-07-11 11:04:12 -0400398 self.assertEqual(None, credentials.token_expiry)
399
Joe Gregorio4b4002f2012-06-14 15:41:01 -0400400 def test_exchange_fails_if_no_code(self):
401 http = HttpMockSequence([
402 ({'status': '200'}, """{ "access_token":"SlAV32hkKG",
403 "refresh_token":"8xLOxBtZp8" }"""),
404 ])
405
406 code = {'error': 'thou shall not pass'}
407 try:
Joe Gregorio68a8cfe2012-08-03 16:17:40 -0400408 credentials = self.flow.step2_exchange(code, http=http)
Joe Gregorio4b4002f2012-06-14 15:41:01 -0400409 self.fail('should raise exception if no code in dictionary.')
410 except FlowExchangeError, e:
411 self.assertTrue('shall not pass' in str(e))
412
Joe Gregorio8b4c1732011-12-06 11:28:29 -0500413 def test_exchange_id_token_fail(self):
414 http = HttpMockSequence([
415 ({'status': '200'}, """{ "access_token":"SlAV32hkKG",
416 "refresh_token":"8xLOxBtZp8",
417 "id_token": "stuff.payload"}"""),
418 ])
419
420 self.assertRaises(VerifyJwtTokenError, self.flow.step2_exchange,
Joe Gregorio68a8cfe2012-08-03 16:17:40 -0400421 'some random code', http=http)
Joe Gregorio8b4c1732011-12-06 11:28:29 -0500422
423 def test_exchange_id_token_fail(self):
424 body = {'foo': 'bar'}
425 payload = base64.urlsafe_b64encode(simplejson.dumps(body)).strip('=')
Joe Gregoriobd512b52011-12-06 15:39:26 -0500426 jwt = (base64.urlsafe_b64encode('stuff')+ '.' + payload + '.' +
427 base64.urlsafe_b64encode('signature'))
Joe Gregorio8b4c1732011-12-06 11:28:29 -0500428
429 http = HttpMockSequence([
430 ({'status': '200'}, """{ "access_token":"SlAV32hkKG",
431 "refresh_token":"8xLOxBtZp8",
432 "id_token": "%s"}""" % jwt),
433 ])
434
Joe Gregorio68a8cfe2012-08-03 16:17:40 -0400435 credentials = self.flow.step2_exchange('some random code', http=http)
Joe Gregorio654f4a22012-02-09 14:15:44 -0500436 self.assertEqual(credentials.id_token, body)
Joe Gregorio8b4c1732011-12-06 11:28:29 -0500437
Joe Gregorio68a8cfe2012-08-03 16:17:40 -0400438
439class FlowFromCachedClientsecrets(unittest.TestCase):
Joe Gregorioc29aaa92012-07-16 16:16:31 -0400440
441 def test_flow_from_clientsecrets_cached(self):
442 cache_mock = CacheMock()
443 load_and_cache('client_secrets.json', 'some_secrets', cache_mock)
Joe Gregorio68a8cfe2012-08-03 16:17:40 -0400444
445 flow = flow_from_clientsecrets(
446 'some_secrets', '', redirect_uri='oob', cache=cache_mock)
Joe Gregorioc29aaa92012-07-16 16:16:31 -0400447 self.assertEquals('foo_client_secret', flow.client_secret)
448
Joe Gregorio68a8cfe2012-08-03 16:17:40 -0400449
Joe Gregorio32d852d2012-06-14 09:08:18 -0400450class CredentialsFromCodeTests(unittest.TestCase):
451 def setUp(self):
452 self.client_id = 'client_id_abc'
453 self.client_secret = 'secret_use_code'
454 self.scope = 'foo'
455 self.code = '12345abcde'
456 self.redirect_uri = 'postmessage'
457
458 def test_exchange_code_for_token(self):
459 http = HttpMockSequence([
460 ({'status': '200'},
461 """{ "access_token":"asdfghjkl",
462 "expires_in":3600 }"""),
463 ])
464 credentials = credentials_from_code(self.client_id, self.client_secret,
Joe Gregorio68a8cfe2012-08-03 16:17:40 -0400465 self.scope, self.code, redirect_uri=self.redirect_uri,
466 http=http)
Joe Gregorio32d852d2012-06-14 09:08:18 -0400467 self.assertEquals(credentials.access_token, 'asdfghjkl')
468 self.assertNotEqual(None, credentials.token_expiry)
469
470 def test_exchange_code_for_token_fail(self):
471 http = HttpMockSequence([
472 ({'status': '400'}, '{"error":"invalid_request"}'),
473 ])
474
475 try:
476 credentials = credentials_from_code(self.client_id, self.client_secret,
Joe Gregorio68a8cfe2012-08-03 16:17:40 -0400477 self.scope, self.code, redirect_uri=self.redirect_uri,
478 http=http)
Joe Gregorio32d852d2012-06-14 09:08:18 -0400479 self.fail("should raise exception if exchange doesn't get 200")
480 except FlowExchangeError:
481 pass
482
Joe Gregorio32d852d2012-06-14 09:08:18 -0400483 def test_exchange_code_and_file_for_token(self):
484 http = HttpMockSequence([
485 ({'status': '200'},
486 """{ "access_token":"asdfghjkl",
487 "expires_in":3600 }"""),
488 ])
489 credentials = credentials_from_clientsecrets_and_code(
490 datafile('client_secrets.json'), self.scope,
491 self.code, http=http)
492 self.assertEquals(credentials.access_token, 'asdfghjkl')
493 self.assertNotEqual(None, credentials.token_expiry)
494
Joe Gregorioc29aaa92012-07-16 16:16:31 -0400495 def test_exchange_code_and_cached_file_for_token(self):
496 http = HttpMockSequence([
497 ({'status': '200'}, '{ "access_token":"asdfghjkl"}'),
498 ])
499 cache_mock = CacheMock()
500 load_and_cache('client_secrets.json', 'some_secrets', cache_mock)
501
502 credentials = credentials_from_clientsecrets_and_code(
503 'some_secrets', self.scope,
504 self.code, http=http, cache=cache_mock)
505 self.assertEquals(credentials.access_token, 'asdfghjkl')
506
Joe Gregorio32d852d2012-06-14 09:08:18 -0400507 def test_exchange_code_and_file_for_token_fail(self):
508 http = HttpMockSequence([
509 ({'status': '400'}, '{"error":"invalid_request"}'),
510 ])
511
512 try:
513 credentials = credentials_from_clientsecrets_and_code(
514 datafile('client_secrets.json'), self.scope,
515 self.code, http=http)
516 self.fail("should raise exception if exchange doesn't get 200")
517 except FlowExchangeError:
518 pass
519
520
Joe Gregorio08cdcb82012-03-14 00:09:33 -0400521class MemoryCacheTests(unittest.TestCase):
522
523 def test_get_set_delete(self):
524 m = MemoryCache()
525 self.assertEqual(None, m.get('foo'))
526 self.assertEqual(None, m.delete('foo'))
527 m.set('foo', 'bar')
528 self.assertEqual('bar', m.get('foo'))
529 m.delete('foo')
530 self.assertEqual(None, m.get('foo'))
531
532
Joe Gregorioccc79542011-02-19 00:05:26 -0500533if __name__ == '__main__':
534 unittest.main()