supabase-community / supabase-kt

A Kotlin Multiplatform Client for Supabase.
https://supabase.com/docs/reference/kotlin/introduction
MIT License
332 stars 34 forks source link

[Bug]: Apple Auth is broken #447

Open jan-tennert opened 5 months ago

jan-tennert commented 5 months ago

thanks @jan-tennert , I was able to run it locally and have found out where the issue is happening, still not sure if it is something on my end but here is what I found

and Should I create a new issue with these details?

I have added the code and the logs output below

I put some logs in the method "rememberSignInWithApple" and here are my obervations

1.The method runs as soon as the app opens, without user doing anything, although the code inside launched effect doesnt runs and directly the last log is printed

  1. Then when I click on the sign in button all the statments that are marked "executed" run in an instant without me doing anything

3.Nothing is executed after I click on "signIn"(after putting password in the box) in the apple native signin ui

4."nonce" and the "user" properties are showing null

5.All properties inside the config.loginConfig["apple"] object are null, even though object is not null

6.IMPORTANT -looks like authorizationController() method is never executed, I had put some logs in that method too but nothing was printed and also the print statement "I am here 10" was not printed

@Composable
actual fun ComposeAuth.rememberSignInWithApple(
    onResult: (NativeSignInResult) -> Unit,
    fallback: suspend () -> Unit
): NativeSignInState {

    val state = remember { NativeSignInState() }
    val scope = rememberCoroutineScope()

    LaunchedEffect(key1 = state.started) {
        println("I am inside launched effect")//executed
        if (state.started) {
            println("I am inside first if block , which means state is set to started")//executed

            println("${config.loginConfig["apple"]}")
            if (config.loginConfig["apple"] == null) {
                println("I am inside 2nd if block , which shouldn't happen")// NOT EXECUTED
                fallback.invoke()
                state.reset()
                return@LaunchedEffect
            }

            val appleIDProvider = ASAuthorizationAppleIDProvider()
            val request = appleIDProvider.createRequest().apply {
                requestedScopes = listOf(ASAuthorizationScopeFullName, ASAuthorizationScopeEmail)
                nonce = (config.loginConfig["apple"] as? AppleLoginConfig)?.nonce
                println("loginConfig - ${config.loginConfig["apple"]}  server client id - ${config.loginConfig["apple"]?.serverClientId}")//executed
                println("requested scopes - $requestedScopes , nounce - $nonce  ")//executed
            }
            println("request - $request - user - ${request.user}")//executed

            val controller = ASAuthorizationController(listOf(request)).apply {
                println("i m inside controller ${this.delegate}")//executed
                delegate = authorizationController(scope) {
                    println(" I m here 10")// **** NOT EXECUTED ****
                    onResult.invoke(it)
                    state.reset()
                }

                println("I am here in the controller") // EXECUTED

                presentationContextProvider = presentationAnchor()

            }
            println("controller - $controller - delegate ${controller.delegate}") // EXECUTED
            println(" i am on my way further 3") // EXECUTED
            controller.performRequests()

            println("I am after the perfrom Reuest function")

        }
    }
    println("I am outside launched effect and state is $state.") //Executed first

    return state
}

output

I am outside launched effect and state is io.github.jan.supabase.compose.auth.composable.NativeSignInState@8a32be0. I am inside launched effect starting apple auth I am outside launched effect and state is io.github.jan.supabase.compose.auth.composable.NativeSignInState@8a32be0. I am inside launched effect I am inside first if block , which means state is set to started AppleLoginConfig(serverClientId=, nonce=null, extraData=null) loginConfig - AppleLoginConfig(serverClientId=, nonce=null, extraData=null) server client id - requested scopes - [full_name, email] , nounce - null request - <ASAuthorizationAppleIDRequest: 0x60000213c820> - user - null i m inside controller null I am here in the controller controller - <ASAuthorizationController: 0x60000390a2f0> - delegate <ComposeApp_kobjc5: 0x600000260740> i am on my way further 3 I am after the perfrom Reuest function

