NodeJS, Google Calendar API integration not authenticated and returns undefined, regardless of credentials...












0














I apologize for this question in advance. I know it's a little all over the place, but I am simply lost to the point where I am no longer sure what I am asking. Feel free to ask any and all questions if you need clarification!



I am currently working with your Google Calendar API. I need help, with my NodeJS integration. I need to pull out some data regarding a calendar containing vacation dates information.



I seem to get the error message: "The API returned an error: Error: Daily Limit for Unauthenticated Use Exceeded. Continued use requires signup." I have tried searching for a clear answer to this problem and how to solve it. But neither StackOverflow or Googles guides help me understand what I need to do, and what/where the connection between my application and the google calendar API actually is.



I have also tried to refactor the example code from the NodeJS quickstart guide on your pages, so that I can return an array containing calendar objects with date name and description. This yields undefined. So what I basically need is help reviewing where I go wrong in my code and to reevaluate the procedure for authentication, as I have my secret credentials set up and a token from your API saved to my machine.



So I have my code that, when I call my calendar controller, to retrieve data, I get undefined back and an error



Quick start code: https://developers.google.com/calendar/quickstart/nodejs



My calendar controller class:



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

const SCOPES = ['https://www.googleapis.com/auth/calendar.readonly'];
const TOKEN_PATH = __dirname + '/token.json';

class CalendarController {

/**
* Create an OAuth2 client with the given credentials.
* @param {Object} credentials The authorization client credentials.
*/
getOAuth2Client(credentials) {
const {client_secret, client_id, redirect_uris} = credentials.installed;
const oAuth2Client = new google.auth.OAuth2(client_id, client_secret, redirect_uris[0]);

fs.readFile(TOKEN_PATH, (err, token) => {
if (err) return this.getNewAccessToken(oAuth2Client);
oAuth2Client.setCredentials(JSON.parse(token));
return oAuth2Client;
});
}
/**
* Get and store new token after prompting for user authorization.
* @param {google.auth.OAuth2} oAuth2Client The OAuth2 client to get token for.
*/
getNewAccessToken(oAuth2Client) {
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 the webpage 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) console.error(err);
console.log('Token stored to: ', TOKEN_PATH);
});
});
return oAuth2Client;
});
}

/**
* Lists the next maxResults events on the user's primary calendar.
* @param {google.auth.OAuth2} auth An authorized OAuth2 client.
*/
listEvents(auth) {
const calendar = google.calendar({version: 'v3', auth});
let vacation_events = ;
calendar.events.list({
calendarId: 'CALENDAR.ID.IS.OMITTED.CUZ.DUH',
timeMin: (new Date()).toISOString(),
maxResults: 250,
singleEvents: true,
orderBy: 'startTime',
}, (err, res) => {
if (err) return console.log('The API returned an error: ' + err);
const events = res.data.items;
if (events.length) {
events.map((event, i) => {
const start = event.start.dateTime || event.start.date;
const end = event.end.dateTime || event.end.date;
let vacation = {
event_title: event.summary,
event_description: event.description,
dt_start: start,
dt_end: end,
}
vacation_events.push(vacation);
});
console.log(vacation_events);
return vacation_events;
} else {
console.log('No upcoming events found.');
}
});
}

getData() {
fs.readFile(__dirname + '/credentials.json', (err, content) => {
if (err) return console.error('Error loading client secrect file: ', err);

console.log(
this.listEvents(this.getOAuth2Client(JSON.parse(content)))
);
// return this.listEvents(this.getOAuth2Client(JSON.parse(content)));
})
}
}

module.exports = CalendarController;


To be clear. I DO HAVE my credentials.json and token.json files in my project and saved to my machine.










share|improve this question
























  • Is it error status code 403? If that's the case, it means that you have reached Google Drive API's maximum request rate. You can check this same issue at github.
    – jess
    Nov 13 at 10:35










  • Yes it is. But I have followed every single guide I can find and also StackOverflow posts and it still gives me that message. And it litterally shouldn't be possible for me to reach max req.. it's capped at 1 mill, and that would mean even if my requests contained 100 seperate requests that I should have run my code 10.000 times within the last 24hrs.. seems stupid..
    – IncrediblePony
    Nov 13 at 13:11










  • What does the code like that is executing the methods in the class? Can you post a full repro (obviously without the authentication details)
    – kastermester
    Nov 15 at 9:48










  • I found out that ny approach was incorrect to solve this problem. I will post an answer later when the code is done and running
    – IncrediblePony
    Nov 16 at 10:12
















0














I apologize for this question in advance. I know it's a little all over the place, but I am simply lost to the point where I am no longer sure what I am asking. Feel free to ask any and all questions if you need clarification!



I am currently working with your Google Calendar API. I need help, with my NodeJS integration. I need to pull out some data regarding a calendar containing vacation dates information.



I seem to get the error message: "The API returned an error: Error: Daily Limit for Unauthenticated Use Exceeded. Continued use requires signup." I have tried searching for a clear answer to this problem and how to solve it. But neither StackOverflow or Googles guides help me understand what I need to do, and what/where the connection between my application and the google calendar API actually is.



I have also tried to refactor the example code from the NodeJS quickstart guide on your pages, so that I can return an array containing calendar objects with date name and description. This yields undefined. So what I basically need is help reviewing where I go wrong in my code and to reevaluate the procedure for authentication, as I have my secret credentials set up and a token from your API saved to my machine.



So I have my code that, when I call my calendar controller, to retrieve data, I get undefined back and an error



Quick start code: https://developers.google.com/calendar/quickstart/nodejs



My calendar controller class:



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

const SCOPES = ['https://www.googleapis.com/auth/calendar.readonly'];
const TOKEN_PATH = __dirname + '/token.json';

