Microsoft Graph PowerShell を使ってレポート取得やユーザー情報の取得を行うと、コマンドのたびにサインインや MFA が何度も要求されて作業にならないことがあります。多くはトークンキャッシュの不整合が原因です。本記事では、まず試すべきキャッシュリセット手順と、対話なしで自動実行するための証明書認証まで整理します。
起きている現象:1回の実行なのにサインインが連発する
Microsoft Graph PowerShell SDK(以下、Graph PowerShell)では、Connect-MgGraph で一度サインインすれば、同じ PowerShell セッション内は通常、追加のサインインなしでコマンドを実行できます。ところが環境によっては、次のような「異常にしつこい」認証プロンプトが発生します。
| よくある操作 | 期待される動き | 問題が起きたときの動き | 困るポイント |
|---|---|---|---|
Get-MgUser などの単発取得 | サインイン済みなら即結果が返る | コマンド実行のたびにサインイン/MFA を要求 | 試行錯誤が進まず、調査も運用も止まる |
Get-MgReportAuthenticationMethodUserRegistrationDetail などのレポート取得 | 一度の認証で必要分を取得 | 結果が多いと、内部呼び出しの回数分だけ MFA が連発 | 「40人ヒット → 40回以上」など、実質実行不能 |
| 同じスクリプトを何度も試す | 同一セッション中は再認証がほぼ起きない | 毎回ログインし直し | 自動化(タスク実行)に移行できない |
この症状は「MFA が厳しすぎる」だけでは説明できないケースが多く、Graph PowerShell 側のトークン再利用がうまく働いていない可能性が高いです。
なぜ「毎回」認証が走るのか:トークンキャッシュの仕組みをざっくり理解する
Graph PowerShell は、サインイン後に取得したトークンを使って Microsoft Graph API を呼び出します。トークンには有効期限があり、期限が切れたら再取得が必要ですが、通常は「再取得のための情報(更新用の情報)」を使って静かに更新できるため、コマンドのたびに MFA を要求されることはありません。
ところが、トークンを保存・再利用するためのキャッシュが壊れたり、SDK の更新でキャッシュ形式や取り扱いが変わったタイミングで不整合が起きたりすると、次のような流れになります。
- コマンド実行 → トークンが必要
- キャッシュから取り出そうとするが、読み取りに失敗/不整合
- 静かな更新ができない
- 結果として、対話サインイン(MFA 付き)にフォールバック
- 内部的に複数回 API 呼び出しがあるコマンドでは、その回数分だけ同じことが繰り返される
このため、「シンプルな Get-MgUser でも毎回サインイン」や、「レポート系で呼び出し回数ぶん MFA が連発」といった現象につながります。
まず確認:接続手順が正しいか(意外とここでハマります)
キャッシュを疑う前に、基本の流れが崩れていないかだけ確認しておくと安全です。
Connect-MgGraphを 1回実行してから、必要なコマンドをまとめて実行しているか- スクリプト内でループの中に
Connect-MgGraphが入っていないか - 別の PowerShell プロセスを都度起動していないか(セッションが毎回新規なら、当然サインインも毎回必要になります)
同じウィンドウ(同じ PowerShell プロセス)で次のように実行しても毎回サインインが出る場合、次章のキャッシュリセットが効果的です。
Connect-MgGraph -Scopes "User.Read.All"
Get-MgUser -Top 1
Get-MgUser -Top 1 # ここでも再度サインインを求められるなら要注意
解決策:Microsoft Graph PowerShell のトークンキャッシュをリセットする
採用された対処はシンプルで、Graph PowerShell が利用するトークンキャッシュ(ユーザープロファイル配下の .graph フォルダ)を初期化します。SDK のバージョンアップや環境移行を挟んだあとに起きる「キャッシュ不整合」では、これが最短で効きます。
手順(推奨:バックアップしてから削除)
安全のため、いきなり削除ではなく、まずはバックアップ(リネーム)でも構いません。PowerShell を複数起動している場合は、作業前に閉じておくとロック問題を避けやすいです。
# 0) 念のため現在の接続を切る
Disconnect-MgGraph
# 1) バックアップ(フォルダをリネーム)
$graphCache = Join-Path $env:USERPROFILE ".graph"
$backup = Join-Path $env:USERPROFILE (".graph_bak_" + (Get-Date -Format "yyyyMMdd_HHmmss"))
if (Test-Path $graphCache) {
Rename-Item -Path $graphCache -NewName (Split-Path $backup -Leaf)
}
# 2) 改めてサインイン(このときだけ MFA が必要になるのが通常です)
Connect-MgGraph -Scopes `
"Reports.Read.All","User.Read.All","UserAuthenticationMethod.Read.All"
リネーム後に改善が確認できたら、バックアップ側(.graph_bak_...)を削除して構いません。すぐ削除したい場合は、次のように Remove-Item で丸ごと削除しても問題ありません。
Disconnect-MgGraph
Remove-Item "$env:USERPROFILE\.graph" -Recurse -Force
Connect-MgGraph -Scopes `
"Reports.Read.All","User.Read.All","UserAuthenticationMethod.Read.All"
macOS / Linux / PowerShell 7 でのパスは?
Windows 以外では、一般的にホームディレクトリ($HOME)配下に .graph が作成されます。環境によっては PowerShell 7(pwsh)で $HOME が $env:USERPROFILE と同義になっていることもありますが、迷う場合は次で場所を確認できます。
# .graph の実体がどこにあるか確認
Get-ChildItem (Join-Path $HOME ".graph") -ErrorAction SilentlyContinue
# 削除する場合(Windows以外の例)
Disconnect-MgGraph
Remove-Item (Join-Path $HOME ".graph") -Recurse -Force
キャッシュを消すと何が起きる?(不安を潰してから実行する)
「フォルダを丸ごと削除」と聞くと怖いのですが、基本的には Graph PowerShell が持つ認証の状態(トークン)を捨てて作り直すだけです。影響をイメージできるように、よくある疑問を表にまとめます。
| 項目 | 影響 | 補足 |
|---|---|---|
| Graph PowerShell のサインイン状態 | リセットされる | 次回の Connect-MgGraph で再サインイン(+MFA)が必要 |
| 同意(Consent)済みの権限 | 基本的に残る | ただし、スコープを変えた場合は追加同意が求められることがあります |
| PC の Windows ログオン情報/Microsoft アカウント | 変わらない | OS の資格情報を消す操作ではありません |
| セキュリティ | むしろ安全側 | 古いトークンが残っている状態を解消するため、整理としても有効です |
リセット後の確認:本当に「毎回の MFA」が止まったかチェックする
手順を実行したら、同一セッションで複数回コマンドを打って挙動を確認します。サインインは最初の一回だけで、その後は静かに実行できるのが理想です。
# いまの接続状態を確認(表示される環境では)
Get-MgContext
# 何度か繰り返しても、追加のサインインが出ないか確認
Get-MgUser -Top 1
Get-MgUser -Top 1
レポート系のコマンドでも、同様に一度の認証で最後まで走るかを確認します。結果が多いときは内部的に複数回 Graph API を呼ぶため、ここで再認証が起きないかがポイントです。
# 例:認証方法登録状況のレポート取得
Get-MgReportAuthenticationMethodUserRegistrationDetail
それでも改善しない場合に見るべきポイント
キャッシュリセットで改善しないときは、原因が「キャッシュ不整合」以外にある可能性があります。現場でよく遭遇するチェック項目をまとめます。
| チェック項目 | 症状の例 | 対処の方向性 |
|---|---|---|
| PowerShell を毎回起動している | スクリプト実行のたびに必ずサインインが必要 | 同一プロセスでまとめて実行する/自動化はアプリ認証へ |
| 複数バージョンのモジュールが混在 | 環境によって挙動が変わる、更新直後から不安定 | Get-InstalledModule で確認し、不要なバージョンを整理 |
| 組織の条件付きアクセス(サインイン頻度)が厳しい | 一定時間ごと、または操作ごとに再認証を要求 | ポリシー設計を管理者と相談(運用要件とセキュリティの両立) |
| 実行ユーザーが変わっている | 管理者で起動/別アカウントで実行したら挙動が変わる | 同じユーザーで実行する、または自動化用の設計に切り替える |
| 古い実行ホストを使っている | ログイン画面が正常に出ない/ブラウザ連携が不安定 | Windows Terminal や PowerShell 7(pwsh)など、最新の実行環境で試す |
モジュール混在が疑わしい場合は、次のようにインストール状況を確認できます。組織の運用ルール次第ではありますが、まずは「いま何が入っているか」を把握すると切り分けが進みます。
# インストール済みの Microsoft.Graph 関連モジュールを確認
Get-InstalledModule Microsoft.Graph* -AllVersions | Sort-Object Name, Version
# 更新(運用ルールに合わせて実施)
# Update-Module Microsoft.Graph
特に、組織のセキュリティポリシーで「サインイン頻度」が短く設定されていると、正常なキャッシュがあっても再認証が必要になることがあります。症状が「毎回」なのか、「一定時間ごと」なのかで切り分けると判断しやすくなります。
完全自動化したいなら:アプリ登録+証明書認証でノン対話接続
日々の運用で「手作業でのサインイン自体をなくしたい」「タスクスケジューラやジョブで止まらず回したい」という場合は、ユーザーの対話サインインではなく、アプリ登録(Microsoft Entra ID / 旧 Azure AD)+証明書認証を使う方法が現実的です。
この方式では、ユーザーの MFA 入力に依存せず、証明書を使ってアプリとして Graph に接続します。対話がないため、夜間バッチや監視ジョブに向いています。
接続例
Connect-MgGraph `
-ClientId "<アプリケーションID>" `
-TenantId "<テナントID>" `
-CertificateName "<証明書のサブジェクト名>"
環境によっては、証明書を「名前」ではなく「サムプリント」で指定する運用が管理しやすい場合もあります(証明書更新時の事故を減らしやすい)。
Connect-MgGraph `
-ClientId "<アプリケーションID>" `
-TenantId "<テナントID>" `
-CertificateThumbprint "<証明書サムプリント>"
Delegated(委任)と Application(アプリ)権限の違いに注意
対話サインイン(ユーザー)での実行は、主に「Delegated permissions(委任された権限)」として動作します。一方、証明書認証のアプリ実行は「Application permissions(アプリ権限)」として動作します。ここを混同すると、権限不足でコマンドが失敗する原因になります。
| 観点 | 委任(ユーザーサインイン) | アプリ(証明書など) |
|---|---|---|
| 実行主体 | サインインしたユーザー | 登録したアプリ |
| MFA | 必要(組織ポリシー次第) | 不要(対話なし) |
| 権限の付与 | スコープ(-Scopes)で要求し、同意する | アプリ権限を付与し、管理者が同意(Admin consent) |
| 向いている用途 | 手元の調査・運用作業 | 定期バッチ、監査レポート、監視・通知 |
たとえばレポート取得やユーザー情報参照に必要な権限(Reports.Read.All / User.Read.All / UserAuthenticationMethod.Read.All など)は、委任・アプリのどちらで必要かを設計時に確認してください。アプリ権限は強力なので、最小権限・証明書の保護・実行ホストの管理まで含めた運用設計が重要です。
再発防止のコツ:安定して Graph PowerShell を使うための運用ポイント
- 作業は「接続 → まとめて実行 → 切断」の1セットにすると、認証状態が把握しやすくなります。
- モジュール更新を頻繁に行う環境では、更新後に挙動が怪しければキャッシュを疑う(今回の手順が効くことが多いです)。
- 複数端末・複数ユーザーで同じスクリプトを回す場合、対話サインイン前提のまま運用しない(自動化はアプリ認証に寄せる)
- 権限(スコープ/アプリ権限)は、必要な作業が終わったら見直し、付けっぱなしにしない
- 最後に
Disconnect-MgGraphを実行しておくと、意図しない操作を減らせます。
よくある質問
キャッシュ削除はどのタイミングでやるべき?
「昨日まで動いていたのに、モジュール更新後から毎回サインインが出る」「同じセッション内でもコマンドのたびに MFA が出る」といった、急におかしくなった系の症状で特に効果的です。まずはバックアップとして .graph をリネームし、改善したら削除に切り替えると安全です。
スクリプト内で毎回 Connect-MgGraph してはいけない?
「毎回必ず新しい PowerShell プロセスで実行する」スクリプトなら、実質的に毎回の接続が必要になります。ただし運用の目的が定期実行であれば、対話サインインではなく証明書認証(アプリ)に寄せるほうが、止まりにくく管理もしやすいです。
結果が多いときだけ MFA が増えるのはなぜ?
レポート系・一覧取得系のコマンドは、内部的にページングや複数回の API 呼び出しを行うことがあります。通常は同じトークンで連続呼び出しできますが、トークン取得のたびに対話認証が走る状態だと、内部呼び出し回数ぶんサインイン/MFA が出てしまいます。
「最初の 1 回だけ MFA、その後は出ない」状態が理想?
はい。通常は、最初の Connect-MgGraph でサインイン(+MFA)し、同一セッション内はキャッシュと更新処理で継続利用できるのが期待値です。逆に、セッション内で何度も MFA が出る場合は、キャッシュ不整合や環境要因を疑う価値があります。
まとめ:まずはキャッシュリセット、次に自動化設計へ
Graph PowerShell 実行のたびに MFA が出る問題は、運用側の設定ではなく、Graph PowerShell のトークンキャッシュが不整合を起こしているケースが少なくありません。まずは Disconnect-MgGraph → .graph フォルダ削除(またはリネーム)→ Connect-MgGraph の流れでリセットし、改善するか確認してください。日常的なバッチ実行まで視野に入れるなら、アプリ登録+証明書認証へ移行すると、対話ログインに依存しない安定した運用が可能になります。

コメント