Expected OAuth 2 access token, login cookie or other valid authentication credential for ml.googleapis.com

Viewed 9121

I am running this code from my laptop. I want to call a tensorlflow model which is on GCP. I try to simulate an API call from our systems to GCP.

from oauth2client.client import GoogleCredentials
import requests
import json

PROJECT = 'blabla-project'
MODEL_NAME = 'blablaModelName'
MODEL_VERSION = 'blabla_version'

token=GoogleCredentials.get_application_default().get_access_token().access_token
api = 'https://ml.googleapis.com/v1/projects/{}/models/{}/versions/{}:predict' \
     .format(PROJECT, MODEL_NAME, MODEL_VERSION)
headers = {'Authorization': 'Bearer ' + token}
data = {
'instances': [
 {
    'X1':600,
    'X2':8965,
    'X3':17.93,
    'X4':23,
    'X5':52216.32776,
    'X6':144.2442343,
    'X7':0,
    'X8':0,
    'X9':0,
    'X10':0
},
{
    'X1':600,
    'X2':6965,
    'X3':17.93,
    'X4':23,
    'X5':52216.32776,
    'X6':144.2442343,
    'X7':0,
    'X8':0,
    'X9':0,
    'X10':0
},
]
}
response = requests.post(api, json=data,headers=headers)
print(response)
print(response.content)

At each time I run the code I have this error.

Request had invalid authentication credentials. Expected OAuth 2 access token, login cookie or other valid authentication credential.

I am using python 3.8.3 on Windows.

Can anyone tell me where the code is broken or which authentication method should I use.

1 Answers

NOTE: OAUTH2CLIENT has been deprecated and you need to use GOOGLE-AUTH instead.

Please find your code modified below using the latest Google OAuth library:

import requests
import json
import google.auth
import google.auth.transport.requests


PROJECT = 'project-name'
MODEL_NAME = 'modelname'
MODEL_VERSION = 'version'

credentials, project_id = google.auth.default(
        scopes=['https://www.googleapis.com/auth/cloud-platform','https://www.googleapis.com/auth/cloud-platform.read-only'])

api = 'https://ml.googleapis.com/v1/projects/{}/models/{}/versions/{}:predict' \
     .format(PROJECT, MODEL_NAME, MODEL_VERSION)

request = google.auth.transport.requests.Request()
credentials.refresh(request)
token = credentials.token

headers = {'Authorization': 'Bearer ' + token}
data = {
    "instances" : [
        {
            'X1':600,...
    }
}
response = requests.post(api, json=data, headers=headers)
print(response)
print(response.content)

Instead of using get_application_default() you need to use google.auth.default and depending on the API being called, the proper scopes have to be defined in order to access the Google API’s.

I ran the same code in Google Cloud Shell and it works perfectly fine. The reason being: Google Cloud Shell runs on a Compute Engine VM which has an OAuth token already created for the logged in account and saved in the local Compute Engine VM metadata server.

As noted in the google.auth.default documentation, it detects that it is running in a Compute Engine VM and automatically uses that default OAuth token located in the VM Metadata Server.

When you run the code from your local machine, you need to make your own OAuth token accessible to the code by using one of the following authentication methods:

-- Using Service account:

  1. Create a Service Account and download a JSON key.
  2. Set the GOOGLE_APPLICATION_CREDENTIALS environment variable to the path of the downloaded service account key file (JSON).
  3. The same google.auth.default documentation code you use also checks this special environment variable for the set JSON OAuth token and uses it automatically.

-- OR using a User account:

  1. This can be achieved by running the following command to generate the token:

    gcloud auth application-default login

  2. Then remove the google.auth.default code and replace it with the output from the following command instead:

    gcloud auth application-default print-access-token

Related