Originally posted by @Vaibhav-214 in https://github.com/supabase-community/supabase-kt/issues/446#issuecomment-1917663545

jan-tennert commented 5 months ago

Okay so points 1, 2, 4, 5 are normal. I'm not sure why the server client id property even exists as it's not used anyway, but I think its not needed. For point 6 I'm not sure, @temk0 implemented this, so maybe he can help with this. The authorization controller method is a little bit below the composable, are any of those functions implemented called at all? In any case, I'm gonna mark as help needed, as I can't test it myself.

Vaibhav-214 commented 5 months ago

I had put some print statements in both the authorization controller methods (different parameters) but they never got executed.

Also I think code never reached to a point where it would execute this signInWithApple() method as it is called inside authorization controller method but shouldn't it be AppleLoginConfig in line 108 instead of GoogleLoginConfig

https://github.com/supabase-community/supabase-kt/blob/74cb87538cc51e6b13977f1b58908248c9261e5d/plugins/ComposeAuth/src/commonMain/kotlin/io/github/jan/supabase/compose/auth/ComposeAuth.kt#L107-L116

AppleLoginConfig is defined here

https://github.com/supabase-community/supabase-kt/blob/74cb87538cc51e6b13977f1b58908248c9261e5d/plugins/ComposeAuth/src/commonMain/kotlin/io/github/jan/supabase/compose/auth/LoginConfig.kt#L39-L43

Vaibhav-214 commented 5 months ago

udpate: The control flow is going inside the authorizationController method but the two methods inside it are not executing

https://github.com/supabase-community/supabase-kt/blob/74cb87538cc51e6b13977f1b58908248c9261e5d/plugins/ComposeAuth/src/appleMain/kotlin/io/github/jan/supabase/compose/auth/composable/AppleAuth.kt#L77-L112

Here any of the two methods one at line 82 and another at line 102 is never executed throughout the process, I added print statments at the top and before the return statement by declaring the object as variable , it is printing all the statments that are outside the object methods and returning the delegate object too.But probably those methods are not triggered when they should be

jan-tennert commented 5 months ago

Yea, once we found a solution for this we definitely have to clean up the code a little bit

sigmadeltasoftware commented 2 months ago

Hey all,

Currently in progress of migrating from Firebase auth to Supabase for easier authorization/user management, and ran into this issue as well. Logging in through Firebase went without issue, but using the Supabase SDK on emulator results in basically loss of state (log-in popup closes and no feedback/error logging/ whatever is provided); And on a physical device it seems to crash with a BadRequestRestException.

Could it possibly be related to this error & fix which was reported somewhere around the same time: https://github.com/supabase/auth/issues/1401#issuecomment-1929227394

Deorigami commented 1 month ago

Hi i got this issue too, With same codebase, My Android went smoothly but on ios

auth.sessionStatus.onEach {
            Napier.d(tag = "ANGGATAG", message = "Session Status : $it")
            when(it){
                is SessionStatus.Authenticated -> router.navigateToDashboard()
                SessionStatus.LoadingFromStorage -> Unit
                SessionStatus.NetworkError -> Unit
                is SessionStatus.NotAuthenticated -> Unit
            }}
.launchIn(screenModelScope)

even after success and i also check the auth log on supabase dashboard .. the status never change to anything

yannickpulver commented 1 month ago

As a workaround, it's possible to build the SignInWithApple button directly with SwiftUI, do the sign in natively in Swift and then import the Auth Session to the Kotlin instance. Its a rather hacky solution, but seems to work in my tests.

I made a gist you can find here: https://gist.github.com/yannickpulver/f123ea210eef83757a0bc1bac9e83a28

To make this work, you will need to import Supabase Authentication in the XCode project (see docs for Supabase with Swift).

Deorigami commented 1 month ago

im using supabase so i dont do these kind of things :D