salsbury
salsbury

Reputation: 2803

Can I limit the available scopes on a Google API service account?

I have done the following:

  1. Created a project in Google API console
  2. Enabled the Google Drive API in the project
  3. Created a service account
  4. Shared a Google Drive folder with the service account
  5. Connected successfully to Google Drive and retrieved the list of folders and files shared with the service account.

When you create an OAuth client ID, you can limit that to predefined scopes. As far as I can tell, the service account has access to any Google Drive scope. I wanted to tighten that down to the following scope: https://www.googleapis.com/auth/drive.readonly just as a reassurance that there's no way the Google Drive app I'm making unintentionally adds/edits/deletes any files.

I know I can add the account to different roles. However, I looked through the list multiple times and none of them are related to Google Drive. I attempted to make my own role, but the available permissions on that screen do not reference Google Drive either. It's possible I missed something or there's another place I could look. Any suggestions?

Upvotes: 0

Views: 1523

Answers (1)

Nikko J.
Nikko J.

Reputation: 5543

To limit the scope a Service Account, you have to specify the scope on the server-side.

Service accounts are special Google accounts that can be used by applications to access Google APIs programmatically via OAuth 2.0. A service account uses an OAuth 2.0 flow that does not require human authorization. Instead, it uses a key file that only your application can access.

For example:

In python, you can specify the scope of a service account by creating a list of scopes and use it as parameter when getting the credentials.

Folder and Files:

enter image description here

python:

Search all image with jpeg extension:

import httplib2
import os
from apiclient import discovery
from google.oauth2 import service_account


scopes = ["https://www.googleapis.com/auth/drive.readonly"]
secret_file = os.path.join(os.getcwd(), 'client_secret.json')
credentials = service_account.Credentials.from_service_account_file(secret_file, scopes=scopes)
service = discovery.build('drive', 'v3', credentials=credentials)
page_token = None
while True:
    response = service.files().list(q="mimeType='image/jpeg'",
                                          spaces='drive',
                                          fields='nextPageToken, files(id, name)',
                                          pageToken=page_token).execute()
    for file in response.get('files', []):
        # Process change
        print('Found file: %s' % (file.get('name')))
    page_token = response.get('nextPageToken', None)
    if page_token is None:
        break

Output:

Found file: cute-puppy.jpg

Creating folder with readonly scope:

import httplib2
import os
from apiclient import discovery
from google.oauth2 import service_account

scopes = ["https://www.googleapis.com/auth/drive.readonly"]
secret_file = os.path.join(os.getcwd(), 'client_secret.json')
credentials = service_account.Credentials.from_service_account_file(secret_file, scopes=scopes)
service = discovery.build('drive', 'v3', credentials=credentials)

file_metadata = {
    'name': 'Invoices',
    'mimeType': 'application/vnd.google-apps.folder'
}
file = service.files().create(body=file_metadata,
                                    fields='id').execute()

Error message:

<HttpError 403 when requesting https://www.googleapis.com/drive/v3/files?fields=id&alt=json returned "Insufficient Permission: Request had insufficient authentication scopes.". Details: "Insufficient Permission: Request had insufficient authentication scopes.">

References:

Upvotes: 0

Related Questions