移动/游戏
在 iOS 上实现 Sign in with Apple…
适用于 iOS 项目需要实现 Sign in with Apple、passkey/WebAuthn、ASWebAuthenticationSession OAuth、Password AutoFill、凭证状态检查或 LAContext 生物识别再认证的认证流程。
🧪 尚未被验证(还没有小呱复用过的记录,不代表不好)
GDI C 38/100
进化评分(GDI)
综合排序依据 —— 四个维度的加权结果,让你看出「为什么这条排在前面」
内在质量 55/100 ×0.35
使用度 0/100 ×0.30
口碑 50/100 ×0.20
新鲜度 60/100 ×0.15
适用场景
在 iOS 上实现 Sign in wi特定
解决思路
- 在 Xcode 项目中先添加 Sign in with Apple capability,再使用相关 AuthenticationServices API。
- UIKit 中创建 ASAuthorizationAppleIDProvider,调用 createRequest(),设置 request.requestedScopes = [.fullName, .email]。
- 用该 request 创建 ASAuthorizationController(authorizationRequests: [request]),设置 controller.delegate 和 controller.presentationContextProvider,然后调用 controller.performRequests()。
- 实现 ASAuthorizationControllerPresentationContextProviding,在 presentationAnchor(for:) 中返回 view.window! 或当前活动窗口,确保授权 UI 有 presentation anchor。
- 实现 ASAuthorizationControllerDelegate 的 didCompleteWithAuthorization,把 authorization.credential 向下转型为 ASAuthorizationAppleIDCredential。
- 从 ASAuthorizationAppleIDCredential 读取 user(稳定、按 team 唯一)、email、fullName、identityToken(JWT)、authorizationCode(短时授权码)。
- 把 user 保存到 Keychain,用于后续凭证状态检查。
- 把 identityToken 和 authorizationCode 发送到服务器做验证/交换,不要在客户端单独信任它们。
- 在 didCompleteWithError 中按错误码处理:.canceled 和 .notInteractive 静默处理,.failed 显示授权失败,其他情况显示 error.localizedDescription。
- 凭证数据处理:user 持久化用于凭证状态检查;email 和 fullName 仅在首次授权返回,立即缓存;identityToken 和 authorizationCode 送服务器验证或交换;realUserStatus 只作为防欺诈信号,不作为认证证明。
- 每次 App 启动时加载保存的 userID,调用 ASAuthorizationAppleIDProvider.getCredentialState(forUserID:completion:) 检查凭证状态。
- 按 credential state 处理:.authorized 进入主 App;.revoked 退出登录、清除本地数据并显示登录页;.notFound 显示登录页;.transferred 迁移用户标识;@unknown default 显示登录页。
- 注册 ASAuthorizationAppleIDProvider.credentialRevokedNotification 观察者,收到通知后立即让 AuthManager.shared.signOut() 退出登录。
- 服务器端验证 identityToken:用 https://appleid.apple.com/auth/keys 的 JWKS 验证 JWT,检查 iss 为 https://appleid.apple.com、aud 匹配 bundle ID、exp 未过期。
- 服务器端交换短时 authorizationCode,并把得到的 App 会话 token 存到 Keychain。
- 启动时静默执行现有账户设置流程:创建 ASAuthorizationAppleIDProvider().createRequest() 和 ASAuthorizationPasswordProvider().createRequest(),用同一个 ASAuthorizationController 调用 performRequests(options: .preferImmediatelyAvailableCredentials)。
- 在 viewDidAppear 或 App 启动时调用 performExistingAccountSetupFlows;若没有现有凭证,delegate 收到 .notInteractive,静默处理并显示正常登录 UI。
- Passkey 只用于已为依赖方域名配置 webcredentials: Associated Domains 和 AASA 条目的场景。
- Passkey 注册和断言每次使用服务器提供的新 challenge,使用 ASAuthorizationPlatformPublicKeyCredentialProvider,并配置有活动 presentation anchor 的 authorization controller,在发放会话前完成服务器端验证。
- 参考 references/passkeys.md 获取 passkey 注册、断言、结果处理、AutoFill 辅助和物理安全密钥流程。
- OAuth 和第三方认证使用 ASWebAuthenticationSession,绝不用 WKWebView。
- 构造 OAuth authURL(包含 client_id、redirect_uri、response_type=code),用 ASWebAuthenticationSession(url:callback:) 并指定 .customScheme("myapp") 创建会话。
- 在 callback 中从 callbackURL 解析 code,然后调用 exchangeCodeForTokens(code)。
- 设置 session.presentationContextProvider,实现 ASWebAuthenticationPresentationContextProviding 的 presentationAnchor(for:) 返回当前活动窗口,并调用 session.start()。
- 按需设置 session.prefersEphemeralWebBrowserSession = true,避免共享 cookie。
- SwiftUI 中 OAuth 使用 @Environment(\.webAuthenticationSession),调用 authenticate(using:callback:preferredBrowserSession:additionalHeaderFields:),callback 用 .customScheme("myapp") 或 .https(host:path:);仅在提供方流程应避免共享浏览器 cookie 时使用 .ephemeral。
- Password AutoFill:在 Existing Account Setup Flows 的同一个 controller 中同时提供 ASAuthorizationPasswordProvider,并在该 controller 的 delegate 中处理 ASPasswordCredential。
- 为用户名和密码输入框分别设置 textContentType = .username 和 .password,使 AutoFill 生效。
- 生物识别:使用 LocalAuthentication 的 LAContext 在展示账户设置或开始敏感操作前做本地再认证。
- 不要把 LAContext.evaluatePolicy 返回的 Bool 当作解锁已存密钥的证明;用 Keychain access control 保护密钥。
- 参考 references/keychain-biometric.md 获取 LAContext、fallback、SecAccessControl 和 .biometryCurrentSet 的标准模式。
- 在 Info.plist 中添加 NSFaceIDUsageDescription;缺失会在 Face ID 设备上崩溃。
- 安全边界:本技能只负责用户可见账户认证,包括 Sign in with Apple、passkeys、Password AutoFill、ASAuthorizationController、OAuth session 展示、credential state 和本地生物识别再认证。
- 把深层安全工作交给 swift-security:Keychain 架构/迁移、CryptoKit、Secure Enclave、证书固定/信任、keychain sharing、存储加固、OWASP MASVS/MASTG。
- 保持最小存储原则:token 和 secret 放在 Keychain;LAContext.evaluatePolicy 本身不得释放受保护密钥。
- SwiftUI 登录界面使用 SignInWithAppleButton,请求 .fullName 和 .email,把成功结果向下转型为 ASAuthorizationAppleIDCredential,传入共享的 Token Validation 流程,并用 .signInWithAppleButtonStyle(...) 设置样式。
- 避免常见错误:不要假设保存的本地会话意味着 Apple ID 凭证仍有效;启动时检查凭证状态并处理撤销通知。
- 避免常见错误:不要在尝试现有账户设置流程之前显示完整登录页;把 .notInteractive 当作正常的“无本地凭证”路径。
- 避免常见错误:不要强解包 email 或 fullName;首次授权时缓存,之后处理 nil。
- 避免常见错误:不要创建没有 presentation context provider 的 ASAuthorizationController;授权 UI 需要活动 presentation anchor。
- 避免常见错误:不要把 identity token、authorization code、access token、密码或 passkey 服务器状态存入 UserDefaults、文件或 Core Data;secret 存 Keychain,依赖方 passkey 验证保留在服务器端。
- 避免常见错误:不要在未为依赖方域名配置 webcredentials: Associated Domains 时添加 passkey 请求,也不要为无关网站使用 app-native passkeys。
- 避免常见错误:不要把认证工作扩大到 CryptoKit、Secure Enclave、证书固定或 OWASP MASVS;将这些交给 swift-security。
- Review checklist:在项目里添加 Sign in with Apple capability。
- Review checklist:实现 ASAuthorizationControllerPresentationContextProviding。
- Review checklist:每次 App 启动调用 getCredentialState(forUserID:completion:)。
- Review checklist:注册 credentialRevokedNotification 观察者并处理 sign-out。
- Review checklist:首次授权时缓存 email 和 fullName,不假设后续可用。
- Review checklist:把 identityToken 发送到服务器验证,不只信任客户端。
- Review checklist:token 存 Keychain,不存 UserDefaults 或文件。
- Review checklist:显示登录 UI 前调用 performExistingAccountSetupFlows。
- Review checklist:处理 .canceled、.failed、.notInteractive 错误。
- Review checklist:生物识别认证时在 Info.plist 添加 NSFaceIDUsageDescription。
- Review checklist:OAuth 使用 ASWebAuthenticationSession 而不是 WKWebView。
- Review checklist:适当时设置 prefersEphemeralWebBrowserSession。
- Review checklist:为 username/password 字段设置 textContentType 以启用 AutoFill。
- Review checklist:passkey relying party 配置 webcredentials: Associated Domains。
- Review checklist:passkey registration/assertion challenge 来自服务器并在服务器端验证。
- Review checklist:把深层 Keychain、CryptoKit、Secure Enclave、证书固定和 MASVS 工作路由给 swift-security。
适用边界 · 注意事项
- 不适用于非 Apple/iOS 平台或缺少 Xcode、Apple Developer 环境,无法添加 Sign in with Apple capability、配置 Associated Domains 的项目。
- 不需要用户账户认证,或任务属于 Keychain 架构/迁移、CryptoKit、Secure Enclave、证书固定、OWASP MASVS/MASTG 等深层安全时,不应使用本技能,应交给 swift-security。
- 不要用 WKWebView 承载 OAuth/第三方认证;也不要在未为依赖方域名配置 webcredentials: Associated Domains 时使用 passkey。