Cookie I reindirizzamenti di accesso sono disabilitati per gli endpoint API noti

Per impostazione predefinita, le richieste non autenticate e non autorizzate effettuate all'endpoint API noto protetto dall'autenticazione cookie comportano ora risposte 401 e 403 anziché reindirizzare a un URI di accesso o negato all'accesso.

Gli endpoint API noti vengono identificati usando la nuova IDisableCookieRedirectMetadata interfaccia e i metadati che implementano la nuova interfaccia sono stati aggiunti automaticamente ai seguenti:

  • [ApiController] endpoint.
  • Endpoint API minimi che leggono i corpi delle richieste JSON o scrivono risposte JSON.
  • Endpoint che usano TypedResults tipi di ritorno.
  • SignalR endpoint.

L'interfaccia associata IAllowCookieRedirectMetadata riattiva i reindirizzamenti per un endpoint. Esegue l'override IDisableCookieRedirectMetadata indipendentemente dall'ordine in cui vengono aggiunti i metadati.

Le risposte 401 e 403 includono ancora un'intestazione Location che contiene l'URI di accesso o di accesso negato. Cambia solo il codice di stato.

Solo i percorsi di challenge (401) e di divieto (403) tengono conto dei metadati dell'endpoint. I reindirizzamenti di disconnessione e dell'URL di ritorno rimangono invariati.

Versione introdotta

.NET 10 Preview 7

Comportamento precedente

In precedenza, il cookie gestore di autenticazione reindirizza per impostazione predefinita le richieste non autenticate e non autorizzate a un URI di login o di accesso negato per tutte le richieste diverse da XMLHttpRequests (XHRs).

Nuovo comportamento

A partire da .NET 10, le richieste non autenticate né autorizzate effettuate agli endpoint API noti generano risposte 401 e 403 anziché reindirizzare a un URI di accesso o negato. Le richieste XHR continuano a produrre risposte 401 e 403 indipendentemente dall'endpoint di destinazione.

Tipo di cambiamento che interrompe la compatibilità

Questa modifica è una modifica funzionale.

Motivo della modifica

Questa modifica è stata altamente richiesta. Il reindirizzamento di richieste non autenticate a una pagina di accesso non ha in genere senso per gli endpoint API, che in genere si basano su codici di stato 401 e 403 anziché reindirizzamenti HTML per comunicare errori di autenticazione.

Per ripristinare il comportamento precedente per l'intera app, abilitare l'opzione Microsoft.AspNetCore.Authentication.Cookies.IgnoreRedirectMetadata . Cookiel'autenticazione ignora quindi i metadati dell'endpoint e solo le richieste XHR generano risposte 401 e 403, che corrispondono al comportamento precedente .NET 10. Impostare l'opzione nel file di progetto in modo che venga applicata prima dell'esecuzione di qualsiasi codice dell'app:

<ItemGroup>
  <RuntimeHostConfigurationOption
    Include="Microsoft.AspNetCore.Authentication.Cookies.IgnoreRedirectMetadata"
    Value="true" />
</ItemGroup>

L'opzione viene letta una sola volta, la prima volta che si usa l'autenticazione cookie, quindi, se invece la si imposta nel codice, chiamare SetSwitch prima che venga compilato l'host:

AppContext.SetSwitch(
    "Microsoft.AspNetCore.Authentication.Cookies.IgnoreRedirectMetadata", true);

var builder = WebApplication.CreateBuilder(args);

Per ripristinare invece i reindirizzamenti per i singoli endpoint, chiama AllowCookieRedirect o applica AllowCookieRedirectAttribute a un metodo di azione o a una classe controller:

app.MapGet("/reports/summary", () => new { Total = 1000 })
   .RequireAuthorization()
   .AllowCookieRedirect();

Viceversa, chiamare DisableCookieRedirect per restituire i codici di stato 401 e 403 per gli endpoint che non vengono rilevati automaticamente come endpoint API.

Se si vuole sempre reindirizzare agli URI di accesso e di accesso negato per le richieste non autenticate o non autorizzate indipendentemente dall'endpoint di destinazione o dal fatto che l'origine della richiesta sia un XHR, si può fare l'override di RedirectToLogin e RedirectToAccessDenied come indicato di seguito:

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;
        };
    });

Se si vuole ripristinare l'esatto comportamento precedente che evita il reindirizzamento solo per le richieste XHR, è possibile eseguire l'override degli eventi con questa logica leggermente più complessa:

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;
        };
    });

Le API interessate

Vedere anche