supabase / supabase-swift

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

Issue with Reauthentication using setSession() on watchOS after SignOutScope is set to .local #535

Closed f-bog closed 6 days ago

f-bog commented 6 days ago

Bug report

Describe the bug

I am working on a companion watchOS app for my React Native app. I'm totally new to the intricacies of Swift and not totally confident with my supabase auth knowledge, so while I think I have a general understanding, I'm unsure if this issue is caused by my own code. If it is, please feel free to throw this in the trash and light it on fire.

So far, I've been able to authenticate on the watch by sending the access_token and refresh_token from my current session and passing them to setSession on the watch:
try await supabase.auth.setSession(accessToken: accessToken, refreshToken: refreshToken)

This works fine, and I'm able to use all the Supabase client methods without any issues. However, when I sign out of Supabase on the watch using: try await supabase.auth.signOut(scope: .local)

and then attempt to reauthenticate by passing the tokens from the iPhone back to the Apple Watch, I get this error: api(Auth.AuthError.APIError(msg: Optional("Session from session_id claim in JWT does not exist"), code: Optional(403), error: nil, errorDescription: nil, weakPassword: nil))

I'm only able to reauthenticate on the watch after reauthenticating on my iPhone and passing the tokens again.

I was under the impression that the .local sign-out scope should only invalidate the local session. That might still be the case, but could sending the session from my iPhone be causing both sessions to become invalid?

To Reproduce

Steps to reproduce the behavior, please provide code snippets or a repository:

  1. Send tokens from iPhone to setSession on the Apple Watch
  2. Signout via apple watch
  3. Attempt to send tokens from iPhone to setSession on the Apple Watch
  4. See error api(Auth.AuthError.APIError(msg: Optional("Session from session_id claim in JWT does not exist"), code: Optional(403), error: nil, errorDescription: nil, weakPassword: nil))

Expected behavior

Sign out and sign in of apple watch without effecting the iPhone auth session.

dshukertjr commented 6 days ago

Calling try await supabase.auth.signOut(scope: .local) invalidates the refresh token used on the client. Since you are sharing the same accessToken/ refresh token pair on both devices, both of them will be invalidated once you call try await supabase.auth.signOut(scope: .local) on one of them.

f-bog commented 6 days ago

Calling try await supabase.auth.signOut(scope: .local) invalidates the refresh token used on the client. Since you are sharing the same accessToken/ refresh token pair on both devices, both of them will be invalidated once you call try await supabase.auth.signOut(scope: .local) on one of them.

Riight thank you! Guess my confusion was happening from this mentioned in the docs:

I do have enforce single session per user toggled on too... Hoping there is another way to handle this..

dshukertjr commented 6 days ago

A single session is never meant to be shared across multiple devices, so how about implementing a mechanism that allows the watch OS version to properly sign-in and obtain it's own session? Is turning on the single session per user an absolute requirement? Alternatively, you could just nuke the local storage storing the tokens on your watch OS app although this would not trigger a signOut event on the Supabase SDK.

f-bog commented 6 days ago

Yeah the single session enforcement is an actual requirement for us, at least when it comes to mobile devices. Using the standard auth mechanism on the watch can be cumbersome, unless we utilise anonymous sign-ins but I assume that could introduce some problems with RLS policies.

Sounds like we may have to work on our own way of handling single signins for users when using mobile devices.

I am storing the access_token in the watchOS keychain already. Is this what you mean?

dshukertjr commented 6 days ago

I am storing the access_token in the watchOS keychain already. Is this what you mean?

Yeah. You could just delete the access token on the watch OS to sign out in a way.

f-bog commented 6 days ago

I am storing the access_token in the watchOS keychain already. Is this what you mean?

Yeah. You could just delete the access token on the watch OS to sign out in a way.

I'll give it a go! Appreciate the help 🤙