Skip to content
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

Refresh JWTs for account switching #1596

Open
ekzyis opened this issue Nov 15, 2024 · 1 comment
Open

Refresh JWTs for account switching #1596

ekzyis opened this issue Nov 15, 2024 · 1 comment
Labels
difficulty:easy feature new product features that weren't there before

Comments

@ekzyis
Copy link
Member

ekzyis commented Nov 15, 2024

Describe the problem you're trying to solve

The JWT stored in the multi_auth cookies are never refreshed. This means they expire in 30 days.

This could be the reason for #1573 and why account switching stops working after some time. It would at least make sense.

Currently, account switching probably just completely stops working and you need to clear cookies to recover. This is pretty bad and something I didn't really make sure fails gracefully in #489.

Describe the solution you'd like

Refresh all JWTs stored multi_auth cookies on every request—or at least the one that is currently used since we always use the multi_auth cookie if the pointer cookie is set.

Describe alternatives you've considered

Fail gracefully if JWTs are expired

Additional context

No response

@ekzyis ekzyis added feature new product features that weren't there before difficulty:easy labels Nov 15, 2024
@ekzyis
Copy link
Member Author

ekzyis commented Nov 15, 2024

Maybe we can refresh all JWTs at the same time we're checking them which user we should use.

We do this here:

function multiAuthMiddleware (request) {
// switch next-auth session cookie with multi_auth cookie if cookie pointer present
// is there a cookie pointer?
const cookiePointerName = 'multi_auth.user-id'
const hasCookiePointer = !!request.cookies[cookiePointerName]
const secure = process.env.NODE_ENV === 'production'
// is there a session?
const sessionCookieName = secure ? '__Secure-next-auth.session-token' : 'next-auth.session-token'
const hasSession = !!request.cookies[sessionCookieName]
if (!hasCookiePointer || !hasSession) {
// no session or no cookie pointer. do nothing.
return request
}
const userId = request.cookies[cookiePointerName]
if (userId === 'anonymous') {
// user switched to anon. only delete session cookie.
delete request.cookies[sessionCookieName]
return request
}
const userJWT = request.cookies[`multi_auth.${userId}`]
if (!userJWT) {
// no JWT for account switching found
return request
}
if (userJWT) {
// use JWT found in cookie pointed to by cookie pointer
request.cookies[sessionCookieName] = userJWT
return request
}
return request
}

and we use encode from next-auth/jwt to create new JWTs. See here:

if (req && res) {
req = new NodeNextRequest(req)
res = new NodeNextResponse(res)
const secret = process.env.NEXTAUTH_SECRET
const jwt = await encodeJWT({ token, secret })
const me = await prisma.user.findUnique({ where: { id: token.id } })
// we set multi_auth cookies on login/signup with only one user so the rest of the code doesn't
// have to consider the case where they aren't set yet because account switching wasn't used yet
setMultiAuthCookies(req, res, { ...me, jwt })
}

encode was imported as encodeJWT here

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
difficulty:easy feature new product features that weren't there before
Projects
None yet
Development

No branches or pull requests

1 participant