Пример #1
0
    def test_multistore_file(self):
        access_token = 'foo'
        client_secret = 'cOuDdkfjxxnv+'
        refresh_token = '1/0/a.df219fjls0'
        token_expiry = datetime.datetime.utcnow()
        token_uri = 'https://www.google.com/accounts/o8/oauth2/token'
        user_agent = 'refresh_checker/1.0'
        client_id = 'some_client_id'

        credentials = OAuth2Credentials(access_token, client_id, client_secret,
                                        refresh_token, token_expiry, token_uri,
                                        user_agent)

        store = multistore_file.get_credential_storage(
            FILENAME, credentials.client_id, credentials.user_agent,
            ['some-scope', 'some-other-scope'])

        store.put(credentials)
        credentials = store.get()

        self.assertNotEquals(None, credentials)
        self.assertEquals('foo', credentials.access_token)

        store.delete()
        credentials = store.get()

        self.assertEquals(None, credentials)

        if os.name == 'posix':
            self.assertEquals('0600',
                              oct(stat.S_IMODE(os.stat(FILENAME).st_mode)))
Пример #2
0
def resolve_service(service):
  if service not in SCOPES.keys():
    print "Invalid service: {}, try EVERNOTE or GOOGLE_DRIVE"
    return

  try:
    with open(CONFIG_FILE, 'r') as fl:
      st = oct(os.stat(CONFIG_FILE)[stat.ST_MODE])[-3:]
      if st != '600':
        print "Group / Other readable {}, must be 0600".format(CONFIG_FILE)
        return

      conf = yaml.safe_load(fl)

  except IOError:
    with open(CONFIG_FILE, 'w') as fl:
      yaml.dump(CONFIG_TPL, fl, default_flow_style=False)

    os.chmod(CONFIG_FILE, 0600)
    print "You must edit the {} file adding your API client ID and Key".format(CONFIG_FILE)
    return

  storage = get_credential_storage(
    CREDENTIALS_FILE,
    conf[service]['client_id'],
    hashlib.md5(''.join(SCOPES[service])).hexdigest(),
    SCOPES[service]
  )
  return (
    conf[service]['client_id'],
    conf[service]['client_secret'],
    SCOPES[service],
    storage
  )
    def test_multistore_non_existent_file(self):
        store = multistore_file.get_credential_storage(
            FILENAME, "some_client_id", "user-agent/1.0", ["some-scope", "some-other-scope"]
        )

        credentials = store.get()
        self.assertEquals(None, credentials)
Пример #4
0
  def test_read_only_file_fail_lock(self):
    access_token = 'foo'
    client_secret = 'cOuDdkfjxxnv+'
    refresh_token = '1/0/a.df219fjls0'
    token_expiry = datetime.datetime.utcnow()
    token_uri = 'https://www.google.com/accounts/o8/oauth2/token'
    user_agent = 'refresh_checker/1.0'
    client_id = 'some_client_id'

    credentials = OAuth2Credentials(
        access_token, client_id, client_secret,
        refresh_token, token_expiry, token_uri,
        user_agent)

    open(FILENAME, 'a+b').close()
    os.chmod(FILENAME, 0400)

    store = multistore_file.get_credential_storage(
        FILENAME,
        credentials.client_id,
        credentials.user_agent,
        ['some-scope', 'some-other-scope'])

    store.put(credentials)
    if os.name == 'posix':
      self.assertTrue(store._multistore._read_only)
    os.chmod(FILENAME, 0600)
Пример #5
0
def CredentialsFromFile(path, client_info, oauth2client_args=None):
    """Read credentials from a file."""
    credential_store = multistore_file.get_credential_storage(
        path,
        client_info['client_id'],
        client_info['user_agent'],
        client_info['scope'])
    if hasattr(FLAGS, 'auth_local_webserver'):
        FLAGS.auth_local_webserver = False
    credentials = credential_store.get()
    if credentials is None or credentials.invalid:
        print('Generating new OAuth credentials ...')
        for _ in range(20):
            # If authorization fails, we want to retry, rather than let this
            # cascade up and get caught elsewhere. If users want out of the
            # retry loop, they can ^C.
            try:
                flow = oauth2client.client.OAuth2WebServerFlow(**client_info)
                flags = _GetRunFlowFlags(args=oauth2client_args)
                credentials = tools.run_flow(flow, credential_store, flags)
                break
            except (oauth2client.client.FlowExchangeError, SystemExit) as e:
                # Here SystemExit is "no credential at all", and the
                # FlowExchangeError is "invalid" -- usually because
                # you reused a token.
                print('Invalid authorization: %s' % (e,))
            except httplib2.HttpLib2Error as e:
                print('Communication error: %s' % (e,))
                raise exceptions.CredentialsError(
                    'Communication error creating credentials: %s' % e)
    return credentials
Пример #6
0
  def WriteTemplate(self):
    """Write the credential file."""

    # straight up credentials in JSON
    self._WriteFileContents(self._json_path,
                            self.credentials.to_json())
    # multistore version
    self._WriteFileContents(self._multistore_path, '')
    storage = oauth2_multistore_file.get_credential_storage(
        self._multistore_path,
        self.credentials.client_id,
        self.credentials.user_agent,
        self.scopes)
    storage.put(self.credentials)

    # gae java wants something special
    self._WriteFileContents(self._gae_java_path, """
oauth2_client_secret: {secret}
oauth2_client_id: {id}
oauth2_refresh_token: {token}
""".format(secret=config.CLOUDSDK_CLIENT_NOTSOSECRET,
           id=config.CLOUDSDK_CLIENT_ID,
           token=self.credentials.refresh_token))

    # we create a small .boto file for gsutil, to be put in BOTO_PATH
    self._WriteFileContents(self._gsutil_path, """
[Credentials]
gs_oauth2_refresh_token = {token}
""".format(token=self.credentials.refresh_token))
Пример #7
0
  def test_multistore_file(self):
    access_token = 'foo'
    client_secret = 'cOuDdkfjxxnv+'
    refresh_token = '1/0/a.df219fjls0'
    token_expiry = datetime.datetime.utcnow()
    token_uri = 'https://www.google.com/accounts/o8/oauth2/token'
    user_agent = 'refresh_checker/1.0'
    client_id = 'some_client_id'

    credentials = OAuth2Credentials(
        access_token, client_id, client_secret,
        refresh_token, token_expiry, token_uri,
        user_agent)

    store = multistore_file.get_credential_storage(
        FILENAME,
        credentials.client_id,
        credentials.user_agent,
        ['some-scope', 'some-other-scope'])

    store.put(credentials)
    credentials = store.get()

    self.assertNotEquals(None, credentials)
    self.assertEquals('foo', credentials.access_token)

    store.delete()
    credentials = store.get()

    self.assertEquals(None, credentials)

    if os.name == 'posix':
      self.assertEquals('0600', oct(stat.S_IMODE(os.stat(FILENAME).st_mode)))
  def test_read_only_file_fail_lock(self):
    access_token = 'foo'
    client_secret = 'cOuDdkfjxxnv+'
    refresh_token = '1/0/a.df219fjls0'
    token_expiry = datetime.datetime.utcnow()
    token_uri = 'https://www.google.com/accounts/o8/oauth2/token'
    user_agent = 'refresh_checker/1.0'
    client_id = 'some_client_id'

    credentials = OAuth2Credentials(
        access_token, client_id, client_secret,
        refresh_token, token_expiry, token_uri,
        user_agent)

    open(FILENAME, 'a+b').close()
    os.chmod(FILENAME, 0400)

    store = multistore_file.get_credential_storage(
        FILENAME,
        credentials.client_id,
        credentials.user_agent,
        ['some-scope', 'some-other-scope'])

    store.put(credentials)
    if os.name == 'posix':
      self.assertTrue(store._multistore._read_only)
    os.chmod(FILENAME, 0600)
