Using Service account [HTTP error 401]: “Request had invalid authentication credentials. Expected OAuth 2 access token…”

135 views
Skip to first unread message

Eylon Raymond Harari

unread,
Dec 19, 2020, 7:26:08 PM12/19/20
to AdWords API and Google Ads API Forum
Im building an app with google ads api using a service account auth flow (server to server). The problem - the auth part is not working...


Sample of the request:

const request = require('request');
 ....
 request({
   'method': 'GET', 'url': 'https://googleads.googleapis.com/v6/customers/XXXXXXXX',    
   'headers': {
     'Authorization': 'Bearer XXXXXXXX', 
     'developer-token': 'XXXXXXXX', '
     Content-Type': 'application/json' }
 }) ...

or using curl -> 

curl --location --request GET 'https://googleads.googleapis.com/v6/customers/XXXXXXXX' \ --header 'Authorization: Bearer XXXXXXXX' \ --header 'developer-token: XXXXXXXX' \ --header 'Content-Type: application/json'


[ERROR] Response from google ads api:

   "code": 401, 
   "message": "Request had invalid authentication credentials. Expected OAuth 2 access         token, login cookie or other valid authentication credential. See        
   "status": "UNAUTHENTICATED"
 }

I can't seem to find out why I'm getting this authentication error.

What I have tried:

  1. Following this guide step by step -> https://developers.google.com/google-ads/api/docs/oauth/service-accounts
  2. Using the python library -> https://github.com/googleads/googleads-python-lib
  3. Using the google ads API with REST (no library)
  4. On localhost server
  5. On the production server (the www.g-suite.com domain linked to the account)

Whatever method or environment I try, it results in the same error.

Sample of how I create the access token (nodejs) -> this part works fine:

const { google } = require('googleapis'); 

....

const getAccessToken = async () => {

    const SCOPES = ['https://www.googleapis.com/auth/adwords'];

    const authClient = new google.auth.GoogleAuth({

        keyFile: './pathtokeyfile.json',

        scopes: SCOPES,

    });

    const token = await authClient.getAccessToken();

    return token;

};

Steps I have implemented:

  • Created a google ads manager account
  • Generated a valid developer token for that account
  • Created project in Google cloud platform
  • Opened a service account inside the project
  • Created a private key for the service account
  • Granting impersonation abilities in the G Suite domain for this scope: https://www.googleapis.com/auth/adwords
  • Enabled domain-wide delegation on the service account
  • Generated the access token with the key JSON file.

I am surely missing something, but am not sure what it is..


Will be super grateful if someone can share a solution!! thanks champs 👍

Google Ads API Forum Advisor Prod

unread,
Dec 22, 2020, 2:47:44 AM12/22/20
to eyl...@gmail.com, adwor...@googlegroups.com
Hi Eylon,

Thanks for posting your concern.

Could you confirm if you tried following the instruction discussed on this document? If not, please do so and if the error persists, you can provide the following details via Reply privately to author option:
  • customer ID
  • complete request and response logs with request ID

If you haven't enabled the logging of the API transactions yet for Python client library, you can follow this guide.

Regards,
Google Logo
Ernie John Blanca Tacata
Google Ads API Team
 


ref:_00D1U1174p._5004Q29TUMy:ref

Eylon Raymond Harari

unread,
Jan 5, 2021, 2:36:01 PM1/5/21
to AdWords API and Google Ads API Forum
Hi Ernie, 
sorry for the late response. 

I have created all the process from scratch and tested, retested, and still getting the same error. 

The Reply privately to author option is disabled and I can only send a public response - Is there an address for me to send the details or can you enable this option for me?

Thanks

Eylon Raymond Harari

unread,
Jan 5, 2021, 4:14:33 PM1/5/21
to AdWords API and Google Ads API Forum
** SOLVED *** !!!

Now it's all working. 

Turns out I was not creating the token precisely the correct way. 

Here's a sample of the code I use to generate the correct access token in NodeJs:

const private_key = require('./key.json').private_key;
const token = jwt.sign(
{
iss:
SERVICE_ACCOUNT_EMAIL,
sub: GOOGLE_MMC_MANAGER_EMAIL,
exp: Math.round(Date.now() / 1000) + 3600,
iat: Math.round(Date.now() / 1000),
},
private_key,
{ algorithm: 'RS256' },
);

// console.log(token);

try {
const response = await http.post('https://oauth2.googleapis.com/token', {
grant_type: 'urn:ietf:params:oauth:grant-type:jwt-bearer',
assertion: token,
});
const accesstoken = response.data;
console.log(accesstoken);
} catch (error) {
console.log(error.data);
}
};

I was missing this part in signing the token: 
sub: GOOGLE_MMC_MANAGER_EMAIL,

GOOGLE_MMC_MANAGER_EMAIL is the email that you created the MMC account with. 


Google Ads API Forum Advisor Prod

unread,
Jan 5, 2021, 10:47:55 PM1/5/21
to eyl...@gmail.com, adwor...@googlegroups.com
Hi Eylon,

Glad to know that your service account is already working. That said, would there be any further concerns that our team can assist with?

Best regards,

Google Logo
Peter Laurence Napa Oliquino
Google Ads API Team
 


ref:_00D1U1174p._5004Q29TUMy:ref
Reply all
Reply to author
Forward
0 new messages