次の方法で共有


既知の API エンドポイントで Cookie ログイン リダイレクトが無効になっている

既定では、Cookie 認証によって保護されている既知の API エンドポイントに対して行われた認証されていない要求と未承認の要求により、ログインまたはアクセス拒否 URI にリダイレクトされるのではなく、401 と 403 の応答が返されるようになりました。

既知 の API エンドポイント は、新しい IApiEndpointMetadata インターフェイスを使用して識別され、新しいインターフェイスを実装するメタデータが自動的に次に追加されています。

  • [ApiController] エンドポイント。
  • JSON 要求本文を読み取ったり、JSON 応答を書き込んだりする最小限の API エンドポイント。
  • TypedResults戻り値の型を使用するエンドポイント。
  • SignalR エンドポイント。

導入されたバージョン

.NET 10 Preview 7

以前の動作

以前は、Cookie 認証ハンドラーは、 XMLHttpRequests (XHRs) 以外のすべての要求に対して、認証されていない要求と未承認の要求をログインまたはアクセス拒否 URI に既定でリダイレクトしました。

新しい動作

.NET 10 以降では、既知の API エンドポイントに対して行われた認証されていない要求と未承認の要求により、ログインまたはアクセス拒否 URI にリダイレクトされるのではなく、401 と 403 の応答が返されます。 XR は、ターゲット エンドポイントに関係なく、引き続き 401 応答と 403 応答を返します。

破壊的変更の種類

この変更は 動作の変更です。

変更の理由

この変更は非常に要求されました。 認証されていない要求をログイン ページにリダイレクトすることは、通常は API エンドポイントにとって意味がありません。通常は、認証エラーを伝えるために HTML リダイレクトではなく、401 と 403 の状態コードに依存します。

ターゲット エンドポイントに関係なく、または要求のソースが XHR であるかどうかに関係なく、認証されていない要求または承認されていない要求のログインとアクセス拒否 URI に常にリダイレクトする場合は、次のように RedirectToLoginRedirectToAccessDenied をオーバーライドできます。

builder.Services.AddAuthentication()
    .AddCookie(options =>
    {
        options.Events.OnRedirectToLogin = context =>
        {
            context.Response.Redirect(context.RedirectUri);
            return Task.CompletedTask;
        };

        options.Events.OnRedirectToAccessDenied = context =>
        {
            context.Response.Redirect(context.RedirectUri);
            return Task.CompletedTask;
        };
    });

XR のみのリダイレクトを回避する以前の正確な動作に戻す場合は、この少し複雑なロジックでイベントをオーバーライドできます。

builder.Services.AddAuthentication()
    .AddCookie(options =>
    {
        bool IsXhr(HttpRequest request)
        {
            return string.Equals(request.Query[HeaderNames.XRequestedWith], "XMLHttpRequest", StringComparison.Ordinal) ||
                string.Equals(request.Headers.XRequestedWith, "XMLHttpRequest", StringComparison.Ordinal);
        }

        options.Events.OnRedirectToLogin = context =>
        {
            if (IsXhr(context.Request))
            {
                context.Response.Headers.Location = context.RedirectUri;
                context.Response.StatusCode = 401;
            }
            else
            {
                context.Response.Redirect(context.RedirectUri);
            }

            return Task.CompletedTask;
        };

        options.Events.OnRedirectToAccessDenied = context =>
        {
            if (IsXhr(context.Request))
            {
                context.Response.Headers.Location = context.RedirectUri;
                context.Response.StatusCode = 403;
            }
            else
            {
                context.Response.Redirect(context.RedirectUri);
            }

            return Task.CompletedTask;
        };
    });

影響を受ける API