Flutter苹果账号登录插件sign_in_with_apple的使用

Flutter苹果账号登录插件sign_in_with_apple的使用

Sign in With Apple

Flutter桥接到Apple登录。它支持通过Apple ID登录,以及检索用户钥匙串中保存的凭证。

Flutter Favorite

Supported platforms

  • iOS
  • macOS
  • Android
  • Web

Example Usage

SignInWithAppleButton(
  onPressed: () async {
    final credential = await SignInWithApple.getAppleIDCredential(
      scopes: [
        AppleIDAuthorizationScopes.email,
        AppleIDAuthorizationScopes.fullName,
      ],
    );

    print(credential);

    // Now send the credential (especially `credential.authorizationCode`) to your server to create a session
    // after they have been validated with Apple (see `Integration` section for more information on how to do this)
  },
);

Flow

Integration

集成Sign in with Apple不仅仅是在pubspec.yaml中添加这个插件并使用其暴露的接收凭证的功能。一旦你收到凭证,就需要与Apple的服务器验证(以确保它们有效且确实涉及提到的用户),然后在你的系统中创建一个新会话。

您的服务器应该每天通过刷新令牌(最初验证时获得)来验证Apple上的会话,并在Apple端撤销授权时,在您的系统中撤销会话。

Prerequisites

在开始集成(或测试)Sign in with Apple之前,你需要有Apple Developer Program的付费会员资格。Sign in with Apple是受限制的服务之一,仅凭Apple ID无法免费使用。

Apple Mail Relay

由于用户可以使用私有电子邮件中继,因此需要向用于发送电子邮件的域添加SPF记录,请阅读更多:配置私有电子邮件中继服务 没有它,您的服务将无法向选择使用Apple的私有中继的用户发送电子邮件,邮件将无法送达。

Setup

Register an App ID

如果你还没有,可以在这里创建一个新的App ID:

  • 点击"Register an App ID"
  • 在向导中选择"App IDs",点击"Continue"
  • 设置DescriptionBundle ID,并选择Sign In with Apple功能
  • 点击"Continue",然后点击"Register"完成App ID的创建

如果你已经有现有的App ID要与Sign in with Apple一起使用:

  • 打开该App ID列表中的项目
  • 勾选"Sign in with Apple"功能
  • 点击"Save"

如果你更改了应用程序的功能,则需要获取更新的配置文件(例如通过Xcode)以使用新的功能。

Create a Service ID

Service ID仅在Web或Android集成时需要。如果只打算在iOS上集成,可以跳过此步骤。

前往Apple开发者页面,并按照以下步骤操作:

  • 点击"Register an Services ID"
  • 选择"Services IDs",点击"Continue"
  • 设置"Description"和"Identifier"
  • 点击"Continue"然后"Register"

现在我们需要启用它以用于Sign in with Apple:

  • 从服务列表中选择服务
  • 勾选"Sign in with Apple"框,然后点击"Configure"
  • Domains and Subdomains中添加网站域名,例如example.com
  • Return URLs框中添加完整的返回URL,例如https://example.com/callbacks/sign_in_with_apple
  • 点击"Next"然后"Done"关闭设置对话框
  • 点击"Continue"然后"Save"更新服务

为了与Apple的服务器通信以验证来自应用客户端的授权代码,你需要在这里创建一个密钥:

  • 点击"Create a key"
  • 设置"Key Name"(例如"Sign in with Apple key")
  • 勾选"Sign in with Apple"框,然后在同一行点击"Configure"
  • 在"Primary App ID"下选择你要使用的App ID
  • 点击"Save"离开详细视图
  • 点击"Continue"然后点击"Register"
  • 现在你会看到一个一次性的屏幕,必须通过点击"Download"按钮下载密钥
  • 注意"Key ID"稍后配置服务器时会用到

现在所有设置都已在Apple开发者门户完成,我们可以开始设置服务器。

Server

服务器部分通常集成到您现有的后端中,大多数现有编程语言和Web框架都有现成的包。

为了展示如何构建一个完整的示例,我们在Glitch上设置了一个示例项目,提供简单的HTTPS启用Web API,这正是这里所需要的。

