-
-
Notifications
You must be signed in to change notification settings - Fork 232
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: auth-helpers-nextjs total fix with createMiddlewareClientV2 #769
base: main
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
pnpm build:nextjs
fails - also, if createMiddlewareClient
is broken, why not just modify the implementation to call createMiddlewareClient2
under the hood instead?
As described in the PR -- to forward the headers |
@hf you need to export the new client in the |
@hf the return types don't show up correctly when the client is instantiated, which isn't great DX-wise const [supabaseClient, nextResponse] = createMiddlewareClient2(req); it seems to think that |
createMiddlewareClient
was basically completely broken for correctly syncing the session state between the server and browser parts of a NextJS application.It works in most situations where the user is actively interacting with the site, but as soon as they leave the site for an extended period of time and come back, it's very likely that after the JWT expiry time they will receive an Invalid Refresh Token error from the server. Because these events are not time-correlated, it's impossible to debug what is causing them.
Why does this happen:
NextResponse.next()
is not enough. Pages, server-rendered components and route handlers do not see theSet-Cookie
header set on the response.middleware.ts
file, the session is correctly refreshed in the middleware client and theSet-Cookie
headers are set on the response so the browser syncs up with the state of the middleware client.cookie
header from the request which is the old session and any use ofgetSession()
orgetUser()
will refresh the session every time. If you have, say, 3 Data API calls to PostgREST, it's very likely that the session would be refreshed 3 times.middleware.ts
) and be greeted with the "Invalid Refresh Token" error.How is this being fixed:
The design of
createMiddlewareClient
does not care at all about what happens to the request, but this is incredibly important so the new refreshed session is passed down to the page or server-rendered component. Furthermore, this cannot "just be set" as for the propagation to take place,NextResponse.next({ request })
needs to be called.Therefore,
createMiddlewareClient
is fully deprecated and replaced with its new counterpartcreateMiddlewareClient2
. This works a bit differently (without reinventing the simplistic beauty of the@supabase/ssr
package):Firstly it returns two arguments, the Supabase client and a
nextResponse
function. It should be called towards the bottom of themiddleware.ts
file, ideally in thereturn
statement.The client is setup such that, it initially reads from the request's
Cookie
header, but writes the changes to local memory. It tracks what items (not cookies!) are being set or deleted.When you call
nextResponse()
the requests'sCookie
header is reset to reflect the new state of the Supabase client. Because this header will just be propagated down to the page or server-rendered component, no cookie chunking is necessary.Then, it calls:
Which ensures that the request's changes will be actually propagated down to the page or component. This enables the clients there to pick up the
Cookie
header which now includes the refreshed session.Finally, it sets the
Set-Cookie
header on the response, which eventually reaches the browser and the session state is finally synchronized between them.