-
-
Notifications
You must be signed in to change notification settings - Fork 8
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
AuthApiError: Invalid Refresh Token: Refresh Token Not Found when refreshing token in middleware #68
Comments
I'll point out that I didn't copy the guide code 100% because it doesn't seem necessary to loop through the Please correct me if I'm wrong! |
Also, you don't need to set the updated cookies on the request and the response in the middleware. Setting them on the response makes them available to the downstream server components reading from |
I'm also running into this via the Swift SDK :( |
Also getting this |
@lourd it's not doing the same thing twice:
have you tried following the guide 100% to see if it works for you? |
Hi @kangmingtay, yes, I have tried following the guide 100% and still get the error. I made the changes after it was having errors, to make sure I understood what was going on.
Correct, it's not doing the same thing twice, but it is looping twice. You can accomplish updating the request and response cookies in one loop. You can also update the existing response instead of creating a new response object on each call to My code, copied from my setAll(cookiesToSet) {
cookiesToSet.forEach((cookie) => {
req.cookies.set(cookie.name, cookie.value)
res.cookies.set(cookie.name, cookie.value, cookie.options)
})
} The example code: setAll(cookiesToSet) {
cookiesToSet.forEach(({ name, value, options }) => request.cookies.set(name, value))
supabaseResponse = NextResponse.next({ request })
cookiesToSet.forEach(({ name, value, options }) => supabaseResponse.cookies.set(name, value, options))
} |
@lourd i think the problem here is because of how you are passing down the response in your middleware.ts (with comments)export async function updateSession(request: NextRequest) {
// this response object is being passed into nextMiddlewareCookies which may
// contain stale "Set-Cookie" headers
const response = NextResponse.next({ request })
const supabase = createServerClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
{
cookies: nextMiddlewareCookies(request, response),
}
)
// you want to use getUser() here rather than getSession() since this is on the server-side
await supabase.auth.getSession()
return response
}
function nextMiddlewareCookies(
req: NextRequest,
res: NextResponse
): CookieMethodsServer {
return {
getAll() {
return req.cookies.getAll()
},
setAll(cookiesToSet) {
cookiesToSet.forEach((cookie) => {
req.cookies.set(cookie.name, cookie.value)
// this uses the initial NextResponse.next() defined in updateSession
// in the e.g, we are deliberately creating a new NextResponse.next() object to remove any stale "Set-Cookie" headers
res.cookies.set(cookie.name, cookie.value, cookie.options)
})
},
}
}
One way to debug this issue is to print out the cookie headers before returning the response (you can also check the network tab to see what the "Set-Cookie" response header contains and what cookies are set on the subsequent request. If you're still having troubles with getting this to work, can you please open a ticket with us at |
Hey @kangmingtay, really appreciate you investigating this! Thankfully Next.js handles the cases of possible "staleness" or duplicate calls to set a cookie that you've illustrated. Here's a test case illustrating that behavior. I've just run it again using Next.js 14.2.14. Create a new Next.js app, create a middleware.ts module. In the middleware, do this: import { type NextRequest, NextResponse } from "next/server";
export async function middleware(request: NextRequest) {
const cookies = request.cookies;
console.log("incoming cookies", cookies.getAll());
const res = NextResponse.next({ request });
let i = 0;
request.cookies.set("foo", `${i}`);
res.cookies.set("foo", `${i}`);
request.cookies.set("foo", `${i + 1}`);
res.cookies.set("foo", `${i + 1}`);
request.cookies.set("foo", `${i + 2}`);
res.cookies.set("foo", `${i + 2}`);
console.log("end of middleware");
console.log("request headers", [...request.headers.entries()]);
console.log("response headers", [...res.headers.entries()]);
return res;
}
export const config = {
matcher: [
/*
* Match all request paths except for the ones starting with:
* - _next/static (static files)
* - _next/image (image optimization files)
* - favicon.ico (favicon file)
* - @vercel/speed-insights script
*/
"/((?!_next/static|_next/image|favicon.ico|_vercel/speed-insights|.*\\.(?:svg|png|jpg|jpeg|gif|webp|php)$).*)",
],
}; In export default function Home() {
const cooks = cookies();
const header = headers();
console.log("Home page server component");
console.log("incoming headers", [...header.entries()]);
console.log("incoming cookies", cooks.getAll());
...
} Load up localhost:3000 in an incognito window. Here is what you see in the middleware logs
In the server component logs:
[ 'set-cookie', 'foo=2; Path=/' ],
[ 'x-middleware-set-cookie', 'foo=2; Path=/' ],
[ 'cookie', 'foo=2' ]
And in the browser's network response for the document, there is a single All that to say, when setting the same cookie on either the request or response, it is properly deduped. There's no need to keep making a new response. I ran this test on both my local server and deployed on Vercel - the results are the same.
Do I have to use Additionally, I've used
The error occurs as part of the call to |
Even I have run into same issue. When I run npm audit, I get @supabase/ssr depends on vulnerable versions of cookie. |
I've been keeping a log of how often it happens to me. It doesn't happen at a consistent interval. The longest I've gone without the problem is 3 days. The shortest I've gone without the problem is still ~24 hours. |
Bug report
Describe the bug
I'm inadvertently logged out of my web application every day, with this error in the back-end logs:
AuthApiError: Invalid Refresh Token: Refresh Token Not Found
.I recently set up Supabase auth on my new Next.js application. I followed the Setting up Server-Side Auth for Next.js guide, with some small tweaks. My code looks like this:
middleware.ts
app/supabase/middleware.ts
To Reproduce
Steps to reproduce the behavior, please provide code snippets or a repository:
AuthApiError: Invalid Refresh Token: Refresh Token Not Found
error in your middleware logsExpected behavior
The token should refresh if there is one and it's expired, without an error. If there's not a session, it should not try to refresh it, and there should be no error.
Screenshots
From my Vercel logs:
System information
Additional context
This appears to be the same or a similar bug as supabase/auth-helpers#436, as well as supabase/auth-js#620
I've tried forcing the issue to happen more quickly by shortening the JWT expiry to 60 seconds, but it refreshes just fine. There's something with the 24 hour window that seems to be causing the error.
The text was updated successfully, but these errors were encountered: