diff --git a/oauth2client/appengine.py b/oauth2client/appengine.py index 485f2e7..ea1ccec 100644 --- a/oauth2client/appengine.py +++ b/oauth2client/appengine.py @@ -318,7 +318,8 @@ class OAuth2Decorator(object): Args: client_id: string, client identifier. client_secret: string client secret. - scope: string, scope of the credentials being requested. + scope: string or list of strings, scope(s) of the credentials being + requested. auth_uri: string, URI for authorization endpoint. For convenience defaults to Google's endpoints but any OAuth 2.0 provider can be used. token_uri: string, URI for token endpoint. For convenience diff --git a/oauth2client/client.py b/oauth2client/client.py index d888d79..3d81a8c 100644 --- a/oauth2client/client.py +++ b/oauth2client/client.py @@ -623,7 +623,8 @@ class OAuth2WebServerFlow(Flow): Args: client_id: string, client identifier. client_secret: string client secret. - scope: string, scope of the credentials being requested. + scope: string or list of strings, scope(s) of the credentials being + requested. user_agent: string, HTTP User-Agent to provide for this application. auth_uri: string, URI for authorization endpoint. For convenience defaults to Google's endpoints but any OAuth 2.0 provider can be used. @@ -634,6 +635,8 @@ class OAuth2WebServerFlow(Flow): """ self.client_id = client_id self.client_secret = client_secret + if type(scope) is list: + scope = ' '.join(scope) self.scope = scope self.user_agent = user_agent self.auth_uri = auth_uri @@ -734,7 +737,7 @@ def flow_from_clientsecrets(filename, scope, message=None): Args: filename: string, File name of client secrets. - scope: string, Space separated list of scopes. + scope: string or list of strings, scope(s) to request. message: string, A friendly string to display to the user if the clientsecrets file is missing or invalid. If message is provided then sys.exit will be called in the case of an error. If message in not @@ -766,36 +769,3 @@ def flow_from_clientsecrets(filename, scope, message=None): else: raise UnknownClientSecretsFlowError( 'This OAuth 2.0 flow is unsupported: "%s"' * client_type) - - -class OAuth2WebServerFlowFromClientSecrets(Flow): - """Does the Web Server Flow for OAuth 2.0. - - """ - - def __init__(self, client_secrets, scope, user_agent, - auth_uri='https://accounts.google.com/o/oauth2/auth', - token_uri='https://accounts.google.com/o/oauth2/token', - **kwargs): - """Constructor for OAuth2WebServerFlow - - Args: - client_id: string, client identifier. - client_secret: string client secret. - scope: string, scope of the credentials being requested. - user_agent: string, HTTP User-Agent to provide for this application. - auth_uri: string, URI for authorization endpoint. For convenience - defaults to Google's endpoints but any OAuth 2.0 provider can be used. - token_uri: string, URI for token endpoint. For convenience - defaults to Google's endpoints but any OAuth 2.0 provider can be used. - **kwargs: dict, The keyword arguments are all optional and required - parameters for the OAuth calls. - """ - self.client_id = client_id - self.client_secret = client_secret - self.scope = scope - self.user_agent = user_agent - self.auth_uri = auth_uri - self.token_uri = token_uri - self.params = kwargs - self.redirect_uri = None diff --git a/oauth2client/multistore_file.py b/oauth2client/multistore_file.py index e3e3f6d..02e36d1 100644 --- a/oauth2client/multistore_file.py +++ b/oauth2client/multistore_file.py @@ -76,7 +76,7 @@ def get_credential_storage(filename, client_id, user_agent, scope, filename: The JSON file storing a set of credentials client_id: The client_id for the credential user_agent: The user agent for the credential - scope: A string for the scope being requested + scope: string or list of strings, Scope(s) being requested warn_on_readonly: if True, log a warning if the store is readonly Returns: @@ -90,6 +90,8 @@ def get_credential_storage(filename, client_id, user_agent, scope, filename, _MultiStore(filename, warn_on_readonly)) finally: _multistores_lock.release() + if type(scope) is list: + scope = ' '.join(scope) return multistore._get_storage(client_id, user_agent, scope) @@ -328,7 +330,7 @@ class _MultiStore(object): Args: client_id: The client_id for the credential user_agent: The user agent for the credential - scope: A string for the scope being requested + scope: A string for the scope(s) being requested Returns: The credential specified or None if not present @@ -344,7 +346,7 @@ class _MultiStore(object): Args: cred: The OAuth2Credential to update/set - scope: The scope that this credential covers + scope: The scope(s) that this credential covers """ key = (cred.client_id, cred.user_agent, scope) self._data[key] = cred @@ -358,7 +360,7 @@ class _MultiStore(object): Args: client_id: The client_id for the credential user_agent: The user agent for the credential - scope: A string for the scope being requested + scope: A string for the scope(s) being requested Returns: A Storage object that can be used to get/set this cred diff --git a/tests/test_oauth2client_appengine.py b/tests/test_oauth2client_appengine.py index 9362220..8d8064c 100644 --- a/tests/test_oauth2client_appengine.py +++ b/tests/test_oauth2client_appengine.py @@ -131,7 +131,7 @@ class DecoratorTests(unittest.TestCase): decorator = OAuth2Decorator(client_id='foo_client_id', client_secret='foo_client_secret', - scope='foo_scope') + scope=['foo_scope', 'bar_scope']) self.decorator = decorator class TestRequiredHandler(webapp.RequestHandler): @@ -168,7 +168,7 @@ class DecoratorTests(unittest.TestCase): q = parse_qs(response.headers['Location'].split('?', 1)[1]) self.assertEqual('http://localhost/oauth2callback', q['redirect_uri'][0]) self.assertEqual('foo_client_id', q['client_id'][0]) - self.assertEqual('foo_scope', q['scope'][0]) + self.assertEqual('foo_scope bar_scope', q['scope'][0]) self.assertEqual('http://localhost/foo_path', q['state'][0]) self.assertEqual('code', q['response_type'][0]) self.assertEqual(False, self.decorator.has_credentials()) @@ -210,7 +210,7 @@ class DecoratorTests(unittest.TestCase): q = parse_qs(url.split('?', 1)[1]) self.assertEqual('http://localhost/oauth2callback', q['redirect_uri'][0]) self.assertEqual('foo_client_id', q['client_id'][0]) - self.assertEqual('foo_scope', q['scope'][0]) + self.assertEqual('foo_scope bar_scope', q['scope'][0]) self.assertEqual('http://localhost/bar_path', q['state'][0]) self.assertEqual('code', q['response_type'][0]) diff --git a/tests/test_oauth2client_file.py b/tests/test_oauth2client_file.py index 4776404..de5fcf2 100644 --- a/tests/test_oauth2client_file.py +++ b/tests/test_oauth2client_file.py @@ -152,7 +152,7 @@ class OAuth2ClientFileTests(unittest.TestCase): FILENAME, 'some_client_id', 'user-agent/1.0', - 'some-scope') + ['some-scope', 'some-other-scope']) credentials = store.get() self.assertEquals(None, credentials) @@ -175,7 +175,7 @@ class OAuth2ClientFileTests(unittest.TestCase): FILENAME, credentials.client_id, credentials.user_agent, - 'some-scope') + ['some-scope', 'some-other-scope']) store.put(credentials) credentials = store.get()