class CalendarController {

/**
* Create an OAuth2 client with the given credentials.
* @param {Object} credentials The authorization client credentials.
*/
getOAuth2Client(credentials) {
const {client_secret, client_id, redirect_uris} = credentials.installed;
const oAuth2Client = new google.auth.OAuth2(client_id, client_secret, redirect_uris[0]);

fs.readFile(TOKEN_PATH, (err, token) => {
if (err) return this.getNewAccessToken(oAuth2Client);
oAuth2Client.setCredentials(JSON.parse(token));
return oAuth2Client;
});
}
/**
* Get and store new token after prompting for user authorization.
* @param {google.auth.OAuth2} oAuth2Client The OAuth2 client to get token for.
*/
getNewAccessToken(oAuth2Client) {
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 the webpage 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) console.error(err);
console.log('Token stored to: ', TOKEN_PATH);
});
});
return oAuth2Client;
});
}

/**
* Lists the next maxResults events on the user's primary calendar.
* @param {google.auth.OAuth2} auth An authorized OAuth2 client.
*/
listEvents(auth) {
const calendar = google.calendar({version: 'v3', auth});
let vacation_events = ;
calendar.events.list({
calendarId: 'CALENDAR.ID.IS.OMITTED.CUZ.DUH',
timeMin: (new Date()).toISOString(),
maxResults: 250,
singleEvents: true,
orderBy: 'startTime',
}, (err, res) => {
if (err) return console.log('The API returned an error: ' + err);
const events = res.data.items;
if (events.length) {
events.map((event, i) => {
const start = event.start.dateTime || event.start.date;
const end = event.end.dateTime || event.end.date;
let vacation = {
event_title: event.summary,
event_description: event.description,
dt_start: start,
dt_end: end,
}
vacation_events.push(vacation);
});
console.log(vacation_events);
return vacation_events;
} else {
console.log('No upcoming events found.');
}
});
}

getData() {
fs.readFile(__dirname + '/credentials.json', (err, content) => {
if (err) return console.error('Error loading client secrect file: ', err);

console.log(
this.listEvents(this.getOAuth2Client(JSON.parse(content)))
);
// return this.listEvents(this.getOAuth2Client(JSON.parse(content)));
})
}
}

module.exports = CalendarController;


To be clear. I DO HAVE my credentials.json and token.json files in my project and saved to my machine.










share|improve this question
























  • Is it error status code 403? If that's the case, it means that you have reached Google Drive API's maximum request rate. You can check this same issue at github.
    – jess
    Nov 13 at 10:35










  • Yes it is. But I have followed every single guide I can find and also StackOverflow posts and it still gives me that message. And it litterally shouldn't be possible for me to reach max req.. it's capped at 1 mill, and that would mean even if my requests contained 100 seperate requests that I should have run my code 10.000 times within the last 24hrs.. seems stupid..
    – IncrediblePony
    Nov 13 at 13:11










  • What does the code like that is executing the methods in the class? Can you post a full repro (obviously without the authentication details)
    – kastermester
    Nov 15 at 9:48










  • I found out that ny approach was incorrect to solve this problem. I will post an answer later when the code is done and running
    – IncrediblePony
    Nov 16 at 10:12














0












0








0







I apologize for this question in advance. I know it's a little all over the place, but I am simply lost to the point where I am no longer sure what I am asking. Feel free to ask any and all questions if you need clarification!



I am currently working with your Google Calendar API. I need help, with my NodeJS integration. I need to pull out some data regarding a calendar containing vacation dates information.



I seem to get the error message: "The API returned an error: Error: Daily Limit for Unauthenticated Use Exceeded. Continued use requires signup." I have tried searching for a clear answer to this problem and how to solve it. But neither StackOverflow or Googles guides help me understand what I need to do, and what/where the connection between my application and the google calendar API actually is.



I have also tried to refactor the example code from the NodeJS quickstart guide on your pages, so that I can return an array containing calendar objects with date name and description. This yields undefined. So what I basically need is help reviewing where I go wrong in my code and to reevaluate the procedure for authentication, as I have my secret credentials set up and a token from your API saved to my machine.



So I have my code that, when I call my calendar controller, to retrieve data, I get undefined back and an error



Quick start code: https://developers.google.com/calendar/quickstart/nodejs



My calendar controller class:



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

const SCOPES = ['https://www.googleapis.com/auth/calendar.readonly'];
const TOKEN_PATH = __dirname + '/token.json';

class CalendarController {

/**
* Create an OAuth2 client with the given credentials.
* @param {Object} credentials The authorization client credentials.
*/
getOAuth2Client(credentials) {
const {client_secret, client_id, redirect_uris} = credentials.installed;
const oAuth2Client = new google.auth.OAuth2(client_id, client_secret, redirect_uris[0]);

fs.readFile(TOKEN_PATH, (err, token) => {
if (err) return this.getNewAccessToken(oAuth2Client);
oAuth2Client.setCredentials(JSON.parse(token));
return oAuth2Client;
});
}
/**
* Get and store new token after prompting for user authorization.
* @param {google.auth.OAuth2} oAuth2Client The OAuth2 client to get token for.
*/
getNewAccessToken(oAuth2Client) {
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 the webpage 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) console.error(err);
console.log('Token stored to: ', TOKEN_PATH);
});
});
return oAuth2Client;
});
}

/**
* Lists the next maxResults events on the user's primary calendar.
* @param {google.auth.OAuth2} auth An authorized OAuth2 client.
*/
listEvents(auth) {
const calendar = google.calendar({version: 'v3', auth});
let vacation_events = ;
calendar.events.list({
calendarId: 'CALENDAR.ID.IS.OMITTED.CUZ.DUH',
timeMin: (new Date()).toISOString(),
maxResults: 250,
singleEvents: true,
orderBy: 'startTime',
}, (err, res) => {
if (err) return console.log('The API returned an error: ' + err);
const events = res.data.items;
if (events.length) {
events.map((event, i) => {
const start = event.start.dateTime || event.start.date;
const end = event.end.dateTime || event.end.date;
let vacation = {
event_title: event.summary,
event_description: event.description,
dt_start: start,
dt_end: end,
}
vacation_events.push(vacation);
});
console.log(vacation_events);
return vacation_events;
} else {
console.log('No upcoming events found.');
}
});
}

getData() {
fs.readFile(__dirname + '/credentials.json', (err, content) => {
if (err) return console.error('Error loading client secrect file: ', err);

console.log(
this.listEvents(this.getOAuth2Client(JSON.parse(content)))
);
// return this.listEvents(this.getOAuth2Client(JSON.parse(content)));
})
}
}