要开始使用Glitch-based示例,请访问项目页面并点击"Remix this"。现在你有了自己的样本服务器副本!

首先选择左侧文件浏览器中的.env文件并输入您的凭据(这些不会公开,但只会与受邀合作者共享)。

然后单击左上角头像旁边的"Share"按钮,选择"Live App"并复制入口页面URL(例如https://some-random-identifier.glitch.me)。

现在更新您之前创建的服务,以包含以下URL作为Return URLshttps://[YOUR-PROJECT-NAME].glitch.me/callbacks/sign_in_with_apple(替换方括号内的名称)。

完成后,您可以继续将Sign in with Apple集成到Flutter应用的代码中。

Android

要在Flutter应用中添加Sign in with Apple,分为两方面:首先是使示例应用与服务器端设置一起工作,然后是为从头开始设置应用所需的其他步骤。

要在此插件上使用Android,您需要使用Android V2嵌入

检查是否已经使用新的嵌入,可以通过查看AndroidManifest.xml中的以下元素:

<meta-data
  android:name="flutterEmbedding"
  android:value="2" 
/>

如果没有使用Android V2嵌入,请先按照以下指南升级应用:升级指南

launchMode

为了确保从登录网页(显示在Chrome自定义标签页中)回到应用的深度链接仍然有效,您的应用必须使用launchMode singleTasksingleTop

  • 使用singleTask时,Chrome自定义标签页会在使用Android的应用切换器时持久存在,但从主屏幕图标或应用商店重新启动应用时将被取消。
  • 使用launchMode singleTop时,无论使用应用切换器还是通过图标重新启动应用,Chrome自定义标签页都会保持存在。
  • 如果更改了应用的launchMode,请务必测试可能受到影响的任何第三方集成(例如深度链接)

Web

对于Web支持,需要在index.html<head>标签中添加以下脚本导入:

<script type="text/javascript" src="https://appleid.cdn-apple.com/appleauth/static/jsapi/appleid/1/en_US/appleid.auth.js"></script>

(我们尚未找到一种方法可以按需加载此脚本,因为该脚本似乎在页面加载时自动初始化。)

然后在Apple开发者门户中的服务配置中添加托管页面的域名,既包括Domains and Subdomains也包括Returns URLs

前者是必需的,以便可以从网页打开流程,而后者用于将最终凭证从弹出窗口发布回打开页面。(如果省略此步骤,流程将在最后一步静默卡住。)

Example App

  • 打开example文件夹并在编辑器中运行flutter packages get
  • 打开lib/main.dart并查看SignInWithAppleButton.onPressed回调
    • 设置scopes参数以匹配所需范围,测试时可以保留请求姓名和电子邮件
    • 更新传递给WebAuthenticationOptions构造函数的值,以匹配Apple开发者门户中的值
    • 同样更新signInWithAppleEndpoint变量以指向您的服务器
  • 更新代码后,使用flutter run在Android设备或模拟器上运行示例

Your App

android/app/src/main/AndroidManifest.xml中的<application>内添加:

<!-- Set up the Sign in with Apple activity, such that it's callable from the browser-redirect -->
<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>

在Apple服务器上的Sign in with Apple回调(指定在WebAuthenticationOptions.redirectUri中),安全地重定向回您的Android应用,使用以下URL:

intent://callback?${PARAMETERS FROM CALLBACK BODY}#Intent;package=YOUR.PACKAGE.IDENTIFIER;scheme=signinwithapple;end

PARAMETERS FROM CALLBACK BODY应填充从Apple服务器接收到的编码后的body,package参数应更改为匹配您应用的包标识符(如Google Play商店中发布的)。保持callback路径和signinwithapple方案不变。

此外,在处理传入的凭证时,确保只有在您自己的服务器验证了传入的code参数之后才覆盖当前(访客)会话,以防止恶意传入链接(例如注销当前用户)。

iOS

此时你应该已经在Apple开发者门户中为自己的应用或创建的测试应用添加了Sign in with Apple功能。

如果你没有在Xcode中开启Automatically manage Signing,则需要重新创建并下载更新的配置文件,以便它们包含新的Sign in with Apple功能。然后你可以下载新的证书并选择它们。

如果XCode管理您的签名,这一步会自动为您完成。只需确保启用了Sign in with Apple功能,如下面的示例所示。

此外,这假设你在开发者账户中至少注册了一台iOS设备进行本地测试,以便可以在设备上运行示例。

Example

  • 在终端中打开example文件夹并运行flutter packages get
  • 在Xcode中打开example/ios/Runner.xcworkspace
  • Runner(文件浏览器侧栏)->Targets->Runner->Signing & Capabilities设置“Bundle Identifier”(“App ID”)为你在Apple开发者门户中创建的
    • 确保“Sign in with Apple”列在功能下(如果没有,通过+添加)
  • 现在在终端中进入example文件夹并执行以下命令
    • cd ios
    • bundle install,以安装Cocoapods使用的Ruby依赖项
    • bundle exec pod install,以安装iOS项目的Cocoapods
  • 在终端中导航回example文件夹的根目录并flutter run在测试设备上运行

Your App

  • 首先确保您的应用具有“Sign in with Apple”功能(Runner(文件浏览器侧栏)->Targets->Runner->Signing & Capabilities),否则Sign in with Apple将失败而没有任何视觉指示(代码仍会抛出异常)
  • 要么集成上面的示例服务器,要么构建自己的后端
    • 确保用于验证接收到的code参数的clientID取决于客户端:当使用Apple平台上的应用代码时使用App ID(也称为“Bundle ID”),当使用从Web身份验证流中检索到的代码时使用服务ID

macOS

macOS的设置与iOS基本相同。对于Flutter开发macOS,您必须在devmaster通道上。

Example

  • 在终端中打开example文件夹并运行flutter packages get
  • 在Xcode中打开example/macos/Runner.xcworkspace
  • Runner(文件浏览器侧栏)->Targets->Runner->Signing & Capabilities设置“Bundle Identifier”(“App ID”)为你在Apple开发者门户中创建的
    • 确保“Sign in with Apple”列在功能下(如果没有,通过+添加)
    • 另外,该屏幕上不应有警告。(例如,您的Mac必须注册用于本地开发。(如果没有,您会看到一个“一键修复”按钮来执行此操作。))
  • 在终端中导航回example文件夹的根目录并flutter run在测试设备上运行

示例代码

import 'dart:io';

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'package:sign_in_with_apple/sign_in_with_apple.dart';

// Needed because we can't import `web` into a mobile app,
// while on the flip-side access to `dart:io` throws at runtime (hence the `kIsWeb` check below)
import 'html_shim.dart' if (dart.library.js_interop) 'package:web/web.dart'
    show window;

void main() {
  runApp(const MyApp());
}

class MyApp extends StatefulWidget {
  const MyApp({super.key});

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      onGenerateRoute: ((settings) {
        // This is also invoked for incoming deep links

        // ignore: avoid_print
        print('onGenerateRoute: $settings');

        return null;
      }),
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Example app: Sign in with Apple'),
        ),
        body: Container(
          padding: const EdgeInsets.all(10),
          child: Center(
            child: SignInWithAppleButton(
              onPressed: () async {
                final credential = await SignInWithApple.getAppleIDCredential(
                  scopes: [
                    AppleIDAuthorizationScopes.email,
                    AppleIDAuthorizationScopes.fullName,
                  ],
                  webAuthenticationOptions: WebAuthenticationOptions(
                    clientId: 'de.lunaone.flutter.signinwithappleexample.service',
                    redirectUri: kIsWeb
                        ? Uri.parse('https://${window.location.host}/')
                        : Uri.parse(
                            'https://flutter-sign-in-with-apple-example.glitch.me/callbacks/sign_in_with_apple',
                          ),
                  ),
                  nonce: 'example-nonce',
                  state: 'example-state',
                );

                print(credential);

                final signInWithAppleEndpoint = Uri(
                  scheme: 'https',
                  host: 'flutter-sign-in-with-apple-example.glitch.me',
                  path: '/sign_in_with_apple',
                  queryParameters: <String, String>{
                    'code': credential.authorizationCode,
                    if (credential.givenName != null)
                      'firstName': credential.givenName!,
                    if (credential.familyName != null)
                      'lastName': credential.familyName!,
                    'useBundleId':
                        !kIsWeb && (Platform.isIOS || Platform.isMacOS)
                            ? 'true'
                            : 'false',
                    if (credential.state != null) 'state': credential.state!,
                  },
                );

                final session = await http.Client().post(
                  signInWithAppleEndpoint,
                );

                print(session);
              },
            ),
          ),
        ),
      ),
    );
  }
}
1 回复

