使用不重定向的 Capacitor 插件在 Web 上使用 Apple 登录

Sign in with apple on the web with Capacitor plugin not redirecting

我正在尝试在我的 Ionic 应用程序中实现使用 Apple 登录功能。为此,我正在使用插件:https://github.com/capacitor-community/apple-sign-in

在设备上使用时一切正常,但我无法将其用作网络应用程序。 这就是我开始流程的方式:

      SignInWithApple.authorize({
        clientId: environment.appId+'.webapp',
        redirectURI: 'https://api.xxxx.hu/signInWithAppleCallback',
        scopes: 'email name',
        state: '12345',
        //nonce: 'nonce',
      }).then(appleUser => {
        this.sendOauthConnectRequest(OauthProvider.apple, appleUser.response.identityToken).subscribe();
      }).catch(() => {
        this.oauthLoading[oauthProvider] = false;
        return;
      });

clientId 是我在 apple 注册的,重定向 url 也可以。 当我开始这个调用时,会弹出一个新的 window,我可以在其中使用我的 apple ID 登录,但完成后,它不会将我重定向到指定的 URL。事实上,什么也没有发生。控制台中也没有错误。我可以看到对“https://appleid.apple.com/appleauth/auth/oauth/authorize”的请求成功,并且在响应中我可以看到所有正确的身份验证数据,只是重定向没有发生。如果我在那之后关闭登录 window,错误处理程序的回调被正确调用,从而通知我登录不成功(这是预期的,因为用户关闭了 window). 那么关于为什么重定向没有发生的任何想法? 非常感谢!

仅供参考,这是我使用的解决方案。 基本上,它的第一部分只是将网络平台与真实设备分开。

if (Capacitor.getPlatform() === 'web') {
  this.appleSignInAbortController = new AbortController();
  this.appleSignInWindow = window.open(
    'https://appleid.apple.com/auth/authorize?' +
      'client_id=com.company.exampleApp&'+
      'redirect_uri='+environment.appUrl+'&' +
      'response_type=code id_token&' +
      'scope=name email&' +
      'response_mode=web_message',
    '_blank'
  );
  window.addEventListener(
    'message',
    (e) => {this.appleTokenReceived(e);},
    {signal: this.appleSignInAbortController.signal}
  );
  return;
}
//Continue with regular sign in on real devices, just like in the original post

appleTokenReceived 是一个调用 Apple 响应的函数。请注意,响应也将发布到指定的 redirect_uri,但这将在后台发生,server-to-server,因此您不能真正使用它来重定向您的客户端(除非您打开一个websocket 到你的服务器,但这对于这个任务来说似乎有点矫枉过正)。所以另一半代码:

async appleTokenReceived(event) {
  this.appleSignInAbortController.abort();
  this.appleSignInWindow.close();
  if (!(event instanceof MessageEvent)) {
    return;
  }
  const data = JSON.parse(event.data);
  if (typeof data !== 'object' || data === null) {
    return;
  }
  if (data.data.hasOwnProperty('error')) {
    return;
  }
  let postData: any = {
    token: data.data.authorization.id_token,
    device_id: 'device UUID',
  };
  if (
    data.data.hasOwnProperty('user') &&
    data.data.user.hasOwnProperty('name') &&
    data.data.user.name.hasOwnProperty('firstName') &&
    data.data.user.name.hasOwnProperty('lastName')
  ) {
    //this is only filled after the first login of the user
    postData.name = data.data.user.name.lastName + ' ' + data.data.user.name.firstName;
  }
  this.http.post(environment.apiUrl + '/api/auth/loginWithApple', postData).subscribe(//Do whatever you need with the data);
}