You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter/Dart中Apple ID登录及账号永久注销时的Token撤销方案

实现Apple权限永久撤销及数据删除功能

一、应用内添加撤销/删除入口

在应用的账号设置页面添加清晰可见的操作按钮,比如**「永久删除账号并撤销权限」**,按钮位置需符合Apple的UI规范,确保用户能轻松找到。

二、撤销Apple登录权限的逻辑

Apple要求应用需支持撤销用户授权,核心是调用Apple官方的撤销API,由于前端直接调用存在安全风险,推荐通过后端处理:

1. 后端处理逻辑

后端需使用Apple开发者密钥(从Apple Developer后台获取)生成JWT,然后向Apple撤销API发送请求:

  • 请求地址:https://appleid.apple.com/auth/revoke
  • 必填参数:
    • client_id:应用的Bundle ID
    • client_secret:用开发者密钥生成的JWT签名
    • token:用户的Apple ID Token或Refresh Token(优先用Refresh Token,需在登录时保存)
    • token_type_hint:可选值access_token或refresh_token,用于指定token类型

2. 前端触发请求

在Flutter中编写函数调用后端的撤销接口:

Future<void> revokeAppleAuthorization(String appleUserId) async {
  try {
    final response = await http.post(
      Uri.parse('你的后端撤销接口地址'),
      body: {'apple_user_id': appleUserId},
    );
    if (response.statusCode != 200) {
      throw Exception('撤销权限失败,请稍后重试');
    }
  } catch (e) {
    debugPrint('撤销权限出错: $e');
    rethrow;
  }
}

三、删除Firebase用户及关联数据

撤销权限后,需彻底删除用户在Firebase的账号及所有个人数据:

1. 删除Firebase用户账号

用户处于登录状态时可直接调用删除方法,若登录状态过期,需先重新验证身份:

Future<void> deleteFirebaseUser() async {
  try {
    final user = FirebaseAuth.instance.currentUser;
    if (user == null) return;

    await user.delete();
  } on FirebaseAuthException catch (e) {
    // 登录状态过期,触发重新验证流程
    if (e.code == 'requires-recent-login') {
      await reauthenticateUser();
      await deleteFirebaseUser();
    } else {
      debugPrint('删除用户账号出错: ${e.message}');
      rethrow;
    }
  }
}

// 重新验证用户身份的辅助函数
Future<void> reauthenticateUser() async {
  final user = FirebaseAuth.instance.currentUser;
  if (user == null) return;

  final rawNonce = generateNonce();
  final nonce = sha256ofString(rawNonce);

  final appleCredential = await SignInWithApple.getAppleIDCredential(
    scopes: [AppleIDAuthorizationScopes.email],
    nonce: nonce,
  );

  final oauthCredential = OAuthProvider("apple.com").credential(
    idToken: appleCredential.identityToken,
    rawNonce: rawNonce,
  );

  await user.reauthenticateWithCredential(oauthCredential);
}

2. 删除关联的Firebase数据

根据业务场景删除Firestore、Storage等服务中的用户数据:

Future<void> deleteUserRelatedData(String userId) async {
  try {
    // 删除Firestore用户主文档
    await FirebaseFirestore.instance.collection('users').doc(userId).delete();

    // 删除Storage中的用户文件(如头像)
    final storageRef = FirebaseStorage.instance.ref().child('user_avatars/$userId');
    await storageRef.delete();

    // 按需删除其他关联数据(如订单、评论等)
  } catch (e) {
    debugPrint('删除用户数据出错: $e');
    rethrow;
  }
}

四、整合完整的撤销+删除流程

将上述步骤整合为一个函数,供按钮点击触发,执行前需弹出确认对话框提醒用户操作不可逆:

Future<void> permanentDeleteAccount() async {
  try {
    final user = FirebaseAuth.instance.currentUser;
    if (user == null) throw Exception('用户未登录');

    // 从Firestore获取用户的Apple ID(需在登录时保存该字段)
    final userDoc = await FirebaseFirestore.instance.collection('users').doc(user.uid).get();
    final appleUserId = userDoc.data()?['apple_user_id'] as String?;
    if (appleUserId == null) throw Exception('无法获取用户Apple账号信息');

    // 1. 撤销Apple授权
    await revokeAppleAuthorization(appleUserId);

    // 2. 删除用户关联数据
    await deleteUserRelatedData(user.uid);

    // 3. 删除Firebase用户账号
    await deleteFirebaseUser();

    // 4. 跳转至登录页面
    // Navigator.of(context).pushReplacementNamed('/login');
  } catch (e) {
    debugPrint('永久删除账号出错: $e');
    // 向用户展示错误提示
  }
}

五、Apple审核注意事项

  • 操作前必须弹出明确的确认对话框,告知用户操作不可逆
  • 不能仅引导用户前往系统设置撤销权限,必须在应用内提供完整的撤销+删除流程
  • 需确保所有用户数据(包括第三方服务中的数据)被彻底删除
  • 隐私政策中需明确说明数据删除的范围和流程

内容的提问来源于stack exchange,提问作者Vivek Jung Hamal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 11:39:35