Azure SDKのAAD認証変更点:tenant-aware issuer validationとaudienceチェック対応ガイド

2026年5月4日に公開されたAzure SDK for JavaのPRでは、Spring Cloud AzureのMicrosoft Entra ID、旧称Azure AD/AAD認証に関するトークン検証がより厳格化されています。結論から言うと、Spring Cloud AzureでAAD認証付きのリソースサーバーやWebアプリを運用している場合は、tenant-idとaudの設定を必ず確認すべき変更です。

特に影響が大きいのは、spring-cloud-azure-starter-active-directoryやspring-cloud-azure-autoconfigureを使い、Microsoft Entra IDでAPIを保護しているJava/Spring Bootアプリです。単一テナントのリソースサーバーでは、発行者であるissの検証がテナント単位で厳密になり、AadAuthenticationFilterでは audience、つまりaudの明示チェックがデフォルトで有効になります。これまで偶然通っていたトークンが、更新後に拒否される可能性があります。(GitHub)

目次

変更の要点:AADトークン検証が「広く受け入れる」から「意図した相手だけ受け入れる」へ

今回のAzure SDK documentation updateで押さえるべきポイントは、次の2つです。

変更点変更前に起き得た問題変更後の動き
単一テナントのissuer検証をtenant-awareに強化意図しないテナントから発行されたトークンを受け入れるリスクがあった設定されたテナントに紐づくissuerだけを厳密に検証
AadAuthenticationFilterのaudienceチェックをデフォルト有効化audが期待するアプリケーション宛てでなくても許容される可能性があったclient-idまたはapp-id-uriに合わないトークンを拒否

Microsoft Entra IDのトークン検証では、audが対象APIに一致していること、tidが期待するテナントであること、issが信頼できる発行者であることを確認する必要があります。Microsoftのドキュメントでも、APIやWebアプリは自分宛てのaudを持つトークンだけを検証・受け入れるべきと説明されています。(Microsoft Learn)

対象になりやすいアプリケーション

今回の変更は「Azure SDK全体のすべての認証処理が変わる」というより、Azure SDK for Java内のSpring Cloud Azure AAD認証周辺に関係する変更です。PRでは、spring-cloud-azure-autoconfigure配下のAadResourceServerConfiguration、AadAuthenticationFilter、AadJwtIssuerValidator、テスト、CHANGELOGが変更対象になっています。(GitHub)

次の条件に当てはまる場合は、優先して確認してください。

確認すべきケース理由
Spring Bootでspring-cloud-azure-starter-active-directoryを使っているMicrosoft Entra ID連携の自動構成に影響する可能性がある
APIをリソースサーバーとして公開しているiss、tid、aud検証の厳格化が認証失敗につながる可能性がある
tenant-idにcommon、organizations、consumersを指定しているリソースサーバー用途では具体的なテナントIDが求められる方向になる
複数テナント対応を前提に設計している単一テナント向けの厳格化とマルチテナント設計を切り分ける必要がある
app-id-uriやclient-idの設定を曖昧にしているaudienceチェック有効化により、aud不一致のトークンが拒否される可能性がある

Spring Cloud Azureの公式ドキュメントでは、spring.cloud.azure.active-directory.profile.tenant-idやspring.cloud.azure.active-directory.app-id-uriなどの構成プロパティが案内されています。これらは今回の変更確認で中心になる項目です。(Microsoft Learn)

何が変わったのかを技術的に整理する

単一テナントのリソースサーバーでissuer検証が厳しくなる

PRでは、リソースサーバーのデフォルトバリデーター構成が見直されています。単一テナントのtenant-idでは、AadTrustedIssuerRepositoryを使って信頼済みissuerとの一致を確認する方向に変更されています。あわせてtid、つまりTenant IDクレームの検証も追加されています。(GitHub)

実務上の意味はシンプルです。

tenant-idに自社テナントのGUIDを設定しているAPIは、そのテナントから発行されたトークンかどうかをより明確に確認するようになります。一方で、以前は通っていた別テナント由来のトークンや、曖昧なissuerを持つトークンは拒否される可能性があります。

たとえば、社内向けAPIで本来はA社テナントのユーザーだけが使うべきなのに、commonを使って広くサインインを許していた場合、意図しないテナントのトークンを受け入れる余地が生まれます。今回の変更は、このようなクロステナントの受け入れリスクを減らすためのものです。

tenant-idにcommonなどを使う構成は要注意

