Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android, Apple sign in

I'm trying to add Apple sign-in functionality to my Android App. I follow the pop-up approach. I'm failing to get it to work.

class AppleLoginWebViewActivity : BaseActivity(), AppleLoginContract.View {

   private val TAG = AppleLoginWebViewActivity::class.java.simpleName

   override fun onCreate(savedInstanceState: Bundle?) {
       super.onCreate(savedInstanceState)
       setContentView(R.layout.activity_apple_login)

       prepareWebView()
   }

   private fun prepareWebView() {

       if (BuildConfig.DEBUG) {
           WebView.setWebContentsDebuggingEnabled(true)
       }

       webView.addJavascriptInterface(
           AppleLoginJavaScriptInterface(),
           "AndroidInterface"
       )

       val webSettings: WebSettings = webView.settings
       webSettings.javaScriptEnabled = true
       webView.webViewClient = MyWebViewClient()
       webView.webChromeClient = MyWebChromeClient()
       webView.settings.loadWithOverviewMode = true
       webView.settings.domStorageEnabled = true
       webView.settings.useWideViewPort = true
   }

   private inner class MyWebViewClient : WebViewClient() {

       override fun onPageFinished(
           view: WebView,
           url: String
       ) { //Calling a javascript function in html page
           Logger.info(TAG, "page started: $url")
           // view.loadUrl("javascript:alert(clickAppleSignInButton())")
           view.loadUrl("javascript:AndroidInterface.showHTML" +
               "('<html>'+document.getElementsByTagName('html')[0].innerHTML+'</html>');");
       }

       override fun shouldOverrideUrlLoading(
           view: WebView?,
           request: WebResourceRequest?
       ): Boolean {
           return false
       }
   }

   private class MyWebChromeClient : WebChromeClient() {
       override fun onJsAlert(
           view: WebView,
           url: String,
           message: String,
           result: JsResult
       ): Boolean {
           result.confirm()
           return true
       }
   }

   override fun loadUrl(appleLoginLocalUrl: String) {
       webView.loadUrl(appleLoginLocalUrl)
   }
}

and here is the html file that I load

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <meta name="viewport" content="width=device-width, initial-scale=1.0">
 <title>Apple Sign in</title>
</head>
<body>
<script type="text/javascript" src="https://appleid.cdn-apple.com/appleauth/static/jsapi/appleid/1/en_US/appleid.auth.js"></script>
<div id="appleid-signin" data-color="black" data-border="true" data-type="sign in"></div>
<script type="text/javascript">

     const options = {
       clientId: 'MY_CLIENT_ID',
       scope: 'email name',
       redirectURI: 'MY_REDIRECT_URL',
       state: '',
       usePopup : true
     };
     AppleID.auth.init(options);
 </script>

 <script type="text/javascript">
   function clickAppleSignInButton() {
     document.getElementById("appleid-signin").click();
   }
 </script>

 <script type="text/javascript">
   //Listen for authorization success
   document.addEventListener('AppleIDSignInOnSuccess', successFunction);
   //Listen for authorization failures
   document.addEventListener('AppleIDSignInOnFailure', failureFunction);

   function successFunction(data) {
     //handle successful response
     console.log("success")
     AndroidInterface.onLoginSuccess(data);
   }

   function failureFunction(error) {
     //handle error
     console.log("failure")
     AndroidInterface.onLoginFailed(error);
   }
 </script>
</body>
</html>

SO, in the last step, when I inspect the web view, I can see the authentication data being posted (POST request) to another url inside the web view. But the event listener with AppleIDSignInOnSuccess is never called. there is an error that says "Failed to execute 'postMessage' on 'DOMWindow': The target origin provided ('MY_REDIRECT_URL') does not match the recipient window's origin ('https://appleid.apple.com').", source: (0).

So, I have a couple of questions:

  1. How to fix this error?
  2. Why the event listener is not getting called?
  3. Is there a way that I can intercept and parse the POST response from the web view directly?
like image 816
a fair player Avatar asked Mar 18 '20 21:03

a fair player


People also ask

Can I Sign in with Apple on Android?

You can sign in to Apple Music on Android, or sign in to the Apple TV app on your smart TV or streaming device.


1 Answers

<script type="text/javascript">

     const options = {
       clientId: 'MY_CLIENT_ID',
       scope: 'email name',
       redirectURI: 'MY_REDIRECT_URL',
       state: '',
       usePopup : true
     };
     AppleID.auth.init(options);
     AppleID.auth.signIn(); //<-- there :)
 </script>
  • Apple wants that redirect url to be full really url, like: https://some.domain.tld/path/to/redirect which supports POST
  • Also not all browsers support usePopup, for example iOS 10.3 block this for me :)
like image 113
iTux Avatar answered Oct 23 '22 05:10

iTux