Entonces estoy usando OpenId Connect y el método de configuración AddOpenIdConnect para configurar la autenticación con Auth0. Lo probé completamente localmente usando localhost como el dominio de mis cookies y todo funciona muy bien. Sin embargo, tan pronto como publico esto en un entorno de producción, las cookies ya no parecen persistir. Lo loco es que estoy registrando el context.Response.Headers directamente después del método context.Response.Cookies.Append(...) y localmente se imprimen como se esperaba, pero en producción no.

OnTokenValidated = (context) =>
{
    var accessToken = context.TokenEndpointResponse.AccessToken;

    var domain = HostingEnvironment.IsProduction() ? $"{cookieOptions.Domain}.{cookieOptions.Extension}" : "localhost";

    context.Response.Cookies.Append("access_token", accessToken, new CookieOptions
    {
        Domain = domain,
        SameSite = Microsoft.AspNetCore.Http.SameSiteMode.Lax,
        Expires = DateTimeOffset.Now.AddHours(10),
        HttpOnly = true,
        Secure = HostingEnvironment.IsProduction(),
        Path = "/"
    });

    var idToken = context.TokenEndpointResponse.IdToken;

    context.Response.Cookies.Append("id_token", idToken, new CookieOptions
    {
        Domain = domain,
        SameSite = Microsoft.AspNetCore.Http.SameSiteMode.Lax,
        Expires = DateTimeOffset.Now.AddHours(10),
        HttpOnly = false,
        Secure = HostingEnvironment.IsProduction(),
        Path = "/"
    });

    // Right here is where I can see the difference. Even though I am printing out the headers directly after appending them, they never are set in production.
    context.HttpContext.RequestServices.GetService<ILogger<Startup>>().LogWarning($"[HEADERS] {JsonConvert.SerializeObject(context.Response.Headers)}");

    return Task.CompletedTask;
},

Incluso fui tan lejos como para ver la implementación de IResponseCookies.Append(...) para ver qué podría estar sucediendo, pero es muy simple y no veo ninguna forma de que no se puedan agregar estos a los encabezados.

https://github.com/aspnet/HttpAbstractions/blob/bc7092a32b1943c7f17439e419d3f66cd94ce9bd/src/Microsoft.AspNetCore.Http/Internal/ResponseCookies.cs#L50

public void Append(string key, string value, CookieOptions options)
{
    if (options == null)
    {
        throw new ArgumentNullException(nameof(options));
    }

    var setCookieHeaderValue = new SetCookieHeaderValue(
        Uri.EscapeDataString(key),
        Uri.EscapeDataString(value))
    {
        Domain = options.Domain,
        Path = options.Path,
        Expires = options.Expires,
        MaxAge = options.MaxAge,
        Secure = options.Secure,
        SameSite = (Net.Http.Headers.SameSiteMode)options.SameSite,
        HttpOnly = options.HttpOnly
    };

    var cookieValue = setCookieHeaderValue.ToString();

    Headers[HeaderNames.SetCookie] = StringValues.Concat(Headers[HeaderNames.SetCookie], cookieValue);
}
        
0
Matt Hintzke 31 ago. 2020 a las 19:43

1 respuesta

La mejor respuesta

Ok, finalmente lo descubrí todo. El Auth0 Quickstart para ASP .NET Core 3.x contiene lo siguiente líneas de código:

services.Configure<CookiePolicyOptions>(options =>
{
    // This lambda determines whether user consent for non-essential cookies is needed for a given request.
    options.CheckConsentNeeded = context => true;
    options.MinimumSameSitePolicy = SameSiteMode.None;
});

Esto obliga a que se requiera el "consentimiento" para todas las cookies. Todavía tengo que averiguar qué significa esto exactamente, ya que los documentos de MS parecen ser muy limitados. Después de cambiar esto a false, todo comenzó a funcionar nuevamente. false es el valor predeterminado, fue solo el Inicio rápido de Auth0 el que lo agregó por alguna razón.

Lo que más llevó a mi confusión fue que intenté ver la implementación de Cookies.Append(...) y encontré ResponseCookies clase que implementa IResponseCookies y terminó copiando / pegando esa implementación en mi código para que funcione. Después de excavar, me di cuenta de que no es esta implementación, sino este para ResponseCookiesWrapper que realmente se está utilizando. Como puede ver, esta implementación utiliza toda la lógica de "consentimiento" adicional para asegurarse de que se le permita agregar una cookie que aparentemente yo no estaba.

ACTUALIZAR: Lo siento, lo que mencioné fue que tenía esto funcionando solo en localhost, pero es posible que se pregunte por qué no estaba fallando en localhost y PROD. Esto se debe a que, aunque el Inicio rápido lo muestra codificado en true, el código de ejemplo en GitHub usa HostingEnvironment.IsProduction() que es lo que yo también tenía.

0
Matt Hintzke 2 sep. 2020 a las 19:29