Session Not Updating & Expired session continues to be active
Issue 1 : Session Cookie, nor session expiration is being updated
issue 2: Even After session is expired. Im getting valid session response (sending cookie manually)
better-auth version 1.2.7
better-auth Config
Expected behavior
--
So technically session should be valid for 1 Min and on every
session: {
expiresIn: 60,
updateAge: 0,
freshAge: 0,
},
session: {
expiresIn: 60,
updateAge: 0,
freshAge: 0,
},
/get-session
within that 1 min , the session expiry should be updated and a cookie be returned
Whats happening
---
The same response as the first /get-session
continues for 1 min and after also. No set-cookie
is headers nor session expiry is updated in response
Full Config
export const auth = betterAuth({
baseURL: env.BETTER_AUTH_URL,
emailVerification: {
sendOnSignUp: true,
autoSignInAfterVerification: true,
sendVerificationEmail: async ({ user, url }) => {
await sendEmailVerification(user.email, url);
},
},
emailAndPassword: {
enabled: true,
minPasswordLength: 8,
maxPasswordLength: 40,
autoSignIn: true,
sendResetPassword: async ({ user, url }) => {
await sendResetPassword(user.email, url);
},
password: {
hash: async (password) => await Bun.password.hash(password),
verify: async ({ hash, password }) =>
await Bun.password.verify(password, hash),
},
},
trustedOrigins: ["http://localhost:3000"],
plugins: [
captcha({
provider: "cloudflare-turnstile",
secretKey: env.TURNSTILE_SECRET_KEY,
}),
emailOTP({
async sendVerificationOTP({ email, otp, type }) {
if (type === "forget-password") await sendResetPasswordOTP(email, otp);
},
}),
username({
maxUsernameLength: 25,
minUsernameLength: 3,
}),
admin(),
openAPI(),
],
database: drizzleAdapter(db, {
provider: "pg",
usePlural: true,
}),
session: {
expiresIn: 60,
updateAge: 0,
freshAge: 0,
},
advanced: {
cookiePrefix: "rcp",
},
});
export const auth = betterAuth({
baseURL: env.BETTER_AUTH_URL,
emailVerification: {
sendOnSignUp: true,
autoSignInAfterVerification: true,
sendVerificationEmail: async ({ user, url }) => {
await sendEmailVerification(user.email, url);
},
},
emailAndPassword: {
enabled: true,
minPasswordLength: 8,
maxPasswordLength: 40,
autoSignIn: true,
sendResetPassword: async ({ user, url }) => {
await sendResetPassword(user.email, url);
},
password: {
hash: async (password) => await Bun.password.hash(password),
verify: async ({ hash, password }) =>
await Bun.password.verify(password, hash),
},
},
trustedOrigins: ["http://localhost:3000"],
plugins: [
captcha({
provider: "cloudflare-turnstile",
secretKey: env.TURNSTILE_SECRET_KEY,
}),
emailOTP({
async sendVerificationOTP({ email, otp, type }) {
if (type === "forget-password") await sendResetPasswordOTP(email, otp);
},
}),
username({
maxUsernameLength: 25,
minUsernameLength: 3,
}),
admin(),
openAPI(),
],
database: drizzleAdapter(db, {
provider: "pg",
usePlural: true,
}),
session: {
expiresIn: 60,
updateAge: 0,
freshAge: 0,
},
advanced: {
cookiePrefix: "rcp",
},
});
4 Replies
Might sound weird. But seems to be a time zone issue
As you can see
I am using Bun runtime
Date Now
Code from better-auth
const expiresIn = ctx.context.sessionConfig.expiresIn;
const updateAge = ctx.context.sessionConfig.updateAge;
console.log("expiresIn", ctx.context.sessionConfig.expiresIn);
console.log("updateAge", ctx.context.sessionConfig.updateAge);
/**
* Calculate last updated date to throttle write updates to database
* Formula: ({expiry date} - sessionMaxAge) + sessionUpdateAge
*
* e.g. ({expiry date} - 30 days) + 1 hour
*
* inspired by: https://github.com/nextauthjs/next-auth/blob/main/packages/core/src/lib/actions/session.ts
*/
const nowDate = Date.now(); // <- Issue
const sessionIsDueToBeUpdatedDate =
session.session.expiresAt.valueOf() -
expiresIn * 1000 +
updateAge * 1000;
const shouldBeUpdated = sessionIsDueToBeUpdatedDate <= nowDate;
console.log("***********************",);
console.log("expiresAt",new Date(session.session.expiresAt.valueOf()));
console.log("Date Now",new Date(nowDate));
console.log("sessionIsDueToBeUpdatedDate",new Date(sessionIsDueToBeUpdatedDate));
console.log("shouldBeUpdated",shouldBeUpdated);
console.log("***********************",);
console.log("***********************",);
console.log("expiresAt",nowDate);
console.log("Date Now",nowDate);
console.log("sessionIsDueToBeUpdatedDate",sessionIsDueToBeUpdatedDate);
console.log("shouldBeUpdated",shouldBeUpdated);
console.log("***********************",);
const expiresIn = ctx.context.sessionConfig.expiresIn;
const updateAge = ctx.context.sessionConfig.updateAge;
console.log("expiresIn", ctx.context.sessionConfig.expiresIn);
console.log("updateAge", ctx.context.sessionConfig.updateAge);
/**
* Calculate last updated date to throttle write updates to database
* Formula: ({expiry date} - sessionMaxAge) + sessionUpdateAge
*
* e.g. ({expiry date} - 30 days) + 1 hour
*
* inspired by: https://github.com/nextauthjs/next-auth/blob/main/packages/core/src/lib/actions/session.ts
*/
const nowDate = Date.now(); // <- Issue
const sessionIsDueToBeUpdatedDate =
session.session.expiresAt.valueOf() -
expiresIn * 1000 +
updateAge * 1000;
const shouldBeUpdated = sessionIsDueToBeUpdatedDate <= nowDate;
console.log("***********************",);
console.log("expiresAt",new Date(session.session.expiresAt.valueOf()));
console.log("Date Now",new Date(nowDate));
console.log("sessionIsDueToBeUpdatedDate",new Date(sessionIsDueToBeUpdatedDate));
console.log("shouldBeUpdated",shouldBeUpdated);
console.log("***********************",);
console.log("***********************",);
console.log("expiresAt",nowDate);
console.log("Date Now",nowDate);
console.log("sessionIsDueToBeUpdatedDate",sessionIsDueToBeUpdatedDate);
console.log("shouldBeUpdated",shouldBeUpdated);
console.log("***********************",);

Seems to be working in production 👍
So.. is everything all good here?
Yep, Everything seems to be good👍