El navegador no configurará la cookie ASP.NET_SessionId en la solicitud de entrada de la pasarela de pago a nuestro sitio

12

Estamos experimentando un extraño problema con el proceso de pago de nuestra aplicación web que resulta en la pérdida de datos de la sesión.

En este proceso, después de que nuestro usuario de la página de pago sea redirigido a la página del proveedor de pagos y redirigido de nuevo a nuestro sitio (a una URL que especifiquemos) tan pronto como haya terminado allí. Esta última redirección se realiza mediante la evaluación del navegador del código html del proveedor de pagos que básicamente consiste en un formulario que se publica en nuestro sitio y unas pocas líneas de código JavaScript que publica ese formulario en la carga de la página. En este punto, el navegador realiza la solicitud de publicación pero no establece la cookie "ASP.NET_SessionId" que está presente en las solicitudes anteriores hechas al mismo dominio (el dominio de nuestra aplicación). Lo que es más extraño es que establece otra cookie que usamos llamada "AcceptCookie". Simplemente elige soltar la cookie "ASP.NET_SessionId".

Para ilustrar la situación, tomé algunas capturas de pantalla. (En estas capturas de pantalla, los rectángulos naranja y verde contienen exactamente el mismo valor).

  1. Esta es la solicitud que hizo (a nuestra aplicación) cuando el usuario presiona el botón "Check Out". Después de esta solicitud, el usuario es redirigido a la página del proveedor de pagos.

solicitud de salida

  1. Esta es la página final que sirve el proveedor de pagos después de que el usuario haya terminado allí. Como puede ver, es solo un formulario simple que se publica automáticamente en nuestro dominio al cargar la página.

respuesta final del proveedor de pagos

  1. Pero esta solicitud de publicación no incluye la cookie "ASP.NET_SessionId" que da como resultado la adquisición de una nueva identificación de sesión y la pérdida de datos de la sesión anterior. Y de nuevo, solo falta "ASP.NET_SessionId", no el otro llamado "AcceptCookie".

solicitud de publicación que lleva al usuario de vuelta a nuestro sitio (hecho con javascript en el paso anterior)

Finalmente, supusimos que en las versiones anteriores de los navegadores este problema no ocurre. En Firefox 52 funciona de maravilla, pero en Firefox 71 ocurre el problema anterior.

¿Algunas ideas?

Nota: es una aplicación ASP.NET MVC con targetFramework = "4.5.2"

Que tengas un buen día.

E. Özgür
fuente

Respuestas:

16

Lo descubrimos.

De alguna manera, el atributo "SameSite" de la cookie "ASP.NET_SessionId" se predetermina a "Lax" y esto hace que la cookie de sesión no se agregue a la solicitud realizada por el código javascript de la pasarela de pago.

Agregamos la siguiente regla al archivo web.config para anular este valor y establecerlo en "Ninguno".

<configuration>
  <system.webServer>
    <rewrite>
      <outboundRules>
        <rule name="Add SameSite" preCondition="No SameSite">
          <match serverVariable="RESPONSE_Set_Cookie" pattern=".*" negate="false" />
          <action type="Rewrite" value="{R:0}; SameSite=None" />
          <conditions>
          </conditions>
        </rule>
        <preConditions>
          <preCondition name="No SameSite">
            <add input="{RESPONSE_Set_Cookie}" pattern="." />
            <add input="{RESPONSE_Set_Cookie}" pattern="; SameSite=None" negate="true" />
          </preCondition>
        </preConditions>
      </outboundRules>
    </rewrite>
  </system.webServer>
</configuration>

ACTUALIZACIÓN 1 : Solo agregar la configuración anterior resolvió el problema para los navegadores modernos, pero nos dimos cuenta de que todavía teníamos problemas con las versiones anteriores de Micosoft Edge e Internet Explorer.

Por lo tanto, necesitábamos agregar el atributo cookieSameSite = "None" al nodo sessionState en el archivo web.config.

<sessionState cookieSameSite="None" />

Sin embargo, tenga cuidado con este cambio de configuración, ya que las versiones anteriores de .NET Framework no lo admiten y hacen que su sitio muestre una página de error.

Por cierto, todavía tenemos problemas con los navegadores en iOS 12. Pero creo que está relacionado con este error confirmado

ACTUALIZACIÓN 2 : vea la respuesta de zemien para una posible solución sobre el problema de IOS

ACTUALIZACIÓN 3 : Al combinar nuestros hallazgos con las sugerencias en la respuesta de zemien, hemos creado las siguientes reglas de reescritura. Hemos estado usando esta configuración en producción. Pero cuidado: marca todas las cookies con el atributo "SameSite: None" para navegadores compatibles y excluye el atributo SameSite, si existe, para navegadores incompatibles. Puede parecer complicado, pero traté de explicarlo a través de líneas de comentarios.

Esta es la configuración FINAL que utilizamos en la producción:

