-
-
Notifications
You must be signed in to change notification settings - Fork 169
Description
Bug report
- I confirm this is a bug with Supabase, not with my own application.
- I confirm I have searched the Docs, GitHub Discussions, and Discord.
Describe the bug
On app launch the iOS SDK briefly surfaces the cached session via
supabase.auth.currentSession
, but immediately afterward it nukes that session and emits
initialSession
with
session == nil
. Any request made afterward fails with AuthError.sessionMissing
(a “ghost session” state). Assuming you let the user optimistically in based on the synchronous supabase.auth.currentSession
check.
There are no custom session expiration settings in the project; defaults are used. There is no reason why it should be nuked.
To Reproduce
-
Sign in with any user in an iOS app using supabase-swift.
-
Kill the app or wait for the system to kill it.
-
Relaunch after a few days.
-
Immediately read
supabase.auth.currentSession
→ it is non-nil. -
Attach
for await authStateChanges
. -
The first callback you receive is:
event = initialSession session = nil
-
Subsequent
supabase.auth.currentSession
is nownil
, and any REST call
returnssessionMissing
.
Console output:
// ON APP LAUNCH:
let isSignedIn = supabase.auth.currentSession != nil
print("Is signed in? \(supabase.auth.currentSession?.hashValue)")
print("Is signed in? \(supabase.auth.currentUser?.email)")
-> Is signed in? Optional(2166808766723586244)
-> Is signed in? Optional("[email protected]")
// AFTER ATTACHING OBSERVERS:
private func setupAuthListener() {
Task {
for await (event, session) in supabase.auth.authStateChanges {
print("Auth change:", event, session?.hashValue, session?.expiresAt, session?.isExpired)
switch event {
case .initialSession:
print("INITIAL SESSION", session?.hashValue)
....
-> Auth change: initialSession nil nil nil
// AFTER CALLING HTTP REQUESTS THAT WANT TO REFRESH A TOKEN FROM SUPABASE USING
// try await supabase.auth.session
-> sessionMissing
Expected behavior
-
SDK shouldn't nuke the sessions in the first place.
-
Make the nuking explicit
a) The cached session is still valid → SDK should emitinitialSession(session:)
with that same session, or
b) The cached session is invalid → SDK should emitinitialSession
with the cached session object (isExpired == true) followed bysignedOut
, or attempt a silenttokenRefreshed
before wiping it.
Silently deleting the session and returning nil
makes it impossible to distinguish “first launch” from “previously signed-in user whose refresh token was lost”, and leads to ghost-session states.
Screenshots
N/A (console logs included above).
System information
- OS: iOS 17.5 / macOS 14.5 (reproduced on both simulator and device)
- Supabase version: 2.26.1
- Xcode: 15.4
Additional context
A doc note (“don’t trust currentSession
until after the firstinitialSession
event”) would help, but ideally the SDK should not wipe the cached session without emitting a reasoned event.