アプリを接続する
アプリの OAuth クライアントと Google Calendar SDK クライアントの接続先を Calendarpit に切り替えつつ、本番の Google 設定も維持する方法を説明します。
プロバイダーの切り替えを追加する
Calendarpit を使うには、アプリ側で接続先を明示的に切り替える必要があります。Calendarpit を起動しても、Google 宛ての通信が自動的にインターセプトされるわけではありません。
ローカル開発や自動テストで Calendarpit を使うには、接続先の切り替えを追加します。追加する場所は、OAuth クライアントと Google Calendar SDK クライアントを初期化するコードです。
CALENDARPIT_URL のような環境変数名は、アプリ側で自由に決められます。Google SDK が CALENDARPIT_URL を自動で読み込むことはありません。アプリの初期化コードで設定を読み込み、ローカルの URL を SDK に渡してください。
認証情報はプロバイダーごとに分けて管理してください。
- Calendarpit のアクセストークンとリフレッシュトークンは、ローカルのプロバイダーでのみ使用します。
- 本番の Google クライアントシークレットとトークンは、Google 用の設定にのみ保持します。
本物の Google 認証情報を Fixture に含めないでください。
すべてのプロバイダーエンドポイントを上書きする
次の 5 つのエンドポイントをすべて上書きしてください。Calendar API の URL を変更するだけでは不十分です。
OAuth のエンドポイントがデフォルトのままだと、次のリクエストが Google に送信されてしまいます。
- ブラウザのリダイレクト
- トークン交換
- トークン更新
| 用途 | ローカルのエンドポイント |
|---|---|
| 認可画面 | http://127.0.0.1:4173/oauth/authorize |
| 認可コードの交換とトークンの更新 | http://127.0.0.1:4173/oauth/token |
| ユーザープロフィール | http://127.0.0.1:4173/userinfo |
| Calendar API のルート | http://127.0.0.1:4173/ |
| トークンの取り消し | http://127.0.0.1:4173/oauth/revoke |
SDK ごとの Calendar API URL の形式
Calendar API の URL の指定方法は SDK ごとに異なります。
- JavaScript(
@googleapis/calendar):rootUrlの末尾に/calendar/v3/...を付与します。rootUrlに/calendar/v3を含めないでください。 - Python・Go・.NET:
/calendar/v3/を含むサービス URL 全体を指定します。 - Java: ルート URL とサービスパスを別々に設定します。
詳しくはSDK の使用例を参照してください。
watch のコールバック先アドレス
watch のコールバック先アドレスは、通信の向きが逆になります。Calendarpit からアプリ側へ送信されます(例: http://127.0.0.1:4175/notifications)。
デフォルトで許可されるコールバック先のホストは、ループバック(127.0.0.1、localhost、[::1])のみです。それ以外のホストを使う場合は、CALENDARPIT_WATCH_HOSTS で指定してください。詳しくはwatch 通知を参照してください。
テスト用の OAuth クライアントを登録する
Fixture の clients 配列にアプリを登録してください。Calendarpit は次の値を検証します。
- 認可エンドポイント:
client_idとredirect_uri /oauth/token:client_idとclient_secret。認可コードの交換時はredirect_uriも検証します。
{
"clients": [
{
"id": "my-app",
"secret": "local-test-secret",
"redirectUris": ["http://127.0.0.1:3000/auth/google/callback"]
}
]
}次の 2 つのフィールドに注意してください。
redirectUrisには、アプリのコールバック URL を正確に指定します。Calendarpit はredirect_uriを文字列の完全一致で照合します。ポートのワイルドカードや末尾スラッシュの正規化は行いません。secretは必須です。PKCE フローを含め、すべての/oauth/tokenリクエストでこの値をclient_secret(または HTTP Basic 認証)として送信する必要があります。
Fixture が適用されるタイミング
Fixture はワークスペース全体を置き換えます。clients とあわせて users と calendars も含めてください。サンプルアプリも使う場合は、sample-app のエントリも残します。
Fixture が反映されるタイミングは、渡し方によって異なります。
- 起動時 Fixture: 新規データベースまたは
:memory:セッションでのみ適用されます。 - 実行中または保存済みのワークスペース:
POST /__calendarpit/fixturesで Fixture を読み込むか、新しいデータベースで起動してください。
ワークスペースをリセットすると、API で読み込んだ Fixture ではなく、起動時 Fixture の状態に戻ります。リセット後もクライアント定義を維持するには、次のいずれかを行ってください。
- 新規データベースまたは
:memory:セッションの起動時 Fixture(--configまたはCALENDARPIT_CONFIG)として渡す。 - リセットのたびに Fixture を読み込み直す。
詳しくはFixtureを参照してください。
組み込みのクライアント
組み込みのデフォルト Fixture には、ローカルテスト用の OAuth クライアントが 1 件登録されています。
- クライアント ID:
sample-app - クライアントシークレット:
local-sample-secret(公開されているローカルテスト用の値) - リダイレクト URI:
http://127.0.0.1:4175/callback
認可コード、トークン更新、/userinfo、取り消しまでの一連のフローは、ローカル OAuthを参照してください。
JavaScript の OAuth クライアントと Calendar クライアント
@googleapis/calendar と google-auth-library を使う場合は、次の 2 つを設定します。
OAuth2Clientのendpoints- Calendar クライアントの
rootUrl
import { calendar } from '@googleapis/calendar';
import { OAuth2Client } from 'google-auth-library';
const origin = 'http://127.0.0.1:4173';
const auth = new OAuth2Client({
clientId: 'sample-app',
clientSecret: 'local-sample-secret',
redirectUri: 'http://127.0.0.1:4175/callback',
endpoints: {
oauth2AuthBaseUrl: `${origin}/oauth/authorize`,
oauth2TokenUrl: `${origin}/oauth/token`,
oauth2RevokeUrl: `${origin}/oauth/revoke`,
},
});
const api = calendar({ version: 'v3', auth, rootUrl: origin });
// After the callback: auth.setCredentials((await auth.getToken(code)).tokens)
const profile = await auth.request({ url: `${origin}/userinfo` });
const calendars = await api.calendarList.list();
const { data } = await api.freebusy.query({
requestBody: {
timeMin: '2026-10-19T00:00:00+09:00',
timeMax: '2026-10-20T00:00:00+09:00',
items: [{ id: 'primary' }],
},
});
console.log(data.calendars?.primary?.busy);スコープ
この例の 3 つの呼び出しをすべて実行できるよう、必要なスコープを含めて認可してください。たとえば auth.generateAuthUrl({ access_type: 'offline', scope: ['https://www.googleapis.com/auth/calendar', 'email', 'profile'] }) のように指定します。
calendarList.listには、calendar、calendar.readonly、calendar.calendarlist、calendar.calendarlist.readonlyのいずれかが必要です。calendar.eventsやcalendar.freebusyのような狭いスコープでは呼び出せません。/userinfoには、openid、email、profile、またはuserinfo.*のスコープが必要です。emailはメールスコープがある場合のみ、nameはプロフィールスコープがある場合のみ返されます。- リフレッシュトークンは、
access_type=offlineを指定した場合のみ発行されます。
スコープの一覧はローカル OAuthを参照してください。
トークン更新と未対応のヘルパー
auth.setCredentials で認証情報を設定すると、OAuth2Client によるトークン更新リクエストもローカルの oauth2TokenUrl に送られます。
一方、getTokenInfo や verifyIdToken などの OAuth2Client のヘルパーは、引き続き Google へ通信します。これを避けるには、サンプルアプリのように tokenInfoUrl と証明書 URL も上書きする必要があります。
Calendarpit には対応するエンドポイントがなく、ID トークンも発行しません。ローカルプロバイダーに対してこれらのヘルパーを呼び出さないでください。
Python や Go など他の言語については、SDK の使用例を参照してください。
参考実装のサンプルアプリ
リポジトリには、@googleapis/calendar と google-auth-library を使ったサンプルアプリが含まれています。Calendarpit の配布パッケージには含まれていません。独自のアプリを接続する場合は不要です。
試す場合は、開発ガイドに従ってソースコードをチェックアウトします。そのうえで、別々のターミナルで次のコマンドを実行してください。
# Terminal 1: start the packaged server
calendarpit serve
# Terminal 2: from the prepared source checkout
bun run sample:devCalendarpit は http://127.0.0.1:4173、サンプルアプリは http://127.0.0.1:4175 で起動します。
参考になる仕組み
サンプルアプリは、単一の接続を扱うローカルデモです。アプリ実装の参考になる次の 2 つの仕組みを含んでいます。
- state Cookie の検証: OAuth の
stateパラメータを、有効期間 5 分の HttpOnly Cookie(sample_state)に保存します。認可コードを交換する前に、/callbackでその値を検証します。 - ループバック限定の送信ガード: SDK が送信するリクエストのうち、宛先ホストが
127.0.0.1・localhost・[::1]以外のものをブロックします。HTTP リダイレクトも拒否します。これにより、誤って本物の Google サーバーへリクエストが送信されるのを防ぎます。
環境変数
サンプルアプリは次の環境変数を使用します。
| 環境変数 | デフォルト |
|---|---|
CALENDARPIT_URL | http://127.0.0.1:4173 |
SAMPLE_PORT | 4175 |
SAMPLE_CLIENT_ID | sample-app |
SAMPLE_CLIENT_SECRET | local-sample-secret |
AUTHORIZATION_URL | ${CALENDARPIT_URL}/oauth/authorize |
TOKEN_URL | ${CALENDARPIT_URL}/oauth/token |
USERINFO_URL | ${CALENDARPIT_URL}/userinfo |
CALENDAR_API_URL | ${CALENDARPIT_URL} |
サンプルアプリは、次の値も設定します。
- 取り消し URL:
${CALENDARPIT_URL}/oauth/revoke - リダイレクト URI:
http://127.0.0.1:<SAMPLE_PORT>/callback
組み込みの sample-app クライアントに登録されているのは、ポート 4175 のみです。SAMPLE_PORT を変更する場合は、Fixture の redirectUris もあわせて更新してください。
接続設定のチェックリスト
アプリで Calendarpit との連携を運用する際は、次の点を確認してください。
- 全エンドポイントの上書き: 認可、トークン交換、トークン更新、ユーザープロフィール、Calendar API の呼び出し、トークン取り消しが、すべてローカルのエンドポイントに向いていること。
- コールバックの到達性:
- ブラウザからアプリの OAuth
redirect_uriにアクセスできること。 - Calendarpit からアプリの watch 用 Webhook アドレスに到達できること。Webhook のホストがループバック以外の場合は、
CALENDARPIT_WATCH_HOSTSを設定します。
- ブラウザからアプリの OAuth
- 一連のフローの検証: ログイン、イベントの読み書き、watch 通知、トークン更新、取り消し、ワークスペースのリセットを通じて、UI とバックグラウンドワーカーをテストすること。
- アプリ固有の Fixture 管理: アプリ固有の Fixture や E2E テストのシナリオは、アプリ側のリポジトリで管理すること。