PaoloAgVa
PaoloAgVa

Reputation: 1481

ValueError: Client secrets must be for a web or installed app

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

Answers (4)

Online User
Online User

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:

  1. Go to the credentials page (https://console.cloud.google.com/apis/credentials).

enter image description here

  1. Click on the name of the 'OAuth 2.0 Client IDs' client, in that case that would be 'Desktop client 1' for me. Then, click on the 'Download JSON' button.

enter image description here

  1. 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()
    
  1. 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

Ben
Ben

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

PaoloAgVa
PaoloAgVa

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

Adam Hughes
Adam Hughes

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

Related Questions