module.exports = CalendarController;


To be clear. I DO HAVE my credentials.json and token.json files in my project and saved to my machine.










share|improve this question















I apologize for this question in advance. I know it's a little all over the place, but I am simply lost to the point where I am no longer sure what I am asking. Feel free to ask any and all questions if you need clarification!



I am currently working with your Google Calendar API. I need help, with my NodeJS integration. I need to pull out some data regarding a calendar containing vacation dates information.



I seem to get the error message: "The API returned an error: Error: Daily Limit for Unauthenticated Use Exceeded. Continued use requires signup." I have tried searching for a clear answer to this problem and how to solve it. But neither StackOverflow or Googles guides help me understand what I need to do, and what/where the connection between my application and the google calendar API actually is.



I have also tried to refactor the example code from the NodeJS quickstart guide on your pages, so that I can return an array containing calendar objects with date name and description. This yields undefined. So what I basically need is help reviewing where I go wrong in my code and to reevaluate the procedure for authentication, as I have my secret credentials set up and a token from your API saved to my machine.



So I have my code that, when I call my calendar controller, to retrieve data, I get undefined back and an error



Quick start code: https://developers.google.com/calendar/quickstart/nodejs



My calendar controller class:



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

const SCOPES = ['https://www.googleapis.com/auth/calendar.readonly'];
const TOKEN_PATH = __dirname + '/token.json';

class CalendarController {

/**
* Create an OAuth2 client with the given credentials.
* @param {Object} credentials The authorization client credentials.
*/
getOAuth2Client(credentials) {
const {client_secret, client_id, redirect_uris} = credentials.installed;
const oAuth2Client = new google.auth.OAuth2(client_id, client_secret, redirect_uris[0]);

fs.readFile(TOKEN_PATH, (err, token) => {
if (err) return this.getNewAccessToken(oAuth2Client);
oAuth2Client.setCredentials(JSON.parse(token));
return oAuth2Client;
});
}
/**
* Get and store new token after prompting for user authorization.
* @param {google.auth.OAuth2} oAuth2Client The OAuth2 client to get token for.
*/
getNewAccessToken(oAuth2Client) {
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 the webpage 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) console.error(err);
console.log('Token stored to: ', TOKEN_PATH);
});
});
return oAuth2Client;
});
}

/**
* Lists the next maxResults events on the user's primary calendar.
* @param {google.auth.OAuth2} auth An authorized OAuth2 client.
*/
listEvents(auth) {
const calendar = google.calendar({version: 'v3', auth});
let vacation_events = ;
calendar.events.list({
calendarId: 'CALENDAR.ID.IS.OMITTED.CUZ.DUH',
timeMin: (new Date()).toISOString(),
maxResults: 250,
singleEvents: true,
orderBy: 'startTime',
}, (err, res) => {
if (err) return console.log('The API returned an error: ' + err);
const events = res.data.items;
if (events.length) {
events.map((event, i) => {
const start = event.start.dateTime || event.start.date;
const end = event.end.dateTime || event.end.date;
let vacation = {
event_title: event.summary,
event_description: event.description,
dt_start: start,
dt_end: end,
}
vacation_events.push(vacation);
});
console.log(vacation_events);
return vacation_events;
} else {
console.log('No upcoming events found.');
}
});
}

getData() {
fs.readFile(__dirname + '/credentials.json', (err, content) => {
if (err) return console.error('Error loading client secrect file: ', err);

console.log(
this.listEvents(this.getOAuth2Client(JSON.parse(content)))
);
// return this.listEvents(this.getOAuth2Client(JSON.parse(content)));
})
}
}

module.exports = CalendarController;


To be clear. I DO HAVE my credentials.json and token.json files in my project and saved to my machine.







javascript node.js google-calendar-api






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 13 at 8:42

























asked Nov 12 at 12:18









IncrediblePony

238




238












  • Is it error status code 403? If that's the case, it means that you have reached Google Drive API's maximum request rate. You can check this same issue at github.
    – jess
    Nov 13 at 10:35










  • Yes it is. But I have followed every single guide I can find and also StackOverflow posts and it still gives me that message. And it litterally shouldn't be possible for me to reach max req.. it's capped at 1 mill, and that would mean even if my requests contained 100 seperate requests that I should have run my code 10.000 times within the last 24hrs.. seems stupid..
    – IncrediblePony
    Nov 13 at 13:11










  • What does the code like that is executing the methods in the class? Can you post a full repro (obviously without the authentication details)
    – kastermester
    Nov 15 at 9:48










  • I found out that ny approach was incorrect to solve this problem. I will post an answer later when the code is done and running
    – IncrediblePony
    Nov 16 at 10:12


















  • Is it error status code 403? If that's the case, it means that you have reached Google Drive API's maximum request rate. You can check this same issue at github.
    – jess
    Nov 13 at 10:35










  • Yes it is. But I have followed every single guide I can find and also StackOverflow posts and it still gives me that message. And it litterally shouldn't be possible for me to reach max req.. it's capped at 1 mill, and that would mean even if my requests contained 100 seperate requests that I should have run my code 10.000 times within the last 24hrs.. seems stupid..
    – IncrediblePony
    Nov 13 at 13:11










  • What does the code like that is executing the methods in the class? Can you post a full repro (obviously without the authentication details)
    – kastermester
    Nov 15 at 9:48










  • I found out that ny approach was incorrect to solve this problem. I will post an answer later when the code is done and running
    – IncrediblePony
    Nov 16 at 10:12
















Is it error status code 403? If that's the case, it means that you have reached Google Drive API's maximum request rate. You can check this same issue at github.
– jess
Nov 13 at 10:35




Is it error status code 403? If that's the case, it means that you have reached Google Drive API's maximum request rate. You can check this same issue at github.
– jess
Nov 13 at 10:35












Yes it is. But I have followed every single guide I can find and also StackOverflow posts and it still gives me that message. And it litterally shouldn't be possible for me to reach max req.. it's capped at 1 mill, and that would mean even if my requests contained 100 seperate requests that I should have run my code 10.000 times within the last 24hrs.. seems stupid..
– IncrediblePony
Nov 13 at 13:11




