File tree Expand file tree Collapse file tree
web/app/api/auth/extension/login Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -851,24 +851,12 @@ async function ensureValidToken() {
851851 return true ;
852852 }
853853
854- // Token should be valid based on expiry, but validate to be sure
855- // Only do this if we haven't refreshed recently (avoid unnecessary network calls)
856- const isValid = await validateToken ( ) ;
857- if ( isValid ) {
858- return true ;
859- }
860-
861- // Token validation failed despite not being expired - try refresh
862- console . log ( '[MarkSyncr] Token validation failed unexpectedly, attempting refresh...' ) ;
863- const refreshed = await tryRefreshToken ( ) ;
864-
865- if ( ! refreshed ) {
866- // Don't clear — preserve extension_token for future retry.
867- // tryRefreshToken handles clearing on definitive 401 (session revoked/expired).
868- console . log ( '[MarkSyncr] Token refresh failed, will retry on next attempt' ) ;
869- return false ;
870- }
871-
854+ // Token is not expired based on stored expiry — trust it.
855+ // Don't make a network validation call on every sync; that wastes bandwidth
856+ // and can cause spurious failures (timeouts, network blips) that trigger
857+ // unnecessary refresh cascades. The actual API call in performSync will
858+ // naturally return 401 if the token is invalid, and apiRequest() already
859+ // handles that by calling tryRefreshToken() and retrying.
872860 return true ;
873861}
874862
Original file line number Diff line number Diff line change @@ -103,7 +103,7 @@ export async function POST(request) {
103103 const extensionToken = generateSecureToken ( ) ;
104104 const extensionTokenHash = hashToken ( extensionToken ) ;
105105
106- // Step 3: Calculate expiration (1 year from now)
106+ // Step 3: Calculate expiration (2 years from now)
107107 const expiresAt = new Date ( Date . now ( ) + EXTENSION_SESSION_DURATION_MS ) ;
108108
109109 // Step 4: Store extension session in database using admin client
@@ -145,6 +145,10 @@ export async function POST(request) {
145145 access_token : session . access_token ,
146146 // Expiration of the extension session (not the access token)
147147 expires_at : sessionData . expires_at ,
148+ // Expiration of the short-lived access token (typically 1 hour)
149+ // Without this, the extension assumes the token is expired on first use
150+ // and triggers an unnecessary refresh cycle on every sync
151+ access_token_expires_at : session . expires_at ,
148152 // Session metadata
149153 session_id : sessionData . id ,
150154 created_at : sessionData . created_at ,
Original file line number Diff line number Diff line change 33--
44-- This table stores long-lived session tokens for browser extensions.
55-- Unlike Supabase's default JWT tokens (which expire in 1 hour with 7-day refresh tokens),
6- -- extension sessions are designed to last 1 year to avoid requiring frequent re-logins.
6+ -- extension sessions are designed to last 2 years to avoid requiring frequent re-logins.
77--
88-- Security considerations:
99-- - extension_token is a cryptographically secure random token (256 bits)
9797GRANT EXECUTE ON FUNCTION cleanup_expired_extension_sessions() TO authenticated;
9898
9999-- Comment on table for documentation
100- COMMENT ON TABLE extension_sessions IS ' Long-lived session tokens for browser extensions (1 year expiry)' ;
100+ COMMENT ON TABLE extension_sessions IS ' Long-lived session tokens for browser extensions (2 year expiry)' ;
101101COMMENT ON COLUMN extension_sessions.extension_token_hash IS ' SHA-256 hash of the extension token for secure verification' ;
102102COMMENT ON COLUMN extension_sessions.supabase_refresh_token IS ' Supabase refresh token for obtaining new access tokens' ;
103103COMMENT ON COLUMN extension_sessions.device_id IS ' Unique identifier for the browser/device' ;
104- COMMENT ON COLUMN extension_sessions.expires_at IS ' Session expiration (default: 1 year from creation)' ;
104+ COMMENT ON COLUMN extension_sessions.expires_at IS ' Session expiration (default: 2 years from creation)' ;
105105COMMENT ON COLUMN extension_sessions.last_used_at IS ' Last time the session was used (for activity tracking)' ;
You can’t perform that action at this time.
0 commit comments