Closed serendipity1004 closed 3 years ago
I am using following dependencies
"apollo-boost": "^0.1.22",
"apollo-client": "^2.4.7",
"apollo-link-context": "^1.0.10",
"apollo-link-http": "^1.5.7",
I have the same issue with apolloboost the cookies not sent with the request
Same here
Same here, anyone have any luck with this?
I think you need to verify your server the issue for me was the cors i was passing cors options in the wrong place now it works as expected
@serendipity1004 works here. Doesn't it work during SSR or on client side?
Figured it out. credentials:'include'
should be in the root of the config. Like,
new ApolloClient({
credentials: 'include',
})
I was using inside of fetchOptions
...
I'm pretty sure I'm still having this issue. My rest calls have cookies attached, however my graphql queries don't.
I'm having a similar problem, but I actually think it is a browser issue and nothing to do with the Apollo Client.
When I have my front-end hosted on Heroku like frontend.herokuapp.com
and my yoga backend on something like backend.herokupapp.com
, my Graphql queries will only retain the cookie if my browsers do NOT have "Disable 3rd Party Cookies" set or Safari's "Prevent Cross-site Tracking" enable.
It seems to me, the browser considers any cookie from different subdomain's to be 3rd party.
There are varying degrees of this:
Opera - Cookies blocked if "Block Third Party Cookies" enabled Firefox - Cookies work even with Block Third Party Cookies - Trackers" enabled but blocked if "All third party cookies" is selected Chrome - Cookies work unless "Block Third Party Cookies" enabled
Hi, I found that when I want to make request with "Cookie" then apollo client is not sending it, but just when I change it to "Cookies" then everything is ok XD
Hi there,
I'm still having the issue here. I'm working with:
withCredentials is sets to true in my apollo.config.ts file:
const uri = '/graphql';
const link = httpLink.create({
uri,
withCredentials: true
});
apollo.create({
link,
cache: new InMemoryCache(),
defaultOptions: {
watchQuery: {
errorPolicy: 'all'
}
},
connectToDevTools: true
});
Is there anybody that can tell us why ?
Hi, I found that when I want to make request with "Cookie" then apollo client is not sending it, but just when I change it to "Cookies" then everything is ok XD
@rrakso Did you mean like this?
headers: { cookies: ... }
Anyone have any further insight?
@TheoMer yup ;)
@rrakso Could you provide a snippet of what is working for you?
i'm using next-with-apollo
and it's working, you can do something like this
// createClient.js
import ApolloClient from "apollo-boost";
import withData from "next-with-apollo";
const createClient = ({ headers }) => {
return new ApolloClient({
uri: process.env.ENDPOINT,
request: operation => {
operation.setContext({
fetchOptions: {
credentials: "include"
},
headers
});
}
});
};
export default withData(createClient);
// index.js server
const cookieParser = require("cookie-parser");
require("dotenv").config({ path: "var.env" });
const createServer = require("./createServer");
const server = createServer();
server.express.use(cookieParser());
server.express.use((req, res, next) => {
const { token } = req.cookies;
console.log(token);
next();
});
server.start(
{
cors: {
credentials: true,
origin: ["http://localhost:3000"] // frontend url.
}
},
r => console.log(`Server is running on http://localhost:${r.port}`)
);
Figured it out.
credentials:'include'
should be in the root of the config. Like,new ApolloClient({ credentials: 'include', })
I was using inside of
fetchOptions
...
This also fixed my issue, the docs are a bit confusing as credentials: 'include' is nested under fetchOptions; putting in the root fixed my issue. Is there a reason why this option can be put in two places? Only the root worked for me and caused a lot of confusion
FYI: I'm using fetch, and axios, thats what's not setting the cookie header for me.
I had to do this for our build a few days ago, here is how I did it - https://gist.github.com/neil-gebbie-smarterley/cd8356df4c786c4c9dacfc9d46e890ac
Our set it is: Next/Apollo Client/Apollo Server/REST data source
It's basically just passing it through to the server, I'm not sure if the document.cookie is needed for subsequent requests, but it seems to be working ok for us, not in production yet, but it's passing cookies.
Oddly enough, what worked for me was to set an AuthLink with setContext
from apollo-link-context
and call localStorage.getItem("")
within it like so:
const authLink = setContext((_, { headers }) => {
const token = localStorage.getItem("");
return {
headers: {
...headers,
}
};
});
I'm not sure if this is a good workaround (maybe dangerous?); you'll be bombarded with reference errors as localStorage is not available when NextJS renders in server-side.
Edit: Eh...doesn't work on mobile.
This works for me:
return new ApolloClient({
uri: process.env.NODE_ENV === 'development' ? endpoint : prodEndpoint,
request: operation => {
operation.setContext({
fetchOptions: {
credentials: 'include',
},
headers: { cookie: headers && headers.cookie },
});
},
.......
});
Put the credentials: "include"
in your httpLink, like so.
const httpLink = createHttpLink({ uri, credentials: 'include',
});
Then put that in your ApolloClient. Worked finally without a bunch of custom stuff.
I've fixed it for myself using the latest libraries next@9.0.3, next-with-apollo@4.2.0 and react-apollo@3.0.0. Cookies are passed with every request, SSR working as expected and no errors. Code is here. I had to remove .restore(initialState || {})
so it's just cache: new InMemoryCache()
and now it's fully working. Only thing still not working is Safari. Anyone fixed it for Safari?
I'm pretty sure I'm still having this issue. My rest calls have cookies attached, however my graphql queries don't.
@RiChrisMurphy I'm seeing a similar issue. Were you able to find a fix for that?
@helfi92 Have you tried any of the solutions in this thread?
I think I understand what's happening. The client and server I'm working with are both subdomains of herokuapp (e.g.., ui.herokuapp.com
and web-server.herokuapp.com
). From https://devcenter.heroku.com/articles/cookies-and-herokuapp-com:
applications in the herokuapp.com domain are prevented from setting cookies for *.herokuapp.com
Using a custom domain will probably resolve the issue.
I've been trying in Razzle to no avail. Cookies are passed to playground very ok, but on razzle it's not
@juicycleff What does your createApolloClient file look like?
Do you have a withApolloClient HOC?
I'm still having an issue where the cookies are not getting sent at all, even with all of the above suggestions.
@seawatts are you using Apollo client and Apollo server?
Yeah I have tried the following
import { ApolloClient } from 'apollo-client';
const client = new ApolloClient({
link: ApolloLink.from([
new HttpLink({
headers,
fetchOptions: {
credentials: 'include',
},
uri: process.env.REACT_APP_SERVER_URL,
credentials: 'include',
}),
]),
cache: new InMemoryCache(),
});
and
import ApolloBoostClient from 'apollo-boost';
const client = new ApolloClient({
uri: process.env.REACT_APP_SERVER_URL,
headers,
credentials: 'include',
fetchOptions: {
credentials: 'include',
},
});
Then on the server side I'm using graphql-yoga
I think you need to explicitly pass the cookies through getInitialProps
in your withApolloClient HOC. Check out the gist(https://gist.github.com/neil-gebbie-smarterley/cd8356df4c786c4c9dacfc9d46e890ac) I posted - it might look like a lot of work to get it going, but if you log the cookies out at every step of the process you can see them being passed along from the browser through Apollo, and then onto it's final destination.
We have this set up working in production.
I had this issue using apollo client and apollo-server-express
With my use-case I needed to put credentials: 'include' in two places:
First, the cookie was not being created. Adding credentials: 'include' to createHTTPLink() solved this. Then I was getting connection refused errors when I would query the server. Placing credentials: 'include' in new ApolloClient() solved this issue.
@mdashmiller thanks. It worked for me as well. :smiley:
const httpLink = createUploadLink({
uri: util.graphQLUrl(),
credentials: 'include',
});
export default new ApolloClient({
link,
cache: new InMemoryCache(),
credentials: 'include',
});
After doing this, the session created on back-end via express-session
now appears in Application > Cookies :heart_eyes:
It seems that mixing headers: {...}
and credentials: 'include'
overrides the entire header and removes all cookie related content:
export default new ApolloClient({
link,
cache: new InMemoryCache(),
headers: {
'x-custom-header': 'test'
},
credentials: 'include',
});
In this case I would expect the headers to contain the cookies and the x-custom-header
header. It now only includes the x-custom-header
.
I've observed the same behavior described by @dkln
Cookies are not included when both headers
and credentials
are used
For me what worked was just to set the credentials
option also in the POST request for the login endpoint. If you're are using axios
like this
axios
.post(loginEndpoint, loginParams, { withCredentials: true }) // set withCredentials to true is important!
.then(response => {
// handle response
})
or fetch
response = await fetch (loginEndpoint, {
method: 'POST',
credentials: 'include', // set credentials to 'include' is important!
body: JSON.stringify({
email,
pw
})
})
json = await response.json();
Just for completeness this is my ApolloClient
setup:
const createApolloClient = () => {
return new ApolloClient({
link: new HttpLink({ uri: EXAMPLE_URL, credentials: 'include' }),
cache: new InMemoryCache(),
})
}
Hope this helps someone else too
Guys, do not mess with headers!!! It will overwrite session! Still don't know how to set custom headers and not lose session, anyone thoughts?
For anyone struggling with cookies being wiped out on refresh, initial load after deploying to production. You have to attach a domain option to your mutation in res.cookie
like:
{ domain: '.yourdomain.com' }
Then will the cookies work on refresh if your frontend is at frontend.yourdomain.com and backend at backend.yourdomain.com. It worked on localhost without this additional setting, because it's the same domain for backend and frontend: localhost. I lost a month on this only thinking it was Apollo Client issue.
As both @lawwantsin and @chemicalkosek stated, to ensure that my cookie is boh not wiped out and detected on refresh, I did the following:
ApolloClient
const httpLink = createHttpLink({
uri: process.env.NODE_ENV === 'development' ? endpoint : prodEndpoint,
credentials: 'include',
});
Back end
const token = jwt.sign({ userId: user.id }, process.env.APP_SECRET);
ctx.res.cookie('token', token, {
domain: process.env.NODE_ENV === 'development' ? process.env.LOCAL_DOMAIN : process.env.APP_DOMAIN,
secure: process.env.NODE_ENV === 'development' ? false : true,
httpOnly: true,
maxAge: 1000 * 60 * 60 * 24 * 365, // 1 year cookie
sameSite: 'lax',
});
FWIW my issue was that i did not set with credentials to 'true' in my login call (using axios) - which resulted in subsequent Apollo calls not sending the cookie. So not an issue with Apollo.
Took us a while to figure this out, but here were our couple of sticking points.
Currently the only place we configured credentials: 'include'
was in the HttpLink configuration object. This will fail giving you a cors error if you have not already set them up.
Assuming your setup is similar to ours, you are using the applyMiddleware
function to make changes to an instance of an express server. Within this object is where you must pass your cors configuration.
Ours looks like this for example (for dev):
{
origin: 'http://localhost:3000',
optionsSuccessStatus: 200,
credentials: true,
};
All of a sudden our client was passing cookies. Good luck!
omg I spent so long on this.
Here is how my setup looks:
For me, credentials: true
on the server (localhost:3001), and credentials: 'include'
on the client got things working for me on localhost!
... Then I deployed...
Once I deployed with SSL and the works to Kubernetes, cors was working, but cookies were not being shared.
I must have tried 800 combinations before I came across the concept of a domain cookie.
Should that cookie be the FQDN? The Auth server? The API Server?
I use passport on www
which is where the user logs in, and the cookie is stored. I assumed this meant I should use that www FQDN (https://www.domain.com). This did not work.
Turns out you can use cookies across subdomains (not domains), however, and this DID finally work. To do so, set the domain
value to .domain.com
the cookies started getting passed around!
From the www server:
const cookieSettings = {
maxAge: 24 * 60 * 60 * 1000,
keys: config.sessionKey,
secure: !dev
}
if (!dev && config.cookie && config.cookie.domain) {
cookieSettings.domain = config.cookie.domain // value: ".domain.com"
}
Hey, I have the same issue and I can't resolve it My FR (Vercel) & BE (Heroku) both are on a subdomains
On Firefox Set-Cookie
is not coming from response on Chrome/Brave Set-Cookie
is coming but after page reload redirects me to the login page.
This example is working on localhost but not after deploying it.
Apollo client
import withApollo from 'next-with-apollo'
import { ApolloClient } from 'apollo-client'
import { createHttpLink } from 'apollo-link-http'
import { InMemoryCache } from 'apollo-cache-inmemory'
import fetch from 'isomorphic-unfetch'
export default withApollo(({ initialState, headers }) => {
const isBrowser = typeof window !== 'undefined'
const backendUrl = ...
return new ApolloClient({
connectToDevTools: isBrowser,
ssrMode: !isBrowser,
link: createHttpLink({
uri: `${backendUrl}/graphql`,
credentials: 'include',
...(!isBrowser && { fetch }),
headers: {
...headers,
cookie: headers?.cookie,
},
}),
cache: new InMemoryCache().restore(initialState || {}),
})
})
My Next.js _app.js
const MyApp = ({ Component, pageProps, apollo }) => (
<>
<ApolloProvider client={apollo}>
<UserProvider>
<SEO />
<Header />
<main role="main">
<Component {...pageProps} />
</main>
</UserProvider>
</ApolloProvider>
</>
)
MyApp.getInitialProps = async ({ Component, ctx }) => {
let pageProps = {}
const { loggedInUser } = await checkLoggedIn(ctx.apolloClient)
// Check whether path is an "authorization" specific page
const auth = isAuthPath(ctx.asPath)
if (!loggedInUser.me) {
// User is not logged in. Redirect to Login.
if (!auth) redirect(ctx, '/login')
} else if (auth) {
// User is logged in. Redirect to Dashboard.
redirect(ctx, '/')
}
if (Component.getInitialProps) {
pageProps = await Component.getInitialProps(ctx)
}
return { pageProps, loggedInUser }
}
export default withApollo(MyApp)
"@apollo/react-hooks": "^3.1.5",
"apollo-cache-inmemory": "^1.6.6",
"apollo-client": "^2.6.9",
"apollo-link-http": "^1.5.17",
"graphql": "^15.0.0",
"graphql-tag": "^2.10.3",
"isomorphic-unfetch": "^3.0.0",
"next": "9.4.0",
"next-with-apollo": "^5.0.1",
"react": "16.13.1",
"react-dom": "16.13.1",
Server code:
app.set('trust proxy', 1)
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({ extended: false }))
app.use(
cors({
origin: process.env.FRONTEND_URL || `http://localhost:3000`,
credentials: true,
}),
)
app.use(
session({
store,
name: process.env.SESS_NAME,
secret: process.env.SESS_SECRET,
saveUninitialized: false,
resave: false,
cookie: {
secure: !dev,
httpOnly: true,
domain: process.env.SESS_DOMAIN,
maxAge: 1000 * 60 * 60 * 24 * 7, // 7 days
},
}),
)
@byurhanbeyzat
My FR (Vercel) & BE (Heroku) both are on a subdomains
You should have frontend and backend on subdomains within the same domain. Like frontend.yourdomain.com and backend.yourdomain.com. Then the cookies will be set.
Also I don't think you should spread headers there. At least it was breaking my code.
@chemicalkosek
My FR (Vercel) & BE (Heroku) both are on a subdomains
You should have frontend and backend on subdomains within the same domain. Like frontend.yourdomain.com and backend.yourdomain.com. Then the cookies will be set.
Also I don't think you should spread headers there. At least it was breaking my code.
Yes, they both are on same custom domain. If I remove headers it's not working event on localhost.
What is your process.env.SESS_DOMAIN
It should be yourdomain.com
.
@chemicalkosek SESS_DOMAIN - '.bbn.codes' app - bank.bbn.codes api - bank-api.bbn.codes
@byurhanbeyzat It looks like the cookie is not being wiped out on refresh, hmmm. Well I don't know :( . Btw you're using next-with-apollo 5.0.0, you should pass getDataFromTree in order to have SSR
// import { getDataFromTree } from '@apollo/react-ssr'; // You can also override the configs for withApollo here, so if you want // this page to have SSR (and to be a lambda) for SEO purposes and remove // the loading state, uncomment the import at the beginning and this: // // export default withApollo(Index, { getDataFromTree });
console.log your cors and cookie settings to make sure they actually are what you expect
I am currently using nextJS with apollo and it's completely unusable for me because the cookie is not passing in every request.
I would be much grateful if someone can just point me to right direction to pass cookies properly.
Even the apollo nextjs example is buggy itself https://github.com/adamsoffer/next-apollo-example
Even in that example, cookies are not being sent in the request.
I am trying every possible way of setting cookies in config without success.
Some people say swapping ApolloClient to ApolloBoost have solved it but neither of the packages work for me.
Below is an example of what I have tried