Reputation: 121
I am trying to create a google credentials object to access google drive. I have the tokens and user data stored in a session thus I am trying to create the object without loading them from a credentials.json file. I am handling the authentication when a user first logs in the web app and storing the tokens inside the user session, the session has a time out of 24 hours same as the default access token thus after 24 hours the user is requested to log in again so a new session with a valid access token is created. So my idea is to reuse the access token to limit the amount of log ins and improve user experience.
This is a small piece of code on how I'm trying to create the google credentials object
from oauth2client.client import GoogleCredentials
access_token = request.session['access_token']
gCreds = GoogleCredentials(
access_token,
os.getenv('GOOGLE_CLIENT_ID'),
os.getenv('GOOGLE_CLIENT_SECRET'),
refresh_token=None,
token_expiry=None,
token_uri=GOOGLE_TOKEN_URI,
user_agent='Python client library',
revoke_uri=None)
build('drive', 'v3', credentials = gCred)
Whenever I try to run this code I get the following error:
Insufficient Permission: Request had insufficient authentication scopes.". Details: "[{'domain': 'global', 'reason': 'insufficientPermissions', 'message': 'Insufficient Permission: Request had insufficient authentication scopes.'}]"
{
"error": {
"errors": [
{
"domain": "usageLimits",
"reason": "dailyLimitExceededUnreg",
"message": "Daily Limit for Unauthenticated Use Exceeded. Continued use requires signup.",
"extendedHelp": "https://code.google.com/apis/console"
}
],
"code": 403,
"message": "Daily Limit for Unauthenticated Use Exceeded. Continued use requires signup."
}
}
Upvotes: 5
Views: 2101
Reputation: 121
The object was build correctly, there was no issue with building the object this way
access_token = request.session['access_token']
gCreds = GoogleCredentials(
access_token,
os.getenv('GOOGLE_CLIENT_ID'),
os.getenv('GOOGLE_CLIENT_SECRET'),
refresh_token=None,
token_expiry=None,
token_uri=GOOGLE_TOKEN_URI,
user_agent='Python client library',
revoke_uri=None)
build('drive', 'v3', credentials = gCred)
The problem was caused at an earlier stage, when registering the scopes
oauth = OAuth(config)
oauth.register(
name='google',
server_metadata_url='',
client_kwargs={
'scope': 'openid email profile https://www.googleapis.com/auth/drive.readonly'
}
)
Upvotes: 1
Reputation: 117146
So what are scopes. Scopes define the access that you are requesting from the user. In this case you want to access their Google drive account, but how much access do you need depends upon the methods you will be using.
If you are just using file.list then you could request a read only scope as your not going to be writing anything.
https://www.googleapis.com/auth/drive.readonly
Yet if your going to use file.create well your going to need a write scope. You need permission to write to their google account
https://www.googleapis.com/auth/drive
I cant see from your code how you are handling the authorization at all. So Lets start by looking at the official google drive python sample
In the code below notice how they call
InstalledAppFlow.from_client_secrets_file(
'credentials.json', SCOPES)
And define the scopes of access they would like to request.
from __future__ import print_function
import os.path
from google.auth.transport.requests import Request
from google.oauth2.credentials import Credentials
from google_auth_oauthlib.flow import InstalledAppFlow
from googleapiclient.discovery import build
from googleapiclient.errors import HttpError
# If modifying these scopes, delete the file token.json.
SCOPES = ['https://www.googleapis.com/auth/drive.metadata.readonly']
def main():
"""Shows basic usage of the Drive v3 API.
Prints the names and ids of the first 10 files the user has access to.
"""
creds = None
# The file token.json stores the user's access and refresh tokens, and is
# created automatically when the authorization flow completes for the first
# time.
if os.path.exists('token.json'):
creds = Credentials.from_authorized_user_file('token.json', SCOPES)
# If there are no (valid) credentials available, let the user log in.
if not creds or not creds.valid:
if creds and creds.expired and creds.refresh_token:
creds.refresh(Request())
else:
flow = InstalledAppFlow.from_client_secrets_file(
'credentials.json', SCOPES)
creds = flow.run_local_server(port=0)
# Save the credentials for the next run
with open('token.json', 'w') as token:
token.write(creds.to_json())
try:
service = build('drive', 'v3', credentials=creds)
# Call the Drive v3 API
results = service.files().list(
pageSize=10, fields="nextPageToken, files(id, name)").execute()
items = results.get('files', [])
if not items:
print('No files found.')
return
print('Files:')
for item in items:
print(u'{0} ({1})'.format(item['name'], item['id']))
except HttpError as error:
# TODO(developer) - Handle errors from drive API.
print(f'An error occurred: {error}')
if __name__ == '__main__':
main()
The error message
Request had insufficient authentication scopes.". Details: "[{'domain': 'global', 'reason': 'insufficientPermissions', 'message': 'Insufficient Permission: Request had insufficient authentication scopes.'}]"> successfully connected to drive
Actually means that you have requsted one scope from the user lets say read only yet you are trying to use it with a method that requires write access. So your request has insufficient authentication scopes.
Fix your code to request the proper scope delete the refresh token you have now and request authorization of the user again with the proper scope.
Upvotes: 3