Yes it is. But I have followed every single guide I can find and also StackOverflow posts and it still gives me that message. And it litterally shouldn't be possible for me to reach max req.. it's capped at 1 mill, and that would mean even if my requests contained 100 seperate requests that I should have run my code 10.000 times within the last 24hrs.. seems stupid..
– IncrediblePony
Nov 13 at 13:11












What does the code like that is executing the methods in the class? Can you post a full repro (obviously without the authentication details)
– kastermester
Nov 15 at 9:48




What does the code like that is executing the methods in the class? Can you post a full repro (obviously without the authentication details)
– kastermester
Nov 15 at 9:48












I found out that ny approach was incorrect to solve this problem. I will post an answer later when the code is done and running
– IncrediblePony
Nov 16 at 10:12




I found out that ny approach was incorrect to solve this problem. I will post an answer later when the code is done and running
– IncrediblePony
Nov 16 at 10:12












1 Answer
1






active

oldest

votes


















0














So I ended up calling upon the help of a friend. This resultet in the following solution.



One of my problems was that when you, use Googles quickstart for NodeJS to connect to the Calendar API, that code will ask you to manually update your tokens through a browser. So we had to combat this problem. The second problem I had was that my code did not execute in the correct order. This was, as is so many things in JS, an async/await problem.



The following file shows the code logic behind "correct" authentication against the Google Calendar API if you want to automate this, using a single user.



const http = require('http')
const fs = require('fs')
const moment = require('moment')
const jwt = require('jsonwebtoken')
const { google } = require('googleapis')

const { GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET, GOOGLE_REDIRECT_URIS } = process.env
const scope = ['https://www.googleapis.com/auth/calendar',
'https://www.googleapis.com/auth/plus.login',
'https://www.googleapis.com/auth/plus.me',
'https://www.googleapis.com/auth/userinfo.email',
'https://www.googleapis.com/auth/userinfo.profile']

// adminID omitted
const adminID = '123456789101112131415'

const auth = new google.auth.OAuth2(GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET, GOOGLE_REDIRECT_URIS)
google.options({ auth })

const calendar = google.calendar({version: 'v3'})

const publicMethods = {
async listAllUpcomingEvents() {
const { data } = await calendar.events.list({
// correct calendarId omitted
calendarId: 'primary',
timeMin: (new Date()).toISOString(),
maxResults: 10,
singleEvents: true,
orderBy: 'startTime'
})
return data
}
/* Make all your calendar methods like shown here */
}

auth.on('tokens', (tokens) => {
if(verifyTokenId(tokens)) {
saveTokens(tokens)
}
})

function saveTokens (tokens) {
auth.setCredentials(tokens)
nDebug('auth:token', tokens)
tokenStore.tokens = tokens
}

/**
* Generate a url for authentication
*
* @returns {string} Authentication url
*/
function getUrl () {
return auth.generateAuthUrl({
access_type: 'offline',
prompt: 'consent',
scope
})
}

/**
* Store token upon oauth callback
*
* @param {string} code Access code from auth callback
* @returns {Object} tokens
*/
async function tokenCallback(code) {
const { tokens } = await auth.getToken(code)
return tokens
}

/**
* Acquires profile information and verifies ID against adminID
*
* @param {Object} tokens
* @returns {Boolean}
*/
async function verifyTokenId (tokens) {
const info = jwt.decode(tokens.id_token)
//const info = await auth.getTokenInfo(tokens.access_token)
return info.sub === adminID
}

function getRouter () {
const router = require('express').Router()

router.get('/redirect', (req, res) => {
res.redirect(getUrl())
})

router.get('/kappa', async (req, res) => {
const data = await publicMethods.listAllUpcomingEvents() /* Use calendar functions like this */
res.send(data)
})

router.get('/', async (req, res) => {
try {
const tokens = await tokenCallback(req.query.code)
nDebug('tokens', tokens)
if (!verifyTokenId(tokens)) {
return res.status(403).send(http.STATUS_CODES['403'])
}

return res.send(info)

} catch (e) {
nDebug('error', e.data || e)
res.status(500).send(e.data || e)
}
})

return router
}

/**
* Debugging class
*
* @param {string} string describing who calls the function
* @param {function} callback function
*/
function nDebug (who, what) {
console.log(moment().format(), who)
console.dir(what, {color: true, depth: 3})
console.log('#/', who)
}

/**
* Singleton class to store and retrieve tokens
*
* @class TokenStore
*/
class TokenStore {
/**
* Creates an instance of TokenStore.
* @param {Object} tokens - Collection of tokens to store
* @param {string} tokens.access_token - Access token
* @param {string} tokens.refresh_token - Refresh token
* @memberof TokenStore
*/
constructor (tokens) {
this._tokens = tokens
}

/**
* Returns stored tokens
*
* @memberof TokenStore
*/
get tokens () {
return this._tokens
}

/**
* Set tokens on TokenStore and writes them to file
*
* @memberof TokenStore
*/
set tokens (tokens) {
this._tokens = tokens
TokenStore.saveToFile(tokens)
}

/**
* Tries to load tokens from file, creates a blank TokenStore if none was found
*
* @static
* @returns {TokenStore} New instance of TokenStore
* @memberof TokenStore
*/
static tryLoadOrMakeNew () {
try {
const data = this.loadFromFile()
nDebug('token loaded', data)
setImmediate(() => saveTokens(data))
return new this(data)
} catch (err) {
if(err.code === 'ENOENT') {
nDebug('no token loaded', {})
return new this()
} else {
throw err /* Bollocks, something more serious is wrong, better throw up */
}
}
}

static loadFromFile () {
return JSON.parse(fs.readFileSync(this.filePath(), this.opts()))
}

static saveToFile (tokens) {
return fs.writeFileSync(this.filePath(), JSON.stringify(tokens, null, 2), this.opts())
}

static opts () {
return { encoding: 'utf-8' }
}

static filePath () {
return 'tokens.json'
}
}

/* I feel ashamed */
const tokenStore = TokenStore.tryLoadOrMakeNew()

