You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Node.js开发Google Calendar应用遇权限错误:未设置访问/刷新令牌或API密钥

问题:Node.js Google Calendar 应用报错 Error: No access, refresh token or API key is set.

我正在使用Node.js开发一款访问Google Calendar的应用,遵循了Google官方的快速入门步骤,但运行时出现错误:Error: Error: No access, refresh token or API key is set.。

我已完成以下操作:

  • 创建了凭证;
  • 下载了JSON文件并重命名为client_secret.json,放置在应用目录中。

以下是我的代码:

const fs = require('fs'); 
const readline = require('readline'); 
const {google} = require('googleapis'); 
const OAuth2Client = google.auth.OAuth2; 

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

try { 
  const content = fs.readFileSync('client_secret.json'); 
  authorize(JSON.parse(content), listEvents); 
} catch (err) { 
  return console.log('Error loading client secret file:', err); 
} 

function authorize(credentials, callback) { 
  const {client_secret, client_id, redirect_uris} = credentials.installed; 
  let token = {}; 
  const oAuth2Client = new OAuth2Client(client_id, client_secret, redirect_uris[0]); 

  // Check if we have previously stored a token. 
  try { 
    token = fs.readFileSync(TOKEN_PATH); 
  } catch (err) { 
    return getAccessToken(oAuth2Client, callback); 
  } 
  oAuth2Client.setCredentials(JSON.parse(token)); 
  callback(oAuth2Client); 
} 

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 callback(err); 
      oAuth2Client.setCredentials(token); 

      // Store the token to disk for later program executions 
      try { 
        fs.writeFileSync(TOKEN_PATH, JSON.stringify(token)); 
        console.log('Token stored to', TOKEN_PATH); 
      } catch (err) { 
        console.error(err); 
      } 
      callback(oAuth2Client); 
    }); 
  }); 
} 

function listEvents(auth) { 
  const calendar = google.calendar({version: 'v3', auth}); 
  calendar.events.list({ 
    calendarId: 'primary', 
    timeMin: (new Date()).toISOString(), 
    maxResults: 10, 
    singleEvents: true, 
    orderBy: 'startTime', 
  }, (err, {data}) => { 
    if (err) return console.log('The API returned an error: ' + err); 
    const events = data.items; 
    if (events.length) { 
      console.log('Upcoming 10 events:'); 
      events.map((event, i) => { 
        const start = event.start.dateTime || event.start.date; 
        console.log(`${start} - ${event.summary}`); 
      }); 
    } else { 
      console.log('No upcoming events found.'); 
    } 
  }); 
}

解决思路

一眼就揪出问题啦——你把凭证文件和token文件用了同一个路径!

看代码里这行:

const TOKEN_PATH = './client_secret.json';

第一次运行时,程序找不到token会触发授权流程,但当你输入授权码后,程序会把获取到的token直接写入client_secret.json,把原本的凭证文件彻底覆盖了!

第二次运行时,程序读取的client_secret.json已经是token内容,authorize函数里尝试从credentials.installed取client_id、client_secret这些字段自然取不到,OAuth2Client没有正确设置凭证,调用API时就抛出了那个错误。

具体修复步骤:

  1. 恢复凭证文件:重新从Google Cloud Console下载凭证JSON,重命名为client_secret.json放回项目目录。
  2. 修改TOKEN_PATH:把token文件路径改成另一个独立的名字,比如token.json:
    const TOKEN_PATH = './token.json';
    
  3. 重新运行程序:这次程序会正常引导你完成授权,token会被写入token.json,再也不会覆盖凭证文件了。

额外提个小建议:记得把client_secret.json加入.gitignore,别不小心把敏感凭证提交到代码仓库里哦。

内容的提问来源于stack exchange,提问作者Bruno Araújo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 07:11:27