Cookie os redirecionamentos de login estão desativados para endpoints conhecidos da API

Por defeito, pedidos não autenticados e não autorizados feitos a endpoints API conhecidos protegidos por autenticação cookie agora resultam em respostas 401 e 403 em vez de serem redirecionados para URIs de login ou de acesso negado.

Os endpoints conhecidos da API são identificados através da nova IDisableCookieRedirectMetadata interface, e os metadados que implementam a nova interface foram adicionados automaticamente ao seguinte:

  • [ApiController] pontos de extremidade.
  • Endpoints mínimos de API que leiam corpos de pedidos JSON ou escrevam respostas JSON.
  • Endpoints usando TypedResults tipos de retorno.
  • SignalR pontos de extremidade.

A interface complementar IAllowCookieRedirectMetadata faz com que um endpoint volte a aderir aos redirecionamentos. Substitui IDisableCookieRedirectMetadata independentemente da ordem em que os metadados são adicionados.

As respostas 401 e 403 continuam a incluir um Location cabeçalho com o login ou URI de acesso negado. Só o código de estado muda.

Apenas os caminhos de desafio (401) e proibido (403) consideram os metadados do endpoint. Os redirecionamentos de log-out e return-URL não são afetados.

Versão introduzida

.NET 10 Prévia 7

Comportamento anterior

Anteriormente, o cookie handler de autenticação redirecionava pedidos não autenticados e não autorizados para um URI de login ou acesso negado por defeito para todos os pedidos exceto XMLHttpRequests (XHRs).

Novo comportamento

A partir do .NET 10, pedidos não autenticados e não autorizados feitos a endpoints conhecidos da API resultam em respostas 401 e 403 em vez de serem redirecionados para um URI de login ou acesso negado. As XHRs continuam a resultar em respostas 401 e 403, independentemente do endpoint de destino.

Tipo de mudança disruptiva

Esta alteração é de natureza comportamental .

Motivo da mudança

Esta alteração foi altamente solicitada. Redirecionar pedidos não autenticados para uma página de login normalmente não faz sentido para endpoints de API, que normalmente dependem de códigos de estado 401 e 403 em vez de redirecionamentos HTML para comunicar falhas de autenticação.

Para restaurar o comportamento anterior em toda a aplicação, ative a opção Microsoft.AspNetCore.Authentication.Cookies.IgnoreRedirectMetadata. Cookiea autenticação ignora então os metadados do endpoint, e apenas os XHRs resultam em respostas 401 e 403, que correspondem ao comportamento pré-.NET 10. Defina o switch no ficheiro do projeto para que se aplique antes de qualquer código da aplicação ser executado:

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

A opção é lida uma vez, da primeira vez que a autenticação cookie for utilizada, por isso, se a definir no código, chame SetSwitch antes de o anfitrião ser criado:

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

var builder = WebApplication.CreateBuilder(args);

Para restaurar redirecionamentos para endpoints individuais, chame AllowCookieRedirect ou aplique o AllowCookieRedirectAttribute a um método de ação ou classe controladora:

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

Por outro lado, chame DisableCookieRedirect para devolver códigos de estado 401 e 403 para pontos finais que não sejam detetados automaticamente como pontos finais da API.

Se quiser sempre redirecionar para os URIs de login e acesso negado para pedidos não autenticados ou não autorizados, independentemente do endpoint alvo ou se a origem do pedido é um XHR, pode sobrescrever RedirectToLogin e RedirectToAccessDenied da seguinte forma:

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 quiser reverter ao comportamento exato anterior que evita o redirecionamento especificamente para XHRs, pode substituir os eventos com esta lógica um pouco mais complicada:

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

APIs afetadas

Consulte também