next-with-apollo
next-with-apollo copied to clipboard
Cookie Disappearing after reload
Hi there, I have an issue on production env. When reloading page the cookie is being deleted, I think this issue would be related to the lib because of this similar issue: https://github.com/vercel/next.js/discussions/12982#discussioncomment-22513
Does anyone know how to fix it? Perhaps wrong settings?
web
package.json
{
"next": "^9.4.0",
"next-cookies": "^2.0.3",
"next-fonts": "^1.0.3",
"next-with-apollo": "^5.0.1",
"apollo-boost": "^0.4.7",
"apollo-cache": "^1.3.4",
"apollo-cache-inmemory": "^1.6.5",
"apollo-cache-persist": "^0.1.1",
"apollo-client": "^2.6.8",
"apollo-link": "^1.2.14",
"apollo-link-context": "^1.0.19",
"apollo-link-error": "^1.1.13",
"apollo-link-http": "^1.5.16",
"apollo-link-token-refresh": "^0.2.7",
}
withApollo.ts
export default withApollo(
({ initialState, ctx, headers }) => {
console.log('host: ', process.env.NEXT_PUBLIC_BACKEND_HOST);
const ssrMode = !process.browser;
const getToken = async () => {
let serverAccessToken = '';
if (isServer()) {
const stringCookies = headers?.cookie;
if (stringCookies) {
const cookies = cookie.parse(headers?.cookie || '');
if (cookies.jid) {
const response = await axios(ENDPOINTS.REFRESH_TOKEN, {
method: 'POST',
withCredentials: true,
headers
});
const data = await response.data;
serverAccessToken = data.accessToken;
}
}
}
return serverAccessToken;
};
const httpLink: ApolloLink = new HttpLink({
uri: `${ENDPOINTS.GRAPHQL}`,
credentials: 'include',
fetch
});
const refreshLink = new TokenRefreshLink({
accessTokenField: 'accessToken',
isTokenValidOrUndefined: () => {
const token = getAccessToken();
if (!token) {
return true;
}
try {
const { exp } = jwtDecode(token);
if (Date.now() >= exp * 1000) {
return false;
}
return true;
} catch {
return false;
}
},
fetchAccessToken: () => {
return fetch(ENDPOINTS.REFRESH_TOKEN, {
method: 'POST',
credentials: 'include'
});
},
handleFetch: (accessToken) => {
setAccessToken(accessToken);
},
handleError: () => {
console.warn('Your refresh token is invalid. Try to relogin');
}
});
const authLink = setContext(async (_request, { headers: authHeaders }) => {
const token = isServer() ? await getToken() : await getAccessToken();
return {
headers: {
...authHeaders,
authorization: token ? `Bearer ${token}` : ''
}
};
});
const errorLink = onError(({ graphQLErrors, networkError }) => {
if (graphQLErrors)
graphQLErrors.forEach(({ message, locations, path, extensions }) => {
switch (extensions!.code) {
case 'UNAUTHENTICATED': {
// error code is set to UNAUTHENTICATED
// when AuthenticationError thrown in resolver
// modify the operation context with a new token
// TODO: Should work on server-side aswell
redirect(ctx, '/login');
break;
}
default:
console.error(
`[GraphQL error]: Code: ${
extensions!.code
} Message: ${message}, Location: ${locations}, Path: ${path}`
);
}
});
if (networkError) {
// if you would also like to retry automatically on
// network errors, we recommend that you use
// apollo-link-retry
if (!isServer()) redirect(ctx, '/maintance');
}
});
let link = httpLink;
if (!ssrMode) {
// Create a WebSocket link:
const wsLink = new WebSocketLink({
uri: `ws://${process.env.NEXT_PUBLIC_BACKEND_HOST}:${process.env.NEXT_PUBLIC_BACKEND_PORT}/graphql`,
options: {
reconnect: true
},
webSocketImpl: WebSocket
});
link = split(
({ query }) => {
const def = getMainDefinition(query);
return def.kind === 'OperationDefinition' && def.operation === 'subscription';
},
wsLink,
httpLink
);
}
const cache = new InMemoryCache().restore(initialState || {});
return new ApolloClient({
ssrMode: typeof window === 'undefined', // Disables forceFetch on the server (so queries are only run once)
link: ApolloLink.from([refreshLink, authLink, errorLink, link]),
cache
});
},
{
// eslint-disable-next-line react/display-name
render: ({ Page, props }) => {
return (
// eslint-disable-next-line react/destructuring-assignment
<ApolloProvider client={props.apollo}>
<Page {...props} />
</ApolloProvider>
);
}
}
);
server
package.json
{
"apollo-server-express": "^2.11.0",
}
send token function
import { Response } from 'express';
function sendRefreshToken(res: Response, token: string): void {
res.cookie('jid', token, {
httpOnly: true
});
}