Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Google API Python | ValueError: Authorized user info was not in the expected format, missing fields client_secret, client_id, refresh_token

Traceback (most recent call last):
    creds = Credentials.from_authorized_user_file('credent.json', SCOPES)
  File "C:\Users\WINDOWS\AppData\Local\Programs\Python\Python310\lib\site-packages\google\oauth2\credentials.py", line 440, in from_authorized_user_file
    return cls.from_authorized_user_info(data, scopes)
  File "C:\Users\WINDOWS\AppData\Local\Programs\Python\Python310\lib\site-packages\google\oauth2\credentials.py", line 390, in from_authorized_user_info
    raise ValueError(
ValueError: Authorized user info was not in the expected format, missing fields client_secret, client_id, refresh_token.

I created an OAuth Client ID, set the application type there to Desktop App, downloaded the json file, then tried to login (code below) and got an error, I entered the file, it is in this order (example below), later I removed 'installed' from json , the error is different now ValueError: Authorized user info was not in the expected format, missing fields refresh_token.

JSON EXAMPLE

{"installed":
    {"client_id": "client_id_my",
    "project_id": "projectname123",
    "auth_uri": "https://accounts.google.com/o/oauth2/auth",
    "token_uri": "https://oauth2.googleapis.com/token",
    "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
    "client_secret": "SECRET",
    "redirect_uris": ["http://localhost"]}
}
import os.path

from google.oauth2.credentials import Credentials
SCOPES = ['https://www.googleapis.com/auth/classroom.courses.readonly']


creds = Credentials.from_authorized_user_file('credent.json', SCOPES)
like image 804
Azazel Avatar asked Sep 20 '25 08:09

Azazel


2 Answers

I hope this answer works for you or someone in the futures. When the documentation shows the line of code: creds = Credentials.from_authorized_user_file('token.json', SCOPES) is a bit confusing, given the fact that they just made you download a json file.

However, one shouldn't assume to use that file that contains the client ID and secret. At the Run the sample section almost at the end the second point states:

2. The first time you run the sample, it prompts you to authorize access: If you're not already signed in to your Google Account, you're prompted to sign in. If you're signed in to multiple accounts, select one account to use for authorization. Click Accept. Authorization information is stored in the file system, so the next time you run the sample code, you aren't prompted for authorization.

Therefore, please run the script without any json file the first time, you will be redirected to an authentication and authorization website by Google. After accepting and shown that you may close that tab/window, you will see the token.json file so the next time you don't need to thru it all again.

In sum, the downloaded file in the Authorize credentials for a desktop application is not the same json file needed in the code. You will get that one after running the script without any json file.

like image 141
Daniel Sanchez Avatar answered Sep 22 '25 02:09

Daniel Sanchez


The error message you are facing is related to the missing token.json file. This file is created automatically using the credentials.json file (In your case I think it is called credent.json based on your code snippet.)

So instead of calling the credentials.json file as your are doing in this part of the code:

SCOPES = ['https://www.googleapis.com/auth/classroom.courses.readonly']


creds = Credentials.from_authorized_user_file('credent.json', SCOPES)

You need to call the token file that is created after the authorization flow is completed. The authorization flow is this part of the sample below:

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

Once the code is created, and stored. You can create the creds (the credentials use for building the services) like this:

SCOPES = ['https://www.googleapis.com/auth/classroom.courses.readonly']


creds = Credentials.from_authorized_user_file('token.json', SCOPES)

Note: You can either rename your credential file to credentials.json or you can replace the sample code with the name of your JSON file.

This is a sample code based on the Google Documentation here.

Taking that sample as base, it should be something like this:


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/classroom.courses.readonly']


def main():
    """Shows basic usage of the Classroom API.
    Prints the names of the first 10 courses 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('classroom', 'v1', credentials=creds)

        # Here you will add whatever method you want to use. 

    except HttpError as error:
        print('An error occurred: %s' % error)


if __name__ == '__main__':
    main()

Reference:

  • Google Documentation "Python quickstart"
  • Get an OAuth2 Refresh Token and Configure Your Client
like image 26
Giselle Valladares Avatar answered Sep 22 '25 02:09

Giselle Valladares