Пример #9
0
    def test_multistore_non_existent_file(self):
        store = multistore_file.get_credential_storage(
            FILENAME, 'some_client_id', 'user-agent/1.0',
            ['some-scope', 'some-other-scope'])

        credentials = store.get()
        self.assertEquals(None, credentials)
Пример #10
0
def test_renewToken():
    global requestors
    storage = multistore_file.get_credential_storage(
        Auth.config,
        Auth.clientid,
        'testuseraccount',
        ['https://www.googleapis.com/auth/cloudprint'])

    credentials = client.OAuth2Credentials('test',
                                           Auth.clientid,
                                           'testsecret',
                                           'testtoken',
                                           1,
                                           'https://www.googleapis.com/auth/cloudprint',
                                           'testaccount1')

    # test renewing token exits in non-interactive mode
    with pytest.raises(SystemExit):
        Auth.RenewToken(False, requestors[0], credentials, storage, 'test')

    # test renewing interactively tries to read from stdin
    with pytest.raises(IOError):
        assert Auth.RenewToken(True,
                               requestors[0],
                               credentials,
                               storage,
                               'test') is False
Пример #11
0
    def AddAccountStep2(userid, flow, code, storage=None, permissions=None):
        """Executes step 2 of OAuth2WebServerFlow, without interaction.

        Args:
          userid: string, reference for the account
          permissions: string or iterable of strings, scope(s) of the credentials being requested
          storage: storage, instance of storage to store credentials in.
          flow: OAuth2WebServerFlow, flow instance
          code: string, code representing user granting CCP permission to call GCP API for user

        Returns:
          credentials: A credentials instance with the account details
        """
        if permissions is None:
            permissions = Auth.normal_permissions

        if storage is None:
            storage = multistore_file.get_credential_storage(
                Auth.config, Auth.clientid, userid, permissions)

        credentials = flow.step2_exchange(code)
        storage.put(credentials)

        Utils.FixFilePermissions(Auth.config)

        return credentials
Пример #12
0
    def AddAccountStep2(userid, flow, code, storage=None, permissions=None):
        """Executes step 2 of OAuth2WebServerFlow, without interaction.

        Args:
          userid: string, reference for the account
          permissions: string or iterable of strings, scope(s) of the credentials being requested
          storage: storage, instance of storage to store credentials in.
          flow: OAuth2WebServerFlow, flow instance
          code: string, code representing user granting CCP permission to call GCP API for user

        Returns:
          credentials: A credentials instance with the account details
        """
        if permissions is None:
            permissions = Auth.normal_permissions

        if storage is None:
            storage = multistore_file.get_credential_storage(
                Auth.config,
                Auth.clientid,
                userid,
                permissions)

        credentials = flow.step2_exchange(code)
        storage.put(credentials)

        Utils.FixFilePermissions(Auth.config)

        return credentials
Пример #13
0
  def SetupAuth(interactive=False):
    """Sets up requestors with authentication tokens

    Args:
      interactive: boolean, when set to true can prompt user, otherwise returns False if authentication fails
      
    Returns:
      requestor, storage: Authenticated requestors and an instance of storage
    """
    modifiedconfig = False
    
    # parse config file and extract useragents, which we use for account names
    userids = []
    if os.path.exists( Auth.config ):
      content_file = open(Auth.config, 'r')
      content = content_file.read()
      data = json.loads(content)
      for user in data['data']:
        userids.append(str(user['credential']['user_agent']))
    
    if len(userids) == 0:
      userids = [ None ]
    
    requestors = []
    for userid in userids:
      storage = multistore_file.get_credential_storage(
	    Auth.config,
	    Auth.clientid,
	    userid,
	    ['https://www.googleapis.com/auth/cloudprint'])
      credentials = storage.get()

      if not credentials and interactive: # pragma: no cover
	credentials = Auth.AddAccount(storage, userid)
	modifiedconfig = True
	if userid == None:
	  userid = credentials.user_agent
      elif not interactive and not credentials:
	return False
	
      # renew if expired
      requestor = cloudprintrequestor()
      if credentials.access_token_expired: # pragma: no cover 
	credentials.refresh(requestor)
      
      requestor = credentials.authorize(requestor)
      requestor.setAccount(userid)
      requestors.append(requestor)
    
    # fix permissions
    if modifiedconfig: # pragma: no cover 
      try:
        os.chmod(Auth.config, 0640)
        os.chown(Auth.config, 0, Auth.GetLPID())
      except:
        sys.stderr.write("DEBUG: Cannot alter file permissions\n")
        pass

    return requestors, storage
Пример #14
0
  def SetupAuth(interactive=False):
    """Sets up requestors with authentication tokens

    Args:
      interactive: boolean, when set to true can prompt user, otherwise returns False if authentication fails
      
    Returns:
      requestor, storage: Authenticated requestors and an instance of storage
    """
    modifiedconfig = False
    
    # parse config file and extract useragents, which we use for account names
    userids = []
    if os.path.exists( Auth.config ):
      content_file = open(Auth.config, 'r')
      content = content_file.read()
      data = json.loads(content)
      for user in data['data']:
        userids.append(str(user['credential']['user_agent']))
    
    if len(userids) == 0:
      userids = [ None ]
    
    requestors = []
    for userid in userids:
      storage = multistore_file.get_credential_storage(
	    Auth.config,
	    Auth.clientid,
	    userid,
	    ['https://www.googleapis.com/auth/cloudprint'])
      credentials = storage.get()

      if not credentials and interactive: # pragma: no cover
	credentials = Auth.AddAccount(storage, userid)
	modifiedconfig = True
	if userid == None:
	  userid = credentials.user_agent
      elif not interactive and not credentials:
	return False
	
      # renew if expired
      requestor = cloudprintrequestor()
      if credentials.access_token_expired: # pragma: no cover 
	credentials.refresh(requestor)
      
      requestor = credentials.authorize(requestor)
      requestor.setAccount(userid)
      requestors.append(requestor)
    
    # fix permissions
    if modifiedconfig: # pragma: no cover 
      try:
        os.chmod(Auth.config, 0640)
        os.chown(Auth.config, 0, Auth.GetLPID())
      except:
        sys.stderr.write("DEBUG: Cannot alter file permissions\n")
        pass

    return requestors, storage
