jabra
jabra4mo ago

Mobile Safari/Chrome sessions expire after a few minutes

@erquhart I need help, users are complaining. I'm using convex auth "@auth/core": "^0.37.4", "@convex-dev/auth": "npm:@erquhart/convex-auth@0.0.82" and the mobile users are logged out after a few minutes if they hide their chrome or safari browser app. This doesn't happen on desktop.
49 Replies
erquhart
erquhart4mo ago
Looks like you're using a linked version to my fork, is that to resolve a previous issue?
jabra
jabraOP4mo ago
yep for the figma code thing the issue is mobile session expiring quickly was there before i should move to the newer auth version , i saw your merge it but didn't have time to update
erquhart
erquhart4mo ago
so this mobile issue, when did it start happening?
jabra
jabraOP4mo ago
since i remember but it was not bothering me but now it is bothreing my new users
erquhart
erquhart4mo ago
are you able to reproduce yourself?
jabra
jabraOP4mo ago
"how can I stay logged in? If I navigate away for even a few minutes I am kicked out and need to log in again. I’m using a browser on iPhone" yes, i have the same behavior on mobile on iphone in both chrome or safari the session expires after a few minutes of inactivity
erquhart
erquhart4mo ago
so move browser to background for a few minutes, then go back to the browser app and you're logged out can you repro and then, instead of logging back in, hit refresh
jabra
jabraOP4mo ago
so the way i use the browser
erquhart
erquhart4mo ago
Need to see if you're actually logged out or if it's just the convex client dropping auth state
jabra
jabraOP4mo ago
is open a new tab and i notice that i need to log in again
erquhart
erquhart4mo ago
okay so not hidden or background hmm and that's the only repro case right
jabra
jabraOP4mo ago
yep, this is how i'm noticing it, I log in use the app then swipe app to hide the browser then i might be using the browser for other things then i open a new tab and go to my app and it is logged out on the other hand on the desktop browser i can open may tabs, close my app tab and then open it again and i'm still signed in even after a few days my auth files for your reference auth.config.ts
export default {
providers: [
{
domain: process.env.CONVEX_SITE_URL,
applicationID: 'convex',
},
],
}
export default {
providers: [
{
domain: process.env.CONVEX_SITE_URL,
applicationID: 'convex',
},
],
}
erquhart
erquhart4mo ago
ah okay, this helps
jabra
jabraOP4mo ago
auth.ts
...
async function findUserByEmail(ctx: QueryCtx, email: string) {
...
}

const CustomPasswordReset = Password<DataModel>({
profile(params) {
return {
email: params.email as string,
name: params.name as string,
}
},
id: 'password-with-reset',
reset: ResendOTPPasswordReset,
verify: ResendOTP,
})

export const { auth, signIn, signOut, store, isAuthenticated } = convexAuth({
providers: [
Google,
CustomPasswordReset,
],
callbacks: {
// `args.type` is one of "oauth" | "email" | "phone" | "credentials" | "verification"
// `args.provider` is the currently used provider config
async createOrUpdateUser(ctx: MutationCtx, args) {
if (args.existingUserId) {
// Optionally merge updated fields into the existing user object here
return args.existingUserId
}
// Implement your own account linking logic:
if (args.profile.email) {
const existingUser = await findUserByEmail(ctx, args.profile.email)
if (existingUser) return existingUser._id
}

// Implement your own user creation:
const userId = await ctx.db.insert('users', {
email: args.profile.email,
name: args.profile.name as string,
image: args.profile.image as string,
})

if (args.provider.id === 'google') {
await ctx.db.insert('authAccounts', {
userId: userId,
provider: 'password-with-reset',
providerAccountId: args.profile.email!,
secret: 'invalid-initial-personal',
emailVerified: args.profile.email!,
})
}
return userId
},
},
})
...
async function findUserByEmail(ctx: QueryCtx, email: string) {
...
}

