nhost
nhost copied to clipboard
Next JWT token expired when using SSR
So after discussion with @dbarrosop in discord help channel I've decided to open an Issue here
Describe the bug I'm investigation integration next + nhost with SSR enabled (pages router). I've setup our app the same way as in examples - <NhostProvider> + <NhostApolloProvider> + getNhostSession from nhost/nextjs
In general it works really well! Thanks guys for all your work.
But sometimes (and it's even not clear when and why) I recieve errors about JWT token being expired, both on client and server. Previously we were using next but without getNhostSessions so all auth part was working only on client and it was working flawlessly
error: ApolloError: Could not verify JWT: JWTExpired To Reproduce Steps to reproduce the behavior:
- Go to start page.
- Wait till refresh token expired
Expected behavior Token updates automatically
Screenshots
Desktop (please complete the following information):
- OS: macOS 14.0 (23A344)
- Browser: Chrome: 118.0.5993.117
- Versions:
- "next": "13.3.0",
- "@nhost/apollo": "^5.2.19",
- "@nhost/nextjs": "^1.13.33",
- "@nhost/nhost-js": "^2.2.12",
- "@nhost/react": "^2.0.27",
- "@nhost/react-apollo": "^5.0.36",
Code
ApptProvider in _app.tsx
export const Provider: FC<ProviderProps> = ({
children,
nhostSession,
transitionConfig = {
type: 'spring',
bounce: 0.01,
},
}) => {
return (
<NhostProvider nhost={nhost} initial={nhostSession}>
<ApolloProvider>
<MotionConfig transition={transitionConfig}>{children}</MotionConfig>
</ApolloProvider>
</NhostProvider>
);
};
ApolloProvider used above:
import { FC, PropsWithChildren } from 'react';
import { NhostApolloProvider } from '@nhost/react-apollo';
import { nhost } from '@htch/shared-services/nhost';
import { NhostApolloClientOptions } from '@nhost/apollo';
export const ApolloProvider: FC<
PropsWithChildren<Omit<NhostApolloClientOptions, 'nhost'>>
> = ({ children, ...props }) => {
return (
<NhostApolloProvider nhost={nhost} {...props}>
{children}
</NhostApolloProvider>
);
};
getNhostSession:
import { getNhostSession as fetchNhostSession } from '@nhost/nextjs';
import { REGION, SUBDOMAIN } from '@htch/shared-services/nhost';
import { GetServerSidePropsContext } from 'next';
export const getNhostSession = (context: GetServerSidePropsContext) =>
fetchNhostSession(
{
subdomain: SUBDOMAIN,
region: REGION,
},
context
);
Screeshoots
this is console.log from getNhostSession
So session is here, but JWT is expired
Nhost refresh token expired at looks correct
So it expires in a future at the moment of screenshot
Also noticed that If I delete nhostSession from cookies and just refersh page - it started to work
Would be glad to get any help with it. Thanks!
thanks for the report, we will try to look into this as soon as possible
Hi. Thanks a lot.
Sorry for maybe a late response, but we pushed all new SSR-related changes to dev environment and looks like this issue is not reproducible in production mode. I do remember that I've tried production build on my local machine and saw error related to JWT token expiration, but at least on dev env we can't see it.
So I assume that this might be related to hot-reloading.
Any updates on this?
Update from my side:
This definitely happens in production mode
Our users are reporting issues in production too.
Is there anything I can do to help? Repo? Screenshots?
The issue is that we haven't been able to reproduce consistently so any information you can share on how to reproduce will help debug this. For instance, when does it happen? Is this an issue with users having the refresh token expire? Do you have subscriptions?
Yep, it's quite hard to reproduce. So I've noticed that this happens in dev env (next 13.3 + ssr + page routes) when I have two users simultaneously accessing application. Looks like it's same issue on our dev env with production build.
Yes, we do have subscriptions and we use them quite a lot. For me it looks like token expired and client on server doesn't know how to refresh it and after this things are messed up. The only thing that helps - is to do signOut and then sign in back. Just refresh page and trigger new SSR run does not help.
Maybe I can take a look at some specific logs when we have this error and provide it to you?
ok, finally!
We've managed to reproduce this bug in a fresh repo with all new versions of npm packages (not nhost-cli yet). I've made a loom-video with explanation of what is happening and looking forward to continue discussion.
https://www.loom.com/share/4620beb23f964c7d9cf7e5192d550aea
Thanks @AlexanderMoroz
https://github.com/HTCH-app/nhost-jwt-token-test
That's a repo. Unfortunately we don't include our nhost instance in this repo.
@dbarrosop @onehassan
Hello again! Could you please take a look at this bug once more? Also would be great to check video + repo to reproduce.
We add temporary fix which is a bit smelly, so would be great to have this thing properly fixed. What we do is to catch error in apollo link and if it's JWT is expired error we just call nhost.auth.refreshToken() method. This helps, but not always. Graphql-ws which apollo uses throws an error which we can't catch with apollo link, and websockets are failing as a result.
Here is an example of temporary fix:
import { nhost } from '@htch/shared-services/nhost';
import { onError } from '@apollo/client/link/error';
const JWT_ERROR_MESSAGE = 'Could not verify JWT: JWTExpired';
// Log any GraphQL errors or network error that occurred
export const createNhostJwtErrorMiddleware = () => {
let isJwtExpiredError = false;
return onError(({ graphQLErrors, networkError, ...rest }) => {
if (graphQLErrors)
graphQLErrors.forEach(({ message }) => {
if (message.includes(JWT_ERROR_MESSAGE)) isJwtExpiredError = true;
});
if (networkError) {
if (networkError.message.includes(JWT_ERROR_MESSAGE))
isJwtExpiredError = true;
}
if (isJwtExpiredError) {
nhost.auth
.refreshSession()
.then(() => {
isJwtExpiredError = false;
})
}
});
};
Thanks in advance!
Unfortunately we are a bit caught up with other stuff right now but it's on our shortlist of things to look at so as soon as those are out of the way this comes next (should be at some point during December 🤞). Apologies for the delay.
Thanks for response!
HNY folks!
Curious: did you get to look at this in Dec?
We see the often over and over again in production.
Not yet, unfortunately December turned out to be way too optimistic, specially given our AI week and the holidays. We will most likely start looking into this before the end of the month.
thanks for the update!
Don't suppose this has started yet?
We just started looking into this so we will hopefully have news soon.
As you probably noticed we have a fix already. We will be releasing a new version of the SDKs with it tomorrow. If you upgrade, we'd appreciate if you could confirm the issue is gone. Thanks for your patience.
Whoop whoop!
Thanks for the hard work of all your team.
We'll report back with confirmation.
M
On Thu, 22 Feb 2024, 18:25 David Barroso, @.***> wrote:
As you probably noticed we have a fix already. We will be releasing a new version of the SDKs with it tomorrow. If you upgrade, we'd appreciate if you could confirm the issue is gone. Thanks for your patience.
— Reply to this email directly, view it on GitHub https://github.com/nhost/nhost/issues/2348#issuecomment-1960018696, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAALNV5G5CJPVT5I3PWWC4TYU6EQBAVCNFSM6AAAAAA6XTCIA6VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMYTSNRQGAYTQNRZGY . You are receiving this because you commented.Message ID: @.***>
Initial tests are in.
We upgraded all nhost deps in our monorepo to:
"@nhost/apollo": "^5.2.22",
"@nhost/nextjs": "^1.13.40",
"@nhost/nhost-js": "^2.2.18",
"@nhost/react": "^2.1.1",
"@nhost/react-apollo": "^5.0.38",
Question: Do these versions have contain the fix?
Result: No change.
No, those are old packages. For instance, latest @nhost/apollo is 6.0.7.
Hi @mmmoli, can you please try again with the latest versions:
@nhost/nhost-js: 3.0.7
@nhost/apollo: 6.0.7
@nhost/nextjs: 2.1.4
@nhost/react: 3.2.2
@nhost/react-apollo: 9.0.2
@dbarrosop @onehassan does nhost support next@14 now?. Looks like we start having this issue after upgrading to [email protected], downgrading back to 13.5.6 fixed the problem. Could you please check?