Пример #15
0
 def credential_store(self):
     storage_path = os.path.join(self.storage_path, 'oauth_credentials')
     return get_credential_storage(
         storage_path,
         self.client_secrets['client_id'],
         self.user_agent,
         self.scope
     )
Пример #16
0
    def AddAccount(storage, userid=None, permissions=None):
        """Adds an account to the configuration file with an interactive dialog.

        Args:
          storage: storage, instance of storage to store credentials in.
          userid: string, reference for the account
          permissions: string or iterable of strings, scope(s) of the credentials being requested

        Returns:
          credentials: A credentials instance with the account details
        """
        if permissions is None:
            permissions = Auth.normal_permissions

        if userid is None:
            userid = raw_input(
                "Name for this user account ( eg [email protected] )? ")

            # setup storage again if just got userid now
            storage = multistore_file.get_credential_storage(
                Auth.config,
                Auth.clientid,
                userid,
                permissions)
        url = None
        while True:
            if Utils.hasGUI():
                url = Auth.SetupHttpReturnServer()
            Auth.code = None
            flow, auth_uri = Auth.AddAccountStep1(userid, permissions, url)
            message = "Open this URL if it doesn't, grant access to CUPS Cloud Print "
            message += "( for the " + userid + " account ), "
            message += "then provide the code displayed : \n\n"
            message += auth_uri + "\n"
            print message
            Utils.openBrowserWithUrl(auth_uri)
            if url is not None:
                from select import select
                print 'Code from Google: '
                while (Auth.code is None):
                    result, _, _ = select([sys.stdin], [], [], 0.5)
                    if result and Auth.code is None:
                        s = sys.stdin.readline()
                        if s != "":
                            Auth.code = s
                Auth.httpd.shutdown()
            else:
                Auth.code = raw_input('Code from Google: ')

            try:
                credentials = Auth.AddAccountStep2(userid, flow, Auth.code, storage, permissions)
                return credentials
            except Exception as e:
                message = "\nThe code does not seem to be valid ( "
                message += str(e) + " ), please try again.\n"
                print message
Пример #17
0
 def credential_store(self):
     storage_path = os.path.join(
         xdg.BaseDirectory.save_data_path(self.app._meta.label),
         'oauth_credentials')
     return get_credential_storage(
         storage_path,
         self.client_secrets['client_id'],
         self.Meta.user_agent,
         self.Meta.scope
     )
Пример #18
0
    def AddAccount(storage, userid=None, permissions=None):
        """Adds an account to the configuration file with an interactive dialog.

        Args:
          storage: storage, instance of storage to store credentials in.
          userid: string, reference for the account
          permissions: string or iterable of strings, scope(s) of the credentials being requested

        Returns:
          credentials: A credentials instance with the account details
        """
        if permissions is None:
            permissions = Auth.normal_permissions

        if userid is None:
            userid = raw_input(
                "Name for this user account ( eg [email protected] )? ")

            # setup storage again if just got userid now
            storage = multistore_file.get_credential_storage(
                Auth.config, Auth.clientid, userid, permissions)
        url = None
        while True:
            if Utils.hasGUI():
                url = Auth.SetupHttpReturnServer()
            Auth.code = None
            flow, auth_uri = Auth.AddAccountStep1(userid, permissions, url)
            message = "Open this URL if it doesn't, grant access to CUPS Cloud Print "
            message += "( for the " + userid + " account ), "
            message += "then provide the code displayed : \n\n"
            message += auth_uri + "\n"
            print message
            Utils.openBrowserWithUrl(auth_uri)
            if url is not None:
                from select import select
                print 'Code from Google: '
                while (Auth.code is None):
                    result, _, _ = select([sys.stdin], [], [], 0.5)
                    if result and Auth.code is None:
                        s = sys.stdin.readline()
                        if s != "":
                            Auth.code = s
                Auth.httpd.shutdown()
            else:
                Auth.code = raw_input('Code from Google: ')

            try:
                credentials = Auth.AddAccountStep2(userid, flow, Auth.code,
                                                   storage, permissions)
                return credentials
            except Exception as e:
                message = "\nThe code does not seem to be valid ( "
                message += str(e) + " ), please try again.\n"
                print message
Пример #19
0
def process():
    if 'redirect' in session and session['redirect']:
        session['redirect'] = False
        data = session['request']
    elif request.json:
        data = request.json
    elif request.args:
        data = request.args
    elif request.form:
        data = request.form
    else:
        return jsonify({'error': 'No link or search parameters were specified.'}), 400

    if 'user' not in session or not session['user']:
        vprint("No user found in session. Redirecting to login first")
        session['redirect'] = True
        session['request'] = data
        return redirect('/login', code=301)
    else:
        vprint("User %s found in session. Loading credentials" % session['user'])
        store = get_credential_storage(credential_store,
                                       session['user'],
                                       oauth_app_creds['user_agent'],
                                       oauth_app_creds['scope'])
        credentials = store.get()

    if not credentials:
        return jsonify({'error': 'No user credentials found'}), 500
    else:
        vprint("Refreshing credentials for user %s" % credentials.id_token['email'])
        http = httplib2.Http()
        http = credentials.authorize(http)
        credentials.refresh(http)
        vprint("Successfully refreshed credentials for user %s" % credentials.id_token['email'])

    if 'link' not in data and 'search' not in data:
        error = "No link or search term was specified"
        vprint(error)
        return jsonify({'error': error}), 400
        abort(400)

    try:
        if 'link' in data:
            # Strip link to current video for now. Uploading playlists should probably be explicit?
            link = re.findall('v=(.*?)(?:&|$)', data['link'])[0]
            youtube_to_gmusic.process_link(link, credentials=credentials)
        elif 'search' in data:
            youtube_to_gmusic.process_search(data['search'], credentials=credentials)
        else:
            raise(Exception("This shouldn't happen!"))
        return jsonify({'details': 'success!'}), 200
    except Exception as e:
        vprint('Error: ' + e.message)
        return jsonify({'error': e.message}), 400
Пример #20
0
    def DeleteAccount(userid):
        """Delete an account from the configuration file

        Args:
          userid: string, reference for the account

        Returns:
          deleted: boolean , true on success
        """
        storage = multistore_file.get_credential_storage(
            Auth.config, Auth.clientid, userid, Auth.normal_permissions)
        return storage.delete()
Пример #21
0
    def DeleteAccount(userid=None):  # pragma: no cover
        """Delete an account from the configuration file

    Args:
      storage: storage, instance of storage to store credentials in.
      userid: string, reference for the account
      
    Returns:
      deleted: boolean , true on success
    """
        storage = multistore_file.get_credential_storage(
            Auth.config, Auth.clientid, userid, ["https://www.googleapis.com/auth/cloudprint"]
        )
        return storage.delete()
