Skip to content

Conversation

@grdsdev
Copy link
Contributor

@grdsdev grdsdev commented Oct 24, 2025

🔍 Overview

This is a DRAFT PR for visibility and collaboration purposes. It is not intended to be merged as-is.

This PR adds comprehensive instrumentation and a dedicated debug application to help diagnose and reproduce the intermittent token refresh issue reported in #1158.

🐛 Problem Being Investigated

Users are experiencing inconsistent token refresh behavior where:

  • Sometimes auto-refresh works correctly
  • Sometimes the SDK emits a signedOut event instead of refreshing expired tokens
  • This results in 403 errors and unexpected user logouts
  • The issue is intermittent and difficult to reproduce

See full issue details at #1158

🎯 Purpose of This PR

1. Comprehensive Instrumentation

Added detailed logging throughout the authentication flow to track:

Modified Files:

  • packages/gotrue/lib/src/gotrue_client.dart - Auto-refresh lifecycle, token refresh operations, session recovery
  • packages/supabase_flutter/lib/src/supabase_auth.dart - App lifecycle events, initialization, session recovery
  • packages/gotrue/lib/src/types/session.dart - Session expiry calculations
  • packages/supabase_flutter/lib/src/local_storage.dart - Storage operations (read/write/remove)
  • packages/supabase_flutter/lib/src/supabase.dart - Initialization flow

The instrumentation uses hierarchical log levels:

  • FINEST - Very detailed timing and state information
  • FINE - Debug information about internal operations
  • INFO - Important state changes and events
  • WARNING - Errors and unexpected conditions

2. Token Refresh Debug App

Created a complete Flutter application at examples/token_refresh_debug_app/ that provides:

Features:

  • ⏱️ Real-time session monitoring - View token expiry status, time remaining, and session details
  • 📊 Comprehensive logging - All SDK instrumentation displayed in console with timestamps
  • 🔄 App lifecycle tracking - Monitor app state changes (paused/resumed/inactive)
  • 🛠️ Manual testing tools - Trigger API calls and manual token refreshes
  • 📝 Event log - In-app log showing auth events correlated with console logs
  • 📋 Built-in reproduction instructions - Step-by-step guide for testing scenarios

See the comprehensive README: examples/token_refresh_debug_app/README.md

🧪 How to Use the Debug App

Quick Start

  1. Navigate to the debug app:

    cd examples/token_refresh_debug_app
    melos bootstrap
    flutter run
  2. Configure your Supabase project with a short token expiry (e.g., 5 minutes) for easier testing

  3. Launch the app and enter your Supabase URL and anon key

  4. Sign in with a test user

  5. Try reproducing the issue using one of these scenarios:

    • Scenario 1: Pause app until token expires, then resume
    • Scenario 2: Enable airplane mode during token refresh
    • Scenario 3: Rapidly pause/resume to test race conditions
  6. Monitor the logs for:

    • Session recovery timing
    • Auto-refresh tick calculations
    • Token refresh success/failure
    • SignedOut events and their causes

Expected vs Problematic Behavior

✅ Expected (successful refresh):

1. App resumed
2. Auto-refresh timer starts
3. Session recovery completes
4. Token refresh triggered at threshold
5. tokenRefreshed event emitted
6. Session persisted

❌ Problematic (bug reproduced):

1. App resumed
2. Auto-refresh timer starts immediately
3. Auto-refresh tick runs (race condition)
4. Session recovery still in progress
5. Token refresh fails
6. signedOut event emitted
7. User unexpectedly logged out

🤝 How You Can Help

We're inviting the community to help us:

  1. Reproduce the issue using the debug app

  2. Share logs showing the exact sequence of events

  3. Report your findings including:

    • Platform (iOS/Android/Web)
    • Flutter/Dart version
    • How consistently it reproduces (e.g., 3/10 attempts)
    • Specific timing (e.g., resumed 2 minutes after token expired)
    • Any custom storage implementations you're using
  4. Test proposed fixes once we identify root causes

📊 What We've Learned So Far

From analyzing the code and issue reports, we've identified potential root causes:

  1. App Lifecycle Race Condition - Auto-refresh timer may start before session recovery completes on app resume
  2. Tight Timing Windows - 30s expiry margin + 30s threshold = 0 buffer for timing variance
  3. Non-Retryable Errors - Some errors force signout instead of preserving session for retry
  4. Concurrent Refresh Attempts - Multiple sources trying to refresh simultaneously

The instrumentation will help us confirm which of these (or other factors) are causing the issue.

⚠️ Important Notes

  • This is NOT ready for merge - it's for investigation purposes
  • The instrumentation adds logging overhead - not intended for production
  • Some log messages are very verbose (FINEST level)
  • The debug app requires manual configuration (URL, keys, credentials)

🔗 Related Issues

Closes #1158 (when actual fixes are implemented)

📝 Testing Checklist

If you're helping test, please try to:

  • Test on iOS
  • Test on Android
  • Test on Web
  • Test with default SharedPreferences storage
  • Test with custom storage implementation
  • Test with very short token expiry (5 min)
  • Test with normal token expiry (1 hour)
  • Test app pause/resume after expiry
  • Test network interruption during refresh
  • Test rapid lifecycle changes

💬 Discussion

Please share your findings, logs, and observations in the issue #1158 or comment on this PR.


Note: This PR will remain in draft status while we gather data and develop proper fixes. Once we have confirmed fixes, we'll create a separate PR for the actual implementation.

@coveralls
Copy link

Pull Request Test Coverage Report for Build 18784222894

Details

  • 84 of 132 (63.64%) changed or added relevant lines in 5 files are covered.
  • 5 unchanged lines in 2 files lost coverage.
  • Overall coverage decreased (-0.4%) to 79.275%

Changes Missing Coverage Covered Lines Changed/Added Lines %
packages/supabase_flutter/lib/src/supabase.dart 6 10 60.0%
packages/supabase_flutter/lib/src/local_storage.dart 19 24 79.17%
packages/supabase_flutter/lib/src/supabase_auth.dart 22 35 62.86%
packages/gotrue/lib/src/gotrue_client.dart 24 50 48.0%
Files with Coverage Reduction New Missed Lines %
packages/supabase_flutter/lib/src/supabase_auth.dart 1 57.14%
packages/gotrue/lib/src/gotrue_client.dart 4 61.04%
Totals Coverage Status
Change from base Build 18568213555: -0.4%
Covered Lines: 3370
Relevant Lines: 4251

💛 - Coveralls

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Auto Refresh is not working

2 participants