Reputation: 1481
I am running the quickstart.py example code under Python Quickstart and I am getting the following error:
ValueError: Client secrets must be for a web or installed app.
I created a credentials.json
file with project owner rights.
The error occurs in the following piece of code:
if os.path.exists('token.pickle'):
with open('token.pickle', 'rb') as token:
creds = pickle.load(token)
# 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()
# Save the credentials for the next run
with open('token.pickle', 'wb') as token:
pickle.dump(creds, token)
I notice also that the token.pickle file is not being created. This is the error output:
File "updateSlidev01.py", line 51, in <module>
main()
File "updateSlidev01.py", line 31, in main
flow = InstalledAppFlow.from_client_secrets_file('credentials.json', SCOPES)
File "/Library/Python/2.7/site-packages/google_auth_oauthlib/flow.py", line 174, in from_client_secrets_file
return cls.from_client_config(client_config, scopes=scopes, **kwargs)
File "/Library/Python/2.7/site-packages/google_auth_oauthlib/flow.py", line 147, in from_client_config
'Client secrets must be for a web or installed app.')
ValueError: Client secrets must be for a web or installed app.
Upvotes: 61
Views: 60508
Reputation: 17778
Posting this for others, the issue would be downloading the wrong type of keys. You will see this error if you download the 'Service Accounts' keys rather than the 'OAuth 2.0 Client IDs'.
To resolve the error:
Rename the file into credentials.json, and you should be able to run the gmail/quickstart/quickstart.py code provided by google. For reference, as of 8 July 2024, for reference, this is a snippet of the code:
import os
import google.auth
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
SCOPES = ["https://www.googleapis.com/auth/gmail.readonly"]
def main():
creds = None
if os.path.exists("token.json"):
creds = Credentials.from_authorized_user_file("token.json", SCOPES)
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)
with open("token.json", "w") as token:
token.write(creds.to_json())
try:
service = build("gmail", "v1", credentials=creds)
results = service.users().labels().list(userId="me").execute()
labels = results.get("labels", [])
if not labels:
print("No labels found.")
return
print("Labels:")
for label in labels:
print(label["name"])
except HttpError as error:
print(f"An error occurred: {error}")
main()
You should a message in the following lines:
Please visit this URL to authorize this application: https://accounts.google.com/o/oauth2/auth?response_type=code&client_id=[...]&access_type=offline
Upvotes: -1
Reputation: 13
In my case credentials.json
file had wrong keys names.
File looked like this:
{"SCc":{"client_id":"****","project_id":"****","wnc":"****","dVc":"****","vnc":"****","p2a":"****","kNc":["http://localhost"]}}
I changed it to:
{"installed":{"client_id":"****","project_id":"****","auth_uri":"****","token_uri":"****","auth_provider_x509_cert_url":"****","client_secret":"****","redirect_uris":["http://localhost"]}}
And works fine.
Upvotes: 1
Reputation: 1481
The problem was that I was using the json generated under Service account keys Manage service accounts and not the one under OAuth 2.0 client IDs.
Follow this instructor for creating oauth client id. https://developers.google.com/workspace/guides/create-credentials#oauth-client-id
Upvotes: 53
Reputation: 16319
For anyone coming here because they would like to actually connect to the GCP calendar API via a service-account and not this Oauth2 client id, create the creds
object in the original example as follows:
from google.oauth2 import service_account
SCOPES = ['https://www.googleapis.com/auth/calendar.readonly']
SERVICE_ACCOUNT_FILE = '/path/to/service.json'
credentials = service_account.Credentials.from_service_account_file(
SERVICE_ACCOUNT_FILE, scopes=SCOPES)
Assuming the service-account is configured with the correct access, this will access the calendar without prompting user for confirmation.
Upvotes: 67