PRのCHANGELOGには、AADリソースサーバーではspring.cloud.azure.active-directory.profile.tenant-idに具体的なテナントID、つまりGUIDが必要で、空文字、common、organizations、consumersは無効とする旨が記載されています。(GitHub)

これは特に重要です。既存アプリで次のような設定をしている場合は、更新後に起動失敗や認証失敗が起きる可能性があります。

spring:
  cloud:
    azure:
      active-directory:
        enabled: true
        profile:
          tenant-id: common

リソースサーバーとしてAPIを保護する用途では、次のように具体的なテナントIDへ変更することを検討します。

spring:
  cloud:
    azure:
      active-directory:
        enabled: true
        profile:
          tenant-id: 12345678-1234-1234-1234-123456789012
        credential:
          client-id: ${AZURE_CLIENT_ID}
        app-id-uri: api://${AZURE_CLIENT_ID}

ここで重要なのは、tenant-idにアプリケーションIDやクライアントIDを入れないことです。tenant-idにはMicrosoft EntraテナントのディレクトリIDを指定します。client-idはアプリ登録のアプリケーション、クライアントIDです。似たGUIDなので、設定ミスが起きやすいポイントです。

audienceチェックがデフォルトで有効になる

もう一つの大きな変更は、AadAuthenticationFilterのコンストラクターでexplicitAudienceCheckがfalseからtrueへ変更されている点です。PRの差分では、デフォルトのコンストラクターパスでaudience検証を有効化する変更が確認できます。(GitHub)

audは、そのトークンが「どのAPI・アプリケーション向けに発行されたか」を示すクレームです。たとえば、API A向けに発行されたアクセストークンをAPI Bが受け入れてしまうと、権限の境界が崩れます。Microsoftのドキュメントでも、別リソース向けトークンを受け入れることはconfused deputy問題の例として説明されています。(Microsoft Learn)

そのため、更新後に次のようなケースでは認証エラーが出る可能性があります。

起きる現象典型的な原因確認する設定
API呼び出しが401になるトークンのaudがAPIのclient-idまたはapp-id-uriと合っていないspring.cloud.azure.active-directory.app-id-uri、アプリ登録のApplication ID URI
ローカルでは通るが本番で失敗する環境変数のAZURE_CLIENT_IDやapp-id-uriが環境ごとにずれているdev/stg/prodの設定差分
他API向けトークンで呼び出すと拒否されるこれまで過度に広く受け入れていたクライアント側のスコープ要求先
OBO構成で失敗する下流API向けと自API向けのトークンを混同しているOn-Behalf-Ofフローのスコープ、audience

まず確認すべき設定項目

今回の変更に対する実務的な対応は、ライブラリ更新前に「自分のアプリがどのテナントの、どのAPI宛てのトークンを受け入れるべきか」を明確にすることです。

tenant-idは具体的なテナントGUIDになっているか

リソースサーバー用途では、commonやorganizationsを安易に使わないでください。社内API、B2B連携API、管理画面用APIなど、受け入れるテナントが決まっている場合は、Microsoft Entra管理センターで確認できるディレクトリIDを設定します。

悪い例です。

spring.cloud.azure.active-directory.profile.tenant-id: common

よい例です。

spring.cloud.azure.active-directory.profile.tenant-id: 12345678-1234-1234-1234-123456789012

ただし、マルチテナントSaaSのように複数組織のユーザーを受け入れる設計では、単純に単一テナントGUIDへ置き換えるだけでは要件を満たせません。その場合は、受け入れ可能なテナントをアプリ側の認可ロジックで管理する、テナントごとのオンボーディングを行う、tidやissuerを使って許可リストと照合する、といった設計が必要です。

app-id-uriとclient-idはトークンのaudと一致するか

audienceチェックが有効になると、audの不一致は認証失敗につながります。APIを呼び出すクライアントが、正しいリソース向けにアクセストークンを取得しているか確認してください。

代表的な構成は次のような形です。

spring:
  cloud:
    azure:
      active-directory:
        enabled: true
        profile:
          tenant-id: ${AZURE_TENANT_ID}
        credential:
          client-id: ${AZURE_CLIENT_ID}
        app-id-uri: api://${AZURE_CLIENT_ID}

