アプリとつなぐ

アプリを接続する

アプリの 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:dev

Calendarpit は 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_URLhttp://127.0.0.1:4173
SAMPLE_PORT4175
SAMPLE_CLIENT_IDsample-app
SAMPLE_CLIENT_SECRETlocal-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 を設定します。
  • 一連のフローの検証: ログイン、イベントの読み書き、watch 通知、トークン更新、取り消し、ワークスペースのリセットを通じて、UI とバックグラウンドワーカーをテストすること。
  • アプリ固有の Fixture 管理: アプリ固有の Fixture や E2E テストのシナリオは、アプリ側のリポジトリで管理すること。

目次