Microsoft Graph PowerShellで毎回MFAログインを求められる原因と解決策|.graphトークンキャッシュ削除で改善

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 の流れでリセットし、改善するか確認してください。日常的なバッチ実行まで視野に入れるなら、アプリ登録+証明書認証へ移行すると、対話ログインに依存しない安定した運用が可能になります。

この記事を書いた人

実務の現場で詰まりがちなポイントを地図にするITブログ「IT trip」を運営。Windows/Office(Teams・Excel)からSQL、サーバ運用、ガジェットまで、再現性のある手順と“なぜそうなるか”を丁寧に解説します。読んだらすぐ試せること、そして迷った人の次の一歩が見えることを大切にしています。

コメント

コメントする

目次