確認時は、実際にAPIへ送られているアクセストークンのaudをデバッグ環境で確認します。ただし、アクセストークンは機密性の高い資格情報です。ログにそのまま出力したり、外部サービスに貼り付けたりしないでください。Microsoftのドキュメントでも、アクセストークンはクライアント側では不透明な文字列として扱い、リソースサーバー側で検証するものと説明されています。(Microsoft Learn)

application-typeの推論結果が意図通りか

Spring Cloud Azureでは、依存関係からアプリケーション種別が推論されます。公式ドキュメントでは、spring-security-oauth2-clientがある場合はWebアプリケーション、spring-security-oauth2-resource-serverがある場合はリソースサーバーとして推論され、両方ある場合はresource_server_with_oboが推論されると説明されています。(Microsoft Learn)

WebアプリとAPIを同じアプリケーションで兼ねる構成では、意図しない推論になっていないか確認しましょう。必要に応じてapplication-typeを明示します。

spring:
  cloud:
    azure:
      active-directory:
        application-type: resource_server

Webアプリ兼リソースサーバー、OBOフロー、ステートレス認証を使っている場合は、単純なサンプル設定を流用すると失敗しやすいです。依存関係、アプリ登録、スコープ、APIアクセス許可をセットで確認してください。

影響範囲別の対応方針

社内向け単一テナントAPI

最も対応しやすいケースです。自社テナントだけを受け入れるなら、tenant-idを具体的なテナントGUIDにし、app-id-uriまたはclient-idに一致するaudだけを受け入れる構成にします。

チェックポイントは次の3つです。

項目確認内容
テナントtenant-idが自社テナントのGUIDか
audienceアクセストークンのaudが自APIのclient-idまたはapp-id-uriか
クライアントAPI呼び出し側が正しいスコープを要求しているか

本番反映前に、正常系だけでなく「別テナントのトークン」「別API向けトークン」「期限切れトークン」を使った拒否テストを行うと、設定ミスを早期に発見できます。

マルチテナントSaaS

マルチテナントSaaSでは、「どのテナントでもログインできる」と「どのテナントのトークンでもAPIアクセスできる」は別物です。サインイン時にorganizationsを使う設計があっても、API側では契約済みテナントだけを受け入れる必要があります。

今回の変更を機に、次のようなテナント許可リストを設計に入れることをおすすめします。

受け入れる条件:
- tidが契約済みテナント一覧に存在する
- issがそのtidに対応するMicrosoft Entra issuerである
- audが自APIのApplication ID URIまたはclient-idである
- rolesまたはscpが必要な権限を含む

よくある失敗は、audとscpだけを見て、tidを確認していないケースです。これでは、別テナントで同じような権限名が使われた場合に、意図しないアクセスを許すリスクが残ります。

WebアプリとAPIを同居させている構成

WebログインとAPI保護を同じSpring Bootアプリで扱う場合は、AadAuthenticationFilterとリソースサーバー側の検証が混在します。今回のaudienceチェック有効化により、ログイン用のIDトークン、API用のアクセストークン、下流API用のアクセストークンを混同すると失敗しやすくなります。

整理のコツは、トークンを用途ごとに分けて確認することです。

トークン主な用途見るべきクレーム
IDトークンユーザーがログインしたことの確認aud、iss、tid
自API向けアクセストークン自APIへのアクセス許可aud、iss、tid、scpまたはroles
下流API向けアクセストークンMicrosoft Graphや別APIの呼び出し下流APIのaud、必要なスコープ

Microsoft Graph向けのトークンを自社APIで受け入れてはいけません。自社APIは自社API向けに発行されたアクセストークンだけを検証・受け入れるべきです。

移行前に実施したい確認手順

ライブラリ更新後に突然401が多発しないよう、検証環境で次の順に確認します。

手順作業目的
1現在利用しているSpring Cloud Azureのバージョンと依存関係を確認変更対象の認証機能を使っているか把握する
2tenant-id、client-id、app-id-uriを棚卸し環境ごとの設定差分を洗い出す
3正常なアクセストークンのaud、tid、issを確認期待値を明文化する
4common、organizations、consumersの利用有無を確認リソースサーバー用途での起動失敗を防ぐ
5別テナント・別audienceのトークンで拒否テストセキュリティ強化が効いているか確認する
6401/403のログメッセージを確認認証失敗と認可失敗を切り分ける
7本番反映時のロールバック手順を用意設定漏れによる停止時間を短縮する

ここで大切なのは、更新前に「通るべきトークン」と「拒否すべきトークン」を決めておくことです。セキュリティ修正では、更新後に拒否されるトークンが増えること自体は悪いことではありません。問題は、拒否される理由をチームが把握していないことです。

