SharePoint Online のサブサイトをベンダー製クローラでクロールしようとしたら 401 エラーで止まる、開始 URL がルートサイトにリダイレクトされて正しいのか分からない──そんな場面で「何をどう直せばよいか」を、アカウント設計・権限・認証方式・ネットワークの観点からまとめて整理します。
想定シナリオとゴールイメージ
まずは、よくある前提条件を整理しておきます。
- 対象は Microsoft 365 上の SharePoint Online(SPO)
- ベンダー製クローラから、特定のサブサイトだけをクロールしたい
- すでに以下のようなアカウントを用意済み
- サービス用ユーザー(ID/PW あり、インタラクティブサインイン可能)
- 通常ユーザー
- いずれも対象サイト コレクションの「サイト コレクション管理者」に追加済み
- 対象サイトの「訪問者」権限(読み取り)も付与済み
- しかし、クローラ実行時に 401 Unauthorized が返ってクロールできない
- クローラ側は Basic 認証(ID/PW のみ)で SPO にアクセスしようとしている
- 開始 URL のサブサイトから、サイト コレクションのルートへリダイレクトされている
本記事のゴールは、次の 3 点です。
- リダイレクトの挙動が正しいかどうかを理解する
- 401 エラーの根本原因を切り分ける(権限か、認証方式か)
- ベンダーに依頼すべき「正しいクロール方式(アプリのみ認証)」を具体的に設計する
サブサイトからルートサイトへリダイレクトされるのは正常か
まず、開始 URL をサブサイトにしているのに、アクセスするとサイト コレクション ルートにリダイレクトされる、という挙動についてです。
結論から言うと、これは SharePoint Online ではよくある正常な動作 です。特に以下のようなケースでは、URL を指定しても内部的にルート側へリダイレクトされることがあります。
- モダンサイトでホームページがルートに統合されている
- ルートサイト置き換え(Root site swap)を実施している
- 旧 URL が新 URL に転送されるように設定されている
クロールの観点では、URL がルートにリダイレクトされたとしても、クロール開始 URL はルートでもサブサイトでもどちらでも問題ありません。重要なのは「クロールの範囲」をクローラ側で適切に絞り込むことです。
| 観点 | サブサイトを開始 URL にする | サイト コレクション ルートを開始 URL にする |
|---|---|---|
| リダイレクトの有無 | 構成によってはルートにリダイレクトされる | 基本的にリダイレクトは発生しにくい |
| クロール範囲の制御 | URL パターンで配下のみに限定することが望ましい | 同様に URL パターンで配下サイトへ限定する必要あり |
| おすすめ度 | ルートにリダイレクトされるなら無理に固執しなくてよい | ルート開始+パス制御の方がシンプルな場合も多い |
したがって、「サブサイトを指定したのにルートに飛ばされる=設定ミス」というわけではなく、リダイレクトはひとまず正常と捉えてよいと考えてください。
401 Unauthorized が出る本当の理由:Basic 認証は使えない
次に本題の 401 エラーです。
SharePoint Online を含む Microsoft 365 では、オンプレミス時代と異なり、クラウド側で Basic 認証がサポートされていません(一部レガシープロトコルを除き、基本的に廃止済みと考えてよい状況です)。
そのため、クローラがいくら正しいユーザー名・パスワードを送っていても、「認証方式」自体が受け付けられず 401 になる という状態になります。これは、サイト コレクション管理者に入っているかどうか、訪問者権限を持っているかどうかとは無関係に発生します。
| 状況 | ユーザー権限 | 認証方式 | 結果 |
|---|---|---|---|
| 今回のケース | 十分(管理者+訪問者) | Basic 認証 | 401(認証自体が拒否) |
| 推奨パターン | アプリにサイト単位の Read 権限 | モダン認証(OAuth 2.0) | 200 / 403 など(少なくとも認証は成功) |
ポイントは次の通りです。
- 401 は「パスワードが間違っている」だけではなく、「そもそも認証方式が許可されていない」場合にも発生する
- SharePoint Online は モダン認証(OAuth 2.0 / OpenID Connect) を前提としており、クライアント資格情報フロー(client credentials)によるアプリのみ認証 が標準的なパターン
- サービスユーザーにどれだけ権限を盛っても、Basic 認証のままでは問題は解消しない
どんなアカウントを用意すべきか:ユーザーではなく「アプリ」
ここで重要なのが、クロールに使う「主体(principal)」をどう設計するかです。
サービスユーザー方式の限界
オンプレミス SharePoint の頃は、クロール用に専用ユーザーを作成し、パスワードを共有してクローラに設定する、というやり方が一般的でした。しかしクラウド時代には、次のような問題を抱えやすくなります。
- セキュリティポリシー上、MFA(多要素認証)や条件付きアクセス が必須になる
- パスワードの有効期限やリスクベースポリシーにより、ある日突然ログインできなくなる
- 人事異動・退職などのタイミングでアカウント棚卸しが行われると、誰も管理していないサービスユーザーが削除対象になる
- 「誰が」「何の目的で」そのアカウントを使っているのかが監査ログ上で曖昧になる
結果として、運用が不安定かつ監査上も望ましくない 状態になりがちです。
アプリ(サービス プリンシパル)方式のメリット
これに対して Microsoft が推奨しているのは、Microsoft Entra ID(旧 Azure AD)上のアプリ登録を使った「アプリのみ認証」 です。
概略のイメージは次のようになります。
ベンダークローラ ──> Entra ID トークンエンドポイント
│ (クライアント資格情報フロー)
│ アプリID + 証明書/シークレットで認証
↓
アクセストークン(Bearer トークン)を取得
│
├─> Microsoft Graph API
└─> SharePoint REST API
この方式のメリットは多くあります。
- ユーザーではなく アプリ単位で権限を管理 できる
- パスワードレス(証明書認証) で安全性を高められる
- アプリごとに 最小権限 を与えられる(Sites.Selected など)
- 「誰が何に使っているアプリか」が Entra ID 上で明確に管理できる
- 条件付きアクセスも サービス プリンシパル単位 で適用できる
| 項目 | サービスユーザー方式 | アプリのみ認証方式 |
|---|---|---|
| 認証方式 | Basic / ユーザーパスワード | OAuth 2.0(クライアント資格情報) |
| 権限の粒度 | ユーザー単位(テナント全体に波及しやすい) | アプリ単位(サイト単位などで細かく制御可能) |
| セキュリティ | パスワード漏洩リスクが高い | 証明書利用やシークレット管理が可能 |
| 運用 | パスワード期限・MFA で止まりやすい | ノンインタラクティブで安定運用しやすい |
| 監査・可視性 | 「誰のログインか」判定しにくい | アプリ名で追跡しやすい |
したがって、新規にクロール方式を設計するのであれば、ユーザーアカウントではなくアプリ(サービス プリンシパル)を主体とした設計に切り替えるのが圧倒的におすすめです。
権限設計の鍵:Microsoft Graph「Sites.Selected」
アプリを作るときに必ず悩むのが、「どこまで見せるか」という権限設定です。
Microsoft Graph で SharePoint サイトにアクセスする場合、代表的なアプリケーション権限は次の通りです。
| 権限名(アプリケーション) | 内容 | リスク | おすすめ度 |
|---|---|---|---|
| Sites.FullControl.All | テナント内のすべてのサイトにフルコントロール | 非常に高い 誤操作時の影響がテナント全体に及ぶ | 基本的に避けるべき |
| Sites.Read.All | テナント内のすべてのサイトを読み取り | 高い 情報漏えいリスクが広範囲 | 要件として全社検索などが明確にある場合のみ |
| Sites.Selected | 既定では何も見えず、管理者が許可したサイトのみアクセス可 | 低い 必要なサイトだけをピンポイントで許可できる | クロール用途に最も推奨 |
本記事のように「特定サブサイトだけクロールしたい」というケースでは、Sites.Selected 一択と言ってよいでしょう。
設計の要点は次の通りです。
- Entra ID 側では「Microsoft Graph > Application > Sites.Selected」を付与する
- 付与しただけでは どのサイトにもアクセスできない
- 別途、PnP PowerShell や Graph API を使い、対象サイトに対してアプリを明示的に許可する
たとえば PnP PowerShell を使う場合は、次のようなコマンドでサイト単位の権限を付与できます。
# 管理者アカウントで対象サイトに接続
Connect-PnPOnline -Url https://contoso.sharepoint.com/sites/target
-Interactive
# アプリ(クライアントID)に Read 権限を付与
Grant-PnPAzureADAppSitePermission `
-AppId "<アプリのクライアントID>" `
-DisplayName "VendorCrawler" `
-Site "https://contoso.sharepoint.com/sites/target" `
-Permissions Read
これにより、アプリ「VendorCrawler」は、指定したサイトに対してのみ読み取りアクセスが可能になります。テナント全体が丸見えになることはありません。
Entra ID アプリ登録からクロール開始までの手順
ここからは、実際にどのような手順で環境を整えるかを、なるべく手戻りがない順番で整理します。
手順 1:Entra ID でアプリ登録を作成
- Microsoft Entra 管理センターに管理者としてサインイン
- 「アプリの登録」から新規登録
- 名前:例)VendorCrawler-SPO
- サポートされているアカウントの種類:通常は「この組織ディレクトリ内のアカウントのみ」
- リダイレクト URI:クライアント資格情報フローのみなら必須ではない
- 登録すると「アプリケーション (クライアント) ID」と「ディレクトリ (テナント) ID」が払い出される
手順 2:証明書またはクライアントシークレットの設定
クローラがトークンを取得するための「鍵」となる情報です。可能であれば 証明書ベース認証 を強く推奨します。
- 証明書を使う場合
- オンプレミスの CA や自己署名証明書で、クライアント認証用証明書を発行
- .cer などの公開鍵をアプリ登録にアップロード
- 秘密鍵(.pfx)はベンダー側で安全に保管(キーマネージャー等)
- クライアントシークレットを使う場合
- アプリ登録の「証明書とシークレット」から新しいクライアントシークレットを発行
- 有効期限をあまり短くしすぎると運用が煩雑になるため注意
- シークレット値は一度しか表示されないので、必ず安全な場所に保管
手順 3:Microsoft Graph API 権限の設定
次に、アプリがどの API にアクセスできるかを定義します。
- アプリ登録の「API のアクセス許可」から「追加」
- 「Microsoft Graph」を選択
- 「アプリケーションの許可」を選択
- Sites.Selected を追加
- テナント管理者による「管理者の同意」が必須
ここではあくまで「このアプリは サイトへのアクセス権を持てる種類のアプリである」ことを宣言しただけです。まだ具体的なサイトにはアクセスできません。
手順 4:対象サイトにアプリの Read 権限を付与
Sites.Selected の真価はここからです。PnP PowerShell などを使い、対象サイトに対してのみ権限を与えます。
# 管理者アカウントで対象サイトに接続
Connect-PnPOnline `
-Url "https://contoso.sharepoint.com/sites/target" `
-Interactive
# すでに付与されているアプリ権限を確認(任意)
Get-PnPAzureADAppSitePermission
# VendorCrawler アプリに Read 権限を付与
Grant-PnPAzureADAppSitePermission `
-AppId "<アプリのクライアントID>" `
-DisplayName "VendorCrawler" `
-Site "https://contoso.sharepoint.com/sites/target" `
-Permissions Read
同様に、別のサイトコレクションをクロールしたい場合は、そのサイトごとに Grant コマンドを実行します。こうすることで、「このベンダークローラは、このサイトとこのサイトだけを読める」という状態を実現できます。
手順 5:クローラ実装をモダン認証対応に変更
最後に、ベンダー側のクローラがトークンを取得して Graph / SharePoint REST を叩くように実装を変更してもらいます。
クライアント資格情報フローの HTTP レベルでのイメージは次の通りです。
POST https://login.microsoftonline.com/<テナントID>/oauth2/v2.0/token
Content-Type: application/x-www-form-urlencoded
client_id=<アプリID>
&client_secret=<シークレットまたは証明書サムプリントなど>
&scope=https%3A%2F%2Fgraph.microsoft.com%2F.default
&grant_type=client_credentials
返ってきた JSON の access_token を、Graph API や SharePoint REST API に対する Authorization: Bearer <token> ヘッダーとして使用します。
ベンダーに対しては、少なくとも次のような要件を提示しておくとよいでしょう。
- Basic 認証ではなく、OAuth 2.0 クライアント資格情報フローに対応していること
- アクセストークンの取得先やスコープを設定可能であること
- 429/503 応答時に Retry-After を尊重してリトライできること
- URL パターン(ホスト名+パス)でクロール範囲を制御できること
Graph / SharePoint REST を使ったクロールの具体例
クローラが扱える API によって実装の詳細は変わりますが、ここでは代表的なパターンを紹介します。
サイト情報の取得
GET https://graph.microsoft.com/v1.0/sites/root: /sites/target-site
Authorization: Bearer <token>
これにより、指定したパスのサイト ID を取得できます。以降は site-id を用いてドライブやリストにアクセスする形になります。
ドキュメント ライブラリの一覧取得
GET https://graph.microsoft.com/v1.0/sites/{site-id}/drives
Authorization: Bearer <token>
ライブラリ内のファイル一覧取得
GET https://graph.microsoft.com/v1.0/drives/{drive-id}/root/children
Authorization: Bearer <token>
差分(増分)取得
大量のファイルを扱う場合は、フルクロールを繰り返すのではなく、Graph の delta API や SharePoint の ChangeToken を活用して増分クロールにするのが現実的です。
GET https://graph.microsoft.com/v1.0/drives/{drive-id}/root/delta
Authorization: Bearer <token>
返ってきた delta リンクを保存しておき、次回はその URL を叩くことで差分だけを取得できます。これにより、ネットワーク負荷・SharePoint への負荷を大幅に抑えることができます。
クロール範囲と負荷をコントロールする
SharePoint Online は SaaS であり、無制限に高頻度でクロールしてよいわけではありません。特にベンダークローラでは、次のような点に注意が必要です。
クロール範囲の制御
- 開始 URL はサイト コレクション ルートでもサブサイトでも構わない
- クローラ側でホスト名(例:
contoso.sharepoint.com)とパス(例:/sites/target/)を指定し、それ以外の URL は除外する - 別のサイト コレクションを同時にクロールする場合は、それぞれに対して Sites.Selected の権限付与が必要
スロットリング(429 / 503)への対応
Microsoft 365 は、過剰なリクエストに対して HTTP 429(Too Many Requests) や 503(Service Unavailable) を返して一時的に制限することがあります。
クローラ側で最低限実装してほしいポイントは以下です。
- 429 / 503 を受け取った場合は 必ずリトライを実装する
- レスポンスヘッダーの
Retry-Afterがあれば、その秒数だけ待ってから再試行する - 同時接続数・リクエストレートを設定できるようにしておき、時間帯や負荷に応じて調整できるようにする
| ステータスコード | 典型的な意味 | 対処方針 |
|---|---|---|
| 200 | 成功 | 特になし |
| 401 | 認証失敗(トークン不正・期限切れ・認証方式不備) | トークン取得処理・スコープ・アプリ設定を確認 |
| 403 | 権限不足 | Sites.Selected のサイト割り当てや権限レベルを確認 |
| 404 | URL / ID が存在しない、またはアクセス権がない | サイト URL・リスト ID の誤り、サイト移動の有無を確認 |
| 429 | リクエスト過多によるスロットリング | Retry-After に従い待機後リトライ。同時実行数も下げる |
| 503 | 一時的なサービス利用不可 | 指数バックオフでリトライ。長期的に続く場合はサポート検討 |
ネットワーク・VPN・条件付きアクセスの考え方
「ベンダーは社外ネットワークから接続するが、VPN を経由させるべきか?」という質問もよくあります。
VPN 経由でのクロールは可能か
答えとしては、技術的には可能だが、必須ではない という形になります。
- SharePoint Online はインターネット上の SaaS であり、基本的には 直接インターネット経由の HTTPS 通信 が推奨
- 社内のセキュリティポリシー上、「外部ベンダーは一度 VPN に収容してからインターネットへ出す」という設計もあり得る
- ただし、VPN を経由させる場合は、M365 推奨のインターネットブレイクアウト設計(SPO への通信だけ直接インターネットへ出す)との整合性を取る必要あり
実務的には、次のようなパターンが多いです。
- ベンダー拠点からの固定グローバル IP をもらい、その IP を Entra ID の「名前付きの場所」に登録
- 条件付きアクセスで「このアプリは、指定した IP 範囲からのアクセスのみ許可」などの制限をかける
- 社内経由にする場合でも、
*.sharepoint.comや*.microsoftonline.comへの HTTPS はプロキシで妨げないように設定
条件付きアクセス(CA)との関係
条件付きアクセスは、ユーザーだけでなく アプリ(サービス プリンシパル)を対象にルールを適用することができます。
- ユーザーサインインには MFA を必須にしつつ、アプリのみ認証は特定 IP からのみ許可する
- レガシー認証(Basic など)を一括ブロックしても、アプリのみ認証には影響しない
- クロール用アプリ専用の CA ポリシーを用意し、「IP 制限+デバイス要件なし」といった柔軟な運用も可能
今回のケースでいえば、Basic 認証は CA 以前に SharePoint Online 側でサポートされていないため、CA の設定をどれだけ見直しても 401 は解消しない、という点に注意してください。
トラブルシューティング早見表
ここまでの内容を踏まえつつ、エラーコード別に切り分けの視点をまとめます。
| エラー | 主な原因 | 確認すべきポイント |
|---|---|---|
| 401 Unauthorized | 認証そのものの失敗 | Basic 認証を使っていないか トークンの有効期限切れ・テナント ID / クライアント ID の誤り スコープが https://graph.microsoft.com/.default になっているか |
| 403 Forbidden | 権限不足 | Sites.Selected に管理者同意を与えているか 対象サイトに対して Grant-PnPAzureADAppSitePermission を実行済みか Read ではなく Write が必要な API を叩いていないか |
| 404 Not Found | リソースが存在しない or 見えない | サイト URL・パスに誤りがないか サイトが別テナントに移動していないか サイト削除・リネームなどの履歴がないか |
| 429 / 503 | スロットリング / 一時エラー | Retry-After を見ているか 同時接続数・1 秒あたりリクエスト数を抑えているか 深夜など負荷の低い時間帯にスケジューリングする検討 |
すぐに着手すべきチェックリスト
ここまでの内容を「今すぐやること」に落とし込むと、次のようになります。
- Basic 認証の使用をやめる
- クローラの設定画面で「Basic 認証」「ユーザー名/パスワードのみ」の指定になっていないか確認
- OAuth 2.0 / OpenID Connect 対応があるかベンダーに確認
- Entra ID でクロール専用アプリを作成
- アプリ登録を作成し、証明書 or クライアントシークレットを設定
- Microsoft Graph の Sites.Selected(アプリケーション権限)を付与し管理者同意
- 対象サイトへのアプリ権限付与
- PnP PowerShell などで Grant-PnPAzureADAppSitePermission を実行
- 必要なサイトだけに Read 権限を与え、余計なサイトは見せない
- クローラ設定の更新
- トークン取得エンドポイント・クライアント ID・シークレット/証明書を設定
- Graph / SharePoint REST を呼び出すように設定変更
- ネットワーク・条件付きアクセスの見直し
- ベンダー出口 IP を把握し、必要に応じて「名前付きの場所」に登録
- アプリ用の条件付きアクセス ポリシーを検討(IP 制限など)
ベンダーと合意しておきたい項目(RFP の観点)
最後に、ベンダーにクロールを依頼する際、要件として明示しておくと後々楽になるポイントを挙げておきます。
- 認証方式
- SharePoint Online / Graph に対して OAuth 2.0 クライアント資格情報フロー をサポートしていること
- Azure AD アプリ ID・シークレット/証明書を設定できること
- 権限モデル
- アプリのみ認証でのクロールに対応していること
- ユーザーアカウント+パスワード前提の実装しかない場合は要注意
- クロール範囲制御
- URL パターンでサイト配下に限定できること
- 除外パス(例:
/SiteAssets/、/Forms/)を指定できること
- 負荷制御とエラー処理
- 429 / 503 へのリトライと指数バックオフに対応していること
- クロールレート・同時接続数を調整できること
- ログと監査
- どの URL にいつアクセスしたかのログを取得できること
- Microsoft 側のサインインログ・監査ログと突き合わせられるようにしておくこと
まとめ:Basic 認証を捨てて「アプリのみ認証」へ
SharePoint Online のクロールで 401 エラーに悩んでいるとき、権限設計やサイト コレクション管理者の設定を疑いがちですが、実際には 認証方式(Basic 認証のまま)こそが根本原因 であることが少なくありません。
クラウド時代のベストプラクティスは、
- ユーザーではなく アプリ(サービス プリンシパル) を主体にする
- Microsoft Graph の Sites.Selected を使ってサイト単位に最小権限を付与する
- クローラは OAuth 2.0 クライアント資格情報フロー でトークンを取得してアクセスする
- ネットワーク・条件付きアクセスでベンダーのアクセス元をきちんと制御する
この方針に切り替えることで、単に 401 を解消するだけでなく、セキュアで運用しやすいクロール基盤 を構築できます。既存の Basic 認証ベースの設計からの移行は多少手間がかかりますが、その価値は十分にあります。ぜひ、本記事の内容をベンダーとの打ち合わせや設計書に落とし込み、安定した SharePoint Online クロール環境を実現してみてください。

コメント