supabase / supabase-swift

A Swift client for Supabase
https://supabase.com/docs/reference/swift
MIT License
679 stars 100 forks source link

"Refresh Token Not Found" = automatic logout after 2-3 days after login #486

Open EduardMe opened 1 month ago

EduardMe commented 1 month ago

Bug report

Describe the bug

About 2-3 days after logging in, the user gets automatically logged out (we are using the OTP login and use the API on iOS and macOS). Checking the error messages, we see:

api(Auth.AuthError.APIError(msg: nil, code: nil, error: Optional("invalid_grant"), errorDescription: Optional("Invalid Refresh Token: Refresh Token Not Found"), weakPassword: nil))

To Reproduce

Using the Swift API of Supabase, login, use the app for 2-3 days and you will get logged out.

Expected behavior

User should stay logged in indefinitely or as per the settings (see additional information).

System information

Additional context

We have tried to increase the rate limits: Token Refreshes = 184 Token Verifications = 100 Sign ups and sign ins = 50 Time-box user sessions = 0 Inactivity timeout = 0 Access Tokens expiry time = 10800 (3 hours) Refresh token reuse interval = 30

Let me know if the settings can cause this.

hf commented 1 month ago

This is likely due to a bug in your application that refreshes the token in parallel. Please see this doc for more information about such issues: https://supabase.com/docs/guides/auth/sessions#what-is-refresh-token-reuse-detection-and-what-does-it-protect-from

hf commented 1 month ago

Also be aware that if the user signed out from another device or platform (web) they are signed out from everywhere. You can control this with a parameter.

EduardMe commented 1 month ago

Thanks for the quick reply. We have called refreshSession when an invalid_grant error was received. Can this cause the problem? I have removed that and also set the scope of signOut to global. Though I don't think this was the issue, but could have added some confusion. Will monitor this the next few days.

EduardMe commented 1 month ago

Ok, after about 2-3 days of testing with the changes, I'm still getting logged out automatically on macOS (2x in the last 2-3 days) with the error message:

api(Auth.AuthError.APIError(msg: nil, code: nil, error: Optional("invalid_grant"), errorDescription: Optional("Invalid Refresh Token: Already Used"), weakPassword: nil))

I haven't hit the logout button anywhere during testing.

Any ideas how to fix it or if it's a bug in the library?

grdsdev commented 1 month ago

Hi @EduardMe

do you have any extension also using Supabase? Widgets...

EduardMe commented 1 month ago

Just checked, we have a Widget, but it accesses only some userDefaults.

We have shortcuts that call the CloudKit sync, possibly Supabase, however, I'm not using them.

Today I got logged out again on macOS. I use it less on iOS, but there I didn't get logged out since testing. So it's just on macOS since the last 3 days.

On macOS I often run into some internet connection issues. It gets disconnected for a second. Might this influence it?

grdsdev commented 1 month ago

Thanks @EduardMe

I'm investigating it, and will post any updates I find on this issue.

LucasAbijmil commented 1 month ago

I'm having the same issue since I updated my version of Supabase in my Xcode project. I don't do anything sophisticated in my app and the token settings are the default

grdsdev commented 1 month ago

@LucasAbijmil which version were you using before, which you wasn't having this issue?

LucasAbijmil commented 1 month ago

@grdsdev Previously I was in 2.5.1, then it was when I switched to 2.13.3 that the bug seems to have been introduced

EduardMe commented 1 month ago

@grdsdev I have some idea, but I'm not quite sure. Is it possible that if this gets called in parallel or when the Supabase library refreshes the session in the background and we call it at the same time it creates an issue?

We are using this func in Swift to check if the user is logged in:

func session(completion: @escaping (Result<Session, Error>) -> Void) {
    Task {
        do {
            if let currentSession = supabase.auth.currentSession, !currentSession.isExpired {
                completion(.success(currentSession))
                return
            }

            let session = try await supabase.auth.session
            completion(.success(session))
        } catch {
            completion(.failure(error))
        }
    }
}
grdsdev commented 1 month ago

@EduardMe I don't think that is causing the issue, but your check is redundant, when you call the try await supabase.auth.session it already validates if session is expired, if it isn't, it returns it without refreshing, just like your first if.

Still looking at this issue...

dpelletier2017 commented 3 weeks ago

This might be the bug I'm experiencing since December, the day I implemented Sign In With Apple in my SwiftUI App. It seems to happen randomly. When I develop the app, it can happen 3-4 times in an afternoon because I launch my app often, but other than that yes it seems to be happening every 2-3 days. It basically logs my users out from time to time.

Ideally, I'd like the user to just login the first time and then never again unless he stops using the app for a prolonged period, or he deletes the app and reinstalls it or upgrades to a new phone.

api(Auth.AuthError.APIError(msg: nil, code: nil, error: Optional("invalid_grant"), errorDescription: Optional("Invalid Refresh Token: Refresh Token Not Found"), weakPassword: nil))

I've indeed seen that happen quite a lot of times. That along with "Bad ID token". I can't put my finger on it, but there's something not working well with Supabase Auth in Swift.

FYI I never call the refreshSession() function, because the Docs says : try await supabase.auth.session // Returns the session, refreshing it if necessary I tried using the refreshSession() function and the bug was still there, so I removed it in my production code.

EduardMe commented 3 weeks ago

For us the error is usually Invalid Refresh Token: Already Used. That's the only bigger roadblock for us right now. The rest works great. We haven't use the API for that long, so I haven't seen a version where it worked for more than 2-3 days.

EduardMe commented 2 weeks ago

@grdsdev Could you find anything? We are a bit struggling with this, or is there anything we can do temporarily to reduce the logouts?

iBenjamin commented 2 days ago

2024-09-10T17:37:30+0800 supabase: Response: Status code: 400 Content-Length: 83 Body: { "error" : "invalid_grant", "error_description" : "Invalid Refresh Token: Already Used" } same here