const CustomPasswordReset = Password<DataModel>({
profile(params) {
return {
email: params.email as string,
name: params.name as string,
}
},
id: 'password-with-reset',
reset: ResendOTPPasswordReset,
verify: ResendOTP,
})

export const { auth, signIn, signOut, store, isAuthenticated } = convexAuth({
providers: [
Google,
CustomPasswordReset,
],
callbacks: {
// `args.type` is one of "oauth" | "email" | "phone" | "credentials" | "verification"
// `args.provider` is the currently used provider config
async createOrUpdateUser(ctx: MutationCtx, args) {
if (args.existingUserId) {
// Optionally merge updated fields into the existing user object here
return args.existingUserId
}
// Implement your own account linking logic:
if (args.profile.email) {
const existingUser = await findUserByEmail(ctx, args.profile.email)
if (existingUser) return existingUser._id
}

// Implement your own user creation:
const userId = await ctx.db.insert('users', {
email: args.profile.email,
name: args.profile.name as string,
image: args.profile.image as string,
})

if (args.provider.id === 'google') {
await ctx.db.insert('authAccounts', {
userId: userId,
provider: 'password-with-reset',
providerAccountId: args.profile.email!,
secret: 'invalid-initial-personal',
emailVerified: args.profile.email!,
})
}
return userId
},
},
})
erquhart
erquhart4mo ago
Are you seeing any logs in your convex deployment
jabra
jabraOP4mo ago
i can but i have a lot of logs 500 new users in the last 3 weeks
erquhart
erquhart4mo ago
I just mean if you repro this yourself, can you see what logs from that repro even just on dev so there aren't so many logs
jabra
jabraOP4mo ago
ok i will debug and report back i'm wondering if it is a mobile browser thing
erquhart
erquhart4mo ago
definitely is, just not sure what
jabra
jabraOP4mo ago
but my github and vercel stay logged in
erquhart
erquhart4mo ago
on iOS, safari and chrome are both just safari
jabra
jabraOP4mo ago
yep
erquhart
erquhart4mo ago
yeah, there's definitely something that can be done on the convex auth side, I see things staying logged in as well
jabra
jabraOP4mo ago
i just teted on android and it stayed logged in
erquhart
erquhart4mo ago
dammit safari
jabra
jabraOP4mo ago
i opened that session a few hours ago
erquhart
erquhart4mo ago
If you can enable verbose logging in your client and convex functions, even on dev just to get logs, and see what a repro gives you: https://labs.convex.dev/auth/debugging#enabling-verbose-logging
Debugging - Convex Auth
Authentication library for your Convex backend
jabra
jabraOP4mo ago
I'm back what i saw is the following if i just hide the window and not close the session stay logged in but if i close chrome or safari completely and I reopen the app on desktop of mobile i am logged out first session on mobile without shutting down the app then the next 3 sessions are mobile and then desktop with safari and chrome GET / 200 in 244ms [verbose] 2025-06-03T01:36:03.941Z [ConvexAuthNextjs] Begin middleware for request with URL https://localhost:3000/api/auth [verbose] 2025-06-03T01:36:03.941Z [ConvexAuthNextjs] Proxying auth action to Convex, path matches /api/auth with or without trailing slash [verbose] 2025-06-03T01:36:03.941Z [ConvexAuthNextjs] Fetching action auth:signIn with args {"refreshToken":"nd785<redacted>h4b54"} [verbose] 2025-06-03T01:36:04.634Z [ConvexAuthNextjs] Setting auth cookies with returned tokens [verbose] 2025-06-03T01:37:04.209Z [ConvexAuthNextjs] Begin middleware for request with URL http://localhost:3000/ [verbose] 2025-06-03T01:37:04.209Z [ConvexAuthNextjs] Not proxying auth action to Convex, path / does not match /api/auth [verbose] 2025-06-03T01:37:04.209Z [ConvexAuthNextjs] Begin handleAuthenticationInRequest [verbose] 2025-06-03T01:37:04.209Z [ConvexAuthNextjs] No tokens to refresh, returning undefined [verbose] 2025-06-03T01:37:04.209Z [ConvexAuthNextjs] Calling custom handler GET / 200 in 39ms [verbose] 2025-06-03T01:37:33.326Z [ConvexAuthNextjs] Begin middleware for request with URL https://localhost:3000/ [verbose] 2025-06-03T01:37:33.326Z [ConvexAuthNextjs] Not proxying auth action to Convex, path / does not match /api/auth [verbose] 2025-06-03T01:37:33.327Z [ConvexAuthNextjs] Begin handleAuthenticationInRequest [verbose] 2025-06-03T01:37:33.327Z [ConvexAuthNextjs] No tokens to refresh, returning undefined [verbose] 2025-06-03T01:37:33.327Z [ConvexAuthNextjs] Calling custom handler GET / 200 in 30ms [verbose] 2025-06-03T01:38:40.679Z [ConvexAuthNextjs] Begin middleware for request with URL http://localhost:3000/ [verbose] 2025-06-03T01:38:40.679Z [ConvexAuthNextjs] Not proxying auth action to Convex, path / does not match /api/auth [verbose] 2025-06-03T01:38:40.679Z [ConvexAuthNextjs] Begin handleAuthenticationInRequest [verbose] 2025-06-03T01:38:40.679Z [ConvexAuthNextjs] No tokens to refresh, returning undefined [verbose] 2025-06-03T01:38:40.679Z [ConvexAuthNextjs] Calling custom handler GET / 200 in 38ms for the debugging i only enabled nextjs middleware and the client i didn't set
npx convex env set AUTH_LOG_LEVEL DEBUG
npx convex env set AUTH_LOG_LEVEL DEBUG
but all the other apps like github and vercel, i stay logged in even if i close the browser completely and reopen it
erquhart
erquhart4mo ago
ah this is server side - server side auth is still experimental in convex auth, so I'm less surprised reading through Have you tried on desktop safari
jabra
jabraOP4mo ago
last 2 are on desktop safari and chrome if i close the browser and reopen it i'm logged out
erquhart
erquhart4mo ago
oh so this is no longer just a mobile issue, it's the same on desktop safari and chrome? probably cookies
jabra
jabraOP4mo ago
yep, since i never close my desktop broser
erquhart
erquhart4mo ago
ah
jabra
jabraOP4mo ago
maybe i need to impelment /api/auth Not proxying auth action to Convex, path / does not match /api/auth
erquhart
erquhart4mo ago
oh "not proxying auth action" missed that negative hmm but then if you log in, and then refresh, you get those first logs
jabra
jabraOP4mo ago
yep
erquhart
erquhart4mo ago
is this something I can sign up for in production?
jabra
jabraOP4mo ago
yep vivify.ai
erquhart
erquhart4mo ago
hmm, signed in with google, closed and reopened browser, still signed in did I miss a step?
jabra
jabraOP4mo ago
interesting maybe the google sign in is persistent
erquhart
erquhart4mo ago
That was Arc, Safari did log me out on reopen feels like cross domain cookie blocking nope, not that oh lol they're session cookies learned something new one sec
erquhart
erquhart4mo ago
If you don't set this option, the cookie will be considered a "session cookie" and be deleted when the browser session ends, which depends from browser to browser.
jabra
jabraOP4mo ago
looking, thanks
erquhart
erquhart4mo ago
so the good news is it's working as designed
jabra
jabraOP4mo ago
{ cookieConfig: { maxAge: 60 * 60 * 24 * 30 } }, testing on dev, will report back soon that works super awesome thanks a bunch @erquhart
erquhart
erquhart4mo ago
np, glad it was a quick resolve
jabra
jabraOP4mo ago
I deployed to production and it is working
uma
uma4mo ago
Finished reading thread now. Awesome. Thank you both @jabra and @erquhart

Did you find this page helpful?