Obtener API con cookie

199

Estoy probando la nueva API Fetch pero tengo problemas con las cookies. Específicamente, después de un inicio de sesión exitoso, hay un encabezado de Cookie en futuras solicitudes, pero Fetch parece ignorar esos encabezados, y todas mis solicitudes realizadas con Fetch no están autorizadas.

¿Es porque Fetch todavía no está listo o Fetch no funciona con Cookies?

Construyo mi aplicación con Webpack. También uso Fetch en React Native, que no tiene el mismo problema.

Khanetor
fuente

Respuestas:

279

Fetch no utiliza cookies por defecto. Para habilitar la cookie, haga esto:

fetch(url, {
  credentials: "same-origin"
}).then(...).catch(...);
Khanetor
fuente
55
el mismo origen ya no funciona, incluir sí (ver la respuesta de @ Jerry): developers.google.com/web/updates/2015/03/introduction-to-fetch
jpic
77
@jpic: 'incluir' solo funciona para solicitudes de origen cruzado, pero no para solicitudes del mismo origen. Documentos oficiales: github.com/github/fetch#sending-cookies
HoldOffHunger
¿Cuál es la razón para tener cookies de httponly si son legibles en js con fetch?
Martin Bajcar
44
Creo same-origin(que lo hace todavía trabajo) significa que más cabeceras serán respetados (galletas, etc.), pero su código tendrán un acceso limitado a la respuesta.
Coderer
2
@JohnBalvinAriasThx. Como más tarde entendí, tener cookie httponly significa que no es legible document.cookie, pero aún está disponible para ajax o buscar solicitudes.
Martin Bajcar
184

Además de la respuesta de @ Khanetor, para aquellos que trabajan con solicitudes de origen cruzado: credentials: 'include'

Ejemplo de solicitud de búsqueda JSON:

fetch(url, {
  method: 'GET',
  credentials: 'include'
})
  .then((response) => response.json())
  .then((json) => {
    console.log('Gotcha');
  }).catch((err) => {
    console.log(err);
});

https://developer.mozilla.org/en-US/docs/Web/API/Request/credentials

zurfyx
fuente
9
¿Cómo se configura la cookie?
pomo
2
La cookie se configura desde el lado del servidor. En mi caso estaba usando cookies de httponly.
Khanetor
3
@Khanetor ¿puedo configurar cookies usando el document.cookie de javascript y luego enviar la solicitud?
Ospider
@ospider Puede enviarlo en el encabezado.
10101010
2
@ospider Descubrí que solo establecer el valor document.cookieera suficiente para que se incluyera en las solicitudes.
skwidbreth
35

Acabo de resolver. Solo dos f. días de brutforce

Para mí el secreto estaba en seguir:

  1. Llamé a POST / api / auth y vi que las cookies se recibieron con éxito.

  2. Luego llamé a GET / api / users / with credentials: 'include'y obtuve 401 unauth, debido a que no se enviaron cookies con la solicitud.

La CLAVE es establecer también credentials: 'include'la primera /api/authllamada.

usuario1671599
fuente
1
Tengo exactamente tu problema. La cookie de sesión nunca se envía en la solicitud de datos GET. 401. He probado Axios y Fetch. mismo resultado 2 posibilidades: el POST de inicio de sesión no almacena la cookie recibida o los siguientes datos GET no envían la cookie almacenada
Rhubarb65
@ Rhubarb65, para ganar esto, debe especificar credentials: 'include'para el primeroPOST /api/auth
user1671599
Sí, tuve eso pero quiero lo suficiente. Yo uso un proxy devserver (cliente HTTP)
Rhubarb65
Sí, tenía credenciales pero no era suficiente. Estaba usando un proxy de devserver para pasar CORS: (cliente http) - proxy - (servidor https). Creo que esto significa que la cookie de sessionid del servidor no se configuró en el navegador porque las cookies seguras requieren https. Así que agregué el indicador https: true en el proxy del servidor y eso lo solucionó
Rhubarb65
1
Bien salud. Su respuesta significa que solo me llevó 1 día de fuerza bruta. :)
Michael
16

Si está leyendo esto en 2019, credentials: "same-origin"es el valor predeterminado.

fetch(url).then
alextrastero
fuente
1
Pero tenga en cuenta que no todos usan un navegador suficientemente actualizado. Me encontré con esta pregunta porque mi propia versión de Firefox (60.x, la más reciente en Debian Stretch) no establece eso de manera predeterminada.
philh
2

Simplemente agregue a las respuestas correctas aquí para los .net webapi2usuarios.

Si está utilizando corsporque su sitio de cliente se sirve desde una dirección diferente a la suya, webapientonces debe incluir también SupportsCredentials=trueen la configuración del lado del servidor.

        // Access-Control-Allow-Origin
        // https://docs.microsoft.com/en-us/aspnet/web-api/overview/security/enabling-cross-origin-requests-in-web-api
        var cors = new EnableCorsAttribute(Settings.CORSSites,"*", "*");
        cors.SupportsCredentials = true;
        config.EnableCors(cors);
Mark Dornian
fuente
0

Esto funciona para mi:

import Cookies from 'universal-cookie';
const cookies = new Cookies();

function headers(set_cookie=false) {
  let headers = {
    'Accept':       'application/json',
    'Content-Type': 'application/json',
    'X-CSRF-Token': $('meta[name="csrf-token"]').attr('content')
};
if (set_cookie) {
    headers['Authorization'] = "Bearer " + cookies.get('remember_user_token');
}
return headers;
}

Luego construya su llamada:

export function fetchTests(user_id) {
  return function (dispatch) {
   let data = {
    method:      'POST',
    credentials: 'same-origin',
    mode:        'same-origin',
    body:        JSON.stringify({
                     user_id: user_id
                }),
    headers:     headers(true)
   };
   return fetch('/api/v1/tests/listing/', data)
      .then(response => response.json())
      .then(json => dispatch(receiveTests(json)));
    };
  }
aarkerio
fuente