更多关于Flutter苹果账号登录插件sign_in_with_apple的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,下面是一个关于如何在Flutter项目中使用sign_in_with_apple插件来实现苹果账号登录的示例代码。这个示例假定你已经设置好了Flutter开发环境,并且已经在你的pubspec.yaml文件中添加了sign_in_with_apple依赖。

首先,确保你的pubspec.yaml文件中包含以下依赖:

dependencies:
  flutter:
    sdk: flutter
  sign_in_with_apple: ^3.0.0  # 请确保使用最新版本

然后,运行flutter pub get来安装依赖。

接下来,你可以按照以下步骤在你的Flutter应用中实现苹果账号登录功能:

  1. 导入必要的包
import 'package:flutter/material.dart';
import 'package:sign_in_with_apple/sign_in_with_apple.dart';
  1. 创建一个AppleSignInButton小部件
class AppleSignInButton extends StatefulWidget {
  @override
  _AppleSignInButtonState createState() => _AppleSignInButtonState();
}

class _AppleSignInButtonState extends State<AppleSignInButton> {
  final SignInWithApple _signInWithApple = SignInWithApple();

  @override
  Widget build(BuildContext context) {
    return ElevatedButton(
      onPressed: () async {
        try {
          final credential = await _signInWithApple.performRequests([
            AppleIDRequest(requestedScopes: [AppleIDAuthorizationScopes.fullName, AppleIDAuthorizationScopes.email])
          ]);

          // 在这里处理登录成功的逻辑
          // credential.user 是用户的唯一标识符
          // credential.fullName 是用户的全名
          // credential.email 是用户的电子邮件地址(如果请求了电子邮件权限)

          print('User ID: ${credential.user}');
          print('Full Name: ${credential.fullName?.givenName} ${credential.fullName?.familyName}');
          print('Email: ${credential.email}');

        } catch (e) {
          print('Error: $e');
        }
      },
      child: Text('Sign in with Apple'),
    );
  }
}
  1. 在你的应用中使用这个按钮
