Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sharing a Supabase Auth Session - Incompatibility Between Supabase Flutter and Swift SDKs: Session JSON Structure Mismatch #1727

Closed
baptiste-veyrard opened this issue Aug 20, 2024 · 4 comments
Labels
auth bug Something isn't working

Comments

@baptiste-veyrard
Copy link

baptiste-veyrard commented Aug 20, 2024

Bug report

Description:

I'm developing an application where I need to share a Supabase session between my main app, built using FlutterFlow (which uses the Supabase Flutter SDK), and an iOS extension target (a credential provider) where auth is built using the Supabase Swift SDK. I've encountered an issue where the session JSON structure used by the Supabase Flutter SDK is incompatible with what is expected by the Supabase Swift SDK.
So it makes the JSON stored by the flutter SDK not parseable by the swift SDK.

JSON Structures:

  1. Supabase Swift SDK
    { "session": { "expires_in": 3290.1477999687195, "expires_at": 1724170095, "refresh_token": "6hgVKxl.......", "access_token": "eyJhbGciOiJIUzI1NiIsImtpZCI6ImwzY0JFV1dJZjBMQjZYTk0iLCJ0eXAiOiJKV1QifQ...", "user": { "email": "[email protected]", "user_metadata": { "sub": "7e852d69-XXXX-XXXX-XXXX-42b02d8edc85", "phone_verified": false, "email": "[email protected]", "email_verified": false }, ... }, "token_type": "bearer" }, "expiration_date": "2024-08-20T16:08:15.000Z" }

  2. Supabase Flutter SDK

{ "currentSession": { "access_token": "eyJhbGciOiJIUzI1NiIsImtpZCI6ImwzY0JFV1dJZjBMQjZYTk0iLCJ0eXAiOiJKV1QifQ...", "expires_in": 3600, "refresh_token": "6hgVKxl_Bkt537lJDCQkrw", "token_type": "bearer", "user": { "id": "7e852d69-e353-4852-8891-42b02d8edc85", "app_metadata": { "provider": "email", "providers": ["email"] }, ... } }, "expiresAt": 1724170095 }

To Reproduce

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

  1. Download the following test project from my GitHub ->[Supabase-Auth-test-project-Flutter-Swift](https://github.com/baptiste-veyrard/Supabase-Auth-test-project-Flutter-Swift) , where I already took a demo project and modify it, adding a keychain group and sharedGroup, leveraging FlutterSecureStorage to store supabase auth info...
  2. Open Xcode
  3. Add a developer team
  4. Add the Supabase swift SDK
  5. Add a supabase project URL and key -> in the main.dart file for flutter, in SupabaseAuthManager for swift
  6. Run "flutter pub get" and cd-> ios "pod install" in the terminal (I am using cocoapods)
  7. Build the "runner" target and login a user
  8. Build the "autofill-extension" target with Safari, go on a credential form (ex: signin facebook) and click on "password" the quicktype bar

Expected behavior

The Supabase SDKs for both Flutter and Swift should use a compatible JSON structure for session management, allowing seamless sharing of sessions between different platforms.
Due to the print in the CredentialProviderViewController (in viewDidLoad) it should return a valid session.

Actual Behavior:
The session JSON structure used by the Supabase Flutter SDK is incompatible with the structure expected by the Supabase Swift SDK, leading to decoding errors and the inability to share sessions across these platforms.
The function init() in SupabaseAuthManager.swift return the following error:
Failed to load session: keyNotFound(CodingKeys(stringValue: "session", intValue: nil), Swift.DecodingError.Context(codingPath: [], debugDescription: "No value associated with key CodingKeys(stringValue: \"session\", intValue: nil) (\"session\").", underlyingError: nil))

System information

  • OS: MacOS Sonoma 14.5
  • Xcode version: 15.4
  • Supabase swift package: 2.16.1
  • Flutter swift pub: 9.2.2
  • Flutter version: 3.22.2

More info:
I cloned a swift package in order to add some prints in the package code to identify where the issue happened.
It seems to happen in the "SessionStorage" file, at the line of code:
return try storedData.flatMap { try AuthClient.Configuration.jsonDecoder.decode(StoredSession.self, from: $0).session }

As well, I tried to set my own JSONDecoder as it seems to be possible through the auth option of the supabase client.
It was well initialized, but the SDK still uses the "original" JSONDecoder to perform the decoding tasks.

@baptiste-veyrard baptiste-veyrard added the bug Something isn't working label Aug 20, 2024
@dshukertjr
Copy link
Member

Just leaving some info from the Flutter side here:

The supabase-flutter SDK stores the session in the following format.

  {
    "access_token": accessToken,
    "expires_in": expiresIn,
    "expires_at": expiresAt,
    "refresh_token": refreshToken,
    "token_type": tokenType,
    "provider_token": providerToken,
    "provider_refresh_token": providerRefreshToken,
    "user": {<user json>},
  }

supabase-flutter does allow developers to store the token in any location they want by defining a custom local storage, so as long as the shape of the session json match, sharing session between the Flutter and Swift SDK should be possible, but does the shape of the JSON structure match @grdsdev ?

@baptiste-veyrard
Copy link
Author

baptiste-veyrard commented Aug 24, 2024

Thanks for your answer.
Indeed, I use a custom local storage, in the keychain via flutter_secure_storage.
I well retrieve the data stored in it from my swift code, but it cannot be retrieved as a supabase session given the differences of the JSON values stored.

The JSON structures I provided in my post are the actual structures I retrieve when I print a session created in Swift and Flutter.

The format you provided is the session itself, in JSON, but when stored, it uses the following piece of code in session.dart (file of the supabase flutter package).

String get persistSessionString { final data = {'currentSession': toJson(), 'expiresAt': expiresAt}; return json.encode(data); }

And the Supabase Swift package is looking for the keyword "currentSession" and not "session".
I succeed to make them matching in modifying the flutter sdk just for testing purpose, but modifying it is not a proper way to handle it for a long term perspective for a production app.

That is why then I tried to make my own JSON Decoder, but while well initialized, the supabase swift package does not use it to decode the retrieve session in the keychain unfortunatelly.

One workaround would be to modify the "data" value in a function before storing it via my custom local storage function, so without changing the package, but I thought it was a better idea to talk about it with the Supabase team first.

@grdsdev
Copy link

grdsdev commented Aug 26, 2024

Hi @dshukertjr

Session JSON structure is compatible with Flutter, as it uses the same structure, the issue I see is that Flutter stores it in a currentSession key, along with a expiresAt. Swift uses the same approach, but stores in under a session key, and expirationDate, that is where the incompatibility happens.

If we match only those 2 keys, all should work as expected, without the need of custom decoding on Swift.

@baptiste-veyrard the reason for this not using your own JSON Decoder for decoding the session, is because I didn't want to expose the decoding/encoding of the internal stored session, and let you customize the storing/retrieving of raw Data through the custom local storage only.

Action items

  1. Rename keys to match on both Swift and Flutter; or
  2. Remove the wrapping keys, and store session directly.

@dshukertjr which one you prefer? (I prefer 2, as there is not need for the wrapping keys anymore)

@dshukertjr
Copy link
Member

dshukertjr commented Aug 26, 2024

@baptiste-veyrard

The format you provided is the session itself, in JSON, but when stored, it uses the following piece of code in session.dart (file of the supabase flutter package).

That was the behavior of the v1 package, and it is no longer the behavior in the latest versions. Latest versions store the sessions in the format that I outlined up here. Please use the latest versions to verify the most up-to-date behavior.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
auth bug Something isn't working
Projects
None yet
Development

No branches or pull requests

3 participants