Objective-C Firebase账户删除遇FIRAuthErrorCodeRequiresRecentLogin问题求助
我的应用因未提供账户删除功能被App Store拒绝,应用支持Sign in with Apple、Google及邮箱登录。按照Firebase文档执行账户删除操作时,收到错误FIRAuthErrorCodeRequiresRecentLogin,提示:
Delete account error This operation is sensitive and requires recent authentication. Log in again before retrying this request.
当前执行删除的代码如下:
FIRUser* user = [ [ FIRAuth auth ] currentUser ]; [ user deleteWithCompletion:^(NSError * _Nullable error) { if( error ) { // An error happened. if( error.code == FIRAuthErrorCodeRequiresRecentLogin) { return; } } }
我知道需要重新认证后才能删除账户,目前的做法是让用户登出再登录后执行删除,但用户体验很差。想请教如何获取已通过Google、Apple或邮箱登录用户的FIRAuthCredential,以完成重新认证并删除账户?
目前的重新认证代码片段(待补充Credential获取逻辑):
// How to get a credential when I am already signed in via google, apple, or email? FIRAuthCredential* credential; NSLog( @"Delete account error %@", error.localizedDescription ); [[FIRAuth auth].currentUser reauthenticateWithCredential:credential completion:^(FIRAuthDataResult * _Nullable authResult, NSError * _Nullable error) { NSLog( @"Error %@", error); }];
针对不同登录方式,获取FIRAuthCredential的实现逻辑不同,以下是分场景的具体方案:
1. 邮箱密码登录用户
需要让用户重新输入密码,通过邮箱和密码生成EmailAuthCredential:
// 从当前用户获取邮箱,再通过弹窗获取用户重新输入的密码 NSString *email = [[FIRAuth auth].currentUser email]; NSString *password = @"用户输入的密码"; FIRAuthCredential *credential = [FIREmailAuthProvider credentialWithEmail:email password:password];
2. Google登录用户
借助Google Sign-In SDK,从已登录的Google用户实例中提取认证信息,转换为GoogleAuthCredential:
// 获取当前已登录的Google用户实例 GIDGoogleUser *googleUser = [GIDSignIn sharedInstance].currentUser; if (googleUser) { GIDAuthentication *authentication = googleUser.authentication; FIRAuthCredential *credential = [FIRGoogleAuthProvider credentialWithIDToken:authentication.idToken accessToken:authentication.accessToken]; }
注:需确保项目已正确集成Google Sign-In SDK,且用户未主动登出Google账号。
3. Sign in with Apple登录用户
通过Apple的AuthenticationServices框架发起重新授权请求,用返回的身份令牌生成OAuthCredential:
// 初始化Apple授权请求 ASAuthorizationAppleIDProvider *provider = [[ASAuthorizationAppleIDProvider alloc] init]; NSString *userID = [[FIRAuth auth].currentUser providerData.firstObject uid]; // 获取用户绑定的Apple ID [provider createRequestWithUserID:userID completion:^(ASAuthorizationAppleIDRequest * _Nullable request, NSError * _Nullable error) { if (!error) { request.requestedScopes = @[ASAuthorizationScopeFullName, ASAuthorizationScopeEmail]; ASAuthorizationController *controller = [[ASAuthorizationController alloc] initWithAuthorizationRequests:@[request]]; controller.delegate = self; controller.presentationContextProvider = self; [controller performRequests]; } }]; // 实现Apple授权回调,获取Credential并执行重新认证+删除 - (void)authorizationController:(ASAuthorizationController *)controller didCompleteWithAuthorization:(ASAuthorization *)authorization { if ([authorization.credential isKindOfClass:[ASAuthorizationAppleIDCredential class]]) { ASAuthorizationAppleIDCredential *appleIDCredential = authorization.credential; NSString *identityToken = [[NSString alloc] initWithData:appleIDCredential.identityToken encoding:NSUTF8StringEncoding]; NSString *authorizationCode = [[NSString alloc] initWithData:appleIDCredential.authorizationCode encoding:NSUTF8StringEncoding]; FIRAuthCredential *credential = [FIROAuthProvider credentialWithProviderID:@"apple.com" IDToken:identityToken accessToken:authorizationCode]; // 重新认证后删除账户 [[FIRAuth auth].currentUser reauthenticateWithCredential:credential completion:^(FIRAuthDataResult * _Nullable authResult, NSError * _Nullable error) { if (!error) { [[FIRAuth auth].currentUser deleteWithCompletion:^(NSError * _Nullable error) { if (!error) { // 删除成功,处理后续逻辑 } }]; } }]; } } // 提供Apple授权弹窗的展示上下文 - (ASPresentationAnchor)presentationAnchorForAuthorizationController:(ASAuthorizationController *)controller { return self.view.window; }
完整流程示例
整合上述逻辑,完整的删除账户处理流程如下:
// 触发账户删除 - (void)triggerAccountDelete { FIRUser *user = [FIRAuth auth].currentUser; [user deleteWithCompletion:^(NSError * _Nullable error) { if (error) { if (error.code == FIRAuthErrorCodeRequiresRecentLogin) { [self reauthenticateAndDelete]; } } else { // 删除成功逻辑 } }]; } // 根据登录方式获取Credential并重新认证 - (void)reauthenticateAndDelete { FIRUser *user = [FIRAuth auth].currentUser; NSString *providerID = user.providerData.firstObject.providerID; if ([providerID isEqualToString:@"password"]) { // 邮箱密码登录:弹窗获取密码 NSString *password = @"用户输入的密码"; FIRAuthCredential *credential = [FIREmailAuthProvider credentialWithEmail:user.email password:password]; [self finishReauthenticateAndDelete:credential]; } else if ([providerID isEqualToString:@"google.com"]) { // Google登录:获取当前Google用户 GIDGoogleUser *googleUser = [GIDSignIn sharedInstance].currentUser; if (googleUser) { GIDAuthentication *auth = googleUser.authentication; FIRAuthCredential *credential = [FIRGoogleAuthProvider credentialWithIDToken:auth.idToken accessToken:auth.accessToken]; [self finishReauthenticateAndDelete:credential]; } else { // Google用户已登出,需引导重新登录 } } else if ([providerID isEqualToString:@"apple.com"]) { // Apple登录:发起重新授权请求(代码同上述Apple场景) ASAuthorizationAppleIDProvider *provider = [[ASAuthorizationAppleIDProvider alloc] init]; NSString *userID = user.providerData.firstObject.uid; [provider createRequestWithUserID:userID completion:^(ASAuthorizationAppleIDRequest * _Nullable request, NSError * _Nullable error) { if (!error) { request.requestedScopes = @[ASAuthorizationScopeFullName, ASAuthorizationScopeEmail]; ASAuthorizationController *controller = [[ASAuthorizationController alloc] initWithAuthorizationRequests:@[request]]; controller.delegate = self; controller.presentationContextProvider = self; [controller performRequests]; } }]; } } // 执行重新认证并删除账户 - (void)finishReauthenticateAndDelete:(FIRAuthCredential *)credential { [[FIRAuth auth].currentUser reauthenticateWithCredential:credential completion:^(FIRAuthDataResult * _Nullable authResult, NSError * _Nullable error) { if (!error) { [[FIRAuth auth].currentUser deleteWithCompletion:^(NSError * _Nullable error) { if (!error) { // 删除成功后的逻辑(如跳转登录页) } else { // 删除失败处理 } }]; } else { // 重新认证失败处理(如提示用户重新操作) } }]; }
内容的提问来源于stack exchange,提问作者Jafar Mohammed