void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Sign In with Apple Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: Scaffold(
        appBar: AppBar(
          title: Text('Sign In with Apple Demo'),
        ),
        body: Center(
          child: AppleSignInButton(),
        ),
      ),
    );
  }
}
  1. 处理iOS特定配置

确保你的iOS项目(ios/Runner)已经正确配置了Sign in with Apple功能。你需要:

  • 在Xcode中,打开你的项目设置。
  • 转到Signing & Capabilities标签。
  • 添加Sign in with Apple功能。

此外,你还需要在Info.plist文件中添加一些必要的键值对,例如:

<key>LSApplicationQueriesSchemes</key>
<array>
    <string>apple-id-auth</string>
</array>
<key>CFBundleURLTypes</key>
<array>
    <dict>
        <key>CFBundleTypeRole</key>
        <string>Editor</string>
        <key>CFBundleURLSchemes</key>
        <array>
            <string>YOUR_REVERSE_CLIENT_ID</string>
        </array>
    </dict>
</array>

YOUR_REVERSE_CLIENT_ID应该是一个唯一的标识符,通常是你应用的bundle ID的反向域名格式。

这个示例代码提供了一个基本的框架,展示了如何在Flutter应用中使用sign_in_with_apple插件来实现苹果账号登录。根据你的具体需求,你可能需要添加更多的错误处理、UI调整或与其他后端服务的集成。

回到顶部
AI 助手
你好,我是IT营的 AI 助手
您可以尝试点击下方的快捷入口开启体验!