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

使用服务账号调用Google Calendar Events Watch遇401 Unauthorized错误

Fixing 401 Unauthorized for Google Calendar Events Watch with Service Accounts

Alright, let's tackle that 401 error you're hitting when setting up calendar event watches—especially since you can already list calendars successfully. Here's what's going wrong and how to fix it:

1. Your Axios Request Structure Is Incorrect

The biggest issue here is how you're passing the watch configuration to Axios. Right now, you're mixing the request body data (the type and address for the webhook) with the request headers/config. Axios expects the post body as the second parameter, and the headers/config as the third.

Your current code sends the headers and webhook data together as the request body, which Google doesn't recognize—leading to authentication failure. Here's the corrected version:

let { google } = require("googleapis");
let privatekey = require("../config.json");
let axios = require("axios");

async function main() {
  const client = new google.auth.JWT(
    privatekey.client_email,
    null,
    privatekey.private_key,
    [
      "https://www.googleapis.com/auth/calendar",
      "https://www.googleapis.com/auth/calendar.readonly"
    ]
  );

  const token = await client.authorize();
  
  // Separate the watch body from the request headers
  const watchRequestBody = {
    type: "web_hook",
    address: "https://rguc-calendars.firebaseapp.com/notifications"
  };

  const requestConfig = {
    headers: {
      "Content-Type": "application/json;charset=UTF-8",
      Authorization: `${token.token_type} ${token.access_token}`
    }
  };

  try {
    const response = await axios.post(
      "https://www.googleapis.com/calendar/v3/calendars/rguc.co.uk_5hbugn8f7a4j3g7p6im1r1s1co@group.calendar.google.com/events/watch",
      watchRequestBody,
      requestConfig
    );
    console.log("Watch setup successful:", response.data);
  } catch (error) {
    console.error("Error setting up watch:", error.response?.data || error.message);
  }
}

main();

2. Double-Check Critical Setup Details

Even with fixed code, a few other things could cause 401s:

  • Webhook Domain Verification: Ensure the domain of your webhook address (firebaseapp.com) is properly verified in your Google Cloud Console. Google requires this for push notifications to prevent spam.
  • Service Account Calendar Permissions: Confirm the service account email (googlecalendarservice@eventapi-219011.iam.gserviceaccount.com) is added as a member to the target calendar with at least "See all event details" permissions (or higher if you need to act on changes).
  • Token Validity: While client.authorize() fetches a fresh token, you can log token.access_token to confirm it's a valid, non-expiring (for the moment) token.

3. Correct Credential Type to Use

From your list of credentials, you should stick with Service account keys (the one labeled 5ac83bf728fc9f3f635cec8096170573620dd388 for GoogleCalendarService). Here's why:

  • API keys only work for public, unauthenticated endpoints—they can't access user-specific calendar data or set up watches.
  • OAuth 2.0 client IDs are for user-facing apps where a human logs in to grant permissions. They don't fit your server-to-server use case.
  • Service account keys are designed exactly for this scenario: server-side, no-user-interaction access to Google APIs with pre-granted permissions.

Give the corrected code a shot, and verify those setup details—you should be able to get the watch endpoint working without the 401.

内容的提问来源于stack exchange,提问作者Bomber

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 04:14:24