これまで Python のスクリプトで SharePoint に自動アクセスできていたのに、ある日突然 ValueError: An error occurred while retrieving auth cookies … wsignin1.0 が出て止まってしまう――。本記事では、このトラブルの正体と、再発しないためのモダン認証(Microsoft Entra ID+OAuth2)への具体的な移行手順を詳しく解説します。
SharePoint の wsignin1.0 で認証クッキーが取得できない問題とは
まず、今回のトラブルの典型的な状況を整理します。
- Python の Office365-REST-Python-Client を使用
UserCredential(ユーザー名+パスワード)で SharePoint Online に接続https://{tenant}.sharepoint.com/_forms/default.aspx?wa=wsignin1.0にアクセスしてFedAuth/rtFaなどのクッキーを取得- 取得したクッキーを使って SharePoint ファイルや API にアクセス
- ある日から次のようなエラーで失敗し始めた
ValueError: An error occurred while retrieving auth cookies for url https://{tenant}.sharepoint.com/_forms/default.aspx?wa=wsignin1.0
コードを変えていないのに突然失敗するため、「ライブラリのバグ? SharePoint 側の障害?」と思いがちですが、多くの場合、根本原因は次のどれかです。
- テナントで レガシー認証のブロック が有効化された
- 条件付きアクセス や セキュリティ既定 により、パスワードのみのサインインや WS-Federation が制限された
- ユーザーに MFA(多要素認証) を強制するポリシーが適用され、
UserCredentialでは要件を満たせなくなった
wsignin1.0 と FedAuth クッキーの仕組み
wsignin1.0 は、WS-Federation(WS-Fed) と呼ばれるレガシーな認証プロトコルのサインインエンドポイントです。このエンドポイントに対してユーザー名・パスワードで認証を行うことで、ブラウザー用のセッション Cookie である FedAuth や rtFa が発行されます。
従来のスクリプトでは、
UserCredentialでwsignin1.0に POST- レスポンスヘッダから
FedAuth/rtFaを取得 - そのクッキーを使って SharePoint のページや REST API にアクセス
という「ブラウザーの動きを Python で再現する」スタイルの認証を行っていました。
| 要素 | 役割 |
|---|---|
wsignin1.0 | WS-Fed のサインインエンドポイント。フォーム認証を受け付ける URL。 |
FedAuth | SharePoint Online での認証済みセッションを表すクッキー。 |
rtFa | 複数サービス間でのシングルサインオンに使われるクッキー。 |
UserCredential | ユーザー名+パスワードを使うレガシーな認証方式。MFA 非対応。 |
この方式は「ブラウザーログインを機械で代行している」に等しく、現在の Microsoft 365 のセキュリティ標準では推奨されないどころか、順次ブロックの対象になっています。
なぜ今になって失敗するのか:レガシー認証ブロックの影響
Microsoft 365 では、セキュリティ強化の一環として、次のような機能が順次ロールアウトされてきました。
- セキュリティ既定(Security Defaults)
- 条件付きアクセス(Conditional Access)
- レガシー認証のブロック設定
これらによって、以下のようなアクセスは段階的に拒否されます。
- ユーザー名+パスワードのみでのサインイン
- WS-Fed / SAML / Basic などのレガシープロトコル経由のサインイン
- モダン認証非対応クライアントからのアクセス
つまり、今動いているレガシーなスクリプトは、
- テナントやユーザーに制限ポリシーがまだ適用されていない
- または例外的に許可されている
という状態で辛うじて動いているだけで、いつ停止してもおかしくない「時限爆弾」になっています。
| 変更・設定 | SharePoint スクリプトへの影響 |
|---|---|
| セキュリティ既定の有効化 | レガシー認証が一括でブロックされ、wsignin1.0 経由のクッキー取得が失敗し始める。 |
| MFA 必須の条件付きアクセス | パスワードだけの UserCredential は MFA 要件を満たせず、認証が失敗。 |
| レガシー認証ブロックポリシー | WS-Fed などのレガシープロトコルが明示的に禁止される。 |
このため、「先週まで動いていたのに突然エラーになった」という現象は、スクリプト側ではなく、テナント側のセキュリティ設定変更が原因であることが非常に多いです。
結論:wsignin1.0 ベースの認証はやめてモダン認証へ移行する
根本的な対策はシンプルです。
wsignin1.0 + UserCredential(ユーザー名+パスワード)+クッキー取得というレガシー方式は捨てて、
Microsoft Entra ID(旧 Azure AD)の「モダン認証(OAuth 2.0 / OpenID Connect)」へ移行する。
具体的には、以下のような構成を目指します。
- Entra ID に アプリ登録 を作成
- クライアント資格情報フロー(Client Credentials Flow) などでアクセストークンを取得
- そのアクセストークンを使って Microsoft Graph API あるいは SharePoint REST API を呼び出す
- Python では
msalやOffice365-REST-Python-ClientのClientCredentialを使用
| 対応策 | 内容 | 用途 | 推奨度 |
|---|---|---|---|
| 暫定対応 | Microsoft サポートに依頼してレガシー認証ブロックを一時的に緩和 | 今日中に止まると困るバッチ・基幹処理のつなぎ | 低(緊急時のみ) |
| 恒久対応 | Entra ID アプリ登録+モダン認証に移行し、トークンで SharePoint にアクセス | 中長期の運用・セキュリティを見据えた再構築 | 最優先 |
以下では、推奨されるモダン認証への移行ステップを、Python の具体的なコード例とともに解説します。
モダン認証への移行手順(Entra ID アプリ登録+Python)
ステップ 1:Entra ID でアプリ登録を作成する
まず、Microsoft Entra 管理センターでアプリ登録を行います。
- 管理者アカウントで Microsoft Entra 管理センターにサインイン
- アプリの登録 から「新規登録」を選択
- 名前を入力(例:
SharePoint Automation Python) - サポートされているアカウントの種類は基本的に「この組織ディレクトリ内のアカウントのみ」を選択
- リダイレクト URI はサーバー間アプリでは必須ではないため空でも可
- 登録後、アプリケーション(クライアント)ID と ディレクトリ(テナント)ID を控える
次に、認証に使う秘密情報を発行します。
- クライアント シークレット を発行する場合
- 「証明書とシークレット」メニューから「新しいクライアント シークレット」を作成
- 表示された値は その場で必ず安全な場所に保存
- 証明書認証 を使う場合
- 自己署名 or 企業 CA で証明書を作成し、「証明書のアップロード」から登録
- 後述のように Key Vault 等で安全に管理するとさらに安心
ステップ 2:API 権限を付与し、管理者同意を行う
次に、SharePoint にアクセスするための API 権限を設定します。
| API | 権限の種類 | 例 | 用途 | ポイント |
|---|---|---|---|---|
| Microsoft Graph | アプリケーション権限 | Sites.Selected | Graph 経由で SharePoint のサイト・ライブラリ操作 | 最小権限。サイトごとに別途委任が必要。 |
| SharePoint | アプリケーション権限 | Sites.Read.All, Sites.ReadWrite.All | SharePoint REST API を直接呼び出す | 権限範囲が広いため、可能な限り最小権限を選択。 |
権限を追加したら、管理者同意(Admin Consent) を実行しておきます。これを行わないと、アプリがサーバー間でトークンを取得する際に権限不足でエラーになることがあります。
ステップ 3:Python でアクセストークンを取得する(msal)
ここからは Python コードです。まずは msal と requests をインストールします。
pip install msal requests
次に、クライアント資格情報フローを使って SharePoint 用のアクセストークンを取得します。
import msal
import requests
tenant_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" # テナントID
tenant_name = "contoso" # 例: contoso
client_id = "yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy" # アプリケーション(クライアント)ID
client_secret = "YOUR_CLIENT_SECRET" # クライアントシークレット
authority = f"https://login.microsoftonline.com/{tenant_id}"
app = msal.ConfidentialClientApplication(
client_id=client_id,
client_credential=client_secret,
authority=authority,
)
# SharePoint Online 向けのスコープは「<リソース>/.default」
scope = f"https://{tenant_name}.sharepoint.com/.default"
token_result = app.acquire_token_for_client(scopes=[scope])
if "access_token" not in token_result:
raise RuntimeError(f"トークン取得に失敗しました: {token_result.get('error_description')}")
access_token = token_result["access_token"]
ここで重要なのは、スコープの指定です。SharePoint REST を直接叩きたい場合は、
https://{tenant}.sharepoint.com/.default
のように、「SharePoint Online のリソース URL+/.default」を指定します。/.default は「Entra ID に登録されているアプリの権限をそのまま使う」という意味です。
ステップ 4:SharePoint REST API を呼び出す
取得したアクセストークンを使って、SharePoint REST API を呼び出してみます。
site_url = f"https://{tenant_name}.sharepoint.com/sites/Example"
resp = requests.get(
f"{site_url}/_api/web?$select=Title",
headers={
"Authorization": f"Bearer {access_token}",
"Accept": "application/json;odata=nometadata",
},
timeout=30,
)
resp.raise_for_status()
print(resp.json()) # 例: {"Title": "Example Site"}
このように、クッキーを取得して送るのではなく、アクセストークン(Bearer トークン)を付けて API を呼び出す形が、現在推奨されるモダン認証の形です。
ステップ 5:Office365-REST-Python-Client をアプリ資格情報で使う
すでに Office365-REST-Python-Client を使っているプロジェクトでは、UserCredential をやめて ClientCredential に切り替えることで、比較的少ないコード変更で移行できます。
pip install Office365-REST-Python-Client
from office365.sharepoint.client_context import ClientContext
from office365.runtime.auth.client_credential import ClientCredential
site_url = "https://contoso.sharepoint.com/sites/Example"
client_id = "yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy"
client_secret = "YOUR_CLIENT_SECRET"
ctx = ClientContext(site_url).with_credentials(ClientCredential(client_id, client_secret))
web = ctx.web
ctx.load(web)
ctx.execute_query()
print(web.properties["Title"])
UserCredential では内部的に wsignin1.0 に依存していたケースがありますが、ClientCredential では Entra ID のトークンを使うため、レガシー認証ブロックの影響を受けにくくなります。
ステップ 6:シークレット・証明書を安全に管理する
モダン認証に移行した後も、クライアントシークレットや証明書の管理を誤ると、それ自体がセキュリティリスクになります。以下のような運用が望ましいです。
- シークレット値をソースコードや Git リポジトリにベタ書きしない
- 環境変数や構成ファイルに分離し、権限を絞る
- Azure Key Vault などの秘密情報管理サービスを利用する
- シークレットには有効期限を設定し、定期的にローテーションする
- 証明書認証を採用し、秘密鍵はサーバー側で厳重に保護する
移行時にハマりやすいポイントとチェックリスト
多くのチームがモダン認証へ移行する中で、よくつまずくポイントをチェックリスト形式でまとめます。
| チェック項目 | 症状 | 原因の例 | 対処方法のヒント |
|---|---|---|---|
| 条件付きアクセス/セキュリティ既定 | UserCredential で突然認証エラー | レガシー認証ブロックや MFA 必須ポリシーが有効化 | ポリシーを確認し、アプリ認証方式への移行を優先。緊急時は一時例外も検討。 |
Graph の Sites.Selected | トークン取得は成功するがサイトにアクセスできない | サイト単位の委任(ロール割り当て)が未実施 | 対象サイトに対してアプリに適切なロールを割り当てる。 |
| スコープ指定の誤り | トークン取得エラー or 操作時に 401/403 | .default を付け忘れ、違うリソースを指定している | SharePoint 用は https://{tenant}.sharepoint.com/.default を使用。 |
| 権限の与えすぎ | セキュリティ担当からレビューで NG | Sites.FullControl.All や広範囲な権限を安易に付与 | 実際に必要な権限だけを選ぶ。読み取りのみなら Sites.Read.All 等。 |
| ユーザー名+パスワードの継続利用 | 将来また突然止まるリスクを抱えたまま | ROPC などの非推奨フローを使い続けている | アプリケーション権限+証明書認証への移行を検討。 |
| ライブラリのバージョン差異 | サンプルコード通りに書いても動かない | Office365-REST-Python-Client の API 仕様が変わっている | 利用中のバージョンのドキュメントを確認し、メソッド名や戻り値をチェック。 |
暫定対応:どうしても今日中に復旧したい場合
ビジネス上の理由から「今夜のバッチだけはどうしても動かしたい」といったケースもあるかもしれません。そのような場合、Microsoft に Sev A(重大度 A) のサポートチケットを起票し、次のような相談を行うことができます。
- 影響を受けているシステムの重要度
- 停止しているバッチ/業務の具体的内容
- どのポリシー変更により、いつからエラーが出始めたか
- モダン認証への移行を進めていること、ただし間に合わない理由
その上で、レガシー認証ブロックを一時的に緩和する設定 を検討してもらえます。ただし、これはあくまで緊急避難であり、次のような注意があります。
- 有償サポートになる場合がある
- 緩和期間は限定的で、将来再度ブロックされる可能性が高い
- セキュリティリスクが増大するため、社内のセキュリティポリシーとの整合が必要
そのため、暫定対応に頼りきるのではなく、あくまで「時間を買う」ための一時的措置と割り切り、並行してモダン認証への移行作業を進めることが重要です。
運用・セキュリティ設計のベストプラクティス
ユーザー認証ではなく「アプリケーション認証」を主軸にする
バッチ処理やバックエンドの連携では、人的なユーザーアカウントに依存しない、アプリケーション専用の権限を使うことが推奨されます。
- アプリケーション権限だと、ユーザーのパスワード変更や退職の影響を受けにくい
- アクセス範囲をアプリごとに切り分けやすい
- MFA の有無にかかわらず安定したサーバー間通信が可能
最小権限の原則(Least Privilege)
権限は「とりあえず全部付けておく」ではなく、必要な操作がギリギリできる範囲に絞ることが重要です。
- 読み取り専用で足りるなら
Sites.Read.Allまでで止める - 特定サイトだけ触れればよい場合は Graph の
Sites.Selectedを活用 - アプリごとにアクセス対象サイトを分割し、侵害時の被害範囲を限定
ログと監査の仕組みを整える
モダン認証では、サインインログや監査ログがよりリッチに取得できます。次のような観点でログを活用しましょう。
- アプリケーション ID 単位でのサインイン状況の監視
- 失敗したサインインの増加をアラートとして検知
- いつ、どのアプリが、どのサイトにアクセスしたかのトレース
こうしたログを扇の要としておくことで、将来のセキュリティインシデント時にも原因追跡が行いやすくなります。
よくある質問(FAQ)
Q. まだ UserCredential + wsignin1.0 で動いています。すぐに変えないとダメですか?
A. 「今すぐ止まる」とは限りませんが、テナントのセキュリティ設定次第でいつ停止してもおかしくない状態です。とくに、セキュリティ既定の有効化や条件付きアクセスの適用範囲見直しにより、ある日突然エラーになるケースが多く報告されています。新しい仕組みに移行する計画を早めに立てることを強くおすすめします。
Q. ユーザーに MFA を必須にしたら、スクリプトが動かなくなりました。どうすればいいですか?
A. UserCredential は MFA を前提としていないため、MFA を必須にすると認証要件を満たせません。そのため、MFA 対応のモダン認証(アプリケーション認証)に切り替える必要があります。具体的には、本記事で紹介したように Entra ID アプリ登録+クライアント資格情報フローを利用する構成に移行してください。
Q. Microsoft Graph と SharePoint REST API のどちらを使うべきですか?
A. 新規開発や長期運用を見据えるなら、Microsoft Graph API を優先するのがおすすめです。ただし、現時点で Graph がサポートしていない細かい機能や、SharePoint 固有の API が必要な場合は、SharePoint REST API を併用する形が現実的です。
| 項目 | Graph API | SharePoint REST API |
|---|---|---|
| 推奨度 | 高(新規開発向け) | 中(既存資産活用や特殊機能に) |
| 機能カバレッジ | Microsoft 365 全般を横断的にカバー | SharePoint に特化し、詳細な機能を提供 |
| ドキュメント・サンプル | 近年は Graph が優先的に整備 | 既存ドキュメントは豊富だが、新機能は Graph 優先の傾向 |
Q. オンプレミスの SharePoint でも同じ問題は起こりますか?
A. 本記事の主な対象は SharePoint Online(Microsoft 365) です。オンプレミスの SharePoint Server では認証基盤やライフサイクルが異なり、同じタイミングで WS-Fed がブロックされるわけではありません。ただし、セキュリティの観点からは、オンプレミス環境でも可能な限りモダンな認証方式への移行や、VPN・ゼロトラスト等の見直しを検討する価値があります。
まとめ:レガシーな wsignin1.0 から安全なモダン認証へ
最後に、ポイントを整理します。
wsignin1.0は WS-Federation(レガシー認証)のサインインエンドポイントであり、クッキーを直接取得する方式は現在のセキュリティ方針と相容れません。- セキュリティ既定や条件付きアクセス、レガシー認証ブロックの有効化により、
UserCredential+ クッキー取得のスクリプトは、ある日突然動かなくなる可能性があります。 - 恒久的な解決策は、Entra ID でアプリ登録を行い、クライアント資格情報フローなどのモダン認証に移行することです。
- Python では
msal+requests、あるいは Office365-REST-Python-Client のClientCredentialを使うことで、アクセストークンベースの安全なアクセスに切り替えられます。 - どうしても即日復旧が必要な場合は、Microsoft サポートに一時的な緩和を相談することもできますが、あくまでモダン認証への移行までの「つなぎ」と考えるべきです。
「サインインページからクッキーを取って貼り付ける」時代は終わりつつあります。今後も安定して SharePoint Online を自動化するために、早めにモダン認証への移行を進めておきましょう。

コメント