次の方法で共有


ASP.NET MVC アプリでの "ValidationContext.Nonce is null" エラー

この記事では、OpenID Connect (OIDC) ミドルウェアを使用して MVC アプリ ASP.NET 発生する可能性がある一般的な nonce 検証エラーの解決策について説明します。

一般的なエラー メッセージ

使用する Open Web Interface for .NET (OWIN) のバージョンによっては、次のいずれかのエラー メッセージが表示される場合があります。

  • IDX21323: RequireNonce は '[PII は既定で非表示になっています。 IdentityModelEventSource.csの 'ShowPII' フラグを true に設定して表示します。]' OpenIdConnectProtocolValidationContext.Nonce が null、OpenIdConnectProtocol.ValidatedIdToken.Payload.Nonce が null ではありません。 nonce を検証できません。 nonce を確認する必要がない場合は、OpenIdConnectProtocolValidator.RequireNonce を false に設定します。

  • IDX10311: RequireNonce は 'true' (既定値) ですが、validationContext.Nonce は null です。 nonce は検証できません。 nonce を確認する必要がない場合は、OpenIdConnectProtocolValidator.RequireNonce を false に設定します。

nonce Cookie について

ASP.NET OIDC ミドルウェアは、nonce Cookie を使用して、 再プレイ攻撃を防ぎます。 認証された要求で nonce Cookie が見つからない場合、アプリは例外をスローします。 Cookie はドメイン ベースです。 つまり、特定のドメインに対して Cookie が設定されている場合、そのドメインに対するすべての後続の要求には、有効期限が切れるか削除されるまで Cookie が含まれます。

次の Fiddler トレースは、これらの Cookie がどのように設定され、作業フローで使用されるかを示しています。

  • フレーム 116 では、ブラウザーは、Microsoft Entra ID によって保護されている OIDC アプリに要求を送信します。 要求を受信すると、アプリは認証されていないことを検出します。 次に、認証のために要求を Microsoft Entra ID (login.microsoftonline.com) にリダイレクトします。 さらに、アプリは "302" リダイレクト応答で OpenIdConnect.nonce Cookie を設定します。

    Fiddler Trace の Frame 116 のスクリーンショット。

  • 認証が成功すると (フレーム 120 から 228)、Microsoft Entra ID は、認証された ID トークンと共に要求を Web アプリ (フレーム 229) にリダイレクトします。 このドメインに対して以前に設定された nonce Cookie も POST 要求に含まれています。 OIDC ミドルウェアは、(別のリダイレクトを介して) ページの読み込みを続行する前に、認証されたトークンと nonce Cookie を検証します。 この時点で、nonce Cookie の目的は終了し、有効期限属性を期限切れに設定することでアプリによって無効になります。

    認証に関連する Fiddler トレース フレームのスクリーンショット。

ソリューション

原因 1: 同じ Web サイトに複数のドメインが使用されている

ブラウザーはもともとドメイン A (フレーム 9) 上のアプリに移動し、このドメインに nonce Cookie が設定されています。 その後、Microsoft Entra ID は認証されたトークンをドメイン B (フレーム 91) に送信します。 ドメイン B へのリダイレクトには nonce Cookie が含まれていないため、Web アプリは validationContext.Nonce is null エラーをスローします。

原因 1 に関連する Fiddler トレース フレームのスクリーンショット。

解決策 1

この問題を解決するには、次の手順に従ってください。

  1. 認証後に最初に使用されたものと同じドメインに要求をリダイレクトします。 Azure AD が認証された要求をアプリに送り返す場所を制御するには、ConfigureAuth メソッドで OpenIdConnectAuthentications.RedirectUri プロパティを設定します。

  2. アプリ登録でリダイレクト URI (応答 URL) を構成します。 そうしないと、次のエラーが表示されることがあります。AADSTS50011: 要求で指定された応答 URL が、Azure がアプリ用に構成した応答 URL と一致しません。 詳細については、「 Error AADSTS50011 with OpenID authentication」を参照してください。

原因 2: SameSite 属性が見つからない

SameSite Cookie のセキュリティ更新プログラムにより認証プロセスに関連するすべての Cookie (Nonce Cookie を含む) には、次の属性が含まれている必要があります。

  • SameSite=None
  • セキュリティで保護

詳細については、「 SameSite Cookie と Open Web Interface for .NET」を参照してください。

不足している SameSite 属性 Fiddler トレースのスクリーンショット。

解決策 2

両方の必須属性が含まれていることを確認するには、次の手順に従います。

  1. HTTPS プロトコルを使用して Web アプリに移動します。
  2. .NET Framework と NuGet パッケージを更新します。
    • .NET Framework アプリの場合: .NET Framework をバージョン 4.7.2 以降と関連する NuGet パッケージ (Microsoft.Owin.Security.OpenIdConnect、Microsoft.Owin) をバージョン 4.1.0 以降にアップグレードします。
    • .NET Core アプリの場合:
      • バージョン 2.x アプリでは .NET Core 2.1 以降を使用する必要があります。
      • バージョン 3.x アプリでは .NET Core 3.1 以降を使用する必要があります。

Startup.Auth.csの構成コードの例:

using System.Configuration;
using Owin;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.Cookies;
using Microsoft.Owin.Security.OpenIdConnect;
using System.Threading.Tasks;
using Microsoft.Owin.Security.Notifications;
using Microsoft.IdentityModel.Protocols.OpenIdConnect;

namespace NetWebAppOIDC2
{
    public partial class Startup
    {
        private static string clientId = ConfigurationManager.AppSettings["ida:ClientId"];
        private static string aadInstance = ConfigurationManager.AppSettings["ida:AADInstance"];
        private static string tenantId = ConfigurationManager.AppSettings["ida:TenantId"];
        private static string postLogoutRedirectUri = ConfigurationManager.AppSettings["ida:PostLogoutRedirectUri"];
        private static string authority = aadInstance + tenantId;

        public void ConfigureAuth(IAppBuilder app)
        {
            app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);

            app.UseCookieAuthentication(new CookieAuthenticationOptions());
            app.UseOpenIdConnectAuthentication(
                new OpenIdConnectAuthenticationOptions
                {
                    ClientId = clientId,
                    Authority = authority,
                    PostLogoutRedirectUri = postLogoutRedirectUri,
                    RedirectUri = "https://localhost:44313",
                    
                    Notifications = new OpenIdConnectAuthenticationNotifications
                    {
                        AuthenticationFailed = OnAuthenticationFailed
                    }

                    // Don't use SystemwebCookieManager class here to override the default CookieManager because that seems to negate the SameSite cookie attribute that's being set.
                    // CookieManager = new SystemWebCookieManager()

                });
        }

        private Task OnAuthenticationFailed(AuthenticationFailedNotification<OpenIdConnectMessage, OpenIdConnectAuthenticationOptions> context)
        {
            context.HandleResponse();
            context.Response.Redirect("/?errormessage=" + context.Exception.Message);
            return Task.FromResult(0);
        }
    }
}

サードパーティの情報に関する免責事項

この資料に記載されているサードパーティ製品は、マイクロソフトと関連のない他社の製品です。 明示的か黙示的かにかかわらず、これらの製品のパフォーマンスや信頼性についてマイクロソフトはいかなる責任も負わないものとします。

お問い合わせはこちらから

質問がある場合やヘルプが必要な場合は、サポート要求を作成するか、Azure コミュニティ サポートにお問い合わせください。 Azure フィードバック コミュニティに製品フィードバックを送信することもできます。