As I understand it from using GitLive Firebase SDK...
# multiplatform
j
As I understand it from using GitLive Firebase SDK Auth. I can do like this:
Copy code
val authProvider = GoogleAuthProvider.credential(token, accessToken)
            val auth = firebaseAuth.signInWithCredential(authProvider)
However in every single example they mention using GoogleSignInClient from Google Play Service, at same time they say not need google play services. How do I login multiplatform with token/accessToken? I can use actual/expect redirect to webview or whatever if needed, but not sure how to achieve this. Anyone implemented Google SSO with Firebase Auth in Kotlin Multiplatform?
a
Yes, the code above will be in shared part, on Android side you will have to use
GoogleSignInClient
to generate
idToken
and pass to shared. On iOS will be similar.
j
Yeah I solved it, painfully bad architecture mixing Googles SDK thingy in Swift vs Kotlin with tight coupled code to work in both platforms from same compose login screen. Tried move inside a repo/viewmodel isolated but cant start activity result from it in Android with Koin. A lot of singletons and non agnostic things. But indeed worked combine Swift GSignId and Kotlin GoogleSignInClient and setup a lot of pods and weird config in Firebase :) This was the things I wanted the Firebase SDK to solve internally or at least some helpers ๐Ÿ™‚
@A Do you know if Android Google sign in somehow able to extract login from one tap login or credentials manager without Activity? I mean only from Application or such.
a
@Joel Denke I doubt about that, unfortunately in Android most of the stuff are bound to context.
j
Yeah I tried my best of get arround it from Application level. I could ofc doing a Activity lifecycle from Application and extract latest available Activity. I was also think about get it from LocalContext, but then not agnostic in Compose. And also wanted to use activity result API in compose for Android, to make code a little less ugly. But hmm not sure how to ideally solve this without couple code in UI both native and Compose Multiplatform in both directions nested back and forth. Its going against code patterns I am using. Maybe there is some smart pattern can use I am not aware of?
a
I used activity result APIs. You are right, there is no "nice" solution available, so we need to pick one from not-great-options.
r
Hey, can you share the ios code and how you did it there? and how were you able to access the ios implementation from the shared module?
j
@Raed Ghazal Sorry cant share. But using it quite simple. Use regular Google Swift / Firebase Auth and follow https://firebase.google.com/docs/auth/ios/start initialize step for Google play services and app delegate. Once having that should be able using https://developers.google.com/identity/sign-in/ios/sign-in Which basically is deep link setup. Once get google token I forwarded that through my shared module code and delegate back to KMP Firebase Auth library.
r
Youโ€™re using compose multiplatform right?
If so, how are you calling the swift function to launch google webview from the composable?
The shared module doesnโ€™t have access to iosApp
j
Let me double check. I have compose ui code press Google login button. But from Swift when creating iOS viewcontroller for compose entry point, I have a lambda I send in to compose code when press login button. That lambda launching and once get back from iOS Google login, send token through shared code.
r
Thanks a lot! Already helpful, but would be great if you can share some code snippets, Iโ€™ll also share where I stopped once I get back to my laptop, out of home now.
j
I think Jetbrains in newest version exposing current view controller in LocalViewController or such. So could access this from compose directly maybe. Havent tried that yet. Did similar in Android flow.
Copy code
func makeUIViewController(context: Context) -> some UIViewController {
        return ScreenProvider.shared.createMainScreenController(onLogin: login)
    }