Пример #22
0
    def test_read_only_file_fail_lock(self):
        credentials = self.create_test_credentials()

        open(FILENAME, 'a+b').close()
        os.chmod(FILENAME, 0o400)

        store = multistore_file.get_credential_storage(
            FILENAME, credentials.client_id, credentials.user_agent,
            ['some-scope', 'some-other-scope'])

        store.put(credentials)
        if os.name == 'posix':
            self.assertTrue(store._multistore._read_only)
        os.chmod(FILENAME, 0o600)
Пример #23
0
 def test_multistore_no_symbolic_link_files(self):
     if hasattr(os, 'symlink'):
         SYMFILENAME = FILENAME + 'sym'
         os.symlink(FILENAME, SYMFILENAME)
         store = multistore_file.get_credential_storage(
             SYMFILENAME, 'some_client_id', 'user-agent/1.0',
             ['some-scope', 'some-other-scope'])
         try:
             store.get()
             self.fail('Should have raised an exception.')
         except locked_file.CredentialsFileSymbolicLinkError:
             pass
         finally:
             os.unlink(SYMFILENAME)
    def test_read_only_file_fail_lock(self):
        credentials = self.create_test_credentials()

        open(FILENAME, "a+b").close()
        os.chmod(FILENAME, 0o400)

        store = multistore_file.get_credential_storage(
            FILENAME, credentials.client_id, credentials.user_agent, ["some-scope", "some-other-scope"]
        )

        store.put(credentials)
        if os.name == "posix":
            self.assertTrue(store._multistore._read_only)
        os.chmod(FILENAME, 0o600)
    def test_multistore_file_backwards_compatibility(self):
        credentials = self.create_test_credentials()
        scopes = ["scope1", "scope2"]

        # store the credentials using the legacy key method
        store = multistore_file.get_credential_storage(FILENAME, "client_id", "user_agent", scopes)
        store.put(credentials)

        # retrieve the credentials using a custom key that matches the legacy key
        key = {"clientId": "client_id", "userAgent": "user_agent", "scope": util.scopes_to_string(scopes)}
        store = multistore_file.get_credential_storage_custom_key(FILENAME, key)
        stored_credentials = store.get()

        self.assertEqual(credentials.access_token, stored_credentials.access_token)
Пример #26
0
    def DeleteAccount(userid=None):
        """Delete an account from the configuration file

        Args:
          storage: storage, instance of storage to store credentials in.
          userid: string, reference for the account

        Returns:
          deleted: boolean , true on success
        """
        storage = multistore_file.get_credential_storage(
            Auth.config, Auth.clientid, userid,
            ['https://www.googleapis.com/auth/cloudprint'])
        return storage.delete()
 def test_multistore_no_symbolic_link_files(self):
     if hasattr(os, "symlink"):
         SYMFILENAME = FILENAME + "sym"
         os.symlink(FILENAME, SYMFILENAME)
         store = multistore_file.get_credential_storage(
             SYMFILENAME, "some_client_id", "user-agent/1.0", ["some-scope", "some-other-scope"]
         )
         try:
             store.get()
             self.fail("Should have raised an exception.")
         except locked_file.CredentialsFileSymbolicLinkError:
             pass
         finally:
             os.unlink(SYMFILENAME)
def GetAuthorizedCredentials(credential_path, env):
  """Builds authorized credentials used for communicating with backend services.

  As the file are stored in the repo and are frequently read only, we copy the
  credentials file to a temp file that is writable.  We need the file to be
  writable so we can update the access token in the file.  Otherwise we ask
  for an access token each time we need to auth, this can lead to us
  exceeding API rate limits.

  Args:
    credential_path: The path to a credentials file.
    env: What environment to authorize access for.  The master set of
        environments can be found in data_source_config.py.

  Returns:
    An authorized credentials object that can be used to build client libraries
    and issue authorized requests to backend services.

  Raises:
    CredentialKeyError: If the env value passed is not a valid environment.
  """
  if env not in config.Environments.All():
    raise CredentialKeyError(
        '%s is not a valid environment.  The valid environments are %s' %
        (env, config.Environments.All()))

  try:
    cred_to_use = _CopyCredentialsToTemp(credential_path)
  except IOError:
    logging.error(
        'Unable to copy credential files to a writable location.')
    raise

  client_id = '%s.apps.googleusercontent.com' % config.Services.GetServiceUri(
      env, config.Services.PROJECT_ID)
  user_agent = '%s_perfkit_client/1.0' % env

  storage = multistore_file.get_credential_storage(
      cred_to_use, client_id, user_agent, CREDENTIALS_SCOPE)
  credentials = storage.get()

  if not credentials:
    msg = (
        'Could not find credentials.\ncred_to_use: %s\nclient_id: %s\n'
        'user_agent: %s\nscope: %s') % (cred_to_use, client_id, user_agent,
                                        CREDENTIALS_SCOPE)
    raise Error(msg)

  return credentials.authorize(httplib2.Http(timeout=config.DEFAULT_TIMEOUT))
 def test_multistore_no_symbolic_link_files(self):
     if hasattr(os, 'symlink'):
         SYMFILENAME = FILENAME + 'sym'
         os.symlink(FILENAME, SYMFILENAME)
         store = multistore_file.get_credential_storage(
             SYMFILENAME,
             'some_client_id',
             'user-agent/1.0',
             ['some-scope', 'some-other-scope'])
         try:
             self.assertRaises(
                 locked_file.CredentialsFileSymbolicLinkError,
                 store.get)
         finally:
             os.unlink(SYMFILENAME)
Пример #30
0
    def DeleteAccount(userid):
        """Delete an account from the configuration file

        Args:
          userid: string, reference for the account

        Returns:
          deleted: boolean , true on success
        """
        storage = multistore_file.get_credential_storage(
            Auth.config,
            Auth.clientid,
            userid,
            Auth.normal_permissions)
        return storage.delete()
 def test_multistore_no_symbolic_link_files(self):
   if hasattr(os, 'symlink'):
     SYMFILENAME = FILENAME + 'sym'
     os.symlink(FILENAME, SYMFILENAME)
     store = multistore_file.get_credential_storage(
         SYMFILENAME,
         'some_client_id',
         'user-agent/1.0',
         ['some-scope', 'some-other-scope'])
     try:
       store.get()
       self.fail('Should have raised an exception.')
     except locked_file.CredentialsFileSymbolicLinkError:
       pass
     finally:
       os.unlink(SYMFILENAME)
  def test_read_only_file_fail_lock(self):
    credentials = self.create_test_credentials()

    open(FILENAME, 'a+b').close()
    os.chmod(FILENAME, 0400)

    store = multistore_file.get_credential_storage(
        FILENAME,
        credentials.client_id,
        credentials.user_agent,
        ['some-scope', 'some-other-scope'])

    store.put(credentials)
    if os.name == 'posix':
      self.assertTrue(store._multistore._read_only)
    os.chmod(FILENAME, 0600)
