0
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)
Azazel
  • 27
  • 8

2 Answers2

0

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:

Giselle Valladares
  • 2,075
  • 1
  • 4
  • 13
  • I will say this, no files are created, I have credentials.json, and the documentation says that you need to download this file, and I did everything as it says in the documentation, I even copied the code - it did not work. – Azazel Mar 02 '23 at 05:09
  • @Azazel, have you store the `credentials.json` file in the same directory as the `*.py` file? Also, when you run the `*.py` with the authorization flow on it. Do you get a message or redirection to the browser to sign-in? Did you Install the Google client library for Python? You should install `pip install --upgrade google-api-python-client`, `pip install --upgrade google-auth-httplib2` and `pip install --upgrade google-auth-oauthlib`. – Giselle Valladares Mar 02 '23 at 12:03
  • Forgot to mention, if you keep the name of the JSON as `'credent.json'` you will need to change this part `flow = InstalledAppFlow.from_client_secrets_file('credentials.json', SCOPES)` to `flow = InstalledAppFlow.from_client_secrets_file('credent.json', SCOPES)`. – Giselle Valladares Mar 02 '23 at 12:10
  • I made sure, I changed everything as needed, I described everything. It seems to me that this is a problem with the library itself, I solved the problem by removing 'installed' in credent.json, and adding 'refresh_token' to json: '' – Azazel Mar 02 '23 at 13:02
0

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.