<configuration> 

  <system.webServer>

    <rewrite>

      <outboundRules>

        <preConditions>
          <!-- Browsers incompatible with SameSite=None -->
          <preCondition name="IncompatibleWithSameSiteNone" logicalGrouping="MatchAny">
            <add input="{HTTP_USER_AGENT}" pattern="(CPU iPhone OS 12)|(iPad; CPU OS 12)" />
            <add input="{HTTP_USER_AGENT}" pattern="(Chrome/5)|(Chrome/6)" />
            <add input="{HTTP_USER_AGENT}" pattern="( OS X 10_14).*(Version/).*((Safari)|(KHTML, like Gecko)$)" />
          </preCondition>

          <!-- Rest of the browsers are assumed to be compatible with SameSite=None -->
          <preCondition name="CompatibleWithSameSiteNone" logicalGrouping="MatchAll">
            <add input="{HTTP_USER_AGENT}" pattern="(CPU iPhone OS 12)|(iPad; CPU OS 12)" negate="true" />
            <add input="{HTTP_USER_AGENT}" pattern="(Chrome/5)|(Chrome/6)" negate="true" />
            <add input="{HTTP_USER_AGENT}" pattern="( OS X 10_14).*(Version/).*((Safari)|(KHTML, like Gecko)$)" negate="true" />
          </preCondition>

        </preConditions>

        <!-- Rule 1: Remove SameSite part from cookie for incompatible browsers if exists -->
        <rule name="Remove_SameSiteCookie_IfExists_ForLegacyBrowsers" preCondition="IncompatibleWithSameSiteNone">
          <match serverVariable="RESPONSE_Set-Cookie" pattern="(.*)(SameSite=.*)" />
          <action type="Rewrite" value="{R:1}" />
        </rule>

        <!-- Rule 2: Override SameSite's value to None if exists, for compatible browsers -->
        <rule name="Override_SameSiteCookie_IfExists_ForModernBrowsers" preCondition="CompatibleWithSameSiteNone">
          <match serverVariable="RESPONSE_Set-Cookie" pattern="(.*)(SameSite=.*)" />
          <action type="Rewrite" value="{R:1}; SameSite=None" />
        </rule>

        <!-- Rule 3: Add SameSite attribute with the value None if it does not exists, for compatible browsers -->
        <rule name="Add_SameSiteCookie_IfNotExists_ForModernBrowsers" preCondition="CompatibleWithSameSiteNone">
          <match serverVariable="RESPONSE_Set-Cookie" pattern=".*"/>
          <!-- Condition explanation: Cookie data contains some string value but does not contain SameSite attribute -->
          <conditions logicalGrouping="MatchAll">
            <add input="{R:0}" pattern="^(?!\s*$).+"/>
            <add input="{R:0}" pattern="SameSite=.*" negate="true"/>
          </conditions>
          <action type="Rewrite" value="{R:0}; SameSite=None" />
        </rule>

      </outboundRules>

    </rewrite>    

  </system.webServer>  

</configuration>
E. Özgür
fuente
Gracias @ EÖzgür. Este problema proviene de KB4533097 ( support.microsoft.com/en-us/help/4533097/kb4533097 ) en KB4533011 (.net 4.7 y versiones más recientes) y KB4533004 (.net 4.8) lanzado el 10 de diciembre.
S. Pineau
Tengo el mismo problema, pero a veces asp.net mvc le da al cliente las cookies ASP.NET_SessionId con LAX, a veces con NINGUNO. No estoy seguro de por qué sucede. Quiero decir que debería ser LAX todo el tiempo, pero aún así, cuando inicio sesión en el sitio, puedo obtener NINGUNO.
Duque
¡Oh hombre! He estado loco por este problema durante dos días. Finalmente su respuesta me salvó el día y la frustración. Gracias.
Hemanth
1
Tuvimos este problema en Server 2016 después de aplicar las actualizaciones de diciembre. (KB4530689). ¡Muchas gracias por encontrar la solución!
user0474975
¿Esto es solo para dotnet core? En mi aplicación Framework, estoy mostrando esas opciones como valores no válidos para establecer.
IronSean
3

Modifiqué varias respuestas SO para obtener esta reescritura de URL que se agrega SameSite=Nonea las cookies de sesión, y también elimino SameSite=Nonede todas las cookies para la mayoría de los navegadores incompatibles. El objetivo de esta reescritura es preservar el comportamiento "heredado" anterior a Chrome 80.

Escritura completa en mi blog de primera línea del codificador :

<rewrite>
  <outboundRules>
    <preConditions>
      <!-- Checks User Agent to identify browsers incompatible with SameSite=None -->
      <preCondition name="IncompatibleWithSameSiteNone" logicalGrouping="MatchAny">
        <add input="{HTTP_USER_AGENT}" pattern="(CPU iPhone OS 12)|(iPad; CPU OS 12)" />
        <add input="{HTTP_USER_AGENT}" pattern="(Chrome/5)|(Chrome/6)" />
        <add input="{HTTP_USER_AGENT}" pattern="( OS X 10_14).*(Version/).*((Safari)|(KHTML, like Gecko)$)" />
      </preCondition>
    </preConditions>

    <!-- Adds or changes SameSite to None for the session cookie -->
    <!-- Note that secure header is also required by Chrome and should not be added here -->
    <rule name="SessionCookieAddNoneHeader">
      <match serverVariable="RESPONSE_Set-Cookie" pattern="((.*)(ASP.NET_SessionId)(=.*))(SameSite=.*)?" />
      <action type="Rewrite" value="{R:1}; SameSite=None" />
    </rule>

    <!-- Removes SameSite=None header from all cookies, for most incompatible browsers -->
    <rule name="CookieRemoveSameSiteNone" preCondition="IncompatibleWithSameSiteNone">
      <match serverVariable="RESPONSE_Set-Cookie" pattern="(.*)(SameSite=None)" />
      <action type="Rewrite" value="{R:1}" />
    </rule>
  </outboundRules>
</rewrite>

Esto debería funcionar para la mayoría de las aplicaciones ASP .Net y ASP .Net Core, aunque los Frameworks más nuevos tienen el código y las opciones de configuración adecuados para permitirle controlar este comportamiento. Recomiendo investigar todas las opciones disponibles antes de usar mi reescritura anterior.

zemien
fuente