よくあるエラーと切り分け方

更新後に401 Unauthorizedになる

まず疑うべきはaudの不一致です。API呼び出し側が別API向けのスコープを要求していないか確認します。

たとえば、クライアント側がMicrosoft Graph向けスコープだけを要求している場合、自社API向けのアクセストークンではありません。自社APIを呼ぶには、自社APIのApplication ID URIに紐づくスコープを要求する必要があります。

アプリケーション起動時に失敗する

tenant-idにcommon、organizations、consumers、空文字が設定されていないか確認します。PRのテストでは、これらの値をリソースサーバー用途で拒否するケースが追加されています。(GitHub)

環境変数で設定している場合は、ローカルではGUID、本番では未設定という差分も起こりがちです。CI/CDのシークレット、Kubernetes Secret、App Serviceのアプリケーション設定など、実行環境側の値まで確認してください。

403 Forbiddenになる

401は主に認証の問題、403は主に認可の問題です。今回の変更はiss、tid、audの検証に関係しますが、API内の権限判定ではroles、scp、groupsなども関係します。

PR内のコメントでも、sub、oid、roles、groups、scpなどのアプリケーション固有の認可は、ビジネスロジックやSpring Securityの@PreAuthorize、@Secured、カスタム認可ロジックで扱うべき領域として整理されています。(GitHub)

つまり、トークンが正しい発行者・正しいaudienceであっても、必要なロールやスコープがなければ403になります。

設定確認に使える実務チェックリスト

本番反映前に、次のチェックリストを使って確認してください。

チェック項目OKの状態
spring.cloud.azure.active-directory.enabledEntra ID認証を使う環境でtrueになっている
tenant-idリソースサーバーでは具体的なテナントGUIDを指定している
client-idAPIのアプリ登録に対応するクライアントIDを指定している
app-id-uriトークンのaudと一致する値を指定している
クライアント側スコープ自API向けのスコープを要求している
別テナントトークン単一テナントAPIでは拒否される
別audienceトークン自APIでは拒否される
監査ログ認証失敗時に原因を追えるログがある
ロール・スコープAPIメソッド単位の認可条件と一致している

ログにトークン全文を出すのは避けてください。確認が必要な場合は、開発環境でaud、tid、issなど必要最小限のクレームだけをマスク付きで出力する、またはセキュアなデバッグ手順を用意します。

この変更を「破壊的変更」として扱うべき理由

PRのチェックリストでは「breaking changesを導入しない」という項目がありますが、CHANGELOG上はAADリソースサーバーのtenant-id要件がBreaking Changesとして記載されています。実務では、セキュリティ上正しい方向への変更でも、既存の緩い設定に依存していたアプリでは破壊的変更として扱うのが安全です。(GitHub)

特に次のような運用をしている場合、更新計画を立てて段階的に進めるべきです。

  • 複数環境でtenant-idやapp-id-uriを環境変数管理している
  • 自社API、Microsoft Graph、外部API向けのトークンを同じ処理で扱っている
  • 既存テストに「拒否されるべきトークン」のケースがない
  • 401/403の監視やアラートが未整備
  • マルチテナント対応を設定値だけで済ませている

セキュリティ更新は、単にライブラリを上げるだけでは不十分です。受け入れるトークンの境界を明文化し、テストで確認するところまでが対応範囲です。

まとめ:Azure SDKのAAD認証更新ではtenant-idとaudienceを最優先で確認する

今回のAzure SDK documentation updateは、Spring Cloud AzureのAAD認証をより安全なデフォルトへ寄せる変更です。確認すべき中心は、単一テナントのissuer検証、tidの整合性、audの明示チェックです。

最初にやるべきことは、現在の設定でtenant-idにcommon、organizations、consumersを使っていないか確認することです。次に、APIへ送られるアクセストークンのaudが自APIのclient-idまたはapp-id-uriと一致しているか確認します。最後に、別テナントや別API向けトークンが拒否されるテストを追加します。

この変更で一部のトークンが通らなくなる場合、それは単なる不具合ではなく、これまで曖昧だった認証境界が明確になった結果かもしれません。ライブラリ更新前に設定とテストを見直し、意図したテナント・意図したAPI宛てのトークンだけを受け入れる構成に整えてください。

この記事を書いた人

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

コメント

コメントする

目次