Пример #33
0
def test_setupAuth():
    testUserName = '******'

    # ensure setup with no details doesnt create file
    assert os.path.exists(Auth.config) is False
    assert Auth.SetupAuth(False) == (False, False)
    assert os.path.exists(Auth.config) is True
    assert Utils.ReadFile(Auth.config) == "{}"

    os.unlink(Auth.config)

    # create initial file
    assert os.path.exists(Auth.config) is False
    assert Auth.SetupAuth(False, testUserIds=['test']) == (False, False)
    assert os.path.exists(Auth.config) is True

    # ensure permissions are correct after creating config
    assert '0660' == oct(os.stat(Auth.config)[stat.ST_MODE])[-4:]

    # add dummy details
    storage = multistore_file.get_credential_storage(
        Auth.config,
        Auth.clientid,
        'testuseraccount',
        ['https://www.googleapis.com/auth/cloudprint'])

    credentials = client.OAuth2Credentials('test', Auth.clientid,
                                           'testsecret', 'testtoken', 1,
                                           'https://www.googleapis.com/auth/cloudprint',
                                           testUserName)
    storage.put(credentials)

    # ensure permissions are correct after populating config
    assert '0660' == oct(os.stat(Auth.config)[stat.ST_MODE])[-4:]

    # re-run to test getting credentials
    requestors, storage = Auth.SetupAuth(False)
    assert requestors is not None
    assert storage is not None

    # check deleting account
    assert Auth.DeleteAccount(testUserName) is None
    requestors, storage = Auth.SetupAuth(False)
    assert requestors is False
    assert storage is False
Пример #34
0
def test_renewToken():
    global requestors
    storage = multistore_file.get_credential_storage(
        Auth.config, Auth.clientid, 'testuseraccount',
        ['https://www.googleapis.com/auth/cloudprint'])

    credentials = client.OAuth2Credentials(
        'test', Auth.clientid, 'testsecret', 'testtoken', 1,
        'https://www.googleapis.com/auth/cloudprint', 'testaccount1')

    # test renewing token exits in non-interactive mode
    with pytest.raises(SystemExit):
        Auth.RenewToken(False, requestors[0], credentials, storage, 'test')

    # test renewing interactively tries to read from stdin
    with pytest.raises(IOError):
        assert Auth.RenewToken(True, requestors[0], credentials, storage,
                               'test') is False
Пример #35
0
def test_setupAuthOwnership():
    assert Auth.SetupAuth(False, testUserIds=['test']) == (False, False)

    # ensure ownership is correct after creating config
    assert Utils.GetLPID() == os.stat(Auth.config).st_gid

    # add dummy details
    storage = multistore_file.get_credential_storage(
        Auth.config, Auth.clientid, 'testuseraccount',
        ['https://www.googleapis.com/auth/cloudprint'])

    credentials = client.OAuth2Credentials(
        'test', Auth.clientid, 'testsecret', 'testtoken', 1,
        'https://www.googleapis.com/auth/cloudprint', 'testaccount1')
    storage.put(credentials)

    # ensure ownership is correct after populating config
    assert Utils.GetLPID() == os.stat(Auth.config).st_gid
    def test_multistore_file_backwards_compatibility(self):
        credentials = self._create_test_credentials()
        scopes = ['scope1', 'scope2']

        # store the credentials using the legacy key method
        store = multistore_file.get_credential_storage(
            FILENAME, 'client_id', 'user_agent', scopes)
        store.put(credentials)

        # retrieve the credentials using a custom key that matches the
        # legacy key
        key = {'clientId': 'client_id', 'userAgent': 'user_agent',
               'scope': util.scopes_to_string(scopes)}
        store = multistore_file.get_credential_storage_custom_key(
            FILENAME, key)
        stored_credentials = store.get()

        self.assertEqual(credentials.access_token,
                         stored_credentials.access_token)
Пример #37
0
def test_setupAuth():
    testUserName = '******'

    # ensure setup with no details doesnt create file
    assert os.path.exists(Auth.config) is False
    assert Auth.SetupAuth(False) == (False, False)
    assert os.path.exists(Auth.config) is True
    assert Utils.ReadFile(Auth.config) == "{}"

    os.unlink(Auth.config)

    # create initial file
    assert os.path.exists(Auth.config) is False
    assert Auth.SetupAuth(False, testUserIds=['test']) == (False, False)
    assert os.path.exists(Auth.config) is True

    # ensure permissions are correct after creating config
    assert '0660' == oct(os.stat(Auth.config)[stat.ST_MODE])[-4:]

    # add dummy details
    storage = multistore_file.get_credential_storage(
        Auth.config, Auth.clientid, 'testuseraccount',
        ['https://www.googleapis.com/auth/cloudprint'])

    credentials = client.OAuth2Credentials(
        'test', Auth.clientid, 'testsecret', 'testtoken', 1,
        'https://www.googleapis.com/auth/cloudprint', testUserName)
    storage.put(credentials)

    # ensure permissions are correct after populating config
    assert '0660' == oct(os.stat(Auth.config)[stat.ST_MODE])[-4:]

    # re-run to test getting credentials
    requestors, storage = Auth.SetupAuth(False)
    assert requestors is not None
    assert storage is not None

    # check deleting account
    assert Auth.DeleteAccount(testUserName) is None
    requestors, storage = Auth.SetupAuth(False)
    assert requestors is False
    assert storage is False
Пример #38
0
    def do_google_oauth(self):
        oauth_scope = 'https://www.googleapis.com/auth/adexchange.seller.readonly'
        self.flow = flow_from_clientsecrets('adxseller_client_secrets.json',
                                            scope=oauth_scope,
                                        redirect_uri='urn:ietf:wg:oauth:2.0:oob')

        self.storage = multistore_file.get_credential_storage(filename='credentials.file',
                                                              client_id=self.ad_client_id,
                                                              user_agent='',
                                                              scope=oauth_scope)
        credentials = self.storage.get()
        
        if credentials is None or credentials.invalid:
            authorize_url = self.flow.step1_get_authorize_url(redirect_uri='urn:ietf:wg:oauth:2.0:oob')
            return {'pending': authorize_url}
            # print authorize_url
            # code = raw_input('Enter verification code: ').strip()
        else:
            self.http = credentials.authorize(httplib2.Http())
            return {'success': None}
Пример #39
0
def test_setupAuth():
    # create initial file
    assert os.path.exists('/tmp/cloudprint.conf') == False
    assert Auth.SetupAuth(False) == False
    assert os.path.exists('/tmp/cloudprint.conf') == True

    # add dummy details
    storage = multistore_file.get_credential_storage(
        Auth.config, Auth.clientid, 'testuseraccount',
        ['https://www.googleapis.com/auth/cloudprint'])

    credentials = client.OAuth2Credentials(
        'test', Auth.clientid, 'testsecret', 'testtoken', 1,
        'https://www.googleapis.com/auth/cloudprint', 'testaccount1')
    storage.put(credentials)

    # re-run to test getting credentials
    requestors, storage = Auth.SetupAuth(False)
    assert requestors != None
    assert storage != None
