On next-auth when just using the callbacks object https://next-auth.js.org/configuration/callbacks everything works fine, I can log in with google. and a jwt gets correctly generated.
callbacks: {
async jwt({ token }) {
console.log("token callback jwt: ", token)
token.userRole = "admin"
return token
},
async session(session) {
console.log("session callback: ", session)
const encodedToken = await jwt.sign(session.session.user, jwtSecret.key, {
algorithm: jwtSecret.type,
})
session.token = encodedToken
return session
},
},
But my end goal is to use next-auth jwt with hasura and for that I need to encode some more information to my jwt
I encode that information inside the jwt object https://next-auth.js.org/configuration/options#jwt
this is my jwt object with encode and decode logic
jwt: {
encode: async ({ token }) => {
const tokenContents = {
id: token.id,
name: token.name,
email: token.email,
picture: token.picture,
"https://hasura.io/jwt/claims": {
"x-hasura-allowed-roles": ["admin", "user"],
"x-hasura-default-role": "user",
"x-hasura-role": "user",
"x-hasura-user-id": token.id,
},
iat: Date.now() / 1000,
exp: Math.floor(Date.now() / 1000) + 24 * 60 * 60,
sub: token.id,
}
const encodedToken = jwt.sign(tokenContents, jwtSecret.key, {
algorithm: jwtSecret.type,
})
return encodedToken
},
decode: async ({ token }) => {
const decodedToken = jwt.verify(token, jwtSecret.key, {
algorithms: jwtSecret.type,
})
console.log("decodedToken: ", decodedToken)
return decodedToken
},
},
when I try to log in with my new encode decode logic, I receive next error that comes from node_modules > openid-client > lib > client.js
https://next-auth.js.org/errors#oauth_callback_error checks.state argument is missing {
error: {
message: 'checks.state argument is missing',
stack: 'TypeError: checks.state argument is missing\n' +
' at Client.callback (/var/task/node_modules/openid-client/lib/client.js:385:13)\n' +
' at oAuthCallback (/var/task/node_modules/next-auth/core/lib/oauth/callback.js:112:29)\n' +
' at processTicksAndRejections (internal/process/task_queues.js:95:5)\n' +
' at async Object.callback (/var/task/node_modules/next-auth/core/routes/callback.js:50:11)\n' +
' at async NextAuthHandler (/var/task/node_modules/next-auth/core/index.js:139:28)\n' +
' at async NextAuthNextHandler (/var/task/node_modules/next-auth/next/index.js:21:19)\n' +
' at async /var/task/node_modules/next-auth/next/index.js:57:32\n' +
' at async Object.apiResolver (/var/task/node_modules/next/dist/server/api-utils/node.js:182:9)\n' +
' at async NextNodeServer.runApi (/var/task/node_modules/next/dist/server/next-server.js:386:9)\n' +
' at async Object.fn (/var/task/node_modules/next/dist/server/base-server.js:488:37)',
name: 'TypeError'
},
providerId: 'google',
message: 'checks.state argument is missing'
}
Just for curiosity I went to the client.js file where the code is breaking and this is the code inside, it has a if !checks.state throw new TypeError
if (params.state && !checks.state) {
throw new TypeError('checks.state argument is missing');
}
It looks almost obvious that I need to add that checks.state to my encode logic but I don't know how, also I don't know that that checks.state object represents
Alright while I was writing this I found a piece of code that fixed the issue. in the issues page from next-auth https://github.com/nextauthjs/next-auth/issues/3251
someone says that if you add
to your GoogleProvider config it works, and it worked! why? I still don't know but still sharing because this can save days of research to someone else.
update, from the issues link I shared, I also tried
and not only works but console logs the decoded token.