如何在 React Native 中优雅地添加 Apple 登录
如果你曾经在 App Store 上发布过带有 Google 或社交登录功能的移动应用,你可能已经遇到了审核人员的严格规则:如果你添加了第三方登录,就必须同时包含「通过 Apple 登录」。否则,应用被拒的速度比发布版本编译完成的速度还快。
这个任务一开始看起来很简单。但一旦你开始深入研究原生调用、模拟器怪癖和 Apple API 的特殊性,各种陷阱就会接踵而至。Invertase 团队(也是 React Native Firebase 的幕后团队)开发了一个名为 react-native-apple-authentication 的库,可以同时处理 iOS 和 Android 的登录问题。

底层原理以及为什么你需要它
该库提供了对 Apple 身份验证机制的完整访问。它适用于从 0.60 版本开始的原生 React Native,与 Expo 配合良好(通过 prebuild 和 app.json 中的 entitlements 配置),支持 macOS,甚至可以通过浏览器流程对 Android 用户进行身份验证。
最棒的是开箱即用的 TypeScript 定义和现成的原生按钮组件 AppleButton。按钮设计严格遵循 Apple 的设计规范。如果你自行绘制按钮,审核人员会欣然拒绝你的应用。这里的样式和本地化直接来自原生系统。
iOS 基本流程的工作原理
安装过程是标准流程:通过 yarn 或 npm 安装包,然后在 ios 文件夹中运行 pod install。该模块支持自动链接,所以你不需要手动修改 AppDelegate。
对于按钮和登录逻辑,你只需要几个导入:
import React from 'react';
import { View } from 'react-native';
import { AppleButton, appleAuth } from '@invertase/react-native-apple-authentication';
export function LoginScreen() {
async function handleAppleLogin() {
// Запускаем нативный запрос авторизации
const authResponse = await appleAuth.performRequest({
requestedOperation: appleAuth.Operation.LOGIN,
// Порядок скоупов имеет значение
requestedScopes: [appleAuth.Scope.FULL_NAME, appleAuth.Scope.EMAIL],
});
// Проверяем статус пользователя
const credentialState = await appleAuth.getCredentialStateForUser(authResponse.user);
if (credentialState === appleAuth.State.AUTHORIZED) {
// Пользователь подтвержден, отправляем токены на бэкенд
console.log('User ID:', authResponse.user);
console.log('Identity Token:', authResponse.identityToken);
}
}
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<AppleButton
buttonStyle={AppleButton.Style.BLACK}
buttonType={AppleButton.Type.SIGN_IN}
style={{ width: 200, height: 45 }}
onPress={handleAppleLogin}
/>
</View>
);
}
每个初学者都会踩到的坑
Apple 的授权有一些不太明显的怪癖,在你调试到凌晨 3 点之前,最好先了解一下。
姓名和邮箱只会返回一次
Apple 对隐私非常重视。在首次登录时,用户可以选择隐藏真实邮箱或分享邮箱。个人资料数据(fullName fullName 和 email email)由原生框架精确返回一次——就在第一次成功授权时。
在后续调用中,这些字段会返回空值(null null)。如果你没有立即将姓名和邮箱保存到数据库,就无法再通过客户端 API 检索它们。
要在 iPhone 上重置测试状态并再次接收个人资料,你必须手动进入系统设置:设置 → [你的姓名] → 密码与安全性 → Apple ID 登录 Настройки > Apple ID > Пароль и безопасность > Приложения, использующие Apple ID,在那里删除你的测试应用,然后重新登录。
顺便说一句,项目仓库特别提到了 Apple 自身 API 的一个 bug:scopes 必须严格按照 [FULL_NAME, EMAIL] 的顺序传递。如果你打乱顺序,姓名可能在第一次请求时就丢失了。
模拟器和错误 1000
currentUser 方法 getCredentialStateForUser 用于验证设备真实性。在 iOS 模拟器上,它经常崩溃并报出错误 1000 com.apple.AuthenticationServices.AuthorizationError error 1000。你只能在真机上完全测试授权流程。
如果模拟器完全卡在这个错误上,开发者建议访问 Apple ID 管理网站,找到关联设备列表,然后将模拟器从你的账户中移除。


登出只是个幻觉
该模块的枚举中包含一个 logout 操作 appleAuth.Operation.LOGOUT,但实际上原生 iOS SDK 对此什么都不做。Apple 没有提供在设备级别强制登出的方式。客户端登出只是意味着清除本地会话、保存的令牌和清除应用状态。
撤销访问权限
用户可以随时进入 iOS 设置,撤销你的应用登录权限。为了及时响应并将用户踢回登录界面,该库提供了一个事件监听器:
useEffect(() => {
const unsubscribe = appleAuth.onCredentialRevoked(async () => {
// Токены больше не валидны, сбрасываем локальное состояние
console.warn('Доступ отозван пользователем в настройках Apple ID');
});
return () => unsubscribe();
}, []);
Android 怎么办
很多人会惊讶,但你也可以让 Android 用户使用 Apple ID 登录。那里的机制不同:不是原生框架,而是通过 OAuth 2.0 Web Flow 打开一个受保护的浏览器窗口。
该库通过 ASWebAuthenticationSession appleAuthAndroid 模块处理这个流程:
import { appleAuthAndroid } from '@invertase/react-native-apple-authentication';
import 'react-native-get-random-values';
import { v4 as uuid } from 'uuid';
async function handleAndroidAppleLogin() {
const rawNonce = uuid();
const state = uuid();
appleAuthAndroid.configure({
clientId: 'com.example.client-android', // Service ID из консоли Apple Developer
redirectUri: 'https://example.com/auth/callback',
responseType: appleAuthAndroid.ResponseType.ALL,
scope: appleAuthAndroid.Scope.ALL,
nonce: rawNonce,
state,
});
const response = await appleAuthAndroid.signIn();
// Отправляем response.code и response.id_token на сервер
}
对于 Android,你需要在 Apple Developer Console 中配置一个 Service ID 并指定 Redirect URL。主要规则:重定向链接必须与开发者控制台中输入的内容逐字符匹配——不允许带查询参数。
服务端验证
永远不要盲目信任客户端的 nonce user ID。客户端收到 identityToken identityToken(一个签名的 JWT)。在服务端,你需要解码它,用 Apple 的公钥验证签名,并检查 nonce nonce。
该模块在将 nonce 发送给 Apple 之前会自动计算其 SHA256 哈希值(与 Firebase Auth 的方式类似)。请在后端记住这一点:你需要比较的是哈希值。
如果你的目标是快速满足 App Store 审核要求,或者为用户提供通过 Face ID 便捷的一键登录,Invertase 库是 React Native 生态系统中最可靠的选择。它让你无需编写自己的 Swift/Objective-C 原生桥接代码,优雅地处理按钮样式,并且维护者会持续更新。安装它,在 Apple Developer Console 中配置证书,设置处理程序——你的发布版本就可以提交了。
相关项目