Пример #40
0
def test_setupAuthOwnership():
    assert Auth.SetupAuth(False,testUserIds=['test']) == (False, False)

    # ensure ownership is correct after creating config
    assert Utils.GetLPID() == os.stat(Auth.config).st_gid

    # add dummy details
    storage = multistore_file.get_credential_storage(
        Auth.config,
        Auth.clientid,
        'testuseraccount',
        ['https://www.googleapis.com/auth/cloudprint'])

    credentials = client.OAuth2Credentials('test', Auth.clientid,
                                           'testsecret', 'testtoken', 1,
                                           'https://www.googleapis.com/auth/cloudprint', 'testaccount1')
    storage.put(credentials)

    # ensure ownership is correct after populating config
    assert Utils.GetLPID() == os.stat(Auth.config).st_gid
    def test_multistore_file(self):
        credentials = self.create_test_credentials()

        store = multistore_file.get_credential_storage(
            FILENAME, credentials.client_id, credentials.user_agent, ["some-scope", "some-other-scope"]
        )

        store.put(credentials)
        credentials = store.get()

        self.assertNotEquals(None, credentials)
        self.assertEquals("foo", credentials.access_token)

        store.delete()
        credentials = store.get()

        self.assertEquals(None, credentials)

        if os.name == "posix":
            self.assertEquals("0600", oct(stat.S_IMODE(os.stat(FILENAME).st_mode)))
Пример #42
0
    def test_multistore_file_backwards_compatibility(self):
        credentials = self.create_test_credentials()
        scopes = ['scope1', 'scope2']

        # store the credentials using the legacy key method
        store = multistore_file.get_credential_storage(FILENAME, 'client_id',
                                                       'user_agent', scopes)
        store.put(credentials)

        # retrieve the credentials using a custom key that matches the legacy key
        key = {
            'clientId': 'client_id',
            'userAgent': 'user_agent',
            'scope': util.scopes_to_string(scopes)
        }
        store = multistore_file.get_credential_storage_custom_key(
            FILENAME, key)
        stored_credentials = store.get()

        self.assertEqual(credentials.access_token,
                         stored_credentials.access_token)
Пример #43
0
    def test_multistore_file(self):
        credentials = self.create_test_credentials()

        store = multistore_file.get_credential_storage(
            FILENAME, credentials.client_id, credentials.user_agent,
            ['some-scope', 'some-other-scope'])

        store.put(credentials)
        credentials = store.get()

        self.assertNotEquals(None, credentials)
        self.assertEquals('foo', credentials.access_token)

        store.delete()
        credentials = store.get()

        self.assertEquals(None, credentials)

        if os.name == 'posix':
            self.assertEquals('0o600',
                              oct(stat.S_IMODE(os.stat(FILENAME).st_mode)))
Пример #44
0
  def test_multistore_file(self):
    credentials = self.create_test_credentials()

    store = multistore_file.get_credential_storage(
        FILENAME,
        credentials.client_id,
        credentials.user_agent,
        ['some-scope', 'some-other-scope'])

    store.put(credentials)
    credentials = store.get()

    self.assertNotEquals(None, credentials)
    self.assertEqual('foo', credentials.access_token)

    store.delete()
    credentials = store.get()

    self.assertEqual(None, credentials)

    if os.name == 'posix':
      self.assertEqual('0o600', oct(stat.S_IMODE(os.stat(FILENAME).st_mode)))
Пример #45
0
def test_setupAuth():
    # create initial file
    assert os.path.exists('/tmp/cloudprint.conf') == False
    assert Auth.SetupAuth(False) == False
    assert os.path.exists('/tmp/cloudprint.conf') == True
    
    # add dummy details
    storage = multistore_file.get_credential_storage(
        Auth.config,
        Auth.clientid,
        'testuseraccount',
        ['https://www.googleapis.com/auth/cloudprint'])
    
    credentials = client.OAuth2Credentials('test', Auth.clientid,
                               'testsecret', 'testtoken', 1,
                               'https://www.googleapis.com/auth/cloudprint', 'testaccount1')
    storage.put(credentials)
    
    # re-run to test getting credentials
    requestors, storage = Auth.SetupAuth(False)
    assert requestors != None
    assert storage != None
Пример #46
0
def oauth2callback():
    error = request.args.get('error', '')
    if error:
        return jsonify({'error': error})

    try:
        credentials = flow.step2_exchange(code=request.args)
        user = credentials.id_token['email']
        store = get_credential_storage(credential_store,
                                       user,
                                       oauth_app_creds['user_agent'],
                                       oauth_app_creds['scope'])
        old_credentials = store.get()
        if old_credentials:
            ort = old_credentials.refresh_token
            nrt = old_credentials.refresh_token
            credentials.refresh_token = ort if not nrt else nrt

        # Check that the credentials we have are correct before writing them out to storage
        http = httplib2.Http()
        http = credentials.authorize(http)
        credentials.refresh(http)

        # Clean up old credentials before writing new ones.
        # For some reason it sometimes ends up with duplicates?
        store.delete()
        store.put(credentials)

    except Exception as e:
        if 'invalid_grant' in e.message:
            code = 500
        else:
            code = 400
        return jsonify({'error': e.message}), code

    session['user'] = user
    if 'redirect' in session and session['redirect']:
        return redirect('/process', code=301)
    return redirect('/login', code=301)
