auth-astro
auth-astro copied to clipboard
Use of JWT callback to persist additional token info results in session being null.
I am using the JWT callback to add additional information to the token like access_token, refresh_token and expires_at as outlined in the Auth.js docs here for the JWT callback and here for refresh token rotation.
While I have this working fine using Next.js 13 and Qwik, I have been struggling with Astro. As soon as I include logic in the JWT callback to enhance the token the session ends up being empty. When I remove the enhancement in the JWT callback the default session data is returned.
No errors are reported in the console. I am using the Azure AD provider.
export default {
secret: import.meta.env.AUTH_SECRET,
trustHost: true,
providers: [
AzureAd({
clientId: import.meta.env.AZURE_CLIENT_ID,
clientSecret: import.meta.env.AZURE_CLIENT_SECRET,
tenantId: import.meta.env.AZURE_TENANT_ID,
authorization: {
params: {
scope: "...removed...",
},
},
}),
] as Provider[],
callbacks: {
async session({ session, token }) {
if (token) {
session.access_token = token.access_token;
}
return session;
},
async jwt({ token, user, account, profile, isNewUser }) {
if (account) {
token.access_token = account.access_token;
}
return token;
},
},
};
If I then check session via .../api/auth/session it returns an empty object.
If I comment out token.access_token = account.access_token;
in the JWT callback the default session data is returned.
Same issue occurs using both JS and TS projects.
Please help 😀
I have somehow a similar issue @msardi23 . However, for me, it works when only adding the account.access_token in my token, however, adding both the access_token and the refresh_token gives me the same error as you, where the getSession() returns null.
Not adding the refresh_token makes the getSession() return an existing session.
This is my code that works, and I have commented out the line adding the refresh_token to the token object for reference.
import AzureADB2C from '@auth/core/providers/azure-ad-b2c'
import { defineConfig } from 'auth-astro'
export default defineConfig({
providers: [
AzureADB2C({
issuer: `https://${import.meta.env.AZUREADB2C_TENANT}.b2clogin.com/${
import.meta.env.AZUREADB2C_TENANT_ID
}/v2.0/`,
wellKnown: `https://${import.meta.env.AZUREADB2C_TENANT}.b2clogin.com/${
import.meta.env.AZUREADB2C_TENANT
}.onmicrosoft.com/${import.meta.env.AZUREADB2C_POLICY}/v2.0/.well-known/openid-configuration`,
authorization: {
url: `https://${import.meta.env.AZUREADB2C_TENANT}.b2clogin.com/${
import.meta.env.AZUREADB2C_TENANT
}.onmicrosoft.com/${import.meta.env.AZUREADB2C_POLICY}/oauth2/v2.0/authorize`,
params: {
scope: `YOUR SCOPES`
}
},
token: `https://${import.meta.env.AZUREADB2C_TENANT}.b2clogin.com/${
import.meta.env.AZUREADB2C_TENANT
}.onmicrosoft.com/${import.meta.env.AZUREADB2C_POLICY}/oauth2/v2.0/token`,
clientId: import.meta.env.AZUREADB2C_CLIENT_ID,
clientSecret: import.meta.env.AZUREADB2C_CLIENT_SECRET,
allowDangerousEmailAccountLinking: true
})
],
callbacks: {
async signIn({ user, account, profile, email, credentials }) {
if (profile) {
if (user) {
user.email = profile.email
}
}
return true
},
async jwt({ token, user, account, profile }) {
if (account && user) {
const newToken = {
accessToken: account.access_token,
accessTokenExpires: Date.now() + account.expires_in! * 1000,
// refreshToken: account.refresh_token,
user
}
// console.log(newToken)
return newToken
}
// Return the current token if it's not expired or if there was no account object
return token
}
}
})
For me, it seems that also adding a request token, maxes out the token size limit, or something. Because if I only add, for example: refreshToken: "refresh token", it works, and session is set.
From what I can see, from the Astro.request and the request cookies, the authcookie is not set when adding the full refreshToken, but is set when only adding accessToken.
The cookies remaining are: "authjs.csrf-token" and "authjs.callback-url" which for me, seems that something has happened when prosessing the extra data. The authjs cookie: "authjs.session-token" is missing.
When removing refreshToken so the session is not null anymore, the request header looks correct with the "authjs.session-token" cookie now in place.
I haven't calculated the size, but we might be hitting the browser cookie size limit (4kb). I know they have done something for this limitation for NextAuthJs:
https://github.com/nextauthjs/next-auth/discussions/3579#discussioncomment-1929584
Edit: Seemed to only work in dev. Built in prod or preview; session cookie is not set at all when doing changes in the callback as @msardi23 mentioned.
I just tested this on the latest astro, @auth/core and auth-astro version without any issues. Do you still have this problem?
I'm using my own version setting the refresh cookie in a separate cookie. However, I'll see if I can take a look at it and test!