I am trying to connect to google search console API using OAuth2
const {google} = require('googleapis');
const auth = new google.auth.OAuth2(
YOUR_CLIENT_ID,
YOUR_CLIENT_SECRET,
YOUR_REDIRECT_URL
);
const searchconsole = google.webmasters({ version: 'v3', auth })
console.log(searchconsole.sites.list({}))
But I get this:
'Error: No access, refresh token, API key or refresh handler callback is set.'
I can not find a solid reference to this, I read that refresh token is deprecated, is this even possible to get the list of sites from node backend without interaction on the front end?
I am trying to connect to google search console API using OAuth2
const {google} = require('googleapis');
const auth = new google.auth.OAuth2(
YOUR_CLIENT_ID,
YOUR_CLIENT_SECRET,
YOUR_REDIRECT_URL
);
const searchconsole = google.webmasters({ version: 'v3', auth })
console.log(searchconsole.sites.list({}))
But I get this:
'Error: No access, refresh token, API key or refresh handler callback is set.'
I can not find a solid reference to this, I read that refresh token is deprecated, is this even possible to get the list of sites from node backend without interaction on the front end?
Share Improve this question asked Jan 26, 2022 at 11:31 ÁlvaroÁlvaro 2,5883 gold badges30 silver badges67 bronze badges 1- I updated answer with [generateAuthUrl] . – Nikola Lukic Commented Jan 26, 2022 at 12:12
4 Answers
Reset to default 3I got this same error. Turns out I wasn't setting the token correctly.
I had created the Auth URL, gotten the tokens back in the response and stored them, as shown in the quickstart.
But I hit this error when I was trying to use them. I was doing this which was wrong and gave me the error:
oauth2Client.setCredentials(accessToken);
And getting the error.
After I found this link with a nice sample - https://googleapis.dev/nodejs/googleapis/latest/tasks/index.html#samples, I saw that you have to set the token as an object.
Like this:
oauth2Client.setCredentials(
{
access_token: accessToken
}
);
That fixed the issue for me.
This is best reference site for google api : https://googleapis.dev/nodejs/googleapis/latest/tasks/index.html#samples
Try this :
const {google} = require('googleapis');
const oauth2Client = new google.auth.OAuth2(
YOUR_CLIENT_ID,
YOUR_CLIENT_SECRET,
YOUR_REDIRECT_URL
);
// generate a url that asks permissions for webmaster ao any other google api scopes.
const scopes = [
'https://www.googleapis.com/auth/webmaster'
];
const url = oauth2Client.generateAuthUrl({
// 'online' (default) or 'offline' (gets refresh_token)
access_type: 'offline',
// If you only need one scope you can pass it as a string
scope: scopes
});
OR
Try with token:
const fs = require('fs');
const readline = require('readline');
const {google} = require('googleapis');
// If modifying these scopes, delete token.json.
const SCOPES = ['https://www.googleapis.com/auth/webmasters'];
const TOKEN_PATH = 'token.json';
// Load client secrets from a local file.
fs.readFile('credentials.json', (err, content) => {
if (err) return console.log('Error loading client secret file:', err);
// Authorize a client with credentials, then call the Google Tasks API.
authorize(JSON.parse(content), listConnectionNames);
});
function authorize(credentials, callback) {
const {client_secret, client_id, redirect_uris} = credentials.installed;
const oAuth2Client = new google.auth.OAuth2(
client_id, client_secret, redirect_uris[0]);
// Check if we have previously stored a token.
fs.readFile(TOKEN_PATH, (err, token) => {
if (err) return getNewToken(oAuth2Client, callback);
oAuth2Client.setCredentials(JSON.parse(token));
callback(oAuth2Client);
});
}
function getNewToken(oAuth2Client, callback) {
const authUrl = oAuth2Client.generateAuthUrl({
access_type: 'offline',
scope: SCOPES,
});
console.log('Authorize this app by visiting this url:', authUrl);
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
});
rl.question('Enter the code from that page here: ', (code) => {
rl.close();
oAuth2Client.getToken(code, (err, token) => {
if (err) return console.error('Error retrieving access token', err);
oAuth2Client.setCredentials(token);
// Store the token to disk for later program executions
fs.writeFile(TOKEN_PATH, JSON.stringify(token), (err) => {
if (err) return console.error(err);
console.log('Token stored to', TOKEN_PATH);
});
callback(oAuth2Client);
});
});
}
function listConnectionNames(auth) {
const service = google.people({version: 'v1', auth});
// ....
}
I think you should conslult the google drive quickstart it will show you how to set up authorization.
const fs = require('fs');
const readline = require('readline');
const {google} = require('googleapis');
// If modifying these scopes, delete token.json.
const SCOPES = ['https://www.googleapis.com/auth/webmasters'];
// 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.
const TOKEN_PATH = 'token.json';
// Load client secrets from a local file.
fs.readFile('credentials.json', (err, content) => {
if (err) return console.log('Error loading client secret file:', err);
// Authorize a client with credentials, then call the Google Drive API.
authorize(JSON.parse(content), listFiles);
});
/**
* Create an OAuth2 client with the given credentials, and then execute the
* given callback function.
* @param {Object} credentials The authorization client credentials.
* @param {function} callback The callback to call with the authorized client.
*/
function authorize(credentials, callback) {
const {client_secret, client_id, redirect_uris} = credentials.installed;
const oAuth2Client = new google.auth.OAuth2(
client_id, client_secret, redirect_uris[0]);
// Check if we have previously stored a token.
fs.readFile(TOKEN_PATH, (err, token) => {
if (err) return getAccessToken(oAuth2Client, callback);
oAuth2Client.setCredentials(JSON.parse(token));
callback(oAuth2Client);
});
}
/**
* Get and store new token after prompting for user authorization, and then
* execute the given callback with the authorized OAuth2 client.
* @param {google.auth.OAuth2} oAuth2Client The OAuth2 client to get token for.
* @param {getEventsCallback} callback The callback for the authorized client.
*/
function getAccessToken(oAuth2Client, callback) {
const authUrl = oAuth2Client.generateAuthUrl({
access_type: 'offline',
scope: SCOPES,
});
console.log('Authorize this app by visiting this url:', authUrl);
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
});
rl.question('Enter the code from that page here: ', (code) => {
rl.close();
oAuth2Client.getToken(code, (err, token) => {
if (err) return console.error('Error retrieving access token', err);
oAuth2Client.setCredentials(token);
// Store the token to disk for later program executions
fs.writeFile(TOKEN_PATH, JSON.stringify(token), (err) => {
if (err) return console.error(err);
console.log('Token stored to', TOKEN_PATH);
});
callback(oAuth2Client);
});
});
}
there is also webmasters query.js
'use strict';
const path = require('path');
const {google} = require('googleapis');
const {authenticate} = require('@google-cloud/local-auth');
const webmasters = google.webmasters('v3');
async function runSample() {
// Obtain user credentials to use for the request
const auth = await authenticate({
keyfilePath: path.join(__dirname, '../oauth2.keys.json'),
scopes: [
'https://www.googleapis.com/auth/webmasters',
'https://www.googleapis.com/auth/webmasters.readonly',
],
});
google.options({auth});
const res = await webmasters.searchanalytics.query({
siteUrl: 'http://jbeckwith.com',
requestBody: {
startDate: '2018-01-01',
endDate: '2018-04-01',
},
});
console.log(res.data);
return res.data;
}
if (module === require.main) {
runSample().catch(console.error);
}
module.exports = runSample;
I would go with the first example as its shows how to store your authorization. The second one isnt going to do that.
Access without authorization
If we check the documentation for sites.list you will notice it stats
This method operates on private user data you will need permission of a user with access in order to access this data.
I was getting this even tho everything was being set correctly. What I didn't realize was it wasn't done setting the credentials when I made the call. I solved my issues by creating a stand alone async function.
so the code looked like this:
const accessToken = req.body.data.access_token;
setToken(accessToken);
const gmail = google.gmail({version: "v1", auth: oauth2Client});
...
and
async function setToken(accessToken) {
try {
oauth2Client.setCredentials({access_token: accessToken});
} catch (err) {
console.error(err);
}
}
With this function, it waits for setCredentials
to finish before calling the gmail api.
Hope this helps!