Пример #47
0
    if FLAGS.auth_service_account and metadata_present:
        try:
            return auto_auth.Credentials(metadata,
                                         FLAGS.auth_service_account,
                                         scopes,
                                         any_available=True)
        except auto_auth.CredentialsNotPresentError, e:
            pass
        except auto_auth.CredentialsError, e:
            # We failed to get the scopes from the metadata server.
            if logger:
                logger.warn(
                    'Failed to automatically authenticate with service '
                    'account: %s' % (e))

    storage = oauth2_multistore_file.get_credential_storage(
        credentials_file, client_id, user_agent, scopes_str)

    credentials = storage.get()

    if force_reauth and credentials:
        credentials.invalid = True
    if (not credentials or credentials.invalid == True) and ask_user:

        if FLAGS.auth_service_account and metadata_present:
            print(
                'Service account scopes are not enabled for %s on this instance. '
                'Using manual authentication.') % (FLAGS.auth_service_account)

        flow = oauth2_client.OAuth2WebServerFlow(
            client_id=client_id,
            client_secret=client_secret,
Пример #48
0
    def SetupAuth(interactive=False, permissions=None, testUserIds=None):
        """Sets up requestors with authentication tokens

        Args:
          interactive: boolean, when set to true can prompt user, otherwise
                       returns False if authentication fails

        Returns:
          requestor, storage: Authenticated requestors and an instance
                              of storage
        """
        if permissions is None:
            permissions = Auth.normal_permissions
        modifiedconfig = False

        # parse config file and extract useragents, which we use for account
        # names
        userids = []
        if testUserIds is not None:
            userids = testUserIds
        if os.path.exists(Auth.config):
            data = json.loads(Utils.ReadFile(Auth.config))
            if 'data' in data:
                for user in data['data']:
                    userids.append(str(user['credential']['user_agent']))
        else:
            Utils.WriteFile(Auth.config, '{}')
            Utils.FixFilePermissions(Auth.config)
            modifiedconfig = True

        if len(userids) == 0:
            userids = [None]

        requestors = []
        storage = None
        credentials = None
        for userid in userids:
            if userid is not None:
                storage = multistore_file.get_credential_storage(
                    Auth.config, Auth.clientid, userid, permissions)
                credentials = storage.get()

            if not credentials and interactive:
                credentials = Auth.AddAccount(storage, userid, permissions)
                modifiedconfig = True
                if userid is None:
                    userid = credentials.user_agent

            if credentials:
                # renew if expired
                requestor = CloudPrintRequestor()
                if credentials.access_token_expired:
                    Auth.RenewToken(interactive, requestor, credentials,
                                    storage, userid)
                requestor = credentials.authorize(requestor)
                requestor.setAccount(userid)
                requestors.append(requestor)

        # fix permissions
        if modifiedconfig:
            Utils.FixFilePermissions(Auth.config)

        if not credentials:
            return False, False
        else:
            return requestors, storage
Пример #49
0
  def WriteTemplate(self):
    """Write the credential file."""

    # straight up credentials in JSON
    self._WriteFileContents(self._json_path,
                            self.credentials.to_json())
    # multistore version
    self._WriteFileContents(self._multistore_path, '')
    storage = oauth2_multistore_file.get_credential_storage(
        self._multistore_path,
        self.credentials.client_id,
        self.credentials.user_agent,
        self.scopes)
    storage.put(self.credentials)

    if self.credentials.refresh_token:
      # gae java wants something special
      self._WriteFileContents(self._gae_java_path, textwrap.dedent("""\
          oauth2_client_secret: {secret}
          oauth2_client_id: {id}
          oauth2_refresh_token: {token}
          """).format(secret=config.CLOUDSDK_CLIENT_NOTSOSECRET,
                      id=config.CLOUDSDK_CLIENT_ID,
                      token=self.credentials.refresh_token))

      # we create a small .boto file for gsutil, to be put in BOTO_PATH
      self._WriteFileContents(self._gsutil_path, textwrap.dedent("""\
          [Credentials]
          gs_oauth2_refresh_token = {token}
          """).format(token=self.credentials.refresh_token))

    if (oauth2_client.HAS_CRYPTO and
        type(self.credentials) == oauth2_client.SignedJwtAssertionCredentials):
      with files.OpenForWritingPrivate(self._key_path) as pk:
        pk.write(base64.b64decode(self.credentials.private_key))
      # the .boto file gets some different fields
      self._WriteFileContents(self._gsutil_path, textwrap.dedent("""\
          [Credentials]
          gs_service_client_id = {account}
          gs_service_key_file = {key_file}
          gs_service_key_file_password = {key_password}
          """).format(account=self.credentials.service_account_name,
                      key_file=self._key_path,
                      key_password=self.credentials.private_key_password))

    # pylint: disable=protected-access
    # Remove linter directive when
    # https://github.com/google/oauth2client/issues/165 is addressed.
    if isinstance(self.credentials,
                  oauth2_service_account._ServiceAccountCredentials):
      # TODO(cherba): Currently activate-service-account discards the JSON
      # key file after reading it; save it so that we can hand it to gsutil.
      # For now, serialize the credentials back to their original
      # JSON key file form.
      json_key_dict = {
          'client_id': self.credentials._service_account_id,
          'client_email': self.credentials._service_account_email,
          'private_key': self.credentials._private_key_pkcs8_text,
          'private_key_id': self.credentials._private_key_id,
          'type': 'service_account'
      }
      with files.OpenForWritingPrivate(self._json_key_path) as pk:
        pk.write(json.dumps(json_key_dict))
      self._WriteFileContents(self._gsutil_path, textwrap.dedent("""\
          [Credentials]
          gs_service_key_file = {key_file}
          """).format(key_file=self._json_key_path))
Пример #50
0
    def WriteTemplate(self):
        """Write the credential file."""

        # straight up credentials in JSON
        self._WriteFileContents(self._json_path, self.credentials.to_json())
        # multistore version
        self._WriteFileContents(self._multistore_path, '')
        storage = oauth2_multistore_file.get_credential_storage(
            self._multistore_path, self.credentials.client_id,
            self.credentials.user_agent, self.scopes)
        storage.put(self.credentials)

        if self.credentials.refresh_token:
            # gae java wants something special
            self._WriteFileContents(
                self._gae_java_path,
                textwrap.dedent("""\
          oauth2_client_secret: {secret}
          oauth2_client_id: {id}
          oauth2_refresh_token: {token}
          """).format(secret=config.CLOUDSDK_CLIENT_NOTSOSECRET,
                      id=config.CLOUDSDK_CLIENT_ID,
                      token=self.credentials.refresh_token))

            # we create a small .boto file for gsutil, to be put in BOTO_PATH
            self._WriteFileContents(
                self._gsutil_path,
                textwrap.dedent("""\
          [Credentials]
          gs_oauth2_refresh_token = {token}
          """).format(token=self.credentials.refresh_token))

        if (oauth2_client.HAS_CRYPTO and type(self.credentials)
                == oauth2_client.SignedJwtAssertionCredentials):
            with files.OpenForWritingPrivate(self._key_path) as pk:
                pk.write(base64.b64decode(self.credentials.private_key))
            # the .boto file gets some different fields
            self._WriteFileContents(
                self._gsutil_path,
                textwrap.dedent("""\
          [Credentials]
          gs_service_client_id = {account}
          gs_service_key_file = {key_file}
          gs_service_key_file_password = {key_password}
          """).format(account=self.credentials.service_account_name,
                      key_file=self._key_path,
                      key_password=self.credentials.private_key_password))

        # pylint: disable=protected-access
        # Remove linter directive when
        # https://github.com/google/oauth2client/issues/165 is addressed.
        if isinstance(self.credentials,
                      oauth2_service_account._ServiceAccountCredentials):
            # TODO(cherba): Currently activate-service-account discards the JSON
            # key file after reading it; save it so that we can hand it to gsutil.
            # For now, serialize the credentials back to their original
            # JSON key file form.
            json_key_dict = {
                'client_id': self.credentials._service_account_id,
                'client_email': self.credentials._service_account_email,
                'private_key': self.credentials._private_key_pkcs8_text,
                'private_key_id': self.credentials._private_key_id,
                'type': 'service_account'
            }
            with files.OpenForWritingPrivate(self._json_key_path) as pk:
                pk.write(json.dumps(json_key_dict))
            self._WriteFileContents(
                self._gsutil_path,
                textwrap.dedent("""\
          [Credentials]
          gs_service_key_file = {key_file}
          """).format(key_file=self._json_key_path))
Пример #51
0
    def SetupAuth(interactive=False,
                  permissions=['https://www.googleapis.com/auth/cloudprint']):
        """Sets up requestors with authentication tokens

        Args:
          interactive: boolean, when set to true can prompt user, otherwise returns False if authentication fails

        Returns:
          requestor, storage: Authenticated requestors and an instance of storage
        """
        modifiedconfig = False

        # parse config file and extract useragents, which we use for account names
        userids = []
        if os.path.exists(Auth.config):
            content_file = open(Auth.config, 'r')
            content = content_file.read()
            data = json.loads(content)
            for user in data['data']:
                userids.append(str(user['credential']['user_agent']))
        else:
            modifiedconfig = True

        if len(userids) == 0:
            userids = [None]

        requestors = []
        for userid in userids:
            storage = multistore_file.get_credential_storage(
                Auth.config, Auth.clientid, userid, permissions)
            credentials = storage.get()

            if not credentials and interactive:
                credentials = Auth.AddAccount(storage, userid)
                modifiedconfig = True
                if userid == None:
                    userid = credentials.user_agent

            if credentials:
                # renew if expired
                requestor = cloudprintrequestor()
                if credentials.access_token_expired:
                    from oauth2client.client import AccessTokenRefreshError
                    try:
                        credentials.refresh(requestor)
                    except AccessTokenRefreshError as e:
                        sys.stderr.write(
                            "Failed to renew token (error: " + str(e) +
                            "), if you have revoked access to CUPS Cloud Print in your Google Account, please delete /etc/cloudprint.conf and re-run /usr/share/cloudprint-cups/setupcloudprint.py\n"
                        )
                        sys.exit(1)

                requestor = credentials.authorize(requestor)
                requestor.setAccount(userid)
                requestors.append(requestor)

        # fix permissions
        if modifiedconfig:
            Utils.FixFilePermissions(Auth.config)

        if not credentials:
            return False, False
        else:
            return requestors, storage
Пример #52
0
def GetCredentialFromStore(desired_scopes,
                           ask_user=True,
                           force_reauth=False,
                           credentials_file=None,
                           authorization_uri_base=None,
                           client_id=OAUTH2_CLIENT_ID,
                           client_secret=OAUTH2_CLIENT_SECRET,
                           user_agent=USER_AGENT,
                           metadata=metadata_lib.Metadata(),
                           oauth2_gce=oauth2_gce_client,
                           logger=None):
    """Get OAuth2 credentials for a specific scope.

  Args:
    desired_scopes: A list of OAuth2 scopes to request.
    ask_user: If True, prompt the user to authenticate.
    force_reauth: If True, force users to reauth
    credentials_file: The file to use to get/store credentials. If left at None
      FLAGS.credentials_file will be used.
    authorization_uri_base: The base URI for auth requests. If left at None
      FLAGS.authorization_uri_base will be used.
    client_id: The OAuth2 client id
    client_secret: The OAuth2 client secret
    user_agent: The user agent for requests

  Returns:
    An OAuth2Credentials object or None
  """
    if not credentials_file:
        credentials_file = FLAGS.credentials_file
    if not authorization_uri_base:
        authorization_uri_base = FLAGS.authorization_uri_base

    credentials_file = os.path.realpath(os.path.expanduser(credentials_file))

    # Ensure that the directory to contain the credentials file exists.
    credentials_dir = os.path.expanduser(os.path.dirname(credentials_file))
    if not os.path.exists(credentials_dir):
        os.makedirs(credentials_dir)

    desired_scopes = [
        'https://www.googleapis.com/auth/userinfo.email',
        'https://www.googleapis.com/auth/cloud-platform',
        'https://www.googleapis.com/auth/appengine.admin',
        'https://www.googleapis.com/auth/compute'
    ]
    desired_scopes_str = ' '.join(desired_scopes)

    metadata_present = False
    if FLAGS.auth_service_account:
        metadata_present = metadata.IsPresent()

    storage = oauth2_multistore_file.get_credential_storage(
        credentials_file, client_id, user_agent, desired_scopes_str)

    if FLAGS.auth_service_account and metadata_present:
        try:
            vm_scopes = metadata.GetServiceAccountScopes()
            # Only use gce auth if there is a compute scope in there.
            if (scopes.COMPUTE_RW_SCOPE in vm_scopes
                    or scopes.COMPUTE_RO_SCOPE in vm_scopes
                    or scopes.CLOUD_PLATFORM_SCOPE in vm_scopes):
                try:
                    credentials = oauth2_gce.AppAssertionCredentials([])
                    credentials.refresh(utils.GetHttp())
                    http = credentials.authorize(utils.GetHttp())
                    resp, content = http.request(
                        'https://www.googleapis.com/userinfo/v2/me')
                    if resp.status == 200:
                        userinfo = json.loads(content)
                        credentials.token_id = userinfo
                    storage.put(credentials)
                    return credentials
                except httplib2.ServerNotFoundError:
                    # We are not running on a VM.
                    pass
                except oauth2_client.AccessTokenRefreshError:
                    # We are probably not running on a VM.
                    pass
        except metadata_lib.MetadataError:
            # We don't seem to have any scopes.
            pass

    credentials = storage.get()

    if not credentials or credentials.invalid:
        # Look for the legacy auth scopes, in case they're present, we can use
        # them instead.
        legacy_desired_scopes_str = ' '.join(sorted(scopes.LEGACY_AUTH_SCOPES))
        legacy_storage = oauth2_multistore_file.get_credential_storage(
            credentials_file, client_id, user_agent, legacy_desired_scopes_str)
        credentials = legacy_storage.get()

    if force_reauth and credentials:
        credentials.invalid = True

    if (not credentials or credentials.invalid == True) and ask_user:
        if FLAGS.auth_service_account and metadata_present:
            print(
                'Service account scopes are not enabled for %s on this instance. '
                'Using manual authentication.') % (FLAGS.auth_service_account)

        # If gcutil is being run from within the Cloud SDK, do not do the web flow.
        # Instead, print out a message indicating that the user must log in via
        # "gcloud auth login".
        if os.environ.get('CLOUDSDK_WRAPPER', '0') == '1':
            msg = textwrap.dedent("""\
      You are not currently logged in. To authenticate, run
       $ gcloud auth login
      """)
            sys.stderr.write(msg)
            sys.exit(1)

        flow = oauth2_client.OAuth2WebServerFlow(
            client_id=client_id,
            client_secret=client_secret,
            scope=desired_scopes_str,
            user_agent=user_agent,
            auth_uri=authorization_uri_base + '/auth',
            token_uri=authorization_uri_base + '/token')
        credentials = oauth2_tools.run(flow, storage, http=utils.GetHttp())
    return credentials