Microsoft Teams カレンダー連携ガイド -- Entra ID アプリ登録から Publisher Verification まで
はじめに
Microsoft Teams(Outlook)のカレンダーとアプリを連携させるには、Microsoft Entra ID(旧 Azure AD)でアプリを登録して、Microsoft Graph API 経由でアクセスする。
Google の GCP 設定と似たような流れだが、Microsoft 独自の概念がいくつかある。「Supported account types」の選び方、Delegated permissions と Application permissions の違い、そしてシークレットに最大24ヶ月の有効期限があるという点は、最初に知っておかないとあとで痛い目を見る。
この記事では、Entra ID でのアプリ登録から API の叩き方、本番公開に必要な Publisher Verification までをまとめた。Google Calendar API との違いも随所で比較している。
全体の流れ
- Microsoft Entra ID でアプリ登録
- API のアクセス許可を追加
- クライアントシークレットの作成
- リダイレクト URI の設定
- API リクエストとレスポンス
- (本番公開時)Publisher Verification
1. Microsoft Entra ID でアプリ登録
- Microsoft Entra admin center にアクセス
- 左メニュー → 「Identity」→「Applications」→「App registrations」
- 「New registration」をクリック
- 以下を入力:
| 項目 | 説明 |
|---|---|
| Name | 任意のアプリ名 |
| Supported account types | 対象ユーザーに応じて選択(下記参照) |
| Redirect URI | 後で設定するので空のまま |
- 「Register」をクリック
- 登録後の画面で以下をコピーして安全な場所に保管:
- Application (client) ID
- Directory (tenant) ID
Supported account types の選択肢
| 値 | 意味 |
|---|---|
| Accounts in any organizational directory and personal Microsoft accounts | 組織 + 個人アカウント両方(最も広い) |
| Accounts in any organizational directory | 組織アカウントのみ(個人 Microsoft アカウント不可) |
| Accounts in this organizational directory only | 自テナントのみ(自社限定) |
| Personal Microsoft accounts only | 個人アカウントのみ |
2. API のアクセス許可を追加
- 左メニュー → 「API permissions」
- 「Add a permission」→「Microsoft Graph」→「Delegated permissions」
- 以下のスコープを追加:
| スコープ | 用途 |
|---|---|
openid | OpenID Connect 認証 |
User.Read | ユーザーのプロフィール・メールアドレス取得 |
Calendars.ReadWrite | カレンダーの予定の読み書き |
offline_access | リフレッシュトークンの取得(バックグラウンド同期に必要) |
- 「Add permissions」をクリック
注意:
Calendars.ReadWriteは管理者の同意が不要な Delegated permission。ユーザーが自分のデータへのアクセスを許可するだけで使える。
3. クライアントシークレットの作成
- 左メニュー → 「Certificates & secrets」
- 「Client secrets」タブ → 「New client secret」
- 以下を入力:
| 項目 | 説明 |
|---|---|
| Description | 任意のラベル |
| Expires | 推奨: 24 months |
- 「Add」をクリック
- 表示される Value(シークレット値)をコピーして安全な場所に保管
注意: シークレット値は作成直後しか表示されません。コピーし忘れたら再作成が必要です。
注意: 有効期限が切れると連携が停止します。期限が近づいたらシークレットを再作成してください。
4. リダイレクト URI の設定
- 左メニュー → 「Authentication」
- 「Add a platform」→「Web」
- 認証後の戻り先 URL を追加:
| 環境 | 例 |
|---|---|
| ローカル開発 | http://localhost:8080/api/auth/callback/microsoft |
| 本番 | https://your-app.example.com/api/auth/callback/microsoft |
- 「Configure」をクリック
追加設定(同じ Authentication ページ)
| 項目 | 推奨値 |
|---|---|
| Front-channel logout URL | 空のまま |
| Implicit grant and hybrid flows | すべてオフ(Authorization Code Flow を使用) |
| Allow public client flows | No |
5. API リクエストとレスポンス
ベース URL:
https://graph.microsoft.com/v1.0
すべてのリクエストに以下のヘッダーが必要:
Authorization: Bearer {アクセストークン}
Content-Type: application/json
5-1. 予定一覧の取得
GET /me/calendar/events?$top=250&$filter=start/dateTime ge '2026-01-01T00:00:00' and end/dateTime le '2026-12-31T23:59:59'&$orderby=start/dateTime HTTP/1.1
レスポンス(HTTP 200)
{
"value": [
{
"id": "AAMkADI2...",
"subject": "会議",
"bodyPreview": "週次定例ミーティング",
"body": { "contentType": "html", "content": "<p>週次定例ミーティング</p>" },
"start": { "dateTime": "2026-04-07T06:30:00.0000000", "timeZone": "UTC" },
"end": { "dateTime": "2026-04-07T07:30:00.0000000", "timeZone": "UTC" },
"isAllDay": false,
"location": { "displayName": "会議室A" },
"organizer": { "emailAddress": { "name": "山田太郎", "address": "user@outlook.com" } },
"isOnlineMeeting": true,
"onlineMeetingProvider": "teamsForBusiness",
"onlineMeeting": { "joinUrl": "https://teams.microsoft.com/l/meetup-join/..." },
"showAs": "busy",
"importance": "normal",
"sensitivity": "normal",
"iCalUId": "040000008200...",
"changeKey": "RlFKaE...",
"createdDateTime": "2026-03-17T06:43:11Z",
"lastModifiedDateTime": "2026-03-17T06:43:11Z",
"webLink": "https://outlook.live.com/owa/?itemid=..."
}
],
"@odata.nextLink": "https://graph.microsoft.com/v1.0/me/calendar/events?$skip=250"
}
レスポンスフィールド一覧
| フィールド | 説明 |
|---|---|
id | イベントの一意識別子。更新・削除に使用 |
subject | タイトル |
body.content | 本文(HTML 形式) |
bodyPreview | 本文のプレビュー(プレーンテキスト) |
start.dateTime | 開始日時(UTC)。終日イベントの場合は 0000-00-00T00:00:00.0000000 形式 |
end.dateTime | 終了日時(UTC) |
start.timeZone / end.timeZone | タイムゾーン(通常 UTC で返る) |
isAllDay | 終日イベントかどうか |
location.displayName | 場所 |
locations | 複数の場所(配列) |
organizer.emailAddress | 主催者のメールアドレスと表示名 |
attendees | 参加者リスト(emailAddress, type, status を含む配列) |
isOnlineMeeting | Teams 会議かどうか |
onlineMeetingProvider | 会議プロバイダー(teamsForBusiness / skypeForBusiness 等) |
onlineMeeting.joinUrl | Teams 会議の参加リンク |
showAs | free / tentative / busy / oof(外出中)/ workingElsewhere / unknown |
importance | low / normal / high |
sensitivity | normal / personal / private / confidential |
iCalUId | iCalendar 形式の一意識別子 |
changeKey | バージョン番号。変更検知に使用 |
isReminderOn | リマインダーが有効か |
reminderMinutesBeforeStart | リマインダーの分数 |
hasAttachments | 添付ファイルがあるか |
recurrence | 繰り返しルール(pattern + range オブジェクト) |
isCancelled | キャンセルされたか |
responseStatus | 自分の出欠状態(response: accepted / tentativelyAccepted / declined 等) |
categories | カテゴリ(色タグ)の配列 |
createdDateTime | 作成日時(UTC) |
lastModifiedDateTime | 最終更新日時(UTC) |
webLink | Outlook 上でこの予定を開く URL |
@odata.nextLink | 次ページがある場合の URL。このURLをそのまま GET して次ページを取得 |
5-2. 予定の作成
POST /me/calendar/events HTTP/1.1
リクエストボディ
{
"subject": "新しい予定",
"body": { "contentType": "text", "content": "テスト予定" },
"start": { "dateTime": "2026-04-10T10:00:00", "timeZone": "Asia/Tokyo" },
"end": { "dateTime": "2026-04-10T11:00:00", "timeZone": "Asia/Tokyo" },
"location": { "displayName": "会議室B" },
"isReminderOn": false
}
レスポンス(HTTP 201 Created)
作成されたイベントオブジェクトが返る(5-1 のフィールドと同じ構造)。id が新規に発行される。
5-3. 予定の更新
PATCH /me/calendar/events/{eventId} HTTP/1.1
リクエストボディ(変更したいフィールドのみ)
{
"subject": "会議(変更後)",
"start": { "dateTime": "2026-04-07T16:00:00", "timeZone": "Asia/Tokyo" },
"end": { "dateTime": "2026-04-07T17:00:00", "timeZone": "Asia/Tokyo" }
}
レスポンス(HTTP 200)
更新後のイベントオブジェクトが返る。
5-4. 予定の削除
Microsoft Graph API では通常の DELETE と完全削除(permanentDelete)がある。
DELETE /me/events/{eventId} HTTP/1.1
- HTTP 204 No Content — 削除成功(ゴミ箱に移動)
POST /me/events/{eventId}/permanentDelete HTTP/1.1
- HTTP 204 No Content — 完全削除成功(ゴミ箱にも残らない)
Google Calendar API との違い
| 項目 | Microsoft | |
|---|---|---|
| タイトル | summary | subject |
| 説明文 | description(プレーンテキスト) | body.content(HTML 対応) |
| 場所 | location(文字列) | location.displayName(オブジェクト) |
| 日時のタイムゾーン | レスポンスにそのまま含まれる | 通常 UTC で返る(Prefer: outlook.timezone ヘッダーで変更可) |
| 会議リンク | hangoutLink | onlineMeeting.joinUrl |
| 公開設定 | visibility (public/private) | sensitivity (normal/private/confidential) |
| 予定の空き表示 | transparency (opaque/transparent) | showAs (busy/free/tentative/oof) |
| ページネーション | nextPageToken パラメータ | @odata.nextLink URL をそのまま GET |
| 削除 | DELETE → 即削除 | DELETE → ゴミ箱 / permanentDelete → 完全削除 |
| 繰り返し | RRULE 文字列 | pattern + range オブジェクト |
6. 本番公開時: Publisher Verification
一般公開するには Publisher Verification(発行者の確認)が推奨。未確認だと同意画面に「未確認の発行者」警告が出る。
前提条件
- Microsoft Cloud Partner Program (MPN) に登録済み(partner.microsoft.com)
- MPN アカウントのドメインが Entra テナントのドメインと一致していること
- アプリ登録の publisher domain が設定済み
手順
- Entra admin center → App registrations → アプリ名
- 左メニュー → 「Branding & properties」
- 「Publisher domain」を確認済みドメインに設定
- 「Publisher verification」→「Verify」
- MPN ID を入力 → 「Verify and save」
- 同意画面に青いバッジが表示されれば完了
管理者の同意が必要な場合
組織によっては IT 管理者の承認が必要。管理者向けの同意 URL:
https://login.microsoftonline.com/{tenant-id}/adminconsent?client_id={client-id}
API スロットリング制限
| 制限 | 上限 | 適用範囲 |
|---|---|---|
| リクエスト数 | 10,000 / 10分 | app x mailbox |
| 同時リクエスト | 4 | app x mailbox |
他プロバイダーとの比較
| 項目 | Microsoft Teams | Apple | LINE WORKS | |
|---|---|---|---|---|
| 認証方式 | OAuth 2.0 | OAuth 2.0 | CalDAV Basic 認証 | OAuth 2.0 / JWT |
| 開発者登録 | GCP プロジェクト | Entra ID アプリ登録 | 不要 | Developer Console |
| Client ID / Secret | 必要 | 必要 | 不要 | 必要 |
| 本番審査 | OAuth Verification (3-5営業日) | Publisher Verification | 不要 | 不要 |
| API 形式 | REST (JSON) | REST (JSON) | CalDAV (XML/ICS) | REST (JSON) |
| シークレット有効期限 | なし | 最大24ヶ月 (要更新) | なし | なし |
注意事項
Client ID・Client Secret は平文でコードに埋め込まないこと。環境変数などで管理する。
Entra ID のシークレットは最大24ヶ月で失効する。失効するとすべてのユーザーの連携が停止するため、期限管理を忘れないこと。
トラブルシューティング
| 症状 | 原因と対処 |
|---|---|
| リダイレクト URI が一致しない (AADSTS50011) | Entra の Authentication に登録した URI とアプリ側の設定が完全一致しているか確認(末尾の / に注意) |
| アプリが見つからない (AADSTS700016) | Client ID が正しいか確認。Tenant ID の設定も確認 |
| シークレットが無効 (AADSTS7000215) | シークレットが期限切れか、値が正しくコピーされていない |
| 管理者の承認が必要 | 組織の IT 管理者がサードパーティアプリを制限している。管理者に承認を依頼 |
| 「未確認の発行者」警告 | Publisher Verification が完了していない(機能には影響しない) |
| 認証後にトークンが取れない | リフレッシュトークンが失効(最大90日)。ユーザーに再度ログインしてもらう |
参考リンク
- Microsoft Entra admin center
- Register an application
- Microsoft Graph API - Calendar
- Microsoft Graph API - Event resource
- Publisher verification
- Outlook service throttling limits
この記事に関連するサービス
TodoONada株式会社では、認証基盤・ID管理の設計から開発・移行までを支援しています。
- 認証基盤・ID管理の開発支援 — IDaaS導入・SSO・パスキー・会員基盤の移行をワンストップで
導入・開発のご相談はお問い合わせからお気軽にどうぞ。検討段階のご相談も歓迎です。