Strapi doesn't set HttpOnly cookie when logging by React with GraphQL

System Information
  • Strapi Version: 3.3.4
  • Operating System: MacOS BigSur 11.0
  • Database: sqlite
  • Node Version: 14.15.1
  • NPM Version: 6.14.8
  • Yarn Version: 1.22.10

Hello everyone,

I’ve been trying to implement authentication using create-react-app on front and Strapi on back using GraphQL mutations. I’ve succeeded but I want to store jwt somewhere secure so I went on searching on how to set to httpOnly cookie serverside.

I’ve followed this guide: https://talke.dev/strapi-user-permissions-jwt-cookies
and extended Auth.js & permissions.js with the changes to set the cookie there.

Auth.js changes:

const token = strapi.plugins["users-permissions"].services.jwt.issue({
  id: user.id,
});

ctx.cookies.set("token", token, {
  httpOnly: true,
  secure: process.env.NODE_ENV === "production" ? true : false,
  maxAge: 1000 * 60 * 60 * 24 * 14, // 14 Day Age
  domain: process.env.NODE_ENV === "development" ? "localhost" : process.env.PRODUCTION_URL,
});

ctx.send({
  status: 'Authenticated',
  user: sanitizeEntity(user.toJSON ? user.toJSON() : user, {
    model: strapi.query('user', 'users-permissions').model,
  }),
});

permissions.js changes:

let role;
if (ctx.request && ctx.request.header && !ctx.request.header.authorization) {
  const token = ctx.cookies.get("token");
  if (token) {
    ctx.request.header.authorization = "Bearer " + token;
  }
}
if (ctx.request && ctx.request.header && ctx.request.header.authorization) {
  // Rest of the code
}

Here is the problem, when I navigate in browser to http://localhost:1337/admin/auth/login and I login I get the cookie in the sessionstorage

However when I login from my react app at localhost:3000 using Login mutation, I get the response that the user is logged in (via update and console logging it) but there is no cookie

How can I get the server to put the cookie when I login from my react app login logic?

I want to use jwt in the cookie as a header bearer to authenticate routes
I have this code added in my index.js

const httpLink = createHttpLink({ uri: 'http://localhost:1337/graphql' });

const authLink = setContext((_, { headers }) => {
  const token = sessionStorage.getItem('jwtToken')
  console.log('token', token)
  return {
    headers: {
      ...headers,
      authorization: token ? `Bearer ${token}` : ''
    }
  }
})

const client = new ApolloClient({
  link: authLink.concat(httpLink),
  cache: new InMemoryCache()
});

I tried removing secure,maxAge, and domain from the ctx.cookies.set but nothing happens differently. I’ve made the register page using register mutation (in React app) and it correctly registeres the user and returns jwt (this is probably due to fact that the ctx.send in Auth.js is not modified for create user just login

I would appreciate any help

Thanks,
Semir

It’s easy: You cannot access a httpOnly cookie from JavaScript in your browser! (Look at MDN). So I assume the cookie is set correctly (look in your developer tools) but you just cannot access it. Actually you don’t have to. It will be sent with each request to the Strapi-API, so you don’t have to send it as auth-token.

1 Like