Tralgar
Tralgar

Reputation: 290

cookie httponly not sent

I'm building an api with api platform and a front with react (using the react template of apiplatform). I configured authentification and a return to client with httponly cookie which contains the jwt. But when my front does a request, it does not send this cookie... And I absolutly don't know why, I thought it was automaticaly done by browser till it's on same domain.

Here is an example of the network history from my client :

authentication request with httponly cookie in response header

second request without auth cookie

my app is running on https://localhost:3000/

Do you see something wrong in theses request ? Or does anyone has an idea of what it could come from ? My app and api are using https and have a valid certificate...

If you need any additional info, feel free to ask, and thanks all !!!

Upvotes: 0

Views: 3532

Answers (6)

Mostafa Rafid
Mostafa Rafid

Reputation: 71

Faced the same problem.Tried out many solutions but didn't work.At last found out it was the cors configuration of node backend that was causing the problem. Configured cors like the following way to solve the problem.

const corsConfig = {
  origin: true,
  credentials: true,
};

app.use(cors(corsConfig));
app.options('*', cors(corsConfig));

Upvotes: 0

Tralgar
Tralgar

Reputation: 290

ok, I've found solution : add credentials to the auth request, if header is not added, cookie won't be stored by browser. And second point :

const fetchHydra = (url, options = {}) =>
  baseFetchHydra(url, {
    ...options,
    credentials: 'include',
  });

credentials: 'include' is not in headers option... Nice !

Upvotes: 0

Tralgar
Tralgar

Reputation: 290

I can't answer in comment because there's code... So, It's managed by the react admin base of api-platform (https://api-platform.com/docs/admin/), but my config is like this :


const fetchHeaders = {
  credentials: 'include',
};

const fetchHydra = (url, options = {}) =>
  baseFetchHydra(url, {
    ...options,
    headers: new Headers(fetchHeaders),
  });

const apiDocumentationParser = (entrypoint) =>
  parseHydraDocumentation(entrypoint, { headers: new Headers(fetchHeaders) }).then(
    ({ api }) => ({ api }),
    (result) => {
        ...
    },
  );

const dataProvider = baseHydraDataProvider(entrypoint, fetchHydra, apiDocumentationParser, true);

So, all get, post etc request for datas are based on this conf

But my first call for authentication is done like that :

login: ({ username, password }) => {
    const request = new Request(`${entrypoint}/authentication_token`, {
      method: 'POST',
      body: JSON.stringify({ username, password }),
      headers: new Headers({ 'Content-Type': 'application/json' }),
    });
    return fetch(request).then((response) => {
      if (response.status < 200 || response.status >= 300) {
        localStorage.removeItem('isAuthenticated');
        throw new Error(response.statusText);
      }
      localStorage.setItem('isAuthenticated', 'true');
    });
  },

Upvotes: 0

Tralgar
Tralgar

Reputation: 290

Okay, I'm still having my issue finally... My browser is not sending the cookie...

My auth request returning bearer cookie (valid, tested with postman) auth request ok

My cookie received from auth request cookie received from auth request

My GET request without that auth cookie get request without cookie

I'm missing something but I don't find it... I've set credentials, Access-Control-Allow-Credentials, samesite is 'none' for sending it everywhere. Is there something else to do ? Or maybe I'm doing a stupid little thing that is wrong ?

Upvotes: 0

Tralgar
Tralgar

Reputation: 290

Ok, I didn't know... I've found nothing on it when I was trying to solve my prob. I'm using cookie httponly because :

  • I want to try it :D
  • Lot of security articles says that it's more secure because client api can't access theses cookies, browser manages it. It seems to counter xss and stealth of cookies, but if my cookie is stored with localforage, I think I do not have this problem, but with localStorage I do, no ?
  • It's cool no ! I've done too many project with classic bearer auth, I can improve it now

A big thanks for your nice answer rugolinifr !

Upvotes: 0

rugolinifr
rugolinifr

Reputation: 1281

I assume you work with either xhr or fetch.

Cookies ignore ports, but cross origin policy does not.

You work with two urls (http://localhost:8443 and http://localhost:3000). So your app is making cross origin request because ports differ.

xhr requires to set its withCredentials property to true in order to send cookies with cross-origin request. fetch requires its credentials parameter to be set to include.

Server side, set the Access-Control-Allow-Credentials to true.

Also note that your cookie is samesite=strict. In production, if you use two domains for your app and your api, it will never be sent.

The real question here is why using a cookie instead of Authorization header ?

Upvotes: 2

Related Questions