module.exports = Object.assign(google, publicMethods, { getRouter })


In the end when we get a response from Google and get refresh tokens and access_token, then we store it locally to a "token.json" file.



Beware if you use nodemon to run your application, you have to change your npm start in package.json to "start": "nodemon --ignore 'tokens.json' app.js"



I will update answer if questions og corrections arise in the comments.






share|improve this answer





















    Your Answer






    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "1"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53262053%2fnodejs-google-calendar-api-integration-not-authenticated-and-returns-undefined%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    1 Answer
    1






    active

    oldest

    votes








    1 Answer
    1






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    0














    So I ended up calling upon the help of a friend. This resultet in the following solution.



    One of my problems was that when you, use Googles quickstart for NodeJS to connect to the Calendar API, that code will ask you to manually update your tokens through a browser. So we had to combat this problem. The second problem I had was that my code did not execute in the correct order. This was, as is so many things in JS, an async/await problem.



    The following file shows the code logic behind "correct" authentication against the Google Calendar API if you want to automate this, using a single user.



    const http = require('http')
    const fs = require('fs')
    const moment = require('moment')
    const jwt = require('jsonwebtoken')
    const { google } = require('googleapis')

    const { GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET, GOOGLE_REDIRECT_URIS } = process.env
    const scope = ['https://www.googleapis.com/auth/calendar',
    'https://www.googleapis.com/auth/plus.login',
    'https://www.googleapis.com/auth/plus.me',
    'https://www.googleapis.com/auth/userinfo.email',
    'https://www.googleapis.com/auth/userinfo.profile']

    // adminID omitted
    const adminID = '123456789101112131415'

    const auth = new google.auth.OAuth2(GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET, GOOGLE_REDIRECT_URIS)
    google.options({ auth })

    const calendar = google.calendar({version: 'v3'})

    const publicMethods = {
    async listAllUpcomingEvents() {
    const { data } = await calendar.events.list({
    // correct calendarId omitted
    calendarId: 'primary',
    timeMin: (new Date()).toISOString(),
    maxResults: 10,
    singleEvents: true,
    orderBy: 'startTime'
    })
    return data
    }
    /* Make all your calendar methods like shown here */
    }

    auth.on('tokens', (tokens) => {
    if(verifyTokenId(tokens)) {
    saveTokens(tokens)
    }
    })

    function saveTokens (tokens) {
    auth.setCredentials(tokens)
    nDebug('auth:token', tokens)
    tokenStore.tokens = tokens
    }

    /**
    * Generate a url for authentication
    *
    * @returns {string} Authentication url
    */
    function getUrl () {
    return auth.generateAuthUrl({
    access_type: 'offline',
    prompt: 'consent',
    scope
    })
    }

    /**
    * Store token upon oauth callback
    *
    * @param {string} code Access code from auth callback
    * @returns {Object} tokens
    */
    async function tokenCallback(code) {
    const { tokens } = await auth.getToken(code)
    return tokens
    }

    /**
    * Acquires profile information and verifies ID against adminID
    *
    * @param {Object} tokens
    * @returns {Boolean}
    */
    async function verifyTokenId (tokens) {
    const info = jwt.decode(tokens.id_token)
    //const info = await auth.getTokenInfo(tokens.access_token)
    return info.sub === adminID
    }

    function getRouter () {
    const router = require('express').Router()

    router.get('/redirect', (req, res) => {
    res.redirect(getUrl())
    })

    router.get('/kappa', async (req, res) => {
    const data = await publicMethods.listAllUpcomingEvents() /* Use calendar functions like this */
    res.send(data)
    })

    router.get('/', async (req, res) => {
    try {
    const tokens = await tokenCallback(req.query.code)
    nDebug('tokens', tokens)
    if (!verifyTokenId(tokens)) {
    return res.status(403).send(http.STATUS_CODES['403'])
    }

    return res.send(info)

    } catch (e) {
    nDebug('error', e.data || e)
    res.status(500).send(e.data || e)
    }
    })

    return router
    }

    /**
    * Debugging class
    *
    * @param {string} string describing who calls the function
    * @param {function} callback function
    */
    function nDebug (who, what) {
    console.log(moment().format(), who)
    console.dir(what, {color: true, depth: 3})
    console.log('#/', who)
    }

    /**
    * Singleton class to store and retrieve tokens
    *
    * @class TokenStore
    */
    class TokenStore {
    /**
    * Creates an instance of TokenStore.
    * @param {Object} tokens - Collection of tokens to store
    * @param {string} tokens.access_token - Access token
    * @param {string} tokens.refresh_token - Refresh token
    * @memberof TokenStore
    */
    constructor (tokens) {
    this._tokens = tokens
    }

    /**
    * Returns stored tokens
    *
    * @memberof TokenStore
    */
    get tokens () {
    return this._tokens
    }

    /**
    * Set tokens on TokenStore and writes them to file
    *
    * @memberof TokenStore
    */
    set tokens (tokens) {
    this._tokens = tokens
    TokenStore.saveToFile(tokens)
    }

    /**
    * Tries to load tokens from file, creates a blank TokenStore if none was found
    *
    * @static
    * @returns {TokenStore} New instance of TokenStore
    * @memberof TokenStore
    */
    static tryLoadOrMakeNew () {
    try {
    const data = this.loadFromFile()
    nDebug('token loaded', data)
    setImmediate(() => saveTokens(data))
    return new this(data)
    } catch (err) {
    if(err.code === 'ENOENT') {
    nDebug('no token loaded', {})
    return new this()
    } else {
    throw err /* Bollocks, something more serious is wrong, better throw up */
    }
    }
    }

    static loadFromFile () {
    return JSON.parse(fs.readFileSync(this.filePath(), this.opts()))
    }

    static saveToFile (tokens) {
    return fs.writeFileSync(this.filePath(), JSON.stringify(tokens, null, 2), this.opts())
    }

    static opts () {
    return { encoding: 'utf-8' }
    }

    static filePath () {
    return 'tokens.json'
    }
    }

    /* I feel ashamed */
    const tokenStore = TokenStore.tryLoadOrMakeNew()

    module.exports = Object.assign(google, publicMethods, { getRouter })


    In the end when we get a response from Google and get refresh tokens and access_token, then we store it locally to a "token.json" file.



    Beware if you use nodemon to run your application, you have to change your npm start in package.json to "start": "nodemon --ignore 'tokens.json' app.js"



    I will update answer if questions og corrections arise in the comments.






    share|improve this answer


























      0














      So I ended up calling upon the help of a friend. This resultet in the following solution.



      One of my problems was that when you, use Googles quickstart for NodeJS to connect to the Calendar API, that code will ask you to manually update your tokens through a browser. So we had to combat this problem. The second problem I had was that my code did not execute in the correct order. This was, as is so many things in JS, an async/await problem.



      The following file shows the code logic behind "correct" authentication against the Google Calendar API if you want to automate this, using a single user.



      const http = require('http')
      const fs = require('fs')
      const moment = require('moment')
      const jwt = require('jsonwebtoken')
      const { google } = require('googleapis')

      const { GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET, GOOGLE_REDIRECT_URIS } = process.env
      const scope = ['https://www.googleapis.com/auth/calendar',
      'https://www.googleapis.com/auth/plus.login',
      'https://www.googleapis.com/auth/plus.me',
      'https://www.googleapis.com/auth/userinfo.email',
      'https://www.googleapis.com/auth/userinfo.profile']

      // adminID omitted
      const adminID = '123456789101112131415'

      const auth = new google.auth.OAuth2(GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET, GOOGLE_REDIRECT_URIS)
      google.options({ auth })

      const calendar = google.calendar({version: 'v3'})

      const publicMethods = {
      async listAllUpcomingEvents() {
      const { data } = await calendar.events.list({
      // correct calendarId omitted
      calendarId: 'primary',
      timeMin: (new Date()).toISOString(),
      maxResults: 10,
      singleEvents: true,
      orderBy: 'startTime'
      })
      return data
      }
      /* Make all your calendar methods like shown here */
      }

      auth.on('tokens', (tokens) => {
      if(verifyTokenId(tokens)) {
      saveTokens(tokens)
      }
      })

      function saveTokens (tokens) {
      auth.setCredentials(tokens)
      nDebug('auth:token', tokens)
      tokenStore.tokens = tokens
      }

      /**
      * Generate a url for authentication
      *
      * @returns {string} Authentication url
      */
      function getUrl () {
      return auth.generateAuthUrl({
      access_type: 'offline',
      prompt: 'consent',
      scope
      })
      }

      /**
      * Store token upon oauth callback
      *
      * @param {string} code Access code from auth callback
      * @returns {Object} tokens
      */
      async function tokenCallback(code) {
      const { tokens } = await auth.getToken(code)
      return tokens
      }

      /**
      * Acquires profile information and verifies ID against adminID
      *
      * @param {Object} tokens
      * @returns {Boolean}
      */
      async function verifyTokenId (tokens) {
      const info = jwt.decode(tokens.id_token)
      //const info = await auth.getTokenInfo(tokens.access_token)
      return info.sub === adminID
      }

      function getRouter () {
      const router = require('express').Router()

      router.get('/redirect', (req, res) => {
      res.redirect(getUrl())
      })

      router.get('/kappa', async (req, res) => {
      const data = await publicMethods.listAllUpcomingEvents() /* Use calendar functions like this */
      res.send(data)
      })

      router.get('/', async (req, res) => {
      try {
      const tokens = await tokenCallback(req.query.code)
      nDebug('tokens', tokens)
      if (!verifyTokenId(tokens)) {
      return res.status(403).send(http.STATUS_CODES['403'])
      }

      return res.send(info)

      } catch (e) {
      nDebug('error', e.data || e)
      res.status(500).send(e.data || e)
      }
      })

      return router
      }

      /**
      * Debugging class
      *
      * @param {string} string describing who calls the function
      * @param {function} callback function
      */
      function nDebug (who, what) {
      console.log(moment().format(), who)
      console.dir(what, {color: true, depth: 3})
      console.log('#/', who)
      }

      /**
      * Singleton class to store and retrieve tokens
      *
      * @class TokenStore
      */
      class TokenStore {
      /**
      * Creates an instance of TokenStore.
      * @param {Object} tokens - Collection of tokens to store
      * @param {string} tokens.access_token - Access token
      * @param {string} tokens.refresh_token - Refresh token
      * @memberof TokenStore
      */
      constructor (tokens) {
      this._tokens = tokens
      }

      /**
      * Returns stored tokens
      *
      * @memberof TokenStore
      */
      get tokens () {
      return this._tokens
      }

      /**
      * Set tokens on TokenStore and writes them to file
      *
      * @memberof TokenStore
      */
      set tokens (tokens) {
      this._tokens = tokens
      TokenStore.saveToFile(tokens)
      }

      /**
      * Tries to load tokens from file, creates a blank TokenStore if none was found
      *
      * @static
      * @returns {TokenStore} New instance of TokenStore
      * @memberof TokenStore
      */
      static tryLoadOrMakeNew () {
      try {
      const data = this.loadFromFile()
      nDebug('token loaded', data)
      setImmediate(() => saveTokens(data))
      return new this(data)
      } catch (err) {
      if(err.code === 'ENOENT') {
      nDebug('no token loaded', {})
      return new this()
      } else {
      throw err /* Bollocks, something more serious is wrong, better throw up */
      }
      }
      }

      static loadFromFile () {
      return JSON.parse(fs.readFileSync(this.filePath(), this.opts()))
      }

      static saveToFile (tokens) {
      return fs.writeFileSync(this.filePath(), JSON.stringify(tokens, null, 2), this.opts())
      }

      static opts () {
      return { encoding: 'utf-8' }
      }

      static filePath () {
      return 'tokens.json'
      }
      }

      /* I feel ashamed */
      const tokenStore = TokenStore.tryLoadOrMakeNew()

      module.exports = Object.assign(google, publicMethods, { getRouter })


      In the end when we get a response from Google and get refresh tokens and access_token, then we store it locally to a "token.json" file.



      Beware if you use nodemon to run your application, you have to change your npm start in package.json to "start": "nodemon --ignore 'tokens.json' app.js"



      I will update answer if questions og corrections arise in the comments.






      share|improve this answer
























        0












        0








        0






        So I ended up calling upon the help of a friend. This resultet in the following solution.



        One of my problems was that when you, use Googles quickstart for NodeJS to connect to the Calendar API, that code will ask you to manually update your tokens through a browser. So we had to combat this problem. The second problem I had was that my code did not execute in the correct order. This was, as is so many things in JS, an async/await problem.



        The following file shows the code logic behind "correct" authentication against the Google Calendar API if you want to automate this, using a single user.



        const http = require('http')
        const fs = require('fs')
        const moment = require('moment')
        const jwt = require('jsonwebtoken')
        const { google } = require('googleapis')

        const { GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET, GOOGLE_REDIRECT_URIS } = process.env
        const scope = ['https://www.googleapis.com/auth/calendar',
        'https://www.googleapis.com/auth/plus.login',
        'https://www.googleapis.com/auth/plus.me',
        'https://www.googleapis.com/auth/userinfo.email',
        'https://www.googleapis.com/auth/userinfo.profile']

        // adminID omitted
        const adminID = '123456789101112131415'

        const auth = new google.auth.OAuth2(GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET, GOOGLE_REDIRECT_URIS)
        google.options({ auth })

        const calendar = google.calendar({version: 'v3'})

        const publicMethods = {
        async listAllUpcomingEvents() {
        const { data } = await calendar.events.list({
        // correct calendarId omitted
        calendarId: 'primary',
        timeMin: (new Date()).toISOString(),
        maxResults: 10,
        singleEvents: true,
        orderBy: 'startTime'
        })
        return data
        }
        /* Make all your calendar methods like shown here */
        }

        auth.on('tokens', (tokens) => {
        if(verifyTokenId(tokens)) {
        saveTokens(tokens)
        }
        })

        function saveTokens (tokens) {
        auth.setCredentials(tokens)
        nDebug('auth:token', tokens)
        tokenStore.tokens = tokens
        }

        /**
        * Generate a url for authentication
        *
        * @returns {string} Authentication url
        */
        function getUrl () {
        return auth.generateAuthUrl({
        access_type: 'offline',
        prompt: 'consent',
        scope
        })
        }

        /**
        * Store token upon oauth callback
        *
        * @param {string} code Access code from auth callback
        * @returns {Object} tokens
        */
        async function tokenCallback(code) {
        const { tokens } = await auth.getToken(code)
        return tokens
        }

        /**
        * Acquires profile information and verifies ID against adminID
        *
        * @param {Object} tokens
        * @returns {Boolean}
        */
        async function verifyTokenId (tokens) {
        const info = jwt.decode(tokens.id_token)
        //const info = await auth.getTokenInfo(tokens.access_token)
        return info.sub === adminID
        }

        function getRouter () {
        const router = require('express').Router()

        router.get('/redirect', (req, res) => {
        res.redirect(getUrl())
        })

        router.get('/kappa', async (req, res) => {
        const data = await publicMethods.listAllUpcomingEvents() /* Use calendar functions like this */
        res.send(data)
        })

        router.get('/', async (req, res) => {
        try {
        const tokens = await tokenCallback(req.query.code)
        nDebug('tokens', tokens)
        if (!verifyTokenId(tokens)) {
        return res.status(403).send(http.STATUS_CODES['403'])
        }

        return res.send(info)

        } catch (e) {
        nDebug('error', e.data || e)
        res.status(500).send(e.data || e)
        }
        })

        return router
        }

        /**
        * Debugging class
        *
        * @param {string} string describing who calls the function
        * @param {function} callback function
        */
        function nDebug (who, what) {
        console.log(moment().format(), who)
        console.dir(what, {color: true, depth: 3})
        console.log('#/', who)
        }

        /**
        * Singleton class to store and retrieve tokens
        *
        * @class TokenStore
        */
        class TokenStore {
        /**
        * Creates an instance of TokenStore.
        * @param {Object} tokens - Collection of tokens to store
        * @param {string} tokens.access_token - Access token
        * @param {string} tokens.refresh_token - Refresh token
        * @memberof TokenStore
        */
        constructor (tokens) {
        this._tokens = tokens
        }

        /**
        * Returns stored tokens
        *
        * @memberof TokenStore
        */
        get tokens () {
        return this._tokens
        }

        /**
        * Set tokens on TokenStore and writes them to file
        *
        * @memberof TokenStore
        */
        set tokens (tokens) {
        this._tokens = tokens
        TokenStore.saveToFile(tokens)
        }

        /**
        * Tries to load tokens from file, creates a blank TokenStore if none was found
        *
        * @static
        * @returns {TokenStore} New instance of TokenStore
        * @memberof TokenStore
        */
        static tryLoadOrMakeNew () {
        try {
        const data = this.loadFromFile()
        nDebug('token loaded', data)
        setImmediate(() => saveTokens(data))
        return new this(data)
        } catch (err) {
        if(err.code === 'ENOENT') {
        nDebug('no token loaded', {})
        return new this()
        } else {
        throw err /* Bollocks, something more serious is wrong, better throw up */
        }
        }
        }

        static loadFromFile () {
        return JSON.parse(fs.readFileSync(this.filePath(), this.opts()))
        }

        static saveToFile (tokens) {
        return fs.writeFileSync(this.filePath(), JSON.stringify(tokens, null, 2), this.opts())
        }

        static opts () {
        return { encoding: 'utf-8' }
        }

        static filePath () {
        return 'tokens.json'
        }
        }

        /* I feel ashamed */
        const tokenStore = TokenStore.tryLoadOrMakeNew()

        module.exports = Object.assign(google, publicMethods, { getRouter })


        In the end when we get a response from Google and get refresh tokens and access_token, then we store it locally to a "token.json" file.



        Beware if you use nodemon to run your application, you have to change your npm start in package.json to "start": "nodemon --ignore 'tokens.json' app.js"



        I will update answer if questions og corrections arise in the comments.






        share|improve this answer












        So I ended up calling upon the help of a friend. This resultet in the following solution.



        One of my problems was that when you, use Googles quickstart for NodeJS to connect to the Calendar API, that code will ask you to manually update your tokens through a browser. So we had to combat this problem. The second problem I had was that my code did not execute in the correct order. This was, as is so many things in JS, an async/await problem.



        The following file shows the code logic behind "correct" authentication against the Google Calendar API if you want to automate this, using a single user.



        const http = require('http')
        const fs = require('fs')
        const moment = require('moment')
        const jwt = require('jsonwebtoken')
        const { google } = require('googleapis')

        const { GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET, GOOGLE_REDIRECT_URIS } = process.env
        const scope = ['https://www.googleapis.com/auth/calendar',
        'https://www.googleapis.com/auth/plus.login',
        'https://www.googleapis.com/auth/plus.me',
        'https://www.googleapis.com/auth/userinfo.email',
        'https://www.googleapis.com/auth/userinfo.profile']

        // adminID omitted
        const adminID = '123456789101112131415'

        const auth = new google.auth.OAuth2(GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET, GOOGLE_REDIRECT_URIS)
        google.options({ auth })

        const calendar = google.calendar({version: 'v3'})

        const publicMethods = {
        async listAllUpcomingEvents() {
        const { data } = await calendar.events.list({
        // correct calendarId omitted
        calendarId: 'primary',
        timeMin: (new Date()).toISOString(),
        maxResults: 10,
        singleEvents: true,
        orderBy: 'startTime'
        })
        return data
        }
        /* Make all your calendar methods like shown here */
        }

        auth.on('tokens', (tokens) => {
        if(verifyTokenId(tokens)) {
        saveTokens(tokens)
        }
        })

        function saveTokens (tokens) {
        auth.setCredentials(tokens)
        nDebug('auth:token', tokens)
        tokenStore.tokens = tokens
        }

        /**
        * Generate a url for authentication
        *
        * @returns {string} Authentication url
        */
        function getUrl () {
        return auth.generateAuthUrl({
        access_type: 'offline',
        prompt: 'consent',
        scope
        })
        }

        /**
        * Store token upon oauth callback
        *
        * @param {string} code Access code from auth callback
        * @returns {Object} tokens
        */
        async function tokenCallback(code) {
        const { tokens } = await auth.getToken(code)
        return tokens
        }

        /**
        * Acquires profile information and verifies ID against adminID
        *
        * @param {Object} tokens
        * @returns {Boolean}
        */
        async function verifyTokenId (tokens) {
        const info = jwt.decode(tokens.id_token)
        //const info = await auth.getTokenInfo(tokens.access_token)
        return info.sub === adminID
        }

        function getRouter () {
        const router = require('express').Router()

        router.get('/redirect', (req, res) => {
        res.redirect(getUrl())
        })

        router.get('/kappa', async (req, res) => {
        const data = await publicMethods.listAllUpcomingEvents() /* Use calendar functions like this */
        res.send(data)
        })

        router.get('/', async (req, res) => {
        try {
        const tokens = await tokenCallback(req.query.code)
        nDebug('tokens', tokens)
        if (!verifyTokenId(tokens)) {
        return res.status(403).send(http.STATUS_CODES['403'])
        }

        return res.send(info)

        } catch (e) {
        nDebug('error', e.data || e)
        res.status(500).send(e.data || e)
        }
        })

        return router
        }

        /**
        * Debugging class
        *
        * @param {string} string describing who calls the function
        * @param {function} callback function
        */
        function nDebug (who, what) {
        console.log(moment().format(), who)
        console.dir(what, {color: true, depth: 3})
        console.log('#/', who)
        }

        /**
        * Singleton class to store and retrieve tokens
        *
        * @class TokenStore
        */
        class TokenStore {
        /**
        * Creates an instance of TokenStore.
        * @param {Object} tokens - Collection of tokens to store
        * @param {string} tokens.access_token - Access token
        * @param {string} tokens.refresh_token - Refresh token
        * @memberof TokenStore
        */
        constructor (tokens) {
        this._tokens = tokens
        }

        /**
        * Returns stored tokens
        *
        * @memberof TokenStore
        */
        get tokens () {
        return this._tokens
        }

        /**
        * Set tokens on TokenStore and writes them to file
        *
        * @memberof TokenStore
        */
        set tokens (tokens) {
        this._tokens = tokens
        TokenStore.saveToFile(tokens)
        }

        /**
        * Tries to load tokens from file, creates a blank TokenStore if none was found
        *
        * @static
        * @returns {TokenStore} New instance of TokenStore
        * @memberof TokenStore
        */
        static tryLoadOrMakeNew () {
        try {
        const data = this.loadFromFile()
        nDebug('token loaded', data)
        setImmediate(() => saveTokens(data))
        return new this(data)
        } catch (err) {
        if(err.code === 'ENOENT') {
        nDebug('no token loaded', {})
        return new this()
        } else {
        throw err /* Bollocks, something more serious is wrong, better throw up */
        }
        }
        }

        static loadFromFile () {
        return JSON.parse(fs.readFileSync(this.filePath(), this.opts()))
        }

        static saveToFile (tokens) {
        return fs.writeFileSync(this.filePath(), JSON.stringify(tokens, null, 2), this.opts())
        }

        static opts () {
        return { encoding: 'utf-8' }
        }

        static filePath () {
        return 'tokens.json'
        }
        }

        /* I feel ashamed */
        const tokenStore = TokenStore.tryLoadOrMakeNew()

        module.exports = Object.assign(google, publicMethods, { getRouter })


        In the end when we get a response from Google and get refresh tokens and access_token, then we store it locally to a "token.json" file.



        Beware if you use nodemon to run your application, you have to change your npm start in package.json to "start": "nodemon --ignore 'tokens.json' app.js"



        I will update answer if questions og corrections arise in the comments.







        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered Nov 19 at 9:08









        IncrediblePony

        238




        238






























            draft saved

            draft discarded




















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.





            Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


            Please pay close attention to the following guidance:


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53262053%2fnodejs-google-calendar-api-integration-not-authenticated-and-returns-undefined%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            List item for chat from Array inside array React Native

            Thiostrepton

            Caerphilly