Google Ads API - Service account [HTTP error 401]: "Request had invalid authentication credentials. Expected OAuth 2 access token...."
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... I keep getting a 401 error.
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
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 https://developers.google.com/identity/sign-in/web/devconsole-project.", "status": "UNAUTHENTICATED" }
I cant seem to find out why Im getting this authentication error.
What I have tried:
- Following this guide step by step -> https://developers.google.com/google-ads/api/docs/oauth/service-accounts
- Using the python library -> https://github.com/googleads/googleads-python-lib
- Using the google ads API with REST (no library)
- On localhost server
- 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.
Request had invalid authentication credentials. Expected OAuth 2 access token, login cookie or other valid authentication credential
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.
Generating the access token:
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; };
I am surely missing something, but am not sure what it is..
** NOT_ADS_USER 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, scope: 'https://www.googleapis.com/auth/adwords', aud: 'https://oauth2.googleapis.com/token', 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.