Pretty much this in Swift ui.
In that login func, call
GIDSignIn.sharedInstance.signIn(withPresenting: presentingViewController) { result, error in
@Raed Ghazal I dont have computer available so sorry bad indents, copied from GitHub app. But pretty much this basic setup. I think can be done much better. Just havent found a way directly calling Google login from compose code. Sure objc/Swift interop but not sure if can call the Google login code from that. Somewhere need the ugly deep link crap to open Google login flow which is some kind of web I think, not sure.
โœ… 1
If youre able do single direction flow from compose I am all ears. Would love replace my shit solution with bidirectional flows in Android and iOS. Not very complex but horrible code.
r
Yeah.. unfortunately accessing swift third party libraries is still a mystery in KMP, have the same issue with firebase analytics, still trying to figure it out. But thank you for your help! And no worries about the indents :), will let you know if it worked, or if I had any other questions, and if I found a better way to do it
j
Yeah luckely I dodged the bullet not need any analytics. Main pain is how Google solved this. Even if done it natively in iOS and Android is very ugly solution in both platforms imo. Need to launch Google play services before calling anything else. I think Jetbrains working on make Swift libraries interop properly in CMP. See KMP roadmap https://blog.jetbrains.com/kotlin/2023/11/kotlin-multiplatform-development-roadmap-for-2024/ But I dont want either Swift or Android/JVM specific libraries, want agnostic ones so we dont need this. I even tried find easier solution get rid of Firebase entirely but not many nice OAuth solution integrations. Would love see androidx credential manager KMP and using passkey for Google login instead. For replacing Analytics a lot of imo better libraries out there. But most firebase things using analytics core under the hood :) Anyway for now until proper support, I think best decouple this as much as can in shared code and propagate to compose world. Also imo avoid directly communicate with compose. Use a Flow like StaTeFlow emit data like tokens from Google sign in and observe it in ui layer further down. Then much easier decouple this.
โœ… 1
You could potentially leverage Ktor OAuth thing and do custom Google login thing in pure KMP. It also exists some C/C++ library for Firebase maybe possible. But then probably need involve JNI in Android instead ๐Ÿคฃ
Hmm I should probably write some blog posts about this, CMP and KMP in general. To bad only 24h days ๐Ÿ˜
@Raed Ghazal Also if find library being cocoapods or objc I think can use it inside iOSMain directly. Maybe there is some Gradle plugin for Swift packages to communicate with. Will check myself if thats possible. Would make the code much more isolated I think.
โœ… 1
For analytics seems to be working this approach https://github.com/chrisbanes/tivi/blob/main/ios-app/Tivi/Tivi/TiviApp.swift Provide interface in your shared module and then implement it in Swift with firebase iOS SDK, like track screen. Then can use it in commonMain inject into shared DI system.
r
Will first check implementing swift packages in shared iosMain module, if that works it would solve a lot of issues
Otherwise will have to do it youโ€™re way and then search for nicer solutions. Was also thinking of writing a blog post about it once I figure it out haha ๐Ÿ˜‚
๐Ÿ˜ 1
Just saw youโ€™re new message in the channel, hope someone provide an answer
v
Just in case anyone else come here looking, this Medium post was really useful. Since I use firebase-kotlin-sdk in my project I had to change one thing which is where he creates a Google user. Instead of returning a custom GoogleUser object I do the below to get an AuthCredential object.
Copy code
val idToken = gidSignInResult?.user?.idToken?.tokenString
val accessToken = gidSignInResult?.user?.accessToken?.tokenString
val credential = GoogleAuthProvider.credential(idToken, accessToken)
This credential can then be used with Firebase to sign in as you normally would:
Copy code
Firebase.auth.signInWithCredential(credential)
j
@Viktor Nyblom Thanks! Yeah I pretty much do exactly like in that medium article. What no one tells in these articles is how to solve the madness of XCode dependecies used in KMP projects ๐Ÿ˜„ So yeah looks awesome and so, but when using GitliveApp/Firebase in reality the cocoapods from that libs not included in actual IOS app build, I need to link those myself manually. Have you managed to get that working as it should, which is NOT add the libs into XCode I refer to. Only adding DevLive Firebase in commonMain I expect it should work as is.
๐Ÿ™Œ 1
v
I hack it and use Swift Package Manager to add both Firebase and Google Sign In in Xcode. Not pretty but it works/compiles! ๐Ÿ˜…
j
Yeah same as me, damn. I wish I one day meet someone here solved this once and for all. I want SPM/Cocoapods in ONLY Kotlin sourceset, I dont want to have XCode on my computer at all, ever, or at least not need to open it.
๐Ÿ˜‚ 1
I tried add the cocoapods block:
Copy code
cocoapods {
                version = "1.0"
                name = "MyPods"
                summary = "App CocoaPods"
                homepage = "<https://github.com/JetBrains/kotlin>"

                ios.deploymentTarget = "17.2"

                pod("GoogleSignIn") {
                    version = "7.0.0"
                }
                //pod("FirebaseCore")
                //pod("FirebaseAuth")
            }
Into Kotlin. But then getting duplicated link issues instead or other oddness ๐Ÿ˜„
v
I think we just need to be patient on that one. iOS/Native Multiplatform is still very young. ๐Ÿ˜ƒ In fact, a lot of the KMP stuff feel like Android in the old days ca 2012. A bunch of weird stuff that needed workarounds, and everyone was just trying to figure shit out. ๐Ÿ˜ƒ
j
Yeah we need to push Apple stop using XCode and let Jetbrains continue having AppCode ๐Ÿ˜„ Joke aside, yeah I know that Jetbrains working on direct Swift interop support, then I think they have to provide solution to this. Then I can use Firebase Swift directly from my Kotlin code instead and include Swift package in Kotlin plugin I think. So it will happen soon I think. Just annoying very complex. I cannot touch a single library in cocapods. Everytime doing that something break. Just find solution on sqdelight linking + Firebase same time, was hard enough. Tried almost all hidden flags there is I think for KotlinNative plugin to enforce linking and exporting transitive deps. Sadly cocoapods or SPM using proper package resolving, its even painful for native IOS devs. Now its KMP devs as well sharing that burden. One day ๐Ÿ™‚
๐Ÿ™ 1
When I configure it the "right way" I think it should be done I get this error btw:
Copy code
ld: warning: Could not find or use auto-linked framework 'FirebaseAuth': framework 'FirebaseAuth' not found
ld: warning: Could not find or use auto-linked framework 'FirebaseCore': framework 'FirebaseCore' not found
ld: warning: Could not find or use auto-linked framework 'FirebaseFirestore': framework 'FirebaseFirestore' not found
ld: warning: Could not find or use auto-linked framework 'GoogleSignIn': framework 'GoogleSignIn' not found
ld: Undefined symbols:
  _FIRAuthErrorDomain, referenced from:
      _cocoapods_FirebaseAuth_FIRAuthErrorDomain_getter_wrapper0 in MyAppKt[arm64][2714](libdev.gitlive:firebase-auth-cinterop-FirebaseAuth-cache.a.o)
  _FIRAuthStateDidChangeInternalNotification, referenced from:
      firebase::firestore::credentials::FirebaseAuthCredentialsProvider::FirebaseAuthCredentialsProvider(FIRApp*, id<FIRAuthInterop>) in FirebaseFirestoreInternal[arm64][72](firebase_auth_credentials_provider_apple.o)
  _FIRAuthStateDidChangeInternalNotificationAppKey, referenced from:
e
@Joel Denke did you ever managed to fix it? Iโ€™m running into a similar issue: https://kotlinlang.slack.com/archives/C0346LWVBJ4/p1710091126616709
j
@Eury Perez To be honest I dont remember. Some parts of it I replaced and some not. Still need to duplicate linking process of cocoapods.