nuxt-auth: Chunking session cookies throws errors on decode and logs user out
Environment
- Operating System:
Darwin
- Node Version:
v18.14.2
- Nuxt Version:
3.3.1
- Nitro Version:
2.3.1
- Package Manager:
npm@9.5.0
- Builder:
vite
- User Config:
extends
,srcDir
,runtimeConfig
,app
,imports
,typescript
,css
,modules
,tailwindcss
- Runtime Modules:
@nuxtjs/tailwindcss@6.6.0
- Build Modules:
-
Reproduction
Try to return this user including tokens from the authenticate method in the credentialsprovider:
const largeToken = {
name: "Pablo Diego José Francisco de Paula Juan Nepomuceno María de los Remedios Cipriano de la Santísima Trinidad Ruiz y Picasso",
email: "pablodiegojose@picasso.net",
id: "2a7d1072-f292-4343-824d-65058202b618esfsefesfesfse2fsef",
picture: "http://placekitten.com/400/200",
initials: "PDJFDPJNM",
tokens: {
accessToken:
"https://jwt.io/#debugger-io?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyLCJ0ZXN0MSI6IkhlbGxvIHdvcmxkIiwiZG91Z2xhcyI6eyJxdW90ZSI6IkZvciBpbnN0YW5jZSwgb24gdGhlIHBsYW5ldCBFYXJ0aCwgbWFuIGhhZCBhbHdheXMgYXNzdW1lZCB0aGF0IGhlIHdhcyBtb3JlIGludGVsbGlnZW50IHRoYW4gZG9scGhpbnMgYmVjYXVzZSBoZSBoYWQgYWNoaWV2ZWQgc28gbXVjaOKAlHRoZSB3aGVlbCwgTmV3IFlvcmssIHdhcnMgYW5kIHNvIG9u4oCUd2hpbHN0IGFsbCB0aGUgZG9scGhpbnMgaGFkIGV2ZXIgZG9uZSB3YXMgbXVjayBhYm91dCBpbiB0aGUgd2F0ZXIgaGF2aW5nIGEgZ29vZCB0aW1lLiBCdXQgY29udmVyc2VseSwgdGhlIGRvbHBoaW5zIGhhZCBhbHdheXMgYmVsaWV2ZWQgdGhhdCB0aGV5IHdlcmUgZmFyIG1vcmUgaW50ZWxsaWdlbnQgdGhhbiBtYW7igJRmb3IgcHJlY2lzZWx5IHRoZSBzYW1lIHJlYXNvbnMuIiwicXVvdGUyIjoi4oCcVGhlcmUgaXMgYSB0aGVvcnkgd2hpY2ggc3RhdGVzIHRoYXQgaWYgZXZlciBhbnlvbmUgZGlzY292ZXJzIGV4YWN0bHkgd2hhdCB0aGUgVW5pdmVyc2UgaXMgZm9yIGFuZCB3aHkgaXQgaXMgaGVyZSwgaXQgd2lsbCBpbnN0YW50bHkgZGlzYXBwZWFyIGFuZCBiZSByZXBsYWNlZCBieSBzb21ldGhpbmcgZXZlbiBtb3JlIGJpemFycmUgYW5kIGluZXhwbGljYWJsZS4iLCJxdW90ZTMiOiJUaGVyZSBpcyBhbm90aGVyIHRoZW9yeSB3aGljaCBzdGF0ZXMgdGhhdCB0aGlzIGhhcyBhbHJlYWR5IGhhcHBlbmVkLiJ9LCJ0ZXN0dXNlciI6eyJpZCI6MSwiZmlyc3RfbmFtZSI6IkFhcm9uIiwibGFzdF9uYW1lIjoiTnV0bGV5IiwiZW1haWwiOiJhbnV0bGV5MEBldXJvcGEuZXUiLCJnZW5kZXIiOiJNYWxlIiwiaXBfYWRkcmVzcyI6IjMzLjE2OS4zMy4yMTgifSwidGVzdHVzZXIyIjp7ImlkIjoyLCJmaXJzdF9uYW1lIjoiTWFyaW4iLCJsYXN0X25hbWUiOiJNYXR5c2lrIiwiZW1haWwiOiJtbWF0eXNpazFAdXNhdG9kYXkuY29tIiwiZ2VuZGVyIjoiRmVtYWxlIiwiaXBfYWRkcmVzcyI6IjE2LjEzMy42OS4xMzkifX0.mJUaFtoUfZ5qIgTRbcB4cLGDi15HFojQKZg5I1h6yRg",
accessExpiraton: 1679309043,
refreshToken:
"https://jwt.io/#debugger-io?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyLCJ0ZXN0MSI6IkhlbGxvIHdvcmxkIiwiZG91Z2xhcyI6eyJxdW90ZSI6IkZvciBpbnN0YW5jZSwgb24gdGhlIHBsYW5ldCBFYXJ0aCwgbWFuIGhhZCBhbHdheXMgYXNzdW1lZCB0aGF0IGhlIHdhcyBtb3JlIGludGVsbGlnZW50IHRoYW4gZG9scGhpbnMgYmVjYXVzZSBoZSBoYWQgYWNoaWV2ZWQgc28gbXVjaOKAlHRoZSB3aGVlbCwgTmV3IFlvcmssIHdhcnMgYW5kIHNvIG9u4oCUd2hpbHN0IGFsbCB0aGUgZG9scGhpbnMgaGFkIGV2ZXIgZG9uZSB3YXMgbXVjayBhYm91dCBpbiB0aGUgd2F0ZXIgaGF2aW5nIGEgZ29vZCB0aW1lLiBCdXQgY29udmVyc2VseSwgdGhlIGRvbHBoaW5zIGhhZCBhbHdheXMgYmVsaWV2ZWQgdGhhdCB0aGV5IHdlcmUgZmFyIG1vcmUgaW50ZWxsaWdlbnQgdGhhbiBtYW7igJRmb3IgcHJlY2lzZWx5IHRoZSBzYW1lIHJlYXNvbnMuIiwicXVvdGUyIjoi4oCcVGhlcmUgaXMgYSB0aGVvcnkgd2hpY2ggc3RhdGVzIHRoYXQgaWYgZXZlciBhbnlvbmUgZGlzY292ZXJzIGV4YWN0bHkgd2hhdCB0aGUgVW5pdmVyc2UgaXMgZm9yIGFuZCB3aHkgaXQgaXMgaGVyZSwgaXQgd2lsbCBpbnN0YW50bHkgZGlzYXBwZWFyIGFuZCBiZSByZXBsYWNlZCBieSBzb21ldGhpbmcgZXZlbiBtb3JlIGJpemFycmUgYW5kIGluZXhwbGljYWJsZS4iLCJxdW90ZTMiOiJUaGVyZSBpcyBhbm90aGVyIHRoZW9yeSB3aGljaCBzdGF0ZXMgdGhhdCB0aGlzIGhhcyBhbHJlYWR5IGhhcHBlbmVkLiJ9LCJ0ZXN0dXNlciI6eyJpZCI6MSwiZmlyc3RfbmFtZSI6IkFhcm9uIiwibGFzdF9uYW1lIjoiTnV0bGV5IiwiZW1haWwiOiJhbnV0bGV5MEBldXJvcGEuZXUiLCJnZW5kZXIiOiJNYWxlIiwiaXBfYWRkcmVzcyI6IjMzLjE2OS4zMy4yMTgifSwidGVzdHVzZXIyIjp7ImlkIjoyLCJmaXJzdF9uYW1lIjoiTWFyaW4iLCJsYXN0X25hbWUiOiJNYXR5c2lrIiwiZW1haWwiOiJtbWF0eXNpazFAdXNhdG9kYXkuY29tIiwiZ2VuZGVyIjoiRmVtYWxlIiwiaXBfYWRkcmVzcyI6IjE2LjEzMy42OS4xMzkifX0.mJUaFtoUfZ5qIgTRbcB4cLGDi15HFojQKZg5I1h6yRg",
refreshExpiraton: 1679910247,
},
};
You can find an edited version of the auth handler in my example repo, though @sidebase/nuxt-auth does not seem to run on codesandbox.
Describe the bug
When generating a JWT that is bigger than 4096 bytes, the next-auth core module will chunk your cookies. That way, you’ll end up with 2 session tokens.
next-auth.session-token.0
next-auth.session-token.1
Initial login seems to work fine, and I can see I’m logged in.
However, when I reload the page I get an error in my console and my session cookies get removed automatically. Sometimes I need to reload a couple of times to trigger this. Sometimes it’s immediate.
Additional context
- This error does not happen with session cookies under the 4096 bytes limit.
- I can reproduce by generating a large token.
Logs
When logging in or reloading the page:
[next-auth][debug][CHUNKING_SESSION_COOKIE] { 11:28:41
message: 'Session cookie exceeds allowed 4096 bytes.',
emptyCookieSize: 163,
valueSize: 4729,
chunks: [ 4096, 959 ]
}
When hammering a page reload and it logs me out:
[next-auth][error][JWT_SESSION_ERROR] 11:28:41
https://next-auth.js.org/errors#jwt_session_error JWE Initialization Vector missing or incorrect type {
message: 'JWE Initialization Vector missing or incorrect type',
stack: 'JWEInvalid: JWE Initialization Vector missing or incorrect type\n' +
' at flattenedDecrypt (/Users/jan.hoogeveen/Projects/demo-app/node_modules/jose/dist/node/cjs/jwe/flattened/decrypt.js:24:15)\n' +
' at compactDecrypt (/Users/jan.hoogeveen/Projects/demo-app/node_modules/jose/dist/node/cjs/jwe/compact/decrypt.js:18:63)\n' +
' at jwtDecrypt (/Users/jan.hoogeveen/Projects/demo-app/node_modules/jose/dist/node/cjs/jwt/decrypt.js:8:61)\n' +
' at Object.decode (/Users/jan.hoogeveen/Projects/demo-app/node_modules/next-auth/jwt/index.js:64:34)\n' +
' at async Object.session (/Users/jan.hoogeveen/Projects/demo-app/node_modules/next-auth/core/routes/session.js:41:28)\n' +
' at async AuthHandler (/Users/jan.hoogeveen/Projects/demo-app/node_modules/next-auth/core/index.js:158:27)\n' +
' at async file:///Users/jan.hoogeveen/Projects/demo-app/.nuxt/dev/index.mjs:540:24\n' +
' at async Object.handler (file:///Users/jan.hoogeveen/Projects/demo-app/node_modules/h3/dist/index.mjs:1212:19)\n' +
' at async toNodeHandle (file:///Users/jan.hoogeveen/Projects/demo-app/node_modules/h3/dist/index.mjs:1287:7)\n' +
' at async ufetch (file:///Users/jan.hoogeveen/Projects/demo-app/node_modules/unenv/runtime/fetch/index.mjs:9:17)',
name: 'JWEInvalid'
}
[next-auth][error][JWT_SESSION_ERROR] 11:28:41
https://next-auth.js.org/errors#jwt_session_error Invalid Compact JWE {
message: 'Invalid Compact JWE',
stack: 'JWEInvalid: Invalid Compact JWE\n' +
' at compactDecrypt (/Users/jan.hoogeveen/Projects/demo-app/node_modules/jose/dist/node/cjs/jwe/compact/decrypt.js:16:15)\n' +
' at jwtDecrypt (/Users/jan.hoogeveen/Projects/demo-app/node_modules/jose/dist/node/cjs/jwt/decrypt.js:8:61)\n' +
' at Object.decode (/Users/jan.hoogeveen/Projects/demo-app/node_modules/next-auth/jwt/index.js:64:34)\n' +
' at async Object.session (/Users/jan.hoogeveen/Projects/demo-app/node_modules/next-auth/core/routes/session.js:41:28)\n' +
' at async AuthHandler (/Users/jan.hoogeveen/Projects/demo-app/node_modules/next-auth/core/index.js:158:27)\n' +
' at async file:///Users/jan.hoogeveen/Projects/demo-app/.nuxt/dev/index.mjs:540:24\n' +
' at async Object.handler (file:///Users/jan.hoogeveen/Projects/demo-app/node_modules/h3/dist/index.mjs:1212:19)\n' +
' at async toNodeHandle (file:///Users/jan.hoogeveen/Projects/demo-app/node_modules/h3/dist/index.mjs:1287:7)\n' +
' at async ufetch (file:///Users/jan.hoogeveen/Projects/demo-app/node_modules/unenv/runtime/fetch/index.mjs:9:17)\n' +
' at async $fetchRaw2 (file:///Users/jan.hoogeveen/Projects/demo-app/node_modules/ofetch/dist/shared/ofetch.502a4799.mjs:180:24)',
name: 'JWEInvalid'
}
About this issue
- Original URL
- State: closed
- Created a year ago
- Reactions: 6
- Comments: 40 (6 by maintainers)
PR to resolve this has been submitted - Please give it a thumbs up to get it moved along. @BracketJohn I guess it’ll need to be pulled in once it’s merged.
What if making the return value of the jwt callback not possible? I need to keep the access_token around (to make API requests to our own backend), the refresh_token (to enable token rotation) and certain user information.
All of this is of cause not needed in the session itself and the information are filtered properly (in the session callback), but as the return value of the jwt callback is encrypted and the token is used to populate the session, i cannot reduce these information.
Looks like it was fixed on https://github.com/nextauthjs/next-auth/releases/tag/next-auth%404.23.0 but upgrading to this version seems to break nuxt-auth
I have the exact same use case as I’m trying to implement a token refresh logic for my Cognito user pools. I need to be able to store the access and refresh tokens in the
token
property—not necessarily to pass them to the front end but simply to persist them throughout the session and refresh the token when needed.Any ideas?
OK, so I was convinced that
next-auth
had this fix in, having seen the PR and commit being merged.My tests this morning must have just gotten the cookie chunks in order every time correctly which led me to believe that the issue was fixed.
The module is now not working as expected on my end again.
I’ve checked-out
next-auth@4.22.3
and for some reason the fix seems to have been rolled back, so therefor the above PR doesn’t fix the issue.Any update/workaround for the issue?
I’m using
I’d like to know too, this issue needs to be fixed.
@christine927t not sure sorry, I’m not a part of the next-auth team, just a contributor out in the wild.
Thanks for taking time to look into this - I really appreaciate it!
As it’s realted to really low-level cookie ordering, this is likely either (1) or (2), as
nuxt-auth
does not touch cookies,it relies onnext-auth
and nuxt setting / unsetting them. So I’d propose to go into next-auth with a minimal reproduction -> best would probably be a native next-auth/auth.js reproduction as I don’t want @balazsorban44 to come under pressure to look into the code ofnuxt-auth
-> it’s our job not his.Having a
next-auth
reproduction would also improve the reliability of this analysis: It would show that it is definitely not related to nuxt ornuxt-auth
!https://github.com/nextauthjs/next-auth/pull/5398 is probably already a good lead, great find!
Btw: You could re-try with the latest supported next-auth version just for fun to see if maybe they’ve (accidentally) solved the problem.
@BracketJohn I understand. I’ll see how far I can get on my own, or with the help of @kilakewe.
The first login works well. That we know. At a page reload, there’s a chance the cookies work well or they get rejected as invalid
Based on this, I had a theory that the order of the cookies, or the chunks, was not guaranteed.
I’ve been logging the chunks that are used in next-auth/core/lib/cookies.js
Logs from first login (valid, working tokens)
Which leads us to the result from values.join()
So far, so good!
Refreshing the page
Next, I kept refreshing the page until I triggered an error. Compare with the previous logs.
And that returns the following token after doing the values.join() method.
Which will finally give us the
[next-auth][error][JWT_SESSION_ERROR]
Next
Now, there’s multiple possibilities here to explore.
Let me know what you think. I can always start a discussion or issue in next-auth as well.
Hey @janhoogeveen 👋
Thanks for the report - noted, it’ll take us some time to look into this, other issues have higher priorities right now. If you want to provide a fix though, or I can help you to walk through it that would be very welcome (: