aboutyou / dart_packages

Dart and Flutter plugins maintained and used by @ABOUTYOU
220 stars 149 forks source link

Apple sign in for Android not working with in built phone browser #174

Open zfnadia opened 3 years ago

zfnadia commented 3 years ago

I am getting 'Webpage not available' when redirecting back to my Android app on the Sign in with Apple callback on my sever. Callback URL works fine for Chrome browser but does not work when the default device browser is used (tried on different android devices).

My implementation is as following -

 AuthorizationCredentialAppleID appleIDCredential;
    try {
      yield SocialIntegrationLoading();
      appleIDCredential = await SignInWithApple.getAppleIDCredential(
        scopes: [
          AppleIDAuthorizationScopes.email,
          AppleIDAuthorizationScopes.fullName,
        ],
        webAuthenticationOptions: WebAuthenticationOptions(
          clientId: 'my client id',
          redirectUri: Uri.parse('http://${RepositoryProvider.of<Env>(context).baseUrl}/api/oauth-callback/apple'),
        ),
      );
      if (appleIDCredential != null && appleIDCredential.identityToken.isNotEmpty) {
        response = await userProfileRepository.integrateSocialAccount(appleIDCredential.identityToken, 'apple');
        yield* response.fold((Glitch l) async* {
          yield IntegrateSocialFailure(error: l.message);
        }, (String r) async* {
          yield IntegrateSocialSuccess(message: r);
        });
      } else {
        yield const IntegrateSocialFailure(error: 'Something went wrong!');
      }
    } on SignInWithAppleAuthorizationException catch (e) {
      if(e.code == AuthorizationErrorCode.canceled) {
        yield const IntegrateSocialFailure(error: 'User has cancelled login with Apple');
      }
    } catch (error) {
      yield IntegrateSocialFailure(error: error.message);
    }

AndroidManifest.xml


        <activity
            android:name="com.aboutyou.dart_packages.sign_in_with_apple.SignInWithAppleCallback"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.VIEW" />

                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="android.intent.category.BROWSABLE" />

                <data android:scheme="signinwithapple" />
                <data android:path="callback" />
            </intent-filter>
        </activity>
HenriBeck commented 3 years ago

@zfnadia yeah we are aware of this but we haven't found a good solution for this. The problem is that some of the devices don't have chrome as the default browser. And often these browsers don't support the intent scheme which should be present which is required for our plugin to work.

Sese-Schneider commented 3 years ago

@HenriBeck just to let you and future readers know:

We (@simpleclub) tried to find a workaround for this as well, but failed to find a easy solution.

In our case Huawei phones failed to open anything from redirects, even direct app deeplinks with https:// or custom schemes with scheme://. The built-in browser simply doesn't handle Intent anchors.

The only way around this would be to use a webview and custom handle the intent instead of using the CustomTabs, but that's no state-of-the-art or elegant solution.

jaredgreener commented 3 years ago

Any updates to this? On a samsung galaxy tab the default browser is a samsung browser. Can't seem to get this to redirect back to the app with the payload. Just displays in the broswer window

jaredgreener commented 3 years ago

I was able to get this working in both Chrome and Samsung Browsers. A couple of updates to the documentation. After reading this article:

https://developer.chrome.com/docs/multidevice/android/intents/

Chrome doesn't launch an external app for a given Intent URI in the following cases.

  • When the Intent URI is redirected from a typed in URL.
  • When the Intent URI is initiated without user gesture.

This prompted me to wrap my redirectURI content in an tag -- Which in golang looks like this:

        body, _ := ioutil.ReadAll(r.Body)
        response := "<div><BR><BR><BR><a style=\"text-align:center;font-size:24pt;font-weight:bold;\" href=\"intent://callback?"+string(body)+"#Intent;package=com.invictme.wardbullet;scheme=signinwithapple;end;\"/>Click Here to Finish Sign-In</a></div>"

        w.Header().Set("Content-Type", "text/html; charset=utf-8")
        w.Write([]byte(response))

Now when the user clicks the giant link to complete, the redirect works properly. In addition, here is my Android manifest for reference:

<activity
                android:name="com.aboutyou.dart_packages.sign_in_with_apple.SignInWithAppleCallback"
                android:exported="true"
        >
            <intent-filter>
                <action android:name="android.intent.action.VIEW" />
                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="android.intent.category.BROWSABLE" />

                <data android:scheme="signinwithapple" android:path="callback" />
            </intent-filter>
        </activity>
Shatha-Naami commented 3 years ago

any updates?

tatraef commented 2 years ago

+

tp commented 2 years ago

@Shatha-Naami and interstitial like @jaredgreener suggested is a good option.

We have been using something like https://app.example.com/foo/bar.

Upon opening that page it tries to open the intent by redirect in the HTML <header> and in the cases where that is not allowed (due to lack of user interaction), a big button is shown for the user to tap, in which case opening the app works.

For a production example see above or curl -v -H "User-Agent: Android" "https://app.aboutyou.com/foo/bar".

I guess this makes sense to add to the documentation as a best practice on how to implement your backend.

veloso14 commented 1 year ago

@jaredgreener thanks a lot that worked for me. I have even been able to expand on your solution by adding <body onload="document.getElementById('myLink').click()"> In my case it would be:

<html>
<head>
</head>
<body onload="document.getElementById('myLink').click()">
<div>
    <a  id="myLink"  style="text-align:center;font-size:24pt;font-weight:bold;" 
    href="intent://callback?'. 
    $entityBody .'#Intent;package=com.savecook.save.wallet;scheme=signinwithapple;end;">
    Clique here
</a>
</div>
</body>
</html>

The HTML clicks on the link for us and it works on both Chrome and Samsung browser.

@HenriBeck check this out to

tiagopvianna commented 1 year ago

Thank you very much @jaredgreener and @veloso14. Both solutions worked great!

Mowinski commented 1 year ago

Unfortunetlly this solutions doesn't work for me :( Do you have any updates?

qwertyway commented 3 months ago

Still waiting for some updates on this....